Bond
 
Loading...
Searching...
No Matches
encoding.h
1// Copyright (c) Microsoft. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
4#pragma once
5
6#include <bond/core/config.h>
7
8#include <bond/core/blob.h>
9#include <bond/core/containers.h>
10
11#include <exception>
12#include <stdio.h>
13
14namespace bond
15{
16
17
18template <typename Buffer, typename T, typename Enable = void> struct
19implements_varint_write
20 : std::false_type {};
21
22
23template <typename Buffer, typename T> struct
24implements_varint_write<Buffer, T,
25#ifdef BOND_NO_SFINAE_EXPR
26 typename boost::enable_if<check_method<void (Buffer::*)(T), &Buffer::WriteVariableUnsigned> >::type>
27#else
28 detail::mpl::void_t<decltype(std::declval<Buffer>().WriteVariableUnsigned(std::declval<T>()))>>
29#endif
30 : std::true_type {};
31
32
33// GenericWriteVariableUnsigned and WriteVariableUnsigned are mutually
34// recursive, so we need a forward declaration of one of them.
35template<typename Buffer, typename T>
36inline void GenericWriteVariableUnsigned(Buffer& output, T value);
37
38
39template<typename Buffer, typename T>
40inline
41typename boost::enable_if<implements_varint_write<Buffer, T> >::type
42WriteVariableUnsigned(Buffer& output, T value)
43{
44 BOOST_STATIC_ASSERT(std::is_unsigned<T>::value);
45
46 // Use Buffer's implementation of WriteVariableUnsigned
47 output.WriteVariableUnsigned(value);
48}
49
50
51template<typename Buffer, typename T>
52inline
53typename boost::disable_if<implements_varint_write<Buffer, T> >::type
54WriteVariableUnsigned(Buffer& output, T value)
55{
56 BOOST_STATIC_ASSERT(std::is_unsigned<T>::value);
57
58 // Use generic WriteVariableUnsigned
59 GenericWriteVariableUnsigned(output, value);
60}
61
62
63template<typename Buffer, typename T>
64BOND_NO_INLINE
65inline void GenericWriteVariableUnsigned(Buffer& output, T value)
66{
67 T x = value;
68
69 if (value >>= 7)
70 {
71 output.Write(static_cast<uint8_t>(x | 0x80));
72 WriteVariableUnsigned(output, value);
73 }
74 else
75 {
76 output.Write(static_cast<uint8_t>(x));
77 }
78}
79
80
81template <typename Buffer, typename T, typename Enable = void> struct
82implements_varint_read
83 : std::false_type {};
84
85
86template <typename Buffer, typename T> struct
87implements_varint_read<Buffer, T,
88#ifdef BOND_NO_SFINAE_EXPR
89 typename boost::enable_if<check_method<void (Buffer::*)(T&), &Buffer::ReadVariableUnsigned> >::type>
90#else
91 detail::mpl::void_t<decltype(std::declval<Buffer>().ReadVariableUnsigned(std::declval<T&>()))>>
92#endif
93 : std::true_type {};
94
95
96template<typename Buffer, typename T>
97inline
98typename boost::enable_if<implements_varint_read<Buffer, T> >::type
99ReadVariableUnsigned(Buffer& input, T& value)
100{
101 BOOST_STATIC_ASSERT(std::is_unsigned<T>::value);
102
103 // Use Buffer's implementation of ReadVariableUnsigned
104 input.ReadVariableUnsigned(value);
105}
106
107
108template<typename Buffer, typename T>
109BOND_NO_INLINE
110void GenericReadVariableUnsigned(Buffer& input, T& value)
111{
112 value = 0;
113 uint8_t byte;
114 uint32_t shift = 0;
115
116 do
117 {
118 input.Read(byte);
119
120 T part = byte & 0x7f;
121 value += part << shift;
122 shift += 7;
123 }
124 while(byte >= 0x80);
125}
126
127
128template<typename Buffer, typename T>
129inline
130typename boost::disable_if<implements_varint_read<Buffer, T> >::type
131ReadVariableUnsigned(Buffer& input, T& value)
132{
133 BOOST_STATIC_ASSERT(std::is_unsigned<T>::value);
134
135 // Use generic ReadVariableUnsigned
136 GenericReadVariableUnsigned(input, value);
137}
138
139
140// ZigZag encoding
141template<typename T>
142inline
143typename std::make_unsigned<T>::type EncodeZigZag(T value)
144{
145 return (value << 1) ^ (value >> (sizeof(T) * 8 - 1));
146}
147
148// ZigZag decoding
149template<typename T>
150inline
151typename std::make_signed<T>::type DecodeZigZag(T value)
152{
153 return (value >> 1) ^ (-static_cast<typename std::make_signed<T>::type>((value & 1)));
154}
155
156
157namespace detail
158{
159
160// HexDigit
161inline char HexDigit(int n)
162{
163 char d = n & 0xf;
164 return d < 10 ? ('0' + d) : ('a' + d - 10);
165}
166
167inline int HexDigit(char c)
168{
169 if (c >= 'a' && c <= 'f')
170 return c - 'a' + 10;
171 else if (c >= 'A' && c <= 'F')
172 return c - 'A' + 10;
173 else
174 return c - '0';
175}
176
177template <typename T, typename Enable = void> struct
178string_char_int_type;
179
180template <typename T> struct
181string_char_int_type<T, typename boost::enable_if<is_string<T> >::type>
182{
183 typedef uint8_t type;
184};
185
186template <typename T> struct
187string_char_int_type<T, typename boost::enable_if<is_wstring<T> >::type>
188{
189 typedef uint16_t type;
190};
191
192template <typename Buffer, typename T>
193typename boost::enable_if_c<(sizeof(typename element_type<T>::type) == sizeof(typename string_char_int_type<T>::type))>::type
194inline ReadStringData(Buffer& input, T& value, uint32_t length)
195{
196 resize_string(value, length);
197 input.Read(string_data(value), length * sizeof(typename element_type<T>::type));
198}
199
200template <typename Buffer, typename T>
201typename boost::enable_if_c<(sizeof(typename element_type<T>::type) > sizeof(typename string_char_int_type<T>::type))>::type
202inline ReadStringData(Buffer& input, T& value, uint32_t length)
203{
204 resize_string(value, length);
205 typename element_type<T>::type* data = string_data(value);
206 typename element_type<T>::type* const data_end = data + length;
207 typename string_char_int_type<T>::type ch;
208 for (; data != data_end; ++data)
209 {
210 input.Read(ch);
211 *data = static_cast<typename element_type<T>::type>(ch);
212 }
213}
214
215template <typename Buffer, typename T>
216typename boost::enable_if_c<(sizeof(typename element_type<T>::type) == sizeof(typename string_char_int_type<T>::type))>::type
217inline WriteStringData(Buffer& output, const T& value, uint32_t length)
218{
219 output.Write(string_data(value), length * sizeof(typename element_type<T>::type));
220}
221
222template <typename Buffer, typename T>
223typename boost::enable_if_c<(sizeof(typename element_type<T>::type) > sizeof(typename string_char_int_type<T>::type))>::type
224inline WriteStringData(Buffer& output, const T& value, uint32_t length)
225{
226 const typename element_type<T>::type* data = string_data(value);
227 const typename element_type<T>::type* const data_end = data + length;
228 typename string_char_int_type<T>::type ch;
229 for (; data != data_end; ++data)
230 {
231 ch = static_cast<typename string_char_int_type<T>::type>(*data);
232 output.Write(ch);
233 }
234}
235
236} // namespace detail
237
238} // namespace bond
namespace bond
Definition: apply.h:17