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