ROSE  0.11.22.0
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://github.com/matzke1/sawyer.
4 
5 
6 
7 
8 #ifndef Sawyer_BitFlags_H
9 #define Sawyer_BitFlags_H
10 
11 #include <Sawyer/Sawyer.h>
12 
13 #include <boost/foreach.hpp>
14 #include <boost/serialization/access.hpp>
15 #include <Sawyer/Assert.h>
16 #include <vector>
17 
18 namespace Sawyer {
19 
65 template<typename E, typename V = int64_t>
66 class BitFlags {
67 public:
68  typedef E Enum;
69  typedef V Vector;
70 
71 private:
72  Vector vector_;
73 
74 private:
75  friend class boost::serialization::access;
76 
77  template<class S>
78  void serialize(S &s, const unsigned /*version*/) {
79  s & BOOST_SERIALIZATION_NVP(vector_);
80  }
81 
82 public:
85  : vector_(0) {}
86 
88  BitFlags(Vector v) /*implicit*/
89  : vector_(v) {}
90 
91  BitFlags(E e) /*implicit*/
92  : vector_(Vector(e)) {}
93 
95  Vector vector() const {
96  return vector_;
97  }
98 
100  bool isSet(Enum e) const {
101  return (vector_ & Vector(e)) != 0;
102  }
103 
105  bool isAllSet(BitFlags other) const {
106  return (vector_ & other.vector_) == other.vector_;
107  }
108 
110  bool isAnySet(BitFlags other) const {
111  return (vector_ & other.vector_) != 0;
112  }
113 
115  bool isAnySet() const {
116  return vector_ != 0;
117  }
118 
120  bool isEmpty() const {
121  return 0 == vector_;
122  }
123 
125  bool isClear(Enum e) const {
126  return !isSet(e);
127  }
128 
130  BitFlags& set(Enum e) {
131  vector_ |= Vector(e);
132  return *this;
133  }
134 
137  vector_ |= other.vector_;
138  return *this;
139  }
140 
142  BitFlags& clear(Enum e) {
143  vector_ &= ~Vector(e);
144  return *this;
145  }
146 
149  vector_ &= ~other.vector_;
150  return *this;
151  }
152 
155  vector_ = Vector(0);
156  return *this;
157  }
158 
160  bool testAndClear(Enum e) {
161  bool retval = isSet(e);
162  clear(e);
163  return retval;
164  }
165 
167  bool testAndSet(Enum e) {
168  bool retval = isSet(e);
169  set(e);
170  return retval;
171  }
172 
174  BitFlags& operator=(Vector v) {
175  vector_ = v;
176  return *this;
177  }
178 
181  vector_ = other.vector_;
182  return *this;
183  }
184 
188  BitFlags operator|(BitFlags other) const {
189  return vector_ | other.vector_;
190  }
191  BitFlags operator|(Enum e) const {
192  return vector_ | Vector(e);
193  }
200  return vector_ & other.vector_;
201  }
202  BitFlags intersection(Enum e) const {
203  return vector_ & Vector(e);
204  }
205  BitFlags operator&(BitFlags other) const {
206  return intersection(other);
207  }
208  BitFlags operator&(Enum e) const {
209  return intersection(e);
210  }
216  bool operator==(BitFlags other) const {
217  return vector_ == other.vector_;
218  }
219  bool operator!=(BitFlags other) const {
220  return vector_ != other.vector_;
221  }
222  bool operator<(BitFlags other) const {
223  return vector_ < other.vector_;
224  }
225  bool operator<=(BitFlags other) const {
226  return vector_ <= other.vector_;
227  }
228  bool operator>(BitFlags other) const {
229  return vector_ > other.vector_;
230  }
231  bool operator>=(BitFlags other) const {
232  return vector_ >= other.vector_;
233  }
241  std::vector<Enum> split(std::vector<int64_t> constants, Vector &leftovers /*out*/) const {
242  leftovers = Vector(0);
243  std::vector<Enum> retval;
244  std::sort(constants.begin(), constants.end(), moreBits);
245  Vector tmp = vector_;
246  while (tmp) {
247  bool found = false;
248  for (size_t i=0; i<constants.size() && !found; ++i) {
249  if (Vector(tmp & constants[i]) == Vector(constants[i]) && constants[i] != 0) {
250  retval.push_back(Enum(constants[i]));
251  tmp &= ~constants[i];
252  found = true;
253  }
254  }
255  if (!found) {
256  leftovers = tmp;
257  tmp = 0;
258  }
259  }
260  return retval;
261  }
262 
264  std::vector<Enum> split(Vector &leftovers /*out*/) const {
265  std::vector<Enum> retval;
266  for (size_t i = 0; i < 8*sizeof(Enum); ++i) {
267  Enum e = static_cast<Enum>(uint64_t(1) << i);
268  if (isSet(e))
269  retval.push_back(e);
270  }
271  return retval;
272  }
273 
274 #if __cplusplus >= 201103L
275 
278  template<class F>
279  void each(std::vector<int64_t> constants, const F &functor) const {
280  Vector leftovers;
281  for (Enum e: split(constants, leftovers))
282  functor(e);
283  }
284 
288  template<class F>
289  void each(const F &functor) const {
290  Vector leftovers;
291  for (Enum e: split(leftovers))
292  functor(e);
293  }
294 #endif
295 
296 private:
297  static size_t nBits(Vector vector) {
298  size_t retval = 0;
299  for (size_t i = 0; i < 8*sizeof(Vector); ++i) {
300  if ((vector & (Vector(1) << i)) != 0)
301  ++retval;
302  }
303  return retval;
304  }
305 
306  static bool moreBits(Vector a, Vector b) {
307  return nBits(a) > nBits(b);
308  }
309 };
310 
311 } // namespace
312 #endif
BitFlags & clear()
Clear all bits.
bool operator>=(BitFlags other) const
Compare two vectors.
BitFlags & set(Enum e)
Set the specified bit.
bool operator<(BitFlags other) const
Compare two vectors.
bool testAndSet(Enum e)
Test whether a bit is set, then set it.
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.
BitFlags & operator=(BitFlags other)
Set the vector to the same as another.
bool isSet(Enum e) const
Test whether a bit is set.
bool isEmpty() const
True if no bits are set.
bool operator!=(BitFlags other) const
Compare two vectors.
std::vector< Enum > split(Vector &leftovers) const
Split a vector into the individual bits values.
Stores a vector of enum bit flags.
Definition: BitFlags.h:60
Vector vector() const
Current value of the bit vector.
bool isAnySet() const
True if any bit is set.
bool operator<=(BitFlags other) const
Compare two vectors.
BitFlags operator|(Enum e) const
Create a new vector that's the union of two vectors.
Name space for the entire library.
BitFlags operator&(Enum e) const
Create a new vector that's the intersection of two vectors.
BitFlags operator|(BitFlags other) const
Create a new vector that's the union of two vectors.
BitFlags & clear(Enum e)
Clear the specified bit.
bool operator>(BitFlags other) const
Compare two vectors.
bool operator==(BitFlags other) const
Compare two vectors.
BitFlags & set(BitFlags other)
Set all bits that are set in other.
bool isClear(Enum e) const
Test whether a bit is clear.
BitFlags & operator=(Vector v)
Set the vector to an exact value.
bool testAndClear(Enum e)
Test whether a bit is set, then clear it.
BitFlags()
Default constructor with all bits clear.
BitFlags(Vector v)
Construct bit vector from value or bit.
bool isAllSet(BitFlags other) const
True if all specified bits are set.
BitFlags & clear(BitFlags other)
Clear all bits that are set in other.
bool isAnySet(BitFlags other) const
True if any of the specified bits are set.
BitFlags operator&(BitFlags other) const
Create a new vector that's the intersection of two vectors.
BitFlags intersection(Enum e) const
Create a new vector that's the intersection of two vectors.
Stores a vector of enum bit flags.