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 2404720 : void operator()(const uint8_t *data, int element_size, U *obj) {
19 2404720 : int value = get_value(data, element_size);
20 2404719 : T::set(obj, value);
21 2404713 : }
22 : };
23 :
24 : template <>
25 : struct ApplySetter<void> {
26 1002588 : void operator()(const uint8_t *data, int element_size, void *obj) {
27 1002588 : }
28 : };
29 :
30 : template <typename T>
31 : struct ApplyGetter {
32 : template <typename U>
33 3011193 : void operator()(uint8_t *data, int element_size, U *obj) {
34 3011193 : uint64_t value = T::get(obj);
35 3011260 : put_value(data, element_size, value);
36 3011274 : }
37 : };
38 : template <>
39 : struct ApplyGetter<void> {
40 : template <typename U>
41 1125432 : void operator()(uint8_t *data, int element_size, U *obj) {
42 1125432 : memset(data, 0, element_size);
43 1125432 : }
44 : };
45 :
46 : template <typename Accessor, typename T>
47 : struct VariableLengthWriter {
48 : template <typename Iterator>
49 2144218 : int Copy(Iterator begin, Iterator end, uint8_t *data) {
50 2144218 : int count = 0;
51 17418878 : for (Iterator iter = begin; iter != end; ++iter) {
52 15274504 : put_value(data, sizeof(*iter), *iter);
53 15274630 : data += sizeof(*iter);
54 15274630 : count+= sizeof(*iter);
55 : }
56 2144289 : return count;
57 : }
58 2144204 : int operator()(uint8_t *data, int element_size, T *obj) {
59 2144204 : int count = Copy(Accessor::begin(obj), Accessor::end(obj), data);
60 2144288 : return count;
61 : }
62 : };
63 : template <typename T>
64 : struct VariableLengthWriter<void, T> {
65 677727 : int operator()(uint8_t *data, int element_size, T *obj) {
66 677727 : return 0;
67 : }
68 : };
69 :
70 : template <typename P, typename C>
71 : struct ContextPush {
72 1987046 : C * operator()(ParseContext *context, P *obj) {
73 1987046 : C *child_obj = new C;
74 1987055 : context->Push(child_obj);
75 1987029 : return child_obj;
76 : }
77 : };
78 : template <typename P>
79 : struct ContextPush<P, void> {
80 659464 : P *operator()(ParseContext *context, P *obj) {
81 659464 : context->ReleaseData();
82 659442 : context->Push(obj);
83 659469 : return obj;
84 : }
85 : };
86 :
87 : template <>
88 : struct ContextPush<void, void> {
89 197008 : void *operator()(ParseContext *context, void *obj) {
90 197008 : return obj;
91 : }
92 : };
93 : template <typename T>
94 : struct NoContextPush {
95 629566 : T *operator()(ParseContext *context, T *obj) {
96 629566 : return obj;
97 : }
98 : };
99 :
100 : template<typename T, typename ChildContextType>
101 : struct StoreContext {
102 : template <typename C>
103 1793300 : void operator()(C *obj, ParseObject *context_obj) {
104 1793300 : ChildContextType *child_obj =
105 1793300 : dynamic_cast<ChildContextType *>(context_obj);
106 1793300 : assert(child_obj);
107 1793300 : T::insert(obj, child_obj);
108 1793320 : }
109 : };
110 :
111 : template <typename ChildContextType>
112 : struct StoreContext<void, ChildContextType> {
113 189456 : void operator()(void *obj, ParseObject *child_obj) {
114 189456 : delete child_obj;
115 189456 : }
116 : };
117 :
118 : template <typename Parent, typename T, typename ChildContextType>
119 : struct ContextPop {
120 1982777 : void operator()(ParseContext *context, T *obj) {
121 : StoreContext<typename Parent::ContextStorer, ChildContextType> storer;
122 1982777 : storer(obj, context->Pop());
123 1982776 : }
124 : };
125 :
126 : template<typename Parent, typename T>
127 : struct ContextPop<Parent, T, void> {
128 655809 : void operator()(ParseContext *context, void *obj) {
129 655809 : context->SwapData(context->Pop());
130 655799 : }
131 : };
132 :
133 : template<typename Parent>
134 : struct ContextPop<Parent, void, void> {
135 9483060 : void operator()(ParseContext *context, void *obj) {
136 9483060 : }
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 193059 : opt_ctx_t *operator()(ParseContext *context, T *obj) {
143 : ContextPush<T, opt_ctx_t> pushfn;
144 386118 : 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 8047905 : T *operator()(ParseContext *context, T *obj) {
154 8047905 : return obj;
155 : }
156 : };
157 : template <typename Child>
158 : struct DescendentContextSwap {
159 : typedef typename Child::ContextType ctx_t;
160 : template <typename U>
161 629592 : ctx_t *operator()(ParseContext *context, U *obj) {
162 : typedef typename Child::ContextSwap swap_t;
163 629592 : ctx_t *nobj = swap_t()(obj);
164 : if (nobj == NULL) {
165 : // TODO:
166 : }
167 629595 : if (nobj != obj) {
168 629595 : context->SwapData(nobj);
169 : }
170 629584 : return nobj;
171 : }
172 : };
173 :
174 : template <class Parent, typename Child>
175 : struct DescendentParser {
176 : template <typename T>
177 8870547 : 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 8870547 : ctx_t *child_obj = context_op_t()(context, obj);
197 :
198 8870550 : int result = Child::Parse(data, size, context, child_obj);
199 8870608 : 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 8854072 : popfn(context, obj);
209 8854072 : return result;
210 : }
211 : };
212 :
213 : template <typename T, typename Context>
214 : struct SequenceLengthSetter {
215 1809265 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
216 : size_t msgsize, Context *obj) {
217 : T t;
218 1809265 : int value = t(obj, data, size);
219 1809263 : context->set_lensize(size);
220 1809252 : if ((size_t) value > msgsize) {
221 161 : PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
222 : << value << " > " << msgsize);
223 161 : return -1;
224 : }
225 1809091 : context->set_size(value);
226 1809105 : return 0;
227 : }
228 : };
229 :
230 : template <typename Context>
231 : struct SequenceLengthSetter<int, Context> {
232 342011 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
233 : size_t msgsize, Context *obj) {
234 342011 : int value = get_value(data, size);
235 342009 : context->set_lensize(size);
236 342005 : if ((size_t) value > msgsize) {
237 2 : PROTO_DEBUG(TYPE_NAME(Context) << " Sequence length error: "
238 : << value << " > " << msgsize);
239 2 : return -1;
240 : }
241 342003 : context->set_size(value);
242 342005 : return 0;
243 : }
244 : };
245 :
246 : template <typename Context>
247 : struct SequenceLengthSetter<void, Context> {
248 3602727 : int operator()(ParseContext *context, const uint8_t *data, size_t size,
249 : size_t msgsize, Context *obj) {
250 3602727 : return 0;
251 : }
252 : };
253 :
254 : template<typename T>
255 : struct SequenceLengthAddCallback {
256 1589374 : void operator()(EncodeContext::CallbackType cb, EncodeContext *context,
257 : uint8_t *data, int arg) {
258 1589374 : context->AddCallback(cb, data, arg);
259 1589238 : }
260 : };
261 : template<>
262 : struct SequenceLengthAddCallback<void> {
263 5707767 : void operator()(EncodeContext::CallbackType cb, EncodeContext *context,
264 : uint8_t *data, int arg) {
265 5707767 : }
266 : };
267 :
268 : template<typename Accessor, typename T>
269 : struct VariableLengthSetter {
270 1553523 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
271 : T *obj) {
272 1553523 : int element_size = context->size();
273 : // If element size is unknown, read till the end of buffer
274 1553519 : if (element_size < 0) element_size = size;
275 1548190 : 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 1553519 : Accessor::set(obj, data, element_size);
281 1553551 : 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 629426 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
295 : T *obj) {
296 629426 : return SizeSetter::get(obj);
297 : }
298 : };
299 :
300 : template<typename Derived, typename T>
301 : struct FixedLengthSetter {
302 3407320 : 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 3407320 : setter(data, Derived::kSize, obj);
307 3407313 : return Derived::kSize;
308 : }
309 : };
310 :
311 : template<typename Derived, typename T>
312 : struct NopSetter {
313 163604 : int operator()(const uint8_t *data, size_t size, ParseContext *context,
314 : T *obj) {
315 163604 : return Derived::kSize;
316 : }
317 : };
318 :
319 : template <typename Derived>
320 : struct SizeComparer {
321 3411492 : bool operator()(int size) const {
322 3411492 : return size >= Derived::kSize;
323 : }
324 : };
325 :
326 : struct NopComparer {
327 2346739 : bool operator()(int size) const {
328 2346739 : return true;
329 : }
330 : };
331 :
332 : template <typename Setter, typename T>
333 : struct VarLengthSizeValue {
334 2144352 : static int get(const T *msg) {
335 2144352 : 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 4476077 : static int get(const void *msg) {
347 4476077 : return Derived::kSize;
348 : }
349 : };
350 :
351 : template <typename T>
352 : struct AddCallback {
353 450383 : void operator()(EncodeContext *context, uint8_t *data, int arg) {
354 450383 : context->AddCallback(&T::Callback, data, arg);
355 450375 : }
356 : };
357 : template <>
358 : struct AddCallback<void>{
359 6846053 : void operator()(EncodeContext *context, uint8_t *data, int arg) {
360 6846053 : }
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 960673 : ContextIterator(const Obj *obj)
377 960673 : : iter(accessor.begin(obj)) {
378 :
379 960704 : }
380 :
381 2335097 : ValueType * Next() {
382 2335097 : ValueType *obj = *iter;
383 2335092 : ++iter;
384 2335092 : return obj;
385 : }
386 :
387 : template <typename Obj>
388 3295590 : bool HasNext(Obj *obj) const {
389 3295590 : 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 574633 : void operator()(EncodeContext *ctx) {
407 574633 : ctx->SaveOffset(T()());
408 574802 : }
409 : };
410 :
411 : template <>
412 : struct SaveOffset<void> {
413 9461128 : void operator()(EncodeContext *ctx) { }
414 : };
415 :
416 : } // detail
417 :
418 :
419 : #endif
|