#include <dai/exceptions.h>
-namespace dai {
+/// Extends the C++ enum type by supporting io streaming and conversion to and from const char* (using anonymous variadic macros)
-// C++ enums are too limited for my purposes. This defines wrapper classes
-// that provide much more functionality than a simple enum. The only
-// disadvantage is that one wrapper class needs to be written for each
-// number of values an enum can take... a better solution is needed.
-
-
-#define ENUM2(x,a,b) class x {\
- public:\
- enum value {a, b};\
-\
- x() : v(a) {}\
-\
- x(value w) : v(w) {}\
-\
- x(char const *w) {\
- static char const* labels[] = {#a, #b};\
- size_t i = 0;\
- for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
- if( strcmp( w, labels[i] ) == 0 ) {\
- v = (value)i;\
- break;\
- }\
- if( i == sizeof(labels) / sizeof(char const *) )\
- DAI_THROW(UNKNOWN_ENUM_VALUE);\
- }\
-\
- operator value () const { return v; }\
-\
- operator size_t () const { return (size_t)v; }\
-\
- operator char const* () const {\
- static char const* labels[] = {#a, #b};\
- return labels[v];\
- }\
-\
- friend std::istream& operator >> (std::istream& is, x& y) {\
- std::string s;\
- is >> s;\
- y = x(s.c_str());\
- return is;\
- }\
-\
- friend std::ostream& operator << (std::ostream& os, const x& y) {\
- os << (const char *)y;\
- return os;\
- }\
-\
- private:\
- value v;\
-};
-
-
-#define ENUM3(x,a,b,c) class x {\
- public:\
- enum value {a, b, c};\
-\
- x() : v(a) {}\
-\
- x(value w) : v(w) {}\
-\
- x(char const *w) {\
- static char const* labels[] = {#a, #b, #c};\
- size_t i = 0;\
- for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
- if( strcmp( w, labels[i] ) == 0 ) {\
- v = (value)i;\
- break;\
- }\
- if( i == sizeof(labels) / sizeof(char const *) )\
- DAI_THROW(UNKNOWN_ENUM_VALUE);\
- }\
-\
- operator value () const { return v; }\
-\
- operator size_t () const { return (size_t)v; }\
-\
- operator char const* () const {\
- static char const* labels[] = {#a, #b, #c};\
- return labels[v];\
- }\
-\
- friend std::istream& operator >> (std::istream& is, x& y) {\
- std::string s;\
- is >> s;\
- y = x(s.c_str());\
- return is;\
- }\
-\
- friend std::ostream& operator << (std::ostream& os, const x& y) {\
- os << (const char *)y;\
- return os;\
- }\
-\
- private:\
- value v;\
-};
-
-
-#define ENUM4(x,a,b,c,d) class x {\
- public:\
- enum value {a, b, c, d};\
-\
- x() : v(a) {}\
-\
- x(value w) : v(w) {}\
-\
- x(char const *w) {\
- static char const* labels[] = {#a, #b, #c, #d};\
- size_t i = 0;\
- for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
- if( strcmp( w, labels[i] ) == 0 ) {\
- v = (value)i;\
- break;\
- }\
- if( i == sizeof(labels) / sizeof(char const *) )\
- DAI_THROW(UNKNOWN_ENUM_VALUE);\
- }\
-\
- operator value () const { return v; }\
-\
- operator size_t () const { return (size_t)v; }\
-\
- operator char const* () const {\
- static char const* labels[] = {#a, #b, #c, #d};\
- return labels[v];\
- }\
-\
- friend std::istream& operator >> (std::istream& is, x& y) {\
- std::string s;\
- is >> s;\
- y = x(s.c_str());\
- return is;\
- }\
-\
- friend std::ostream& operator << (std::ostream& os, const x& y) {\
- os << (const char *)y;\
- return os;\
- }\
-\
- private:\
- value v;\
-};
-
-
-#define ENUM5(x,a,b,c,d,e) class x {\
- public:\
- enum value {a, b, c, d, e};\
-\
- x() : v(a) {}\
-\
- x(value w) : v(w) {}\
-\
- x(char const *w) {\
- static char const* labels[] = {#a, #b, #c, #d, #e};\
- size_t i = 0;\
- for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
- if( strcmp( w, labels[i] ) == 0 ) {\
- v = (value)i;\
- break;\
- }\
- if( i == sizeof(labels) / sizeof(char const *) )\
- DAI_THROW(UNKNOWN_ENUM_VALUE);\
- }\
-\
- operator value () const { return v; }\
-\
- operator size_t () const { return (size_t)v; }\
-\
- operator char const* () const {\
- static char const* labels[] = {#a, #b, #c, #d, #e};\
- return labels[v];\
- }\
-\
- friend std::istream& operator >> (std::istream& is, x& y) {\
- std::string s;\
- is >> s;\
- y = x(s.c_str());\
- return is;\
- }\
-\
- friend std::ostream& operator << (std::ostream& os, const x& y) {\
- os << (const char *)y;\
- return os;\
- }\
-\
- private:\
- value v;\
-};
-
-
-#define ENUM6(x,a,b,c,d,e,f) class x {\
+#define DAI_ENUM(x,val0,...) class x {\
public:\
- enum value {a, b, c, d, e, f};\
+ enum value {val0,__VA_ARGS__};\
\
- x() : v(a) {}\
+ x() : v(val0) {}\
\
x(value w) : v(w) {}\
\
x(char const *w) {\
- static char const* labels[] = {#a, #b, #c, #d, #e, #f};\
- size_t i = 0;\
- for( ; i < sizeof(labels) / sizeof(char const *); i++ )\
- if( strcmp( w, labels[i] ) == 0 ) {\
- v = (value)i;\
- break;\
- }\
- if( i == sizeof(labels) / sizeof(char const *) )\
- DAI_THROW(UNKNOWN_ENUM_VALUE);\
- }\
-\
- operator value () const { return v; }\
-\
- operator size_t () const { return (size_t)v; }\
-\
- operator char const* () const {\
- static char const* labels[] = {#a, #b, #c, #d, #e, #f};\
- return labels[v];\
+ static char const* labelstring = #val0 "," #__VA_ARGS__ ",";\
+ size_t pos_begin = 0;\
+ size_t i = 0;\
+ for( size_t pos_end = 0; labelstring[pos_end] != '\0'; pos_end++ )\
+ if( (labelstring[pos_end] == ',') ) {\
+ if( (strlen( w ) == pos_end - pos_begin) && (strncmp( labelstring + pos_begin, w, pos_end - pos_begin ) == 0) ) {\
+ v = (value)i;\
+ return;\
+ } else {\
+ i++;\
+ pos_begin = pos_end + 1;\
+ }\
+ }\
+ DAI_THROW(UNKNOWN_ENUM_VALUE);\
+ }\
+\
+ operator value() const { return v; }\
+\
+ operator size_t() const { return (size_t)v; }\
+\
+ operator char const*() const {\
+ static char labelstring[] = #val0 "," #__VA_ARGS__;\
+ size_t pos_begin = 0;\
+ size_t i = 0;\
+ for( size_t pos_end = 0; ; pos_end++ )\
+ if( (labelstring[pos_end] == ',') || (labelstring[pos_end] == '\0') ) {\
+ if( (size_t)v == i ) {\
+ labelstring[pos_end] = '\0';\
+ return labelstring + pos_begin;\
+ } else {\
+ i++;\
+ pos_begin = pos_end + 1;\
+ }\
+ }\
}\
\
friend std::istream& operator >> (std::istream& is, x& y) {\
};
-} // end of namespace dai
-
-
#endif