PTLib  Version 2.12.9
 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>
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 
55  __inline PBitwiseEnum(Enumeration e = Zero()) : m_enum(e) { }
56  __inline PBitwiseEnum(const PBitwiseEnum & e) : m_enum(e.m_enum) { }
57 
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 
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 
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:
218 
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 
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 ///////////////////////////////////////////////////////////////