bitinput_impl.h 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. #pragma once
  2. #include <util/generic/bitops.h>
  3. #include <util/system/unaligned_mem.h>
  4. namespace NBitIO {
  5. class TBitInputImpl {
  6. i64 RealStart;
  7. i64 Start;
  8. ui64 Length;
  9. ui64 BOffset;
  10. const ui32 FakeStart;
  11. char Fake[16];
  12. const i64 FStart;
  13. public:
  14. TBitInputImpl(const char* start, const char* end)
  15. : RealStart((i64)start)
  16. , Start((i64)start)
  17. , Length((end - start) << 3)
  18. , BOffset(0)
  19. , FakeStart(Length > 64 ? Length - 64 : 0)
  20. , FStart((i64)Fake - (FakeStart >> 3))
  21. {
  22. memcpy(Fake, (const char*)(RealStart + (FakeStart >> 3)), (Length - FakeStart) >> 3);
  23. Start = FakeStart ? RealStart : FStart;
  24. }
  25. ui64 GetBitLength() const {
  26. return Length;
  27. }
  28. protected:
  29. template <ui32 bits>
  30. Y_FORCE_INLINE bool ReadKImpl(ui64& result) {
  31. result = (ReadUnaligned<ui64>((const void*)(Start + (BOffset >> 3))) >> (BOffset & 7)) & Mask64(bits);
  32. BOffset += bits;
  33. if (BOffset < FakeStart)
  34. return true;
  35. if (BOffset > Length) {
  36. result = 0;
  37. BOffset -= bits;
  38. return false;
  39. }
  40. Start = FStart;
  41. return true;
  42. }
  43. Y_FORCE_INLINE bool ReadImpl(ui64& result, ui32 bits) {
  44. result = (ReadUnaligned<ui64>((const void*)(Start + (BOffset >> 3))) >> (BOffset & 7)) & MaskLowerBits(bits);
  45. BOffset += bits;
  46. if (BOffset < FakeStart)
  47. return true;
  48. if (Y_UNLIKELY(BOffset > Length)) {
  49. result = 0;
  50. BOffset -= bits;
  51. return false;
  52. }
  53. Start = FStart;
  54. return true;
  55. }
  56. Y_FORCE_INLINE bool EofImpl() const {
  57. return BOffset >= Length;
  58. }
  59. Y_FORCE_INLINE ui64 BitOffset() const {
  60. return BOffset;
  61. }
  62. Y_FORCE_INLINE bool Seek(i64 offset) {
  63. if (offset < 0 || offset > (i64)Length)
  64. return false;
  65. BOffset = offset;
  66. Start = BOffset < FakeStart ? RealStart : FStart;
  67. return true;
  68. }
  69. protected:
  70. template <ui64 bits, typename T>
  71. Y_FORCE_INLINE static void CopyToResultK(T& result, ui64 r64, ui64 skipbits) {
  72. result = (result & ~(Mask64(bits) << skipbits)) | (r64 << skipbits);
  73. }
  74. template <typename T>
  75. Y_FORCE_INLINE static void CopyToResult(T& result, ui64 r64, ui64 bits, ui64 skipbits) {
  76. result = (result & InverseMaskLowerBits(bits, skipbits)) | (r64 << skipbits);
  77. }
  78. public:
  79. template <ui64 bits>
  80. Y_FORCE_INLINE bool ReadWordsImpl(ui64& data) {
  81. data = 0;
  82. const ui64 haveMore = NthBit64(bits);
  83. const ui64 mask = Mask64(bits);
  84. ui64 current = 0;
  85. ui64 byteNo = 0;
  86. do {
  87. if (!ReadKImpl<bits + 1>(current))
  88. return false;
  89. data |= (current & mask) << (byteNo++ * bits);
  90. } while (current & haveMore);
  91. return true;
  92. }
  93. };
  94. }