New git HEAD version
[libdai.git] / include / dai / enum.h
1 /* This file is part of libDAI - http://www.libdai.org/
2 *
3 * Copyright (c) 2006-2011, The libDAI authors. All rights reserved.
4 *
5 * Use of this source code is governed by a BSD-style license that can be found in the LICENSE file.
6 */
7
8
9 /// \file
10 /// \brief Defines the DAI_ENUM macro, which can be used to define an \c enum with additional functionality.
11
12
13 #ifndef __defined_libdai_enum_h
14 #define __defined_libdai_enum_h
15
16
17 #include <cstring>
18 #include <iostream>
19 #include <dai/exceptions.h>
20
21
22 /// Extends the C++ \c enum type by supporting input/output streaming and conversion to and from <tt>const char*</tt> and \c size_t
23 /** For more details see the source code.
24 *
25 * \par Example:
26 * \code
27 * DAI_ENUM(colors,RED,GREEN,BLUE)
28 * \endcode
29 * defines a class \a colors encapsulating an
30 * \code
31 * enum {RED, GREEN, BLUE};
32 * \endcode
33 * which offers additional functionality over the plain \c enum keyword.
34 */
35 #define DAI_ENUM(x,val0,...) class x {\
36 public:\
37 enum value {val0,__VA_ARGS__};\
38 \
39 x() : v(val0) {}\
40 \
41 x(value w) : v(w) {}\
42 \
43 x(char const *w) {\
44 static char const* labelstring = #val0 "," #__VA_ARGS__;\
45 size_t pos_begin = 0;\
46 size_t i = 0;\
47 for( size_t pos_end = 0; ; pos_end++ ) {\
48 if( (labelstring[pos_end] == ',') || (labelstring[pos_end] == '\0') ) {\
49 if( (strlen( w ) == pos_end - pos_begin) && (strncmp( labelstring + pos_begin, w, pos_end - pos_begin ) == 0) ) {\
50 v = (value)i;\
51 return;\
52 } else {\
53 i++;\
54 pos_begin = pos_end + 1;\
55 }\
56 }\
57 if( labelstring[pos_end] == '\0' )\
58 break;\
59 }\
60 DAI_THROWE(UNKNOWN_ENUM_VALUE,"'" + std::string(w) + "' is not in [" + std::string(labelstring) + "]");\
61 }\
62 \
63 operator value() const { return v; }\
64 \
65 operator size_t() const { return (size_t)v; }\
66 \
67 operator char const*() const {\
68 static char labelstring[] = #val0 "," #__VA_ARGS__;\
69 size_t pos_begin = 0;\
70 size_t i = 0;\
71 for( size_t pos_end = 0; ; pos_end++ )\
72 if( (labelstring[pos_end] == ',') || (labelstring[pos_end] == '\0') ) {\
73 if( (size_t)v == i ) {\
74 labelstring[pos_end] = '\0';\
75 return labelstring + pos_begin;\
76 } else {\
77 i++;\
78 pos_begin = pos_end + 1;\
79 }\
80 }\
81 }\
82 \
83 operator wchar_t const*() const {\
84 static wchar_t labelstring[] = #val0 L"," #__VA_ARGS__;\
85 size_t pos_begin = 0;\
86 size_t i = 0;\
87 for( size_t pos_end = 0; ; pos_end++ )\
88 if( (labelstring[pos_end] == L',') || (labelstring[pos_end] == L'\0') ) {\
89 if( (size_t)v == i ) {\
90 labelstring[pos_end] = L'\0';\
91 return labelstring + pos_begin;\
92 } else {\
93 i++;\
94 pos_begin = pos_end + 1;\
95 }\
96 }\
97 }\
98 \
99 friend std::istream& operator >> (std::istream& is, x& y) {\
100 std::string s;\
101 is >> s;\
102 y = x(s.c_str());\
103 return is;\
104 }\
105 \
106 friend std::wistream& operator >> (std::wistream& wis, x& y) {\
107 std::wstring s;\
108 wis >> s;\
109 y = x((const char *)s.c_str());\
110 return wis;\
111 }\
112 \
113 friend std::ostream& operator << (std::ostream& os, const x& y) {\
114 os << (const char *)y;\
115 return os;\
116 }\
117 \
118 friend std::wostream& operator << (std::wostream& wos, const x& y) {\
119 wos << (const wchar_t *)y;\
120 return wos;\
121 }\
122 \
123 protected:\
124 value v;\
125 };
126
127
128 #endif