varint-inl.h 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #ifndef VARINT_INL_H_
  2. #error "Direct inclusion of this file is not allowed, include varint.h"
  3. // For the sake of sane code completion.
  4. #include "varint.h"
  5. #endif
  6. #include "zig_zag.h"
  7. namespace NYT {
  8. ////////////////////////////////////////////////////////////////////////////////
  9. template <class TWriteCallback>
  10. Y_FORCE_INLINE int WriteVarUint64Impl(TWriteCallback doWrite, ui64 value)
  11. {
  12. bool stop = false;
  13. int bytesWritten = 0;
  14. while (!stop) {
  15. ++bytesWritten;
  16. ui8 byte = static_cast<ui8>(value | 0x80);
  17. value >>= 7;
  18. if (value == 0) {
  19. stop = true;
  20. byte &= 0x7F;
  21. }
  22. doWrite(byte);
  23. }
  24. return bytesWritten;
  25. }
  26. // These are optimized versions of these Read/Write functions in protobuf/io/coded_stream.cc.
  27. Y_FORCE_INLINE int WriteVarUint64(IOutputStream* output, ui64 value)
  28. {
  29. return WriteVarUint64Impl([&] (ui8 byte) {
  30. output->Write(byte);
  31. }, value);
  32. }
  33. Y_FORCE_INLINE int WriteVarUint64(char* output, ui64 value)
  34. {
  35. return WriteVarUint64Impl([&] (ui8 byte) {
  36. *output++ = byte;
  37. }, value);
  38. }
  39. ////////////////////////////////////////////////////////////////////////////////
  40. template <class TOutput>
  41. Y_FORCE_INLINE int WriteVarUint32Impl(TOutput output, ui32 value)
  42. {
  43. return WriteVarUint64(output, static_cast<ui64>(value));
  44. }
  45. Y_FORCE_INLINE int WriteVarUint32(IOutputStream* output, ui32 value)
  46. {
  47. return WriteVarUint32Impl(output, value);
  48. }
  49. Y_FORCE_INLINE int WriteVarUint32(char* output, ui32 value)
  50. {
  51. return WriteVarUint32Impl(output, value);
  52. }
  53. ////////////////////////////////////////////////////////////////////////////////
  54. template <class TOutput>
  55. Y_FORCE_INLINE int WriteVarInt32Impl(TOutput output, i32 value)
  56. {
  57. return WriteVarUint64(output, static_cast<ui64>(ZigZagEncode32(value)));
  58. }
  59. Y_FORCE_INLINE int WriteVarInt32(IOutputStream* output, i32 value)
  60. {
  61. return WriteVarInt32Impl(output, value);
  62. }
  63. Y_FORCE_INLINE int WriteVarInt32(char* output, i32 value)
  64. {
  65. return WriteVarInt32Impl(output, value);
  66. }
  67. ////////////////////////////////////////////////////////////////////////////////
  68. template <class TOutput>
  69. Y_FORCE_INLINE int WriteVarInt64Impl(TOutput output, i64 value)
  70. {
  71. return WriteVarUint64(output, static_cast<ui64>(ZigZagEncode64(value)));
  72. }
  73. Y_FORCE_INLINE int WriteVarInt64(IOutputStream* output, i64 value)
  74. {
  75. return WriteVarInt64Impl(output, value);
  76. }
  77. Y_FORCE_INLINE int WriteVarInt64(char* output, i64 value)
  78. {
  79. return WriteVarInt64Impl(output, value);
  80. }
  81. ////////////////////////////////////////////////////////////////////////////////
  82. template <class TReadCallback>
  83. Y_FORCE_INLINE int ReadVarUint64Impl(TReadCallback doRead, ui64* value)
  84. {
  85. size_t count = 0;
  86. ui64 result = 0;
  87. ui8 byte;
  88. do {
  89. if (7 * count > 8 * sizeof(ui64) ) {
  90. throw TSimpleException("Value is too big for varuint64");
  91. }
  92. byte = doRead();
  93. result |= (static_cast<ui64> (byte & 0x7F)) << (7 * count);
  94. ++count;
  95. } while (byte & 0x80);
  96. *value = result;
  97. return count;
  98. }
  99. Y_FORCE_INLINE int ReadVarUint64(IInputStream* input, ui64* value)
  100. {
  101. return ReadVarUint64Impl([&] () {
  102. char byte;
  103. if (input->Read(&byte, 1) != 1) {
  104. throw TSimpleException("Premature end of stream while reading varuint64");
  105. }
  106. return byte;
  107. }, value);
  108. }
  109. Y_FORCE_INLINE int ReadVarUint64(const char* input, ui64* value)
  110. {
  111. return ReadVarUint64Impl([&] () {
  112. char byte = *input;
  113. ++input;
  114. return byte;
  115. }, value);
  116. }
  117. Y_FORCE_INLINE int ReadVarUint64(const char* input, const char* end, ui64* value)
  118. {
  119. return ReadVarUint64Impl([&] () {
  120. if (input == end) {
  121. throw TSimpleException("Premature end of data while reading varuint64");
  122. }
  123. char byte = *input;
  124. ++input;
  125. return byte;
  126. }, value);
  127. }
  128. ////////////////////////////////////////////////////////////////////////////////
  129. template <class... Args>
  130. Y_FORCE_INLINE int ReadVarUint32Impl(ui32* value, Args... args)
  131. {
  132. ui64 varInt;
  133. int bytesRead = ReadVarUint64(args..., &varInt);
  134. if (varInt > std::numeric_limits<ui32>::max()) {
  135. throw TSimpleException("Value is too big for varuint32");
  136. }
  137. *value = static_cast<ui32>(varInt);
  138. return bytesRead;
  139. }
  140. Y_FORCE_INLINE int ReadVarUint32(IInputStream* input, ui32* value)
  141. {
  142. return ReadVarUint32Impl(value, input);
  143. }
  144. Y_FORCE_INLINE int ReadVarUint32(const char* input, ui32* value)
  145. {
  146. return ReadVarUint32Impl(value, input);
  147. }
  148. Y_FORCE_INLINE int ReadVarUint32(const char* input, const char* end, ui32* value)
  149. {
  150. return ReadVarUint32Impl(value, input, end);
  151. }
  152. ////////////////////////////////////////////////////////////////////////////////
  153. template <class... Args>
  154. Y_FORCE_INLINE int ReadVarInt32Impl(i32* value, Args... args)
  155. {
  156. ui64 varInt;
  157. int bytesRead = ReadVarUint64(args..., &varInt);
  158. if (varInt > std::numeric_limits<ui32>::max()) {
  159. throw TSimpleException("Value is too big for varint32");
  160. }
  161. *value = ZigZagDecode32(static_cast<ui32>(varInt));
  162. return bytesRead;
  163. }
  164. Y_FORCE_INLINE int ReadVarInt32(IInputStream* input, i32* value)
  165. {
  166. return ReadVarInt32Impl(value, input);
  167. }
  168. Y_FORCE_INLINE int ReadVarInt32(const char* input, i32* value)
  169. {
  170. return ReadVarInt32Impl(value, input);
  171. }
  172. Y_FORCE_INLINE int ReadVarInt32(const char* input, const char* end, i32* value)
  173. {
  174. return ReadVarInt32Impl(value, input, end);
  175. }
  176. ////////////////////////////////////////////////////////////////////////////////
  177. template <class... Args>
  178. Y_FORCE_INLINE int ReadVarInt64Impl(i64* value, Args... args)
  179. {
  180. ui64 varInt;
  181. int bytesRead = ReadVarUint64(args..., &varInt);
  182. *value = ZigZagDecode64(varInt);
  183. return bytesRead;
  184. }
  185. Y_FORCE_INLINE int ReadVarInt64(IInputStream* input, i64* value)
  186. {
  187. return ReadVarInt64Impl(value, input);
  188. }
  189. Y_FORCE_INLINE int ReadVarInt64(const char* input, i64* value)
  190. {
  191. return ReadVarInt64Impl(value, input);
  192. }
  193. Y_FORCE_INLINE int ReadVarInt64(const char* input, const char* end, i64* value)
  194. {
  195. return ReadVarInt64Impl(value, input, end);
  196. }
  197. ////////////////////////////////////////////////////////////////////////////////
  198. } // namespace NYT