ROSE 0.11.145.147
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 BitFlags& set(Enum e) {
144 vector_ |= Vector(e);
145 return *this;
146 }
147
150 vector_ |= other.vector_;
151 return *this;
152 }
153
155 BitFlags& clear(Enum e) {
156 vector_ &= ~Vector(e);
157 return *this;
158 }
159
162 vector_ &= ~other.vector_;
163 return *this;
164 }
165
168 vector_ = Vector(0);
169 return *this;
170 }
171
173 bool testAndClear(Enum e) {
174 bool retval = isSet(e);
175 clear(e);
176 return retval;
177 }
178
180 bool testAndSet(Enum e) {
181 bool retval = isSet(e);
182 set(e);
183 return retval;
184 }
185
187 BitFlags& operator=(Vector v) {
188 vector_ = v;
189 return *this;
190 }
191
194 vector_ = other.vector_;
195 return *this;
196 }
197
202 return vector_ | other.vector_;
203 }
204 BitFlags operator|(Enum e) const {
205 return vector_ | Vector(e);
206 }
213 return vector_ & other.vector_;
214 }
215 BitFlags intersection(Enum e) const {
216 return vector_ & Vector(e);
217 }
219 return intersection(other);
220 }
221 BitFlags operator&(Enum e) const {
222 return intersection(e);
223 }
229 bool operator==(BitFlags other) const {
230 return vector_ == other.vector_;
231 }
232 bool operator!=(BitFlags other) const {
233 return vector_ != other.vector_;
234 }
235 bool operator<(BitFlags other) const {
236 return vector_ < other.vector_;
237 }
238 bool operator<=(BitFlags other) const {
239 return vector_ <= other.vector_;
240 }
241 bool operator>(BitFlags other) const {
242 return vector_ > other.vector_;
243 }
244 bool operator>=(BitFlags other) const {
245 return vector_ >= other.vector_;
246 }
254 std::vector<Enum> split(std::vector<int64_t> constants, Vector &leftovers /*out*/) const {
255 leftovers = Vector(0);
256 std::vector<Enum> retval;
257 std::sort(constants.begin(), constants.end(), moreBits);
258 Vector tmp = vector_;
259 while (tmp) {
260 bool found = false;
261 for (size_t i=0; i<constants.size() && !found; ++i) {
262 if (Vector(tmp & constants[i]) == Vector(constants[i]) && constants[i] != 0) {
263 retval.push_back(Enum(constants[i]));
264 tmp &= ~constants[i];
265 found = true;
266 }
267 }
268 if (!found) {
269 leftovers = tmp;
270 tmp = 0;
271 }
272 }
273 return retval;
274 }
275
277 std::vector<Enum> split() const {
278 std::vector<Enum> retval;
279 for (size_t i = 0; i < 8*sizeof(Enum); ++i) {
280 Enum e = static_cast<Enum>(uint64_t(1) << i);
281 if (isSet(e))
282 retval.push_back(e);
283 }
284 return retval;
285 }
286
287#if __cplusplus >= 201103L
291 template<class F>
292 void each(std::vector<int64_t> constants, const F &functor) const {
293 Vector leftovers;
294 for (Enum e: split(constants, leftovers))
295 functor(e);
296 }
297
301 template<class F>
302 void each(const F &functor) const {
303 for (Enum e: split())
304 functor(e);
305 }
306#endif
307
308private:
309 static size_t nBits(Vector vector) {
310 size_t retval = 0;
311 for (size_t i = 0; i < 8*sizeof(Vector); ++i) {
312 if ((vector & (Vector(1) << i)) != 0)
313 ++retval;
314 }
315 return retval;
316 }
317
318 static bool moreBits(Vector a, Vector b) {
319 return nBits(a) > nBits(b);
320 }
321};
322
323} // namespace
324#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.
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.
BitFlags()
Default constructor with all bits clear.
Sawyer support library.