8#ifndef HPP_ALIB_BITBUFFER
9#define HPP_ALIB_BITBUFFER
16namespace alib {
namespace bitbuffer {
50 "Unsupported size of C++ int type" );
71 lang::ShiftOpRHS
bit= 0;
92 lang::ShiftOpRHS
Bit()
const {
return bit; }
118 || (startIdx.pos ==
pos && startIdx.bit <
bit),
119 "Given buffer start index is greater than this index." )
156 "32bit too narrow for endcoding BitBuffer::Index." )
213 return !(*
this == rhs);
248 return !(*
this < rhs);
259 return !(*
this <= rhs);
355 return reinterpret_cast<char*
>( &
data[idx.pos] );
411 const Index& endIndex );
473 if( capacityNeeded >
storage.capacity() )
504 :
ma( monoAllocator )
533 if( capacityNeeded >
storage.capacity() )
561template<u
integer TCapacity>
599 if( capacityNeeded > TCapacity )
601 ALIB_ERROR(
"BITBUFFER",
"Local bit buffer cannot expand its capacity" )
740 template<ShiftOpRHS TW
idth,
typename TIntegral,
bool TMaskValue= false>
744 template<lang::ShiftOpRHS TW
idth,
typename TValue,
bool TMaskValue= false>
750 static_assert(
bitsof(TValue) >= TWidth,
"Fixed size given greater than value type.");
753 || TWidth ==
bitsof(TValue)
754 || val == (val & lang::LowerMask<TValue>(TWidth) ), "BITBUFFER",
755 "Upper bits dirty while TMaskValue flag not set." )
757 if constexpr ( (TWidth <
bitsof(TValue)) && TMaskValue )
758 val&= lang::LowerMask<TWidth, TValue >();
774 template<lang::ShiftOpRHS TW
idth,
typename TValue,
bool TMaskValue= false>
780 static_assert(
bitsof(TValue) >= TWidth,
"Fixed size given greater than value type.");
783 || TWidth ==
bitsof(TValue)
784 || val == (val & lang::LowerMask<TValue>(TWidth) ), "BITBUFFER",
785 "Upper bits dirty while TMaskValue not set." )
787 if constexpr ( (TWidth <
bitsof(TValue)) && TMaskValue )
788 val&= lang::LowerMask<TWidth, TValue>();
799 if(bitsWritten >= TWidth )
816 template<lang::ShiftOpRHS TW
idth,
typename TValue,
bool TMaskValue= false>
821 using TUI=
typename std::make_unsigned<TValue>::type;
824 template<
typename TValue>
848 template<
typename TValue,
bool TMaskValue= false>
852 template<
typename TValue,
bool TMaskValue= false>
853 ATMP_T_IF(
void, std::is_integral<TValue>::value
854 && (
sizeof(TValue) <=
sizeof(
TStorage)) )
855 Write(lang::ShiftOpRHS width, TValue val)
861 ALIB_ASSERT_ERROR( TMaskValue || width>=
bitsof(TValue) || val == (val & lang::LowerMask<TValue>(width) ), "BITBUFFER",
862 "Upper bits dirty while TMaskValue not set.")
864 if constexpr (TMaskValue)
865 if( width <
bitsof(TValue) )
866 val&= lang::LowerMask<TValue>(width);
882 template<
typename TValue,
bool TMaskValue= false>
883 ATMP_T_IF(
void, std::is_integral<TValue>::value
884 && (
sizeof(TValue) >
sizeof(
TStorage)) )
885 Write(lang::ShiftOpRHS width, TValue val)
889 "BitBufferBase::
Write: Width too high: ", width )
890 ALIB_ASSERT_ERROR( TMaskValue || width==
bitsof(TValue) || val == (val & lang::LowerMask<TValue>(width) ), "BITBUFFER",
891 "Upper bits dirty while TMaskValue not set.")
893 if constexpr (TMaskValue)
894 if( width <=
bitsof(TValue) )
895 val&= lang::LowerMask<TValue>(width);
922 if(bitsWritten >= width )
961 template<
typename TIntegral>
965 void Write( TIntegral val )
972 void Write( TIntegral val )
975 using TUnsigned= typename std::make_unsigned<TIntegral>::type;
977 : TUnsigned( (TUnsigned(-(val+ 1)) << 1) | 1 ) );
1020 word= bb.GetWord(idx);
1033 word= bb.GetWord(idx) >> idx.bit;
1041 "BitBufferBase overflow detected. Ensure a higher capacity" )
1049 word= bb.GetWord(idx);
1068 word= bb.GetWord(idx) >> idx.bit;
1085 template<ShiftOpRHS TW
idth,
typename TResult>
1089 template<lang::ShiftOpRHS TW
idth,
typename TResult=
int>
1090 ATMP_T_IF(TResult, std::is_integral<TResult>::value
1094 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1099 if constexpr ( TWidth == 1 )
1106 word= bb.GetWord(idx);
1112 static_assert(
bitsof(TResult) >= TWidth,
"Fixed size to read greater than given result type.");
1113 if constexpr ( TWidth ==
bitsof(TStorage) )
1114 result= TResult( word );
1117 result= TResult( word & lang::LowerMask<TWidth, TStorage>() );
1122 if(idx.bit >=
bitsof(TStorage))
1125 word= bb.GetWord(idx);
1126 idx.bit-=
bitsof(TStorage);
1129 lang::ShiftOpRHS bitsRead= TWidth - idx.bit;
1130 if constexpr ( TWidth <
bitsof(TStorage) )
1131 result |= TResult( ( word << bitsRead )
1132 & lang::LowerMask<TWidth, TStorage>() );
1134 result |= TResult( word << bitsRead );
1144 template<lang::ShiftOpRHS TW
idth,
typename TResult=
int>
1145 ATMP_T_IF(TResult, std::is_integral<TResult>::value
1146 && (TWidth >
bitsof(TStorage)) )
1149 static_assert(
bitsof(TResult) >= TWidth,
"Fixed size to read greater than given result type.");
1150 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1152 TResult result = word;
1153 lang::ShiftOpRHS bitsRead=
bitsof(TStorage) - idx.bit;
1157 word= bb.GetWord(idx);
1158 result|= TResult(word) << bitsRead;
1159 bitsRead+=
bitsof(TStorage);
1161 while( bitsRead < TWidth);
1163 idx.bit= (idx.bit + TWidth) %
bitsof(TStorage);
1169 result= lang::LowerBits<TWidth, TResult>( result );
1171 word= bb.GetWord(idx) >> idx.bit;
1192 template<
typename TResult>
1195 template<
typename TResult=
int>
1197 Read( lang::ShiftOpRHS width )
1199 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1201 "BITBUFFER", "Read size given greater than value type.")
1205 result= TResult( word & lang::LowerMask<
TStorage>(width) );
1207 result= TResult( word );
1214 word= bb.GetWord(idx);
1219 lang::ShiftOpRHS bitsRead= width - idx.bit;
1220 result |= TResult( ( word << bitsRead )
1221 & lang::LowerMask<TStorage>(width) );
1229 template<
typename TResult=
int>
1230 ATMP_T_IF(TResult, (
sizeof(TResult) >
sizeof(TStorage)) )
1231 Read( lang::ShiftOpRHS width )
1233 ALIB_ASSERT_ERROR(idx.pos < bb.Capacity(),
"BITBUFFER",
"BitBufferBase overflow" )
1235 "Read size given greater than value type.")
1237 if( width <=
bitsof(TStorage))
1240 if ( width <
bitsof(TStorage) )
1241 result= TResult( word & lang::LowerMask<TStorage>(width) );
1243 result= TResult( word );
1247 if(idx.bit >=
bitsof(TStorage))
1250 word= bb.GetWord(idx);
1251 idx.bit-=
bitsof(TStorage);
1255 lang::ShiftOpRHS bitsRead= width - idx.bit;
1256 result |= TResult( ( word << bitsRead )
1257 & lang::LowerMask<TStorage>(width) );
1266 TResult result = TResult( word );
1267 lang::ShiftOpRHS bitsRead=
bitsof(TStorage) - idx.bit;
1271 word= bb.GetWord(idx);
1272 result|= TResult(word) << bitsRead;
1273 bitsRead+=
bitsof(TStorage);
1275 while( bitsRead < width);
1277 idx.bit= (idx.bit + width) %
bitsof(TStorage);
1283 word= bb.GetWord(idx);
1287 result= lang::LowerBits<TResult>( width, result );
1300 template<
typename TIntegral>
1304 TIntegral Read() {
return readUIntegral8(); }
1307 TIntegral Read() {
return readUIntegral16(); }
1310 TIntegral Read() {
return readUIntegral32(); }
1313 TIntegral Read() {
return readUIntegral64(); }
1318 using TUnsigned=
typename std::make_unsigned<TIntegral>::type;
1319 TUnsigned result= Read<TUnsigned>();
1320 return result & 1 ? -TIntegral( result >> 1 ) - 1
1321 : TIntegral( result >> 1 );
1332 ALIB_API uint16_t readUIntegral16();
1336 ALIB_API uint32_t readUIntegral32();
1340 ALIB_API uint64_t readUIntegral64();
1354template<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)
Index()=default
Default constructor initializing members pos and bit to zero.
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)
void Clear()
Sets this index to zero, hence pointing to the first bit in the buffer.
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
BitBufferBase() noexcept
Default Constructor (the only one).
ALIB_API void FromLittleEndianEncoding(const Index &startIndex, const Index &endIndex)
virtual ~BitBufferBase()
Virtual destructor (does nothing, needed for abstract virtual class).
TStorage storage[(TCapacity+bitsof(TStorage) - 1)/bitsof(TStorage)]
The array that holds the data.
virtual bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index idx) override
virtual uinteger Capacity() const override
BitBufferLocal() noexcept
Constructor.
virtual bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index idx) override
virtual uinteger Capacity() const override
BitBufferMA(MonoAllocator &monoAllocator, uinteger initialCapacity)
MonoAllocator & GetAllocator()
StdVectorMono< TStorage > storage
The vector that holds the data.
virtual bool EnsureCapacity(uinteger bitsRequired, BitBufferBase::Index idx) override
virtual uinteger Capacity() const override
std::vector< TStorage > storage
The vector that holds the data.
BitBuffer(uinteger initialCapacity)
Non-instantiatable base class for types BitWriter and BitReader.
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
Reads bits from a BitBufferBase.
void Reset(const BitBufferBase::Index &index)
void Reset()
Resets this reader to the start of the bit buffer.
TResult Read(ShiftOpRHS width)
BitBufferBase::TStorage word
The current word, which is partly read and shifted to start with current bit.
BitReader(BitBufferBase &buffer)
BitBufferBase::TStorage TStorage
Local type alias (shortcut)
BitReader(BitBufferBase &buffer, const BitBufferBase::Index &index)
Writes bits into a BitBufferBase.
void Write(ShiftOpRHS width, TValue value)
void Reset(const BitBufferBase::Index &index)
ALIB_API void writeUIntegral(uint8_t val)
BitWriter(BitBufferBase &buffer)
void Reset()
Resets the internal index of this writer to the start of the bit buffer.
~BitWriter()
Destructs a bit writer. Invokes Flush().
BitBufferBase::TStorage word
The current word, which is partly written and not stored in buffer, yet.
BitBufferBase::TStorage TStorage
Local type alias (shortcut)
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()
constexpr int Log2OfSize()
lang::uinteger uinteger
Type alias in namespace alib.
std::vector< T, SCAMono< T > > StdVectorMono
Type alias in namespace alib.
int ShiftOpRHS
Type alias in namespace alib.
lang::integer integer
Type alias in namespace alib.