123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- #pragma once
- #include "bitinput_impl.h"
- #include <util/system/yassert.h>
- #include <util/generic/vector.h>
- #include <util/generic/yexception.h>
- #include <iterator>
- namespace NBitIO {
- // Based on junk/solar/codecs/bitstream.h
- class TBitInput: protected TBitInputImpl {
- public:
- template <typename TVec>
- 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 <ui64 bits, typename T>
- Y_FORCE_INLINE bool ReadK(T& result, ui64 skipbits) {
- ui64 r64 = 0;
- bool ret = bits <= 56 ? ReadKImpl<bits>(r64) : ReadSafe(r64, bits);
- CopyToResultK<bits>(result, r64, skipbits);
- return ret;
- }
- // Read with static number of bits.
- // Zeroes other bits in result.
- template <ui64 bits, typename T>
- Y_FORCE_INLINE bool ReadK(T& result) {
- ui64 r = 0;
- bool res = ReadK<bits>(r);
- result = r;
- return res;
- }
- // Shortcut to impl.
- template <ui64 bits>
- Y_FORCE_INLINE bool ReadK(ui64& result) {
- if (bits <= 56)
- return ReadKImpl<bits>(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 <typename T>
- 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 <typename T>
- 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 <typename T>
- 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 <typename T>
- 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 <ui64 bits, typename T>
- Y_FORCE_INLINE bool ReadWords(T& result) {
- ui64 r64 = 0;
- bool retCode = ReadWordsImpl<bits>(r64);
- result = r64;
- return retCode;
- }
- // Shortcut to impl.
- template <ui64 bits>
- Y_FORCE_INLINE bool ReadWords(ui64& result) {
- return ReadWordsImpl<bits>(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 <typename T>
- Y_FORCE_INLINE bool ReadRandom(ui64 bitoffset, T& result, ui64 bits, ui64 skipbits) {
- const ui64 curr = BitOffset();
- Seek(bitoffset);
- bool ret = ReadSafe<T>(result, bits, skipbits);
- Seek(curr);
- return ret;
- }
- };
- }
|