Alchemy  1.0
A framework to robustly process network messages and structured data
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
message_dynamic_detail.h
Go to the documentation of this file.
1 /// @file message_dynamic_detail.h
2 ///
3 /// Internal details for the implementation of a dynamic message size query.
4 ///
5 /// The MIT License(MIT)
6 /// @copyright 2014 Paul M Watt
7 // ****************************************************************************
8 #ifndef MESSAGE_DYNAMIC_DETAIL_H_INCLUDED
9 #define MESSAGE_DYNAMIC_DETAIL_H_INCLUDED
10 // Includes *******************************************************************
11 #include <Pb/dynamic.h>
12 #include <Pb/meta_foreach.h>
13 #include <Pb/type_at.h>
14 #include <Hg/deduce_type_trait.h>
15 
16 namespace Hg
17 {
18 
19 namespace detail
20 {
21 
22 // Forward Declarations *******************************************************
23 // ****************************************************************************
24 template< typename MsgT,
25  bool IsDynamicT
26  >
27 struct DynamicSizeWorker;
28 
29 
30 // ****************************************************************************
31 /// Determines the number of bytes required to serialize a vector.
32 ///
33 template< class T,
34  class A,
35  class TypeTraitT
36  >
38 {
39  // **************************************************************************
40  template< class TypeT,
41  class AllocT,
42  template <class, class> class VectorT
43  >
44  size_t operator()(const VectorT<TypeT,AllocT>& field)
45  {
46  return field.size() * sizeof(TypeT);
47  }
48 };
49 
50 namespace nested
51 {
52 
53 // ****************************************************************************
54 // Returns the size of a vector that contains a dynamically-sized nested type.
55 //
56 template< class T,
57  class A,
58  bool HasDynamicT
59  >
60 struct HelperSizeOfVector
61 {
62  static size_t size(const std::vector<T,A>& field)
63  {
64  size_t total_size = 0;
65 
66  // This specialization represents vectors of nested traits.
67  // Therefore, T must have a defined format_type.
68  const size_t k_fixed_size = Hg::SizeOf<typename T::format_type>::value;
69 
70  for (size_t index = 0; index < field.size(); ++index)
71  {
72  // Type T is the MsgT parameter of a message definition.
73  // Therefore there will be a format_type that can be used
74  // to tag dispatch this variation of the DynamicSizeWorker.
75  //
76  // Add both the fixed-size as well as the actual dynamic-size.
77  total_size += k_fixed_size
78  + DynamicSizeWorker<T, true>().size(field[index]);
79  }
80 
81  return total_size;
82  }
83 };
84 
85 // ****************************************************************************
86 // Returns the size of a vector that contains a fixed-size nested type.
87 //
88 template< class T,
89  class A
90  >
91 struct HelperSizeOfVector <T, A, false>
92 {
93  static size_t size(const std::vector<T,A>& field)
94  {
95  return field.size() * Hg::SizeOf<typename T::format_type>::value;
96  }
97 };
98 
99 } // namespace nested
100 
101 // ****************************************************************************
102 /// Determines the number of bytes required to serialize a vector.
103 /// This version handles a vector with sub-messages.
104 ///
105 template< class T,
106  class A
107  >
109 {
110  // **************************************************************************
111  size_t operator()(const std::vector<T,A>& field)
112  {
113  typedef typename
114  T::format_type format_type;
115 
116  return nested::HelperSizeOfVector<T, A, has_dynamic<format_type>::value>::size(field);
117  }
118 };
119 
120 // ****************************************************************************
121 /// Determines the number of bytes required to serialize a vector.
122 /// This version handles a vector with variable-length types.
123 ///
124 template< typename T,
125  typename A
126  >
128 {
129  // **************************************************************************
130  size_t operator()(const std::vector<T,A>& field)
131  {
132  size_t total_size = 0;
133 
134  SizeOfVector< typename T::value_type,
135  typename T::allocator_type,
137  > Size;
138 
139  for (size_t index = 0; index < field.size(); ++index)
140  {
141  total_size += Size(field[index]);
142  }
143 
144  return total_size;
145  }
146 };
147 
148 // ****************************************************************************
149 /// Reports the total dynamic size of vector of bit-fields for this item.
150 ///
151 template< class T,
152  class A
153  >
154 size_t dynamic_size(const Hg::BitFieldVector<T,A>& field)
155 {
156  return field.size() * Hg::SizeOf<T>::value;
157 }
158 
159 // ****************************************************************************
160 /// Reports the total size of the dynamic buffers required for this message.
161 ///
162 template< class T,
163  class A
164  >
165 size_t dynamic_size(const std::vector<T,A>& field)
166 {
167  SizeOfVector<T,A, typename DeduceTypeTrait<T>::type> Size;
168  return Size(field);
169 }
170 
171 // ****************************************************************************
172 /// Catch all implementation that returns 0 dynamic size.
173 ///
174 template <typename T>
175 size_t dynamic_size(const T& field)
176 {
177  return 0;
178 }
179 
180 // ****************************************************************************
181 template< typename MsgT >
182 struct DynamicSizeFunctor
183 {
184  // Typedefs *****************************************************************
185  typedef MsgT message_type;
186  typedef typename
187  message_type::format_type format_type;
188 
189  typedef typename
190  dynamic_fields<format_type>::type dynamic_field_indices;
191 
192  // Data Members *************************************************************
193  const message_type &message;
194  size_t m_dynamic_size;
195 
196  // **************************************************************************
197  /// Value constructor that initializes the input message being queried.
198  ///
199  /// @param rhs The Message object that contains the specified data.
200  ///
201  explicit
202  DynamicSizeFunctor(const message_type& rhs)
203  : message(rhs)
204  , m_dynamic_size(0)
205  { }
206 
207  // **************************************************************************
208  /// Parameterized function operator
209  ///
210  /// Reports the dynamic size of the requested field.
211  ///
212  /// @paramt size_t Parameterized value that specifies the index
213  /// of the data field to be converted.
214  /// @paramt value_type [typename] A discriminator type for disambiguation.
215  /// @param unnamed An unused variable to disambiguate the appropriate
216  /// specialization function for the compiler to select.
217  ///
218  template< size_t IdxT,
219  typename value_t
220  >
221  void operator()(const value_t*)
222  {
223  typedef typename
225  format_type>::type proxy_type;
226  typedef typename
227  proxy_type::value_type value_type;
228 
229  message_type &msg = const_cast<message_type&>(message);
230  value_type &value = msg.template FieldAt<IdxT>().get();
231  m_dynamic_size += dynamic_size(value);
232  }
233 
234  // **************************************************************************
235  /// Returns the dynamic size calculated by the functor.
236  ///
237  size_t size()
238  {
239  return m_dynamic_size;
240  }
241 };
242 
243 
244 
245 // ****************************************************************************
246 ///
247 ///
248 template< typename MsgT,
249  bool IsDynamicT
250  >
251 struct DynamicSizeWorker
252 {
253  static
254  size_t size(const MsgT& msg)
255  {
256  typedef MsgT message_type;
257  typedef typename
258  message_type::format_type format_type;
259 
260  // Initialize a functor to query for the dynamic size of each field.
261  detail::DynamicSizeFunctor< message_type > ftor(msg);
262  Hg::ForEachType < 0,
264  format_type
265  > (ftor);
266 
267  return ftor.size();
268  }
269 };
270 
271 // ****************************************************************************
272 /// Specialization that does not request dynamic size values for non-dynamic msgs.
273 ///
274 template< typename MsgT >
275 struct DynamicSizeWorker<MsgT, false>
276 {
277  static
278  size_t size(const MsgT& msg)
279  {
280  return 0;
281  }
282 };
283 
284 
285 } // namespace detail
286 
287 } // namespace Hg
288 
289 #endif