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