PTLib  Version 2.14.3
 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: 31484 $
27  * $Author: rjongbloed $
28  * $Date: 2014-02-15 21:52:20 +1100 (Sat, 15 Feb 2014) $
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>
44 {
45  public:
46  typedef BaseEnum Enumeration;
47  typedef BaseInt IntType;
48 
49  protected:
51 
52  public:
53  static __inline Enumeration Zero() { return (Enumeration)0; }
54  static __inline Enumeration All() { return (Enumeration)((MaxValue<<1)-1); }
55  static __inline Enumeration Begin() { return (Enumeration)1; }
56  static __inline Enumeration End() { return MaxValue; }
57 
58  __inline PBitwiseEnum(Enumeration e = Zero()) : m_enum(e) { }
59  __inline PBitwiseEnum(const PBitwiseEnum & e) : m_enum(e.m_enum) { }
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 &All()); }
70  __inline static Enumeration FromBit (unsigned b) { return (Enumeration)((1<<b)&All()); }
71 
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 
81  {
82  if (m_enum < MaxValue)
83  m_enum = static_cast<Enumeration>(static_cast<IntType>(m_enum) << 1);
84  return *this;
85  }
86 
88  {
89  Enumeration previous = m_enum;
90  m_enum = static_cast<Enumeration>(static_cast<IntType>(m_enum) >> 1);
91  return previous;
92  }
93 
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  __inline PBitwiseEnum & operator^=(Enumeration rhs) { m_enum = P_BITWISE_ENUM_INTERNAL_OP2( ^ ); return *this; }
109 
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  __inline PBitwiseEnum operator* (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP2( & ); }
114  __inline PBitwiseEnum operator^ (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP2( ^ ); }
115 
116  __inline bool operator& (Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(&) != 0; }
117  __inline bool operator==(Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(==); }
118  __inline bool operator<=(Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(<=); }
119  __inline bool operator>=(Enumeration rhs) const { return P_BITWISE_ENUM_INTERNAL_OP1(>=); }
120 
121  __inline bool operator!=(Enumeration rhs) const { return !operator==(rhs); }
122  __inline bool operator< (Enumeration rhs) const { return !operator>=(rhs); }
123  __inline bool operator> (Enumeration rhs) const { return !operator<=(rhs); }
124 
125  __inline PBitwiseEnum & operator|=(PBitwiseEnum rhs) { return operator|=(rhs.m_enum); }
126  __inline PBitwiseEnum & operator+=(PBitwiseEnum rhs) { return operator+=(rhs.m_enum); }
127  __inline PBitwiseEnum & operator-=(PBitwiseEnum rhs) { return operator-=(rhs.m_enum); }
128  __inline PBitwiseEnum & operator*=(PBitwiseEnum rhs) { return operator*=(rhs.m_enum); }
129  __inline PBitwiseEnum & operator^=(PBitwiseEnum rhs) { return operator^=(rhs.m_enum); }
130 
131  __inline PBitwiseEnum operator| (PBitwiseEnum rhs) const { return operator|(rhs.m_enum); }
132  __inline PBitwiseEnum operator+ (PBitwiseEnum rhs) const { return operator+(rhs.m_enum); }
133  __inline PBitwiseEnum operator- (PBitwiseEnum rhs) const { return operator-(rhs.m_enum); }
134  __inline PBitwiseEnum operator* (PBitwiseEnum rhs) const { return operator*(rhs.m_enum); }
135  __inline PBitwiseEnum operator^ (PBitwiseEnum rhs) const { return operator^(rhs.m_enum); }
136 
137  __inline bool operator& (PBitwiseEnum rhs) const { return operator& (rhs.m_enum); }
138  __inline bool operator==(PBitwiseEnum rhs) const { return operator==(rhs.m_enum); }
139  __inline bool operator<=(PBitwiseEnum rhs) const { return operator<=(rhs.m_enum); }
140  __inline bool operator>=(PBitwiseEnum rhs) const { return operator>=(rhs.m_enum); }
141 
142  __inline bool operator!=(PBitwiseEnum rhs) const { return !operator==(rhs); }
143  __inline bool operator< (PBitwiseEnum rhs) const { return !operator>=(rhs); }
144  __inline bool operator> (PBitwiseEnum rhs) const { return !operator<=(rhs); }
145 
146  __inline PBitwiseEnum operator~ () const { return FromBits(~m_enum); }
147 };
148 
149 
150 #define P_DECLARE_BITWISE_ENUM_1(_0,_1)_0=0,_1=1
151 #define P_DECLARE_BITWISE_ENUM_2(_0,_1,_2)P_DECLARE_BITWISE_ENUM_1(_0,_1),_2=2
152 #define P_DECLARE_BITWISE_ENUM_3(_0,_1,_2,_3)P_DECLARE_BITWISE_ENUM_2(_0,_1,_2),_3=4
153 #define P_DECLARE_BITWISE_ENUM_4(_0,_1,_2,_3,_4)P_DECLARE_BITWISE_ENUM_3(_0,_1,_2,_3),_4=8
154 #define P_DECLARE_BITWISE_ENUM_5(_0,_1,_2,_3,_4,_5)P_DECLARE_BITWISE_ENUM_4(_0,_1,_2,_3,_4),_5=16
155 #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
156 #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
157 #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
158 #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
159 #define P_DECLARE_BITWISE_ENUM_10(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10)P_DECLARE_BITWISE_ENUM_9(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9),_10=512
160 #define P_DECLARE_BITWISE_ENUM_11(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11)P_DECLARE_BITWISE_ENUM_10(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10),_11=1024
161 #define P_DECLARE_BITWISE_ENUM_12(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12)P_DECLARE_BITWISE_ENUM_11(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11),_11=2048
162 
163 #define P_DECLARE_BITWISE_NAMES_1(_0,_1)#_0,#_1
164 #define P_DECLARE_BITWISE_NAMES_2(_0,_1,_2)P_DECLARE_BITWISE_NAMES_1(_0,_1),#_2
165 #define P_DECLARE_BITWISE_NAMES_3(_0,_1,_2,_3)P_DECLARE_BITWISE_NAMES_2(_0,_1,_2),#_3
166 #define P_DECLARE_BITWISE_NAMES_4(_0,_1,_2,_3,_4)P_DECLARE_BITWISE_NAMES_3(_0,_1,_2,_3),#_4
167 #define P_DECLARE_BITWISE_NAMES_5(_0,_1,_2,_3,_4,_5)P_DECLARE_BITWISE_NAMES_4(_0,_1,_2,_3,_4),#_5
168 #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
169 #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
170 #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
171 #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
172 #define P_DECLARE_BITWISE_NAMES_10(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10)P_DECLARE_BITWISE_NAMES_9(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9),#_10
173 #define P_DECLARE_BITWISE_NAMES_11(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11)P_DECLARE_BITWISE_NAMES_10(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10),#_11
174 #define P_DECLARE_BITWISE_NAMES_12(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11,_12)P_DECLARE_BITWISE_NAMES_11(_0,_1,_2,_3,_4,_5,_6,_7,_8,_9,_10,_11),#_12
175 
176 #define P_DECLARE_BITWISE_ENUM_FRIENDS(name) \
177  __inline friend name##_Bits operator+(name##_Bits lhs, name##_Bits rhs) \
178  { return static_cast<name##_Bits>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); } \
179  __inline friend name##_Bits operator|(name##_Bits lhs, name##_Bits rhs) \
180  { return static_cast<name##_Bits>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); } \
181  __inline friend name##_Bits operator-(name##_Bits lhs, name##_Bits rhs) \
182  { return static_cast<name##_Bits>(static_cast<unsigned>(lhs) & ~static_cast<unsigned>(rhs)); }
183 
184 #define P_DECLARE_BITWISE_ENUM_END(name, count) \
185  P_DECLARE_BITWISE_ENUM_FRIENDS(name) \
186  typedef PBitwiseEnum<name##_Bits, (name##_Bits)(1<<(count-1))> name
187 
188 
199 #define P_DECLARE_BITWISE_ENUM(name, count, values) \
200  enum name##_Bits { P_DECLARE_BITWISE_ENUM_##count values }; \
201  P_DECLARE_BITWISE_ENUM_END(name, count)
202 
214 #define P_DECLARE_BITWISE_ENUM_EX(name, count, values, ...) \
215  enum name##_Bits { P_DECLARE_BITWISE_ENUM_##count values , ##__VA_ARGS__ }; \
216  P_DECLARE_BITWISE_ENUM_END(name, count)
217 
218 
219 extern void PPrintBitwiseEnum(std::ostream & strm, unsigned bits, char const * const * names);
220 extern unsigned PReadBitwiseEnum(std::istream & strm, char const * const * names, bool continueOnError = false);
221 
222 
223 template <typename BaseEnum, BaseEnum MaxValue, typename BaseInt = unsigned>
224 class PStreamableBitwiseEnum : public PBitwiseEnum<BaseEnum, MaxValue, BaseInt>
225 {
226  public:
228 
230  __inline virtual ~PStreamableBitwiseEnum() { }
231 
232  friend __inline std::ostream & operator<<(std::ostream & strm, const PStreamableBitwiseEnum & e)
233  {
234  PPrintBitwiseEnum(strm, e.AsBits(), e.Names());
235  return strm;
236  }
237 
238  friend __inline std::istream & operator>>(std::istream & strm, PStreamableBitwiseEnum & e)
239  {
240  e.m_enum = BaseClass::FromBits(PReadBitwiseEnum(strm, e.Names(), false));
241  return strm;
242  }
243 
245  {
246  PStringStream strm;
247  strm >> *this;
248  return strm;
249  }
250 
251  bool FromString(const PString & s, bool clear = true)
252  {
253  if (clear)
254  this->m_enum = BaseClass::Zero();
255 
256  PStringStream strm(s);
257  this->m_enum = BaseClass::FromBits(this->m_enum | PReadBitwiseEnum(strm, Names(), true));
258  return strm.good();
259  }
260 
261  virtual char const * const * Names() const = 0;
262 };
263 
264 #define P_DECLARE_STREAMABLE_BITWISE_ENUM_EX(name, count, values, ...) \
265  enum name##_Bits { P_DECLARE_BITWISE_ENUM_##count values }; \
266  P_DECLARE_BITWISE_ENUM_FRIENDS(name) \
267  class name : public PStreamableBitwiseEnum<name##_Bits, (name##_Bits)(1<<count)>{ \
268  public: typedef PStreamableBitwiseEnum<name##_Bits, (name##_Bits)(1<<count)> BaseClass; \
269  __inline name(BaseClass::Enumeration e = BaseClass::Zero()) : BaseClass(e) { } \
270  __inline explicit name(const PString & s) { FromString(s); } \
271  virtual char const * const * Names() const { static char const * const Strings[] = { __VA_ARGS__, NULL }; return Strings; } \
272  }
273 
274 #define P_DECLARE_STREAMABLE_BITWISE_ENUM(name, count, values) \
275  P_DECLARE_STREAMABLE_BITWISE_ENUM_EX(name, count, values, P_DECLARE_BITWISE_NAMES_##count values)
276 
277 
278 #endif // PTLIB_BITWISE_ENUM_H
279 
280 
281 // End Of File ///////////////////////////////////////////////////////////////