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