-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBitStreamOut.h
More file actions
92 lines (78 loc) · 2.72 KB
/
BitStreamOut.h
File metadata and controls
92 lines (78 loc) · 2.72 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
#ifndef STRING_PROCESSING_CPP_BITSTREAMOUT_H
#define STRING_PROCESSING_CPP_BITSTREAMOUT_H
#include <ostream>
#include <cstdint>
#include <ShortBitSet.h>
// Wrapper for easy writing of bits to std::ostream
class BitStreamOut {
public:
explicit BitStreamOut(std::ostream& _os) : os{_os} {}
BitStreamOut() = delete;
BitStreamOut(BitStreamOut&& rhs) = delete;
BitStreamOut(const BitStreamOut& rhs) = delete;
BitStreamOut& operator=(const BitStreamOut& rhs) = delete;
void writeEmpty(const size_t totalLength) {
for (size_t written=0; written < totalLength; ++written) {
++idx;
if (fullByte()) flush();
}
}
// write integer bits (length is calculated starting at least significant bit)
template<typename T>
void writeInteger(const T val, const size_t totalLengthBits = 8 * sizeof(T)) {
static_assert(std::is_integral_v<T>, "T must be integral type");
if (totalLengthBits < 1) throw std::invalid_argument("Integer write needs at least one bit");
constexpr size_t numBitsFull = 8*sizeof(T);
size_t bitsToWrite = totalLengthBits;
if (bitsToWrite > numBitsFull) {
writeEmpty(totalLengthBits - numBitsFull);
bitsToWrite -= numBitsFull;
}
while (bitsToWrite-- > 0) {
// bitsToWrite is also offset
curr |= ( (val & (static_cast<T>(1) << bitsToWrite)) >> bitsToWrite ) << (7 - idx);
++idx;
if (fullByte()) flush();
}
}
void write(const bool val, const size_t totalLengthBits = 1) {
if (totalLengthBits < 1) throw std::invalid_argument("Bool write needs at least one bit");
writeEmpty(totalLengthBits - 1);
if (val) {
curr |= 1 << (7 - idx);
}
++idx;
if (fullByte()) flush();
}
// write all bits of ShortBitSet
void write(const ShortBitSet& bs) {
for (size_t i=0; i < bs.size(); ++i) {
if (bs.at(i)) {
curr |= 1 << (7 - idx);
}
++idx;
if (fullByte()) flush();
}
}
// force to write out current buffer (except if empty)
void flush() {
if (idx == 0) return;
os.write(reinterpret_cast<char*>(&curr), 1);
curr = 0;
idx = 0;
}
~BitStreamOut() {
// write last char if at least one bit was set
flush();
}
private:
std::ostream& os; // output stream
uint8_t curr = 0; // buffer of length 8 bits
size_t idx = 0; // next index in buffer that can be written
// whether the current 8 bit buffer is full
[[nodiscard]]
bool fullByte() const {
return idx == 8;
}
};
#endif //STRING_PROCESSING_CPP_BITSTREAMOUT_H