unpack_template.h 16 KB

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