8#ifndef HPP_AWORX_ALIB_BITBUFFER
9#define HPP_AWORX_ALIB_BITBUFFER
11#if !defined(HPP_ALIB_LANG_BITS)
15#if !defined (HPP_ALIB_MONOMEM_MONOALLOCATOR)
19#if !defined(HPP_ALIB_MONOMEM_STDCONTAINERMA)
23#if !defined (_GLIBCXX_VECTOR) && !defined(_VECTOR_)
27#if !defined (_GLIBCXX_MEMORY) && !defined(_MEMORY_)
33namespace alib {
namespace bitbuffer {
67 "Unsupported size of C++ int type" );
83 #if !defined(ALIB_DOX)
151 || (startIdx.pos ==
pos && startIdx.bit <
bit),
152 "Given buffer start index is greater than this index." )
195 "32bit too narrow for endcoding BitBuffer::Index." )
196 return uint32_t(
pos) | (uint32_t(
bit) << (31 - lang::Log2OfSize<TStorage>() ));
209 {
return uint64_t(
pos) | (uint64_t(
bit) << (63L - lang::Log2OfSize<TStorage>() )); }
258 return !(*
this == rhs);
293 return !(*
this < rhs);
304 return !(*
this <= rhs);
400 return reinterpret_cast<char*
>( &
data[idx.pos] );
456 const Index& endIndex );
516 if( capacityNeeded >
storage.capacity() )
534 std::shared_ptr<MonoAllocator>
ma;
537 std::vector<TStorage, alib::StdContMAOptional<TStorage>>
storage;
547 :
ma( monoAllocator )
575 if( capacityNeeded >
storage.capacity() )
603template<u
integer TCapacity>
641 if( capacityNeeded > TCapacity )
643 ALIB_ERROR(
"BITBUFFER",
"Local bit buffer can not expand its capacity" )
783 #if defined(ALIB_DOX)
800 template<ShiftOpRHS TW
idth,
typename TIntegral,
bool TMaskValue= false>
804 template<lang::ShiftOpRHS TW
idth,
typename TValue,
bool TMaskValue= false>
810 static_assert(
bitsof(TValue) >= TWidth,
"Fixed size given greater than value type.");
813 || TWidth ==
bitsof(TValue)
814 || val == (val & lang::LowerMask<TValue>(TWidth) ), "BITBUFFER",
815 "Upper bits dirty while TMaskValue flag not set." )
817 if constexpr ( (TWidth <
bitsof(TValue)) && TMaskValue )
818 val&= lang::LowerMask<TWidth, TValue >();
834 template<lang::ShiftOpRHS TW
idth,
typename TValue,
bool TMaskValue= false>
840 static_assert(
bitsof(TValue) >= TWidth,
"Fixed size given greater than value type.");
843 || TWidth ==
bitsof(TValue)
844 || val == (val & lang::LowerMask<TValue>(TWidth) ), "BITBUFFER",
845 "Upper bits dirty while TMaskValue not set." )
847 if constexpr ( (TWidth <
bitsof(TValue)) && TMaskValue )
848 val&= lang::LowerMask<TWidth, TValue>();
859 if(bitsWritten >= TWidth )
876 template<lang::ShiftOpRHS TW
idth,
typename TValue,
bool TMaskValue= false>
881 using TUI=
typename std::make_unsigned<TValue>::type;
882 Write<TWidth, TUI, TMaskValue>(
static_cast<TUI
>( val ) );
884 template<
typename TValue>
888 Write<1, unsigned int, false>(
static_cast<unsigned int>( val ) );
893 #if defined(ALIB_DOX)
910 template<
typename TValue,
bool TMaskValue= false>
914 template<
typename TValue,
bool TMaskValue= false>
915 ATMP_T_IF(
void, std::is_integral<TValue>::value
916 && (
sizeof(TValue) <=
sizeof(
TStorage)) )
923 ALIB_ASSERT_ERROR( TMaskValue || width>=
bitsof(TValue) || val == (val & lang::LowerMask<TValue>(width) ), "BITBUFFER",
924 "Upper bits dirty while TMaskValue not set.")
926 if constexpr (TMaskValue)
927 if( width <
bitsof(TValue) )
928 val&= lang::LowerMask<TValue>(width);
944 template<
typename TValue,
bool TMaskValue= false>
945 ATMP_T_IF(
void, std::is_integral<TValue>::value
946 && (
sizeof(TValue) >
sizeof(
TStorage)) )
951 "BitBufferBase::
Write: Width too high: ", width )
952 ALIB_ASSERT_ERROR( TMaskValue || width==
bitsof(TValue) || val == (val & lang::LowerMask<TValue>(width) ), "BITBUFFER",
953 "Upper bits dirty while TMaskValue not set.")
955 if constexpr (TMaskValue)
956 if( width <=
bitsof(TValue) )
957 val&= lang::LowerMask<TValue>(width);
984 if(bitsWritten >= width )
999 #if defined(ALIB_DOX)
1025 template<
typename TIntegral>
1029 void Write( TIntegral val )
1036 void Write( TIntegral val )
1039 using TUnsigned= typename std::make_unsigned<TIntegral>::type;
1041 : TUnsigned( (TUnsigned(-(val+ 1)) << 1) | 1 ) );
1094 word= bb.GetWord(idx);
1109 word= bb.GetWord(idx) >> idx.bit;
1117 "BitBufferBase overflow detected. Ensure a higher capacity" )
1125 word= bb.GetWord(idx);
1148 word= bb.GetWord(idx) >> idx.bit;
1152 #if defined(ALIB_DOX)
1167 template<ShiftOpRHS TW
idth,
typename TResult>
1171 template<lang::ShiftOpRHS TW
idth,
typename TResult=
int>
1172 ATMP_T_IF(TResult, std::is_integral<TResult>::value
1176 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1181 if constexpr ( TWidth == 1 )
1188 word= bb.GetWord(idx);
1194 static_assert(
bitsof(TResult) >= TWidth,
"Fixed size to read greater than given result type.");
1195 if constexpr ( TWidth ==
bitsof(TStorage) )
1196 result= TResult( word );
1199 result= TResult( word & lang::LowerMask<TWidth, TStorage>() );
1204 if(idx.bit >=
bitsof(TStorage))
1207 word= bb.GetWord(idx);
1208 idx.bit-=
bitsof(TStorage);
1211 lang::ShiftOpRHS bitsRead= TWidth - idx.bit;
1212 if constexpr ( TWidth <
bitsof(TStorage) )
1213 result |= TResult( ( word << bitsRead )
1214 & lang::LowerMask<TWidth, TStorage>() );
1216 result |= TResult( word << bitsRead );
1226 template<lang::ShiftOpRHS TW
idth,
typename TResult=
int>
1227 ATMP_T_IF(TResult, std::is_integral<TResult>::value
1228 && (TWidth >
bitsof(TStorage)) )
1231 static_assert(
bitsof(TResult) >= TWidth,
"Fixed size to read greater than given result type.");
1232 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1234 TResult result = word;
1235 lang::ShiftOpRHS bitsRead=
bitsof(TStorage) - idx.bit;
1239 word= bb.GetWord(idx);
1240 result|= TResult(word) << bitsRead;
1241 bitsRead+=
bitsof(TStorage);
1243 while( bitsRead < TWidth);
1245 idx.bit= (idx.bit + TWidth) %
bitsof(TStorage);
1251 result= lang::LowerBits<TWidth, TResult>( result );
1253 word= bb.GetWord(idx) >> idx.bit;
1259 #if defined(ALIB_DOX)
1276 template<
typename TResult>
1279 template<
typename TResult=
int>
1283 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1285 "BITBUFFER", "Read size given greater than value type.")
1289 result= TResult( word & lang::LowerMask<
TStorage>(width) );
1291 result= TResult( word );
1298 word= bb.GetWord(idx);
1304 result |= TResult( ( word << bitsRead )
1305 & lang::LowerMask<TStorage>(width) );
1313 template<
typename TResult=
int>
1314 ATMP_T_IF(TResult, (
sizeof(TResult) >
sizeof(TStorage)) )
1315 Read( lang::ShiftOpRHS width )
1317 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1319 "Read size given greater than value type.")
1321 if( width <=
bitsof(TStorage))
1324 if ( width <
bitsof(TStorage) )
1325 result= TResult( word & lang::LowerMask<TStorage>(width) );
1327 result= TResult( word );
1331 if(idx.bit >=
bitsof(TStorage))
1334 word= bb.GetWord(idx);
1335 idx.bit-=
bitsof(TStorage);
1339 lang::ShiftOpRHS bitsRead= width - idx.bit;
1340 result |= TResult( ( word << bitsRead )
1341 & lang::LowerMask<TStorage>(width) );
1350 TResult result = TResult( word );
1351 lang::ShiftOpRHS bitsRead=
bitsof(TStorage) - idx.bit;
1355 word= bb.GetWord(idx);
1356 result|= TResult(word) << bitsRead;
1357 bitsRead+=
bitsof(TStorage);
1359 while( bitsRead < width);
1361 idx.bit= (idx.bit + width) %
bitsof(TStorage);
1367 word= bb.GetWord(idx);
1371 result= lang::LowerBits<TResult>( width, result );
1379 #if defined(ALIB_DOX)
1386 template<
typename TIntegral>
1390 TIntegral Read() {
return readUIntegral8(); }
1393 TIntegral Read() {
return readUIntegral16(); }
1396 TIntegral Read() {
return readUIntegral32(); }
1399 TIntegral Read() {
return readUIntegral64(); }
1404 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
1405 TUnsigned result= Read<TUnsigned>();
1406 return result & 1 ? -TIntegral( result >> 1 ) - 1
1407 : TIntegral( result >> 1 );
1422 ALIB_API uint16_t readUIntegral16();
1428 ALIB_API uint32_t readUIntegral32();
1434 ALIB_API uint64_t readUIntegral64();
1448template<u
integer TCapacity>
lang::ShiftOpRHS bit
Current bit index in the current word.
bool operator==(const Index &rhs) const
static Index Decode32(uint32_t code)
uinteger pos
Index of the current word to read/write.
integer GetByteOffset(Index startIdx=Index(0, 0)) const
bool operator<=(const Index &rhs) const
bool operator>=(const Index &rhs) const
bool operator>(const Index &rhs) const
static Index Decode64(uint64_t code)
lang::ShiftOpRHS Bit() const
bool operator<(const Index &rhs) const
void SetFromByteOffset(uinteger byteOffset)
bool operator!=(const Index &rhs) const
Index(uinteger pPos, lang::ShiftOpRHS pBit)
uinteger CountBits() const
TStorage GetWord(const Index &index) const
ALIB_API Index Terminate(Index writerIndex)
void SetWord(const Index &index, TStorage value)
ALIB_API Index Unterminate(Index terminationIndex)
virtual ALIB_API uinteger Capacity() const =0
char * CharStream(Index idx=Index(0, 0))
virtual ALIB_API bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index index)=0
ALIB_API void ToLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
uinteger RemainingSize(const Index &idx) const
ALIB_API void FromLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
TStorage storage[(TCapacity+bitsof(TStorage) - 1)/bitsof(TStorage)]
virtual bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index idx) override
virtual uinteger Capacity() const override
BitBufferLocal() noexcept
virtual bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index idx) override
virtual uinteger Capacity() const override
std::vector< TStorage, alib::StdContMAOptional< TStorage > > storage
BitBufferMA(std::shared_ptr< MonoAllocator > monoAllocator, uinteger initialCapacity)
std::shared_ptr< MonoAllocator > GetAllocator()
std::shared_ptr< MonoAllocator > ma
virtual bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index idx) override
virtual uinteger Capacity() const override
std::vector< TStorage > storage
BitBuffer(uinteger initialCapacity)
uinteger RemainingSize() const
BitRWBase(BitBufferBase &buffer)
BitBufferBase & bb
The bit buffer to write into. Provided on construction.
BitBufferBase & GetBuffer() const
BitBufferBase::Index idx
The current reading/writing index within bb.
BitBufferBase::Index GetIndex() const
void Reset(const BitBufferBase::Index &index)
TResult Read(ShiftOpRHS width)
BitBufferBase::TStorage word
BitReader(BitBufferBase &buffer)
BitBufferBase::TStorage TStorage
BitReader(BitBufferBase &buffer, const BitBufferBase::Index &index)
void Write(ShiftOpRHS width, TValue value)
void Reset(const BitBufferBase::Index &index)
ALIB_API void writeUIntegral(uint8_t val)
BitWriter(BitBufferBase &buffer)
BitBufferBase::TStorage word
BitBufferBase::TStorage TStorage
void Write(TIntegral value)
void Write(TIntegral value)
BitWriter(BitBufferBase &buffer, const BitBufferBase::Index &index)
#define ALIB_ASSERT_MODULE(modulename)
#define ALIB_WARNINGS_RESTORE
#define ATMP_EQ( T, TEqual)
#define ALIB_ASSERT_ERROR(cond,...)
#define ALIB_WARNINGS_ALLOW_UNSAFE_BUFFER_USAGE
#define ATMP_SELECT_IF_1TP(TParam, ...)
#define ATMP_T_IF(T, Cond)
constexpr TIntegral LowerMask()
lang::uinteger uinteger
Type alias in namespace alib.
int ShiftOpRHS
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.