ALib C++ Library
Library Version: 2402 R1
Documentation generated by doxygen
Loading...
Searching...
No Matches
bitbuffer.cpp
1// #################################################################################################
2// ALib C++ Library
3//
4// Copyright 2013-2024 A-Worx GmbH, Germany
5// Published under 'Boost Software License' (a free software license, see LICENSE.txt)
6// #################################################################################################
8
9#if !defined(HPP_AWORX_ALIB_BITBUFFER)
11#endif
12
13namespace alib {
14
15/** ************************************************************************************************
16 * This \alibmod implements a buffer that is write- and readable bit by bit.
17 * Conversion for standard numerical types is provided. Furthermore several array compression
18 * algorithms are given, which allow the bit buffers to be compressed before transported or
19 * stored.
20 *
21 * Please consult the little quick
22 * \ref alib_mod_bitbuffer "ALib Module BitBuffer - Programmer's Manual" for further information.
23 **************************************************************************************************/
24namespace bitbuffer {
25
27{
28 // write termination bit
29 {
30 BitWriter bw(*this, idx);
31 bw.Write<1>(1);
32 idx= bw.GetIndex();
33 }// <bw.Flush
34
35 // fast forward to next word
36 if(idx.bit)
37 {
38 idx.pos++;
39 idx.bit= 0;
40 }
41 return idx;
42}
43
45{
47 ALIB_ASSERT_ERROR(terminationIndex.pos > 0 && terminationIndex.bit == 0 && data[terminationIndex.pos - 1] != 0, "BITBUFFER",
48 "Given index is no termination index" )
50
51 // go back to previous word...
52 terminationIndex.pos--;
53 TStorage word= GetWord(terminationIndex);
54
55 //...search and delete MSB
56 terminationIndex.bit= lang::MSB(word );
57 terminationIndex.bit--;
58 word^= BitBuffer::TStorage(1) << terminationIndex.bit;
59
60 // store word and return new reduced index
61 SetWord(terminationIndex, word );
62 return terminationIndex;
63}
64
65#if !defined(ALIB_DOX)
66// anonymous check if this platform has little endian encoding
67// already (done once). If so, this method does nothing.
68namespace
69{
70 static int isLittleEndianEncoding= 0;
71 static BitBufferBase::TStorage testWord;
72 bool IsLittleEndianEncoding()
73 {
74 if( isLittleEndianEncoding == 0 )
75 {
76 static_assert( bitsof(BitBufferBase::TStorage) == 16
79 "Platform not supported");
80
81 isLittleEndianEncoding= 2;
82 if constexpr ( bitsof(BitBufferBase::TStorage) == 16 )
83 {
84 testWord= 0x2211;
86 uint8_t* bytes= reinterpret_cast<uint8_t*>( &testWord );
88 if( *bytes == 0x11 && *(bytes+1) == 0x22)
89 isLittleEndianEncoding= 1;
90 }
91
92 else if constexpr ( bitsof(BitBufferBase::TStorage) == 32 )
93 {
94 testWord= 0x44332211;
96 uint8_t* bytes= reinterpret_cast<uint8_t*>( &testWord );
98 if( * bytes == 0x11 && *(bytes+1) == 0x22
99 && *(bytes+2) == 0x33 && *(bytes+3) == 0x44 )
100 isLittleEndianEncoding= 1;
101 }
102
103 else if constexpr ( bitsof(BitBufferBase::TStorage) == 64 )
104 {
106 testWord= 0x8877665544332211u;
108 uint8_t* bytes= reinterpret_cast<uint8_t*>( &testWord );
110 if( * bytes == 0x11 && *(bytes+1) == 0x22
111 && *(bytes+2) == 0x33 && *(bytes+3) == 0x44
112 && *(bytes+4) == 0x55 && *(bytes+5) == 0x66
113 && *(bytes+6) == 0x77 && *(bytes+7) == 0x88 )
114 isLittleEndianEncoding= 1;
116
117 }
118 }
119
120 return (isLittleEndianEncoding == 1);
121 }
122}
123#endif
124
125void BitBufferBase::ToLittleEndianEncoding( const Index& startIndex, const Index& endIndex )
126{
127 ALIB_ASSERT_ERROR( startIndex.IsAligned(), "BITBUFFER",
128 "Given start index is not algined. The easiest way to get an aligned "
129 "index is to terminate the buffer." )
130
131 if( IsLittleEndianEncoding())
132 return;
133
134 const size_t end= endIndex.pos + (endIndex.bit != 0 );
135 for (size_t pos= startIndex.pos; pos < end; ++pos)
136 {
138 TStorage word = data[pos];
139 uint8_t* bytes= reinterpret_cast<uint8_t*>( &data[pos] );
141 bytes[0]= word & 0xFF;
142 word>>= 8; bytes[1]= word & 0xFF;
143
144 if constexpr ( bitsof(TStorage) > 16 )
145 {
146 word>>= 8; bytes[2]= word & 0xFF;
147 word>>= 8; bytes[3]= word & 0xFF;
148 }
149
150 if constexpr ( bitsof(TStorage) > 32 )
151 {
152 word>>= 8; bytes[4]= word & 0xFF;
153 word>>= 8; bytes[5]= word & 0xFF;
154 word>>= 8; bytes[6]= word & 0xFF;
155 word>>= 8; bytes[7]= word & 0xFF;
156 }
157 }
158}
159
160void BitBufferBase::FromLittleEndianEncoding( const Index& startIndex, const Index& endIndex )
161{
162 if( IsLittleEndianEncoding())
163 return;
164
165 size_t end= endIndex.pos + (endIndex.bit != 0 );
166 for (size_t pos= startIndex.pos; pos < end; ++pos)
167 {
168 TStorage word = 0;
170 uint8_t* bytes= reinterpret_cast<uint8_t*>( &data[pos] );
171 word|= TStorage(bytes[0]);
172 word|= TStorage(bytes[1]) << 8;
173
174 if constexpr ( bitsof(TStorage) > 16 )
175 {
176 word|= TStorage(bytes[2]) << 16;
177 word|= TStorage(bytes[3]) << 24;
178 }
179
180 if constexpr ( bitsof(TStorage) > 32 )
181 {
183 word|= TStorage(bytes[4]) << 32;
184 word|= TStorage(bytes[5]) << 40;
185 word|= TStorage(bytes[6]) << 48;
186 word|= TStorage(bytes[7]) << 56;
188 }
189
190 data[pos]= word;
192 }
193}
194
195
196
197// write 8-bit values
199{
200 if( val < (1<<3) )
201 {
202 Write<4>( val << 1); // | 0
203 return;
204 }
205
206 Write<9>( (val << 1) |1 ) ;
207}
208
209// write 16-bit values
211{
212 if( val < (1<<8) )
213 {
214 Write<9>( val << 1);
215 return;
216 }
217
218 Write<17>( ( val << 1 ) | 1 ) ;
219}
220
221// write 32-bit byte values
223{
224 if( val < (1<< 8) ) { Write<10>( val << 2 ); }
225 else if( val < (1<<16) ) { Write<18>(( val << 2) | 1u ); }
226 else if( val < (1<<24) ) { Write<26>(( val << 2) | 2u ); }
227 else { Write< 2>( 3 );
228 Write<32>( val ); }
229}
230
231// write 64-bit byte values
233{
234 if( val < uint64_t(1) << 8 ) { Write<11>( int16_t (val) << 3 ); }
235 else if( val < uint64_t(1) << 16 ) { Write<19>( ( uint32_t (val) << 3 ) | 1u); }
236 else if( val < uint64_t(1) << 24 ) { Write<27>( ( uint32_t (val) << 3 ) | 2u); }
237 else if( val < uint64_t(1) << 32 ) { Write<35>( ( val << 3 ) | 3u); }
238 else if( val < uint64_t(1) << 40 ) { Write<43>( ( val << 3 ) | 4u); }
239 else if( val < uint64_t(1) << 48 ) { Write<51>( ( val << 3 ) | 5u); }
240 else if( val < uint64_t(1) << 56 ) { Write<59>( ( val << 3 ) | 6u); }
241 else { Write< 3>( 7 );
242 Write<64>( val ); }
243}
244
245
246// read 8-bit values
248{
249 auto result= Read<4>();
250 if( !(result & 1))
251 return uint8_t(result >> 1);
252
253 return uint8_t( result >> 1
254 | Read<5>() << 3 );
255}
256
258{
259 auto result= Read< 9>();
260 if( !(result & 1))
261 return uint16_t(result >> 1);
262
263 return uint16_t( result >> 1
264 | Read<8>() << 8 );
265}
266
268{
269 uint32_t result= Read< 10, uint32_t>();
270 switch (result & 3)
271 {
272 case 0: return uint32_t(result >> 2);
273 case 1: return uint32_t(result >> 2 | (Read< 8, uint32_t>() << 8 ) );
274 case 2: return uint32_t(result >> 2 | (Read< 16, uint32_t>() << 8 ) );
275 default: return uint32_t(result >> 2 | (Read< 24, uint32_t>() << 8 ) );
276 }
277}
278
280{
281 uint64_t result= Read< 11, uint64_t>();
282 switch (result & 7)
283 {
284 case 0: return uint64_t(result >> 3);
285 case 1: return uint64_t(result >> 3 | (Read< 8, uint64_t>() << 8 ));
286 case 2: return uint64_t(result >> 3 | (Read< 16, uint64_t>() << 8 ));
287 case 3: return uint64_t(result >> 3 | (Read< 24, uint64_t>() << 8 ));
288 case 4: return uint64_t(result >> 3 | (Read< 32, uint64_t>() << 8 ));
289 case 5: return uint64_t(result >> 3 | (Read< 40, uint64_t>() << 8 ));
290 case 6: return uint64_t(result >> 3 | (Read< 48, uint64_t>() << 8 ));
291 default: return uint64_t(result >> 3 | (Read< 56, uint64_t>() << 8 ));
292 }
293}
294
295
296
297}} // namespace [alib::bitbuffer]
lang::ShiftOpRHS bit
Current bit index in the current word.
Definition bitbuffer.hpp:90
uinteger pos
Index of the current word to read/write.
Definition bitbuffer.hpp:89
TStorage GetWord(const Index &index) const
ALIB_API Index Terminate(Index writerIndex)
Definition bitbuffer.cpp:26
void SetWord(const Index &index, TStorage value)
ALIB_API Index Unterminate(Index terminationIndex)
Definition bitbuffer.cpp:44
ALIB_API void ToLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
ALIB_API void FromLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
BitBufferBase::Index GetIndex() const
ALIB_API uint16_t readUIntegral16()
ALIB_API uint32_t readUIntegral32()
ALIB_API uint64_t readUIntegral64()
ALIB_API uint8_t readUIntegral8()
ALIB_API void writeUIntegral(uint8_t val)
void Write(TIntegral value)
#define bitsof(type)
Definition bits.hpp:52
#define ALIB_WARNINGS_IGNORE_INTEGRAL_CONSTANT_OVERFLOW
Definition alib.hpp:699
#define ALIB_WARNINGS_RESTORE
Definition alib.hpp:715
#define ALIB_ASSERT_ERROR(cond,...)
Definition alib.hpp:984
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
Definition alib.hpp:644
#define ALIB_WARNINGS_IGNORE_INTEGER_OVERFLOW
Definition alib.hpp:710
constexpr int MSB(TIntegral value)
Definition alib.cpp:57