rippled
Loading...
Searching...
No Matches
varint.h
1#ifndef BEAST_NUDB_VARINT_H_INCLUDED
2#define BEAST_NUDB_VARINT_H_INCLUDED
3
4#include <nudb/detail/stream.hpp>
5
6#include <cstdint>
7#include <type_traits>
8
9namespace ripple {
10namespace NodeStore {
11
12// This is a variant of the base128 varint format from
13// google protocol buffers:
14// https://developers.google.com/protocol-buffers/docs/encoding#varints
15
16// field tag
17struct varint;
18
19// Metafuncton to return largest
20// possible size of T represented as varint.
21// T must be unsigned
22template <class T, bool = std::is_unsigned<T>::value>
24
25template <class T>
26struct varint_traits<T, true>
27{
28 explicit varint_traits() = default;
29
30 static std::size_t constexpr max = (8 * sizeof(T) + 6) / 7;
31};
32
33// Returns: Number of bytes consumed or 0 on error,
34// if the buffer was too small or t overflowed.
35//
36template <class = void>
38read_varint(void const* buf, std::size_t buflen, std::size_t& t)
39{
40 if (buflen == 0)
41 return 0;
42 t = 0;
43 std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
44 std::size_t n = 0;
45 while (p[n] & 0x80)
46 if (++n >= buflen)
47 return 0;
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--)
58 {
59 auto const d = p[n];
60 auto const t0 = t;
61 t *= 127;
62 t += d & 0x7f;
63 if (t <= t0)
64 return 0; // overflow
65 }
66 return used;
67}
68
69template <class T, std::enable_if_t<std::is_unsigned<T>::value>* = nullptr>
72{
73 std::size_t n = 0;
74 do
75 {
76 v /= 127;
77 ++n;
78 } while (v != 0);
79 return n;
80}
81
82template <class = void>
85{
86 std::uint8_t* p = reinterpret_cast<std::uint8_t*>(p0);
87 do
88 {
89 std::uint8_t d = v % 127;
90 v /= 127;
91 if (v != 0)
92 d |= 0x80;
93 *p++ = d;
94 } while (v != 0);
95 return p - reinterpret_cast<std::uint8_t*>(p0);
96}
97
98// input stream
99
100template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
101void
102read(nudb::detail::istream& is, std::size_t& u)
103{
104 auto p0 = is(1);
105 auto p1 = p0;
106 while (*p1++ & 0x80)
107 is(1);
108 read_varint(p0, p1 - p0, u);
109}
110
111// output stream
112
113template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
114void
115write(nudb::detail::ostream& os, std::size_t t)
116{
117 write_varint(os.data(size_varint(t)), t);
118}
119
120} // namespace NodeStore
121} // namespace ripple
122
123#endif
std::size_t read_varint(void const *buf, std::size_t buflen, std::size_t &t)
Definition varint.h:38
std::size_t size_varint(T v)
Definition varint.h:71
void write(nudb::detail::ostream &os, std::size_t t)
Definition varint.h:115
void read(nudb::detail::istream &is, std::size_t &u)
Definition varint.h:102
std::size_t write_varint(void *p0, std::size_t v)
Definition varint.h:84
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:6