GCS  0.2.3
gu_serialize.hpp
1 /*
2  * Copyright (C) 2009-2012 Codership Oy <info@codership.com>
3  */
4 
28 #ifndef GU_SERIALIZE_HPP
29 #define GU_SERIALIZE_HPP
30 
31 #include "gu_throw.hpp"
32 #include "gu_byteswap.hpp"
33 #include "gu_buffer.hpp"
34 #include "gu_macros.hpp"
35 
36 #include <limits>
37 
38 namespace gu
39 {
40  template <typename T>
41  inline size_t serial_size(const T& t)
42  { return t.serial_size(); }
43 
44  template <>
45  inline size_t serial_size(const uint8_t& b)
46  { return sizeof(b); }
47 
48  template <>
49  inline size_t serial_size(const uint16_t& b)
50  { return sizeof(b); }
51 
52  template <>
53  inline size_t serial_size(const uint32_t& b)
54  { return sizeof(b); }
55 
56  template <>
57  inline size_t serial_size(const uint64_t& b)
58  { return sizeof(b); }
59 
60  /* Should not be used directly! */
61  template <typename TO, typename FROM>
62  inline size_t
63  __private_serialize(const FROM& f, void* const buf, size_t const buflen,
64  size_t const offset)
65  {
66  GU_COMPILE_ASSERT(std::numeric_limits<TO>::is_integer, not_integer1);
67  GU_COMPILE_ASSERT(std::numeric_limits<FROM>::is_integer, not_integer2);
68  GU_COMPILE_ASSERT(sizeof(FROM) == sizeof(TO), size_differs);
69  size_t const ret = offset + sizeof(TO);
70  if (gu_unlikely(ret > buflen))
71  {
72  gu_throw_error(EMSGSIZE) << ret << " > " << buflen;
73  }
74  void* const pos(reinterpret_cast<byte_t*>(buf) + offset);
75  *reinterpret_cast<TO*>(pos) = htog<TO>(f);
76  return ret;
77  }
78 
79  /* Should not be used directly! */
80  template <typename FROM, typename TO>
81  inline size_t
82  __private_unserialize(const void* const buf, size_t const buflen,
83  size_t const offset, TO& t)
84  {
85  GU_COMPILE_ASSERT(std::numeric_limits<TO>::is_integer, not_integer1);
86  GU_COMPILE_ASSERT(std::numeric_limits<FROM>::is_integer, not_integer2);
87  GU_COMPILE_ASSERT(sizeof(FROM) == sizeof(TO), size_differs);
88  size_t const ret = offset + sizeof(t);
89  if (gu_unlikely(ret > buflen))
90  {
91  gu_throw_error(EMSGSIZE) << ret << " > " << buflen;
92  }
93  const void* const pos(reinterpret_cast<const byte_t*>(buf) + offset);
94  t = gtoh<FROM>(*reinterpret_cast<const FROM*>(pos));
95  return ret;
96  }
97 
98  template <typename T>
99  GU_FORCE_INLINE size_t serialize1(const T& t,
100  void* const buf,
101  size_t const buflen,
102  size_t const offset)
103  {
104  return __private_serialize<uint8_t>(t, buf, buflen, offset);
105  }
106 
107  template <typename T>
108  GU_FORCE_INLINE size_t unserialize1(const void* const buf,
109  size_t const buflen,
110  size_t const offset,
111  T& t)
112  {
113  return __private_unserialize<uint8_t>(buf, buflen, offset, t);
114  }
115 
116  template <typename T>
117  GU_FORCE_INLINE size_t serialize2(const T& t,
118  void* const buf,
119  size_t const buflen,
120  size_t const offset)
121  {
122  return __private_serialize<uint16_t>(t, buf, buflen, offset);
123  }
124 
125  template <typename T>
126  GU_FORCE_INLINE size_t unserialize2(const void* const buf,
127  size_t const buflen,
128  size_t const offset,
129  T& t)
130  {
131  return __private_unserialize<uint16_t>(buf, buflen, offset, t);
132  }
133 
134  template <typename T>
135  GU_FORCE_INLINE size_t serialize4(const T& t,
136  void* const buf,
137  size_t const buflen,
138  size_t const offset)
139  {
140  return __private_serialize<uint32_t>(t, buf, buflen, offset);
141  }
142 
143  template <typename T>
144  GU_FORCE_INLINE size_t unserialize4(const void* const buf,
145  size_t const buflen,
146  size_t const offset,
147  T& t)
148  {
149  return __private_unserialize<uint32_t>(buf, buflen, offset, t);
150  }
151 
152  template <typename T>
153  GU_FORCE_INLINE size_t serialize8(const T& t,
154  void* const buf,
155  size_t const buflen,
156  size_t const offset)
157  {
158  return __private_serialize<uint64_t>(t, buf, buflen, offset);
159  }
160 
161  template <typename T>
162  GU_FORCE_INLINE size_t unserialize8(const void* const buf,
163  size_t const buflen,
164  size_t const offset,
165  T& t)
166  {
167  return __private_unserialize<uint64_t>(buf, buflen, offset, t);
168  }
169 
170  template <typename ST>
171  inline size_t __private_serial_size(const Buffer& sb)
172  {
173  GU_COMPILE_ASSERT(std::numeric_limits<ST>::is_integer, must_be_integer);
174  if (sb.size() > std::numeric_limits<ST>::max())
175  gu_throw_error(ERANGE) << sb.size() << " unrepresentable in "
176  << sizeof(ST) << " bytes.";
177  return sizeof(ST) + sb.size();
178  }
179 
180  GU_FORCE_INLINE size_t serial_size1(const Buffer& sb)
181  {
182  return __private_serial_size<uint8_t>(sb);
183  }
184 
185  GU_FORCE_INLINE size_t serial_size2(const Buffer& sb)
186  {
187  return __private_serial_size<uint16_t>(sb);
188  }
189 
190  GU_FORCE_INLINE size_t serial_size4(const Buffer& sb)
191  {
192  return __private_serial_size<uint32_t>(sb);
193  }
194 
195  GU_FORCE_INLINE size_t serial_size8(const Buffer& sb)
196  {
197  return __private_serial_size<uint64_t>(sb);
198  }
199 
200  template <typename ST>
201  inline size_t __private_serialize(const Buffer& b,
202  void* const buf,
203  size_t const buflen,
204  size_t offset)
205  {
206  size_t const ret = offset + __private_serial_size<ST>(b);
207 
208  if (ret > buflen)
209  {
210  gu_throw_error(EMSGSIZE) << ret << " > " << buflen;
211  }
212 
213  offset = __private_serialize<ST>(static_cast<ST>(b.size()),
214  buf, buflen, offset);
215  copy(b.begin(), b.end(), reinterpret_cast<byte_t*>(buf) + offset);
216  return ret;
217  }
218 
219  template <typename ST>
220  inline size_t __private_unserialize(const void* const buf,
221  size_t const buflen,
222  size_t offset,
223  Buffer& b)
224  {
225  GU_COMPILE_ASSERT(std::numeric_limits<ST>::is_integer, must_be_integer);
226  ST len(0);
227  size_t ret = offset + sizeof(len);
228 
229  if (ret > buflen) gu_throw_error(EMSGSIZE) << ret << " > " << buflen;
230 
231  offset = __private_unserialize<ST>(buf, buflen, offset, len);
232  ret += len;
233 
234  if (ret > buflen) gu_throw_error(EMSGSIZE) << ret << " > " << buflen;
235 
236  b.resize(len);
237  const byte_t* const ptr(reinterpret_cast<const byte_t*>(buf));
238  copy(ptr + offset, ptr + ret, b.begin());
239 
240  return ret;
241  }
242 
243  GU_FORCE_INLINE size_t serialize1(const Buffer& b,
244  void* const buf,
245  size_t const buflen,
246  size_t const offset)
247  {
248  return __private_serialize<uint8_t>(b, buf, buflen, offset);
249  }
250 
251  GU_FORCE_INLINE size_t unserialize1(const void* const buf,
252  size_t const buflen,
253  size_t const offset,
254  Buffer& b)
255  {
256  return __private_unserialize<uint8_t>(buf, buflen, offset, b);
257  }
258 
259  GU_FORCE_INLINE size_t serialize2(const Buffer& b,
260  void* const buf,
261  size_t const buflen,
262  size_t const offset)
263  {
264  return __private_serialize<uint16_t>(b, buf, buflen, offset);
265  }
266 
267  GU_FORCE_INLINE size_t unserialize2(const void* const buf,
268  size_t const buflen,
269  size_t const offset,
270  Buffer& b)
271  {
272  return __private_unserialize<uint16_t>(buf, buflen, offset, b);
273  }
274 
275  GU_FORCE_INLINE size_t serialize4(const Buffer& b,
276  void* const buf,
277  size_t const buflen,
278  size_t const offset)
279  {
280  return __private_serialize<uint32_t>(b, buf, buflen, offset);
281  }
282 
283  GU_FORCE_INLINE size_t unserialize4(const void* const buf,
284  size_t const buflen,
285  size_t const offset,
286  Buffer& b)
287  {
288  return __private_unserialize<uint32_t>(buf, buflen, offset, b);
289  }
290 
291  GU_FORCE_INLINE size_t serialize8(const Buffer& b,
292  void* const buf,
293  size_t const buflen,
294  size_t const offset)
295  {
296  return __private_serialize<uint64_t>(b, buf, buflen, offset);
297  }
298 
299  GU_FORCE_INLINE size_t unserialize8(const void* const buf,
300  size_t const buflen,
301  size_t const offset,
302  Buffer& b)
303  {
304  return __private_unserialize<uint64_t>(buf, buflen, offset, b);
305  }
306 
307 } // namespace gu
308 
309 #endif // GU_SERIALIZE_HPP