varint.cpp 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. #include "varint.h"
  2. #include <util/generic/yexception.h>
  3. #include <util/stream/input.h>
  4. #include <util/stream/output.h>
  5. namespace NMonitoring {
  6. ui32 WriteVarUInt32(IOutputStream* output, ui32 value) {
  7. bool stop = false;
  8. ui32 written = 0;
  9. while (!stop) {
  10. ui8 byte = static_cast<ui8>(value | 0x80);
  11. value >>= 7;
  12. if (value == 0) {
  13. stop = true;
  14. byte &= 0x7F;
  15. }
  16. output->Write(byte);
  17. written++;
  18. }
  19. return written;
  20. }
  21. ui32 ReadVarUInt32(IInputStream* input) {
  22. ui32 value = 0;
  23. switch (TryReadVarUInt32(input, &value)) {
  24. case EReadResult::OK:
  25. return value;
  26. case EReadResult::ERR_OVERFLOW:
  27. ythrow yexception() << "the data is too long to read ui32";
  28. case EReadResult::ERR_UNEXPECTED_EOF:
  29. ythrow yexception() << "the data unexpectedly ended";
  30. default:
  31. ythrow yexception() << "unknown error while reading varint";
  32. }
  33. }
  34. size_t ReadVarUInt32(const ui8* buf, size_t len, ui32* result) {
  35. size_t count = 0;
  36. ui32 value = 0;
  37. ui8 byte = 0;
  38. do {
  39. if (7 * count > 8 * sizeof(ui32)) {
  40. ythrow yexception() << "the data is too long to read ui32";
  41. }
  42. if (count == len) {
  43. ythrow yexception() << "the data unexpectedly ended";
  44. }
  45. byte = buf[count];
  46. value |= (static_cast<ui32>(byte & 0x7F)) << (7 * count);
  47. ++count;
  48. } while (byte & 0x80);
  49. *result = value;
  50. return count;
  51. }
  52. EReadResult TryReadVarUInt32(IInputStream* input, ui32* value) {
  53. size_t count = 0;
  54. ui32 result = 0;
  55. ui8 byte = 0;
  56. do {
  57. if (7 * count > 8 * sizeof(ui32)) {
  58. return EReadResult::ERR_OVERFLOW;
  59. }
  60. if (input->Read(&byte, 1) != 1) {
  61. return EReadResult::ERR_UNEXPECTED_EOF;
  62. }
  63. result |= (static_cast<ui32>(byte & 0x7F)) << (7 * count);
  64. ++count;
  65. } while (byte & 0x80);
  66. *value = result;
  67. return EReadResult::OK;
  68. }
  69. }