Small changes
[libdai.git] / include / dai / enum.h
1 /* Copyright (C) 2006-2008 Joris Mooij [j dot mooij at science dot ru dot nl]
2 Radboud University Nijmegen, The Netherlands
3
4 This file is part of libDAI.
5
6 libDAI is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10
11 libDAI is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with libDAI; if not, write to the Free Software
18 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21
22 #ifndef __defined_libdai_enum_h
23 #define __defined_libdai_enum_h
24
25
26 #include <cstring>
27 #include <iostream>
28 #include <dai/exceptions.h>
29
30
31 /// Extends the C++ enum type by supporting io streaming and conversion to and from const char* (using anonymous variadic macros)
32
33
34 #define DAI_ENUM(x,val0,...) class x {\
35 public:\
36 enum value {val0,__VA_ARGS__};\
37 \
38 x() : v(val0) {}\
39 \
40 x(value w) : v(w) {}\
41 \
42 x(char const *w) {\
43 static char const* labelstring = #val0 "," #__VA_ARGS__ ",";\
44 size_t pos_begin = 0;\
45 size_t i = 0;\
46 for( size_t pos_end = 0; labelstring[pos_end] != '\0'; pos_end++ )\
47 if( (labelstring[pos_end] == ',') ) {\
48 if( (strlen( w ) == pos_end - pos_begin) && (strncmp( labelstring + pos_begin, w, pos_end - pos_begin ) == 0) ) {\
49 v = (value)i;\
50 return;\
51 } else {\
52 i++;\
53 pos_begin = pos_end + 1;\
54 }\
55 }\
56 DAI_THROW(UNKNOWN_ENUM_VALUE);\
57 }\
58 \
59 operator value() const { return v; }\
60 \
61 operator size_t() const { return (size_t)v; }\
62 \
63 operator char const*() const {\
64 static char labelstring[] = #val0 "," #__VA_ARGS__;\
65 size_t pos_begin = 0;\
66 size_t i = 0;\
67 for( size_t pos_end = 0; ; pos_end++ )\
68 if( (labelstring[pos_end] == ',') || (labelstring[pos_end] == '\0') ) {\
69 if( (size_t)v == i ) {\
70 labelstring[pos_end] = '\0';\
71 return labelstring + pos_begin;\
72 } else {\
73 i++;\
74 pos_begin = pos_end + 1;\
75 }\
76 }\
77 }\
78 \
79 friend std::istream& operator >> (std::istream& is, x& y) {\
80 std::string s;\
81 is >> s;\
82 y = x(s.c_str());\
83 return is;\
84 }\
85 \
86 friend std::ostream& operator << (std::ostream& os, const x& y) {\
87 os << (const char *)y;\
88 return os;\
89 }\
90 \
91 private:\
92 value v;\
93 };
94
95
96 #endif