Line data Source code
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 : 16 : struct ParseContext::StackFrame { 17 2641020 : StackFrame() : offset(0), lensize(0), size(-1), total_size(-1) { 18 2640982 : } 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 : 26 196398 : ParseContext::ParseContext() 27 196398 : : offset_(0) { 28 196393 : } 29 : 30 : struct deleter { 31 : template <typename T> 32 196784 : void operator()(T *ptr) { 33 196784 : delete ptr; 34 196787 : } 35 : }; 36 : 37 196390 : ParseContext::~ParseContext() { 38 196390 : for_each(stack_.begin(), stack_.end(), deleter()); 39 196394 : stack_.clear(); 40 196395 : } 41 : 42 188851 : ParseObject *ParseContext::release() { 43 188851 : if (stack_.empty()) { 44 0 : return NULL; 45 : } 46 188855 : StackFrame *current = stack_.back(); 47 188854 : return current->data.release(); 48 : } 49 : 50 2640994 : void ParseContext::Push(ParseObject *data) { 51 2640994 : StackFrame *frame = new StackFrame(); 52 2640984 : frame->data.reset(data); 53 2640914 : stack_.push_back(frame); 54 2640942 : } 55 : 56 2632982 : ParseObject *ParseContext::Pop() { 57 2632982 : if (stack_.size() <= 1) { 58 188849 : return NULL; 59 : } 60 2444133 : StackFrame *frame = stack_.back(); 61 2444142 : ParseObject *obj = frame->data.release(); 62 2444131 : stack_.pop_back(); 63 2444130 : delete frame; 64 2444160 : return obj; 65 : } 66 : 67 657594 : void ParseContext::ReleaseData() { 68 657594 : if (!stack_.empty()) { 69 657589 : StackFrame *frame = stack_.back(); 70 657586 : frame->data.release(); 71 : } 72 657587 : } 73 1282059 : void ParseContext::SwapData(ParseObject *obj) { 74 1282059 : if (!stack_.empty() && obj) { 75 1282042 : StackFrame *frame = stack_.back(); 76 1282036 : frame->data.reset(obj); 77 : } else { 78 1 : delete obj; 79 : } 80 1282033 : } 81 : 82 0 : ParseObject *ParseContext::data() { 83 0 : if (stack_.empty()) { 84 0 : return NULL; 85 : } 86 0 : StackFrame *current = stack_.back(); 87 0 : return current->data.get(); 88 : } 89 : 90 9196404 : void ParseContext::advance(int delta) { 91 9196404 : if (!stack_.empty()) { 92 8615691 : stack_.back()->offset += delta; 93 : } 94 9195665 : offset_ += delta; 95 9195665 : } 96 : 97 2148095 : void ParseContext::set_lensize(int length) { 98 2148095 : if (!stack_.empty()) { 99 2148102 : StackFrame *current = stack_.back(); 100 2148096 : current->lensize = length; 101 : } 102 2148096 : } 103 : 104 3260610 : int ParseContext::lensize() const { 105 3260610 : if (stack_.empty()) { 106 0 : return -1; 107 : } 108 3260608 : StackFrame *current = stack_.back(); 109 3260606 : return current->lensize; 110 : } 111 : 112 7222587 : void ParseContext::set_size(size_t length) { 113 7222587 : if (!stack_.empty()) { 114 6834640 : StackFrame *current = stack_.back(); 115 6834526 : current->size = length; 116 : } 117 7222207 : } 118 : 119 23438723 : size_t ParseContext::size() const { 120 23438723 : if (stack_.empty()) { 121 972204 : return -1; 122 : } 123 22464134 : StackFrame *current = stack_.back(); 124 22463306 : return current->size; 125 : } 126 : 127 2775407 : void ParseContext::set_total_size() { 128 2775407 : if (!stack_.empty()) { 129 2775392 : StackFrame *current = stack_.back(); 130 2775384 : current->total_size = current->size; 131 : } 132 2775384 : } 133 : 134 86158 : size_t ParseContext::total_size() const { 135 86158 : if (stack_.empty()) { 136 0 : return -1; 137 : } 138 86162 : StackFrame *current = stack_.back(); 139 86161 : return current->total_size >= 0 ? current->total_size : current->size; 140 : } 141 : 142 7840 : void ParseContext::SetError(int error, int subcode, std::string type, 143 : const uint8_t *data, int data_size) { 144 7840 : if (error_context_.error_code) { 145 : // Error already set. Ignore this one. 146 300 : return; 147 : } 148 7540 : error_context_.error_code = error; 149 7540 : error_context_.error_subcode = subcode; 150 7540 : error_context_.type_name = type; 151 7540 : error_context_.data = data; 152 7540 : error_context_.data_size = data_size; 153 : } 154 : 155 : struct EncodeContext::StackFrame { 156 : typedef boost::function<void(EncodeContext *)> CallbackFn; 157 : typedef std::vector<CallbackFn>::iterator CallbackIterator; 158 5077613 : StackFrame() : offset(0) { 159 5077452 : } 160 : int offset; 161 : std::vector<CallbackFn> callbacks; 162 : }; 163 : 164 275628 : EncodeContext::EncodeContext() { 165 275633 : } 166 : 167 275644 : EncodeContext::~EncodeContext() { 168 275644 : } 169 : 170 5077012 : void EncodeContext::Push() { 171 5077012 : StackFrame *frame = new StackFrame(); 172 5077428 : stack_.push_back(frame); 173 5075747 : } 174 : 175 5076392 : void EncodeContext::Pop(bool callback) { 176 5076392 : StackFrame *frame = &stack_.back(); 177 5075257 : if (callback) { 178 5075016 : for (StackFrame::CallbackIterator iter = 179 12587320 : frame->callbacks.begin(); iter != frame->callbacks.end(); ++iter) { 180 2436988 : StackFrame::CallbackFn cb = *iter; 181 2437032 : (cb)(this); 182 2436805 : } 183 : } 184 : 185 5075587 : int p_offset = frame->offset; 186 5075587 : stack_.pop_back(); // deletes frame 187 5075818 : if (!stack_.empty()) { 188 4799994 : StackFrame *top = &(stack_.back()); 189 4798832 : top->offset += p_offset; 190 : } 191 5074015 : } 192 : 193 8595594 : void EncodeContext::advance(int delta) { 194 8595594 : if (stack_.empty()) { 195 0 : return; 196 : } 197 8593581 : StackFrame *frame = &stack_.back(); 198 8589574 : frame->offset += delta; 199 : } 200 : 201 2200448 : int EncodeContext::length() const { 202 2200448 : const StackFrame *frame = &stack_.back(); 203 2200210 : return frame->offset; 204 : }; 205 : 206 2437856 : void EncodeContext::AddCallback(CallbackType cb, uint8_t *data, 207 : int element_size) { 208 2437856 : StackFrame *top = &(stack_.back()); 209 2437466 : top->callbacks.push_back( 210 4874430 : boost::bind(cb, _1, data, top->offset, element_size)); 211 2436928 : } 212 : 213 578758 : void EncodeOffsets::SaveOffset(std::string key, int offset) { 214 : std::pair<std::map<std::string, int>::iterator, bool > result = 215 578758 : offsets_.insert(make_pair(key, offset)); 216 578954 : if (!result.second) { 217 4 : PROTO_DEBUG("Offset for " << key << " already set"); 218 : } 219 578954 : } 220 : 221 578727 : void EncodeContext::SaveOffset(std::string key) { 222 578727 : int length = 0; 223 578727 : for (boost::ptr_vector<StackFrame>::iterator it = stack_.begin(); 224 2232103 : it != stack_.end(); ++it) { 225 1653369 : length += it->offset; 226 : } 227 578601 : PROTO_DEBUG("Saving Offset for " << key << " at " << length); 228 578601 : offsets_.SaveOffset(key, length); 229 578953 : } 230 : 231 181582 : int EncodeOffsets::FindOffset(const char *key) { 232 181582 : std::map<std::string, int>::iterator it = offsets_.find(std::string(key)); 233 181564 : if (it == offsets_.end()) 234 0 : return -1; 235 181561 : return it->second; 236 : }