Welcome to mirror list, hosted at ThFree Co, Russian Federation.

varint_misc.hpp « coding - github.com/mapsme/omim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
blob: a727adcbf6ca0963482257f87379b31892d62561 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
// Author: Artyom Polkovnikov.
// Different variants of Varint encoding/decoding.

#pragma once

#include "coding/reader.hpp"
#include "coding/writer.hpp"

#include "base/assert.hpp"
#include "std/cstdint.hpp"
#include "std/vector.hpp"

// Encode Varint by appending to vector of bytes.
inline void VarintEncode(vector<uint8_t> & dst, uint64_t n)
{
  if (n == 0)
  {
    dst.push_back(0);
  }
  else
  {
    while (n != 0)
    {
      uint8_t b = n & 0x7F;
      n >>= 7;
      b |= n == 0 ? 0 : 0x80;
      dst.push_back(b);
    }
  }
}
// Encode varint using bytes Writer.
inline void VarintEncode(Writer & writer, uint64_t n)
{
  if (n == 0)
  {
    writer.Write(&n, 1);
  }
  else
  {
    while (n != 0)
    {
      uint8_t b = n & 0x7F;
      n >>= 7;
      b |= n == 0 ? 0 : 0x80;
      writer.Write(&b, 1);
    }
  }
}
// Deocde varint at given pointer and offset, offset is incremented after encoding.
inline uint64_t VarintDecode(void * src, uint64_t & offset)
{
  uint64_t n = 0;
  int shift = 0;
  while (1)
  {
    uint8_t b = *(((uint8_t*)src) + offset);
    CHECK_LESS_OR_EQUAL(shift, 56, ());
    n |= uint64_t(b & 0x7F) << shift;
    ++offset;
    if ((b & 0x80) == 0) break;
    shift += 7;
  }
  return n;
}
// Decode varint using bytes Reader, offset is incremented after decoding.
inline uint64_t VarintDecode(Reader & reader, uint64_t & offset)
{
  uint64_t n = 0;
  int shift = 0;
  while (1)
  {
    uint8_t b = 0;
    reader.Read(offset, &b, 1);
    CHECK_LESS_OR_EQUAL(shift, 56, ());
    n |= uint64_t(b & 0x7F) << shift;
    ++offset;
    if ((b & 0x80) == 0) break;
    shift += 7;
  }
  return n;
}
// Reverse decode varint. Offset should point to last byte of decoded varint.
// It is compulsory that there is at least one encoded varint before this varint.
// After decoding offset points to the last byte of previous varint.
inline uint64_t VarintDecodeReverse(Reader & reader, uint64_t & offset)
{
  uint8_t b = 0;
  do
  {
    --offset;
    reader.Read(offset, &b, 1);
  }
  while ((b & 0x80) != 0);
  uint64_t prevLastEncodedByteOffset = offset;
  ++offset;
  uint64_t num = VarintDecode(reader, offset);
  offset = prevLastEncodedByteOffset;
  return num;
}