LCOV - code coverage report
Current view: top level - root/contrail/src/contrail-common/base - proto.h (source / functions) Hit Total Coverage
Test: OpenSDN C/C++ coverage (all TARGET_SET jobs) Lines: 274 286 95.8 %
Date: 2026-08-03 02:19:58 Functions: 1262 1375 91.8 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
       3             :  */
       4             : 
       5             : #ifndef ctrlplane_proto_h
       6             : #define ctrlplane_proto_h
       7             : 
       8             : #define BOOST_MPL_CFG_NO_PREPROCESSED_HEADERS
       9             : #define BOOST_MPL_LIMIT_MAP_SIZE 30
      10             : 
      11             : #include <map>
      12             : #include <memory>
      13             : 
      14             : #include <vector>
      15             : 
      16             : #include <boost/ptr_container/ptr_vector.hpp>
      17             : #include <boost/function.hpp>
      18             : #include <boost/type_traits/is_same.hpp>
      19             : #include <boost/type_traits/is_base_of.hpp>
      20             : #include <boost/mpl/equal_to.hpp>
      21             : #include <boost/mpl/for_each.hpp>
      22             : #include <boost/mpl/greater.hpp>
      23             : #include <boost/mpl/list.hpp>
      24             : #include <boost/mpl/map.hpp>
      25             : #include <boost/mpl/or.hpp>
      26             : #include <boost/mpl/vector.hpp>
      27             : #include <boost/mpl/string.hpp>
      28             : 
      29             : #include "base/compiler.h"
      30             : #include "base/logging.h"
      31             : #include "base/parse_object.h"
      32             : 
      33             : namespace mpl = boost::mpl;
      34             : 
      35             : class ParseContext {
      36             : public:
      37             : 
      38             :     ParseContext();
      39             :     ~ParseContext();
      40             : 
      41             :     ParseObject *release();
      42             : 
      43             :     void Push(ParseObject *data);
      44             :     ParseObject *Pop();
      45             : 
      46             :     void SwapData(ParseObject *obj);
      47             :     void ReleaseData();
      48             : 
      49             :     ParseObject *data();
      50             : 
      51             :     void advance(int delta);
      52      198701 :     int offset() const { return offset_; }
      53             : 
      54             :     void set_lensize(int lensize);
      55             :     int lensize() const;
      56             :     void set_size(size_t length);
      57             :     size_t size() const;
      58             :     void set_total_size();
      59             :     size_t total_size() const;
      60             : 
      61             :     void SetError(int error, int subcode, std::string type, const uint8_t *data,
      62             :                   int data_size);
      63         139 :     const ParseErrorContext &error_context() { return error_context_; }
      64             : private:
      65             : 
      66             :     ParseErrorContext error_context_;
      67             :     struct StackFrame;
      68             :     int offset_;
      69             :     std::vector<StackFrame *> stack_;
      70             : };
      71             : 
      72             : class EncodeContext {
      73             : public:
      74             :     typedef boost::function<void(EncodeContext *, uint8_t *, int, int)> CallbackType;
      75             : 
      76             :     EncodeContext();
      77             :     ~EncodeContext();
      78             : 
      79             :     void Push();
      80             :     void Pop(bool callback);
      81             :     void AddCallback(CallbackType cb, uint8_t *data, int arg);
      82             : 
      83             :     void advance(int delta);
      84             :     int length() const;
      85             : 
      86             :     void SaveOffset(std::string);
      87      156963 :     EncodeOffsets &encode_offsets() { return offsets_; }
      88             : private:
      89             :     struct StackFrame;
      90             :     boost::ptr_vector<StackFrame> stack_;
      91             :     EncodeOffsets offsets_;
      92             : };
      93             : 
      94             : template <class C, typename T, T C::* Member>
      95             : struct Accessor {
      96             :     typedef T C::* member_ptr_t;
      97     2386376 :     static void set(C *obj, T value) {
      98     2386376 :         obj->*Member = value;
      99     2386376 :     }
     100     3051540 :     static T get(const C *obj) {
     101     3051540 :         return obj->*Member;
     102             :     }
     103             : };
     104             : 
     105             : template <class C, std::string C::* Member>
     106             : struct Accessor<C, std::string, Member> {
     107        5965 :     static void set(C*obj, const uint8_t *data, size_t elem_size) {
     108        5965 :         obj->*Member = std::string((const char *) data, elem_size);
     109        5966 :     }
     110        8694 :     static int size(const C *obj) {
     111        8694 :         return (obj->*Member).size();
     112             :     }
     113        8695 :     static std::string::const_iterator begin(const C *obj) {
     114        8695 :         return (obj->*Member).begin();
     115             :     }
     116        8695 :     static std::string::const_iterator end(const C *obj) {
     117        8695 :         return (obj->*Member).end();
     118             :     }
     119             : };
     120             : 
     121             : template <class C, typename T, std::vector<T> C::* Member>
     122             : struct VectorAccessor {
     123     1551981 :     static void set(C*obj, const uint8_t *data, size_t elem_size) {
     124     1551981 :         obj->*Member = std::vector<T>();
     125     1552039 :         size_t size = sizeof(T);
     126    13386812 :         for (size_t i = 0; i < elem_size; i += size) {
     127    11834793 :             T value = get_value(data, size);
     128    11834774 :             data += size;
     129    11834774 :             (obj->*Member).push_back(value);
     130             :         }
     131     1552019 :     }
     132     2143795 :     static int size(const C *obj) {
     133     2143795 :         return (obj->*Member).size() * sizeof(T);
     134             :     }
     135     2143673 :     static typename std::vector<T>::const_iterator begin(const C *obj) {
     136     2143673 :         return (obj->*Member).begin();
     137             :     }
     138     2143662 :     static typename std::vector<T>::const_iterator end(const C *obj) {
     139     2143662 :         return (obj->*Member).end();
     140             :     }
     141             : };
     142             : 
     143             : // Extract the underlying type for pointer types.
     144             : template <typename T>
     145             : struct ValueType {
     146             :     typedef T type;
     147             : };
     148             : template <typename T>
     149             : struct ValueType<T *> {
     150             :     typedef T type;
     151             : };
     152             : 
     153             : template <typename Obj, typename Col, Col Obj::* Member>
     154             : struct CollectionAccessor {
     155             :     typedef typename ValueType<typename Col::value_type>::type ValueType;
     156             :     typedef Col CollectionType;
     157             :     typedef typename CollectionType::const_iterator iterator;
     158     1801062 :     static void insert(Obj *obj, ValueType *element) {
     159     1801062 :         (obj->*Member).push_back(element);
     160     1801030 :     }
     161      970417 :     static iterator begin(const Obj *obj) {
     162      970417 :         return (obj->*Member).begin();
     163             :     }
     164     3316989 :     static iterator end(const Obj *obj) {
     165     3316989 :         return (obj->*Member).end();
     166             :     }
     167             : };
     168             : 
     169             : // Interface
     170             : struct ElementBase {
     171             :     static const int kSize = 0;
     172             :     static const int kErrorCode = 0;
     173             :     static const int kErrorSubcode = 0;
     174             :     struct NullCtxInit {
     175     5787403 :         void operator()(void *) {
     176     5787403 :         }
     177             :     };
     178             :     struct NoMatch {
     179             :         bool match(const void *) {
     180             :             return false;
     181             :         }
     182             :     };
     183     6254052 :     static bool Verifier(const void * obj, const uint8_t *data, size_t size,
     184             :                          ParseContext *context) {
     185     6254052 :         return true;
     186             :     }
     187             : 
     188             :     typedef void SaveOffset;            // Save the offset in encode context
     189             :     typedef void ContextType;           // push a new context on the stack
     190             :     typedef NullCtxInit ContextInit;    // initialize the context data
     191             :     typedef NoMatch ContextMatch;
     192             :     typedef void Setter;
     193             :     typedef void EncodingCallback;
     194             :     typedef void ContextSwap;           // swap a context with another one
     195             :     typedef void SizeSetter;            // set the size of the element
     196             : };
     197             : 
     198             : struct ChoiceBase : public ElementBase {
     199             :     typedef void ContextStorer; // store the context data on pop.
     200             : };
     201             : 
     202             : class SequenceBase : public ElementBase {
     203             : public:
     204             :     static const int kMinOccurs = 1;
     205             :     static const int kMaxOccurs = 1;
     206             :     typedef void ContextStorer; // store the context data on pop.
     207             : };
     208             : 
     209             : #include "base/proto_impl.h"
     210             : 
     211             : template<class Derived>
     212             : class ProtoElement : public ElementBase {
     213             : public:
     214             :     typedef void SequenceLength;
     215             : 
     216             :     template <typename T>
     217     6999020 :     static void Writer(T *msg, uint8_t *data, size_t size) {
     218             :         typedef typename Derived::Setter setter_t;
     219             :         typedef typename mpl::if_<
     220             :             mpl::equal_to<
     221             :                 mpl::int_<Derived::kSize>, mpl::int_<-1> >,
     222             :             detail::VariableLengthWriter<typename Derived::Setter, T>,
     223             :             detail::ApplyGetter<setter_t>
     224             :         >::type writer_t;
     225             :         writer_t writer;
     226     6999020 :         writer(data, Derived::kSize, msg);
     227     6999189 :     }
     228             : 
     229             :     template <typename T>
     230     5792090 :     static int Parse(const uint8_t *data, size_t size, ParseContext *context,
     231             :                      T *obj) {
     232             :         typedef typename mpl::if_<
     233             :             mpl::greater<
     234             :                 mpl::int_<Derived::kSize>, mpl::int_<0> >,
     235             :             detail::SizeComparer<Derived>,
     236             :             detail::NopComparer
     237             :         >::type cmp_t;
     238             : 
     239             :         cmp_t cmp;
     240     5792090 :         if (!cmp(size)) {
     241           8 :             PROTO_DEBUG("Error: cmp(size) failed");
     242           8 :             context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     243             :                     TYPE_NAME(Derived), data,
     244           0 :                     Derived::kSize > 0 ? Derived::kSize : context->size());
     245           8 :             return -1;
     246             :         }
     247     5792079 :         if (!Derived::Verifier(obj, data, size, context)) {
     248        4240 :             PROTO_DEBUG(TYPE_NAME(Derived) << " Verifier failed");
     249        4240 :             context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     250             :                     TYPE_NAME(Derived), data,
     251         109 :                     Derived::kSize > 0 ? Derived::kSize : context->size());
     252        4240 :             return -1;
     253             :         }
     254             : 
     255             :         typedef typename Derived::ContextInit ctx_init_t;
     256             :         ctx_init_t initializer;
     257     5787832 :         initializer(obj);
     258             : 
     259             :         detail::SequenceLengthSetter<typename Derived::SequenceLength, T> slen;
     260     5787831 :         int res = slen(context, data, Derived::kSize, size, obj);
     261     5787833 :         if (res < 0) {
     262         163 :             PROTO_DEBUG(TYPE_NAME(Derived) << ": error: Length Setter failed");
     263         163 :             context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     264             :                               TYPE_NAME(Derived), data, context->lensize());
     265         163 :             return -1;
     266             :         }
     267             : 
     268             :         typedef typename mpl::if_<boost::is_same<typename Derived::SizeSetter, void>,
     269             :             typename mpl::if_<
     270             :                 mpl::equal_to<mpl::int_<Derived::kSize>, mpl::int_<-1> >,
     271             :                 detail::VariableLengthSetter<typename Derived::Setter, T>,
     272             :                 typename mpl::if_<
     273             :                     mpl::greater<mpl::int_<Derived::kSize>, mpl::int_<0> >,
     274             :                     detail::FixedLengthSetter<Derived, T>,
     275             :                     detail::NopSetter<Derived, T>
     276             :                 >::type
     277             :             >::type,
     278             :             detail::LengthSizeSetter<typename Derived::SizeSetter, T>
     279             :         >::type setter_t;
     280             : 
     281             :         setter_t setter;
     282     5787670 :         res = setter(data, size, context, obj);
     283     5787712 :         if (res < 0) {
     284           2 :             context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     285             :                     TYPE_NAME(Derived), data,
     286           0 :                     Derived::kSize > 0 ? Derived::kSize : context->size());
     287             :         }
     288     5787712 :         return res;
     289             :     }
     290             : 
     291             :     template <typename T>
     292     7343246 :     static int Encode(EncodeContext *context, const T *msg, uint8_t *data,
     293             :                       size_t size) {
     294             :         typedef typename
     295             :             mpl::if_<boost::is_same<typename Derived::SizeSetter, void>,
     296             :             typename mpl::if_<mpl::equal_to<mpl::int_<Derived::kSize>, mpl::int_<-1> >,
     297             :                      detail::VarLengthSizeValue<typename Derived::Setter, T>,
     298             :                      detail::FixedLengthSizeValue<Derived> >::type,
     299             :             typename Derived::SizeSetter
     300             :         >::type size_value_t;
     301             : 
     302     7343246 :         int element_size = size_value_t::get(msg);
     303     7343268 :         if (data == NULL) {
     304          19 :             context->advance(element_size);
     305           0 :             return element_size;
     306             :         }
     307     7343253 :         assert(element_size >= 0);
     308     7343253 :         if (size < (size_t) element_size) {
     309         176 :             return -1;
     310             :         }
     311             : 
     312             :         // Setter overrides SequenceLength. Do not register a sequence length
     313             :         // callback if the element has defined a Setter.
     314             :         typename mpl::if_<
     315             :             boost::is_same<typename Derived::Setter, void>,
     316             :             detail::SequenceLengthAddCallback<typename Derived::SequenceLength>,
     317             :             detail::SequenceLengthAddCallback<void> >::type slen;
     318     7343077 :         slen(&ProtoElement::SequenceLengthWriteLen, context, data, element_size);
     319             : 
     320             :         detail::AddCallback<typename Derived::EncodingCallback> cbadd;
     321     7342993 :         cbadd(context, data, element_size);
     322             : 
     323     7342996 :         detail::SaveOffset<typename Derived::SaveOffset>()(context);
     324             : 
     325     7343048 :         Derived::Writer(msg, data, size);
     326             : 
     327     7343201 :         context->advance(element_size);
     328     7342945 :         return element_size;
     329             :     }
     330             : 
     331             : private:
     332     1598592 :     static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data,
     333             :                                        int offset, int element_size) {
     334     1598592 :         int length = context->length() - offset - element_size;
     335     1598520 :         put_value(data, element_size, length);
     336     1598524 :     }
     337             : };
     338             : 
     339             : template <typename Setter, typename T>
     340             : struct ChoiceSetter {
     341      797209 :     void operator()(T *obj, int &value) {
     342      797209 :         Setter::set(obj, value);
     343      797208 :     }
     344             : };
     345             : 
     346             : template <typename T>
     347             : struct ChoiceSetter<void, T> {
     348      202546 :     void operator()(T* obj, int value) { }
     349             : };
     350             : 
     351             : template <class Derived>
     352             : class ProtoChoice : public ChoiceBase {
     353             : public:
     354             :     template <typename T>
     355      999744 :     static int Parse(const uint8_t *data, size_t size, ParseContext *context,
     356             :                      T *obj) {
     357      999744 :         int advance = Derived::kSize;
     358      999744 :         int value = -1;
     359             : 
     360      999744 :         if (size < (size_t) advance) {
     361           0 :             context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     362             :                               TYPE_NAME(Derived), data, advance);
     363           0 :             return -1;
     364             :         }
     365             : 
     366      999744 :         value = get_value(data, advance);
     367             : 
     368      999750 :         data += advance;
     369      999750 :         size -= advance;
     370      999750 :         context->advance(advance);
     371             : 
     372             :         typedef typename mpl::if_<
     373             :             boost::is_same<typename Derived::Setter, void>,
     374             :             ChoiceSetter<void, T>,
     375             :             ChoiceSetter<typename Derived::Setter, T>
     376             :         >::type choice_setter_t;
     377             : 
     378             :         choice_setter_t setter;
     379      999762 :         setter(obj, value);
     380             : 
     381      999757 :         int result = ParseChoice(data, size, value, context, obj);
     382      999754 :         if (result < 0) {
     383        4188 :             PROTO_DEBUG(TYPE_NAME(Derived) << " ParseChoice failed");
     384        4188 :             if (result == -2) {
     385          45 :                 context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     386          45 :                               TYPE_NAME(Derived), data - advance, advance);
     387             :             }
     388        4188 :             return result;
     389             :         }
     390      995566 :         advance += result;
     391      995566 :         return advance;
     392             :     }
     393             : 
     394             :     template <typename T>
     395     1083558 :     static int Encode(EncodeContext *context, const T *msg, uint8_t *data,
     396             :                       size_t size) {
     397             :         typedef typename Derived::Choice choice_t;
     398     1083558 :         int result = 0;
     399     1083558 :         ChoiceEncoder<T> encoder(context, msg, data, size, &result);
     400     1083627 :         mpl::for_each<choice_t>(encoder);
     401     1083793 :         return result;
     402             :     }
     403             : 
     404             : private:
     405             :     template <typename T>
     406             :     struct ChoiceMatcher {
     407      999755 :         ChoiceMatcher(const uint8_t *data, size_t size, int value,
     408             :                       ParseContext *context, T *obj, int *resultp)
     409      999755 :             : data(data), size(size), value(value), context(context),
     410      999755 :               obj(obj), resultp(resultp), found(false) {
     411      999755 :         }
     412             :         template <typename U>
     413    14767246 :         void operator()(U x) {
     414    14767246 :             if (found) return;
     415     5820845 :             if (U::first::value != -1 && U::first::value != value) {
     416     4823848 :                 return;
     417             :             }
     418      999601 :             found = true;
     419             :             typedef detail::DescendentParser<Derived, typename U::second>
     420             :                 parser_t;
     421      999601 :             *resultp = parser_t::Parse(data, size, context, obj);
     422             :         }
     423             :         const uint8_t *data;
     424             :         size_t size;
     425             :         int value;
     426             :         ParseContext *context;
     427             :         T *obj;
     428             :         int *resultp;
     429             :         bool found;
     430             :     };
     431             :     template <typename T>
     432      999753 :     static int ParseChoice(const uint8_t *data, size_t size, int value,
     433             :                            ParseContext *context, T *obj) {
     434      999753 :         int result = -2;
     435      999753 :         ChoiceMatcher<T> match(data, size, value, context, obj, &result);
     436      999754 :         mpl::for_each<typename Derived::Choice>(match);
     437      999752 :         return result;
     438             :     }
     439             : 
     440             :     template <typename T>
     441             :     struct ChoiceEncoder {
     442     1083604 :         ChoiceEncoder(EncodeContext *context, const T *msg, uint8_t *data, int size,
     443             :                       int *resultp)
     444     1083604 :             : context(context), msg(msg), data(data), size(size),
     445     1083604 :             resultp(resultp), found(false) {
     446     1083604 :         }
     447             :         template <typename U, typename CtxType>
     448             :         struct EncoderTrue {
     449     1083862 :             int operator()(int opt, EncodeContext *context, const CtxType *msg,
     450             :                            uint8_t *data, int size) {
     451             :                 if (Derived::kSize) {
     452      909845 :                     if (data != NULL) {
     453      909858 :                         if (size < Derived::kSize) return -1;
     454      909858 :                         put_value(data, Derived::kSize, opt);
     455      909859 :                         data += Derived::kSize;
     456      909859 :                         size -= Derived::kSize;
     457             :                     }
     458      909846 :                     context->advance(Derived::kSize);
     459             :                 }
     460     1083841 :                 int result = U::Encode(context, msg, data, size);
     461     1083870 :                 if (result >= 0) {
     462     1083535 :                     result += Derived::kSize;
     463             :                 }
     464     1083870 :                 return result;
     465             :             }
     466             :         };
     467             :         template <typename U, typename CtxType>
     468             :         struct EncoderSetter {
     469      739837 :             int operator()(int opt, EncodeContext *context, const CtxType *msg,
     470             :                     uint8_t *data, int size) {
     471      739837 :                 int value = Derived::Setter::get(msg);
     472      739840 :                 if (value == opt || opt == -1) {
     473      682369 :                     return EncoderTrue<U, CtxType>()(value, context, msg, data, size);
     474             :                 }
     475       57471 :                 return 0;
     476             :             }
     477             :         };
     478             :         template <typename U>
     479             :         struct EncoderMatch {
     480      255683 :             int operator()(int opt, EncodeContext *context, const T *msg,
     481             :                            uint8_t *data, int size) {
     482             :                 typename U::ContextMatch matcher;
     483      255683 :                 if (matcher.match(msg)) {
     484      184748 :                     return EncoderTrue<U, T>()(opt, context, msg, data, size);
     485             :                 }
     486       70936 :                 return 0;
     487             :             }
     488             :         };
     489             :         template <typename U>
     490             :         struct EncoderRunTime {
     491     6091311 :             int operator()(int opt, EncodeContext *context, const T *msg,
     492             :                            uint8_t *data, int size) {
     493     6091311 :                 if (typeid(*msg) == typeid(typename U::ContextType)) {
     494             :                     typedef typename U::ContextType ctx_t;
     495      956433 :                     const ctx_t *ctx = static_cast<const ctx_t *>(msg);
     496             : 
     497             :                     typedef typename mpl::if_<
     498             :                         boost::is_same<typename Derived::Setter, void>,
     499             :                         EncoderTrue<U, ctx_t>,
     500             :                         EncoderSetter<U, ctx_t>
     501             :                     >::type encoder;
     502      956433 :                     return encoder()(opt, context, ctx, data, size);
     503             :                 }
     504     5134916 :                 return 0;
     505             :             }
     506             :         };
     507             :         struct EncoderNil {
     508             :             int operator()(int opt, EncodeContext *context, T *msg,
     509             :                            uint8_t *data, int size) {
     510             :                 return 0;
     511             :             }
     512             :         };
     513             :         template <typename U>
     514    15901339 :         void operator()(U x) {
     515    15901339 :             if (*resultp < 0 || found) {
     516     9554294 :                 return;
     517             :             }
     518             :             // The choice element can be determined by:
     519             :             // 1. ContextType of the descendent or
     520             :             // 2. ContextMatch type of the descendent
     521             :             // In the case of ContextType match, the match can be either
     522             :             // performed at compile type (in case of exact match) or at run
     523             :             // type using RTTI.
     524             :             typedef typename mpl::if_<
     525             :                 boost::is_same<typename U::second::ContextType, T>,
     526             :                 EncoderTrue<typename U::second, T>,
     527             :                 typename mpl::if_<
     528             :                     boost::is_same<typename U::second::ContextType, void>,
     529             :                     EncoderMatch<typename U::second>,
     530             :                     typename mpl::if_<
     531             :                         boost::is_base_of<T, typename U::second::ContextType>,
     532             :                           EncoderRunTime<typename U::second>,
     533             :                           EncoderNil
     534             :                         >::type
     535             :                     >::type
     536             :             >::type choice_t;
     537             :             choice_t choice;
     538     6347050 :             int result = choice(U::first::value, context, msg, data, size);
     539     6347136 :             if (result < 0) {
     540         334 :                 *resultp = result;
     541     6346802 :             } else if (result > 0) {
     542     1070296 :                 found = true;
     543     1070296 :                 *resultp += result;
     544             :             }
     545             :         }
     546             :     private:
     547             :         EncodeContext *context;
     548             :         const T *msg;
     549             :         uint8_t *data;
     550             :         int size;
     551             :         int *resultp;
     552             :         bool found;
     553             :     };
     554             : };
     555             : 
     556             : template <class Derived>
     557             : class ProtoSequence : public SequenceBase {
     558             : public:
     559             :     template <typename T>
     560             :     struct SequenceParser {
     561     3300248 :         SequenceParser(const uint8_t *data, size_t size, ParseContext *context,
     562             :             T *obj, int *resultp)
     563     3300248 :             : data(data), size(size), context(context), obj(obj),
     564     3300248 :               resultp(resultp) {
     565     3300248 :         }
     566             : 
     567             :         template <typename U>
     568     7941424 :         void operator()(U x) {
     569     7941424 :             if (*resultp < 0) {
     570        9007 :                 return;
     571             :             }
     572             :             typedef detail::DescendentParser<Derived, U> parser_t;
     573     7932417 :             size_t prev_size = context->size();
     574     7932384 :             int result = parser_t::Parse(data, size, context, obj);
     575     7932435 :             if (result < 0) {
     576       12393 :                 *resultp = result;
     577       12393 :                 return;
     578             :             }
     579             : 
     580     7920042 :             data += result;
     581     7920042 :             size -= result;
     582     7920042 :             context->advance(result);
     583     7920048 :             *resultp += result;
     584             : 
     585     7920048 :             if (context->size() != prev_size) {
     586     2793557 :                 size = context->size();
     587     2793610 :                 context->set_total_size();
     588             :             } else {
     589     5126457 :                 context->set_size(prev_size - result);
     590             :             }
     591             :         }
     592             : 
     593             :         const uint8_t *data;
     594             :         size_t size;
     595             :         ParseContext *context;
     596             :         T *obj;
     597             :         int *resultp;
     598             :     };
     599             : 
     600             :     template <typename T>
     601     2340151 :     static int Parse(const uint8_t *data, size_t size, ParseContext *context,
     602             :                      T *obj) {
     603     2340151 :         int min = Derived::kMinOccurs;
     604     2340151 :         if (min == 0 && size == 0) {
     605      209173 :             return 0;
     606             :         }
     607     2130978 :         if (!Derived::Verifier(obj, data, size, context)) {
     608          48 :             PROTO_DEBUG(TYPE_NAME(Derived) << " Verifier failed");
     609          48 :             context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     610             :                     TYPE_NAME(Derived), data,
     611          48 :                     Derived::kSize > 0 ? Derived::kSize : context->size());
     612          48 :             return -1;
     613             :         }
     614     2130940 :         int lensize = Derived::kSize;
     615     2130940 :         int length = size;
     616     2130940 :         if (lensize) {
     617      365513 :             if (size < (size_t) lensize) {
     618           0 :                 PROTO_DEBUG("Error: size = " << size << " lensize = " << lensize);
     619           0 :                 context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     620             :                                   TYPE_NAME(Derived), data, lensize);
     621           0 :                 return -1;
     622             :             }
     623             :             // TODO: options for length (include or exclude length field).
     624      365513 :             length = get_value(data, lensize);
     625      365515 :             assert(length >= 0);
     626      365517 :             size -= lensize;
     627      365517 :             if ((size_t) length > size) {
     628        3036 :                 PROTO_DEBUG("Error: length = " << length << " size = " << size);
     629        3036 :                 context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     630             :                                   TYPE_NAME(Derived), data, lensize);
     631        3036 :                 return -1;
     632             :             }
     633      362481 :             data += lensize;
     634      362481 :             context->advance(lensize);
     635             :         }
     636     2127902 :         int result = lensize;
     637     2127902 :         int max = Derived::kMaxOccurs;
     638     5415771 :         for (int i = 0; (max == -1 || i < max) && (length > 0); i++) {
     639     3300264 :             int sublen = 0;
     640             :             typedef typename Derived::ContextStorer ctx_access_t;
     641             :             typedef typename
     642             :             detail::ContextElementType<ctx_access_t>::ValueType child_obj_t;
     643             :             typedef typename mpl::if_<boost::is_same<typename Derived::ContextSwap, void>,
     644             :                     detail::ContextPush<T, child_obj_t>,
     645             :                     detail::NoContextPush<T>
     646             :             >::type ContextPush;
     647             :             ContextPush pushfn;
     648             :             typedef typename mpl::if_<boost::is_same<child_obj_t, void>,
     649             :                         T, child_obj_t>::type ctx_t;
     650     3300264 :             ctx_t *child_obj = pushfn(context, obj);
     651             : 
     652     3300252 :             SequenceParser<ctx_t> parser(data, length, context, child_obj, &sublen);
     653     3300251 :             mpl::for_each<typename Derived::Sequence>(parser);
     654     3300288 :             if (sublen < 0) {
     655       12393 :                 PROTO_DEBUG(TYPE_NAME(Derived) << ": error: sublen " << sublen);
     656       12393 :                 return -1;
     657             :             }
     658     3287895 :             if (sublen < (int)(context->size() + context->lensize())) {
     659           0 :                 PROTO_DEBUG(TYPE_NAME(Derived) << ": error: sublen " << sublen
     660             :                         << " < " << context->size() << "+" << context->lensize());
     661           0 :                 context->SetError(Derived::kErrorCode, Derived::kErrorSubcode,
     662             :                         TYPE_NAME(Derived), data,
     663           0 :                         context->size()+context->lensize());
     664           0 :                 return -1;
     665             :             }
     666     3287898 :             result += sublen;
     667     3287898 :             data += sublen;
     668     3287898 :             length -= sublen;
     669             : 
     670             :             typedef typename mpl::if_<boost::is_same<typename Derived::ContextSwap, void>,
     671             :                     detail::ContextPop<Derived, T, child_obj_t>,
     672             :                     detail::ContextPop<Derived, void, void>
     673             :             >::type ContextPop;
     674             :             ContextPop popfn;
     675     3287898 :             popfn(context, obj);
     676             :         }
     677     2115507 :         return result;
     678             :     }
     679             : 
     680             :     template <typename T>
     681             :     struct SingleEncoder {
     682             :         typedef typename Derived::Sequence sequence_t;
     683     1795536 :         int operator()(EncodeContext *context, const T *msg, uint8_t *data,
     684             :                        size_t size) {
     685     1795536 :             int result = 0;
     686     1795536 :             SequenceEncoder<T> encoder(context, msg, data, size, &result);
     687     1795582 :             mpl::for_each<sequence_t>(encoder);
     688     1795663 :             return result;
     689             :         }
     690             :     };
     691             : 
     692             :     template <typename T>
     693             :     struct ListEncoder {
     694             :         typedef typename Derived::Sequence sequence_t;
     695      970440 :         int operator()(EncodeContext *context, const T *msg, uint8_t *data,
     696             :                        size_t size) {
     697             :             typedef typename Derived::ContextStorer ctx_access_t;
     698             :             typedef typename
     699             :             detail::ContextElementType<ctx_access_t>::ValueType child_obj_t;
     700      970440 :             int result = 0;
     701             : 
     702      970440 :             detail::ContextIterator<ctx_access_t> iter(msg);
     703     3317070 :             while (iter.HasNext(msg)) {
     704     2346833 :                 child_obj_t *child_obj = iter.Next();
     705     2346825 :                 int subres = 0;
     706     2346825 :                 context->Push();
     707     2346777 :                 SequenceEncoder<child_obj_t> encoder(context, child_obj,
     708             :                                                      data, size, &subres);
     709     2346787 :                 mpl::for_each<sequence_t>(encoder);
     710     2346896 :                 if (subres < 0) {
     711         224 :                     result = subres;
     712         224 :                     break;
     713             :                 }
     714     2346672 :                 result += subres;
     715     2346672 :                 if (data != NULL) {
     716     2346679 :                     data += subres;
     717     2346679 :                     size -= subres;
     718             :                 }
     719     2346672 :                 context->Pop(data != NULL);
     720             :             }
     721      970379 :             return result;
     722             :         }
     723             :     };
     724             : 
     725             :     template <typename T>
     726     2765995 :     static int Encode(EncodeContext *context, const T *msg, uint8_t *data,
     727             :                       size_t size) {
     728     2765995 :         context->Push();
     729     2766004 :         detail::SaveOffset<typename Derived::SaveOffset>()(context);
     730             :         if (Derived::kSize > 0) {
     731             :             // context push callback
     732      401847 :             if (data != NULL) {
     733      401854 :                 context->AddCallback(&SequenceLengthWriteLen, data, Derived::kSize);
     734      401789 :                 data += Derived::kSize;
     735      401789 :                 size -= Derived::kSize;
     736             :             }
     737      401782 :             context->advance(Derived::kSize);
     738             :         }
     739             :         typedef typename mpl::if_<
     740             :             mpl::or_<
     741             :                 mpl::equal_to<mpl::int_<Derived::kMaxOccurs>,
     742             :                               mpl::int_<-1> >,
     743             :                 mpl::greater<mpl::int_<Derived::kMaxOccurs>,
     744             :                              mpl::int_<1> >
     745             :                 >,
     746             :             ListEncoder<T>,
     747             :             SingleEncoder<T> >::type encoder_t;
     748             :         encoder_t encoder;
     749     2766015 :         int result = encoder(context, msg, data, size);
     750     2766167 :         if (result >= 0) {
     751     2765453 :             result += Derived::kSize;
     752     2765453 :             context->Pop(data != NULL);
     753             :         }
     754     2766127 :         return result;
     755             :     }
     756             : 
     757             : private:
     758             :     template <typename T>
     759             :     struct SequenceEncoder {
     760     4142316 :         SequenceEncoder(EncodeContext *context, const T *msg, uint8_t *data,
     761             :                         size_t size, int *resultp)
     762     4142316 :         : context(context), msg(msg), data(data), size(size),
     763     4142316 :           resultp(resultp) {
     764     4142316 :         }
     765             :         template <typename U>
     766     9829713 :         void operator()(U element) {
     767     9829713 :             if (*resultp < 0) {
     768         241 :                 return;
     769             :             }
     770     9829472 :             int res = U::Encode(context, msg, data, size);
     771     9829597 :             if (res < 0) {
     772         735 :                 *resultp = res;
     773             :             } else {
     774     9828862 :                 *resultp += res;
     775             :             }
     776     9829597 :             if (data != NULL) {
     777     9829617 :                 data += res;
     778     9829617 :                 size -= res;
     779             :             }
     780             :         }
     781             : 
     782             :     private:
     783             :         EncodeContext *context;
     784             :         const T *msg;
     785             :         uint8_t *data;
     786             :         size_t size;
     787             :         int *resultp;
     788             :     };
     789             : 
     790      401664 :     static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data,
     791             :                                        int offset, int arg) {
     792      401664 :         int length = context->length() - Derived::kSize;
     793      401645 :         put_value(data, Derived::kSize, length);
     794      401654 :     }
     795             : };
     796             : 
     797             : #endif

Generated by: LCOV version 1.14