MessagePack C implementation for mbed, modified from https://github.com/msgpack/msgpack-c

Dependents:   msgpack_example

Committer:
yihui
Date:
Sat Oct 25 16:32:57 2014 +0000
Revision:
0:1382f081365b
initial

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 0:1382f081365b 1 /*
yihui 0:1382f081365b 2 * MessagePack for C unpacking routine
yihui 0:1382f081365b 3 *
yihui 0:1382f081365b 4 * Copyright (C) 2008-2009 FURUHASHI Sadayuki
yihui 0:1382f081365b 5 *
yihui 0:1382f081365b 6 * Licensed under the Apache License, Version 2.0 (the "License");
yihui 0:1382f081365b 7 * you may not use this file except in compliance with the License.
yihui 0:1382f081365b 8 * You may obtain a copy of the License at
yihui 0:1382f081365b 9 *
yihui 0:1382f081365b 10 * http://www.apache.org/licenses/LICENSE-2.0
yihui 0:1382f081365b 11 *
yihui 0:1382f081365b 12 * Unless required by applicable law or agreed to in writing, software
yihui 0:1382f081365b 13 * distributed under the License is distributed on an "AS IS" BASIS,
yihui 0:1382f081365b 14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
yihui 0:1382f081365b 15 * See the License for the specific language governing permissions and
yihui 0:1382f081365b 16 * limitations under the License.
yihui 0:1382f081365b 17 */
yihui 0:1382f081365b 18 #include "msgpack/unpack.h"
yihui 0:1382f081365b 19 #include "msgpack/unpack_define.h"
yihui 0:1382f081365b 20 #include <stdlib.h>
yihui 0:1382f081365b 21
yihui 0:1382f081365b 22 #ifdef _msgpack_atomic_counter_header
yihui 0:1382f081365b 23 #include _msgpack_atomic_counter_header
yihui 0:1382f081365b 24 #endif
yihui 0:1382f081365b 25
yihui 0:1382f081365b 26
yihui 0:1382f081365b 27 typedef struct {
yihui 0:1382f081365b 28 msgpack_zone* z;
yihui 0:1382f081365b 29 bool referenced;
yihui 0:1382f081365b 30 } unpack_user;
yihui 0:1382f081365b 31
yihui 0:1382f081365b 32
yihui 0:1382f081365b 33 #define msgpack_unpack_struct(name) \
yihui 0:1382f081365b 34 struct template ## name
yihui 0:1382f081365b 35
yihui 0:1382f081365b 36 #define msgpack_unpack_func(ret, name) \
yihui 0:1382f081365b 37 ret template ## name
yihui 0:1382f081365b 38
yihui 0:1382f081365b 39 #define msgpack_unpack_callback(name) \
yihui 0:1382f081365b 40 template_callback ## name
yihui 0:1382f081365b 41
yihui 0:1382f081365b 42 #define msgpack_unpack_object msgpack_object
yihui 0:1382f081365b 43
yihui 0:1382f081365b 44 #define msgpack_unpack_user unpack_user
yihui 0:1382f081365b 45
yihui 0:1382f081365b 46
yihui 0:1382f081365b 47 struct template_context;
yihui 0:1382f081365b 48 typedef struct template_context template_context;
yihui 0:1382f081365b 49
yihui 0:1382f081365b 50 static void template_init(template_context* ctx);
yihui 0:1382f081365b 51
yihui 0:1382f081365b 52 static msgpack_object template_data(template_context* ctx);
yihui 0:1382f081365b 53
yihui 0:1382f081365b 54 static int template_execute(template_context* ctx,
yihui 0:1382f081365b 55 const char* data, size_t len, size_t* off);
yihui 0:1382f081365b 56
yihui 0:1382f081365b 57
yihui 0:1382f081365b 58 static inline msgpack_object template_callback_root(unpack_user* u)
yihui 0:1382f081365b 59 { msgpack_object o = { MSGPACK_OBJECT_NIL }; return o; }
yihui 0:1382f081365b 60
yihui 0:1382f081365b 61 static inline int template_callback_uint8(unpack_user* u, uint8_t d, msgpack_object* o)
yihui 0:1382f081365b 62 { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
yihui 0:1382f081365b 63
yihui 0:1382f081365b 64 static inline int template_callback_uint16(unpack_user* u, uint16_t d, msgpack_object* o)
yihui 0:1382f081365b 65 { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
yihui 0:1382f081365b 66
yihui 0:1382f081365b 67 static inline int template_callback_uint32(unpack_user* u, uint32_t d, msgpack_object* o)
yihui 0:1382f081365b 68 { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
yihui 0:1382f081365b 69
yihui 0:1382f081365b 70 static inline int template_callback_uint64(unpack_user* u, uint64_t d, msgpack_object* o)
yihui 0:1382f081365b 71 { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = d; return 0; }
yihui 0:1382f081365b 72
yihui 0:1382f081365b 73 static inline int template_callback_int8(unpack_user* u, int8_t d, msgpack_object* o)
yihui 0:1382f081365b 74 { if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = (uint64_t)d; return 0; }
yihui 0:1382f081365b 75 else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
yihui 0:1382f081365b 76
yihui 0:1382f081365b 77 static inline int template_callback_int16(unpack_user* u, int16_t d, msgpack_object* o)
yihui 0:1382f081365b 78 { if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = (uint64_t)d; return 0; }
yihui 0:1382f081365b 79 else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
yihui 0:1382f081365b 80
yihui 0:1382f081365b 81 static inline int template_callback_int32(unpack_user* u, int32_t d, msgpack_object* o)
yihui 0:1382f081365b 82 { if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = (uint64_t)d; return 0; }
yihui 0:1382f081365b 83 else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
yihui 0:1382f081365b 84
yihui 0:1382f081365b 85 static inline int template_callback_int64(unpack_user* u, int64_t d, msgpack_object* o)
yihui 0:1382f081365b 86 { if(d >= 0) { o->type = MSGPACK_OBJECT_POSITIVE_INTEGER; o->via.u64 = (uint64_t)d; return 0; }
yihui 0:1382f081365b 87 else { o->type = MSGPACK_OBJECT_NEGATIVE_INTEGER; o->via.i64 = d; return 0; } }
yihui 0:1382f081365b 88
yihui 0:1382f081365b 89 static inline int template_callback_float(unpack_user* u, float d, msgpack_object* o)
yihui 0:1382f081365b 90 { o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
yihui 0:1382f081365b 91
yihui 0:1382f081365b 92 static inline int template_callback_double(unpack_user* u, double d, msgpack_object* o)
yihui 0:1382f081365b 93 { o->type = MSGPACK_OBJECT_DOUBLE; o->via.dec = d; return 0; }
yihui 0:1382f081365b 94
yihui 0:1382f081365b 95 static inline int template_callback_nil(unpack_user* u, msgpack_object* o)
yihui 0:1382f081365b 96 { o->type = MSGPACK_OBJECT_NIL; return 0; }
yihui 0:1382f081365b 97
yihui 0:1382f081365b 98 static inline int template_callback_true(unpack_user* u, msgpack_object* o)
yihui 0:1382f081365b 99 { o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = true; return 0; }
yihui 0:1382f081365b 100
yihui 0:1382f081365b 101 static inline int template_callback_false(unpack_user* u, msgpack_object* o)
yihui 0:1382f081365b 102 { o->type = MSGPACK_OBJECT_BOOLEAN; o->via.boolean = false; return 0; }
yihui 0:1382f081365b 103
yihui 0:1382f081365b 104 static inline int template_callback_array(unpack_user* u, unsigned int n, msgpack_object* o)
yihui 0:1382f081365b 105 {
yihui 0:1382f081365b 106 o->type = MSGPACK_OBJECT_ARRAY;
yihui 0:1382f081365b 107 o->via.array.size = 0;
yihui 0:1382f081365b 108 o->via.array.ptr = (msgpack_object*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object));
yihui 0:1382f081365b 109 if(o->via.array.ptr == NULL) { return -1; }
yihui 0:1382f081365b 110 return 0;
yihui 0:1382f081365b 111 }
yihui 0:1382f081365b 112
yihui 0:1382f081365b 113 static inline int template_callback_array_item(unpack_user* u, msgpack_object* c, msgpack_object o)
yihui 0:1382f081365b 114 {
yihui 0:1382f081365b 115 #if defined(__GNUC__) && !defined(__clang__)
yihui 0:1382f081365b 116 memcpy(&c->via.array.ptr[c->via.array.size], &o, sizeof(msgpack_object));
yihui 0:1382f081365b 117 #else /* __GNUC__ && !__clang__ */
yihui 0:1382f081365b 118 c->via.array.ptr[c->via.array.size] = o;
yihui 0:1382f081365b 119 #endif /* __GNUC__ && !__clang__ */
yihui 0:1382f081365b 120 ++c->via.array.size;
yihui 0:1382f081365b 121 return 0;
yihui 0:1382f081365b 122 }
yihui 0:1382f081365b 123
yihui 0:1382f081365b 124 static inline int template_callback_map(unpack_user* u, unsigned int n, msgpack_object* o)
yihui 0:1382f081365b 125 {
yihui 0:1382f081365b 126 o->type = MSGPACK_OBJECT_MAP;
yihui 0:1382f081365b 127 o->via.map.size = 0;
yihui 0:1382f081365b 128 o->via.map.ptr = (msgpack_object_kv*)msgpack_zone_malloc(u->z, n*sizeof(msgpack_object_kv));
yihui 0:1382f081365b 129 if(o->via.map.ptr == NULL) { return -1; }
yihui 0:1382f081365b 130 return 0;
yihui 0:1382f081365b 131 }
yihui 0:1382f081365b 132
yihui 0:1382f081365b 133 static inline int template_callback_map_item(unpack_user* u, msgpack_object* c, msgpack_object k, msgpack_object v)
yihui 0:1382f081365b 134 {
yihui 0:1382f081365b 135 #if defined(__GNUC__) && !defined(__clang__)
yihui 0:1382f081365b 136 memcpy(&c->via.map.ptr[c->via.map.size].key, &k, sizeof(msgpack_object));
yihui 0:1382f081365b 137 memcpy(&c->via.map.ptr[c->via.map.size].val, &v, sizeof(msgpack_object));
yihui 0:1382f081365b 138 #else /* __GNUC__ && !__clang__ */
yihui 0:1382f081365b 139 c->via.map.ptr[c->via.map.size].key = k;
yihui 0:1382f081365b 140 c->via.map.ptr[c->via.map.size].val = v;
yihui 0:1382f081365b 141 #endif /* __GNUC__ && !__clang__ */
yihui 0:1382f081365b 142 ++c->via.map.size;
yihui 0:1382f081365b 143 return 0;
yihui 0:1382f081365b 144 }
yihui 0:1382f081365b 145
yihui 0:1382f081365b 146 static inline int template_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_object* o)
yihui 0:1382f081365b 147 {
yihui 0:1382f081365b 148 o->type = MSGPACK_OBJECT_RAW;
yihui 0:1382f081365b 149 o->via.raw.ptr = p;
yihui 0:1382f081365b 150 o->via.raw.size = l;
yihui 0:1382f081365b 151 u->referenced = true;
yihui 0:1382f081365b 152 return 0;
yihui 0:1382f081365b 153 }
yihui 0:1382f081365b 154
yihui 0:1382f081365b 155 #include "msgpack/unpack_template.h"
yihui 0:1382f081365b 156
yihui 0:1382f081365b 157
yihui 0:1382f081365b 158 #define CTX_CAST(m) ((template_context*)(m))
yihui 0:1382f081365b 159 #define CTX_REFERENCED(mpac) CTX_CAST((mpac)->ctx)->user.referenced
yihui 0:1382f081365b 160
yihui 0:1382f081365b 161 #define COUNTER_SIZE (sizeof(_msgpack_atomic_counter_t))
yihui 0:1382f081365b 162
yihui 0:1382f081365b 163
yihui 0:1382f081365b 164 static inline void init_count(void* buffer)
yihui 0:1382f081365b 165 {
yihui 0:1382f081365b 166 *(volatile _msgpack_atomic_counter_t*)buffer = 1;
yihui 0:1382f081365b 167 }
yihui 0:1382f081365b 168
yihui 0:1382f081365b 169 static inline void decl_count(void* buffer)
yihui 0:1382f081365b 170 {
yihui 0:1382f081365b 171 // atomic if(--*(_msgpack_atomic_counter_t*)buffer == 0) { free(buffer); }
yihui 0:1382f081365b 172 if(_msgpack_sync_decr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer) == 0) {
yihui 0:1382f081365b 173 free(buffer);
yihui 0:1382f081365b 174 }
yihui 0:1382f081365b 175 }
yihui 0:1382f081365b 176
yihui 0:1382f081365b 177 static inline void incr_count(void* buffer)
yihui 0:1382f081365b 178 {
yihui 0:1382f081365b 179 // atomic ++*(_msgpack_atomic_counter_t*)buffer;
yihui 0:1382f081365b 180 _msgpack_sync_incr_and_fetch((volatile _msgpack_atomic_counter_t*)buffer);
yihui 0:1382f081365b 181 }
yihui 0:1382f081365b 182
yihui 0:1382f081365b 183 static inline _msgpack_atomic_counter_t get_count(void* buffer)
yihui 0:1382f081365b 184 {
yihui 0:1382f081365b 185 return *(volatile _msgpack_atomic_counter_t*)buffer;
yihui 0:1382f081365b 186 }
yihui 0:1382f081365b 187
yihui 0:1382f081365b 188
yihui 0:1382f081365b 189
yihui 0:1382f081365b 190 bool msgpack_unpacker_init(msgpack_unpacker* mpac, size_t initial_buffer_size)
yihui 0:1382f081365b 191 {
yihui 0:1382f081365b 192 if(initial_buffer_size < COUNTER_SIZE) {
yihui 0:1382f081365b 193 initial_buffer_size = COUNTER_SIZE;
yihui 0:1382f081365b 194 }
yihui 0:1382f081365b 195
yihui 0:1382f081365b 196 char* buffer = (char*)malloc(initial_buffer_size);
yihui 0:1382f081365b 197 if(buffer == NULL) {
yihui 0:1382f081365b 198 return false;
yihui 0:1382f081365b 199 }
yihui 0:1382f081365b 200
yihui 0:1382f081365b 201 void* ctx = malloc(sizeof(template_context));
yihui 0:1382f081365b 202 if(ctx == NULL) {
yihui 0:1382f081365b 203 free(buffer);
yihui 0:1382f081365b 204 return false;
yihui 0:1382f081365b 205 }
yihui 0:1382f081365b 206
yihui 0:1382f081365b 207 msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
yihui 0:1382f081365b 208 if(z == NULL) {
yihui 0:1382f081365b 209 free(ctx);
yihui 0:1382f081365b 210 free(buffer);
yihui 0:1382f081365b 211 return false;
yihui 0:1382f081365b 212 }
yihui 0:1382f081365b 213
yihui 0:1382f081365b 214 mpac->buffer = buffer;
yihui 0:1382f081365b 215 mpac->used = COUNTER_SIZE;
yihui 0:1382f081365b 216 mpac->free = initial_buffer_size - mpac->used;
yihui 0:1382f081365b 217 mpac->off = COUNTER_SIZE;
yihui 0:1382f081365b 218 mpac->parsed = 0;
yihui 0:1382f081365b 219 mpac->initial_buffer_size = initial_buffer_size;
yihui 0:1382f081365b 220 mpac->z = z;
yihui 0:1382f081365b 221 mpac->ctx = ctx;
yihui 0:1382f081365b 222
yihui 0:1382f081365b 223 init_count(mpac->buffer);
yihui 0:1382f081365b 224
yihui 0:1382f081365b 225 template_init(CTX_CAST(mpac->ctx));
yihui 0:1382f081365b 226 CTX_CAST(mpac->ctx)->user.z = mpac->z;
yihui 0:1382f081365b 227 CTX_CAST(mpac->ctx)->user.referenced = false;
yihui 0:1382f081365b 228
yihui 0:1382f081365b 229 return true;
yihui 0:1382f081365b 230 }
yihui 0:1382f081365b 231
yihui 0:1382f081365b 232 void msgpack_unpacker_destroy(msgpack_unpacker* mpac)
yihui 0:1382f081365b 233 {
yihui 0:1382f081365b 234 msgpack_zone_free(mpac->z);
yihui 0:1382f081365b 235 free(mpac->ctx);
yihui 0:1382f081365b 236 decl_count(mpac->buffer);
yihui 0:1382f081365b 237 }
yihui 0:1382f081365b 238
yihui 0:1382f081365b 239
yihui 0:1382f081365b 240 msgpack_unpacker* msgpack_unpacker_new(size_t initial_buffer_size)
yihui 0:1382f081365b 241 {
yihui 0:1382f081365b 242 msgpack_unpacker* mpac = (msgpack_unpacker*)malloc(sizeof(msgpack_unpacker));
yihui 0:1382f081365b 243 if(mpac == NULL) {
yihui 0:1382f081365b 244 return NULL;
yihui 0:1382f081365b 245 }
yihui 0:1382f081365b 246
yihui 0:1382f081365b 247 if(!msgpack_unpacker_init(mpac, initial_buffer_size)) {
yihui 0:1382f081365b 248 free(mpac);
yihui 0:1382f081365b 249 return NULL;
yihui 0:1382f081365b 250 }
yihui 0:1382f081365b 251
yihui 0:1382f081365b 252 return mpac;
yihui 0:1382f081365b 253 }
yihui 0:1382f081365b 254
yihui 0:1382f081365b 255 void msgpack_unpacker_free(msgpack_unpacker* mpac)
yihui 0:1382f081365b 256 {
yihui 0:1382f081365b 257 msgpack_unpacker_destroy(mpac);
yihui 0:1382f081365b 258 free(mpac);
yihui 0:1382f081365b 259 }
yihui 0:1382f081365b 260
yihui 0:1382f081365b 261 bool msgpack_unpacker_expand_buffer(msgpack_unpacker* mpac, size_t size)
yihui 0:1382f081365b 262 {
yihui 0:1382f081365b 263 if(mpac->used == mpac->off && get_count(mpac->buffer) == 1
yihui 0:1382f081365b 264 && !CTX_REFERENCED(mpac)) {
yihui 0:1382f081365b 265 // rewind buffer
yihui 0:1382f081365b 266 mpac->free += mpac->used - COUNTER_SIZE;
yihui 0:1382f081365b 267 mpac->used = COUNTER_SIZE;
yihui 0:1382f081365b 268 mpac->off = COUNTER_SIZE;
yihui 0:1382f081365b 269
yihui 0:1382f081365b 270 if(mpac->free >= size) {
yihui 0:1382f081365b 271 return true;
yihui 0:1382f081365b 272 }
yihui 0:1382f081365b 273 }
yihui 0:1382f081365b 274
yihui 0:1382f081365b 275 if(mpac->off == COUNTER_SIZE) {
yihui 0:1382f081365b 276 size_t next_size = (mpac->used + mpac->free) * 2; // include COUNTER_SIZE
yihui 0:1382f081365b 277 while(next_size < size + mpac->used) {
yihui 0:1382f081365b 278 next_size *= 2;
yihui 0:1382f081365b 279 }
yihui 0:1382f081365b 280
yihui 0:1382f081365b 281 char* tmp = (char*)realloc(mpac->buffer, next_size);
yihui 0:1382f081365b 282 if(tmp == NULL) {
yihui 0:1382f081365b 283 return false;
yihui 0:1382f081365b 284 }
yihui 0:1382f081365b 285
yihui 0:1382f081365b 286 mpac->buffer = tmp;
yihui 0:1382f081365b 287 mpac->free = next_size - mpac->used;
yihui 0:1382f081365b 288
yihui 0:1382f081365b 289 } else {
yihui 0:1382f081365b 290 size_t next_size = mpac->initial_buffer_size; // include COUNTER_SIZE
yihui 0:1382f081365b 291 size_t not_parsed = mpac->used - mpac->off;
yihui 0:1382f081365b 292 while(next_size < size + not_parsed + COUNTER_SIZE) {
yihui 0:1382f081365b 293 next_size *= 2;
yihui 0:1382f081365b 294 }
yihui 0:1382f081365b 295
yihui 0:1382f081365b 296 char* tmp = (char*)malloc(next_size);
yihui 0:1382f081365b 297 if(tmp == NULL) {
yihui 0:1382f081365b 298 return false;
yihui 0:1382f081365b 299 }
yihui 0:1382f081365b 300
yihui 0:1382f081365b 301 init_count(tmp);
yihui 0:1382f081365b 302
yihui 0:1382f081365b 303 memcpy(tmp+COUNTER_SIZE, mpac->buffer+mpac->off, not_parsed);
yihui 0:1382f081365b 304
yihui 0:1382f081365b 305 if(CTX_REFERENCED(mpac)) {
yihui 0:1382f081365b 306 if(!msgpack_zone_push_finalizer(mpac->z, decl_count, mpac->buffer)) {
yihui 0:1382f081365b 307 free(tmp);
yihui 0:1382f081365b 308 return false;
yihui 0:1382f081365b 309 }
yihui 0:1382f081365b 310 CTX_REFERENCED(mpac) = false;
yihui 0:1382f081365b 311 } else {
yihui 0:1382f081365b 312 decl_count(mpac->buffer);
yihui 0:1382f081365b 313 }
yihui 0:1382f081365b 314
yihui 0:1382f081365b 315 mpac->buffer = tmp;
yihui 0:1382f081365b 316 mpac->used = not_parsed + COUNTER_SIZE;
yihui 0:1382f081365b 317 mpac->free = next_size - mpac->used;
yihui 0:1382f081365b 318 mpac->off = COUNTER_SIZE;
yihui 0:1382f081365b 319 }
yihui 0:1382f081365b 320
yihui 0:1382f081365b 321 return true;
yihui 0:1382f081365b 322 }
yihui 0:1382f081365b 323
yihui 0:1382f081365b 324 int msgpack_unpacker_execute(msgpack_unpacker* mpac)
yihui 0:1382f081365b 325 {
yihui 0:1382f081365b 326 size_t off = mpac->off;
yihui 0:1382f081365b 327 int ret = template_execute(CTX_CAST(mpac->ctx),
yihui 0:1382f081365b 328 mpac->buffer, mpac->used, &mpac->off);
yihui 0:1382f081365b 329 if(mpac->off > off) {
yihui 0:1382f081365b 330 mpac->parsed += mpac->off - off;
yihui 0:1382f081365b 331 }
yihui 0:1382f081365b 332 return ret;
yihui 0:1382f081365b 333 }
yihui 0:1382f081365b 334
yihui 0:1382f081365b 335 msgpack_object msgpack_unpacker_data(msgpack_unpacker* mpac)
yihui 0:1382f081365b 336 {
yihui 0:1382f081365b 337 return template_data(CTX_CAST(mpac->ctx));
yihui 0:1382f081365b 338 }
yihui 0:1382f081365b 339
yihui 0:1382f081365b 340 msgpack_zone* msgpack_unpacker_release_zone(msgpack_unpacker* mpac)
yihui 0:1382f081365b 341 {
yihui 0:1382f081365b 342 if(!msgpack_unpacker_flush_zone(mpac)) {
yihui 0:1382f081365b 343 return NULL;
yihui 0:1382f081365b 344 }
yihui 0:1382f081365b 345
yihui 0:1382f081365b 346 msgpack_zone* r = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
yihui 0:1382f081365b 347 if(r == NULL) {
yihui 0:1382f081365b 348 return NULL;
yihui 0:1382f081365b 349 }
yihui 0:1382f081365b 350
yihui 0:1382f081365b 351 msgpack_zone* old = mpac->z;
yihui 0:1382f081365b 352 mpac->z = r;
yihui 0:1382f081365b 353 CTX_CAST(mpac->ctx)->user.z = mpac->z;
yihui 0:1382f081365b 354
yihui 0:1382f081365b 355 return old;
yihui 0:1382f081365b 356 }
yihui 0:1382f081365b 357
yihui 0:1382f081365b 358 void msgpack_unpacker_reset_zone(msgpack_unpacker* mpac)
yihui 0:1382f081365b 359 {
yihui 0:1382f081365b 360 msgpack_zone_clear(mpac->z);
yihui 0:1382f081365b 361 }
yihui 0:1382f081365b 362
yihui 0:1382f081365b 363 bool msgpack_unpacker_flush_zone(msgpack_unpacker* mpac)
yihui 0:1382f081365b 364 {
yihui 0:1382f081365b 365 if(CTX_REFERENCED(mpac)) {
yihui 0:1382f081365b 366 if(!msgpack_zone_push_finalizer(mpac->z, decl_count, mpac->buffer)) {
yihui 0:1382f081365b 367 return false;
yihui 0:1382f081365b 368 }
yihui 0:1382f081365b 369 CTX_REFERENCED(mpac) = false;
yihui 0:1382f081365b 370
yihui 0:1382f081365b 371 incr_count(mpac->buffer);
yihui 0:1382f081365b 372 }
yihui 0:1382f081365b 373
yihui 0:1382f081365b 374 return true;
yihui 0:1382f081365b 375 }
yihui 0:1382f081365b 376
yihui 0:1382f081365b 377 void msgpack_unpacker_reset(msgpack_unpacker* mpac)
yihui 0:1382f081365b 378 {
yihui 0:1382f081365b 379 template_init(CTX_CAST(mpac->ctx));
yihui 0:1382f081365b 380 // don't reset referenced flag
yihui 0:1382f081365b 381 mpac->parsed = 0;
yihui 0:1382f081365b 382 }
yihui 0:1382f081365b 383
yihui 0:1382f081365b 384 bool msgpack_unpacker_next(msgpack_unpacker* mpac, msgpack_unpacked* result)
yihui 0:1382f081365b 385 {
yihui 0:1382f081365b 386 if(result->zone != NULL) {
yihui 0:1382f081365b 387 msgpack_zone_free(result->zone);
yihui 0:1382f081365b 388 }
yihui 0:1382f081365b 389
yihui 0:1382f081365b 390 int ret = msgpack_unpacker_execute(mpac);
yihui 0:1382f081365b 391
yihui 0:1382f081365b 392 if(ret <= 0) {
yihui 0:1382f081365b 393 result->zone = NULL;
yihui 0:1382f081365b 394 memset(&result->data, 0, sizeof(msgpack_object));
yihui 0:1382f081365b 395 return false;
yihui 0:1382f081365b 396 }
yihui 0:1382f081365b 397
yihui 0:1382f081365b 398 result->zone = msgpack_unpacker_release_zone(mpac);
yihui 0:1382f081365b 399 result->data = msgpack_unpacker_data(mpac);
yihui 0:1382f081365b 400 msgpack_unpacker_reset(mpac);
yihui 0:1382f081365b 401
yihui 0:1382f081365b 402 return true;
yihui 0:1382f081365b 403 }
yihui 0:1382f081365b 404
yihui 0:1382f081365b 405
yihui 0:1382f081365b 406 msgpack_unpack_return
yihui 0:1382f081365b 407 msgpack_unpack(const char* data, size_t len, size_t* off,
yihui 0:1382f081365b 408 msgpack_zone* result_zone, msgpack_object* result)
yihui 0:1382f081365b 409 {
yihui 0:1382f081365b 410 size_t noff = 0;
yihui 0:1382f081365b 411 if(off != NULL) { noff = *off; }
yihui 0:1382f081365b 412
yihui 0:1382f081365b 413 if(len <= noff) {
yihui 0:1382f081365b 414 // FIXME
yihui 0:1382f081365b 415 return MSGPACK_UNPACK_CONTINUE;
yihui 0:1382f081365b 416 }
yihui 0:1382f081365b 417
yihui 0:1382f081365b 418 template_context ctx;
yihui 0:1382f081365b 419 template_init(&ctx);
yihui 0:1382f081365b 420
yihui 0:1382f081365b 421 ctx.user.z = result_zone;
yihui 0:1382f081365b 422 ctx.user.referenced = false;
yihui 0:1382f081365b 423
yihui 0:1382f081365b 424 int e = template_execute(&ctx, data, len, &noff);
yihui 0:1382f081365b 425 if(e < 0) {
yihui 0:1382f081365b 426 return MSGPACK_UNPACK_PARSE_ERROR;
yihui 0:1382f081365b 427 }
yihui 0:1382f081365b 428
yihui 0:1382f081365b 429 if(off != NULL) { *off = noff; }
yihui 0:1382f081365b 430
yihui 0:1382f081365b 431 if(e == 0) {
yihui 0:1382f081365b 432 return MSGPACK_UNPACK_CONTINUE;
yihui 0:1382f081365b 433 }
yihui 0:1382f081365b 434
yihui 0:1382f081365b 435 *result = template_data(&ctx);
yihui 0:1382f081365b 436
yihui 0:1382f081365b 437 if(noff < len) {
yihui 0:1382f081365b 438 return MSGPACK_UNPACK_EXTRA_BYTES;
yihui 0:1382f081365b 439 }
yihui 0:1382f081365b 440
yihui 0:1382f081365b 441 return MSGPACK_UNPACK_SUCCESS;
yihui 0:1382f081365b 442 }
yihui 0:1382f081365b 443
yihui 0:1382f081365b 444 bool msgpack_unpack_next(msgpack_unpacked* result,
yihui 0:1382f081365b 445 const char* data, size_t len, size_t* off)
yihui 0:1382f081365b 446 {
yihui 0:1382f081365b 447 msgpack_unpacked_destroy(result);
yihui 0:1382f081365b 448
yihui 0:1382f081365b 449 size_t noff = 0;
yihui 0:1382f081365b 450 if(off != NULL) { noff = *off; }
yihui 0:1382f081365b 451
yihui 0:1382f081365b 452 if(len <= noff) {
yihui 0:1382f081365b 453 return false;
yihui 0:1382f081365b 454 }
yihui 0:1382f081365b 455
yihui 0:1382f081365b 456 msgpack_zone* z = msgpack_zone_new(MSGPACK_ZONE_CHUNK_SIZE);
yihui 0:1382f081365b 457
yihui 0:1382f081365b 458 template_context ctx;
yihui 0:1382f081365b 459 template_init(&ctx);
yihui 0:1382f081365b 460
yihui 0:1382f081365b 461 ctx.user.z = z;
yihui 0:1382f081365b 462 ctx.user.referenced = false;
yihui 0:1382f081365b 463
yihui 0:1382f081365b 464 int e = template_execute(&ctx, data, len, &noff);
yihui 0:1382f081365b 465 if(e <= 0) {
yihui 0:1382f081365b 466 msgpack_zone_free(z);
yihui 0:1382f081365b 467 return false;
yihui 0:1382f081365b 468 }
yihui 0:1382f081365b 469
yihui 0:1382f081365b 470 if(off != NULL) { *off = noff; }
yihui 0:1382f081365b 471
yihui 0:1382f081365b 472 result->zone = z;
yihui 0:1382f081365b 473 result->data = template_data(&ctx);
yihui 0:1382f081365b 474
yihui 0:1382f081365b 475 return true;
yihui 0:1382f081365b 476 }
yihui 0:1382f081365b 477
yihui 0:1382f081365b 478 #if defined(MSGPACK_OLD_COMPILER_BUS_ERROR_WORKAROUND)
yihui 0:1382f081365b 479 // FIXME: Dirty hack to avoid a bus error caused by OS X's old gcc.
yihui 0:1382f081365b 480 static void dummy_function_to_avoid_bus_error()
yihui 0:1382f081365b 481 {
yihui 0:1382f081365b 482 }
yihui 0:1382f081365b 483 #endif