1/* 2 * MessagePack unpacking routine template 3 * 4 * Copyright (C) 2008-2010 FURUHASHI Sadayuki 5 * 6 * Distributed under the Boost Software License, Version 1.0. 7 * (See accompanying file LICENSE_1_0.txt or copy at 8 * http://www.boost.org/LICENSE_1_0.txt) 9 */ 10 11#ifndef msgpack_unpack_func 12#error msgpack_unpack_func template is not defined 13#endif 14 15#ifndef msgpack_unpack_callback 16#error msgpack_unpack_callback template is not defined 17#endif 18 19#ifndef msgpack_unpack_struct 20#error msgpack_unpack_struct template is not defined 21#endif 22 23#ifndef msgpack_unpack_struct_decl 24#define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name) 25#endif 26 27#ifndef msgpack_unpack_object 28#error msgpack_unpack_object type is not defined 29#endif 30 31#ifndef msgpack_unpack_user 32#error msgpack_unpack_user type is not defined 33#endif 34 35#ifndef USE_CASE_RANGE 36#if !defined(_MSC_VER) 37#define USE_CASE_RANGE 38#endif 39#endif 40 41msgpack_unpack_struct_decl(_stack) { 42 msgpack_unpack_object obj; 43 size_t count; 44 unsigned int ct; 45 msgpack_unpack_object map_key; 46}; 47 48msgpack_unpack_struct_decl(_context) { 49 msgpack_unpack_user user; 50 unsigned int cs; 51 unsigned int trail; 52 unsigned int top; 53 /* 54 msgpack_unpack_struct(_stack)* stack; 55 unsigned int stack_size; 56 msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE]; 57 */ 58 msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE]; 59}; 60 61 62msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx) 63{ 64 ctx->cs = MSGPACK_CS_HEADER; 65 ctx->trail = 0; 66 ctx->top = 0; 67 /* 68 ctx->stack = ctx->embed_stack; 69 ctx->stack_size = MSGPACK_EMBED_STACK_SIZE; 70 */ 71 ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user); 72} 73 74/* 75msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx) 76{ 77 if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) { 78 free(ctx->stack); 79 } 80} 81*/ 82 83msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx) 84{ 85 return (ctx)->stack[0].obj; 86} 87 88 89msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off) 90{ 91 assert(len >= *off); 92 { 93 const unsigned char* p = (unsigned char*)data + *off; 94 const unsigned char* const pe = (unsigned char*)data + len; 95 const void* n = NULL; 96 97 unsigned int trail = ctx->trail; 98 unsigned int cs = ctx->cs; 99 unsigned int top = ctx->top; 100 msgpack_unpack_struct(_stack)* stack = ctx->stack; 101 /* 102 unsigned int stack_size = ctx->stack_size; 103 */ 104 msgpack_unpack_user* user = &ctx->user; 105 106 msgpack_unpack_object obj; 107 msgpack_unpack_struct(_stack)* c = NULL; 108 109 int ret; 110 111#define push_simple_value(func) \ 112 if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \ 113 goto _push 114#define push_fixed_value(func, arg) \ 115 if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \ 116 goto _push 117#define push_variable_value(func, base, pos, len) \ 118 if(msgpack_unpack_callback(func)(user, \ 119 (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \ 120 goto _push 121 122#define again_fixed_trail(_cs, trail_len) \ 123 trail = trail_len; \ 124 cs = _cs; \ 125 goto _fixed_trail_again 126#define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ 127 trail = trail_len; \ 128 if(trail == 0) { goto ifzero; } \ 129 cs = _cs; \ 130 goto _fixed_trail_again 131 132#define start_container(func, count_, ct_) \ 133 if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \ 134 if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ 135 if((count_) == 0) { obj = stack[top].obj; goto _push; } \ 136 stack[top].ct = ct_; \ 137 stack[top].count = count_; \ 138 ++top; \ 139 /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ 140 /*printf("stack push %d\n", top);*/ \ 141 /* FIXME \ 142 if(top >= stack_size) { \ 143 if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \ 144 size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \ 145 size_t nsize = csize * 2; \ 146 msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \ 147 if(tmp == NULL) { goto _failed; } \ 148 memcpy(tmp, ctx->stack, csize); \ 149 ctx->stack = stack = tmp; \ 150 ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \ 151 } else { \ 152 size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \ 153 msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \ 154 if(tmp == NULL) { goto _failed; } \ 155 ctx->stack = stack = tmp; \ 156 ctx->stack_size = stack_size = stack_size * 2; \ 157 } \ 158 } \ 159 */ \ 160 goto _header_again 161 162#define NEXT_CS(p) \ 163 ((unsigned int)*p & 0x1f) 164 165#ifdef USE_CASE_RANGE 166#define SWITCH_RANGE_BEGIN switch(*p) { 167#define SWITCH_RANGE(FROM, TO) case FROM ... TO: 168#define SWITCH_RANGE_DEFAULT default: 169#define SWITCH_RANGE_END } 170#else 171#define SWITCH_RANGE_BEGIN { if(0) { 172#define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) { 173#define SWITCH_RANGE_DEFAULT } else { 174#define SWITCH_RANGE_END } } 175#endif 176 177 if(p == pe) { goto _out; } 178 do { 179 switch(cs) { 180 case MSGPACK_CS_HEADER: 181 SWITCH_RANGE_BEGIN 182 SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum 183 push_fixed_value(_uint8, *(uint8_t*)p); 184 SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum 185 push_fixed_value(_int8, *(int8_t*)p); 186 SWITCH_RANGE(0xc0, 0xdf) // Variable 187 switch(*p) { 188 case 0xc0: // nil 189 push_simple_value(_nil); 190 //case 0xc1: // string 191 // again_terminal_trail(NEXT_CS(p), p+1); 192 case 0xc2: // false 193 push_simple_value(_false); 194 case 0xc3: // true 195 push_simple_value(_true); 196 case 0xc4: // bin 8 197 case 0xc5: // bin 16 198 case 0xc6: // bin 32 199 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); 200 case 0xc7: // ext 8 201 case 0xc8: // ext 16 202 case 0xc9: // ext 32 203 again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) + 1) & 0x03)); 204 case 0xca: // float 205 case 0xcb: // double 206 case 0xcc: // unsigned int 8 207 case 0xcd: // unsigned int 16 208 case 0xce: // unsigned int 32 209 case 0xcf: // unsigned int 64 210 case 0xd0: // signed int 8 211 case 0xd1: // signed int 16 212 case 0xd2: // signed int 32 213 case 0xd3: // signed int 64 214 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); 215 case 0xd4: // fixext 1 216 case 0xd5: // fixext 2 217 case 0xd6: // fixext 4 218 case 0xd7: // fixext 8 219 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 220 (1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero); 221 case 0xd8: // fixext 16 222 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero); 223 224 case 0xd9: // str 8 225 case 0xda: // str 16 226 case 0xdb: // str 32 227 again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) & 0x03) - 1)); 228 case 0xdc: // array 16 229 case 0xdd: // array 32 230 case 0xde: // map 16 231 case 0xdf: // map 32 232 again_fixed_trail(NEXT_CS(p), 2u << (((unsigned int)*p) & 0x01)); 233 default: 234 goto _failed; 235 } 236 SWITCH_RANGE(0xa0, 0xbf) // FixStr 237 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, ((unsigned int)*p & 0x1f), _str_zero); 238 SWITCH_RANGE(0x90, 0x9f) // FixArray 239 start_container(_array, ((unsigned int)*p) & 0x0f, MSGPACK_CT_ARRAY_ITEM); 240 SWITCH_RANGE(0x80, 0x8f) // FixMap 241 start_container(_map, ((unsigned int)*p) & 0x0f, MSGPACK_CT_MAP_KEY); 242 243 SWITCH_RANGE_DEFAULT 244 goto _failed; 245 SWITCH_RANGE_END 246 // end MSGPACK_CS_HEADER 247 248 249 _fixed_trail_again: 250 ++p; 251 252 default: 253 if((size_t)(pe - p) < trail) { goto _out; } 254 n = p; p += trail - 1; 255 switch(cs) { 256 //case MSGPACK_CS_ 257 //case MSGPACK_CS_ 258 case MSGPACK_CS_FLOAT: { 259 union { uint32_t i; float f; } mem; 260 _msgpack_load32(uint32_t, n, &mem.i); 261 push_fixed_value(_float, mem.f); } 262 case MSGPACK_CS_DOUBLE: { 263 union { uint64_t i; double f; } mem; 264 _msgpack_load64(uint64_t, n, &mem.i); 265#if defined(TARGET_OS_IPHONE) 266 // ok 267#elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi 268 // https://github.com/msgpack/msgpack-perl/pull/1 269 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL); 270#endif 271 push_fixed_value(_double, mem.f); } 272 case MSGPACK_CS_UINT_8: 273 push_fixed_value(_uint8, *(uint8_t*)n); 274 case MSGPACK_CS_UINT_16:{ 275 uint16_t tmp; 276 _msgpack_load16(uint16_t,n,&tmp); 277 push_fixed_value(_uint16, tmp); 278 } 279 case MSGPACK_CS_UINT_32:{ 280 uint32_t tmp; 281 _msgpack_load32(uint32_t,n,&tmp); 282 push_fixed_value(_uint32, tmp); 283 } 284 case MSGPACK_CS_UINT_64:{ 285 uint64_t tmp; 286 _msgpack_load64(uint64_t,n,&tmp); 287 push_fixed_value(_uint64, tmp); 288 } 289 case MSGPACK_CS_INT_8: 290 push_fixed_value(_int8, *(int8_t*)n); 291 case MSGPACK_CS_INT_16:{ 292 int16_t tmp; 293 _msgpack_load16(int16_t,n,&tmp); 294 push_fixed_value(_int16, tmp); 295 } 296 case MSGPACK_CS_INT_32:{ 297 int32_t tmp; 298 _msgpack_load32(int32_t,n,&tmp); 299 push_fixed_value(_int32, tmp); 300 } 301 case MSGPACK_CS_INT_64:{ 302 int64_t tmp; 303 _msgpack_load64(int64_t,n,&tmp); 304 push_fixed_value(_int64, tmp); 305 } 306 case MSGPACK_CS_FIXEXT_1: 307 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 1+1, _ext_zero); 308 case MSGPACK_CS_FIXEXT_2: 309 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 2+1, _ext_zero); 310 case MSGPACK_CS_FIXEXT_4: 311 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 4+1, _ext_zero); 312 case MSGPACK_CS_FIXEXT_8: 313 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 8+1, _ext_zero); 314 case MSGPACK_CS_FIXEXT_16: 315 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero); 316 case MSGPACK_CS_STR_8: 317 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, *(uint8_t*)n, _str_zero); 318 case MSGPACK_CS_BIN_8: 319 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero); 320 case MSGPACK_CS_EXT_8: 321 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, (*(uint8_t*)n) + 1, _ext_zero); 322 case MSGPACK_CS_STR_16:{ 323 uint16_t tmp; 324 _msgpack_load16(uint16_t,n,&tmp); 325 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero); 326 } 327 case MSGPACK_CS_BIN_16:{ 328 uint16_t tmp; 329 _msgpack_load16(uint16_t,n,&tmp); 330 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero); 331 } 332 case MSGPACK_CS_EXT_16:{ 333 uint16_t tmp; 334 _msgpack_load16(uint16_t,n,&tmp); 335 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero); 336 } 337 case MSGPACK_CS_STR_32:{ 338 uint32_t tmp; 339 _msgpack_load32(uint32_t,n,&tmp); 340 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero); 341 } 342 case MSGPACK_CS_BIN_32:{ 343 uint32_t tmp; 344 _msgpack_load32(uint32_t,n,&tmp); 345 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero); 346 } 347 case MSGPACK_CS_EXT_32:{ 348 uint32_t tmp; 349 _msgpack_load32(uint32_t,n,&tmp); 350 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero); 351 } 352 case MSGPACK_ACS_STR_VALUE: 353 _str_zero: 354 push_variable_value(_str, data, n, trail); 355 case MSGPACK_ACS_BIN_VALUE: 356 _bin_zero: 357 push_variable_value(_bin, data, n, trail); 358 case MSGPACK_ACS_EXT_VALUE: 359 _ext_zero: 360 push_variable_value(_ext, data, n, trail); 361 362 case MSGPACK_CS_ARRAY_16:{ 363 uint16_t tmp; 364 _msgpack_load16(uint16_t,n,&tmp); 365 start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM); 366 } 367 case MSGPACK_CS_ARRAY_32:{ 368 /* FIXME security guard */ 369 uint32_t tmp; 370 _msgpack_load32(uint32_t,n,&tmp); 371 start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM); 372 } 373 374 case MSGPACK_CS_MAP_16:{ 375 uint16_t tmp; 376 _msgpack_load16(uint16_t,n,&tmp); 377 start_container(_map, tmp, MSGPACK_CT_MAP_KEY); 378 } 379 case MSGPACK_CS_MAP_32:{ 380 /* FIXME security guard */ 381 uint32_t tmp; 382 _msgpack_load32(uint32_t,n,&tmp); 383 start_container(_map, tmp, MSGPACK_CT_MAP_KEY); 384 } 385 386 default: 387 goto _failed; 388 } 389 } 390 391 _push: 392 if(top == 0) { goto _finish; } 393 c = &stack[top-1]; 394 switch(c->ct) { 395 case MSGPACK_CT_ARRAY_ITEM: 396 if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; } 397 if(--c->count == 0) { 398 obj = c->obj; 399 --top; 400 /*printf("stack pop %d\n", top);*/ 401 goto _push; 402 } 403 goto _header_again; 404 case MSGPACK_CT_MAP_KEY: 405 c->map_key = obj; 406 c->ct = MSGPACK_CT_MAP_VALUE; 407 goto _header_again; 408 case MSGPACK_CT_MAP_VALUE: 409 if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; } 410 if(--c->count == 0) { 411 obj = c->obj; 412 --top; 413 /*printf("stack pop %d\n", top);*/ 414 goto _push; 415 } 416 c->ct = MSGPACK_CT_MAP_KEY; 417 goto _header_again; 418 419 default: 420 goto _failed; 421 } 422 423 _header_again: 424 cs = MSGPACK_CS_HEADER; 425 ++p; 426 } while(p != pe); 427 goto _out; 428 429 430 _finish: 431 stack[0].obj = obj; 432 ++p; 433 ret = 1; 434 /*printf("-- finish --\n"); */ 435 goto _end; 436 437 _failed: 438 /*printf("** FAILED **\n"); */ 439 ret = -1; 440 goto _end; 441 442 _out: 443 ret = 0; 444 goto _end; 445 446 _end: 447 ctx->cs = cs; 448 ctx->trail = trail; 449 ctx->top = top; 450 *off = (size_t)(p - (const unsigned char*)data); 451 452 return ret; 453 } 454} 455 456#undef msgpack_unpack_func 457#undef msgpack_unpack_callback 458#undef msgpack_unpack_struct 459#undef msgpack_unpack_object 460#undef msgpack_unpack_user 461 462#undef push_simple_value 463#undef push_fixed_value 464#undef push_variable_value 465#undef again_fixed_trail 466#undef again_fixed_trail_if_zero 467#undef start_container 468 469#undef NEXT_CS 470 471#undef SWITCH_RANGE_BEGIN 472#undef SWITCH_RANGE 473#undef SWITCH_RANGE_DEFAULT 474#undef SWITCH_RANGE_END 475