SSP21-CPP
SerializationTemplates.h
1 /*
2  * Copyright (c) 2018, Automatak LLC
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
6  * following conditions are met:
7  *
8  * 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following
9  * disclaimer.
10  *
11  * 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following
12  * disclaimer in the documentation and/or other materials provided with the distribution.
13  *
14  * 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote
15  * products derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
18  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
22  * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
23  * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25 #ifndef SER4CPP_SERIALIZATIONTEMPLATES_H
26 #define SER4CPP_SERIALIZATIONTEMPLATES_H
27 
28 #include "ser4cpp/container/SequenceTypes.h"
29 #include "ser4cpp/serialization/UInt48Type.h"
30 
31 #include <cstdint>
32 #include <cstring>
33 
34 // On linux (at least Ubuntu 18.10), termios defines B0
35 // as a bitrate constant, making the templates compilation
36 // crash. For now, we just undef it.
37 #ifdef B0
38 #undef B0
39 #endif
40 
41 namespace ser4cpp
42 {
43 
44 class UInt8
45 {
46 public:
47  inline static bool read_from(rseq_t& input, uint8_t& out)
48  {
49  if (input.length() < size) return false;
50 
51  out = read(input);
52  input.advance(size);
53  return true;
54  }
55 
56  static bool write_to(wseq_t& dest, uint8_t value)
57  {
58  if (dest.length() < size) return false;
59 
60  write(dest, value);
61  dest.advance(size);
62  return true;
63  }
64 
65  const static size_t size = 1;
66  const static uint8_t min_value = 0;
67  const static uint8_t max_value = 255;
68 
69  typedef uint8_t type_t;
70 
71 private:
72  inline static uint8_t read(const uint8_t* start)
73  {
74  return (*start);
75  }
76 
77  inline static void write(uint8_t* start, uint8_t value)
78  {
79  *(start) = value;
80  }
81 };
82 
83 template <class T, uint8_t B0, uint8_t B1>
84 class Bit16
85 {
86  static_assert(sizeof(T) == 2, "bad size");
87  static_assert((B0 < sizeof(T))&& (B1 < sizeof(T))&& (B0 != B1), "bad config");
88 
89 public:
90  static bool write_to(wseq_t& dest, T value)
91  {
92  if (dest.length() < size) return false;
93 
94  write(dest, value);
95  dest.advance(size);
96  return true;
97  }
98 
99  inline static bool read_from(rseq_t& input, T& out)
100  {
101  if (input.length() < size) return false;
102 
103  out = read(input);
104  input.advance(size);
105  return true;
106  }
107 
108  typedef T type_t;
109 
110  const static size_t size = sizeof(T);
111  const static T max_value;
112  const static T min_value;
113 
114 private:
115  static T read(const uint8_t* data)
116  {
117  return (static_cast<T>(data[B0]) << 0) | (static_cast<T>(data[B1]) << 8);
118  }
119 
120  static void write(uint8_t* data, T value)
121  {
122  data[B0] = static_cast<uint8_t>(value & 0xFF);
123  data[B1] = static_cast<uint8_t>((value >> 8) & 0xFF);
124  }
125 };
126 
127 template <class T, uint8_t B0, uint8_t B1>
128 const T Bit16<T, B0, B1>::max_value = std::numeric_limits<T>::max();
129 
130 template <class T, uint8_t B0, uint8_t B1>
131 const T Bit16<T, B0, B1>::min_value = std::numeric_limits<T>::min();
132 
133 template <class T, uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3>
134 class Bit32
135 {
136  static_assert(sizeof(T) == 4, "bad size");
137  static_assert((B0 < sizeof(T))&& (B1 < sizeof(T))&& (B2 < sizeof(T))&& (B3 < sizeof(T)), "bad config");
138 
139 public:
140  static bool write_to(wseq_t& dest, T value)
141  {
142  if (dest.length() < size) return false;
143 
144  write(dest, value);
145  dest.advance(size);
146  return true;
147  }
148 
149  inline static bool read_from(rseq_t& input, T& out)
150  {
151  if (input.length() < size) return false;
152 
153  out = read(input);
154  input.advance(size);
155  return true;
156  }
157 
158  typedef T type_t;
159 
160  const static size_t size = sizeof(T);
161  const static T max_value;
162  const static T min_value;
163 
164 private:
165  static T read(const uint8_t* data)
166  {
167  return (static_cast<T>(data[B0]) << 0) |
168  (static_cast<T>(data[B1]) << 8) |
169  (static_cast<T>(data[B2]) << 16) |
170  (static_cast<T>(data[B3]) << 24);
171  }
172 
173  static void write(uint8_t* data, T value)
174  {
175  data[B0] = static_cast<uint8_t>(value & 0xFF);
176  data[B1] = static_cast<uint8_t>((value >> 8) & 0xFF);
177  data[B2] = static_cast<uint8_t>((value >> 16) & 0xFF);
178  data[B3] = static_cast<uint8_t>((value >> 24) & 0xFF);
179  }
180 };
181 
182 template <class T, uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3>
183 const T Bit32<T, B0, B1, B2, B3>::max_value = std::numeric_limits<T>::max();
184 
185 template <class T, uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3>
186 const T Bit32<T, B0, B1, B2, B3>::min_value = std::numeric_limits<T>::min();
187 
188 template <class T, uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3, uint8_t B4, uint8_t B5, uint8_t B6, uint8_t B7>
189 class Bit64
190 {
191  static_assert(sizeof(T) == 8, "bad size");
192  static_assert(
193  (B0 < sizeof(T))&& (B1 < sizeof(T))&& (B2 < sizeof(T))&& (B3 < sizeof(T))&& (B4 < sizeof(T))&& (B5 < sizeof(T))&& (B6 < sizeof(T))&& (B7 < sizeof(T)),
194  "bad config"
195  );
196 
197 public:
198  static bool write_to(wseq_t& dest, T value)
199  {
200  if (dest.length() < size) return false;
201 
202  write(dest, value);
203  dest.advance(size);
204  return true;
205  }
206 
207  inline static bool read_from(rseq_t& input, T& out)
208  {
209  if (input.length() < size) return false;
210 
211  out = read(input);
212  input.advance(size);
213  return true;
214  }
215 
216  typedef T type_t;
217 
218  const static size_t size = sizeof(T);
219  const static T max_value;
220  const static T min_value;
221 
222 private:
223  static T read(const uint8_t* data)
224  {
225  return (static_cast<T>(data[B0]) << 0) |
226  (static_cast<T>(data[B1]) << 8) |
227  (static_cast<T>(data[B2]) << 16) |
228  (static_cast<T>(data[B3]) << 24) |
229  (static_cast<T>(data[B4]) << 32) |
230  (static_cast<T>(data[B5]) << 40) |
231  (static_cast<T>(data[B6]) << 48) |
232  (static_cast<T>(data[B7]) << 56);
233  }
234 
235  static void write(uint8_t* data, T value)
236  {
237  data[B0] = static_cast<uint8_t>(value & 0xFF);
238  data[B1] = static_cast<uint8_t>((value >> 8) & 0xFF);
239  data[B2] = static_cast<uint8_t>((value >> 16) & 0xFF);
240  data[B3] = static_cast<uint8_t>((value >> 24) & 0xFF);
241  data[B4] = static_cast<uint8_t>((value >> 32) & 0xFF);
242  data[B5] = static_cast<uint8_t>((value >> 40) & 0xFF);
243  data[B6] = static_cast<uint8_t>((value >> 48) & 0xFF);
244  data[B7] = static_cast<uint8_t>((value >> 56) & 0xFF);
245  }
246 };
247 
248 template <class T, uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3, uint8_t B4, uint8_t B5, uint8_t B6, uint8_t B7>
249 const T Bit64<T, B0, B1, B2, B3, B4, B5, B6, B7>::max_value = std::numeric_limits<T>::max();
250 
251 template <class T, uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3, uint8_t B4, uint8_t B5, uint8_t B6, uint8_t B7>
252 const T Bit64<T, B0, B1, B2, B3, B4, B5, B6, B7>::min_value = std::numeric_limits<T>::min();
253 
254 
255 template <uint8_t B0, uint8_t B1, uint8_t B2, uint8_t B3, uint8_t B4, uint8_t B5>
256 class UBit48
257 {
258  static_assert((B0 < 6)&& (B1 < 6)&& (B2 < 6)&& (B3 < 6)&& (B4 < 6)&& (B5 < 6), "bad config");
259 
260 public:
261  inline static bool read_from(rseq_t& input, UInt48Type& out)
262  {
263  if (input.length() < size) return false;
264 
265  out = read(input);
266  input.advance(size);
267  return true;
268  }
269 
270  static bool write_to(wseq_t& dest, UInt48Type value)
271  {
272  if (dest.length() < size) return false;
273 
274  write(dest, value);
275  dest.advance(size);
276  return true;
277  }
278 
279  typedef UInt48Type type_t;
280  const static size_t size = 6;
281  const static uint64_t min_value = 0;
282  const static uint64_t max_value = 281474976710655ULL; // 2^48 -1
283 
284  static inline UInt48Type read(const uint8_t* data)
285  {
286  return UInt48Type(
287  (static_cast<uint64_t>(data[B0]) << 0) |
288  (static_cast<uint64_t>(data[B1]) << 8) |
289  (static_cast<uint64_t>(data[B2]) << 16) |
290  (static_cast<uint64_t>(data[B3]) << 24) |
291  (static_cast<uint64_t>(data[B4]) << 32) |
292  (static_cast<uint64_t>(data[B5]) << 40));
293  }
294 
295  static inline void write(uint8_t* data, UInt48Type value)
296  {
297  if (value > max_value)
298  {
299  value = UInt48Type(max_value);
300  }
301 
302  data[B0] = static_cast<uint8_t>(value & 0xFF);
303  data[B1] = static_cast<uint8_t>((value >> 8) & 0xFF);
304  data[B2] = static_cast<uint8_t>((value >> 16) & 0xFF);
305  data[B3] = static_cast<uint8_t>((value >> 24) & 0xFF);
306  data[B4] = static_cast<uint8_t>((value >> 32) & 0xFF);
307  data[B5] = static_cast<uint8_t>((value >> 40) & 0xFF);
308  }
309 };
310 
311 }
312 
313 #endif
ser4cpp header-only library namespace
Definition: Buffer.h:33