DCCL v5
Loading...
Searching...
No Matches
bitset.h
1// Copyright 2012-2023:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7// Nathan Knotts <nknotts@gmail.com>
8// philboske <philboske@gmail.com>
9//
10//
11// This file is part of the Dynamic Compact Control Language Library
12// ("DCCL").
13//
14// DCCL is free software: you can redistribute it and/or modify
15// it under the terms of the GNU Lesser General Public License as published by
16// the Free Software Foundation, either version 2.1 of the License, or
17// (at your option) any later version.
18//
19// DCCL is distributed in the hope that it will be useful,
20// but WITHOUT ANY WARRANTY; without even the implied warranty of
21// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22// GNU Lesser General Public License for more details.
23//
24// You should have received a copy of the GNU Lesser General Public License
25// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
26#ifndef DCCLBITSET20120424H
27#define DCCLBITSET20120424H
28
29#include <algorithm>
30#include <cstring>
31#include <deque>
32#include <limits>
33#include <string>
34
35#include "exception.h"
36
37namespace dccl
38{
42class Bitset : public std::deque<bool>
43{
44 public:
48 explicit Bitset(Bitset* parent = nullptr) : parent_(parent) {}
49
55 explicit Bitset(size_type num_bits, unsigned long value = 0, Bitset* parent = nullptr)
56 : std::deque<bool>(num_bits, false), parent_(parent)
57 {
58 from(value, num_bits);
59 }
60
61 ~Bitset() = default;
62
64 const Bitset* parent() const { return parent_; }
65
72 void get_more_bits(size_type num_bits);
73
81 {
82 if (rhs.size() != size())
83 throw(dccl::Exception("Bitset operator&= requires this->size() == rhs.size()"));
84
85 for (size_type i = 0; i != this->size(); ++i) (*this)[i] &= rhs[i];
86 return *this;
87 }
88
96 {
97 if (rhs.size() != size())
98 throw(dccl::Exception("Bitset operator|= requires this->size() == rhs.size()"));
99
100 for (size_type i = 0; i != this->size(); ++i) (*this)[i] |= rhs[i];
101 return *this;
102 }
103
111 {
112 if (rhs.size() != size())
113 throw(dccl::Exception("Bitset operator^= requires this->size() == rhs.size()"));
114
115 for (size_type i = 0; i != this->size(); ++i) (*this)[i] ^= rhs[i];
116 return *this;
117 }
118
119 // Bitset& operator-=(const Bitset& rhs);
120
127 Bitset& operator<<=(size_type n)
128 {
129 for (size_type i = 0; i < n; ++i)
130 {
131 push_front(false);
132 pop_back();
133 }
134 return *this;
135 }
136
143 Bitset& operator>>=(size_type n)
144 {
145 for (size_type i = 0; i < n; ++i)
146 {
147 push_back(false);
148 pop_front();
149 }
150 return *this;
151 }
152
156 Bitset operator<<(size_type n) const
157 {
158 Bitset copy(*this);
159 copy <<= n;
160 return copy;
161 }
162
166 Bitset operator>>(size_type n) const
167 {
168 Bitset copy(*this);
169 copy >>= n;
170 return copy;
171 }
172
178 Bitset& set(size_type n, bool val = true)
179 {
180 (*this)[n] = val;
181 return *this;
182 }
183
188 {
189 for (bool& it : *this) it = true;
190 return *this;
191 }
192
197 Bitset& reset(size_type n) { return set(n, false); }
198
203 {
204 for (bool& it : *this) it = false;
205 return *this;
206 }
207
212 Bitset& flip(size_type n) { return set(n, !(*this)[n]); }
213
218 {
219 for (size_type i = 0, n = size(); i < n; ++i) flip(i);
220 return *this;
221 }
222
227 bool test(size_type n) const { return (*this)[n]; }
228
229 /* bool any() const; */
230 /* bool none() const; */
231 /* Bitset operator~() const; */
232 /* size_type count() const; */
233
238 template <typename IntType>
239 void from(IntType value, size_type num_bits = std::numeric_limits<IntType>::digits)
240 {
241 this->resize(num_bits);
242 for (int i = 0, n = std::min<size_type>(std::numeric_limits<IntType>::digits, size());
243 i < n; ++i)
244 {
245 if (value & (static_cast<IntType>(1) << i))
246 (*this)[i] = true;
247 }
248 }
249
251 void from_ulong(unsigned long value,
252 size_type num_bits = std::numeric_limits<unsigned long>::digits)
253 {
254 from<unsigned long>(value, num_bits);
255 }
256
261 template <typename IntType> IntType to() const
262 {
263 if (size() > static_cast<size_type>(std::numeric_limits<IntType>::digits))
264 throw(Exception("Type IntType cannot represent current bitset (this->size() > "
265 "std::numeric_limits<IntType>::digits)"));
266
267 IntType out = 0;
268 for (int i = 0, n = size(); i < n; ++i)
269 {
270 if ((*this)[i])
271 out |= (static_cast<IntType>(1) << i);
272 }
273
274 return out;
275 }
276
278 unsigned long to_ulong() const { return to<unsigned long>(); }
279
281 std::string to_string() const
282 {
283 std::string s(size(), 0);
284 int i = 0;
285 for (auto it = rbegin(), n = rend(); it != n; ++it)
286 {
287 s[i] = (*it) ? '1' : '0';
288 ++i;
289 }
290 return s;
291 }
292
293 // little-endian
294 // LSB = string[0]
295 // MSB = string[N]
296
300 std::string to_byte_string()
301 {
302 // number of bytes needed is ceil(size() / 8)
303 std::string s(this->size() / 8 + (this->size() % 8 ? 1 : 0), 0);
304
305 for (size_type i = 0, n = this->size(); i < n; ++i)
306 s[i / 8] |= static_cast<char>((*this)[i] << (i % 8));
307
308 return s;
309 }
310
316 size_t to_byte_string(char* buf, size_t max_len)
317 {
318 // number of bytes needed is ceil(size() / 8)
319 size_t len = this->size() / 8 + (this->size() % 8 ? 1 : 0);
320
321 if (max_len < len)
322 {
323 throw std::length_error("max_len must be >= len");
324 }
325
326 // initialize buffer to all zeroes
327 std::fill_n(buf, len, 0);
328
329 for (size_type i = 0, n = this->size(); i < n; ++i)
330 buf[i / 8] |= static_cast<char>((*this)[i] << (i % 8));
331
332 return len;
333 }
334
338 void from_byte_string(const std::string& s) { from_byte_stream(s.begin(), s.end()); }
339
344 template <typename CharIterator> void from_byte_stream(CharIterator begin, CharIterator end)
345 {
346 this->resize(std::distance(begin, end) * 8);
347 int i = 0;
348 for (CharIterator it = begin; it != end; ++it)
349 {
350 for (size_type j = 0; j < 8; ++j) (*this)[i * 8 + j] = (*it) & (1 << j);
351 ++i;
352 }
353 }
354
356 Bitset& prepend(const Bitset& bits)
357 {
358 for (auto it = bits.rbegin(), n = bits.rend(); it != n; ++it) push_front(*it);
359
360 return *this;
361 }
362
364 Bitset& append(const Bitset& bits)
365 {
366 for (bool bit : bits) push_back(bit);
367
368 return *this;
369 }
370
371 private:
372 Bitset relinquish_bits(size_type num_bits, bool final_child);
373
374 private:
375 Bitset* parent_;
376};
377
378inline bool operator==(const Bitset& a, const Bitset& b)
379{
380 return (a.size() == b.size()) && std::equal(a.begin(), a.end(), b.begin());
381}
382
383inline bool operator<(const Bitset& a, const Bitset& b)
384{
385 for (int i = (std::max(a.size(), b.size()) - 1); i >= 0; --i)
386 {
387 bool a_bit = (i < static_cast<int>(a.size())) ? a[i] : 0;
388 bool b_bit = (i < static_cast<int>(b.size())) ? b[i] : 0;
389
390 if (a_bit > b_bit)
391 return false;
392 else if (a_bit < b_bit)
393 return true;
394 }
395 return false;
396}
397
398inline Bitset operator&(const Bitset& b1, const Bitset& b2)
399{
400 Bitset out(b1);
401 out &= b2;
402 return out;
403}
404
405inline Bitset operator|(const Bitset& b1, const Bitset& b2)
406{
407 Bitset out(b1);
408 out |= b2;
409 return out;
410}
411
412inline Bitset operator^(const Bitset& b1, const Bitset& b2)
413{
414 Bitset out(b1);
415 out ^= b2;
416 return out;
417}
418
419inline std::ostream& operator<<(std::ostream& os, const Bitset& b) { return (os << b.to_string()); }
420
421} // namespace dccl
422
423inline void dccl::Bitset::get_more_bits(size_type num_bits) { relinquish_bits(num_bits, true); }
424
425#endif
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
size_t to_byte_string(char *buf, size_t max_len)
Generate a byte string representation of the Bitset, where each character represents 8 bits of the Bi...
Definition bitset.h:316
Bitset & reset()
Set all bits false.
Definition bitset.h:202
std::string to_string() const
Returns the value of the Bitset as a printable string, where each bit is represented by '1' or '0'....
Definition bitset.h:281
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition bitset.h:423
Bitset operator>>(size_type n) const
Right shift.
Definition bitset.h:166
Bitset & operator>>=(size_type n)
Right shift in place.
Definition bitset.h:143
Bitset operator<<(size_type n) const
Left shift.
Definition bitset.h:156
Bitset & operator^=(const Bitset &rhs)
Logical XOR in place.
Definition bitset.h:110
Bitset & append(const Bitset &bits)
Adds the bitset to the big end.
Definition bitset.h:364
bool test(size_type n) const
Test a bit (return its value)
Definition bitset.h:227
Bitset & flip(size_type n)
Flip (toggle) a bit.
Definition bitset.h:212
Bitset & operator<<=(size_type n)
Left shift in place.
Definition bitset.h:127
IntType to() const
Returns the value of the Bitset as a integer.
Definition bitset.h:261
Bitset & operator|=(const Bitset &rhs)
Logical OR in place.
Definition bitset.h:95
Bitset & flip()
Flip (toggle) all bits.
Definition bitset.h:217
void from_ulong(unsigned long value, size_type num_bits=std::numeric_limits< unsigned long >::digits)
Sets value of the Bitset to the contents of an unsigned long integer. Equivalent to from<unsigned lon...
Definition bitset.h:251
unsigned long to_ulong() const
Returns the value of the Bitset as an unsigned long integer. Equivalent to to<unsigned long>().
Definition bitset.h:278
Bitset(Bitset *parent=nullptr)
Construct an empty Bitset.
Definition bitset.h:48
const Bitset * parent() const
The parent Bitset that get_more_bits() draws from, or nullptr if there is none.
Definition bitset.h:64
Bitset & set()
Set all bits true.
Definition bitset.h:187
void from_byte_string(const std::string &s)
Sets the value of the Bitset to the contents of a byte string, where each character represents 8 bits...
Definition bitset.h:338
Bitset & operator&=(const Bitset &rhs)
Logical AND in place.
Definition bitset.h:80
Bitset(size_type num_bits, unsigned long value=0, Bitset *parent=nullptr)
Construct a Bitset of a certain initial size and value.
Definition bitset.h:55
std::string to_byte_string()
Returns the value of the Bitset to a byte string, where each character represents 8 bits of the Bitse...
Definition bitset.h:300
Bitset & reset(size_type n)
Reset a bit (i.e. set it to false)
Definition bitset.h:197
Bitset & set(size_type n, bool val=true)
Set a bit to a given value.
Definition bitset.h:178
Bitset & prepend(const Bitset &bits)
Adds the bitset to the little end.
Definition bitset.h:356
void from_byte_stream(CharIterator begin, CharIterator end)
Sets the value of the Bitset to the contents of a byte string, where each character represents 8 bits...
Definition bitset.h:344
void from(IntType value, size_type num_bits=std::numeric_limits< IntType >::digits)
Sets value of the Bitset to the contents of an integer.
Definition bitset.h:239
Exception class for DCCL.
Definition exception.h:47
Dynamic Compact Control Language namespace.
Definition any.h:28