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-11-09 02:10:49 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             :  * 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

Generated by: LCOV version 1.14