-
Notifications
You must be signed in to change notification settings - Fork 0
/
BitStream.hpp
180 lines (149 loc) · 5.34 KB
/
BitStream.hpp
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
#ifndef UTIL_BITSTREAM_H
#define UTIL_BITSTREAM_H
#include <stdint.h>
#include <cstdio>
#include <fstream>
#include "utils.hpp"
namespace util {
class BitStream {
protected:
uint8_t *buffer;
size_t size; ///< Size in bytes
size_t position; ///< Position in bits
bool managed;
public:
BitStream(uint8_t *b = nullptr, size_t s = 0, size_t p = 0, bool m = false)
: buffer(b), size(s), position(p), managed(m) {}
~BitStream(void) {
if (this->managed) {
util::deallocArray(this->buffer);
}
}
inline uint8_t* get_buffer(void) {
return this->buffer;
}
inline const uint8_t* get_buffer() const {
return this->buffer;
}
inline size_t get_size(void) const {
return this->size;
}
inline size_t get_size_bits(void) const {
return this->size * 8u;
}
inline void set_managed(bool m) {
this->managed = m;
}
inline void set_position(size_t p) {
this->position = p;
}
inline size_t get_position(void) const {
return this->position;
}
inline size_t get_last_byte_position(void) const {
return util::round_to_byte(this->position);
}
inline void reset(void) {
this->set_position(0);
}
/**
* @brief Resize the internal buffer if needed.
* Default resize is by 50% increase.
* @param new_size
* The new size for the buffer.
* @return Returns the size after resizing.
*/
size_t resize(size_t new_size=0u) {
if (this->managed /*&& this->malloc*/) {
if (new_size == 0) {
// Resize by 50%
new_size = this->size + this->size / 2u;
} else if (new_size <= this->get_size()) {
return this->get_size();
}
util::reallocArray(this->buffer, this->size, new_size);
}
return this->get_size();
}
};
/**
* Class which eases reading bitwise from a buffer.
*/
class BitStreamReader : public BitStream {
public:
/**
* Create a bitstreamreader which reads from the provided buffer.
*
* @param [in] buffer The buffer from which bits will be read.
* @param [in] size The size (expressed in bytes) of the buffer from which bits will be read.
*/
BitStreamReader(uint8_t *buffer, size_t size);
~BitStreamReader();
/**
* Read one bit from the bitstream.
*
* @return The value of the bit.
*/
uint8_t get_bit();
/**
* Get l bits from the bitstream
*
* @param [in] l number of bits to read
* @return The value of the bits read
*
* buffer: 0101 1100, position==0
* get(4) returns value 5, position==4
*/
uint32_t get(size_t l);
/**
* Move the bitwise position pointer to the next byte boundary
*/
void flush();
};
/**
* Class which eases writing bitwise into a buffer.
*/
class BitStreamWriter : public BitStream {
public:
/**
* Create a bitstreamwriter which writes into the provided buffer.
*
* @param [in] buffer The buffer into which bits will be written.
* @param [in] size The size (expressed in bytes) of the buffer into which bits will be written.
*/
BitStreamWriter(uint8_t *buffer, size_t size);
/**
* Create a bitstreamwriter and allocate a buffer for it.
*
* @param [in] size The size (expressed in bytes) of the buffer into which bits will be written.
*/
BitStreamWriter(size_t s);
~BitStreamWriter();
/**
* Write one bit into the bitstream.
* @param [in] value The value to put into the bitstream.
*/
void put_bit(int8_t value);
/**
* Put 'length' bits with value 'value' into the bitstream
*
* @param [in] length Number of bits to use for storing the value
* @param [in] value The value to store
*
* buffer: xxxx xxxx, position==0
* put(4, 5)
* buffer: 1010 xxxx, position==4
*/
void put(size_t length, uint32_t value);
/**
* Byte-align: Move the bitwise position pointer to the next byte boundary
*/
void flush();
};
/**
* Write the contents of the bitstream to the specified file
*/
void write(FILE *f, const BitStreamWriter &b);
void write(std::ofstream &fs, const BitStreamWriter &b);
}
#endif /* UTIL_BITSTREAM_H */