ROSE 0.11.145.192
Sawyer/BitFlags.h
1// WARNING: Changes to this file must be contributed back to Sawyer or else they will
2// be clobbered by the next update from Sawyer. The Sawyer repository is at
3// https://gitlab.com/charger7534/sawyer.git.
4
5
6
7
8#ifndef Sawyer_BitFlags_H
9#define Sawyer_BitFlags_H
10
11#include <Sawyer/Sawyer.h>
12
13#include <vector>
14
15namespace Sawyer {
16
62template<typename E, typename V = int64_t>
63class BitFlags {
64public:
65 typedef E Enum;
66 typedef V Vector;
67
68private:
69 Vector vector_;
70
71#ifdef SAWYER_HAVE_BOOST_SERIALIZATION
72private:
73 friend class boost::serialization::access;
74
75 template<class S>
76 void serialize(S &s, const unsigned /*version*/) {
77 s & BOOST_SERIALIZATION_NVP(vector_);
78 }
79#endif
80
81#ifdef SAWYER_HAVE_CEREAL
82private:
83 friend class cereal::access;
84
85 template<class Archive>
86 void serialize(Archive &archive) {
87 archive(CEREAL_NVP(vector_));
88 }
89#endif
90
91public:
94 : vector_(0) {}
95
97 BitFlags(Vector v) /*implicit*/
98 : vector_(v) {}
99
100 BitFlags(E e) /*implicit*/
101 : vector_(Vector(e)) {}
102
104 BitFlags(const BitFlags &other)
105 : vector_(other.vector_) {}
106
108 Vector vector() const {
109 return vector_;
110 }
111
113 bool isSet(Enum e) const {
114 return (vector_ & Vector(e)) != 0;
115 }
116
118 bool isAllSet(BitFlags other) const {
119 return (vector_ & other.vector_) == other.vector_;
120 }
121
123 bool isAnySet(BitFlags other) const {
124 return (vector_ & other.vector_) != 0;
125 }
126
128 bool isAnySet() const {
129 return vector_ != 0;
130 }
131
133 bool isEmpty() const {
134 return 0 == vector_;
135 }
136
138 bool isClear(Enum e) const {
139 return !isSet(e);
140 }
141
143 bool isAllClear(const BitFlags other) const {
144 return (~vector_ & other.vector_) == other.vector_;
145 }
146
148 bool isAnyClear(const BitFlags other) const {
149 return (~vector_ & other.vector_) != 0;
150 }
151
153 BitFlags& set(Enum e) {
154 vector_ |= Vector(e);
155 return *this;
156 }
157
160 vector_ |= other.vector_;
161 return *this;
162 }
163
165 BitFlags& clear(Enum e) {
166 vector_ &= ~Vector(e);
167 return *this;
168 }
169
172 vector_ &= ~other.vector_;
173 return *this;
174 }
175
178 vector_ = Vector(0);
179 return *this;
180 }
181
183 bool testAndClear(Enum e) {
184 bool retval = isSet(e);
185 clear(e);
186 return retval;
187 }
188
190 bool testAndSet(Enum e) {
191 bool retval = isSet(e);
192 set(e);
193 return retval;
194 }
195
197 BitFlags& operator=(Vector v) {
198 vector_ = v;
199 return *this;
200 }
201
204 vector_ = other.vector_;
205 return *this;
206 }
207
212 return vector_ | other.vector_;
213 }
214 BitFlags operator|(Enum e) const {
215 return vector_ | Vector(e);
216 }
223 return vector_ & other.vector_;
224 }
225 BitFlags intersection(Enum e) const {
226 return vector_ & Vector(e);
227 }
229 return intersection(other);
230 }
231 BitFlags operator&(Enum e) const {
232 return intersection(e);
233 }
239 bool operator==(BitFlags other) const {
240 return vector_ == other.vector_;
241 }
242 bool operator!=(BitFlags other) const {
243 return vector_ != other.vector_;
244 }
245 bool operator<(BitFlags other) const {
246 return vector_ < other.vector_;
247 }
248 bool operator<=(BitFlags other) const {
249 return vector_ <= other.vector_;
250 }
251 bool operator>(BitFlags other) const {
252 return vector_ > other.vector_;
253 }
254 bool operator>=(BitFlags other) const {
255 return vector_ >= other.vector_;
256 }
264 std::vector<Enum> split(std::vector<int64_t> constants, Vector &leftovers /*out*/) const {
265 leftovers = Vector(0);
266 std::vector<Enum> retval;
267 std::sort(constants.begin(), constants.end(), moreBits);
268 Vector tmp = vector_;
269 while (tmp) {
270 bool found = false;
271 for (size_t i=0; i<constants.size() && !found; ++i) {
272 if (Vector(tmp & constants[i]) == Vector(constants[i]) && constants[i] != 0) {
273 retval.push_back(Enum(constants[i]));
274 tmp &= ~constants[i];
275 found = true;
276 }
277 }
278 if (!found) {
279 leftovers = tmp;
280 tmp = 0;
281 }
282 }
283 return retval;
284 }
285
287 std::vector<Enum> split() const {
288 std::vector<Enum> retval;
289 for (size_t i = 0; i < 8*sizeof(Enum); ++i) {
290 Enum e = static_cast<Enum>(uint64_t(1) << i);
291 if (isSet(e))
292 retval.push_back(e);
293 }
294 return retval;
295 }
296
297#if __cplusplus >= 201103L
301 template<class F>
302 void each(std::vector<int64_t> constants, const F &functor) const {
303 Vector leftovers;
304 for (Enum e: split(constants, leftovers))
305 functor(e);
306 }
307
311 template<class F>
312 void each(const F &functor) const {
313 for (Enum e: split())
314 functor(e);
315 }
316#endif
317
318private:
319 static size_t nBits(Vector vector) {
320 size_t retval = 0;
321 for (size_t i = 0; i < 8*sizeof(Vector); ++i) {
322 if ((vector & (Vector(1) << i)) != 0)
323 ++retval;
324 }
325 return retval;
326 }
327
328 static bool moreBits(Vector a, Vector b) {
329 return nBits(a) > nBits(b);
330 }
331};
332
333} // namespace
334#endif
Stores a vector of enum bit flags.
BitFlags & operator=(BitFlags other)
Set the vector to the same as another.
BitFlags & set(Enum e)
Set the specified bit.
BitFlags & clear(BitFlags other)
Clear all bits that are set in other.
bool operator<(BitFlags other) const
Compare two vectors.
bool isClear(Enum e) const
Test whether a bit is clear.
bool isAllClear(const BitFlags other) const
True if all specified bits are clear.
BitFlags & clear(Enum e)
Clear the specified bit.
BitFlags operator|(Enum e) const
Create a new vector that's the union of two vectors.
BitFlags(const BitFlags &other)
Copy constructor.
BitFlags operator|(BitFlags other) const
Create a new vector that's the union of two vectors.
bool operator<=(BitFlags other) const
Compare two vectors.
bool operator!=(BitFlags other) const
Compare two vectors.
Vector vector() const
Current value of the bit vector.
BitFlags intersection(Enum e) const
Create a new vector that's the intersection of two vectors.
bool operator==(BitFlags other) const
Compare two vectors.
std::vector< Enum > split(std::vector< int64_t > constants, Vector &leftovers) const
Split a vector into the individual enum values.
BitFlags intersection(BitFlags other) const
Create a new vector that's the intersection of two vectors.
bool operator>(BitFlags other) const
Compare two vectors.
bool isAllSet(BitFlags other) const
True if all specified bits are set.
bool testAndSet(Enum e)
Test whether a bit is set, then set it.
bool isAnySet() const
True if any bit is set.
BitFlags operator&(Enum e) const
Create a new vector that's the intersection of two vectors.
std::vector< Enum > split() const
Split a vector into the individual bits values.
bool testAndClear(Enum e)
Test whether a bit is set, then clear it.
BitFlags & clear()
Clear all bits.
BitFlags operator&(BitFlags other) const
Create a new vector that's the intersection of two vectors.
bool operator>=(BitFlags other) const
Compare two vectors.
bool isEmpty() const
True if no bits are set.
BitFlags & set(BitFlags other)
Set all bits that are set in other.
bool isAnySet(BitFlags other) const
True if any of the specified bits are set.
BitFlags(Vector v)
Construct bit vector from value or bit.
BitFlags & operator=(Vector v)
Set the vector to an exact value.
bool isSet(Enum e) const
Test whether a bit is set.
bool isAnyClear(const BitFlags other) const
True if any specified bit is clear.
BitFlags()
Default constructor with all bits clear.
Sawyer support library.