messagepack implementation for embedded systems (mbed / arduino)
Dependents: hello_message_pack
unpack_template.h
00001 /* 00002 * MessagePack unpacking routine template 00003 * 00004 * Copyright (C) 2008-2010 FURUHASHI Sadayuki 00005 * 00006 * Distributed under the Boost Software License, Version 1.0. 00007 * (See accompanying file LICENSE_1_0.txt or copy at 00008 * http://www.boost.org/LICENSE_1_0.txt) 00009 */ 00010 00011 #ifndef msgpack_unpack_func 00012 #error msgpack_unpack_func template is not defined 00013 #endif 00014 00015 #ifndef msgpack_unpack_callback 00016 #error msgpack_unpack_callback template is not defined 00017 #endif 00018 00019 #ifndef msgpack_unpack_struct 00020 #error msgpack_unpack_struct template is not defined 00021 #endif 00022 00023 #ifndef msgpack_unpack_struct_decl 00024 #define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name) 00025 #endif 00026 00027 #ifndef msgpack_unpack_object 00028 #error msgpack_unpack_object type is not defined 00029 #endif 00030 00031 #ifndef msgpack_unpack_user 00032 #error msgpack_unpack_user type is not defined 00033 #endif 00034 00035 #ifndef USE_CASE_RANGE 00036 #if !defined(_MSC_VER) 00037 #define USE_CASE_RANGE 00038 #endif 00039 #endif 00040 00041 msgpack_unpack_struct_decl(_stack) { 00042 msgpack_unpack_object obj; 00043 size_t count; 00044 unsigned int ct; 00045 msgpack_unpack_object map_key; 00046 }; 00047 00048 msgpack_unpack_struct_decl(_context) { 00049 msgpack_unpack_user user; 00050 unsigned int cs; 00051 unsigned int trail; 00052 unsigned int top; 00053 /* 00054 msgpack_unpack_struct(_stack)* stack; 00055 unsigned int stack_size; 00056 msgpack_unpack_struct(_stack) embed_stack[MSGPACK_EMBED_STACK_SIZE]; 00057 */ 00058 msgpack_unpack_struct(_stack) stack[MSGPACK_EMBED_STACK_SIZE]; 00059 }; 00060 00061 00062 msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx) 00063 { 00064 ctx->cs = MSGPACK_CS_HEADER; 00065 ctx->trail = 0; 00066 ctx->top = 0; 00067 /* 00068 ctx->stack = ctx->embed_stack; 00069 ctx->stack_size = MSGPACK_EMBED_STACK_SIZE; 00070 */ 00071 ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user); 00072 } 00073 00074 /* 00075 msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx) 00076 { 00077 if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) { 00078 free(ctx->stack); 00079 } 00080 } 00081 */ 00082 00083 msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx) 00084 { 00085 return (ctx)->stack[0].obj; 00086 } 00087 00088 00089 msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off) 00090 { 00091 assert(len >= *off); 00092 { 00093 const unsigned char* p = (unsigned char*)data + *off; 00094 const unsigned char* const pe = (unsigned char*)data + len; 00095 const void* n = NULL; 00096 00097 unsigned int trail = ctx->trail; 00098 unsigned int cs = ctx->cs; 00099 unsigned int top = ctx->top; 00100 msgpack_unpack_struct(_stack)* stack = ctx->stack; 00101 /* 00102 unsigned int stack_size = ctx->stack_size; 00103 */ 00104 msgpack_unpack_user* user = &ctx->user; 00105 00106 msgpack_unpack_object obj; 00107 msgpack_unpack_struct(_stack)* c = NULL; 00108 00109 int ret; 00110 00111 #define push_simple_value(func) \ 00112 if(msgpack_unpack_callback(func)(user, &obj) < 0) { goto _failed; } \ 00113 goto _push 00114 #define push_fixed_value(func, arg) \ 00115 if(msgpack_unpack_callback(func)(user, arg, &obj) < 0) { goto _failed; } \ 00116 goto _push 00117 #define push_variable_value(func, base, pos, len) \ 00118 if(msgpack_unpack_callback(func)(user, \ 00119 (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \ 00120 goto _push 00121 00122 #define again_fixed_trail(_cs, trail_len) \ 00123 trail = trail_len; \ 00124 cs = _cs; \ 00125 goto _fixed_trail_again 00126 #define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \ 00127 trail = trail_len; \ 00128 if(trail == 0) { goto ifzero; } \ 00129 cs = _cs; \ 00130 goto _fixed_trail_again 00131 00132 #define start_container(func, count_, ct_) \ 00133 if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \ 00134 if(msgpack_unpack_callback(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \ 00135 if((count_) == 0) { obj = stack[top].obj; goto _push; } \ 00136 stack[top].ct = ct_; \ 00137 stack[top].count = count_; \ 00138 ++top; \ 00139 /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \ 00140 /*printf("stack push %d\n", top);*/ \ 00141 /* FIXME \ 00142 if(top >= stack_size) { \ 00143 if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \ 00144 size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \ 00145 size_t nsize = csize * 2; \ 00146 msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \ 00147 if(tmp == NULL) { goto _failed; } \ 00148 memcpy(tmp, ctx->stack, csize); \ 00149 ctx->stack = stack = tmp; \ 00150 ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \ 00151 } else { \ 00152 size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \ 00153 msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \ 00154 if(tmp == NULL) { goto _failed; } \ 00155 ctx->stack = stack = tmp; \ 00156 ctx->stack_size = stack_size = stack_size * 2; \ 00157 } \ 00158 } \ 00159 */ \ 00160 goto _header_again 00161 00162 #define NEXT_CS(p) \ 00163 ((unsigned int)*p & 0x1f) 00164 00165 #ifdef USE_CASE_RANGE 00166 #define SWITCH_RANGE_BEGIN switch(*p) { 00167 #define SWITCH_RANGE(FROM, TO) case FROM ... TO: 00168 #define SWITCH_RANGE_DEFAULT default: 00169 #define SWITCH_RANGE_END } 00170 #else 00171 #define SWITCH_RANGE_BEGIN { if(0) { 00172 #define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) { 00173 #define SWITCH_RANGE_DEFAULT } else { 00174 #define SWITCH_RANGE_END } } 00175 #endif 00176 00177 if(p == pe) { goto _out; } 00178 do { 00179 switch(cs) { 00180 case MSGPACK_CS_HEADER: 00181 SWITCH_RANGE_BEGIN 00182 SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum 00183 push_fixed_value(_uint8, *(uint8_t*)p); 00184 SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum 00185 push_fixed_value(_int8, *(int8_t*)p); 00186 SWITCH_RANGE(0xc0, 0xdf) // Variable 00187 switch(*p) { 00188 case 0xc0: // nil 00189 push_simple_value(_nil); 00190 //case 0xc1: // string 00191 // again_terminal_trail(NEXT_CS(p), p+1); 00192 case 0xc2: // false 00193 push_simple_value(_false); 00194 case 0xc3: // true 00195 push_simple_value(_true); 00196 case 0xc4: // bin 8 00197 case 0xc5: // bin 16 00198 case 0xc6: // bin 32 00199 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); 00200 case 0xc7: // ext 8 00201 case 0xc8: // ext 16 00202 case 0xc9: // ext 32 00203 again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) + 1) & 0x03)); 00204 case 0xca: // float 00205 case 0xcb: // double 00206 case 0xcc: // unsigned int 8 00207 case 0xcd: // unsigned int 16 00208 case 0xce: // unsigned int 32 00209 case 0xcf: // unsigned int 64 00210 case 0xd0: // signed int 8 00211 case 0xd1: // signed int 16 00212 case 0xd2: // signed int 32 00213 case 0xd3: // signed int 64 00214 again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03)); 00215 case 0xd4: // fixext 1 00216 case 0xd5: // fixext 2 00217 case 0xd6: // fixext 4 00218 case 0xd7: // fixext 8 00219 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 00220 (1 << (((unsigned int)*p) & 0x03)) + 1, _ext_zero); 00221 case 0xd8: // fixext 16 00222 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero); 00223 00224 case 0xd9: // str 8 00225 case 0xda: // str 16 00226 case 0xdb: // str 32 00227 again_fixed_trail(NEXT_CS(p), 1 << ((((unsigned int)*p) & 0x03) - 1)); 00228 case 0xdc: // array 16 00229 case 0xdd: // array 32 00230 case 0xde: // map 16 00231 case 0xdf: // map 32 00232 again_fixed_trail(NEXT_CS(p), 2u << (((unsigned int)*p) & 0x01)); 00233 default: 00234 goto _failed; 00235 } 00236 SWITCH_RANGE(0xa0, 0xbf) // FixStr 00237 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, ((unsigned int)*p & 0x1f), _str_zero); 00238 SWITCH_RANGE(0x90, 0x9f) // FixArray 00239 start_container(_array, ((unsigned int)*p) & 0x0f, MSGPACK_CT_ARRAY_ITEM); 00240 SWITCH_RANGE(0x80, 0x8f) // FixMap 00241 start_container(_map, ((unsigned int)*p) & 0x0f, MSGPACK_CT_MAP_KEY); 00242 00243 SWITCH_RANGE_DEFAULT 00244 goto _failed; 00245 SWITCH_RANGE_END 00246 // end MSGPACK_CS_HEADER 00247 00248 00249 _fixed_trail_again: 00250 ++p; 00251 00252 default: 00253 if((size_t)(pe - p) < trail) { goto _out; } 00254 n = p; p += trail - 1; 00255 switch(cs) { 00256 //case MSGPACK_CS_ 00257 //case MSGPACK_CS_ 00258 case MSGPACK_CS_FLOAT: { 00259 union { uint32_t i; float f; } mem; 00260 _msgpack_load32(uint32_t, n, &mem.i); 00261 push_fixed_value(_float, mem.f); } 00262 case MSGPACK_CS_DOUBLE: { 00263 union { uint64_t i; double f; } mem; 00264 _msgpack_load64(uint64_t, n, &mem.i); 00265 #if defined(TARGET_OS_IPHONE) 00266 // ok 00267 #elif defined(__arm__) && !(__ARM_EABI__) // arm-oabi 00268 // https://github.com/msgpack/msgpack-perl/pull/1 00269 mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL); 00270 #endif 00271 push_fixed_value(_double, mem.f); } 00272 case MSGPACK_CS_UINT_8: 00273 push_fixed_value(_uint8, *(uint8_t*)n); 00274 case MSGPACK_CS_UINT_16:{ 00275 uint16_t tmp; 00276 _msgpack_load16(uint16_t,n,&tmp); 00277 push_fixed_value(_uint16, tmp); 00278 } 00279 case MSGPACK_CS_UINT_32:{ 00280 uint32_t tmp; 00281 _msgpack_load32(uint32_t,n,&tmp); 00282 push_fixed_value(_uint32, tmp); 00283 } 00284 case MSGPACK_CS_UINT_64:{ 00285 uint64_t tmp; 00286 _msgpack_load64(uint64_t,n,&tmp); 00287 push_fixed_value(_uint64, tmp); 00288 } 00289 case MSGPACK_CS_INT_8: 00290 push_fixed_value(_int8, *(int8_t*)n); 00291 case MSGPACK_CS_INT_16:{ 00292 int16_t tmp; 00293 _msgpack_load16(int16_t,n,&tmp); 00294 push_fixed_value(_int16, tmp); 00295 } 00296 case MSGPACK_CS_INT_32:{ 00297 int32_t tmp; 00298 _msgpack_load32(int32_t,n,&tmp); 00299 push_fixed_value(_int32, tmp); 00300 } 00301 case MSGPACK_CS_INT_64:{ 00302 int64_t tmp; 00303 _msgpack_load64(int64_t,n,&tmp); 00304 push_fixed_value(_int64, tmp); 00305 } 00306 case MSGPACK_CS_FIXEXT_1: 00307 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 1+1, _ext_zero); 00308 case MSGPACK_CS_FIXEXT_2: 00309 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 2+1, _ext_zero); 00310 case MSGPACK_CS_FIXEXT_4: 00311 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 4+1, _ext_zero); 00312 case MSGPACK_CS_FIXEXT_8: 00313 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 8+1, _ext_zero); 00314 case MSGPACK_CS_FIXEXT_16: 00315 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, 16+1, _ext_zero); 00316 case MSGPACK_CS_STR_8: 00317 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, *(uint8_t*)n, _str_zero); 00318 case MSGPACK_CS_BIN_8: 00319 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero); 00320 case MSGPACK_CS_EXT_8: 00321 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, (*(uint8_t*)n) + 1, _ext_zero); 00322 case MSGPACK_CS_STR_16:{ 00323 uint16_t tmp; 00324 _msgpack_load16(uint16_t,n,&tmp); 00325 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero); 00326 } 00327 case MSGPACK_CS_BIN_16:{ 00328 uint16_t tmp; 00329 _msgpack_load16(uint16_t,n,&tmp); 00330 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero); 00331 } 00332 case MSGPACK_CS_EXT_16:{ 00333 uint16_t tmp; 00334 _msgpack_load16(uint16_t,n,&tmp); 00335 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero); 00336 } 00337 case MSGPACK_CS_STR_32:{ 00338 uint32_t tmp; 00339 _msgpack_load32(uint32_t,n,&tmp); 00340 again_fixed_trail_if_zero(MSGPACK_ACS_STR_VALUE, tmp, _str_zero); 00341 } 00342 case MSGPACK_CS_BIN_32:{ 00343 uint32_t tmp; 00344 _msgpack_load32(uint32_t,n,&tmp); 00345 again_fixed_trail_if_zero(MSGPACK_ACS_BIN_VALUE, tmp, _bin_zero); 00346 } 00347 case MSGPACK_CS_EXT_32:{ 00348 uint32_t tmp; 00349 _msgpack_load32(uint32_t,n,&tmp); 00350 again_fixed_trail_if_zero(MSGPACK_ACS_EXT_VALUE, tmp + 1, _ext_zero); 00351 } 00352 case MSGPACK_ACS_STR_VALUE: 00353 _str_zero: 00354 push_variable_value(_str, data, n, trail); 00355 case MSGPACK_ACS_BIN_VALUE: 00356 _bin_zero: 00357 push_variable_value(_bin, data, n, trail); 00358 case MSGPACK_ACS_EXT_VALUE: 00359 _ext_zero: 00360 push_variable_value(_ext, data, n, trail); 00361 00362 case MSGPACK_CS_ARRAY_16:{ 00363 uint16_t tmp; 00364 _msgpack_load16(uint16_t,n,&tmp); 00365 start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM); 00366 } 00367 case MSGPACK_CS_ARRAY_32:{ 00368 /* FIXME security guard */ 00369 uint32_t tmp; 00370 _msgpack_load32(uint32_t,n,&tmp); 00371 start_container(_array, tmp, MSGPACK_CT_ARRAY_ITEM); 00372 } 00373 00374 case MSGPACK_CS_MAP_16:{ 00375 uint16_t tmp; 00376 _msgpack_load16(uint16_t,n,&tmp); 00377 start_container(_map, tmp, MSGPACK_CT_MAP_KEY); 00378 } 00379 case MSGPACK_CS_MAP_32:{ 00380 /* FIXME security guard */ 00381 uint32_t tmp; 00382 _msgpack_load32(uint32_t,n,&tmp); 00383 start_container(_map, tmp, MSGPACK_CT_MAP_KEY); 00384 } 00385 00386 default: 00387 goto _failed; 00388 } 00389 } 00390 00391 _push: 00392 if(top == 0) { goto _finish; } 00393 c = &stack[top-1]; 00394 switch(c->ct) { 00395 case MSGPACK_CT_ARRAY_ITEM: 00396 if(msgpack_unpack_callback(_array_item)(user, &c->obj, obj) < 0) { goto _failed; } 00397 if(--c->count == 0) { 00398 obj = c->obj; 00399 --top; 00400 /*printf("stack pop %d\n", top);*/ 00401 goto _push; 00402 } 00403 goto _header_again; 00404 case MSGPACK_CT_MAP_KEY: 00405 c->map_key = obj; 00406 c->ct = MSGPACK_CT_MAP_VALUE; 00407 goto _header_again; 00408 case MSGPACK_CT_MAP_VALUE: 00409 if(msgpack_unpack_callback(_map_item)(user, &c->obj, c->map_key, obj) < 0) { goto _failed; } 00410 if(--c->count == 0) { 00411 obj = c->obj; 00412 --top; 00413 /*printf("stack pop %d\n", top);*/ 00414 goto _push; 00415 } 00416 c->ct = MSGPACK_CT_MAP_KEY; 00417 goto _header_again; 00418 00419 default: 00420 goto _failed; 00421 } 00422 00423 _header_again: 00424 cs = MSGPACK_CS_HEADER; 00425 ++p; 00426 } while(p != pe); 00427 goto _out; 00428 00429 00430 _finish: 00431 stack[0].obj = obj; 00432 ++p; 00433 ret = 1; 00434 /*printf("-- finish --\n"); */ 00435 goto _end; 00436 00437 _failed: 00438 /*printf("** FAILED **\n"); */ 00439 ret = -1; 00440 goto _end; 00441 00442 _out: 00443 ret = 0; 00444 goto _end; 00445 00446 _end: 00447 ctx->cs = cs; 00448 ctx->trail = trail; 00449 ctx->top = top; 00450 *off = (size_t)(p - (const unsigned char*)data); 00451 00452 return ret; 00453 } 00454 } 00455 00456 #undef msgpack_unpack_func 00457 #undef msgpack_unpack_callback 00458 #undef msgpack_unpack_struct 00459 #undef msgpack_unpack_object 00460 #undef msgpack_unpack_user 00461 00462 #undef push_simple_value 00463 #undef push_fixed_value 00464 #undef push_variable_value 00465 #undef again_fixed_trail 00466 #undef again_fixed_trail_if_zero 00467 #undef start_container 00468 00469 #undef NEXT_CS 00470 00471 #undef SWITCH_RANGE_BEGIN 00472 #undef SWITCH_RANGE 00473 #undef SWITCH_RANGE_DEFAULT 00474 #undef SWITCH_RANGE_END 00475
Generated on Tue Jul 12 2022 22:51:46 by 1.7.2