#pragma once #include "bitinput_impl.h" #include #include #include #include namespace NBitIO { // Based on junk/solar/codecs/bitstream.h class TBitInput: protected TBitInputImpl { public: template explicit TBitInput(const TVec& vec) : TBitInputImpl(std::begin(vec), std::end(vec)) { } TBitInput(const char* start, const char* end) : TBitInputImpl(start, end) { } bool Eof() const { return EofImpl(); } ui64 GetOffset() const { ui64 bo = BitOffset(); return bo / 8 + !!(bo % 8); } using TBitInputImpl::GetBitLength; ui64 GetBitOffset() const { return BitOffset() % 8; } public: // Read with static number of bits. // Preserves what's in result. template Y_FORCE_INLINE bool ReadK(T& result, ui64 skipbits) { ui64 r64 = 0; bool ret = bits <= 56 ? ReadKImpl(r64) : ReadSafe(r64, bits); CopyToResultK(result, r64, skipbits); return ret; } // Read with static number of bits. // Zeroes other bits in result. template Y_FORCE_INLINE bool ReadK(T& result) { ui64 r = 0; bool res = ReadK(r); result = r; return res; } // Shortcut to impl. template Y_FORCE_INLINE bool ReadK(ui64& result) { if (bits <= 56) return ReadKImpl(result); ui64 r1 = 0ULL; ui64 r2 = 0ULL; bool ret1 = ReadKImpl<56ULL>(r1); bool ret2 = ReadKImpl<(bits > 56ULL ? bits - 56ULL : 0) /*or else we get negative param in template*/>(r2); result = (r2 << 56ULL) | r1; return ret1 & ret2; } // It's safe to read up to 64 bits. // Zeroes other bits in result. template Y_FORCE_INLINE bool ReadSafe(T& result, ui64 bits) { if (bits <= 56ULL) return Read(result, bits); ui64 r1 = 0ULL; ui64 r2 = 0ULL; bool ret1 = ReadKImpl<56ULL>(r1); bool ret2 = ReadImpl(r2, bits - 56ULL); result = (r2 << 56ULL) | r1; return ret1 & ret2; } // It's safe to read up to 64 bits. // Preserves what's in result. template Y_FORCE_INLINE bool ReadSafe(T& result, ui64 bits, ui64 skipbits) { ui64 r64 = 0; bool ret = ReadSafe(r64, bits); CopyToResult(result, r64, bits, skipbits); return ret; } // Do not try to read more than 56 bits at once. Split in two reads or use ReadSafe. // Zeroes other bits in result. template Y_FORCE_INLINE bool Read(T& result, ui64 bits) { ui64 r64 = 0; bool ret = ReadImpl(r64, bits); result = r64; return ret; } // Shortcut to impl. Y_FORCE_INLINE bool Read(ui64& result, ui64 bits) { return ReadImpl(result, bits); } // Do not try to read more than 56 bits at once. Split in two reads or use ReadSafe. // Preserves what's in result. template Y_FORCE_INLINE bool Read(T& result, ui64 bits, ui64 skipbits) { ui64 r64 = 0; bool ret = ReadImpl(r64, bits); CopyToResult(result, r64, bits, skipbits); return ret; } // Unsigned wordwise read. Underlying data is splitted in "words" of "bits(data) + 1(flag)" bits. // Like this: (unsigned char)0x2E<3> (0010 1110) <=> 1110 0101 // fddd fddd template Y_FORCE_INLINE bool ReadWords(T& result) { ui64 r64 = 0; bool retCode = ReadWordsImpl(r64); result = r64; return retCode; } // Shortcut to impl. template Y_FORCE_INLINE bool ReadWords(ui64& result) { return ReadWordsImpl(result); } Y_FORCE_INLINE bool Back(int bits) { return Seek(BitOffset() - bits); } Y_FORCE_INLINE bool Seek(int bitoffset) { return TBitInputImpl::Seek(bitoffset); } // A way to read a portion of bits at random location. // Didn't want to complicate sequential read, neither to copypaste. template Y_FORCE_INLINE bool ReadRandom(ui64 bitoffset, T& result, ui64 bits, ui64 skipbits) { const ui64 curr = BitOffset(); Seek(bitoffset); bool ret = ReadSafe(result, bits, skipbits); Seek(curr); return ret; } }; }