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  if (buflen == 0)
59  return 0;
60  t = 0;
61  std::uint8_t const* p = reinterpret_cast<std::uint8_t const*>(buf);
62  std::size_t n = 0;
63  while (p[n] & 0x80)
64  if (++n >= buflen)
65  return 0;
66  if (++n > buflen)
67  return 0;
68  // Special case for 0
69  if (n == 1 && *p == 0)
70  {
71  t = 0;
72  return 1;
73  }
74  auto const used = n;
75  while (n--)
76  {
77  auto const d = p[n];
78  auto const t0 = t;
79  t *= 127;
80  t += d & 0x7f;
81  if (t <= t0)
82  return 0; // overflow
83  }
84  return used;
85 }
86 
87 template <class T, std::enable_if_t<std::is_unsigned<T>::value>* = nullptr>
90 {
91  std::size_t n = 0;
92  do
93  {
94  v /= 127;
95  ++n;
96  } while (v != 0);
97  return n;
98 }
99 
100 template <class = void>
103 {
104  std::uint8_t* p = reinterpret_cast<std::uint8_t*>(p0);
105  do
106  {
107  std::uint8_t d = v % 127;
108  v /= 127;
109  if (v != 0)
110  d |= 0x80;
111  *p++ = d;
112  } while (v != 0);
113  return p - reinterpret_cast<std::uint8_t*>(p0);
114 }
115 
116 // input stream
117 
118 template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
119 void
120 read(nudb::detail::istream& is, std::size_t& u)
121 {
122  auto p0 = is(1);
123  auto p1 = p0;
124  while (*p1++ & 0x80)
125  is(1);
126  read_varint(p0, p1 - p0, u);
127 }
128 
129 // output stream
130 
131 template <class T, std::enable_if_t<std::is_same<T, varint>::value>* = nullptr>
132 void
133 write(nudb::detail::ostream& os, std::size_t t)
134 {
135  write_varint(os.data(size_varint(t)), t);
136 }
137 
138 } // namespace NodeStore
139 } // namespace ripple
140 
141 #endif
ripple::NodeStore::read
void read(nudb::detail::istream &is, std::size_t &u)
Definition: varint.h:120
ripple::NodeStore::write
void write(nudb::detail::ostream &os, std::size_t t)
Definition: varint.h:133
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:89
std::size_t
type_traits
ripple::NodeStore::write_varint
std::size_t write_varint(void *p0, std::size_t v)
Definition: varint.h:102