Thinger.io Client Library for ARM mbed platform. This is a generic library that provides a base class that can be used to other develop hardware specific libraries.

Fork of ThingerClient by Alvaro Luis Bustamante

Committer:
alvarolb
Date:
Thu Dec 24 13:18:08 2015 +0000
Revision:
0:b75d784c7c1a
Child:
4:de51256455f7
Initial Commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
alvarolb 0:b75d784c7c1a 1 // The MIT License (MIT)
alvarolb 0:b75d784c7c1a 2 //
alvarolb 0:b75d784c7c1a 3 // Copyright (c) 2015 THINGER LTD
alvarolb 0:b75d784c7c1a 4 // Author: alvarolb@gmail.com (Alvaro Luis Bustamante)
alvarolb 0:b75d784c7c1a 5 //
alvarolb 0:b75d784c7c1a 6 // Permission is hereby granted, free of charge, to any person obtaining a copy
alvarolb 0:b75d784c7c1a 7 // of this software and associated documentation files (the "Software"), to deal
alvarolb 0:b75d784c7c1a 8 // in the Software without restriction, including without limitation the rights
alvarolb 0:b75d784c7c1a 9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
alvarolb 0:b75d784c7c1a 10 // copies of the Software, and to permit persons to whom the Software is
alvarolb 0:b75d784c7c1a 11 // furnished to do so, subject to the following conditions:
alvarolb 0:b75d784c7c1a 12 //
alvarolb 0:b75d784c7c1a 13 // The above copyright notice and this permission notice shall be included in
alvarolb 0:b75d784c7c1a 14 // all copies or substantial portions of the Software.
alvarolb 0:b75d784c7c1a 15 //
alvarolb 0:b75d784c7c1a 16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
alvarolb 0:b75d784c7c1a 17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
alvarolb 0:b75d784c7c1a 18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
alvarolb 0:b75d784c7c1a 19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
alvarolb 0:b75d784c7c1a 20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
alvarolb 0:b75d784c7c1a 21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
alvarolb 0:b75d784c7c1a 22 // THE SOFTWARE.
alvarolb 0:b75d784c7c1a 23
alvarolb 0:b75d784c7c1a 24 #ifndef PSON_HPP
alvarolb 0:b75d784c7c1a 25 #define PSON_HPP
alvarolb 0:b75d784c7c1a 26
alvarolb 0:b75d784c7c1a 27 #include <stdint.h>
alvarolb 0:b75d784c7c1a 28 #include <string.h>
alvarolb 0:b75d784c7c1a 29 #include <math.h>
alvarolb 0:b75d784c7c1a 30 #include <stdlib.h>
alvarolb 0:b75d784c7c1a 31
alvarolb 0:b75d784c7c1a 32 namespace protoson {
alvarolb 0:b75d784c7c1a 33
alvarolb 0:b75d784c7c1a 34 class memory_allocator{
alvarolb 0:b75d784c7c1a 35 public:
alvarolb 0:b75d784c7c1a 36 virtual void *allocate(size_t size) = 0;
alvarolb 0:b75d784c7c1a 37 virtual void deallocate(void *) = 0;
alvarolb 0:b75d784c7c1a 38 };
alvarolb 0:b75d784c7c1a 39
alvarolb 0:b75d784c7c1a 40 template<size_t buffer_size>
alvarolb 0:b75d784c7c1a 41 class circular_memory_allocator : public memory_allocator{
alvarolb 0:b75d784c7c1a 42 private:
alvarolb 0:b75d784c7c1a 43 uint8_t buffer_[buffer_size];
alvarolb 0:b75d784c7c1a 44 size_t index_;
alvarolb 0:b75d784c7c1a 45 public:
alvarolb 0:b75d784c7c1a 46 circular_memory_allocator() : index_(0) {
alvarolb 0:b75d784c7c1a 47 }
alvarolb 0:b75d784c7c1a 48
alvarolb 0:b75d784c7c1a 49 virtual void *allocate(size_t size) {
alvarolb 0:b75d784c7c1a 50 if (index_ + size > buffer_size) {
alvarolb 0:b75d784c7c1a 51 index_ = 0;
alvarolb 0:b75d784c7c1a 52 }
alvarolb 0:b75d784c7c1a 53 void *position = &buffer_[index_];
alvarolb 0:b75d784c7c1a 54 index_ += size;
alvarolb 0:b75d784c7c1a 55 return position;
alvarolb 0:b75d784c7c1a 56 }
alvarolb 0:b75d784c7c1a 57
alvarolb 0:b75d784c7c1a 58 virtual void deallocate(void *) {
alvarolb 0:b75d784c7c1a 59
alvarolb 0:b75d784c7c1a 60 }
alvarolb 0:b75d784c7c1a 61 };
alvarolb 0:b75d784c7c1a 62
alvarolb 0:b75d784c7c1a 63 class dynamic_memory_allocator : public memory_allocator{
alvarolb 0:b75d784c7c1a 64 public:
alvarolb 0:b75d784c7c1a 65 virtual void *allocate(size_t size) {
alvarolb 0:b75d784c7c1a 66 return malloc(size);
alvarolb 0:b75d784c7c1a 67 }
alvarolb 0:b75d784c7c1a 68
alvarolb 0:b75d784c7c1a 69 virtual void deallocate(void *ptr) {
alvarolb 0:b75d784c7c1a 70 free(ptr);
alvarolb 0:b75d784c7c1a 71 }
alvarolb 0:b75d784c7c1a 72 };
alvarolb 0:b75d784c7c1a 73
alvarolb 0:b75d784c7c1a 74 extern memory_allocator& pool;
alvarolb 0:b75d784c7c1a 75 }
alvarolb 0:b75d784c7c1a 76
alvarolb 0:b75d784c7c1a 77 inline void* operator new(size_t sz, protoson::memory_allocator& a)
alvarolb 0:b75d784c7c1a 78 {
alvarolb 0:b75d784c7c1a 79 return a.allocate(sz);
alvarolb 0:b75d784c7c1a 80 }
alvarolb 0:b75d784c7c1a 81
alvarolb 0:b75d784c7c1a 82 inline void operator delete(void* p, protoson::memory_allocator& a)
alvarolb 0:b75d784c7c1a 83 {
alvarolb 0:b75d784c7c1a 84 a.deallocate(p);
alvarolb 0:b75d784c7c1a 85 }
alvarolb 0:b75d784c7c1a 86
alvarolb 0:b75d784c7c1a 87 template<class T>
alvarolb 0:b75d784c7c1a 88 void destroy(T* p, protoson::memory_allocator& a)
alvarolb 0:b75d784c7c1a 89 {
alvarolb 0:b75d784c7c1a 90 if (p) {
alvarolb 0:b75d784c7c1a 91 p->~T();
alvarolb 0:b75d784c7c1a 92 a.deallocate(p);
alvarolb 0:b75d784c7c1a 93 }
alvarolb 0:b75d784c7c1a 94 }
alvarolb 0:b75d784c7c1a 95
alvarolb 0:b75d784c7c1a 96 namespace protoson {
alvarolb 0:b75d784c7c1a 97
alvarolb 0:b75d784c7c1a 98 enum pb_wire_type{
alvarolb 0:b75d784c7c1a 99 varint = 0,
alvarolb 0:b75d784c7c1a 100 fixed_64 = 1,
alvarolb 0:b75d784c7c1a 101 length_delimited = 2,
alvarolb 0:b75d784c7c1a 102 fixed_32 = 5,
alvarolb 0:b75d784c7c1a 103 pson_type = 6
alvarolb 0:b75d784c7c1a 104 };
alvarolb 0:b75d784c7c1a 105
alvarolb 0:b75d784c7c1a 106 template<class T>
alvarolb 0:b75d784c7c1a 107 class pson_container {
alvarolb 0:b75d784c7c1a 108
alvarolb 0:b75d784c7c1a 109 struct list_item{
alvarolb 0:b75d784c7c1a 110 T item_;
alvarolb 0:b75d784c7c1a 111 list_item* next_;
alvarolb 0:b75d784c7c1a 112 };
alvarolb 0:b75d784c7c1a 113
alvarolb 0:b75d784c7c1a 114 public:
alvarolb 0:b75d784c7c1a 115
alvarolb 0:b75d784c7c1a 116 class iterator{
alvarolb 0:b75d784c7c1a 117 public:
alvarolb 0:b75d784c7c1a 118 iterator(list_item *current) : current(current) {
alvarolb 0:b75d784c7c1a 119 }
alvarolb 0:b75d784c7c1a 120
alvarolb 0:b75d784c7c1a 121 private:
alvarolb 0:b75d784c7c1a 122 list_item * current;
alvarolb 0:b75d784c7c1a 123
alvarolb 0:b75d784c7c1a 124 public:
alvarolb 0:b75d784c7c1a 125 bool next(){
alvarolb 0:b75d784c7c1a 126 if(current==NULL) return false;
alvarolb 0:b75d784c7c1a 127 current = current->next_;
alvarolb 0:b75d784c7c1a 128 return true;
alvarolb 0:b75d784c7c1a 129 }
alvarolb 0:b75d784c7c1a 130
alvarolb 0:b75d784c7c1a 131 bool has_next(){
alvarolb 0:b75d784c7c1a 132 return current!=NULL && current->next_!=NULL;
alvarolb 0:b75d784c7c1a 133 }
alvarolb 0:b75d784c7c1a 134
alvarolb 0:b75d784c7c1a 135 bool valid(){
alvarolb 0:b75d784c7c1a 136 return current!=NULL;
alvarolb 0:b75d784c7c1a 137 }
alvarolb 0:b75d784c7c1a 138
alvarolb 0:b75d784c7c1a 139 T& item(){
alvarolb 0:b75d784c7c1a 140 return current->item_;
alvarolb 0:b75d784c7c1a 141 }
alvarolb 0:b75d784c7c1a 142 };
alvarolb 0:b75d784c7c1a 143
alvarolb 0:b75d784c7c1a 144 private:
alvarolb 0:b75d784c7c1a 145 list_item* item_;
alvarolb 0:b75d784c7c1a 146
alvarolb 0:b75d784c7c1a 147 public:
alvarolb 0:b75d784c7c1a 148 iterator begin() const{
alvarolb 0:b75d784c7c1a 149 return iterator(item_);
alvarolb 0:b75d784c7c1a 150 }
alvarolb 0:b75d784c7c1a 151
alvarolb 0:b75d784c7c1a 152 pson_container() : item_(NULL) {
alvarolb 0:b75d784c7c1a 153 }
alvarolb 0:b75d784c7c1a 154
alvarolb 0:b75d784c7c1a 155 ~pson_container(){
alvarolb 0:b75d784c7c1a 156 clear();
alvarolb 0:b75d784c7c1a 157 }
alvarolb 0:b75d784c7c1a 158
alvarolb 0:b75d784c7c1a 159 size_t size() const{
alvarolb 0:b75d784c7c1a 160 size_t size = 0;
alvarolb 0:b75d784c7c1a 161 list_item* current = item_;
alvarolb 0:b75d784c7c1a 162 while(current!=NULL){
alvarolb 0:b75d784c7c1a 163 current = current->next_;
alvarolb 0:b75d784c7c1a 164 size++;
alvarolb 0:b75d784c7c1a 165 }
alvarolb 0:b75d784c7c1a 166 return size;
alvarolb 0:b75d784c7c1a 167 }
alvarolb 0:b75d784c7c1a 168
alvarolb 0:b75d784c7c1a 169 T* operator[](size_t index){
alvarolb 0:b75d784c7c1a 170 list_item* current = item_;
alvarolb 0:b75d784c7c1a 171 size_t current_index = 0;
alvarolb 0:b75d784c7c1a 172 while(current!=NULL){
alvarolb 0:b75d784c7c1a 173 if(current_index==index){
alvarolb 0:b75d784c7c1a 174 return &current->item_;
alvarolb 0:b75d784c7c1a 175 }
alvarolb 0:b75d784c7c1a 176 current = current->next_;
alvarolb 0:b75d784c7c1a 177 current_index++;
alvarolb 0:b75d784c7c1a 178 }
alvarolb 0:b75d784c7c1a 179 return NULL;
alvarolb 0:b75d784c7c1a 180 }
alvarolb 0:b75d784c7c1a 181
alvarolb 0:b75d784c7c1a 182 void clear(){
alvarolb 0:b75d784c7c1a 183 list_item* current = item_;
alvarolb 0:b75d784c7c1a 184 while(current!=NULL){
alvarolb 0:b75d784c7c1a 185 list_item* next = current->next_;
alvarolb 0:b75d784c7c1a 186 destroy(current, pool);
alvarolb 0:b75d784c7c1a 187 current = next;
alvarolb 0:b75d784c7c1a 188 }
alvarolb 0:b75d784c7c1a 189 item_ = NULL;
alvarolb 0:b75d784c7c1a 190 }
alvarolb 0:b75d784c7c1a 191
alvarolb 0:b75d784c7c1a 192 T& create_item(){
alvarolb 0:b75d784c7c1a 193 list_item* new_list_item = new(pool) list_item();
alvarolb 0:b75d784c7c1a 194 if(item_==NULL){
alvarolb 0:b75d784c7c1a 195 item_ = new_list_item;
alvarolb 0:b75d784c7c1a 196 }
alvarolb 0:b75d784c7c1a 197 else{
alvarolb 0:b75d784c7c1a 198 list_item * last = item_;
alvarolb 0:b75d784c7c1a 199 while(last->next_!=NULL) last = last->next_;
alvarolb 0:b75d784c7c1a 200 last->next_ = new_list_item;
alvarolb 0:b75d784c7c1a 201 }
alvarolb 0:b75d784c7c1a 202 return new_list_item->item_;
alvarolb 0:b75d784c7c1a 203 }
alvarolb 0:b75d784c7c1a 204 };
alvarolb 0:b75d784c7c1a 205
alvarolb 0:b75d784c7c1a 206 class pson_object;
alvarolb 0:b75d784c7c1a 207 class pson_array;
alvarolb 0:b75d784c7c1a 208
alvarolb 0:b75d784c7c1a 209 class pson {
alvarolb 0:b75d784c7c1a 210 public:
alvarolb 0:b75d784c7c1a 211 enum field_type {
alvarolb 0:b75d784c7c1a 212 null_field = 0,
alvarolb 0:b75d784c7c1a 213 varint_field = 1,
alvarolb 0:b75d784c7c1a 214 svarint_field = 2,
alvarolb 0:b75d784c7c1a 215 float_field = 3,
alvarolb 0:b75d784c7c1a 216 double_field = 4,
alvarolb 0:b75d784c7c1a 217 true_field = 5,
alvarolb 0:b75d784c7c1a 218 false_field = 6,
alvarolb 0:b75d784c7c1a 219 zero_field = 7,
alvarolb 0:b75d784c7c1a 220 one_field = 8,
alvarolb 0:b75d784c7c1a 221 string_field = 9,
alvarolb 0:b75d784c7c1a 222 empty_string = 10,
alvarolb 0:b75d784c7c1a 223 bytes_field = 11,
alvarolb 0:b75d784c7c1a 224 empty_bytes = 12,
alvarolb 0:b75d784c7c1a 225 object_field = 13,
alvarolb 0:b75d784c7c1a 226 array_field = 14,
alvarolb 0:b75d784c7c1a 227 empty = 15,
alvarolb 0:b75d784c7c1a 228 // a message tag is encoded in a 128-base varint [1-bit][3-bit wire type][4-bit field]
alvarolb 0:b75d784c7c1a 229 // we have up to 4 bits (0-15) for encoding fields in the first byte
alvarolb 0:b75d784c7c1a 230 };
alvarolb 0:b75d784c7c1a 231
alvarolb 0:b75d784c7c1a 232 bool is_boolean() const{
alvarolb 0:b75d784c7c1a 233 return field_type_ == true_field || field_type_ == false_field;
alvarolb 0:b75d784c7c1a 234 }
alvarolb 0:b75d784c7c1a 235
alvarolb 0:b75d784c7c1a 236 bool is_string() const{
alvarolb 0:b75d784c7c1a 237 return field_type_ == string_field;
alvarolb 0:b75d784c7c1a 238 }
alvarolb 0:b75d784c7c1a 239
alvarolb 0:b75d784c7c1a 240 bool is_bytes() const{
alvarolb 0:b75d784c7c1a 241 return field_type_ == bytes_field;
alvarolb 0:b75d784c7c1a 242 }
alvarolb 0:b75d784c7c1a 243
alvarolb 0:b75d784c7c1a 244 bool is_number() const{
alvarolb 0:b75d784c7c1a 245 return field_type_ == varint_field ||
alvarolb 0:b75d784c7c1a 246 field_type_ == svarint_field ||
alvarolb 0:b75d784c7c1a 247 field_type_ == float_field ||
alvarolb 0:b75d784c7c1a 248 field_type_ == double_field ||
alvarolb 0:b75d784c7c1a 249 field_type_ == zero_field ||
alvarolb 0:b75d784c7c1a 250 field_type_ == one_field;
alvarolb 0:b75d784c7c1a 251 }
alvarolb 0:b75d784c7c1a 252
alvarolb 0:b75d784c7c1a 253 bool is_object() const{
alvarolb 0:b75d784c7c1a 254 return field_type_ == object_field;
alvarolb 0:b75d784c7c1a 255 }
alvarolb 0:b75d784c7c1a 256
alvarolb 0:b75d784c7c1a 257 bool is_array() const{
alvarolb 0:b75d784c7c1a 258 return field_type_ == array_field;
alvarolb 0:b75d784c7c1a 259 }
alvarolb 0:b75d784c7c1a 260
alvarolb 0:b75d784c7c1a 261 bool is_null() const{
alvarolb 0:b75d784c7c1a 262 return field_type_ == null_field;
alvarolb 0:b75d784c7c1a 263 }
alvarolb 0:b75d784c7c1a 264
alvarolb 0:b75d784c7c1a 265 bool is_empty() const{
alvarolb 0:b75d784c7c1a 266 return field_type_ == empty;
alvarolb 0:b75d784c7c1a 267 }
alvarolb 0:b75d784c7c1a 268
alvarolb 0:b75d784c7c1a 269 pson() : field_type_(empty), value_(NULL) {
alvarolb 0:b75d784c7c1a 270 }
alvarolb 0:b75d784c7c1a 271
alvarolb 0:b75d784c7c1a 272 template<class T>
alvarolb 0:b75d784c7c1a 273 pson(T value) : field_type_(empty), value_(NULL){
alvarolb 0:b75d784c7c1a 274 *this = value;
alvarolb 0:b75d784c7c1a 275 }
alvarolb 0:b75d784c7c1a 276
alvarolb 0:b75d784c7c1a 277 ~pson(){
alvarolb 0:b75d784c7c1a 278 if(field_type_==object_field){
alvarolb 0:b75d784c7c1a 279 destroy((pson_object *) value_, pool);
alvarolb 0:b75d784c7c1a 280 }else if(field_type_==array_field) {
alvarolb 0:b75d784c7c1a 281 destroy((pson_array *) value_, pool);
alvarolb 0:b75d784c7c1a 282 }else{
alvarolb 0:b75d784c7c1a 283 pool.deallocate(value_);
alvarolb 0:b75d784c7c1a 284 }
alvarolb 0:b75d784c7c1a 285 }
alvarolb 0:b75d784c7c1a 286
alvarolb 0:b75d784c7c1a 287 template<class T>
alvarolb 0:b75d784c7c1a 288 void operator=(T value)
alvarolb 0:b75d784c7c1a 289 {
alvarolb 0:b75d784c7c1a 290 if(value==0){
alvarolb 0:b75d784c7c1a 291 field_type_ = zero_field;
alvarolb 0:b75d784c7c1a 292 }else if(value==1) {
alvarolb 0:b75d784c7c1a 293 field_type_ = one_field;
alvarolb 0:b75d784c7c1a 294 }else{
alvarolb 0:b75d784c7c1a 295 if(value<0){
alvarolb 0:b75d784c7c1a 296 field_type_ = svarint_field;
alvarolb 0:b75d784c7c1a 297 }else{
alvarolb 0:b75d784c7c1a 298 field_type_ = varint_field;
alvarolb 0:b75d784c7c1a 299 }
alvarolb 0:b75d784c7c1a 300 uint64_t uint_value = value>0 ? value : -value;
alvarolb 0:b75d784c7c1a 301 value_ = pool.allocate(pson::get_varint_size(uint_value));
alvarolb 0:b75d784c7c1a 302 pb_encode_varint(uint_value);
alvarolb 0:b75d784c7c1a 303 }
alvarolb 0:b75d784c7c1a 304 }
alvarolb 0:b75d784c7c1a 305
alvarolb 0:b75d784c7c1a 306 void operator=(bool value){
alvarolb 0:b75d784c7c1a 307 field_type_ = value ? true_field : false_field;
alvarolb 0:b75d784c7c1a 308 }
alvarolb 0:b75d784c7c1a 309
alvarolb 0:b75d784c7c1a 310 void operator=(float value) {
alvarolb 0:b75d784c7c1a 311 if(value==(int32_t)value){
alvarolb 0:b75d784c7c1a 312 *this = (int32_t) value;
alvarolb 0:b75d784c7c1a 313 }else{
alvarolb 0:b75d784c7c1a 314 field_type_ = float_field;
alvarolb 0:b75d784c7c1a 315 set(value);
alvarolb 0:b75d784c7c1a 316 }
alvarolb 0:b75d784c7c1a 317 }
alvarolb 0:b75d784c7c1a 318
alvarolb 0:b75d784c7c1a 319 void operator=(double value) {
alvarolb 0:b75d784c7c1a 320 if(value==(int64_t)value) {
alvarolb 0:b75d784c7c1a 321 *this = (int64_t) value;
alvarolb 0:b75d784c7c1a 322 }else if(fabs(value-(float)value)<=0.00001){
alvarolb 0:b75d784c7c1a 323 field_type_ = float_field;
alvarolb 0:b75d784c7c1a 324 set((float)value);
alvarolb 0:b75d784c7c1a 325 }else{
alvarolb 0:b75d784c7c1a 326 field_type_ = double_field;
alvarolb 0:b75d784c7c1a 327 set(value);
alvarolb 0:b75d784c7c1a 328 }
alvarolb 0:b75d784c7c1a 329 }
alvarolb 0:b75d784c7c1a 330
alvarolb 0:b75d784c7c1a 331 void operator=(const char *str) {
alvarolb 0:b75d784c7c1a 332 size_t str_size = strlen(str);
alvarolb 0:b75d784c7c1a 333 if(str_size==0){
alvarolb 0:b75d784c7c1a 334 field_type_ = empty_string;
alvarolb 0:b75d784c7c1a 335 }else{
alvarolb 0:b75d784c7c1a 336 field_type_ = string_field;
alvarolb 0:b75d784c7c1a 337 memcpy(allocate(str_size+1), str, str_size+1);
alvarolb 0:b75d784c7c1a 338 }
alvarolb 0:b75d784c7c1a 339 }
alvarolb 0:b75d784c7c1a 340
alvarolb 0:b75d784c7c1a 341 operator const char *() {
alvarolb 0:b75d784c7c1a 342 switch(field_type_){
alvarolb 0:b75d784c7c1a 343 case string_field:
alvarolb 0:b75d784c7c1a 344 return (const char*) value_;
alvarolb 0:b75d784c7c1a 345 case empty:
alvarolb 0:b75d784c7c1a 346 field_type_ = empty_string;
alvarolb 0:b75d784c7c1a 347 default:
alvarolb 0:b75d784c7c1a 348 return "";
alvarolb 0:b75d784c7c1a 349 }
alvarolb 0:b75d784c7c1a 350 }
alvarolb 0:b75d784c7c1a 351
alvarolb 0:b75d784c7c1a 352 void set_bytes(const void* bytes, size_t size) {
alvarolb 0:b75d784c7c1a 353 if(size>0){
alvarolb 0:b75d784c7c1a 354 size_t varint_size = get_varint_size(size);
alvarolb 0:b75d784c7c1a 355 value_ = pool.allocate(varint_size+size);
alvarolb 0:b75d784c7c1a 356 pb_encode_varint(size);
alvarolb 0:b75d784c7c1a 357 memcpy(((uint8_t*)value_)+varint_size, bytes, size);
alvarolb 0:b75d784c7c1a 358 field_type_ = bytes_field;
alvarolb 0:b75d784c7c1a 359 }else{
alvarolb 0:b75d784c7c1a 360 field_type_ = empty_bytes;
alvarolb 0:b75d784c7c1a 361 }
alvarolb 0:b75d784c7c1a 362 }
alvarolb 0:b75d784c7c1a 363
alvarolb 0:b75d784c7c1a 364 bool get_bytes(const void*& bytes, size_t& size){
alvarolb 0:b75d784c7c1a 365 switch(field_type_){
alvarolb 0:b75d784c7c1a 366 case bytes_field:
alvarolb 0:b75d784c7c1a 367 size = pb_decode_varint();
alvarolb 0:b75d784c7c1a 368 bytes = (uint8_t*) value_ + get_varint_size(size);
alvarolb 0:b75d784c7c1a 369 return true;
alvarolb 0:b75d784c7c1a 370 case empty:
alvarolb 0:b75d784c7c1a 371 field_type_ = empty_bytes;
alvarolb 0:b75d784c7c1a 372 default:
alvarolb 0:b75d784c7c1a 373 return false;
alvarolb 0:b75d784c7c1a 374 }
alvarolb 0:b75d784c7c1a 375 }
alvarolb 0:b75d784c7c1a 376
alvarolb 0:b75d784c7c1a 377 void* allocate(size_t size){
alvarolb 0:b75d784c7c1a 378 value_ = pool.allocate(size);
alvarolb 0:b75d784c7c1a 379 return value_;
alvarolb 0:b75d784c7c1a 380 }
alvarolb 0:b75d784c7c1a 381
alvarolb 0:b75d784c7c1a 382 operator pson_object &();
alvarolb 0:b75d784c7c1a 383 operator pson_array &();
alvarolb 0:b75d784c7c1a 384 pson & operator[](const char *name);
alvarolb 0:b75d784c7c1a 385
alvarolb 0:b75d784c7c1a 386 operator bool(){
alvarolb 0:b75d784c7c1a 387 switch(field_type_){
alvarolb 0:b75d784c7c1a 388 case zero_field:
alvarolb 0:b75d784c7c1a 389 case false_field:
alvarolb 0:b75d784c7c1a 390 return false;
alvarolb 0:b75d784c7c1a 391 case one_field:
alvarolb 0:b75d784c7c1a 392 case true_field:
alvarolb 0:b75d784c7c1a 393 return true;
alvarolb 0:b75d784c7c1a 394 case empty:
alvarolb 0:b75d784c7c1a 395 field_type_ = false_field;
alvarolb 0:b75d784c7c1a 396 default:
alvarolb 0:b75d784c7c1a 397 return false;
alvarolb 0:b75d784c7c1a 398 }
alvarolb 0:b75d784c7c1a 399 }
alvarolb 0:b75d784c7c1a 400
alvarolb 0:b75d784c7c1a 401 template<class T>
alvarolb 0:b75d784c7c1a 402 operator T() {
alvarolb 0:b75d784c7c1a 403 switch(field_type_){
alvarolb 0:b75d784c7c1a 404 case zero_field:
alvarolb 0:b75d784c7c1a 405 case false_field:
alvarolb 0:b75d784c7c1a 406 return 0;
alvarolb 0:b75d784c7c1a 407 case one_field:
alvarolb 0:b75d784c7c1a 408 case true_field:
alvarolb 0:b75d784c7c1a 409 return 1;
alvarolb 0:b75d784c7c1a 410 case float_field:
alvarolb 0:b75d784c7c1a 411 return *(float*)value_;
alvarolb 0:b75d784c7c1a 412 case double_field:
alvarolb 0:b75d784c7c1a 413 return *(double*)value_;
alvarolb 0:b75d784c7c1a 414 case varint_field:
alvarolb 0:b75d784c7c1a 415 return pb_decode_varint();
alvarolb 0:b75d784c7c1a 416 case svarint_field:
alvarolb 0:b75d784c7c1a 417 return -pb_decode_varint();
alvarolb 0:b75d784c7c1a 418 case empty:
alvarolb 0:b75d784c7c1a 419 field_type_ = zero_field;
alvarolb 0:b75d784c7c1a 420 default:
alvarolb 0:b75d784c7c1a 421 return 0;
alvarolb 0:b75d784c7c1a 422 }
alvarolb 0:b75d784c7c1a 423 }
alvarolb 0:b75d784c7c1a 424
alvarolb 0:b75d784c7c1a 425 void* get_value(){
alvarolb 0:b75d784c7c1a 426 return value_;
alvarolb 0:b75d784c7c1a 427 }
alvarolb 0:b75d784c7c1a 428
alvarolb 0:b75d784c7c1a 429 void set_value(void* value){
alvarolb 0:b75d784c7c1a 430 value_ = value;
alvarolb 0:b75d784c7c1a 431 }
alvarolb 0:b75d784c7c1a 432
alvarolb 0:b75d784c7c1a 433 field_type get_type() const{
alvarolb 0:b75d784c7c1a 434 return field_type_;
alvarolb 0:b75d784c7c1a 435 }
alvarolb 0:b75d784c7c1a 436
alvarolb 0:b75d784c7c1a 437 void set_null(){
alvarolb 0:b75d784c7c1a 438 field_type_ = null_field;
alvarolb 0:b75d784c7c1a 439 }
alvarolb 0:b75d784c7c1a 440
alvarolb 0:b75d784c7c1a 441 void set_type(field_type type){
alvarolb 0:b75d784c7c1a 442 field_type_ = type;
alvarolb 0:b75d784c7c1a 443 }
alvarolb 0:b75d784c7c1a 444
alvarolb 0:b75d784c7c1a 445 uint8_t get_varint_size(uint64_t value) const{
alvarolb 0:b75d784c7c1a 446 uint8_t size = 1;
alvarolb 0:b75d784c7c1a 447 while(value>>=7) size++;
alvarolb 0:b75d784c7c1a 448 return size;
alvarolb 0:b75d784c7c1a 449 }
alvarolb 0:b75d784c7c1a 450
alvarolb 0:b75d784c7c1a 451 void pb_encode_varint(uint64_t value) const
alvarolb 0:b75d784c7c1a 452 {
alvarolb 0:b75d784c7c1a 453 uint8_t count = 0;
alvarolb 0:b75d784c7c1a 454 do
alvarolb 0:b75d784c7c1a 455 {
alvarolb 0:b75d784c7c1a 456 uint8_t byte = (uint8_t)(value & 0x7F);
alvarolb 0:b75d784c7c1a 457 value >>= 7;
alvarolb 0:b75d784c7c1a 458 if(value) byte |= 0x80;
alvarolb 0:b75d784c7c1a 459 ((uint8_t*)value_)[count] = byte;
alvarolb 0:b75d784c7c1a 460 count++;
alvarolb 0:b75d784c7c1a 461 }while(value);
alvarolb 0:b75d784c7c1a 462 }
alvarolb 0:b75d784c7c1a 463
alvarolb 0:b75d784c7c1a 464 uint64_t pb_decode_varint() const
alvarolb 0:b75d784c7c1a 465 {
alvarolb 0:b75d784c7c1a 466 if(value_==NULL) return 0;
alvarolb 0:b75d784c7c1a 467 uint64_t value = 0;
alvarolb 0:b75d784c7c1a 468 uint8_t pos = 0;
alvarolb 0:b75d784c7c1a 469 uint8_t byte = 0;
alvarolb 0:b75d784c7c1a 470 do{
alvarolb 0:b75d784c7c1a 471 byte = ((uint8_t*)value_)[pos];
alvarolb 0:b75d784c7c1a 472 value |= (uint64_t)(byte&0x7F) << pos*7;
alvarolb 0:b75d784c7c1a 473 pos++;
alvarolb 0:b75d784c7c1a 474 }while(byte>=0x80);
alvarolb 0:b75d784c7c1a 475 return value;
alvarolb 0:b75d784c7c1a 476 }
alvarolb 0:b75d784c7c1a 477
alvarolb 0:b75d784c7c1a 478 private:
alvarolb 0:b75d784c7c1a 479 void* value_;
alvarolb 0:b75d784c7c1a 480 field_type field_type_;
alvarolb 0:b75d784c7c1a 481
alvarolb 0:b75d784c7c1a 482 template<class T>
alvarolb 0:b75d784c7c1a 483 void set(T value) {
alvarolb 0:b75d784c7c1a 484 memcpy(allocate(sizeof(T)), &value, sizeof(T));
alvarolb 0:b75d784c7c1a 485 }
alvarolb 0:b75d784c7c1a 486 };
alvarolb 0:b75d784c7c1a 487
alvarolb 0:b75d784c7c1a 488 class pson_pair{
alvarolb 0:b75d784c7c1a 489 private:
alvarolb 0:b75d784c7c1a 490 char* name_;
alvarolb 0:b75d784c7c1a 491 pson value_;
alvarolb 0:b75d784c7c1a 492 public:
alvarolb 0:b75d784c7c1a 493 pson_pair() : name_(NULL){
alvarolb 0:b75d784c7c1a 494 }
alvarolb 0:b75d784c7c1a 495
alvarolb 0:b75d784c7c1a 496 ~pson_pair(){
alvarolb 0:b75d784c7c1a 497 destroy(name_, pool);
alvarolb 0:b75d784c7c1a 498 }
alvarolb 0:b75d784c7c1a 499
alvarolb 0:b75d784c7c1a 500 void set_name(const char *name) {
alvarolb 0:b75d784c7c1a 501 size_t name_size = strlen(name) + 1;
alvarolb 0:b75d784c7c1a 502 memcpy(allocate_name(name_size), name, name_size);
alvarolb 0:b75d784c7c1a 503 }
alvarolb 0:b75d784c7c1a 504
alvarolb 0:b75d784c7c1a 505 char* allocate_name(size_t size){
alvarolb 0:b75d784c7c1a 506 name_ = (char*)pool.allocate(size);
alvarolb 0:b75d784c7c1a 507 return name_;
alvarolb 0:b75d784c7c1a 508 }
alvarolb 0:b75d784c7c1a 509
alvarolb 0:b75d784c7c1a 510 pson& value(){
alvarolb 0:b75d784c7c1a 511 return value_;
alvarolb 0:b75d784c7c1a 512 }
alvarolb 0:b75d784c7c1a 513
alvarolb 0:b75d784c7c1a 514 char* name() const{
alvarolb 0:b75d784c7c1a 515 return name_;
alvarolb 0:b75d784c7c1a 516 }
alvarolb 0:b75d784c7c1a 517 };
alvarolb 0:b75d784c7c1a 518
alvarolb 0:b75d784c7c1a 519 class pson_object : public pson_container<pson_pair> {
alvarolb 0:b75d784c7c1a 520 public:
alvarolb 0:b75d784c7c1a 521 pson &operator[](const char *name) {
alvarolb 0:b75d784c7c1a 522 for(iterator it=begin(); it.valid(); it.next()){
alvarolb 0:b75d784c7c1a 523 if(strcmp(it.item().name(), name)==0){
alvarolb 0:b75d784c7c1a 524 return it.item().value();
alvarolb 0:b75d784c7c1a 525 }
alvarolb 0:b75d784c7c1a 526 }
alvarolb 0:b75d784c7c1a 527 pson_pair & pair = create_item();
alvarolb 0:b75d784c7c1a 528 pair.set_name(name);
alvarolb 0:b75d784c7c1a 529 return pair.value();
alvarolb 0:b75d784c7c1a 530 };
alvarolb 0:b75d784c7c1a 531 };
alvarolb 0:b75d784c7c1a 532
alvarolb 0:b75d784c7c1a 533 class pson_array : public pson_container<pson> {
alvarolb 0:b75d784c7c1a 534 public:
alvarolb 0:b75d784c7c1a 535 template<class T>
alvarolb 0:b75d784c7c1a 536 pson_array& add(T item_value){
alvarolb 0:b75d784c7c1a 537 create_item() = item_value;
alvarolb 0:b75d784c7c1a 538 return *this;
alvarolb 0:b75d784c7c1a 539 }
alvarolb 0:b75d784c7c1a 540 };
alvarolb 0:b75d784c7c1a 541
alvarolb 0:b75d784c7c1a 542 inline pson::operator pson_object &() {
alvarolb 0:b75d784c7c1a 543 if (field_type_ != object_field) {
alvarolb 0:b75d784c7c1a 544 value_ = new(pool) pson_object;
alvarolb 0:b75d784c7c1a 545 field_type_ = object_field;
alvarolb 0:b75d784c7c1a 546 }
alvarolb 0:b75d784c7c1a 547 return *((pson_object *)value_);
alvarolb 0:b75d784c7c1a 548 }
alvarolb 0:b75d784c7c1a 549
alvarolb 0:b75d784c7c1a 550 inline pson::operator pson_array &() {
alvarolb 0:b75d784c7c1a 551 if (field_type_ != array_field) {
alvarolb 0:b75d784c7c1a 552 value_ = new(pool) pson_array;
alvarolb 0:b75d784c7c1a 553 field_type_ = array_field;
alvarolb 0:b75d784c7c1a 554 }
alvarolb 0:b75d784c7c1a 555 return *((pson_array *)value_);
alvarolb 0:b75d784c7c1a 556 }
alvarolb 0:b75d784c7c1a 557
alvarolb 0:b75d784c7c1a 558 inline pson &pson::operator[](const char *name) {
alvarolb 0:b75d784c7c1a 559 return ((pson_object &) *this)[name];
alvarolb 0:b75d784c7c1a 560 }
alvarolb 0:b75d784c7c1a 561
alvarolb 0:b75d784c7c1a 562 ////////////////////////////
alvarolb 0:b75d784c7c1a 563 /////// PSON_DECODER ///////
alvarolb 0:b75d784c7c1a 564 ////////////////////////////
alvarolb 0:b75d784c7c1a 565
alvarolb 0:b75d784c7c1a 566 class pson_decoder {
alvarolb 0:b75d784c7c1a 567
alvarolb 0:b75d784c7c1a 568 protected:
alvarolb 0:b75d784c7c1a 569 size_t read_;
alvarolb 0:b75d784c7c1a 570
alvarolb 0:b75d784c7c1a 571 virtual bool read(void* buffer, size_t size){
alvarolb 0:b75d784c7c1a 572 read_+=size;
alvarolb 0:b75d784c7c1a 573 return true;
alvarolb 0:b75d784c7c1a 574 }
alvarolb 0:b75d784c7c1a 575
alvarolb 0:b75d784c7c1a 576 public:
alvarolb 0:b75d784c7c1a 577
alvarolb 0:b75d784c7c1a 578 pson_decoder() : read_(0) {
alvarolb 0:b75d784c7c1a 579
alvarolb 0:b75d784c7c1a 580 }
alvarolb 0:b75d784c7c1a 581
alvarolb 0:b75d784c7c1a 582 void reset(){
alvarolb 0:b75d784c7c1a 583 read_ = 0;
alvarolb 0:b75d784c7c1a 584 }
alvarolb 0:b75d784c7c1a 585
alvarolb 0:b75d784c7c1a 586 size_t bytes_read(){
alvarolb 0:b75d784c7c1a 587 return read_;
alvarolb 0:b75d784c7c1a 588 }
alvarolb 0:b75d784c7c1a 589
alvarolb 0:b75d784c7c1a 590 bool pb_decode_tag(pb_wire_type& wire_type, uint32_t& field_number)
alvarolb 0:b75d784c7c1a 591 {
alvarolb 0:b75d784c7c1a 592 uint32_t temp = pb_decode_varint32();
alvarolb 0:b75d784c7c1a 593 wire_type = (pb_wire_type)(temp & 0x07);
alvarolb 0:b75d784c7c1a 594 field_number = temp >> 3;
alvarolb 0:b75d784c7c1a 595 return true;
alvarolb 0:b75d784c7c1a 596 }
alvarolb 0:b75d784c7c1a 597
alvarolb 0:b75d784c7c1a 598 uint32_t pb_decode_varint32()
alvarolb 0:b75d784c7c1a 599 {
alvarolb 0:b75d784c7c1a 600 uint32_t varint = 0;
alvarolb 0:b75d784c7c1a 601 if(try_pb_decode_varint32(varint)){
alvarolb 0:b75d784c7c1a 602 return varint;
alvarolb 0:b75d784c7c1a 603 }
alvarolb 0:b75d784c7c1a 604 return 0;
alvarolb 0:b75d784c7c1a 605 }
alvarolb 0:b75d784c7c1a 606
alvarolb 0:b75d784c7c1a 607 bool try_pb_decode_varint32(uint32_t& varint){
alvarolb 0:b75d784c7c1a 608 varint = 0;
alvarolb 0:b75d784c7c1a 609 uint8_t byte;
alvarolb 0:b75d784c7c1a 610 uint8_t bit_pos = 0;
alvarolb 0:b75d784c7c1a 611 do{
alvarolb 0:b75d784c7c1a 612 if(!read(&byte, 1) || bit_pos>=32){
alvarolb 0:b75d784c7c1a 613 return false;
alvarolb 0:b75d784c7c1a 614 }
alvarolb 0:b75d784c7c1a 615 varint |= (uint32_t)(byte&0x7F) << bit_pos;
alvarolb 0:b75d784c7c1a 616 bit_pos += 7;
alvarolb 0:b75d784c7c1a 617 }while(byte>=0x80);
alvarolb 0:b75d784c7c1a 618 return true;
alvarolb 0:b75d784c7c1a 619 }
alvarolb 0:b75d784c7c1a 620
alvarolb 0:b75d784c7c1a 621 uint64_t pb_decode_varint64()
alvarolb 0:b75d784c7c1a 622 {
alvarolb 0:b75d784c7c1a 623 uint64_t varint = 0;
alvarolb 0:b75d784c7c1a 624 uint8_t byte;
alvarolb 0:b75d784c7c1a 625 uint8_t bit_pos = 0;
alvarolb 0:b75d784c7c1a 626 do{
alvarolb 0:b75d784c7c1a 627 if(!read(&byte, 1) || bit_pos>=64){
alvarolb 0:b75d784c7c1a 628 return varint;
alvarolb 0:b75d784c7c1a 629 }
alvarolb 0:b75d784c7c1a 630 varint |= (uint32_t)(byte&0x7F) << bit_pos;
alvarolb 0:b75d784c7c1a 631 bit_pos += 7;
alvarolb 0:b75d784c7c1a 632 }while(byte>=0x80);
alvarolb 0:b75d784c7c1a 633 return varint;
alvarolb 0:b75d784c7c1a 634 }
alvarolb 0:b75d784c7c1a 635
alvarolb 0:b75d784c7c1a 636 bool pb_skip(size_t size){
alvarolb 0:b75d784c7c1a 637 uint8_t byte;
alvarolb 0:b75d784c7c1a 638 bool success = true;
alvarolb 0:b75d784c7c1a 639 for(size_t i=0; i<size; i++){
alvarolb 0:b75d784c7c1a 640 success &= read(&byte, 1);
alvarolb 0:b75d784c7c1a 641 }
alvarolb 0:b75d784c7c1a 642 return success;
alvarolb 0:b75d784c7c1a 643 }
alvarolb 0:b75d784c7c1a 644
alvarolb 0:b75d784c7c1a 645 bool pb_skip_varint(){
alvarolb 0:b75d784c7c1a 646 uint8_t byte;
alvarolb 0:b75d784c7c1a 647 bool success = true;
alvarolb 0:b75d784c7c1a 648 do{
alvarolb 0:b75d784c7c1a 649 success &= read(&byte, 1);
alvarolb 0:b75d784c7c1a 650 }while(byte>0x80);
alvarolb 0:b75d784c7c1a 651 return success;
alvarolb 0:b75d784c7c1a 652 }
alvarolb 0:b75d784c7c1a 653
alvarolb 0:b75d784c7c1a 654 bool pb_read_string(char *str, size_t size){
alvarolb 0:b75d784c7c1a 655 bool success = read(str, size);
alvarolb 0:b75d784c7c1a 656 str[size]=0;
alvarolb 0:b75d784c7c1a 657 return success;
alvarolb 0:b75d784c7c1a 658 }
alvarolb 0:b75d784c7c1a 659
alvarolb 0:b75d784c7c1a 660 bool pb_read_varint(pson& value)
alvarolb 0:b75d784c7c1a 661 {
alvarolb 0:b75d784c7c1a 662 uint8_t temp[10];
alvarolb 0:b75d784c7c1a 663 uint8_t byte=0;
alvarolb 0:b75d784c7c1a 664 uint8_t bytes_read=0;
alvarolb 0:b75d784c7c1a 665 do{
alvarolb 0:b75d784c7c1a 666 if(!read(&byte, 1)) return false;
alvarolb 0:b75d784c7c1a 667 temp[bytes_read] = byte;
alvarolb 0:b75d784c7c1a 668 bytes_read++;
alvarolb 0:b75d784c7c1a 669 }while(byte>=0x80);
alvarolb 0:b75d784c7c1a 670 memcpy(value.allocate(bytes_read), temp, bytes_read);
alvarolb 0:b75d784c7c1a 671 return true;
alvarolb 0:b75d784c7c1a 672 }
alvarolb 0:b75d784c7c1a 673
alvarolb 0:b75d784c7c1a 674 public:
alvarolb 0:b75d784c7c1a 675
alvarolb 0:b75d784c7c1a 676 void decode(pson_object & object, size_t size){
alvarolb 0:b75d784c7c1a 677 size_t start_read = bytes_read();
alvarolb 0:b75d784c7c1a 678 while(size-(bytes_read()-start_read)>0){
alvarolb 0:b75d784c7c1a 679 decode(object.create_item());
alvarolb 0:b75d784c7c1a 680 }
alvarolb 0:b75d784c7c1a 681 }
alvarolb 0:b75d784c7c1a 682
alvarolb 0:b75d784c7c1a 683 void decode(pson_array & array, size_t size){
alvarolb 0:b75d784c7c1a 684 size_t start_read = bytes_read();
alvarolb 0:b75d784c7c1a 685 while(size-(bytes_read()-start_read)>0){
alvarolb 0:b75d784c7c1a 686 decode(array.create_item());
alvarolb 0:b75d784c7c1a 687 }
alvarolb 0:b75d784c7c1a 688 }
alvarolb 0:b75d784c7c1a 689
alvarolb 0:b75d784c7c1a 690 void decode(pson_pair & pair){
alvarolb 0:b75d784c7c1a 691 uint32_t name_size = pb_decode_varint32();
alvarolb 0:b75d784c7c1a 692 pb_read_string(pair.allocate_name(name_size+1), name_size);
alvarolb 0:b75d784c7c1a 693 decode(pair.value());
alvarolb 0:b75d784c7c1a 694 }
alvarolb 0:b75d784c7c1a 695
alvarolb 0:b75d784c7c1a 696 void decode(pson& value) {
alvarolb 0:b75d784c7c1a 697 uint32_t field_number;
alvarolb 0:b75d784c7c1a 698 pb_wire_type wire_type;
alvarolb 0:b75d784c7c1a 699 pb_decode_tag(wire_type, field_number);
alvarolb 0:b75d784c7c1a 700 value.set_type((pson::field_type)field_number);
alvarolb 0:b75d784c7c1a 701 if(wire_type==length_delimited){
alvarolb 0:b75d784c7c1a 702 uint32_t size = pb_decode_varint32();
alvarolb 0:b75d784c7c1a 703 switch(field_number){
alvarolb 0:b75d784c7c1a 704 case pson::string_field:
alvarolb 0:b75d784c7c1a 705 pb_read_string((char*)value.allocate(size + 1), size);
alvarolb 0:b75d784c7c1a 706 break;
alvarolb 0:b75d784c7c1a 707 case pson::bytes_field: {
alvarolb 0:b75d784c7c1a 708 uint8_t varint_size = value.get_varint_size(size);
alvarolb 0:b75d784c7c1a 709 read((char*)value.allocate(size + varint_size) + varint_size, size);
alvarolb 0:b75d784c7c1a 710 value.pb_encode_varint(size);
alvarolb 0:b75d784c7c1a 711 }
alvarolb 0:b75d784c7c1a 712 break;
alvarolb 0:b75d784c7c1a 713 case pson::object_field:
alvarolb 0:b75d784c7c1a 714 value.set_value(new (pool) pson_object);
alvarolb 0:b75d784c7c1a 715 decode(*(pson_object *)value.get_value(), size);
alvarolb 0:b75d784c7c1a 716 break;
alvarolb 0:b75d784c7c1a 717 case pson::array_field:
alvarolb 0:b75d784c7c1a 718 value.set_value(new (pool) pson_array);
alvarolb 0:b75d784c7c1a 719 decode(*(pson_array *)value.get_value(), size);
alvarolb 0:b75d784c7c1a 720 break;
alvarolb 0:b75d784c7c1a 721 default:
alvarolb 0:b75d784c7c1a 722 pb_skip(size);
alvarolb 0:b75d784c7c1a 723 break;
alvarolb 0:b75d784c7c1a 724 }
alvarolb 0:b75d784c7c1a 725 }else {
alvarolb 0:b75d784c7c1a 726 switch (field_number) {
alvarolb 0:b75d784c7c1a 727 case pson::svarint_field:
alvarolb 0:b75d784c7c1a 728 case pson::varint_field:
alvarolb 0:b75d784c7c1a 729 pb_read_varint(value);
alvarolb 0:b75d784c7c1a 730 break;
alvarolb 0:b75d784c7c1a 731 case pson::float_field:
alvarolb 0:b75d784c7c1a 732 read(value.allocate(4), 4);
alvarolb 0:b75d784c7c1a 733 break;
alvarolb 0:b75d784c7c1a 734 case pson::double_field:
alvarolb 0:b75d784c7c1a 735 read(value.allocate(8), 8);
alvarolb 0:b75d784c7c1a 736 break;
alvarolb 0:b75d784c7c1a 737 default:
alvarolb 0:b75d784c7c1a 738 break;
alvarolb 0:b75d784c7c1a 739 }
alvarolb 0:b75d784c7c1a 740 }
alvarolb 0:b75d784c7c1a 741 }
alvarolb 0:b75d784c7c1a 742 };
alvarolb 0:b75d784c7c1a 743
alvarolb 0:b75d784c7c1a 744 ////////////////////////////
alvarolb 0:b75d784c7c1a 745 /////// PSON_ENCODER ///////
alvarolb 0:b75d784c7c1a 746 ////////////////////////////
alvarolb 0:b75d784c7c1a 747
alvarolb 0:b75d784c7c1a 748 class pson_encoder {
alvarolb 0:b75d784c7c1a 749
alvarolb 0:b75d784c7c1a 750 protected:
alvarolb 0:b75d784c7c1a 751 size_t written_;
alvarolb 0:b75d784c7c1a 752
alvarolb 0:b75d784c7c1a 753 virtual void write(const void* buffer, size_t size){
alvarolb 0:b75d784c7c1a 754 written_+=size;
alvarolb 0:b75d784c7c1a 755 }
alvarolb 0:b75d784c7c1a 756
alvarolb 0:b75d784c7c1a 757 public:
alvarolb 0:b75d784c7c1a 758
alvarolb 0:b75d784c7c1a 759 pson_encoder() : written_(0) {
alvarolb 0:b75d784c7c1a 760 }
alvarolb 0:b75d784c7c1a 761
alvarolb 0:b75d784c7c1a 762 void reset(){
alvarolb 0:b75d784c7c1a 763 written_ = 0;
alvarolb 0:b75d784c7c1a 764 }
alvarolb 0:b75d784c7c1a 765
alvarolb 0:b75d784c7c1a 766 size_t bytes_written(){
alvarolb 0:b75d784c7c1a 767 return written_;
alvarolb 0:b75d784c7c1a 768 }
alvarolb 0:b75d784c7c1a 769
alvarolb 0:b75d784c7c1a 770 void pb_encode_tag(pb_wire_type wire_type, uint32_t field_number){
alvarolb 0:b75d784c7c1a 771 uint64_t tag = ((uint64_t)field_number << 3) | wire_type;
alvarolb 0:b75d784c7c1a 772 pb_encode_varint(tag);
alvarolb 0:b75d784c7c1a 773 }
alvarolb 0:b75d784c7c1a 774
alvarolb 0:b75d784c7c1a 775 void pb_encode_varint(uint32_t field, uint64_t value)
alvarolb 0:b75d784c7c1a 776 {
alvarolb 0:b75d784c7c1a 777 pb_encode_tag(varint, field);
alvarolb 0:b75d784c7c1a 778 pb_encode_varint(value);
alvarolb 0:b75d784c7c1a 779 }
alvarolb 0:b75d784c7c1a 780
alvarolb 0:b75d784c7c1a 781 uint8_t pb_write_varint(void * buffer)
alvarolb 0:b75d784c7c1a 782 {
alvarolb 0:b75d784c7c1a 783 uint8_t byte=0;
alvarolb 0:b75d784c7c1a 784 uint8_t bytes_written=0;
alvarolb 0:b75d784c7c1a 785 do{
alvarolb 0:b75d784c7c1a 786 byte = *((uint8_t*)buffer + bytes_written);
alvarolb 0:b75d784c7c1a 787 bytes_written++;
alvarolb 0:b75d784c7c1a 788 }while(byte>=0x80);
alvarolb 0:b75d784c7c1a 789 write(buffer, bytes_written);
alvarolb 0:b75d784c7c1a 790 return bytes_written;
alvarolb 0:b75d784c7c1a 791 }
alvarolb 0:b75d784c7c1a 792
alvarolb 0:b75d784c7c1a 793 void pb_encode_varint(uint64_t value)
alvarolb 0:b75d784c7c1a 794 {
alvarolb 0:b75d784c7c1a 795 do
alvarolb 0:b75d784c7c1a 796 {
alvarolb 0:b75d784c7c1a 797 uint8_t byte = (uint8_t)(value & 0x7F);
alvarolb 0:b75d784c7c1a 798 value >>= 7;
alvarolb 0:b75d784c7c1a 799 if(value>0) byte |= 0x80;
alvarolb 0:b75d784c7c1a 800 write(&byte, 1);
alvarolb 0:b75d784c7c1a 801 }while(value>0);
alvarolb 0:b75d784c7c1a 802 }
alvarolb 0:b75d784c7c1a 803
alvarolb 0:b75d784c7c1a 804 void pb_encode_string(const char* str, uint32_t field_number){
alvarolb 0:b75d784c7c1a 805 pb_encode_tag(length_delimited, field_number);
alvarolb 0:b75d784c7c1a 806 pb_encode_string(str);
alvarolb 0:b75d784c7c1a 807 }
alvarolb 0:b75d784c7c1a 808
alvarolb 0:b75d784c7c1a 809 void pb_encode_string(const char* str){
alvarolb 0:b75d784c7c1a 810 size_t string_size = strlen(str);
alvarolb 0:b75d784c7c1a 811 pb_encode_varint(string_size);
alvarolb 0:b75d784c7c1a 812 write(str, string_size);
alvarolb 0:b75d784c7c1a 813 }
alvarolb 0:b75d784c7c1a 814
alvarolb 0:b75d784c7c1a 815 template<class T>
alvarolb 0:b75d784c7c1a 816 void pb_encode_submessage(T& element, uint32_t field_number)
alvarolb 0:b75d784c7c1a 817 {
alvarolb 0:b75d784c7c1a 818 pb_encode_tag(length_delimited, field_number);
alvarolb 0:b75d784c7c1a 819 pson_encoder sink;
alvarolb 0:b75d784c7c1a 820 sink.encode(element);
alvarolb 0:b75d784c7c1a 821 pb_encode_varint(sink.bytes_written());
alvarolb 0:b75d784c7c1a 822 encode(element);
alvarolb 0:b75d784c7c1a 823 }
alvarolb 0:b75d784c7c1a 824
alvarolb 0:b75d784c7c1a 825 void pb_encode_fixed32(void* value){
alvarolb 0:b75d784c7c1a 826 write(value, 4);
alvarolb 0:b75d784c7c1a 827 }
alvarolb 0:b75d784c7c1a 828
alvarolb 0:b75d784c7c1a 829 void pb_encode_fixed64(void* value){
alvarolb 0:b75d784c7c1a 830 write(value, 8);
alvarolb 0:b75d784c7c1a 831 }
alvarolb 0:b75d784c7c1a 832
alvarolb 0:b75d784c7c1a 833 void pb_encode_fixed32(uint32_t field, void*value)
alvarolb 0:b75d784c7c1a 834 {
alvarolb 0:b75d784c7c1a 835 pb_encode_tag(fixed_32, field);
alvarolb 0:b75d784c7c1a 836 pb_encode_fixed32(value);
alvarolb 0:b75d784c7c1a 837 }
alvarolb 0:b75d784c7c1a 838
alvarolb 0:b75d784c7c1a 839 void pb_encode_fixed64(uint32_t field, void*value)
alvarolb 0:b75d784c7c1a 840 {
alvarolb 0:b75d784c7c1a 841 pb_encode_tag(fixed_64, field);
alvarolb 0:b75d784c7c1a 842 pb_encode_fixed64(value);
alvarolb 0:b75d784c7c1a 843 }
alvarolb 0:b75d784c7c1a 844
alvarolb 0:b75d784c7c1a 845 public:
alvarolb 0:b75d784c7c1a 846
alvarolb 0:b75d784c7c1a 847 void encode(pson_object & object){
alvarolb 0:b75d784c7c1a 848 pson_container<pson_pair>::iterator it = object.begin();
alvarolb 0:b75d784c7c1a 849 while(it.valid()){
alvarolb 0:b75d784c7c1a 850 encode(it.item());
alvarolb 0:b75d784c7c1a 851 it.next();
alvarolb 0:b75d784c7c1a 852 }
alvarolb 0:b75d784c7c1a 853 }
alvarolb 0:b75d784c7c1a 854
alvarolb 0:b75d784c7c1a 855 void encode(pson_array & array){
alvarolb 0:b75d784c7c1a 856 pson_container<pson>::iterator it = array.begin();
alvarolb 0:b75d784c7c1a 857 while(it.valid()){
alvarolb 0:b75d784c7c1a 858 encode(it.item());
alvarolb 0:b75d784c7c1a 859 it.next();
alvarolb 0:b75d784c7c1a 860 }
alvarolb 0:b75d784c7c1a 861 }
alvarolb 0:b75d784c7c1a 862
alvarolb 0:b75d784c7c1a 863 void encode(pson_pair & pair){
alvarolb 0:b75d784c7c1a 864 pb_encode_string(pair.name());
alvarolb 0:b75d784c7c1a 865 encode(pair.value());
alvarolb 0:b75d784c7c1a 866 }
alvarolb 0:b75d784c7c1a 867
alvarolb 0:b75d784c7c1a 868 void encode(pson & value) {
alvarolb 0:b75d784c7c1a 869 switch (value.get_type()) {
alvarolb 0:b75d784c7c1a 870 case pson::string_field:
alvarolb 0:b75d784c7c1a 871 pb_encode_string((const char*)value.get_value(), pson::string_field);
alvarolb 0:b75d784c7c1a 872 break;
alvarolb 0:b75d784c7c1a 873 case pson::bytes_field:
alvarolb 0:b75d784c7c1a 874 pb_encode_tag(length_delimited, pson::bytes_field);
alvarolb 0:b75d784c7c1a 875 write(((const char *) value.get_value()) + pb_write_varint(value.get_value()), value.pb_decode_varint());
alvarolb 0:b75d784c7c1a 876 break;
alvarolb 0:b75d784c7c1a 877 case pson::svarint_field:
alvarolb 0:b75d784c7c1a 878 case pson::varint_field:
alvarolb 0:b75d784c7c1a 879 pb_encode_tag(varint, value.get_type());
alvarolb 0:b75d784c7c1a 880 pb_write_varint(value.get_value());
alvarolb 0:b75d784c7c1a 881 break;
alvarolb 0:b75d784c7c1a 882 case pson::float_field:
alvarolb 0:b75d784c7c1a 883 pb_encode_fixed32(pson::float_field, value.get_value());
alvarolb 0:b75d784c7c1a 884 break;
alvarolb 0:b75d784c7c1a 885 case pson::double_field:
alvarolb 0:b75d784c7c1a 886 pb_encode_fixed64(pson::double_field, value.get_value());
alvarolb 0:b75d784c7c1a 887 break;
alvarolb 0:b75d784c7c1a 888 case pson::object_field:
alvarolb 0:b75d784c7c1a 889 pb_encode_submessage(*(pson_object *) value.get_value(), pson::object_field);
alvarolb 0:b75d784c7c1a 890 break;
alvarolb 0:b75d784c7c1a 891 case pson::array_field:
alvarolb 0:b75d784c7c1a 892 pb_encode_submessage(*(pson_array *) value.get_value(), pson::array_field);
alvarolb 0:b75d784c7c1a 893 break;
alvarolb 0:b75d784c7c1a 894 default:
alvarolb 0:b75d784c7c1a 895 pb_encode_tag(varint, value.get_type());
alvarolb 0:b75d784c7c1a 896 break;
alvarolb 0:b75d784c7c1a 897 }
alvarolb 0:b75d784c7c1a 898 }
alvarolb 0:b75d784c7c1a 899 };
alvarolb 0:b75d784c7c1a 900 }
alvarolb 0:b75d784c7c1a 901
alvarolb 0:b75d784c7c1a 902 #endif