PTLib Version 2.12.9

- Main Page
- Related Pages
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
bitwise_enum.h
Go to the documentation of this file.
1 /*
2 * bitwise_enum.h
3 *
4 * Template class to allow operators on an enum representing bits.
5 *
6 * Portable Tools Library
7 *
8 * Copyright (c) 2009 Vox Lucida
9 *
10 * The contents of this file are subject to the Mozilla Public License
11 * Version 1.0 (the "License"); you may not use this file except in
12 * compliance with the License. You may obtain a copy of the License at
13 * http://www.mozilla.org/MPL/
14 *
15 * Software distributed under the License is distributed on an "AS IS"
16 * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
17 * the License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * The Original Code is Portable Windows Library.
21 *
22 * The Initial Developer of the Original Code is Equivalence Pty. Ltd.
23 *
24 * Contributor(s): ______________________________________.
25 *
26 * $Revision: 30991 $
27 * $Author: rjongbloed $
28 * $Date: 2013-11-28 17:59:03 +1100 (Thu, 28 Nov 2013) $
29 */
30
31 #ifndef PTLIB_BITWISE_ENUM_H
32 #define PTLIB_BITWISE_ENUM_H
33
34 #ifdef P_USE_PRAGMA
35 #pragma interface
36 #endif
37
42 template <typename BaseEnum, BaseEnum MaxValue, typename BaseInt = unsigned>
43 class PBitwiseEnum
44 {
45 public:
46 typedef BaseEnum Enumeration;
47 typedef BaseInt IntType;
48
49 protected:
50 Enumeration m_enum;
51
52 public:
53 static __inline Enumeration Zero() { return (Enumeration)0; }
54
55 __inline PBitwiseEnum(Enumeration e = Zero()) : m_enum(e) { }
56 __inline PBitwiseEnum(const PBitwiseEnum & e) : m_enum(e.m_enum) { }
57
58 enum IteratorBounds { First, Last };
59 __inline PBitwiseEnum(IteratorBounds b) : m_enum(b == First ? (Enumeration)1 : MaxValue) { }
60
61 __inline PBitwiseEnum & operator=(const PBitwiseEnum & e) { m_enum = e.m_enum; return *this; }
62 __inline PBitwiseEnum & operator=(Enumeration e) { m_enum = e; return *this; }
63
64 __inline operator Enumeration() const { return m_enum; }
65 __inline operator Enumeration&() { return m_enum; }
66 __inline operator const Enumeration&() const { return m_enum; }
67 __inline Enumeration * operator&() { return &m_enum; }
68 __inline unsigned AsBits() const { return m_enum; }
69 __inline static Enumeration FromBits(unsigned b) { return (Enumeration)( b &((MaxValue<<1)-1)); }
70 __inline static Enumeration FromBit (unsigned b) { return (Enumeration)((1<<b)&((MaxValue<<1)-1)); }
71
72 PBitwiseEnum operator++()
73 {
74 Enumeration previous = m_enum;
75 if (m_enum < MaxValue)
76 m_enum = static_cast<Enumeration>(m_enum << 1);
77 return previous;
78 }
79
80 PBitwiseEnum operator++(int)
81 {
82 if (m_enum < MaxValue)
83 m_enum = static_cast<Enumeration>(static_cast<IntType>(m_enum) << 1);
84 return *this;
85 }
86
87 PBitwiseEnum operator--()
88 {
89 Enumeration previous = m_enum;
90 m_enum = static_cast<Enumeration>(static_cast<IntType>(m_enum) >> 1);
91 return previous;
92 }
93
94 PBitwiseEnum operator--(int)
95 {
96 m_enum = static_cast<Enumeration>(static_cast<IntType>(m_enum) >> 1);
97 return *this;
98 }
99
100
101 #define P_BITWISE_ENUM_INTERNAL_OP1(op) (static_cast<IntType>(m_enum) op static_cast<IntType>(rhs))
102 #define P_BITWISE_ENUM_INTERNAL_OP2(op) static_cast<Enumeration>(P_BITWISE_ENUM_INTERNAL_OP1(op))
103
104 __inline PBitwiseEnum & operator|=(Enumeration rhs) { m_enum = P_BITWISE_ENUM_INTERNAL_OP2( | ); return *this; }
105 __inline PBitwiseEnum & operator+=(Enumeration rhs) { m_enum = P_BITWISE_ENUM_INTERNAL_OP2( | ); return *this; }
106 __inline PBitwiseEnum & operator-=(Enumeration rhs) { m_enum = P_BITWISE_ENUM_INTERNAL_OP2(& ~); return *this; }
107 __inline PBitwiseEnum & operator^=(Enumeration rhs) { m_enum = P_BITWISE_ENUM_INTERNAL_OP2( ^ ); return *this; }
108
109 __inline PBitwiseEnum operator+ (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP2( | ); }
110 __inline PBitwiseEnum operator| (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP2( | ); }
111 __inline PBitwiseEnum operator- (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP2(& ~); }
112 __inline PBitwiseEnum operator^ (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP2( ^ ); }
113
114 __inline bool operator& (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(&) != 0; }
115 __inline bool operator==(Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(==); }
116 __inline bool operator<=(Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(<=); }
117 __inline bool operator>=(Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(>=); }
118
119 __inline bool operator!=(Enumeration rhs) const { return !operator==(rhs); }
120 __inline bool operator< (Enumeration rhs) const { return !operator>=(rhs); }
121 __inline bool operator> (Enumeration rhs) const { return !operator<=(rhs); }
122
123 __inline PBitwiseEnum & operator|=(PBitwiseEnum rhs) { return operator|=(rhs.m_enum); }
124 __inline PBitwiseEnum & operator+=(PBitwiseEnum rhs) { return operator+=(rhs.m_enum); }
125 __inline PBitwiseEnum & operator-=(PBitwiseEnum rhs) { return operator-=(rhs.m_enum); }
126 __inline PBitwiseEnum & operator^=(PBitwiseEnum rhs) { return operator^=(rhs.m_enum); }
127
128 __inline PBitwiseEnum operator| (PBitwiseEnum rhs) const { return operator|(rhs.m_enum); }
129 __inline PBitwiseEnum operator+ (PBitwiseEnum rhs) const { return operator+(rhs.m_enum); }
130 __inline PBitwiseEnum operator- (PBitwiseEnum rhs) const { return operator-(rhs.m_enum); }
131 __inline PBitwiseEnum operator^ (PBitwiseEnum rhs) const { return operator^(rhs.m_enum); }
132
133 __inline bool operator& (PBitwiseEnum rhs) const { return operator& (rhs.m_enum); }
134 __inline bool operator==(PBitwiseEnum rhs) const { return operator==(rhs.m_enum); }
135 __inline bool operator<=(PBitwiseEnum rhs) const { return operator<=(rhs.m_enum); }
136 __inline bool operator>=(PBitwiseEnum rhs) const { return operator>=(rhs.m_enum); }
137
138 __inline bool operator!=(PBitwiseEnum rhs) const { return !operator==(rhs); }
139 __inline bool operator< (PBitwiseEnum rhs) const { return !operator>=(rhs); }
140 __inline bool operator> (PBitwiseEnum rhs) const { return !operator<=(rhs); }
141
142 __inline PBitwiseEnum operator~ () const { return FromBits(~m_enum); }
143 };
144
145
146 #define P_DECLARE_BITWISE_ENUM_1(_0,_1)_0=0,_1=1
147 #define P_DECLARE_BITWISE_ENUM_2(_0,_1,_2)P_DECLARE_BITWISE_ENUM_1(_0,_1),_2=2
148 #define P_DECLARE_BITWISE_ENUM_3(_0,_1,_2,_3)P_DECLARE_BITWISE_ENUM_2(_0,_1,_2),_3=4
149 #define P_DECLARE_BITWISE_ENUM_4(_0,_1,_2,_3,_4)P_DECLARE_BITWISE_ENUM_3(_0,_1,_2,_3),_4=8
150 #define P_DECLARE_BITWISE_ENUM_5(_0,_1,_2,_3,_4,_5)P_DECLARE_BITWISE_ENUM_4(_0,_1,_2,_3,_4),_5=16
151 #define P_DECLARE_BITWISE_ENUM_6(_0,_1,_2,_3,_4,_5,_6)P_DECLARE_BITWISE_ENUM_5(_0,_1,_2,_3,_4,_5),_6=32
152 #define P_DECLARE_BITWISE_ENUM_7(_0,_1,_2,_3,_4,_5,_6,_7)P_DECLARE_BITWISE_ENUM_6(_0,_1,_2,_3,_4,_5,_6),_7=64
153 #define P_DECLARE_BITWISE_ENUM_8(_0,_1,_2,_3,_4,_5,_6,_7,_8)P_DECLARE_BITWISE_ENUM_7(_0,_1,_2,_3,_4,_5,_6,_7),_8=128
154 #define P_DECLARE_BITWISE_ENUM_9(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9)P_DECLARE_BITWISE_ENUM_8(_0,_1,_2,_3,_4,_5,_6,_7,_8),_9=256
155
156 #define P_DECLARE_BITWISE_NAMES_1(_0,_1)#_0,#_1
157 #define P_DECLARE_BITWISE_NAMES_2(_0,_1,_2)P_DECLARE_BITWISE_NAMES_1(_0,_1),#_2
158 #define P_DECLARE_BITWISE_NAMES_3(_0,_1,_2,_3)P_DECLARE_BITWISE_NAMES_2(_0,_1,_2),#_3
159 #define P_DECLARE_BITWISE_NAMES_4(_0,_1,_2,_3,_4)P_DECLARE_BITWISE_NAMES_3(_0,_1,_2,_3),#_4
160 #define P_DECLARE_BITWISE_NAMES_5(_0,_1,_2,_3,_4,_5)P_DECLARE_BITWISE_NAMES_4(_0,_1,_2,_3,_4),#_5
161 #define P_DECLARE_BITWISE_NAMES_6(_0,_1,_2,_3,_4,_5,_6)P_DECLARE_BITWISE_NAMES_5(_0,_1,_2,_3,_4,_5),#_6
162 #define P_DECLARE_BITWISE_NAMES_7(_0,_1,_2,_3,_4,_5,_6,_7)P_DECLARE_BITWISE_NAMES_6(_0,_1,_2,_3,_4,_5,_6),#_7
163 #define P_DECLARE_BITWISE_NAMES_8(_0,_1,_2,_3,_4,_5,_6,_7,_8)P_DECLARE_BITWISE_NAMES_7(_0,_1,_2,_3,_4,_5,_6,_7),#_8
164 #define P_DECLARE_BITWISE_NAMES_9(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9)P_DECLARE_BITWISE_NAMES_8(_0,_1,_2,_3,_4,_5,_6,_7,_8),#_9
165
166 #define P_DECLARE_BITWISE_ENUM_FRIENDS(name) \
167 __inline friend name##_Bits operator+(name##_Bits lhs, name##_Bits rhs) \
168 { return static_cast<name##_Bits>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); } \
169 __inline friend name##_Bits operator|(name##_Bits lhs, name##_Bits rhs) \
170 { return static_cast<name##_Bits>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); } \
171 __inline friend name##_Bits operator-(name##_Bits lhs, name##_Bits rhs) \
172 { return static_cast<name##_Bits>(static_cast<unsigned>(lhs) & ~static_cast<unsigned>(rhs)); }
173
174 #define P_DECLARE_BITWISE_ENUM_END(name, count) \
175 P_DECLARE_BITWISE_ENUM_FRIENDS(name) \
176 typedef PBitwiseEnum<name##_Bits, (name##_Bits)(1<<(count-1))> name
177
178
189 #define P_DECLARE_BITWISE_ENUM(name, count, values) \
190 enum name##_Bits { P_DECLARE_BITWISE_ENUM_##count values }; \
191 P_DECLARE_BITWISE_ENUM_END(name, count)
192
204 #define P_DECLARE_BITWISE_ENUM_EX(name, count, values, ...) \
205 enum name##_Bits { P_DECLARE_BITWISE_ENUM_##count values , ##__VA_ARGS__ }; \
206 P_DECLARE_BITWISE_ENUM_END(name, count)
207
208
209 extern void PPrintBitwiseEnum(std::ostream & strm, unsigned bits, char const * const * names);
210 extern unsigned PReadBitwiseEnum(std::istream & strm, char const * const * names, bool continueOnError = false);
211
212
213 template <typename BaseEnum, BaseEnum MaxValue, typename BaseInt = unsigned>
214 class PStreamableBitwiseEnum : public PBitwiseEnum<BaseEnum, MaxValue, BaseInt>
215 {
216 public:
217 typedef PBitwiseEnum<BaseEnum, MaxValue, BaseInt> BaseClass;
218
219 __inline PStreamableBitwiseEnum(typename BaseClass::Enumeration e = BaseClass::Zero()) : BaseClass(e) { }
220 __inline PStreamableBitwiseEnum(typename BaseClass::IteratorBounds b) : BaseClass(b) { }
221 __inline virtual ~PStreamableBitwiseEnum() { }
222
223 friend __inline std::ostream & operator<<(std::ostream & strm, const PStreamableBitwiseEnum & e)
224 {
225 PPrintBitwiseEnum(strm, e.AsBits(), e.Names());
226 return strm;
227 }
228
229 friend __inline std::istream & operator>>(std::istream & strm, PStreamableBitwiseEnum & e)
230 {
231 e.m_enum = BaseClass::FromBits(PReadBitwiseEnum(strm, e.Names(), false));
232 return strm;
233 }
234
235 PString ToString()
236 {
237 PStringStream strm;
238 strm >> *this;
239 return strm;
240 }
241
242 bool FromString(const PString & s, bool clear = true)
243 {
244 if (clear)
245 this->m_enum = BaseClass::Zero();
246
247 PStringStream strm(s);
248 this->m_enum = BaseClass::FromBits(this->m_enum | PReadBitwiseEnum(strm, Names(), true));
249 return strm.good();
250 }
251
252 virtual char const * const * Names() const = 0;
253 };
254
255 #define P_DECLARE_STREAMABLE_BITWISE_ENUM_EX(name, count, values, ...) \
256 enum name##_Bits { P_DECLARE_BITWISE_ENUM_##count values }; \
257 P_DECLARE_BITWISE_ENUM_FRIENDS(name) \
258 class name : public PStreamableBitwiseEnum<name##_Bits, (name##_Bits)(1<<count)>{ \
259 public: typedef PStreamableBitwiseEnum<name##_Bits, (name##_Bits)(1<<count)> BaseClass; \
260 __inline name(BaseClass::Enumeration e = BaseClass::Zero()) : BaseClass(e) { } \
261 __inline name(IteratorBounds b) : BaseClass(b) { } \
262 __inline explicit name(const PString & s) { FromString(s); } \
263 virtual char const * const * Names() const { static char const * const Strings[] = { __VA_ARGS__, NULL }; return Strings; } \
264 }
265
266 #define P_DECLARE_STREAMABLE_BITWISE_ENUM(name, count, values) \
267 P_DECLARE_STREAMABLE_BITWISE_ENUM_EX(name, count, values, P_DECLARE_BITWISE_NAMES_##count values)
268
269
270 #endif // PTLIB_BITWISE_ENUM_H
271
272
273 // End Of File ///////////////////////////////////////////////////////////////