rippled
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 {
9namespace NodeStore {
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// Metafuncton to return largest
19// possible size of T represented as varint.
20// T must be unsigned
21template <class T, bool = std::is_unsigned<T>::value>
23
24template <class T>
25struct varint_traits<T, true>
26{
27 explicit varint_traits() = default;
28
29 static std::size_t constexpr max = (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>
37read_varint(void const* buf, std::size_t buflen, std::size_t& t)
38{
39 if (buflen == 0)
40 return 0;
41 t = 0;
42 std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
43 std::size_t n = 0;
44 while (p[n] & 0x80)
45 if (++n >= buflen)
46 return 0;
47 if (++n > buflen)
48 return 0;
49 // Special case for 0
50 if (n == 1 && *p == 0)
51 {
52 t = 0;
53 return 1;
54 }
55 auto const used = n;
56 while (n--)
57 {
58 auto const d = p[n];
59 auto const t0 = t;
60 t *= 127;
61 t += d & 0x7f;
62 if (t <= t0)
63 return 0; // overflow
64 }
65 return used;
66}
67
68template <class T, std::enable_if_t<std::is_unsigned<T>::value>* = nullptr>
71{
72 std::size_t n = 0;
73 do
74 {
75 v /= 127;
76 ++n;
77 } while (v != 0);
78 return n;
79}
80
81template <class = void>
84{
85 std::uint8_t* p = reinterpret_cast<std::uint8_t*>(p0);
86 do
87 {
88 std::uint8_t d = v % 127;
89 v /= 127;
90 if (v != 0)
91 d |= 0x80;
92 *p++ = d;
93 } while (v != 0);
94 return p - reinterpret_cast<std::uint8_t*>(p0);
95}
96
97// input stream
98
99template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
100void
101read(nudb::detail::istream& is, std::size_t& u)
102{
103 auto p0 = is(1);
104 auto p1 = p0;
105 while (*p1++ & 0x80)
106 is(1);
107 read_varint(p0, p1 - p0, u);
108}
109
110// output stream
111
112template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
113void
114write(nudb::detail::ostream& os, std::size_t t)
115{
116 write_varint(os.data(size_varint(t)), t);
117}
118
119} // namespace NodeStore
120} // namespace xrpl
void read(nudb::detail::istream &is, std::size_t &u)
Definition varint.h:101
std::size_t size_varint(T v)
Definition varint.h:70
void write(nudb::detail::ostream &os, std::size_t t)
Definition varint.h:114
std::size_t write_varint(void *p0, std::size_t v)
Definition varint.h:83
std::size_t read_varint(void const *buf, std::size_t buflen, std::size_t &t)
Definition varint.h:37
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition algorithm.h:5