Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
unpack_array.h
Go to the documentation of this file.
1 /// @file detail/unpack_array.h
2 ///
3 /// A specialization to unpack a raw buffer of bytes into an array.
4 ///
5 /// The MIT License(MIT)
6 /// @copyright 2014 Paul M Watt
7 // ****************************************************************************
8 #ifndef UNPACK_ARRAY_H_INCLUDED
9 #define UNPACK_ARRAY_H_INCLUDED
10 // Private Usage Include Guard ************************************************
11 // Only allow this header file to be included through unpack_message.h
12 #ifndef UNPACK_MESSAGE_H_INCLUDED
13 # error Do not include this file directly. Use <detail/unpack_message.h> instead
14 #endif
15 
16 namespace Hg
17 {
18 
19 namespace detail
20 {
21 // Forward Declarations *******************************************************
22 // ****************************************************************************
23 template< typename T,
24  size_t N,
25  typename BufferT
26  >
27 size_t DeserializeInBulk( std::array<T,N>&, BufferT&, size_t);
28 
29 // ****************************************************************************
30 template< typename T,
31  size_t N,
32  typename BufferT
33  >
34 size_t DeserializeByItem( std::array<T,N>&, BufferT&, size_t);
35 
36 // ****************************************************************************
37 // Adapter function to simplify deserializing a buffer from a vector-field.
38 //
39 template< class T,
40  class A,
41  class BufferT,
42  template <typename, typename> class VectorT
43  >
44 size_t DeserializeVector (VectorT<T, A> &value,
45  size_t count,
46  BufferT &buffer,
47  size_t offset);
48 
49 // ****************************************************************************
50 template< class T,
51  size_t N,
52  class BufferT,
53  template <typename, size_t> class ArrayT
54  >
55 size_t DeserializeArray ( ArrayT<T, N> &value,
56  BufferT &buffer,
57  size_t offset);
58 
59 
60 // ****************************************************************************
61 // Array Implementation *******************************************************
62 namespace Array
63 {
64 
65 // ****************************************************************************
66 // Imports data from the array for fixed-size POD types.
67 //
68 template< typename ArrayT,
69  typename BufferT,
70  typename TraitT
71  >
72 struct Deserializer
73 {
74  typedef ArrayT array_type;
75 
76  typedef typename
77  array_type::value_type value_type;
78 
79  typedef BufferT buffer_type;
80 
81  typedef TraitT data_type_trait;
82 
83  static
84  const size_t value = Hg::detail::array_size<array_type>::value;
85 
86  // **************************************************************************
87  size_t Read ( array_type &value,
88  size_t count,
89  buffer_type &buffer,
90  size_t offset)
91  {
92  if (0 == count)
93  {
94  return 0;
95  }
96 
97  // Calculate the size of data to write in bytes.
98  size_t size = count * sizeof(value_type);
99 
100  value_type *pFirst = &value[0];
101  return buffer.get_range(pFirst, size, offset);
102  }
103 
104 
105  // **************************************************************************
106  size_t Read ( value_type &value,
107  buffer_type &buffer,
108  size_t offset)
109  {
110  return buffer.get_data( value, offset);
111  }
112 
113 };
114 
115 
116 // ****************************************************************************
117 // Imports an array of bit-list fields.
118 //
119 template< typename T,
120  size_t N,
121  typename BufferT
122  >
123 struct Deserializer <Hg::BitFieldArray<T,N>, BufferT, packed_trait>
124  : public std::integral_constant<size_t, N>
125 {
126  typedef Hg::BitFieldArray<T,N> array_type;
127  typedef typename
128  array_type::value_type value_type;
129  typedef BufferT buffer_type;
130  typedef packed_trait data_type_trait;
131 
132  // **************************************************************************
133  size_t Read ( array_type &value,
134  size_t count,
135  buffer_type &buffer,
136  size_t offset)
137  {
138  if (0 == count)
139  {
140  return 0;
141  }
142 
143  // Calculate the size of data to write in bytes.
144  size_t size = count * sizeof(value_type);
145 
146  value_type *pFirst = &(value[0].value());
147 
148  return buffer.get_range(pFirst, size, offset);
149  }
150 
151  // **************************************************************************
152  size_t Read ( value_type &value,
153  buffer_type &buffer,
154  size_t offset)
155  {
156  return buffer.get_data( value, offset);
157  }
158 };
159 
160 
161 // ****************************************************************************
162 // Imports an array of nested types with each sub-item written individually.
163 //
164 template< typename T,
165  size_t N,
166  typename BufferT
167  >
168 struct Deserializer <std::array<T,N>, BufferT, nested_trait>
169  : public std::integral_constant<size_t, N>
170 {
171  typedef std::array<T,N> array_type;
172  typedef T value_type;
173  typedef BufferT buffer_type;
174  typedef nested_trait data_type_trait;
175 
176  // **************************************************************************
177  size_t Read ( array_type &value,
178  size_t count,
179  buffer_type &buffer,
180  size_t offset)
181  {
182  if (0 == count)
183  {
184  return 0;
185  }
186 
187  size_t bytes_read = 0;
188 
189  // Process each item individually.
190  for (size_t index = 0; index < count; ++index)
191  {
192  // The offset for each item progressively increases
193  // by the number of bytes read from the input buffer.
194  size_t item_offset = offset + bytes_read;
195 
196  bytes_read += Read(value[index], buffer, item_offset);
197  }
198 
199  return bytes_read;
200  }
201 
202  // **************************************************************************
203  size_t Read ( value_type &value,
204  buffer_type &buffer,
205  size_t offset)
206  {
207  // An important typedef for selecting the proper
208  // version of the unpack function for the sub-elements.
209  typedef typename
210  message_size_trait<typename value_type::format_type>::type size_trait;
211 
212  return unpack_message< value_type,
213  buffer_type,
214  size_trait
215  >(value, buffer, offset);
216  }
217 };
218 
219 
220 
221 // ****************************************************************************
222 // Imports a array of arrays with each sub-item written individually.
223 //
224 template< class T,
225  size_t N,
226  class BufferT
227  >
228 struct Deserializer <std::array<T,N>, BufferT, array_trait>
229  : public std::integral_constant<size_t, N>
230 {
231  typedef std::array<T,N> array_type;
232 
233  typedef typename
234  array_type::value_type value_type;
235 
236  typedef BufferT buffer_type;
237 
238  // The next step discriminates on the value_type managed
239  // by the array to select the most efficient and correct
240  // method of deserializing the data.
241  typedef typename
243  < value_type >::type data_type_trait;
244 
245  // **************************************************************************
246  size_t Read ( array_type &value,
247  size_t count,
248  buffer_type &buffer,
249  size_t offset)
250  {
251  return DeserializeByItem(value, buffer, offset);
252  }
253 
254  // **************************************************************************
255 template< class SubT,
256  size_t SubN,
257  class buffer_type,
258  template <class, size_t> class ArrayT
259  >
260  size_t Read ( ArrayT<SubT,SubN> &value,
261  buffer_type &buffer,
262  size_t offset)
263  {
264  typedef
265  ArrayT<SubT,SubN> sub_array_type;
266  typedef typename
267  sub_array_type::value_type data_type;
268 
269  const size_t k_sub_count = Hg::detail::array_size<sub_array_type>::value;
270 
271  // Since this is the array handler,
272  // all single value entries passed in will
273  // be arrays themselves.
274  // Recurse, and start a new decomposition
275  // of array deserialization.
276  size_t bytes_written =
277  DeserializeArray( value, buffer, offset);
278 
279  return bytes_written;
280  }
281 };
282 
283 // ****************************************************************************
284 // Imports a array of vectors with each sub-item written individually.
285 //
286 template< typename T,
287  size_t N,
288  typename BufferT
289  >
290 struct Deserializer <std::array<T,N>, BufferT, vector_trait>
291  : public std::integral_constant<size_t, N>
292 {
293  typedef std::array<T,N> array_type;
294  typedef T value_type;
295  typedef BufferT buffer_type;
296 
297  // The next step discriminates on the value_type managed
298  // by the array to select the most efficient and correct
299  // method of deserializing the data.
300  typedef typename
302  < value_type >::type data_type_trait;
303 
304  // **************************************************************************
305  size_t Read ( array_type &value,
306  size_t count,
307  buffer_type &buffer,
308  size_t offset)
309  {
310  return DeserializeByItem(value, count, buffer, offset);
311  }
312 
313  // **************************************************************************
314  size_t Read ( value_type &value,
315  buffer_type &buffer,
316  size_t offset)
317  {
318  typedef typename
319  value_type::value_type data_type;
320 
321  // Since this is the vector handler,
322  // all single value entries passed in will
323  // be vectors themselves.
324  size_t bytes_written =
325  DeserializeVector< data_type,
326  buffer_type
327  >(value, value.size(), buffer, offset);
328 
329  return bytes_written;
330  }
331 };
332 
333 } // namespace Array
334 
335 // **************************************************************************
336 // This version reads all of the items to the buffer at once.
337 //
338 template< class T,
339  size_t N,
340  class BufferT
341  >
342 size_t DeserializeInBulk( std::array<T,N> &value,
343  BufferT &buffer,
344  size_t offset)
345 {
346  typedef std::array<T,N> array_type;
347 
348  typedef typename
349  array_type::value_type data_type;
350 
351  // The next step discriminates on the value_type managed
352  // by the vector to select the most efficient and correct
353  // method of deserializing the data.
354  typedef typename
356  < data_type >::type data_type_trait;
357 
358  typedef
359  Array::Deserializer
360  < array_type,
361  BufferT,
362  data_type_trait> deserializer_t;
363 
364  const size_t k_count = value.size();
365  deserializer_t deserializer;
366  size_t bytes_written = 0;
367 
368  // TODO: (Optimiztion) Return and add this optimization for bulk reads if possible.
369  // Process each item individually.
370  for (size_t index = 0; index < k_count; ++index)
371  {
372  // The offset for each item progressively increases
373  // by the number of bytes read from the input buffer.
374  size_t item_offset = offset + bytes_written;
375 
376  // Export sub-values one item at a time.
377  size_t read_len =
378  deserializer.Read( value[index], buffer, item_offset);
379 
380  bytes_written += read_len;
381  }
382 
383  return bytes_written;
384 }
385 
386 
387 // **************************************************************************
388 // This version reads each item from the raw buffer individually.
389 // These fields may be because they are distinct fields of a nested definition,
390 // or variable length items.
391 //
392 // ValueT Must be a type that contains a sub-type defined as value_type.
393 // Such as std::vector or std::array
394 //
395 template< class T,
396  size_t N,
397  class BufferT
398  >
399 size_t DeserializeByItem( std::array<T,N> &value,
400  BufferT &buffer,
401  size_t offset)
402 {
403  typedef std::array<T,N> array_type;
404 
405  typedef typename
406  array_type::value_type data_type;
407 
408  // The next step discriminates on the value_type managed
409  // by the vector to select the most efficient and correct
410  // method of deserializing the data.
411  typedef typename
413  < data_type >::type data_type_trait;
414 
415  Array::Deserializer < data_type,
416  BufferT,
417  data_type_trait> deserializer;
418 
419  size_t bytes_written = 0;
420 
421  // Process each item individually.
422  for (size_t index = 0; index < N; ++index)
423  {
424  // The offset for each item progressively increases
425  // by the number of bytes read from the input buffer.
426  size_t item_offset = offset + bytes_written;
427 
428  // Export sub-values one item at a time.
429  size_t read_len =
430  deserializer.Read( value[index], buffer, item_offset);
431 
432  bytes_written += read_len;
433  }
434 
435  return bytes_written;
436 }
437 
438 // ****************************************************************************
439 // Adapter function to simplify deserializing a buffer from an array-field.
440 //
441 template< class T,
442  size_t N,
443  class BufferT,
444  template <typename, size_t> class ArrayT
445  >
446 size_t DeserializeArray ( ArrayT<T, N> &value,
447  BufferT &buffer,
448  size_t offset)
449 {
450  // The next step discriminates on the value_type managed
451  // by the vector to select the most efficient and correct
452  // method of deserializing the data.
453  typedef ArrayT<T,N> array_type;
454 
455  typedef T value_type;
456 
457  typedef typename
459  < value_type >::type value_type_trait;
460 
461  // Define the correct type of deserialize functor
462  // based on the type contained within the vector.
463  typedef Array::Deserializer < array_type,
464  BufferT,
465  value_type_trait
466  > deserializer_t;
467 
468  deserializer_t deserializer;
469  return deserializer.Read(value, N, buffer, offset);
470 }
471 
472 // ****************************************************************************
473 // A specialized functor to read array types.
474 //
475 // @tparam IdxT [size_t] The index of the field to read.
476 // @tparam MsgT [typename] The message defintition used to parse the
477 // buffer.
478 // @tparam BufferT [typename] The buffer type that provides the data
479 // to read into the message.
480 //
481 template< size_t IdxT,
482  typename MsgT,
483  typename BufferT
484  >
485 struct UnpackDatum< IdxT,
486  MsgT,
487  BufferT,
488  array_trait>
489 {
490  // Typedefs *****************************************************************
491  typedef typename
493  < IdxT,
494  typename MsgT::format_type
495  >::type proxy_type;
496 
497  typedef typename
498  proxy_type::value_type value_type;
499  typedef typename
500  value_type::value_type data_type;
501 
502  typedef typename
504  < data_type >::type data_type_trait;
505 
506 
507  // **************************************************************************
508  // Reads a dynamically-size field from the specified buffer.
509  //
510  // @param msg The message object to accept the data to be read.
511  // @param buffer The buffer object to read from.
512  // @param dynamic_offset An additional offset for messages with dynamically
513  // sized fields. The length of the dynamic field read
514  // will be added to this input value to report how much
515  // larger the message has become.
516  //
517  void operator()( MsgT &msg,
518  const BufferT &buffer,
519  size_t &dynamic_offset)
520  {
522  + dynamic_offset;
523 
524  // Read directly into the output array.
525  size_t bytes_read =
526  DeserializeArray(msg.template FieldAt<IdxT>().get(), buffer, offset);
527 
528  dynamic_offset += bytes_read;
529  }
530 };
531 
532 } // namespace detail
533 
534 } // namespace Hg
535 
536 #endif