xrpld
Loading...
Searching...
No Matches
varint.h
1#pragma once
2
3#include <nudb/detail/stream.hpp>
4
5#include <cstdint>
6#include <type_traits>
7
8namespace xrpl::NodeStore {
9
10// This is a variant of the base128 varint format from
11// google protocol buffers:
12// https://developers.google.com/protocol-buffers/docs/encoding#varints
13
14// field tag
15struct varint;
16
17// Metafuncton to return largest
18// possible size of T represented as varint.
19// T must be unsigned
20template <class T, bool = std::is_unsigned_v<T>>
22
23template <class T>
24struct varint_traits<T, true>
25{
26 explicit varint_traits() = default;
27
28 static constexpr std::size_t kMax = ((8 * sizeof(T)) + 6) / 7;
29};
30
31// Returns: Number of bytes consumed or 0 on error,
32// if the buffer was too small or t overflowed.
33//
34template <class = void>
36readVarint(void const* buf, std::size_t buflen, std::size_t& t)
37{
38 if (buflen == 0)
39 return 0;
40 t = 0;
41 std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
42 std::size_t n = 0;
43 while (p[n] & 0x80)
44 {
45 if (++n >= buflen)
46 return 0;
47 }
48 if (++n > buflen)
49 return 0;
50 // Special case for 0
51 if (n == 1 && *p == 0)
52 {
53 t = 0;
54 return 1;
55 }
56 auto const used = n;
57 while (n > 0)
58 {
59 --n;
60 auto const d = p[n];
61 auto const t0 = t;
62 t *= 127;
63 t += d & 0x7f;
64 if (t <= t0)
65 return 0; // overflow
66 }
67 return used;
68}
69
70template <class T, std::enable_if_t<std::is_unsigned_v<T>>* = nullptr>
73{
74 std::size_t n = 0;
75 do
76 {
77 v /= 127;
78 ++n;
79 } while (v != 0);
80 return n;
81}
82
83template <class = void>
86{
87 // NOLINTNEXTLINE(misc-const-correctness)
88 std::uint8_t* p = reinterpret_cast<std::uint8_t*>(p0);
89 do
90 {
91 std::uint8_t d = v % 127;
92 v /= 127;
93 if (v != 0)
94 d |= 0x80;
95 *p++ = d;
96 } while (v != 0);
97 return p - reinterpret_cast<std::uint8_t*>(p0);
98}
99
100// input stream
101
102template <class T, std::enable_if_t<std::is_same_v<T, varint>>* = nullptr>
103void
104read(nudb::detail::istream& is, std::size_t& u)
105{
106 auto p0 = is(1);
107 auto p1 = p0;
108 while (*p1++ & 0x80)
109 is(1);
110 readVarint(p0, p1 - p0, u);
111}
112
113// output stream
114
115template <class T, std::enable_if_t<std::is_same_v<T, varint>>* = nullptr>
116void
117write(nudb::detail::ostream& os, std::size_t t)
118{
119 writeVarint(os.data(sizeVarint(t)), t);
120}
121
122} // namespace xrpl::NodeStore
void read(nudb::detail::istream &is, std::size_t &u)
Definition varint.h:104
std::size_t readVarint(void const *buf, std::size_t buflen, std::size_t &t)
Definition varint.h:36
std::size_t writeVarint(void *p0, std::size_t v)
Definition varint.h:85
void write(nudb::detail::ostream &os, std::size_t t)
Definition varint.h:117
std::size_t sizeVarint(T v)
Definition varint.h:72
static constexpr std::size_t kMax
Definition varint.h:28