Line data Source code
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 2419681 : void operator()(const uint8_t *data, int element_size, U *obj) {
19 2419681 : int value = get_value(data, element_size);
20 2419687 : T::set(obj, value);
21 2419683 : }
22 : };
23 :
24 : template <>
25 : struct ApplySetter<void> {
26 1011921 : void operator()(const uint8_t *data, int element_size, void *obj) {
27 1011921 : }
28 : };
29 :
30 : template <typename T>
31 : struct ApplyGetter {
32 : template <typename U>
33 3031025 : void operator()(uint8_t *data, int element_size, U *obj) {
34 3031025 : uint64_t value = T::get(obj);
35 3031112 : put_value(data, element_size, value);
36 3031113 : }
37 : };
38 : template <>
39 : struct ApplyGetter<void> {
40 : template <typename U>
41 1133300 : void operator()(uint8_t *data, int element_size, U *obj) {
42 1133300 : memset(data, 0, element_size);
43 1133300 : }
44 : };
45 :
46 : template <typename Accessor, typename T>
47 : struct VariableLengthWriter {
48 : template <typename Iterator>
49 2152377 : int Copy(Iterator begin, Iterator end, uint8_t *data) {
50 2152377 : int count = 0;
51 17524972 : for (Iterator iter = begin; iter != end; ++iter) {
52 15372304 : put_value(data, sizeof(*iter), *iter);
53 15372587 : data += sizeof(*iter);
54 15372587 : count+= sizeof(*iter);
55 : }
56 2152452 : return count;
57 : }
58 2152370 : int operator()(uint8_t *data, int element_size, T *obj) {
59 2152370 : int count = Copy(Accessor::begin(obj), Accessor::end(obj), data);
60 2152452 : return count;
61 : }
62 : };
63 : template <typename T>
64 : struct VariableLengthWriter<void, T> {
65 682322 : int operator()(uint8_t *data, int element_size, T *obj) {
66 682322 : return 0;
67 : }
68 : };
69 :
70 : template <typename P, typename C>
71 : struct ContextPush {
72 1997520 : C * operator()(ParseContext *context, P *obj) {
73 1997520 : C *child_obj = new C;
74 1997524 : context->Push(child_obj);
75 1997498 : return child_obj;
76 : }
77 : };
78 : template <typename P>
79 : struct ContextPush<P, void> {
80 664187 : P *operator()(ParseContext *context, P *obj) {
81 664187 : context->ReleaseData();
82 664179 : context->Push(obj);
83 664194 : return obj;
84 : }
85 : };
86 :
87 : template <>
88 : struct ContextPush<void, void> {
89 199762 : void *operator()(ParseContext *context, void *obj) {
90 199762 : return obj;
91 : }
92 : };
93 : template <typename T>
94 : struct NoContextPush {
95 634611 : T *operator()(ParseContext *context, T *obj) {
96 634611 : return obj;
97 : }
98 : };
99 :
100 : template<typename T, typename ChildContextType>
101 : struct StoreContext {
102 : template <typename C>
103 1801027 : void operator()(C *obj, ParseObject *context_obj) {
104 1801027 : ChildContextType *child_obj =
105 1801027 : dynamic_cast<ChildContextType *>(context_obj);
106 1801027 : assert(child_obj);
107 1801027 : T::insert(obj, child_obj);
108 1801027 : }
109 : };
110 :
111 : template <typename ChildContextType>
112 : struct StoreContext<void, ChildContextType> {
113 192205 : void operator()(void *obj, ParseObject *child_obj) {
114 192205 : delete child_obj;
115 192205 : }
116 : };
117 :
118 : template <typename Parent, typename T, typename ChildContextType>
119 : struct ContextPop {
120 1993235 : void operator()(ParseContext *context, T *obj) {
121 : StoreContext<typename Parent::ContextStorer, ChildContextType> storer;
122 1993235 : storer(obj, context->Pop());
123 1993232 : }
124 : };
125 :
126 : template<typename Parent, typename T>
127 : struct ContextPop<Parent, T, void> {
128 660533 : void operator()(ParseContext *context, void *obj) {
129 660533 : context->SwapData(context->Pop());
130 660530 : }
131 : };
132 :
133 : template<typename Parent>
134 : struct ContextPop<Parent, void, void> {
135 9549659 : void operator()(ParseContext *context, void *obj) {
136 9549659 : }
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>
141 : struct DescendentContextPush {
142 195817 : opt_ctx_t *operator()(ParseContext *context, T *obj) {
143 : ContextPush<T, opt_ctx_t> pushfn;
144 391626 : 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 8101678 : T *operator()(ParseContext *context, T *obj) {
154 8101678 : return obj;
155 : }
156 : };
157 : template <typename Child>
158 : struct DescendentContextSwap {
159 : typedef typename Child::ContextType ctx_t;
160 : template <typename U>
161 634636 : ctx_t *operator()(ParseContext *context, U *obj) {
162 : typedef typename Child::ContextSwap swap_t;
163 634636 : ctx_t *nobj = swap_t()(obj);
164 : if (nobj == NULL) {
165 : // TODO:
166 : }
167 634650 : if (nobj != obj) {
168 634651 : context->SwapData(nobj);
169 : }
170 634628 : return nobj;
171 : }
172 : };
173 :
174 : template <class Parent, typename Child>
175 : struct DescendentParser {
176 : template <typename T>
177 8932131 : 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>,
193 : DescendentContextPush<Child, T, typename Child::ContextType>,
194 : DescendentContextSwap<Child> >::type context_op_t;
195 :
196 8932131 : ctx_t *child_obj = context_op_t()(context, obj);
197 :
198 8932122 : int result = Child::Parse(data, size, context, child_obj);
199 8932188 : 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;
207 : ContextPop<Parent, pctx_t, push_ctx_t> popfn;
208 8915652 : popfn(context, obj);
209 8915655 : return result;
210 : }
211 : };
212 :
213 : template <typename T, typename Context>
214 : struct SequenceLengthSetter {
215 1815368 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
216 : size_t msgsize, Context *obj) {
217 : T t;
218 1815368 : int value = t(obj, data, size);
219 1815368 : context->set_lensize(size);
220 1815359 : if ((size_t) value > msgsize) {
221 161 : PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
222 : << value << " > " << msgsize);
223 161 : return -1;
224 : }
225 1815198 : context->set_size(value);
226 1815204 : return 0;
227 : }
228 : };
229 :
230 : template <typename Context>
231 : struct SequenceLengthSetter<int, Context> {
232 344309 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
233 : size_t msgsize, Context *obj) {
234 344309 : int value = get_value(data, size);
235 344307 : context->set_lensize(size);
236 344298 : if ((size_t) value > msgsize) {
237 2 : PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
238 : << value << " > " << msgsize);
239 2 : return -1;
240 : }
241 344296 : context->set_size(value);
242 344309 : return 0;
243 : }
244 : };
245 :
246 : template <typename Context>
247 : struct SequenceLengthSetter<void, Context> {
248 3628129 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
249 : size_t msgsize, Context *obj) {
250 3628129 : return 0;
251 : }
252 : };
253 :
254 : template<typename T>
255 : struct SequenceLengthAddCallback {
256 1598808 : void operator()(EncodeContext::CallbackType cb, EncodeContext *context,
257 : uint8_t *data, int arg) {
258 1598808 : context->AddCallback(cb, data, arg);
259 1598563 : }
260 : };
261 : template<>
262 : struct SequenceLengthAddCallback<void> {
263 5743227 : void operator()(EncodeContext::CallbackType cb, EncodeContext *context,
264 : uint8_t *data, int arg) {
265 5743227 : }
266 : };
267 :
268 : template<typename Accessor, typename T>
269 : struct VariableLengthSetter {
270 1557956 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
271 : T *obj) {
272 1557956 : int element_size = context->size();
273 : // If element size is unknown, read till the end of buffer
274 1557953 : if (element_size < 0) element_size = size;
275 1551988 : else if (size < (size_t) element_size) {
276 0 : PROTO_DEBUG(TYPE_NAME(T) << " Variable Length Setter failed "
277 : << size << " < " << element_size);
278 0 : return -1;
279 : }
280 1557953 : Accessor::set(obj, data, element_size);
281 1557983 : 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>
293 : struct LengthSizeSetter {
294 634477 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
295 : T *obj) {
296 634477 : return SizeSetter::get(obj);
297 : }
298 : };
299 :
300 : template<typename Derived, typename T>
301 : struct FixedLengthSetter {
302 3431604 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
303 : T *obj) {
304 : typedef typename Derived::Setter setter_t;
305 : detail::ApplySetter<setter_t> setter;
306 3431604 : setter(data, Derived::kSize, obj);
307 3431615 : return Derived::kSize;
308 : }
309 : };
310 :
311 : template<typename Derived, typename T>
312 : struct NopSetter {
313 163637 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
314 : T *obj) {
315 163637 : return Derived::kSize;
316 : }
317 : };
318 :
319 : template <typename Derived>
320 : struct SizeComparer {
321 3435790 : bool operator()(int size) const {
322 3435790 : return size >= Derived::kSize;
323 : }
324 : };
325 :
326 : struct NopComparer {
327 2356231 : bool operator()(int size) const {
328 2356231 : return true;
329 : }
330 : };
331 :
332 : template <typename Setter, typename T>
333 : struct VarLengthSizeValue {
334 2152508 : static int get(const T *msg) {
335 2152508 : 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>
345 : struct FixedLengthSizeValue {
346 4508356 : static int get(const void *msg) {
347 4508356 : return Derived::kSize;
348 : }
349 : };
350 :
351 : template <typename T>
352 : struct AddCallback {
353 453690 : void operator()(EncodeContext *context, uint8_t *data, int arg) {
354 453690 : context->AddCallback(&T::Callback, data, arg);
355 453697 : }
356 : };
357 : template <>
358 : struct AddCallback<void>{
359 6887711 : void operator()(EncodeContext *context, uint8_t *data, int arg) {
360 6887711 : }
361 : };
362 :
363 : template <typename ContextAccessor>
364 : struct ContextElementType {
365 : typedef typename ContextAccessor::ValueType ValueType;
366 : };
367 : template <>
368 : struct ContextElementType<void> {
369 : typedef void ValueType;
370 : };
371 :
372 : template <typename Accessor>
373 : struct ContextIterator {
374 : typedef typename Accessor::ValueType ValueType;
375 : template <typename Obj>
376 970421 : ContextIterator(const Obj *obj)
377 970421 : : iter(accessor.begin(obj)) {
378 :
379 970444 : }
380 :
381 2346802 : ValueType * Next() {
382 2346802 : ValueType *obj = *iter;
383 2346827 : ++iter;
384 2346819 : return obj;
385 : }
386 :
387 : template <typename Obj>
388 3316982 : bool HasNext(Obj *obj) const {
389 3316982 : return (iter != accessor.end(obj));
390 : }
391 :
392 : private:
393 : Accessor accessor;
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 {
406 580894 : void operator()(EncodeContext *ctx) {
407 580894 : ctx->SaveOffset(T()());
408 581067 : }
409 : };
410 :
411 : template <>
412 : struct SaveOffset<void> {
413 9524619 : void operator()(EncodeContext *ctx) { }
414 : };
415 :
416 : } // detail
417 :
418 :
419 : #endif
|