bitinput.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. #pragma once
  2. #include "bitinput_impl.h"
  3. #include <util/system/yassert.h>
  4. #include <util/generic/vector.h>
  5. #include <util/generic/yexception.h>
  6. #include <iterator>
  7. namespace NBitIO {
  8. // Based on junk/solar/codecs/bitstream.h
  9. class TBitInput: protected TBitInputImpl {
  10. public:
  11. template <typename TVec>
  12. explicit TBitInput(const TVec& vec)
  13. : TBitInputImpl(std::begin(vec), std::end(vec))
  14. {
  15. }
  16. TBitInput(const char* start, const char* end)
  17. : TBitInputImpl(start, end)
  18. {
  19. }
  20. bool Eof() const {
  21. return EofImpl();
  22. }
  23. ui64 GetOffset() const {
  24. ui64 bo = BitOffset();
  25. return bo / 8 + !!(bo % 8);
  26. }
  27. using TBitInputImpl::GetBitLength;
  28. ui64 GetBitOffset() const {
  29. return BitOffset() % 8;
  30. }
  31. public:
  32. // Read with static number of bits.
  33. // Preserves what's in result.
  34. template <ui64 bits, typename T>
  35. Y_FORCE_INLINE bool ReadK(T& result, ui64 skipbits) {
  36. ui64 r64 = 0;
  37. bool ret = bits <= 56 ? ReadKImpl<bits>(r64) : ReadSafe(r64, bits);
  38. CopyToResultK<bits>(result, r64, skipbits);
  39. return ret;
  40. }
  41. // Read with static number of bits.
  42. // Zeroes other bits in result.
  43. template <ui64 bits, typename T>
  44. Y_FORCE_INLINE bool ReadK(T& result) {
  45. ui64 r = 0;
  46. bool res = ReadK<bits>(r);
  47. result = r;
  48. return res;
  49. }
  50. // Shortcut to impl.
  51. template <ui64 bits>
  52. Y_FORCE_INLINE bool ReadK(ui64& result) {
  53. if (bits <= 56)
  54. return ReadKImpl<bits>(result);
  55. ui64 r1 = 0ULL;
  56. ui64 r2 = 0ULL;
  57. bool ret1 = ReadKImpl<56ULL>(r1);
  58. bool ret2 = ReadKImpl<(bits > 56ULL ? bits - 56ULL : 0) /*or else we get negative param in template*/>(r2);
  59. result = (r2 << 56ULL) | r1;
  60. return ret1 & ret2;
  61. }
  62. // It's safe to read up to 64 bits.
  63. // Zeroes other bits in result.
  64. template <typename T>
  65. Y_FORCE_INLINE bool ReadSafe(T& result, ui64 bits) {
  66. if (bits <= 56ULL)
  67. return Read(result, bits);
  68. ui64 r1 = 0ULL;
  69. ui64 r2 = 0ULL;
  70. bool ret1 = ReadKImpl<56ULL>(r1);
  71. bool ret2 = ReadImpl(r2, bits - 56ULL);
  72. result = (r2 << 56ULL) | r1;
  73. return ret1 & ret2;
  74. }
  75. // It's safe to read up to 64 bits.
  76. // Preserves what's in result.
  77. template <typename T>
  78. Y_FORCE_INLINE bool ReadSafe(T& result, ui64 bits, ui64 skipbits) {
  79. ui64 r64 = 0;
  80. bool ret = ReadSafe(r64, bits);
  81. CopyToResult(result, r64, bits, skipbits);
  82. return ret;
  83. }
  84. // Do not try to read more than 56 bits at once. Split in two reads or use ReadSafe.
  85. // Zeroes other bits in result.
  86. template <typename T>
  87. Y_FORCE_INLINE bool Read(T& result, ui64 bits) {
  88. ui64 r64 = 0;
  89. bool ret = ReadImpl(r64, bits);
  90. result = r64;
  91. return ret;
  92. }
  93. // Shortcut to impl.
  94. Y_FORCE_INLINE bool Read(ui64& result, ui64 bits) {
  95. return ReadImpl(result, bits);
  96. }
  97. // Do not try to read more than 56 bits at once. Split in two reads or use ReadSafe.
  98. // Preserves what's in result.
  99. template <typename T>
  100. Y_FORCE_INLINE bool Read(T& result, ui64 bits, ui64 skipbits) {
  101. ui64 r64 = 0;
  102. bool ret = ReadImpl(r64, bits);
  103. CopyToResult(result, r64, bits, skipbits);
  104. return ret;
  105. }
  106. // Unsigned wordwise read. Underlying data is splitted in "words" of "bits(data) + 1(flag)" bits.
  107. // Like this: (unsigned char)0x2E<3> (0010 1110) <=> 1110 0101
  108. // fddd fddd
  109. template <ui64 bits, typename T>
  110. Y_FORCE_INLINE bool ReadWords(T& result) {
  111. ui64 r64 = 0;
  112. bool retCode = ReadWordsImpl<bits>(r64);
  113. result = r64;
  114. return retCode;
  115. }
  116. // Shortcut to impl.
  117. template <ui64 bits>
  118. Y_FORCE_INLINE bool ReadWords(ui64& result) {
  119. return ReadWordsImpl<bits>(result);
  120. }
  121. Y_FORCE_INLINE bool Back(int bits) {
  122. return Seek(BitOffset() - bits);
  123. }
  124. Y_FORCE_INLINE bool Seek(int bitoffset) {
  125. return TBitInputImpl::Seek(bitoffset);
  126. }
  127. // A way to read a portion of bits at random location.
  128. // Didn't want to complicate sequential read, neither to copypaste.
  129. template <typename T>
  130. Y_FORCE_INLINE bool ReadRandom(ui64 bitoffset, T& result, ui64 bits, ui64 skipbits) {
  131. const ui64 curr = BitOffset();
  132. Seek(bitoffset);
  133. bool ret = ReadSafe<T>(result, bits, skipbits);
  134. Seek(curr);
  135. return ret;
  136. }
  137. };
  138. }