ROSE  0.11.145.0
util/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  BitFlags(const BitFlags &other)
96  : vector_(other.vector_) {}
97 
99  Vector vector() const {
100  return vector_;
101  }
102 
104  bool isSet(Enum e) const {
105  return (vector_ & Vector(e)) != 0;
106  }
107 
109  bool isAllSet(BitFlags other) const {
110  return (vector_ & other.vector_) == other.vector_;
111  }
112 
114  bool isAnySet(BitFlags other) const {
115  return (vector_ & other.vector_) != 0;
116  }
117 
119  bool isAnySet() const {
120  return vector_ != 0;
121  }
122 
124  bool isEmpty() const {
125  return 0 == vector_;
126  }
127 
129  bool isClear(Enum e) const {
130  return !isSet(e);
131  }
132 
134  BitFlags& set(Enum e) {
135  vector_ |= Vector(e);
136  return *this;
137  }
138 
141  vector_ |= other.vector_;
142  return *this;
143  }
144 
146  BitFlags& clear(Enum e) {
147  vector_ &= ~Vector(e);
148  return *this;
149  }
150 
153  vector_ &= ~other.vector_;
154  return *this;
155  }
156 
159  vector_ = Vector(0);
160  return *this;
161  }
162 
164  bool testAndClear(Enum e) {
165  bool retval = isSet(e);
166  clear(e);
167  return retval;
168  }
169 
171  bool testAndSet(Enum e) {
172  bool retval = isSet(e);
173  set(e);
174  return retval;
175  }
176 
178  BitFlags& operator=(Vector v) {
179  vector_ = v;
180  return *this;
181  }
182 
185  vector_ = other.vector_;
186  return *this;
187  }
188 
192  BitFlags operator|(BitFlags other) const {
193  return vector_ | other.vector_;
194  }
195  BitFlags operator|(Enum e) const {
196  return vector_ | Vector(e);
197  }
204  return vector_ & other.vector_;
205  }
206  BitFlags intersection(Enum e) const {
207  return vector_ & Vector(e);
208  }
209  BitFlags operator&(BitFlags other) const {
210  return intersection(other);
211  }
212  BitFlags operator&(Enum e) const {
213  return intersection(e);
214  }
220  bool operator==(BitFlags other) const {
221  return vector_ == other.vector_;
222  }
223  bool operator!=(BitFlags other) const {
224  return vector_ != other.vector_;
225  }
226  bool operator<(BitFlags other) const {
227  return vector_ < other.vector_;
228  }
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  }
245  std::vector<Enum> split(std::vector<int64_t> constants, Vector &leftovers /*out*/) const {
246  leftovers = Vector(0);
247  std::vector<Enum> retval;
248  std::sort(constants.begin(), constants.end(), moreBits);
249  Vector tmp = vector_;
250  while (tmp) {
251  bool found = false;
252  for (size_t i=0; i<constants.size() && !found; ++i) {
253  if (Vector(tmp & constants[i]) == Vector(constants[i]) && constants[i] != 0) {
254  retval.push_back(Enum(constants[i]));
255  tmp &= ~constants[i];
256  found = true;
257  }
258  }
259  if (!found) {
260  leftovers = tmp;
261  tmp = 0;
262  }
263  }
264  return retval;
265  }
266 
268  std::vector<Enum> split() const {
269  std::vector<Enum> retval;
270  for (size_t i = 0; i < 8*sizeof(Enum); ++i) {
271  Enum e = static_cast<Enum>(uint64_t(1) << i);
272  if (isSet(e))
273  retval.push_back(e);
274  }
275  return retval;
276  }
277 
278 #if __cplusplus >= 201103L
279 
282  template<class F>
283  void each(std::vector<int64_t> constants, const F &functor) const {
284  Vector leftovers;
285  for (Enum e: split(constants, leftovers))
286  functor(e);
287  }
288 
292  template<class F>
293  void each(const F &functor) const {
294  for (Enum e: split())
295  functor(e);
296  }
297 #endif
298 
299 private:
300  static size_t nBits(Vector vector) {
301  size_t retval = 0;
302  for (size_t i = 0; i < 8*sizeof(Vector); ++i) {
303  if ((vector & (Vector(1) << i)) != 0)
304  ++retval;
305  }
306  return retval;
307  }
308 
309  static bool moreBits(Vector a, Vector b) {
310  return nBits(a) > nBits(b);
311  }
312 };
313 
314 } // namespace
315 #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.
std::vector< Enum > split() const
Split a vector into the individual bits values.
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.
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.
Definition: FeasiblePath.h:767
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(const BitFlags &other)
Copy constructor.
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.