ROSE  0.11.96.11
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  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
Sawyer::BitFlags::isAnySet
bool isAnySet(BitFlags other) const
True if any of the specified bits are set.
Definition: util/Sawyer/BitFlags.h:110
Sawyer::BitFlags::set
BitFlags & set(Enum e)
Set the specified bit.
Definition: util/Sawyer/BitFlags.h:130
Sawyer::BitFlags::operator=
BitFlags & operator=(Vector v)
Set the vector to an exact value.
Definition: util/Sawyer/BitFlags.h:174
Sawyer::BitFlags::testAndSet
bool testAndSet(Enum e)
Test whether a bit is set, then set it.
Definition: util/Sawyer/BitFlags.h:167
Sawyer::BitFlags::operator&
BitFlags operator&(BitFlags other) const
Create a new vector that's the intersection of two vectors.
Definition: util/Sawyer/BitFlags.h:205
Sawyer::BitFlags::operator==
bool operator==(BitFlags other) const
Compare two vectors.
Definition: util/Sawyer/BitFlags.h:216
Sawyer::BitFlags::clear
BitFlags & clear(Enum e)
Clear the specified bit.
Definition: util/Sawyer/BitFlags.h:142
Sawyer::BitFlags::intersection
BitFlags intersection(Enum e) const
Create a new vector that's the intersection of two vectors.
Definition: util/Sawyer/BitFlags.h:202
Sawyer::BitFlags::BitFlags
BitFlags()
Default constructor with all bits clear.
Definition: util/Sawyer/BitFlags.h:84
Sawyer::BitFlags::operator<=
bool operator<=(BitFlags other) const
Compare two vectors.
Definition: util/Sawyer/BitFlags.h:225
Sawyer::BitFlags::vector
Vector vector() const
Current value of the bit vector.
Definition: util/Sawyer/BitFlags.h:95
Sawyer::BitFlags::isAllSet
bool isAllSet(BitFlags other) const
True if all specified bits are set.
Definition: util/Sawyer/BitFlags.h:105
Sawyer::BitFlags::intersection
BitFlags intersection(BitFlags other) const
Create a new vector that's the intersection of two vectors.
Definition: util/Sawyer/BitFlags.h:199
Sawyer::BitFlags::split
std::vector< Enum > split(Vector &leftovers) const
Split a vector into the individual bits values.
Definition: util/Sawyer/BitFlags.h:264
Sawyer::BitFlags::operator|
BitFlags operator|(Enum e) const
Create a new vector that's the union of two vectors.
Definition: util/Sawyer/BitFlags.h:191
Sawyer::BitFlags::operator|
BitFlags operator|(BitFlags other) const
Create a new vector that's the union of two vectors.
Definition: util/Sawyer/BitFlags.h:188
Sawyer::BitFlags::operator&
BitFlags operator&(Enum e) const
Create a new vector that's the intersection of two vectors.
Definition: util/Sawyer/BitFlags.h:208
Sawyer::BitFlags::clear
BitFlags & clear(BitFlags other)
Clear all bits that are set in other.
Definition: util/Sawyer/BitFlags.h:148
Sawyer::BitFlags::operator=
BitFlags & operator=(BitFlags other)
Set the vector to the same as another.
Definition: util/Sawyer/BitFlags.h:180
Sawyer::BitFlags::operator!=
bool operator!=(BitFlags other) const
Compare two vectors.
Definition: util/Sawyer/BitFlags.h:219
Sawyer::BitFlags::isAnySet
bool isAnySet() const
True if any bit is set.
Definition: util/Sawyer/BitFlags.h:115
Sawyer::BitFlags::BitFlags
BitFlags(Vector v)
Construct bit vector from value or bit.
Definition: util/Sawyer/BitFlags.h:88
Sawyer::BitFlags::isSet
bool isSet(Enum e) const
Test whether a bit is set.
Definition: util/Sawyer/BitFlags.h:100
Sawyer::BitFlags::set
BitFlags & set(BitFlags other)
Set all bits that are set in other.
Definition: util/Sawyer/BitFlags.h:136
Sawyer::BitFlags::testAndClear
bool testAndClear(Enum e)
Test whether a bit is set, then clear it.
Definition: util/Sawyer/BitFlags.h:160
Sawyer::BitFlags
Stores a vector of enum bit flags.
Definition: util/Sawyer/BitFlags.h:66
Sawyer
Name space for the entire library.
Definition: Access.h:13
Sawyer::BitFlags::operator<
bool operator<(BitFlags other) const
Compare two vectors.
Definition: util/Sawyer/BitFlags.h:222
Sawyer::BitFlags::split
std::vector< Enum > split(std::vector< int64_t > constants, Vector &leftovers) const
Split a vector into the individual enum values.
Definition: util/Sawyer/BitFlags.h:241
Sawyer::BitFlags::operator>=
bool operator>=(BitFlags other) const
Compare two vectors.
Definition: util/Sawyer/BitFlags.h:231
Sawyer::BitFlags::isClear
bool isClear(Enum e) const
Test whether a bit is clear.
Definition: util/Sawyer/BitFlags.h:125
Sawyer::BitFlags::isEmpty
bool isEmpty() const
True if no bits are set.
Definition: util/Sawyer/BitFlags.h:120
Sawyer::BitFlags::operator>
bool operator>(BitFlags other) const
Compare two vectors.
Definition: util/Sawyer/BitFlags.h:228
Sawyer::BitFlags::clear
BitFlags & clear()
Clear all bits.
Definition: util/Sawyer/BitFlags.h:154