ALib C++ Framework
by
Library Version: 2605 R0
Documentation generated by doxygen
Loading...
Searching...
No Matches
bitbuffer.cpp
1namespace alib {
2
3//==================================================================================================
4/// This \alibmod implements a buffer that is write- and readable bit by bit.
5/// Conversion for standard numerical types is provided. Furthermore several array compression
6/// algorithms are given, which allow the bit buffers to be compressed before transported or
7/// stored.
8///
9/// Please consult the little quick
10/// #"alib_mod_bitbuffer;ALib Module BitBuffer - Programmer's Manual" for further information.
11//==================================================================================================
12namespace bitbuffer {
13
15 // write termination bit
16 {
17 BitWriter bw(*this, idx);
18 bw.WriteBits<1>(1);
19 idx= bw.GetIndex();
20 }// <bw.Flush
21
22 // fast forward to next word
23 if(idx.bit) {
24 idx.pos++;
25 idx.bit= 0;
26 }
27 return idx;
28}
29
31 ALIB_ASSERT_ERROR( terminationIndex.pos > 0
32 && terminationIndex.bit == 0
33 && data[terminationIndex.pos - 1] != 0,
34 "BITBUFFER", "Given index is no termination index" )
35
36 // go back to previous word...
37 terminationIndex.pos--;
38 TStorage word= GetWord(terminationIndex);
39
40 //...search and delete MSB
41 terminationIndex.bit= lang::MSB(word );
42 terminationIndex.bit--;
43 word^= BitBuffer::TStorage(1) << terminationIndex.bit;
44
45 // store word and return new reduced index
46 SetWord(terminationIndex, word );
47 return terminationIndex;
48}
49
50#if !DOXYGEN
51// anonymous check if this platform has little endian encoding
52// already (done once). If so, this method does nothing.
53namespace
54{
55 static int isLittleEndianEncoding= 0;
56 static BitBufferBase::TStorage testWord;
57bool IsLittleEndianEncoding() {
58 if( isLittleEndianEncoding == 0 ) {
59 ALIB_STATIC_ASSERT( Sizeof_int_must_be_16_32_or_64,
63 "Platform not supported")
64
65 isLittleEndianEncoding= 2;
66 if constexpr ( bitsof(BitBufferBase::TStorage) == 16 ) {
67 testWord= 0x2211;
68 uint8_t* bytes= reinterpret_cast<uint8_t*>( &testWord );
69 if( *bytes == 0x11 && *(bytes+1) == 0x22)
70 isLittleEndianEncoding= 1;
71 }
72
73 else if constexpr ( bitsof(BitBufferBase::TStorage) == 32 ) {
74 testWord= 0x44332211;
75 uint8_t* bytes= reinterpret_cast<uint8_t*>( &testWord );
76 if( * bytes == 0x11 && *(bytes+1) == 0x22
77 && *(bytes+2) == 0x33 && *(bytes+3) == 0x44 )
78 isLittleEndianEncoding= 1;
79 }
80
81 else if constexpr ( bitsof(BitBufferBase::TStorage) == 64 ) {
83 testWord= 0x8877665544332211u;
84 uint8_t* bytes= reinterpret_cast<uint8_t*>( &testWord );
85 if( * bytes == 0x11 && *(bytes+1) == 0x22
86 && *(bytes+2) == 0x33 && *(bytes+3) == 0x44
87 && *(bytes+4) == 0x55 && *(bytes+5) == 0x66
88 && *(bytes+6) == 0x77 && *(bytes+7) == 0x88 )
89 isLittleEndianEncoding= 1;
91
92 } }
93
94 return (isLittleEndianEncoding == 1);
95}
96}
97#endif
98
99void BitBufferBase::ToLittleEndianEncoding( const Index& startIndex, const Index& endIndex ) {
100 ALIB_ASSERT_ERROR( startIndex.IsAligned(), "BITBUFFER",
101 "Given start index is not algined. The easiest way to get an aligned "
102 "index is to terminate the buffer." )
103
104 if( IsLittleEndianEncoding())
105 return;
106
107 const size_t end= endIndex.pos + (endIndex.bit != 0 );
108 for (size_t pos= startIndex.pos; pos < end; ++pos) {
109 TStorage word = data[pos];
110 uint8_t* bytes= reinterpret_cast<uint8_t*>( &data[pos] );
111 bytes[0]= word & 0xFF;
112 word>>= 8; bytes[1]= word & 0xFF;
113
114 if constexpr ( bitsof(TStorage) > 16 ) {
115 word>>= 8; bytes[2]= word & 0xFF;
116 word>>= 8; bytes[3]= word & 0xFF;
117 }
118
119 if constexpr ( bitsof(TStorage) > 32 ) {
120 word>>= 8; bytes[4]= word & 0xFF;
121 word>>= 8; bytes[5]= word & 0xFF;
122 word>>= 8; bytes[6]= word & 0xFF;
123 word>>= 8; bytes[7]= word & 0xFF;
124} } }
125
126void BitBufferBase::FromLittleEndianEncoding( const Index& startIndex, const Index& endIndex ) {
127 if( IsLittleEndianEncoding())
128 return;
129
130 size_t end= endIndex.pos + (endIndex.bit != 0 );
131 for (size_t pos= startIndex.pos; pos < end; ++pos) {
132 TStorage word = 0;
133 uint8_t* bytes= reinterpret_cast<uint8_t*>( &data[pos] );
134 word|= TStorage(bytes[0]);
135 word|= TStorage(bytes[1]) << 8;
136
137 if constexpr ( bitsof(TStorage) > 16 ) {
138 word|= TStorage(bytes[2]) << 16;
139 word|= TStorage(bytes[3]) << 24;
140 }
141
142 if constexpr ( bitsof(TStorage) > 32 ) {
144 word|= TStorage(bytes[4]) << 32;
145 word|= TStorage(bytes[5]) << 40;
146 word|= TStorage(bytes[6]) << 48;
147 word|= TStorage(bytes[7]) << 56;
149 }
150
151 data[pos]= word;
152} }
153
154
155
156// write 8-bit values
157void BitWriter::writeUIntegral(uint8_t val) {
158 if( val < (1<<3) ) {
159 WriteBits<4>( val << 1); // | 0
160 return;
161 }
162
163 WriteBits<9>( (val << 1) |1 ) ;
164}
165
166// write 16-bit values
167void BitWriter::writeUIntegral(uint16_t val) {
168 if( val < (1<<8) ) {
169 WriteBits<9>( val << 1);
170 return;
171 }
172
173 WriteBits<17>( ( val << 1 ) | 1 ) ;
174}
175
176// write 32-bit byte values
177void BitWriter::writeUIntegral(uint32_t val) {
178 if( val < (1<< 8) ) { WriteBits<10>( val << 2 ); }
179 else if( val < (1<<16) ) { WriteBits<18>(( val << 2) | 1u ); }
180 else if( val < (1<<24) ) { WriteBits<26>(( val << 2) | 2u ); }
181 else { WriteBits< 2>( 3 );
182 WriteBits<32>( val ); }
183}
184
185// write 64-bit byte values
186void BitWriter::writeUIntegral(uint64_t val) {
187 if( val < uint64_t(1) << 8 ) { WriteBits<11>( int16_t (val) << 3 ); }
188 else if( val < uint64_t(1) << 16 ) { WriteBits<19>( ( uint32_t (val) << 3 ) | 1u); }
189 else if( val < uint64_t(1) << 24 ) { WriteBits<27>( ( uint32_t (val) << 3 ) | 2u); }
190 else if( val < uint64_t(1) << 32 ) { WriteBits<35>( ( val << 3 ) | 3u); }
191 else if( val < uint64_t(1) << 40 ) { WriteBits<43>( ( val << 3 ) | 4u); }
192 else if( val < uint64_t(1) << 48 ) { WriteBits<51>( ( val << 3 ) | 5u); }
193 else if( val < uint64_t(1) << 56 ) { WriteBits<59>( ( val << 3 ) | 6u); }
194 else { WriteBits< 3>( 7 );
195 WriteBits<64>( val ); }
196}
197
198
199// read 8-bit values
201 auto result= ReadBits<4>();
202 if( !(result & 1))
203 return uint8_t(result >> 1);
204
205 return uint8_t( result >> 1
206 | ReadBits<5>() << 3 );
207}
208
210 auto result= ReadBits< 9>();
211 if( !(result & 1))
212 return uint16_t(result >> 1);
213
214 return uint16_t( result >> 1
215 | ReadBits<8>() << 8 );
216}
217
219 uint32_t result= ReadBits< 10, uint32_t>();
220 switch (result & 3) {
221 case 0: return uint32_t(result >> 2);
222 case 1: return uint32_t(result >> 2 | (ReadBits< 8, uint32_t>() << 8 ) );
223 case 2: return uint32_t(result >> 2 | (ReadBits< 16, uint32_t>() << 8 ) );
224 default: return uint32_t(result >> 2 | (ReadBits< 24, uint32_t>() << 8 ) );
225} }
226
228 uint64_t result= ReadBits< 11, uint64_t>();
229 switch (result & 7) {
230 case 0: return uint64_t(result >> 3);
231 case 1: return uint64_t(result >> 3 | (ReadBits< 8, uint64_t>() << 8 ));
232 case 2: return uint64_t(result >> 3 | (ReadBits< 16, uint64_t>() << 8 ));
233 case 3: return uint64_t(result >> 3 | (ReadBits< 24, uint64_t>() << 8 ));
234 case 4: return uint64_t(result >> 3 | (ReadBits< 32, uint64_t>() << 8 ));
235 case 5: return uint64_t(result >> 3 | (ReadBits< 40, uint64_t>() << 8 ));
236 case 6: return uint64_t(result >> 3 | (ReadBits< 48, uint64_t>() << 8 ));
237 default: return uint64_t(result >> 3 | (ReadBits< 56, uint64_t>() << 8 ));
238} }
239
240}} // namespace [alib::bitbuffer]
#define ALIB_ALLOW_INTEGRAL_CONSTANT_OVERFLOW
#define bitsof(type)
#define ALIB_ALLOW_INTEGER_OVERFLOW
#define ALIB_STATIC_ASSERT(CondVariable, Cond, Message)
#define ALIB_POP_ALLOWANCE
#define ALIB_ASSERT_ERROR(cond, domain,...)
lang::ShiftOpRHS bit
Current bit index in the current word.
Definition bitbuffer.hpp:61
uinteger pos
Index of the current word to read/write.
Definition bitbuffer.hpp:60
Index Unterminate(Index terminationIndex)
Definition bitbuffer.cpp:30
void SetWord(const Index &index, TStorage value)
Index Terminate(Index writerIndex)
Definition bitbuffer.cpp:14
void ToLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
Definition bitbuffer.cpp:99
void FromLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
TStorage GetWord(const Index &index) const
BitBufferBase::Index GetIndex() const
Writes bits into a #"BitBufferBase".
void writeUIntegral(uint8_t value)
void WriteBits(TIntegral value)
constexpr int MSB(TIntegral value)
Definition bits.hpp:309
Definition alox.cpp:14