5 #ifndef ctrlplane_proto_h
6 #define ctrlplane_proto_h
13 #include <boost/ptr_container/ptr_vector.hpp>
14 #include <boost/function.hpp>
15 #include <boost/type_traits/is_same.hpp>
16 #include <boost/type_traits/is_base_of.hpp>
17 #include <boost/mpl/equal_to.hpp>
18 #include <boost/mpl/for_each.hpp>
19 #include <boost/mpl/greater.hpp>
20 #include <boost/mpl/list.hpp>
21 #include <boost/mpl/map.hpp>
22 #include <boost/mpl/or.hpp>
23 #include <boost/mpl/vector.hpp>
24 #include <boost/mpl/string.hpp>
30 namespace mpl = boost::mpl;
58 void SetError(
int error,
int subcode, std::string
type,
const uint8_t *data,
71 typedef boost::function<void(EncodeContext *, uint8_t *, int, int)>
CallbackType;
77 void Pop(
bool callback);
87 boost::ptr_vector<StackFrame>
stack_;
91 template <
class C,
typename T, T C::* Member>
94 static void set(C *obj, T value) {
97 static T
get(
const C *obj) {
102 template <
class C, std::
string C::* Member>
104 static void set(C*obj,
const uint8_t *data,
size_t elem_size) {
105 obj->*Member = std::string((
const char *) data, elem_size);
107 static int size(
const C *obj) {
108 return (obj->*Member).size();
110 static std::string::const_iterator
begin(
const C *obj) {
111 return (obj->*Member).begin();
113 static std::string::const_iterator
end(
const C *obj) {
114 return (obj->*Member).end();
118 template <
class C,
typename T, std::vector<T> C::* Member>
120 static void set(C*obj,
const uint8_t *data,
size_t elem_size) {
121 obj->*Member = std::vector<T>();
122 size_t size =
sizeof(T);
123 for (
size_t i = 0; i < elem_size; i +=
size) {
126 (obj->*Member).push_back(value);
129 static int size(
const C *obj) {
130 return (obj->*Member).size() *
sizeof(T);
132 static typename std::vector<T>::const_iterator
begin(
const C *obj) {
133 return (obj->*Member).begin();
135 static typename std::vector<T>::const_iterator
end(
const C *obj) {
136 return (obj->*Member).end();
141 template <
typename T>
145 template <
typename T>
150 template <
typename Obj,
typename Col, Col Obj::* Member>
154 typedef typename CollectionType::const_iterator
iterator;
156 (obj->*Member).push_back(element);
159 return (obj->*Member).begin();
162 return (obj->*Member).end();
180 static bool Verifier(
const void * obj,
const uint8_t *data,
size_t size,
208 template<
class Derived>
213 template <
typename T>
214 static void Writer(T *msg, uint8_t *data,
size_t size) {
215 typedef typename Derived::Setter setter_t;
216 typedef typename mpl::if_<
218 mpl::int_<Derived::kSize>, mpl::int_<-1> >,
223 writer(data, Derived::kSize, msg);
226 template <
typename T>
229 typedef typename mpl::if_<
231 mpl::int_<Derived::kSize>, mpl::int_<0> >,
239 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
241 Derived::kSize > 0 ? Derived::kSize : context->
size());
244 if (!Derived::Verifier(obj, data, size, context)) {
246 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
248 Derived::kSize > 0 ? Derived::kSize : context->
size());
252 typedef typename Derived::ContextInit ctx_init_t;
253 ctx_init_t initializer;
257 int res = slen(context, data, Derived::kSize, size, obj);
260 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
265 typedef typename mpl::if_<boost::is_same<typename Derived::SizeSetter, void>,
267 mpl::equal_to<mpl::int_<Derived::kSize>, mpl::int_<-1> >,
270 mpl::greater<mpl::int_<Derived::kSize>, mpl::int_<0> >,
279 res = setter(data, size, context, obj);
281 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
283 Derived::kSize > 0 ? Derived::kSize : context->
size());
288 template <
typename T>
292 mpl::if_<boost::is_same<typename Derived::SizeSetter, void>,
293 typename mpl::if_<mpl::equal_to<mpl::int_<Derived::kSize>, mpl::int_<-1> >,
296 typename Derived::SizeSetter
297 >::type size_value_t;
299 int element_size = size_value_t::get(msg);
301 context->
advance(element_size);
304 assert(element_size >= 0);
305 if (size < (
size_t) element_size) {
312 boost::is_same<typename Derived::Setter, void>,
318 cbadd(context, data, element_size);
322 Derived::Writer(msg, data, size);
324 context->
advance(element_size);
330 int offset,
int element_size) {
331 int length = context->
length() - offset - element_size;
336 template <
typename Setter,
typename T>
339 Setter::set(obj, value);
343 template <
typename T>
348 template <
class Derived>
351 template <
typename T>
354 int advance = Derived::kSize;
357 if (size < (
size_t) advance) {
358 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
369 typedef typename mpl::if_<
370 boost::is_same<typename Derived::Setter, void>,
375 choice_setter_t setter;
378 int result =
ParseChoice(data, size, value, context, obj);
382 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
383 TYPE_NAME(Derived), data - advance, advance);
391 template <
typename T>
394 typedef typename Derived::Choice choice_t;
396 ChoiceEncoder<T> encoder(context, msg, data, size, &result);
397 mpl::for_each<choice_t>(encoder);
402 template <
typename T>
406 : data(data), size(size), value(value), context(context),
407 obj(obj), resultp(resultp),
found(false) {
409 template <
typename U>
412 if (U::first::value != -1 && U::first::value !=
value) {
428 template <
typename T>
429 static int ParseChoice(
const uint8_t *data,
size_t size,
int value,
432 ChoiceMatcher<T> match(data, size, value, context, obj, &result);
433 mpl::for_each<typename Derived::Choice>(match);
437 template <
typename T>
441 : context(context), msg(msg), data(data), size(size),
442 resultp(resultp),
found(false) {
444 template <
typename U,
typename CtxType>
448 if (Derived::kSize) {
450 if (size < Derived::kSize)
return -1;
452 data += Derived::kSize;
453 size -= Derived::kSize;
455 context->
advance(Derived::kSize);
457 int result = U::Encode(context, msg, data, size);
459 result += Derived::kSize;
464 template <
typename U,
typename CtxType>
468 int value = Derived::Setter::get(msg);
469 if (value == opt || opt == -1) {
475 template <
typename U>
479 typename U::ContextMatch matcher;
480 if (matcher.match(msg)) {
486 template <
typename U>
490 if (
typeid(*msg) ==
typeid(
typename U::ContextType)) {
491 typedef typename U::ContextType ctx_t;
492 const ctx_t *ctx =
static_cast<const ctx_t *
>(
msg);
494 typedef typename mpl::if_<
495 boost::is_same<typename Derived::Setter, void>,
510 template <
typename U>
521 typedef typename mpl::if_<
522 boost::is_same<typename U::second::ContextType, T>,
525 boost::is_same<typename U::second::ContextType, void>,
528 boost::is_base_of<T, typename U::second::ContextType>,
538 }
else if (result > 0) {
553 template <
class Derived>
556 template <
typename T>
560 : data(data), size(size), context(context), obj(obj),
564 template <
typename U>
597 template <
typename T>
600 int min = Derived::kMinOccurs;
601 if (min == 0 && size == 0) {
604 if (!Derived::Verifier(obj, data, size, context)) {
606 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
608 Derived::kSize > 0 ? Derived::kSize : context->
size());
611 int lensize = Derived::kSize;
614 if (size < (
size_t) lensize) {
615 PROTO_DEBUG(
"Error: size = " << size <<
" lensize = " << lensize);
616 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
624 if ((
size_t) length > size) {
625 PROTO_DEBUG(
"Error: length = " << length <<
" size = " << size);
626 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
633 int result = lensize;
634 int max = Derived::kMaxOccurs;
635 for (
int i = 0; (max == -1 || i < max) && (length > 0); i++) {
637 typedef typename Derived::ContextStorer ctx_access_t;
640 typedef typename mpl::if_<boost::is_same<typename Derived::ContextSwap, void>,
645 typedef typename mpl::if_<boost::is_same<child_obj_t, void>,
646 T, child_obj_t>
::type ctx_t;
647 ctx_t *child_obj = pushfn(context, obj);
649 SequenceParser<ctx_t> parser(data, length, context, child_obj, &sublen);
650 mpl::for_each<typename Derived::Sequence>(parser);
655 if (sublen < (
int)(context->
size() + context->
lensize())) {
657 <<
" < " << context->
size() <<
"+" << context->
lensize());
658 context->
SetError(Derived::kErrorCode, Derived::kErrorSubcode,
667 typedef typename mpl::if_<boost::is_same<typename Derived::ContextSwap, void>,
677 template <
typename T>
684 mpl::for_each<sequence_t>(encoder);
689 template <
typename T>
694 typedef typename Derived::ContextStorer ctx_access_t;
701 child_obj_t *child_obj = iter.
Next();
705 data, size, &subres);
706 mpl::for_each<sequence_t>(encoder);
716 context->
Pop(data != NULL);
722 template <
typename T>
727 if (Derived::kSize > 0) {
731 data += Derived::kSize;
732 size -= Derived::kSize;
734 context->
advance(Derived::kSize);
736 typedef typename mpl::if_<
738 mpl::equal_to<mpl::int_<Derived::kMaxOccurs>,
740 mpl::greater<mpl::int_<Derived::kMaxOccurs>,
744 SingleEncoder<T> >
::type encoder_t;
746 int result = encoder(context, msg, data, size);
748 result += Derived::kSize;
749 context->
Pop(data != NULL);
755 template <
typename T>
759 : context(context), msg(msg), data(data), size(size),
762 template <
typename U>
788 int offset,
int arg) {
789 int length = context->
length() - Derived::kSize;
static bool Verifier(const void *obj, const uint8_t *data, size_t size, ParseContext *context)
#define PROTO_DEBUG(args...)
Derived::Sequence sequence_t
static const int kErrorCode
static int size(const C *obj)
static int size(const C *obj)
static const int kMaxOccurs
static std::string::const_iterator begin(const C *obj)
int operator()(int opt, EncodeContext *context, T *msg, uint8_t *data, int size)
static void insert(Obj *obj, ValueType *element)
void set_lensize(int lensize)
static std::vector< T >::const_iterator begin(const C *obj)
void SwapData(ParseObject *obj)
static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data, int offset, int arg)
Derived::Sequence sequence_t
void operator()(T *obj, int &value)
bool HasNext(Obj *obj) const
int operator()(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
SequenceParser(const uint8_t *data, size_t size, ParseContext *context, T *obj, int *resultp)
static int ParseChoice(const uint8_t *data, size_t size, int value, ParseContext *context, T *obj)
static void set(C *obj, const uint8_t *data, size_t elem_size)
size_t total_size() const
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
void SaveOffset(std::string)
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
void SetError(int error, int subcode, std::string type, const uint8_t *data, int data_size)
static int Encode(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
static uint64_t get_value(const uint8_t *data, int size)
static const int kErrorSubcode
ValueType< typename Col::value_type >::type ValueType
void operator()(U element)
CollectionType::const_iterator iterator
static const int kMinOccurs
EncodeOffsets & encode_offsets()
const ParseErrorContext & error_context()
static void set(C *obj, const uint8_t *data, size_t elem_size)
ParseErrorContext error_context_
int operator()(int opt, EncodeContext *context, const CtxType *msg, uint8_t *data, int size)
std::vector< StackFrame * > stack_
static int Encode(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
void operator()(T *obj, int value)
void AddCallback(CallbackType cb, uint8_t *data, int arg)
int operator()(int opt, EncodeContext *context, const CtxType *msg, uint8_t *data, int size)
boost::function< void(EncodeContext *, uint8_t *, int, int)> CallbackType
static void SequenceLengthWriteLen(EncodeContext *context, uint8_t *data, int offset, int element_size)
static int Parse(const uint8_t *data, size_t size, ParseContext *context, T *obj)
static void set(C *obj, T value)
static iterator begin(const Obj *obj)
ChoiceMatcher(const uint8_t *data, size_t size, int value, ParseContext *context, T *obj, int *resultp)
void set_size(size_t length)
static std::string::const_iterator end(const C *obj)
static int Encode(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
int operator()(int opt, EncodeContext *context, const T *msg, uint8_t *data, int size)
boost::ptr_vector< StackFrame > stack_
static iterator end(const Obj *obj)
int operator()(int opt, EncodeContext *context, const T *msg, uint8_t *data, int size)
static std::vector< T >::const_iterator end(const C *obj)
static void Writer(T *msg, uint8_t *data, size_t size)
SequenceEncoder(EncodeContext *context, const T *msg, uint8_t *data, size_t size, int *resultp)
void Push(ParseObject *data)
int operator()(EncodeContext *context, const T *msg, uint8_t *data, size_t size)
ContextAccessor::ValueType ValueType
ChoiceEncoder(EncodeContext *context, const T *msg, uint8_t *data, int size, int *resultp)
static void put_value(uint8_t *data, int size, uint64_t value)