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 2396753 : void operator()(const uint8_t *data, int element_size, U *obj) {
19 2396753 : int value = get_value(data, element_size);
20 2396753 : T::set(obj, value);
21 2396752 : }
22 : };
23 :
24 : template <>
25 : struct ApplySetter<void> {
26 997996 : void operator()(const uint8_t *data, int element_size, void *obj) {
27 997996 : }
28 : };
29 :
30 : template <typename T>
31 : struct ApplyGetter {
32 : template <typename U>
33 2997425 : void operator()(uint8_t *data, int element_size, U *obj) {
34 2997425 : uint64_t value = T::get(obj);
35 2997496 : put_value(data, element_size, value);
36 2997503 : }
37 : };
38 : template <>
39 : struct ApplyGetter<void> {
40 : template <typename U>
41 1119662 : void operator()(uint8_t *data, int element_size, U *obj) {
42 1119662 : memset(data, 0, element_size);
43 1119662 : }
44 : };
45 :
46 : template <typename Accessor, typename T>
47 : struct VariableLengthWriter {
48 : template <typename Iterator>
49 2139500 : int Copy(Iterator begin, Iterator end, uint8_t *data) {
50 2139500 : int count = 0;
51 17367319 : for (Iterator iter = begin; iter != end; ++iter) {
52 15227625 : put_value(data, sizeof(*iter), *iter);
53 15227805 : data += sizeof(*iter);
54 15227805 : count+= sizeof(*iter);
55 : }
56 2139595 : return count;
57 : }
58 2139494 : int operator()(uint8_t *data, int element_size, T *obj) {
59 2139494 : int count = Copy(Accessor::begin(obj), Accessor::end(obj), data);
60 2139595 : return count;
61 : }
62 : };
63 : template <typename T>
64 : struct VariableLengthWriter<void, T> {
65 673763 : int operator()(uint8_t *data, int element_size, T *obj) {
66 673763 : return 0;
67 : }
68 : };
69 :
70 : template <typename P, typename C>
71 : struct ContextPush {
72 1981521 : C * operator()(ParseContext *context, P *obj) {
73 1981521 : C *child_obj = new C;
74 1981533 : context->Push(child_obj);
75 1981492 : return child_obj;
76 : }
77 : };
78 : template <typename P>
79 : struct ContextPush<P, void> {
80 657120 : P *operator()(ParseContext *context, P *obj) {
81 657120 : context->ReleaseData();
82 657105 : context->Push(obj);
83 657133 : return obj;
84 : }
85 : };
86 :
87 : template <>
88 : struct ContextPush<void, void> {
89 195765 : void *operator()(ParseContext *context, void *obj) {
90 195765 : return obj;
91 : }
92 : };
93 : template <typename T>
94 : struct NoContextPush {
95 626716 : T *operator()(ParseContext *context, T *obj) {
96 626716 : return obj;
97 : }
98 : };
99 :
100 : template<typename T, typename ChildContextType>
101 : struct StoreContext {
102 : template <typename C>
103 1788984 : void operator()(C *obj, ParseObject *context_obj) {
104 1788984 : ChildContextType *child_obj =
105 1788984 : dynamic_cast<ChildContextType *>(context_obj);
106 1788984 : assert(child_obj);
107 1788984 : T::insert(obj, child_obj);
108 1789013 : }
109 : };
110 :
111 : template <typename ChildContextType>
112 : struct StoreContext<void, ChildContextType> {
113 188217 : void operator()(void *obj, ParseObject *child_obj) {
114 188217 : delete child_obj;
115 188217 : }
116 : };
117 :
118 : template <typename Parent, typename T, typename ChildContextType>
119 : struct ContextPop {
120 1977208 : void operator()(ParseContext *context, T *obj) {
121 : StoreContext<typename Parent::ContextStorer, ChildContextType> storer;
122 1977208 : storer(obj, context->Pop());
123 1977228 : }
124 : };
125 :
126 : template<typename Parent, typename T>
127 : struct ContextPop<Parent, T, void> {
128 653472 : void operator()(ParseContext *context, void *obj) {
129 653472 : context->SwapData(context->Pop());
130 653466 : }
131 : };
132 :
133 : template<typename Parent>
134 : struct ContextPop<Parent, void, void> {
135 9448301 : void operator()(ParseContext *context, void *obj) {
136 9448301 : }
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 191821 : opt_ctx_t *operator()(ParseContext *context, T *obj) {
143 : ContextPush<T, opt_ctx_t> pushfn;
144 383639 : 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 8020167 : T *operator()(ParseContext *context, T *obj) {
154 8020167 : return obj;
155 : }
156 : };
157 : template <typename Child>
158 : struct DescendentContextSwap {
159 : typedef typename Child::ContextType ctx_t;
160 : template <typename U>
161 626736 : ctx_t *operator()(ParseContext *context, U *obj) {
162 : typedef typename Child::ContextSwap swap_t;
163 626736 : ctx_t *nobj = swap_t()(obj);
164 : if (nobj == NULL) {
165 : // TODO:
166 : }
167 626738 : if (nobj != obj) {
168 626739 : context->SwapData(nobj);
169 : }
170 626725 : return nobj;
171 : }
172 : };
173 :
174 : template <class Parent, typename Child>
175 : struct DescendentParser {
176 : template <typename T>
177 8838729 : 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 8838729 : ctx_t *child_obj = context_op_t()(context, obj);
197 :
198 8838711 : int result = Child::Parse(data, size, context, child_obj);
199 8838741 : 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 8822205 : popfn(context, obj);
209 8822203 : return result;
210 : }
211 : };
212 :
213 : template <typename T, typename Context>
214 : struct SequenceLengthSetter {
215 1805981 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
216 : size_t msgsize, Context *obj) {
217 : T t;
218 1805981 : int value = t(obj, data, size);
219 1805973 : context->set_lensize(size);
220 1805961 : if ((size_t) value > msgsize) {
221 161 : PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
222 : << value << " > " << msgsize);
223 161 : return -1;
224 : }
225 1805800 : context->set_size(value);
226 1805811 : return 0;
227 : }
228 : };
229 :
230 : template <typename Context>
231 : struct SequenceLengthSetter<int, Context> {
232 340588 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
233 : size_t msgsize, Context *obj) {
234 340588 : int value = get_value(data, size);
235 340587 : context->set_lensize(size);
236 340583 : if ((size_t) value > msgsize) {
237 2 : PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
238 : << value << " > " << msgsize);
239 2 : return -1;
240 : }
241 340581 : context->set_size(value);
242 340583 : return 0;
243 : }
244 : };
245 :
246 : template <typename Context>
247 : struct SequenceLengthSetter<void, Context> {
248 3589299 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
249 : size_t msgsize, Context *obj) {
250 3589299 : return 0;
251 : }
252 : };
253 :
254 : template<typename T>
255 : struct SequenceLengthAddCallback {
256 1582145 : void operator()(EncodeContext::CallbackType cb, EncodeContext *context,
257 : uint8_t *data, int arg) {
258 1582145 : context->AddCallback(cb, data, arg);
259 1581870 : }
260 : };
261 : template<>
262 : struct SequenceLengthAddCallback<void> {
263 5682924 : void operator()(EncodeContext::CallbackType cb, EncodeContext *context,
264 : uint8_t *data, int arg) {
265 5682924 : }
266 : };
267 :
268 : template<typename Accessor, typename T>
269 : struct VariableLengthSetter {
270 1550848 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
271 : T *obj) {
272 1550848 : int element_size = context->size();
273 : // If element size is unknown, read till the end of buffer
274 1550845 : if (element_size < 0) element_size = size;
275 1545803 : 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 1550845 : Accessor::set(obj, data, element_size);
281 1550875 : 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 626568 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
295 : T *obj) {
296 626568 : return SizeSetter::get(obj);
297 : }
298 : };
299 :
300 : template<typename Derived, typename T>
301 : struct FixedLengthSetter {
302 3394754 : 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 3394754 : setter(data, Derived::kSize, obj);
307 3394763 : return Derived::kSize;
308 : }
309 : };
310 :
311 : template<typename Derived, typename T>
312 : struct NopSetter {
313 163554 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
314 : T *obj) {
315 163554 : return Derived::kSize;
316 : }
317 : };
318 :
319 : template <typename Derived>
320 : struct SizeComparer {
321 3398955 : bool operator()(int size) const {
322 3398955 : return size >= Derived::kSize;
323 : }
324 : };
325 :
326 : struct NopComparer {
327 2341155 : bool operator()(int size) const {
328 2341155 : return true;
329 : }
330 : };
331 :
332 : template <typename Setter, typename T>
333 : struct VarLengthSizeValue {
334 2139628 : static int get(const T *msg) {
335 2139628 : 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 4452943 : static int get(const void *msg) {
347 4452943 : return Derived::kSize;
348 : }
349 : };
350 :
351 : template <typename T>
352 : struct AddCallback {
353 447585 : void operator()(EncodeContext *context, uint8_t *data, int arg) {
354 447585 : context->AddCallback(&T::Callback, data, arg);
355 447584 : }
356 : };
357 : template <>
358 : struct AddCallback<void>{
359 6816733 : void operator()(EncodeContext *context, uint8_t *data, int arg) {
360 6816733 : }
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 954048 : ContextIterator(const Obj *obj)
377 954048 : : iter(accessor.begin(obj)) {
378 :
379 954064 : }
380 :
381 2327609 : ValueType * Next() {
382 2327609 : ValueType *obj = *iter;
383 2327606 : ++iter;
384 2327599 : return obj;
385 : }
386 :
387 : template <typename Obj>
388 3281413 : bool HasNext(Obj *obj) const {
389 3281413 : 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 569042 : void operator()(EncodeContext *ctx) {
407 569042 : ctx->SaveOffset(T()());
408 569295 : }
409 : };
410 :
411 : template <>
412 : struct SaveOffset<void> {
413 9415558 : void operator()(EncodeContext *ctx) { }
414 : };
415 :
416 : } // detail
417 :
418 :
419 : #endif
|