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