OpenSDN source code
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
proto_impl.h
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #ifndef __BASE_PROTO_IMPL_H__
6 #define __BASE_PROTO_IMPL_H__
7 
8 #include <vector>
9 
10 namespace detail {
11 
12 extern bool debug_;
13 #define PROTO_DEBUG(args...) if (detail::debug_) LOG(DEBUG, ##args)
14 
15 template <typename T>
16 struct ApplySetter {
17  template <typename U>
18  void operator()(const uint8_t *data, int element_size, U *obj) {
19  int value = get_value(data, element_size);
20  T::set(obj, value);
21  }
22 };
23 
24 template <>
25 struct ApplySetter<void> {
26  void operator()(const uint8_t *data, int element_size, void *obj) {
27  }
28 };
29 
30 template <typename T>
31 struct ApplyGetter {
32  template <typename U>
33  void operator()(uint8_t *data, int element_size, U *obj) {
34  uint64_t value = T::get(obj);
35  put_value(data, element_size, value);
36  }
37 };
38 template <>
39 struct ApplyGetter<void> {
40  template <typename U>
41  void operator()(uint8_t *data, int element_size, U *obj) {
42  memset(data, 0, element_size);
43  }
44 };
45 
46 template <typename Accessor, typename T>
48  template <typename Iterator>
49  int Copy(Iterator begin, Iterator end, uint8_t *data) {
50  int count = 0;
51  for (Iterator iter = begin; iter != end; ++iter) {
52  put_value(data, sizeof(*iter), *iter);
53  data += sizeof(*iter);
54  count+= sizeof(*iter);
55  }
56  return count;
57  }
58  int operator()(uint8_t *data, int element_size, T *obj) {
59  int count = Copy(Accessor::begin(obj), Accessor::end(obj), data);
60  return count;
61  }
62 };
63 template <typename T>
64 struct VariableLengthWriter<void, T> {
65  int operator()(uint8_t *data, int element_size, T *obj) {
66  return 0;
67  }
68 };
69 
70 template <typename P, typename C>
71 struct ContextPush {
72  C * operator()(ParseContext *context, P *obj) {
73  C *child_obj = new C;
74  context->Push(child_obj);
75  return child_obj;
76  }
77 };
78 template <typename P>
79 struct ContextPush<P, void> {
80  P *operator()(ParseContext *context, P *obj) {
81  context->ReleaseData();
82  context->Push(obj);
83  return obj;
84  }
85 };
86 
87 template <>
88 struct ContextPush<void, void> {
89  void *operator()(ParseContext *context, void *obj) {
90  return obj;
91  }
92 };
93 template <typename T>
94 struct NoContextPush {
95  T *operator()(ParseContext *context, T *obj) {
96  return obj;
97  }
98 };
99 
100 template<typename T, typename ChildContextType>
101 struct StoreContext {
102  template <typename C>
103  void operator()(C *obj, ParseObject *context_obj) {
104  ChildContextType *child_obj =
105  dynamic_cast<ChildContextType *>(context_obj);
106  assert(child_obj);
107  T::insert(obj, child_obj);
108  }
109 };
110 
111 template <typename ChildContextType>
112 struct StoreContext<void, ChildContextType> {
113  void operator()(void *obj, ParseObject *child_obj) {
114  delete child_obj;
115  }
116 };
117 
118 template <typename Parent, typename T, typename ChildContextType>
119 struct ContextPop {
120  void operator()(ParseContext *context, T *obj) {
122  storer(obj, context->Pop());
123  }
124 };
125 
126 template<typename Parent, typename T>
127 struct ContextPop<Parent, T, void> {
128  void operator()(ParseContext *context, void *obj) {
129  context->SwapData(context->Pop());
130  }
131 };
132 
133 template<typename Parent>
134 struct ContextPop<Parent, void, void> {
135  void operator()(ParseContext *context, void *obj) {
136  }
137 };
138 
139 // If the child's ContextType is void the obj is copied to child_obj.
140 template <typename Child, typename T, typename opt_ctx_t>
142  opt_ctx_t *operator()(ParseContext *context, T *obj) {
144  return pushfn(context, obj);
145  }
146 };
147 
148 template <typename Child, typename T>
149 struct DescendentContextPush<Child, T, void>
150  {
151  typedef T ctx_t;
152  typedef void pctx_t;
153  T *operator()(ParseContext *context, T *obj) {
154  return obj;
155  }
156 };
157 template <typename Child>
159  typedef typename Child::ContextType ctx_t;
160  template <typename U>
161  ctx_t *operator()(ParseContext *context, U *obj) {
162  typedef typename Child::ContextSwap swap_t;
163  ctx_t *nobj = swap_t()(obj);
164  if (nobj == NULL) {
165  // TODO:
166  }
167  if (nobj != obj) {
168  context->SwapData(nobj);
169  }
170  return nobj;
171  }
172 };
173 
174 template <class Parent, typename Child>
176  template <typename T>
177  static int Parse(const uint8_t *data, size_t size, ParseContext *context,
178  T *obj) {
179  // If the child defines ContextType, this changes the type of the
180  // top of stack element and causes us to push a new context into the
181  // stack.
182  // Context push and pop is only relevant if the child doesn't
183  // define a context swap. If it does, the swap operation will
184  // replace the existing stack frame data object.
185  typedef typename Child::ContextType opt_ctx_t;
186 
187  typedef typename boost::mpl::if_<
188  boost::is_same<opt_ctx_t, void>,
189  T, opt_ctx_t>::type ctx_t;
190 
191  typedef typename boost::mpl::if_<
192  boost::is_same<typename Child::ContextSwap, void>,
194  DescendentContextSwap<Child> >::type context_op_t;
195 
196  ctx_t *child_obj = context_op_t()(context, obj);
197 
198  int result = Child::Parse(data, size, context, child_obj);
199  if (result < 0) return result;
200  typedef typename boost::mpl::if_<
201  boost::is_same<typename Child::ContextSwap, void>,
202  opt_ctx_t,
203  void>::type push_ctx_t;
204  typedef typename boost::mpl::if_<
205  boost::is_same<push_ctx_t, void>,
206  void, T>::type pctx_t;
208  popfn(context, obj);
209  return result;
210  }
211 };
212 
213 template <typename T, typename Context>
215  int operator()(ParseContext *context, const uint8_t *data, size_t size,
216  size_t msgsize, Context *obj) {
217  T t;
218  int value = t(obj, data, size);
219  context->set_lensize(size);
220  if ((size_t) value > msgsize) {
221  PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
222  << value << " > " << msgsize);
223  return -1;
224  }
225  context->set_size(value);
226  return 0;
227  }
228 };
229 
230 template <typename Context>
231 struct SequenceLengthSetter<int, Context> {
232  int operator()(ParseContext *context, const uint8_t *data, size_t size,
233  size_t msgsize, Context *obj) {
234  int value = get_value(data, size);
235  context->set_lensize(size);
236  if ((size_t) value > msgsize) {
237  PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
238  << value << " > " << msgsize);
239  return -1;
240  }
241  context->set_size(value);
242  return 0;
243  }
244 };
245 
246 template <typename Context>
247 struct SequenceLengthSetter<void, Context> {
248  int operator()(ParseContext *context, const uint8_t *data, size_t size,
249  size_t msgsize, Context *obj) {
250  return 0;
251  }
252 };
253 
254 template<typename T>
257  uint8_t *data, int arg) {
258  context->AddCallback(cb, data, arg);
259  }
260 };
261 template<>
264  uint8_t *data, int arg) {
265  }
266 };
267 
268 template<typename Accessor, typename T>
270  int operator()(const uint8_t *data, size_t size, ParseContext *context,
271  T *obj) {
272  int element_size = context->size();
273  // If element size is unknown, read till the end of buffer
274  if (element_size < 0) element_size = size;
275  else if (size < (size_t) element_size) {
276  PROTO_DEBUG(TYPE_NAME(T) << " Variable Length Setter failed "
277  << size << " < " << element_size);
278  return -1;
279  }
280  Accessor::set(obj, data, element_size);
281  return element_size;
282  }
283 };
284 template<typename T>
285 struct VariableLengthSetter<void, T> {
286  int operator()(const uint8_t *data, size_t size, ParseContext *context,
287  T *obj) {
288  return 0;
289  }
290 };
291 
292 template<typename SizeSetter, typename T>
294  int operator()(const uint8_t *data, size_t size, ParseContext *context,
295  T *obj) {
296  return SizeSetter::get(obj);
297  }
298 };
299 
300 template<typename Derived, typename T>
302  int operator()(const uint8_t *data, size_t size, ParseContext *context,
303  T *obj) {
304  typedef typename Derived::Setter setter_t;
306  setter(data, Derived::kSize, obj);
307  return Derived::kSize;
308  }
309 };
310 
311 template<typename Derived, typename T>
312 struct NopSetter {
313  int operator()(const uint8_t *data, size_t size, ParseContext *context,
314  T *obj) {
315  return Derived::kSize;
316  }
317 };
318 
319 template <typename Derived>
320 struct SizeComparer {
321  bool operator()(int size) {
322  return size >= Derived::kSize;
323  }
324 };
325 
326 struct NopComparer {
327  bool operator()(int size) {
328  return true;
329  }
330 };
331 
332 template <typename Setter, typename T>
334  static int get(const T *msg) {
335  return Setter::size(msg);
336  }
337 };
338 template <typename T>
339 struct VarLengthSizeValue<void, T> {
340  static int get(const T *msg) {
341  return 0;
342  }
343 };
344 template <typename Derived>
346  static int get(const void *msg) {
347  return Derived::kSize;
348  }
349 };
350 
351 template <typename T>
352 struct AddCallback {
353  void operator()(EncodeContext *context, uint8_t *data, int arg) {
354  context->AddCallback(&T::Callback, data, arg);
355  }
356 };
357 template <>
358 struct AddCallback<void>{
359  void operator()(EncodeContext *context, uint8_t *data, int arg) {
360  }
361 };
362 
363 template <typename ContextAccessor>
365  typedef typename ContextAccessor::ValueType ValueType;
366 };
367 template <>
368 struct ContextElementType<void> {
369  typedef void ValueType;
370 };
371 
372 template <typename Accessor>
374  typedef typename Accessor::ValueType ValueType;
375  template <typename Obj>
376  ContextIterator(const Obj *obj)
377  : iter(accessor.begin(obj)) {
378 
379  }
380 
382  ValueType *obj = *iter;
383  ++iter;
384  return obj;
385  }
386 
387  template <typename Obj>
388  bool HasNext(Obj *obj) const {
389  return (iter != accessor.end(obj));
390  }
391 
392 private:
394  typename Accessor::CollectionType::const_iterator iter;
395 };
396 template <>
397 struct ContextIterator<void> {
398  ContextIterator(void *obj) {
399  }
400  void * Next() { return NULL; }
401  bool HasNext(void *obj) const { return false; }
402 };
403 
404 template <typename T>
405 struct SaveOffset {
407  ctx->SaveOffset(T()());
408  }
409 };
410 
411 template <>
412 struct SaveOffset<void> {
413  void operator()(EncodeContext *ctx) { }
414 };
415 
416 } // detail
417 
418 
419 #endif
void operator()(ParseContext *context, T *obj)
Definition: proto_impl.h:120
#define PROTO_DEBUG(args...)
Definition: proto_impl.h:13
int operator()(const uint8_t *data, size_t size, ParseContext *context, T *obj)
Definition: proto_impl.h:302
void * operator()(ParseContext *context, void *obj)
Definition: proto_impl.h:89
T * operator()(ParseContext *context, T *obj)
Definition: proto_impl.h:95
T * operator()(ParseContext *context, T *obj)
Definition: proto_impl.h:153
int operator()(uint8_t *data, int element_size, T *obj)
Definition: proto_impl.h:65
ValueType * Next()
Definition: proto_impl.h:381
bool HasNext(void *obj) const
Definition: proto_impl.h:401
void operator()(EncodeContext *ctx)
Definition: proto_impl.h:413
Child::ContextType ctx_t
Definition: proto_impl.h:159
void operator()(EncodeContext::CallbackType cb, EncodeContext *context, uint8_t *data, int arg)
Definition: proto_impl.h:263
void operator()(const uint8_t *data, int element_size, U *obj)
Definition: proto_impl.h:18
void set_lensize(int lensize)
void SwapData(ParseObject *obj)
bool HasNext(Obj *obj) const
Definition: proto_impl.h:388
int operator()(const uint8_t *data, size_t size, ParseContext *context, T *obj)
Definition: proto_impl.h:270
bool operator()(int size)
Definition: proto_impl.h:327
void operator()(uint8_t *data, int element_size, U *obj)
Definition: proto_impl.h:33
int operator()(const uint8_t *data, size_t size, ParseContext *context, T *obj)
Definition: proto_impl.h:294
void operator()(C *obj, ParseObject *context_obj)
Definition: proto_impl.h:103
static uint64_t get_value(const uint8_t *data, int size)
Definition: parse_object.h:39
int operator()(ParseContext *context, const uint8_t *data, size_t size, size_t msgsize, Context *obj)
Definition: proto_impl.h:215
uint8_t type
Definition: load_balance.h:109
void operator()(EncodeContext *context, uint8_t *data, int arg)
Definition: proto_impl.h:353
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
Definition: proto_impl.h:177
int operator()(const uint8_t *data, size_t size, ParseContext *context, T *obj)
Definition: proto_impl.h:313
ContextIterator(const Obj *obj)
Definition: proto_impl.h:376
ctx_t * operator()(ParseContext *context, U *obj)
Definition: proto_impl.h:161
void operator()(void *obj, ParseObject *child_obj)
Definition: proto_impl.h:113
void operator()(EncodeContext *ctx)
Definition: proto_impl.h:406
bool operator()(int size)
Definition: proto_impl.h:321
#define TYPE_NAME(_type)
Definition: logging.h:31
void AddCallback(CallbackType cb, uint8_t *data, int arg)
boost::function< void(EncodeContext *, uint8_t *, int, int)> CallbackType
int Copy(Iterator begin, Iterator end, uint8_t *data)
Definition: proto_impl.h:49
static void set(C *obj, T value)
int operator()(uint8_t *data, int element_size, T *obj)
Definition: proto_impl.h:58
void set_size(size_t length)
Accessor::CollectionType::const_iterator iter
Definition: proto_impl.h:394
void operator()(const uint8_t *data, int element_size, void *obj)
Definition: proto_impl.h:26
int operator()(const uint8_t *data, size_t size, ParseContext *context, T *obj)
Definition: proto_impl.h:286
void operator()(uint8_t *data, int element_size, U *obj)
Definition: proto_impl.h:41
int operator()(ParseContext *context, const uint8_t *data, size_t size, size_t msgsize, Context *obj)
Definition: proto_impl.h:232
opt_ctx_t * operator()(ParseContext *context, T *obj)
Definition: proto_impl.h:142
void operator()(EncodeContext *context, uint8_t *data, int arg)
Definition: proto_impl.h:359
void Push(ParseObject *data)
int operator()(ParseContext *context, const uint8_t *data, size_t size, size_t msgsize, Context *obj)
Definition: proto_impl.h:248
void operator()(ParseContext *context, void *obj)
Definition: proto_impl.h:128
C * operator()(ParseContext *context, P *obj)
Definition: proto_impl.h:72
void operator()(ParseContext *context, void *obj)
Definition: proto_impl.h:135
void operator()(EncodeContext::CallbackType cb, EncodeContext *context, uint8_t *data, int arg)
Definition: proto_impl.h:256
ContextAccessor::ValueType ValueType
Definition: proto_impl.h:365
P * operator()(ParseContext *context, P *obj)
Definition: proto_impl.h:80
Accessor::ValueType ValueType
Definition: proto_impl.h:374
static void put_value(uint8_t *data, int size, uint64_t value)
Definition: parse_object.h:55