OpenSDN source code
src/contrail-common/base/proto.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3  */
4 
5 #include "base/proto.h"
6 
7 #include <boost/bind/bind.hpp>
8 
9 using namespace std;
10 using namespace boost::placeholders;
11 
12 namespace detail {
13  bool debug_ = false;
14 }
15 
17  StackFrame() : offset(0), lensize(0), size(-1), total_size(-1) {
18  }
19  int offset; // offset of the data pointer at present
20  int lensize; //size of the length of the current element being parsed
21  size_t size;
22  size_t total_size;
23  std::unique_ptr<ParseObject> data;
24 };
25 
27  : offset_(0) {
28 }
29 
30 struct deleter {
31  template <typename T>
32  void operator()(T *ptr) {
33  delete ptr;
34  }
35 };
36 
38  for_each(stack_.begin(), stack_.end(), deleter());
39  stack_.clear();
40 }
41 
43  if (stack_.empty()) {
44  return NULL;
45  }
46  StackFrame *current = stack_.back();
47  return current->data.release();
48 }
49 
51  StackFrame *frame = new StackFrame();
52  frame->data.reset(data);
53  stack_.push_back(frame);
54 }
55 
57  if (stack_.size() <= 1) {
58  return NULL;
59  }
60  StackFrame *frame = stack_.back();
61  ParseObject *obj = frame->data.release();
62  stack_.pop_back();
63  delete frame;
64  return obj;
65 }
66 
68  if (!stack_.empty()) {
69  StackFrame *frame = stack_.back();
70  frame->data.release();
71  }
72 }
74  if (!stack_.empty() && obj) {
75  StackFrame *frame = stack_.back();
76  frame->data.reset(obj);
77  } else {
78  delete obj;
79  }
80 }
81 
83  if (stack_.empty()) {
84  return NULL;
85  }
86  StackFrame *current = stack_.back();
87  return current->data.get();
88 }
89 
90 void ParseContext::advance(int delta) {
91  if (!stack_.empty()) {
92  stack_.back()->offset += delta;
93  }
94  offset_ += delta;
95 }
96 
97 void ParseContext::set_lensize(int length) {
98  if (!stack_.empty()) {
99  StackFrame *current = stack_.back();
100  current->lensize = length;
101  }
102 }
103 
105  if (stack_.empty()) {
106  return -1;
107  }
108  StackFrame *current = stack_.back();
109  return current->lensize;
110 }
111 
112 void ParseContext::set_size(size_t length) {
113  if (!stack_.empty()) {
114  StackFrame *current = stack_.back();
115  current->size = length;
116  }
117 }
118 
119 size_t ParseContext::size() const {
120  if (stack_.empty()) {
121  return -1;
122  }
123  StackFrame *current = stack_.back();
124  return current->size;
125 }
126 
128  if (!stack_.empty()) {
129  StackFrame *current = stack_.back();
130  current->total_size = current->size;
131  }
132 }
133 
134 size_t ParseContext::total_size() const {
135  if (stack_.empty()) {
136  return -1;
137  }
138  StackFrame *current = stack_.back();
139  return current->total_size >= 0 ? current->total_size : current->size;
140 }
141 
142 void ParseContext::SetError(int error, int subcode, std::string type,
143  const uint8_t *data, int data_size) {
145  // Error already set. Ignore this one.
146  return;
147  }
148  error_context_.error_code = error;
149  error_context_.error_subcode = subcode;
152  error_context_.data_size = data_size;
153 }
154 
156  typedef boost::function<void(EncodeContext *)> CallbackFn;
157  typedef std::vector<CallbackFn>::iterator CallbackIterator;
159  }
160  int offset;
161  std::vector<CallbackFn> callbacks;
162 };
163 
165 }
166 
168 }
169 
171  StackFrame *frame = new StackFrame();
172  stack_.push_back(frame);
173 }
174 
175 void EncodeContext::Pop(bool callback) {
176  StackFrame *frame = &stack_.back();
177  if (callback) {
178  for (StackFrame::CallbackIterator iter =
179  frame->callbacks.begin(); iter != frame->callbacks.end(); ++iter) {
180  StackFrame::CallbackFn cb = *iter;
181  (cb)(this);
182  }
183  }
184 
185  int p_offset = frame->offset;
186  stack_.pop_back(); // deletes frame
187  if (!stack_.empty()) {
188  StackFrame *top = &(stack_.back());
189  top->offset += p_offset;
190  }
191 }
192 
193 void EncodeContext::advance(int delta) {
194  if (stack_.empty()) {
195  return;
196  }
197  StackFrame *frame = &stack_.back();
198  frame->offset += delta;
199 }
200 
202  const StackFrame *frame = &stack_.back();
203  return frame->offset;
204 };
205 
207  int element_size) {
208  StackFrame *top = &(stack_.back());
209  top->callbacks.push_back(
210  boost::bind(cb, _1, data, top->offset, element_size));
211 }
212 
213 void EncodeOffsets::SaveOffset(std::string key, int offset) {
214  std::pair<std::map<std::string, int>::iterator, bool > result =
215  offsets_.insert(make_pair(key, offset));
216  if (!result.second) {
217  PROTO_DEBUG("Offset for " << key << " already set");
218  }
219 }
220 
221 void EncodeContext::SaveOffset(std::string key) {
222  int length = 0;
223  for (boost::ptr_vector<StackFrame>::iterator it = stack_.begin();
224  it != stack_.end(); ++it) {
225  length += it->offset;
226  }
227  PROTO_DEBUG("Saving Offset for " << key << " at " << length);
228  offsets_.SaveOffset(key, length);
229 }
230 
231 int EncodeOffsets::FindOffset(const char *key) {
232  std::map<std::string, int>::iterator it = offsets_.find(std::string(key));
233  if (it == offsets_.end())
234  return -1;
235  return it->second;
236 }
boost::function< void(EncodeContext *, uint8_t *, int, int)> CallbackType
void AddCallback(CallbackType cb, uint8_t *data, int arg)
boost::ptr_vector< StackFrame > stack_
void SaveOffset(std::string, int)
std::map< std::string, int > offsets_
Definition: parse_object.h:99
void set_lensize(int lensize)
void set_size(size_t length)
void SetError(int error, int subcode, std::string type, const uint8_t *data, int data_size)
void Push(ParseObject *data)
ParseErrorContext error_context_
void SwapData(ParseObject *obj)
std::vector< StackFrame * > stack_
uint8_t type
Definition: load_balance.h:2
#define PROTO_DEBUG(args...)
Definition: proto_impl.h:13
std::vector< CallbackFn >::iterator CallbackIterator
boost::function< void(EncodeContext *)> CallbackFn
std::unique_ptr< ParseObject > data
const uint8_t * data
Definition: parse_object.h:89
std::string type_name
Definition: parse_object.h:88