LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/base - proto_impl.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 131 133 98.5 %
Date: 2026-08-03 02:19:58 Functions: 963 987 97.6 %
Legend: Lines: hit not hit

          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

Generated by: LCOV version 1.14