rippled
varint.h
1 //------------------------------------------------------------------------------
2 /*
3  This file is part of Beast: https://github.com/vinniefalco/Beast
4  Copyright 2014, Vinnie Falco <vinnie.falco@gmail.com>
5 
6  Permission to use, copy, modify, and/or distribute this software for any
7  purpose with or without fee is hereby granted, provided that the above
8  copyright notice and this permission notice appear in all copies.
9 
10  THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11  WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12  MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13  ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14  WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15  ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16  OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */
18 //==============================================================================
19 
20 #ifndef BEAST_NUDB_VARINT_H_INCLUDED
21 #define BEAST_NUDB_VARINT_H_INCLUDED
22 
23 #include <cstdint>
24 #include <nudb/detail/stream.hpp>
25 #include <type_traits>
26 
27 namespace ripple {
28 namespace NodeStore {
29 
30 // This is a variant of the base128 varint format from
31 // google protocol buffers:
32 // https://developers.google.com/protocol-buffers/docs/encoding#varints
33 
34 // field tag
35 struct varint;
36 
37 // Metafuncton to return largest
38 // possible size of T represented as varint.
39 // T must be unsigned
40 template <class T, bool = std::is_unsigned<T>::value>
42 
43 template <class T>
44 struct varint_traits<T, true>
45 {
46  explicit varint_traits() = default;
47 
48  static std::size_t constexpr max = (8 * sizeof(T) + 6) / 7;
49 };
50 
51 // Returns: Number of bytes consumed or 0 on error,
52 // if the buffer was too small or t overflowed.
53 //
54 template <class = void>
56 read_varint(void const* buf, std::size_t buflen, std::size_t& t)
57 {
58  t = 0;
59  std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
60  std::size_t n = 0;
61  while (p[n] & 0x80)
62  if (++n >= buflen)
63  return 0;
64  if (++n > buflen)
65  return 0;
66  // Special case for 0
67  if (n == 1 && *p == 0)
68  {
69  t = 0;
70  return 1;
71  }
72  auto const used = n;
73  while (n--)
74  {
75  auto const d = p[n];
76  auto const t0 = t;
77  t *= 127;
78  t += d & 0x7f;
79  if (t <= t0)
80  return 0; // overflow
81  }
82  return used;
83 }
84 
85 template <class T, std::enable_if_t<std::is_unsigned<T>::value>* = nullptr>
88 {
89  std::size_t n = 0;
90  do
91  {
92  v /= 127;
93  ++n;
94  } while (v != 0);
95  return n;
96 }
97 
98 template <class = void>
101 {
102  std::uint8_t* p = reinterpret_cast<std::uint8_t*>(p0);
103  do
104  {
105  std::uint8_t d = v % 127;
106  v /= 127;
107  if (v != 0)
108  d |= 0x80;
109  *p++ = d;
110  } while (v != 0);
111  return p - reinterpret_cast<std::uint8_t*>(p0);
112 }
113 
114 // input stream
115 
116 template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
117 void
118 read(nudb::detail::istream& is, std::size_t& u)
119 {
120  auto p0 = is(1);
121  auto p1 = p0;
122  while (*p1++ & 0x80)
123  is(1);
124  read_varint(p0, p1 - p0, u);
125 }
126 
127 // output stream
128 
129 template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
130 void
131 write(nudb::detail::ostream& os, std::size_t t)
132 {
133  write_varint(os.data(size_varint(t)), t);
134 }
135 
136 } // namespace NodeStore
137 } // namespace ripple
138 
139 #endif
ripple::NodeStore::read
void read(nudb::detail::istream &is, std::size_t &u)
Definition: varint.h:118
ripple::NodeStore::write
void write(nudb::detail::ostream &os, std::size_t t)
Definition: varint.h:131
ripple::NodeStore::varint_traits
Definition: varint.h:41
ripple::NodeStore::read_varint
std::size_t read_varint(void const *buf, std::size_t buflen, std::size_t &t)
Definition: varint.h:56
cstdint
std::uint8_t
ripple
Use hash_* containers for keys that do not need a cryptographically secure hashing algorithm.
Definition: RCLCensorshipDetector.h:29
ripple::NodeStore::size_varint
std::size_t size_varint(T v)
Definition: varint.h:87
std::size_t
type_traits
ripple::NodeStore::write_varint
std::size_t write_varint(void *p0, std::size_t v)
Definition: varint.h:100