12 class gorgon__no_enum_trait {
14 static const bool isupgradedenum=
false;
98 class expandedenumtraits {
102 expandedenumtraits() {
103 T_ prev=traits.mapping.begin()->first;
104 listing.push_back(prev);
105 for(
auto p : traits.mapping) {
106 for(
auto &c : p.second) c=tolower(c);
108 reversemapping.insert(std::make_pair(p.second, p.first));
110 listing.push_back(p.first);
116 bool lookupstring(T_ e, std::string &s)
const {
117 auto item=traits.mapping.find(e);
118 if(item==traits.mapping.end())
return false;
123 bool lookupvalue(std::string s, T_ &e)
const {
124 for(
auto &c : s) c=tolower(c);
126 auto item=reversemapping.find(s);
127 if(item==reversemapping.end())
return false;
132 typename std::vector<T_>::const_iterator
134 return listing.begin();
137 typename std::vector<T_>::const_iterator
139 return listing.end();
144 std::map<std::
string, T_> reversemapping;
145 std::vector<T_> listing;
150 class staticenumtraits {
154 static bool lookupstring(T_ e, std::string &s) {
155 return traits.lookupstring(e, s);
158 static bool lookupvalue(
const std::string &s, T_ &e) {
159 return traits.lookupvalue(s, e);
162 static typename std::vector<T_>::const_iterator
begin() {
163 return traits.begin();
166 static typename std::vector<T_>::const_iterator
end() {
170 static const expandedenumtraits<T_> traits;
174 const expandedenumtraits<T_> staticenumtraits<T_>::traits;
177 class enum_type_id {};
190 #define DefineEnumStrings(type, ...) \
191 class gorgon_enumtraits_##type {\
193 gorgon_enumtraits_##type() : mapping({__VA_ARGS__}) { }\
195 static const bool isupgradedenum=true;\
197 static const char *name() { return #type; }\
199 const std::multimap<type, std::string> mapping;\
201 gorgon_enumtraits_##type gorgon__enum_tr_loc(type);
213 #define DefineEnumStringsTN(type, typname, ...) \
214 class gorgon_enumtraits_##type {\
216 gorgon_enumtraits_##type() : mapping({__VA_ARGS__}) { }\
218 static const bool isupgradedenum=true;\
220 static const char *name() { return typname; }\
222 const std::multimap<type, std::string> mapping;\
224 gorgon_enumtraits_##type gorgon__enum_tr_loc(type);
235 #define DefineEnumStringsCM(clsname, type, ...) \
236 class gorgon_enumtraits_##type {\
238 gorgon_enumtraits_##type() : mapping({__VA_ARGS__}) { }\
240 static const bool isupgradedenum=true;\
242 static const char *name() { return #type; }\
244 const std::multimap<clsname::type, std::string> mapping;\
246 gorgon_enumtraits_##type gorgon__enum_tr_loc(clsname::type);
256 #define DefineEnumStringsCMTN(clsname, type, typname, ...) \
257 class gorgon_enumtraits_##type {\
259 gorgon_enumtraits_##type() : mapping({__VA_ARGS__}) { }\
261 static const bool isupgradedenum=true;\
263 static const char *name() { return typname; }\
265 const std::multimap<clsname::type, std::string> mapping;\
267 gorgon_enumtraits_##type gorgon__enum_tr_loc(clsname::type);
276 typename std::enable_if<decltype(
gorgon__enum_tr_loc(T_()))::isupgradedenum, enum_type_id<T_>>::type
278 return enum_type_id<T_>();
282 typename std::vector<T_>::const_iterator
288 typename std::vector<T_>::const_iterator
end(enum_type_id<T_>) {
295 To(
const std::string &text) {
297 if(!staticenumtraits<T_>::lookupvalue(text, e))
return T_();
302 typename std::enable_if<decltype(
gorgon__enum_tr_loc(T_()))::isupgradedenum, std::string>::type
305 if(!staticenumtraits<T_>::lookupstring(e, s))
return "";
313 if(!staticenumtraits<T_>::lookupvalue(text, e)) {
314 std::string s =
"\""+text+
"\" is not a valid ";
326 operator <<(std::ostream &out, const T_ &e) {
328 if(!Gorgon::staticenumtraits<T_>::lookupstring(e, s))
return out;
336 typename std::enable_if<decltype(
gorgon__enum_tr_loc(T_()))::isupgradedenum, std::istream&>::type
337 operator >>(std::istream &in, T_ &e) {
341 if(!Gorgon::staticenumtraits<T_>::lookupvalue(s, e)) in.setstate(in.badbit);
349 typename std::enable_if<decltype(
gorgon__enum_tr_loc(T_()))::isupgradedenum, std::istream&>::type
355 while(s.length()>i &&
isspace(s[i])) i++;
358 if(!Gorgon::staticenumtraits<T_>::lookupvalue(s, e)) in.setstate(in.badbit);