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 : #include "base/proto.h" 7 : 8 : #include <boost/bind/bind.hpp> 9 : 10 : using namespace std; 11 : using namespace boost::placeholders; 12 : 13 : namespace detail { 14 : bool debug_ = false; 15 : } 16 : 17 : struct ParseContext::StackFrame { 18 2643977 : StackFrame() : offset(0), lensize(0), size(-1), total_size(-1) { 19 2643935 : } 20 : int offset; // offset of the data pointer at present 21 : int lensize; //size of the length of the current element being parsed 22 : size_t size; 23 : size_t total_size; 24 : std::unique_ptr<ParseObject> data; 25 : }; 26 : 27 196469 : ParseContext::ParseContext() 28 196469 : : offset_(0) { 29 196466 : } 30 : 31 : struct deleter { 32 : template <typename T> 33 196843 : void operator()(T *ptr) { 34 196843 : delete ptr; 35 196850 : } 36 : }; 37 : 38 196454 : ParseContext::~ParseContext() { 39 196454 : for_each(stack_.begin(), stack_.end(), deleter()); 40 196454 : stack_.clear(); 41 196453 : } 42 : 43 188915 : ParseObject *ParseContext::release() { 44 188915 : if (stack_.empty()) { 45 0 : return NULL; 46 : } 47 188914 : StackFrame *current = stack_.back(); 48 188914 : return current->data.release(); 49 : } 50 : 51 2643919 : void ParseContext::Push(ParseObject *data) { 52 2643919 : StackFrame *frame = new StackFrame(); 53 2643934 : frame->data.reset(data); 54 2643842 : stack_.push_back(frame); 55 2643900 : } 56 : 57 2635946 : ParseObject *ParseContext::Pop() { 58 2635946 : if (stack_.size() <= 1) { 59 188909 : return NULL; 60 : } 61 2447038 : StackFrame *frame = stack_.back(); 62 2447033 : ParseObject *obj = frame->data.release(); 63 2447007 : stack_.pop_back(); 64 2447012 : delete frame; 65 2447072 : return obj; 66 : } 67 : 68 658463 : void ParseContext::ReleaseData() { 69 658463 : if (!stack_.empty()) { 70 658464 : StackFrame *frame = stack_.back(); 71 658460 : frame->data.release(); 72 : } 73 658443 : } 74 1283902 : void ParseContext::SwapData(ParseObject *obj) { 75 1283902 : if (!stack_.empty() && obj) { 76 1283871 : StackFrame *frame = stack_.back(); 77 1283855 : frame->data.reset(obj); 78 : } else { 79 0 : delete obj; 80 : } 81 1283849 : } 82 : 83 0 : ParseObject *ParseContext::data() { 84 0 : if (stack_.empty()) { 85 0 : return NULL; 86 : } 87 0 : StackFrame *current = stack_.back(); 88 0 : return current->data.get(); 89 : } 90 : 91 9206166 : void ParseContext::advance(int delta) { 92 9206166 : if (!stack_.empty()) { 93 8625139 : stack_.back()->offset += delta; 94 : } 95 9205172 : offset_ += delta; 96 9205172 : } 97 : 98 2150052 : void ParseContext::set_lensize(int length) { 99 2150052 : if (!stack_.empty()) { 100 2150028 : StackFrame *current = stack_.back(); 101 2150006 : current->lensize = length; 102 : } 103 2150006 : } 104 : 105 3264508 : int ParseContext::lensize() const { 106 3264508 : if (stack_.empty()) { 107 0 : return -1; 108 : } 109 3264487 : StackFrame *current = stack_.back(); 110 3264477 : return current->lensize; 111 : } 112 : 113 7229732 : void ParseContext::set_size(size_t length) { 114 7229732 : if (!stack_.empty()) { 115 6841678 : StackFrame *current = stack_.back(); 116 6841567 : current->size = length; 117 : } 118 7229319 : } 119 : 120 23462733 : size_t ParseContext::size() const { 121 23462733 : if (stack_.empty()) { 122 972530 : return -1; 123 : } 124 22487232 : StackFrame *current = stack_.back(); 125 22486102 : return current->size; 126 : } 127 : 128 2778296 : void ParseContext::set_total_size() { 129 2778296 : if (!stack_.empty()) { 130 2778259 : StackFrame *current = stack_.back(); 131 2778244 : current->total_size = current->size; 132 : } 133 2778244 : } 134 : 135 86536 : size_t ParseContext::total_size() const { 136 86536 : if (stack_.empty()) { 137 0 : return -1; 138 : } 139 86538 : StackFrame *current = stack_.back(); 140 86536 : return current->total_size >= 0 ? current->total_size : current->size; 141 : } 142 : 143 7840 : void ParseContext::SetError(int error, int subcode, std::string type, 144 : const uint8_t *data, int data_size) { 145 7840 : if (error_context_.error_code) { 146 : // Error already set. Ignore this one. 147 300 : return; 148 : } 149 7540 : error_context_.error_code = error; 150 7540 : error_context_.error_subcode = subcode; 151 7540 : error_context_.type_name = type; 152 7540 : error_context_.data = data; 153 7540 : error_context_.data_size = data_size; 154 : } 155 : 156 : struct EncodeContext::StackFrame { 157 : typedef boost::function<void(EncodeContext *)> CallbackFn; 158 : typedef std::vector<CallbackFn>::iterator CallbackIterator; 159 5065221 : StackFrame() : offset(0) { 160 5065189 : } 161 : int offset; 162 : std::vector<CallbackFn> callbacks; 163 : }; 164 : 165 275751 : EncodeContext::EncodeContext() { 166 275741 : } 167 : 168 275762 : EncodeContext::~EncodeContext() { 169 275762 : } 170 : 171 5064622 : void EncodeContext::Push() { 172 5064622 : StackFrame *frame = new StackFrame(); 173 5065172 : stack_.push_back(frame); 174 5063361 : } 175 : 176 5064034 : void EncodeContext::Pop(bool callback) { 177 5064034 : StackFrame *frame = &stack_.back(); 178 5062755 : if (callback) { 179 5062578 : for (StackFrame::CallbackIterator iter = 180 12554027 : frame->callbacks.begin(); iter != frame->callbacks.end(); ++iter) { 181 2428671 : StackFrame::CallbackFn cb = *iter; 182 2428753 : (cb)(this); 183 2428421 : } 184 : } 185 : 186 5063157 : int p_offset = frame->offset; 187 5063157 : stack_.pop_back(); // deletes frame 188 5063422 : if (!stack_.empty()) { 189 4787593 : StackFrame *top = &(stack_.back()); 190 4786447 : top->offset += p_offset; 191 : } 192 5061689 : } 193 : 194 8572870 : void EncodeContext::advance(int delta) { 195 8572870 : if (stack_.empty()) { 196 0 : return; 197 : } 198 8570901 : StackFrame *frame = &stack_.back(); 199 8566474 : frame->offset += delta; 200 : } 201 : 202 2192141 : int EncodeContext::length() const { 203 2192141 : const StackFrame *frame = &stack_.back(); 204 2191893 : return frame->offset; 205 : }; 206 : 207 2429601 : void EncodeContext::AddCallback(CallbackType cb, uint8_t *data, 208 : int element_size) { 209 2429601 : StackFrame *top = &(stack_.back()); 210 2429169 : top->callbacks.push_back( 211 4857738 : boost::bind(cb, _1, data, top->offset, element_size)); 212 2428477 : } 213 : 214 572925 : void EncodeOffsets::SaveOffset(std::string key, int offset) { 215 : std::pair<std::map<std::string, int>::iterator, bool > result = 216 572925 : offsets_.insert(make_pair(key, offset)); 217 573170 : if (!result.second) { 218 4 : PROTO_DEBUG("Offset for " << key << " already set"); 219 : } 220 573170 : } 221 : 222 572890 : void EncodeContext::SaveOffset(std::string key) { 223 572890 : int length = 0; 224 572890 : for (boost::ptr_vector<StackFrame>::iterator it = stack_.begin(); 225 2211144 : it != stack_.end(); ++it) { 226 1638271 : length += it->offset; 227 : } 228 572713 : PROTO_DEBUG("Saving Offset for " << key << " at " << length); 229 572713 : offsets_.SaveOffset(key, length); 230 573168 : } 231 : 232 190165 : int EncodeOffsets::FindOffset(const char *key) { 233 190165 : std::map<std::string, int>::iterator it = offsets_.find(std::string(key)); 234 190149 : if (it == offsets_.end()) 235 0 : return -1; 236 190147 : return it->second; 237 : }