protozero
Minimalistic protocol buffer decoder and encoder in C++.
varint.hpp
Go to the documentation of this file.
1 #ifndef PROTOZERO_VARINT_HPP
2 #define PROTOZERO_VARINT_HPP
3 
4 /*****************************************************************************
5 
6 protozero - Minimalistic protocol buffer decoder and encoder in C++.
7 
8 This file is from https://github.com/mapbox/protozero where you can find more
9 documentation.
10 
11 *****************************************************************************/
12 
19 #include <cstdint>
20 
21 #include <protozero/exception.hpp>
22 
23 namespace protozero {
24 
28 const int8_t max_varint_length = sizeof(uint64_t) * 8 / 7 + 1;
29 
30 // from https://github.com/facebook/folly/blob/master/folly/Varint.h
48 inline uint64_t decode_varint(const char** data, const char* end) {
49  const int8_t* begin = reinterpret_cast<const int8_t*>(*data);
50  const int8_t* iend = reinterpret_cast<const int8_t*>(end);
51  const int8_t* p = begin;
52  uint64_t val = 0;
53 
54  if (iend - begin >= max_varint_length) { // fast path
55  do {
56  int64_t b;
57  b = *p++; val = uint64_t((b & 0x7f) ); if (b >= 0) break;
58  b = *p++; val |= uint64_t((b & 0x7f) << 7); if (b >= 0) break;
59  b = *p++; val |= uint64_t((b & 0x7f) << 14); if (b >= 0) break;
60  b = *p++; val |= uint64_t((b & 0x7f) << 21); if (b >= 0) break;
61  b = *p++; val |= uint64_t((b & 0x7f) << 28); if (b >= 0) break;
62  b = *p++; val |= uint64_t((b & 0x7f) << 35); if (b >= 0) break;
63  b = *p++; val |= uint64_t((b & 0x7f) << 42); if (b >= 0) break;
64  b = *p++; val |= uint64_t((b & 0x7f) << 49); if (b >= 0) break;
65  b = *p++; val |= uint64_t((b & 0x7f) << 56); if (b >= 0) break;
66  b = *p++; val |= uint64_t((b & 0x7f) << 63); if (b >= 0) break;
68  } while (false);
69  } else {
70  int shift = 0;
71  while (p != iend && *p < 0) {
72  val |= uint64_t(*p++ & 0x7f) << shift;
73  shift += 7;
74  }
75  if (p == iend) {
77  }
78  val |= uint64_t(*p++) << shift;
79  }
80 
81  *data = reinterpret_cast<const char*>(p);
82  return val;
83 }
84 
88 template <typename OutputIterator>
89 inline int write_varint(OutputIterator data, uint64_t value) {
90  int n=1;
91 
92  while (value >= 0x80) {
93  *data++ = char((value & 0x7f) | 0x80);
94  value >>= 7;
95  ++n;
96  }
97  *data++ = char(value);
98 
99  return n;
100 }
101 
105 inline uint32_t encode_zigzag32(int32_t value) noexcept {
106  return (static_cast<uint32_t>(value) << 1) ^ (static_cast<uint32_t>(value >> 31));
107 }
108 
112 inline uint64_t encode_zigzag64(int64_t value) noexcept {
113  return (static_cast<uint64_t>(value) << 1) ^ (static_cast<uint64_t>(value >> 63));
114 }
115 
119 inline int32_t decode_zigzag32(uint32_t value) noexcept {
120  return int32_t(value >> 1) ^ -int32_t(value & 1);
121 }
122 
126 inline int64_t decode_zigzag64(uint64_t value) noexcept {
127  return int64_t(value >> 1) ^ -int64_t(value & 1);
128 }
129 
130 } // end namespace protozero
131 
132 #endif // PROTOZERO_VARINT_HPP
uint64_t encode_zigzag64(int64_t value) noexcept
Definition: varint.hpp:112
uint32_t encode_zigzag32(int32_t value) noexcept
Definition: varint.hpp:105
const int8_t max_varint_length
Definition: varint.hpp:28
Contains the exceptions used in the protozero library.
int write_varint(OutputIterator data, uint64_t value)
Definition: varint.hpp:89
Definition: exception.hpp:39
Definition: exception.hpp:61
uint64_t decode_varint(const char **data, const char *end)
Definition: varint.hpp:48
int64_t decode_zigzag64(uint64_t value) noexcept
Definition: varint.hpp:126
All parts of the protozero header-only library are in this namespace.
Definition: byteswap.hpp:22
int32_t decode_zigzag32(uint32_t value) noexcept
Definition: varint.hpp:119