unpack_template.h 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475
  1. /*
  2. * MessagePack unpacking routine template
  3. *
  4. * Copyright (C) 2008-2010 FURUHASHI Sadayuki
  5. *
  6. * Licensed under the Apache License, Version 2.0 (the "License");
  7. * you may not use this file except in compliance with the License.
  8. * You may obtain a copy of the License at
  9. *
  10. * http://www.apache.org/licenses/LICENSE-2.0
  11. *
  12. * Unless required by applicable law or agreed to in writing, software
  13. * distributed under the License is distributed on an "AS IS" BASIS,
  14. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15. * See the License for the specific language governing permissions and
  16. * limitations under the License.
  17. */
  18. #ifndef USE_CASE_RANGE
  19. #if !defined(_MSC_VER)
  20. #define USE_CASE_RANGE
  21. #endif
  22. #endif
  23. typedef struct unpack_stack {
  24. PyObject* obj;
  25. size_t size;
  26. size_t count;
  27. unsigned int ct;
  28. PyObject* map_key;
  29. } unpack_stack;
  30. struct unpack_context {
  31. unpack_user user;
  32. unsigned int cs;
  33. unsigned int trail;
  34. unsigned int top;
  35. /*
  36. unpack_stack* stack;
  37. unsigned int stack_size;
  38. unpack_stack embed_stack[MSGPACK_EMBED_STACK_SIZE];
  39. */
  40. unpack_stack stack[MSGPACK_EMBED_STACK_SIZE];
  41. };
  42. static inline void unpack_init(unpack_context* ctx)
  43. {
  44. ctx->cs = CS_HEADER;
  45. ctx->trail = 0;
  46. ctx->top = 0;
  47. /*
  48. ctx->stack = ctx->embed_stack;
  49. ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
  50. */
  51. ctx->stack[0].obj = unpack_callback_root(&ctx->user);
  52. }
  53. /*
  54. static inline void unpack_destroy(unpack_context* ctx)
  55. {
  56. if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) {
  57. free(ctx->stack);
  58. }
  59. }
  60. */
  61. static inline PyObject* unpack_data(unpack_context* ctx)
  62. {
  63. return (ctx)->stack[0].obj;
  64. }
  65. template <bool construct>
  66. static inline int unpack_execute(unpack_context* ctx, const char* data, size_t len, size_t* off)
  67. {
  68. assert(len >= *off);
  69. const unsigned char* p = (unsigned char*)data + *off;
  70. const unsigned char* const pe = (unsigned char*)data + len;
  71. const void* n = NULL;
  72. unsigned int trail = ctx->trail;
  73. unsigned int cs = ctx->cs;
  74. unsigned int top = ctx->top;
  75. unpack_stack* stack = ctx->stack;
  76. /*
  77. unsigned int stack_size = ctx->stack_size;
  78. */
  79. unpack_user* user = &ctx->user;
  80. PyObject* obj;
  81. unpack_stack* c = NULL;
  82. int ret;
  83. #define construct_cb(name) \
  84. construct && unpack_callback ## name
  85. #define push_simple_value(func) \
  86. if(construct_cb(func)(user, &obj) < 0) { goto _failed; } \
  87. goto _push
  88. #define push_fixed_value(func, arg) \
  89. if(construct_cb(func)(user, arg, &obj) < 0) { goto _failed; } \
  90. goto _push
  91. #define push_variable_value(func, base, pos, len) \
  92. if(construct_cb(func)(user, \
  93. (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \
  94. goto _push
  95. #define again_fixed_trail(_cs, trail_len) \
  96. trail = trail_len; \
  97. cs = _cs; \
  98. goto _fixed_trail_again
  99. #define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
  100. trail = trail_len; \
  101. if(trail == 0) { goto ifzero; } \
  102. cs = _cs; \
  103. goto _fixed_trail_again
  104. #define start_container(func, count_, ct_) \
  105. if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \
  106. if(construct_cb(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \
  107. if((count_) == 0) { obj = stack[top].obj; \
  108. if (construct_cb(func##_end)(user, &obj) < 0) { goto _failed; } \
  109. goto _push; } \
  110. stack[top].ct = ct_; \
  111. stack[top].size = count_; \
  112. stack[top].count = 0; \
  113. ++top; \
  114. /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \
  115. /*printf("stack push %d\n", top);*/ \
  116. /* FIXME \
  117. if(top >= stack_size) { \
  118. if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \
  119. size_t csize = sizeof(unpack_stack) * MSGPACK_EMBED_STACK_SIZE; \
  120. size_t nsize = csize * 2; \
  121. unpack_stack* tmp = (unpack_stack*)malloc(nsize); \
  122. if(tmp == NULL) { goto _failed; } \
  123. memcpy(tmp, ctx->stack, csize); \
  124. ctx->stack = stack = tmp; \
  125. ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \
  126. } else { \
  127. size_t nsize = sizeof(unpack_stack) * ctx->stack_size * 2; \
  128. unpack_stack* tmp = (unpack_stack*)realloc(ctx->stack, nsize); \
  129. if(tmp == NULL) { goto _failed; } \
  130. ctx->stack = stack = tmp; \
  131. ctx->stack_size = stack_size = stack_size * 2; \
  132. } \
  133. } \
  134. */ \
  135. goto _header_again
  136. #define NEXT_CS(p) ((unsigned int)*p & 0x1f)
  137. #ifdef USE_CASE_RANGE
  138. #define SWITCH_RANGE_BEGIN switch(*p) {
  139. #define SWITCH_RANGE(FROM, TO) case FROM ... TO:
  140. #define SWITCH_RANGE_DEFAULT default:
  141. #define SWITCH_RANGE_END }
  142. #else
  143. #define SWITCH_RANGE_BEGIN { if(0) {
  144. #define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
  145. #define SWITCH_RANGE_DEFAULT } else {
  146. #define SWITCH_RANGE_END } }
  147. #endif
  148. if(p == pe) { goto _out; }
  149. do {
  150. switch(cs) {
  151. case CS_HEADER:
  152. SWITCH_RANGE_BEGIN
  153. SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum
  154. push_fixed_value(_uint8, *(uint8_t*)p);
  155. SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum
  156. push_fixed_value(_int8, *(int8_t*)p);
  157. SWITCH_RANGE(0xc0, 0xdf) // Variable
  158. switch(*p) {
  159. case 0xc0: // nil
  160. push_simple_value(_nil);
  161. //case 0xc1: // never used
  162. case 0xc2: // false
  163. push_simple_value(_false);
  164. case 0xc3: // true
  165. push_simple_value(_true);
  166. case 0xc4: // bin 8
  167. again_fixed_trail(NEXT_CS(p), 1);
  168. case 0xc5: // bin 16
  169. again_fixed_trail(NEXT_CS(p), 2);
  170. case 0xc6: // bin 32
  171. again_fixed_trail(NEXT_CS(p), 4);
  172. case 0xc7: // ext 8
  173. again_fixed_trail(NEXT_CS(p), 1);
  174. case 0xc8: // ext 16
  175. again_fixed_trail(NEXT_CS(p), 2);
  176. case 0xc9: // ext 32
  177. again_fixed_trail(NEXT_CS(p), 4);
  178. case 0xca: // float
  179. case 0xcb: // double
  180. case 0xcc: // unsigned int 8
  181. case 0xcd: // unsigned int 16
  182. case 0xce: // unsigned int 32
  183. case 0xcf: // unsigned int 64
  184. case 0xd0: // signed int 8
  185. case 0xd1: // signed int 16
  186. case 0xd2: // signed int 32
  187. case 0xd3: // signed int 64
  188. again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
  189. case 0xd4: // fixext 1
  190. case 0xd5: // fixext 2
  191. case 0xd6: // fixext 4
  192. case 0xd7: // fixext 8
  193. again_fixed_trail_if_zero(ACS_EXT_VALUE,
  194. (1 << (((unsigned int)*p) & 0x03))+1,
  195. _ext_zero);
  196. case 0xd8: // fixext 16
  197. again_fixed_trail_if_zero(ACS_EXT_VALUE, 16+1, _ext_zero);
  198. case 0xd9: // str 8
  199. again_fixed_trail(NEXT_CS(p), 1);
  200. case 0xda: // raw 16
  201. case 0xdb: // raw 32
  202. case 0xdc: // array 16
  203. case 0xdd: // array 32
  204. case 0xde: // map 16
  205. case 0xdf: // map 32
  206. again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01));
  207. default:
  208. goto _failed;
  209. }
  210. SWITCH_RANGE(0xa0, 0xbf) // FixRaw
  211. again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero);
  212. SWITCH_RANGE(0x90, 0x9f) // FixArray
  213. start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM);
  214. SWITCH_RANGE(0x80, 0x8f) // FixMap
  215. start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY);
  216. SWITCH_RANGE_DEFAULT
  217. goto _failed;
  218. SWITCH_RANGE_END
  219. // end CS_HEADER
  220. _fixed_trail_again:
  221. ++p;
  222. default:
  223. if((size_t)(pe - p) < trail) { goto _out; }
  224. n = p; p += trail - 1;
  225. switch(cs) {
  226. case CS_EXT_8:
  227. again_fixed_trail_if_zero(ACS_EXT_VALUE, *(uint8_t*)n+1, _ext_zero);
  228. case CS_EXT_16:
  229. again_fixed_trail_if_zero(ACS_EXT_VALUE,
  230. _msgpack_load16(uint16_t,n)+1,
  231. _ext_zero);
  232. case CS_EXT_32:
  233. again_fixed_trail_if_zero(ACS_EXT_VALUE,
  234. _msgpack_load32(uint32_t,n)+1,
  235. _ext_zero);
  236. case CS_FLOAT: {
  237. union { uint32_t i; float f; } mem;
  238. mem.i = _msgpack_load32(uint32_t,n);
  239. push_fixed_value(_float, mem.f); }
  240. case CS_DOUBLE: {
  241. union { uint64_t i; double f; } mem;
  242. mem.i = _msgpack_load64(uint64_t,n);
  243. #if defined(__arm__) && !(__ARM_EABI__) // arm-oabi
  244. // https://github.com/msgpack/msgpack-perl/pull/1
  245. mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
  246. #endif
  247. push_fixed_value(_double, mem.f); }
  248. case CS_UINT_8:
  249. push_fixed_value(_uint8, *(uint8_t*)n);
  250. case CS_UINT_16:
  251. push_fixed_value(_uint16, _msgpack_load16(uint16_t,n));
  252. case CS_UINT_32:
  253. push_fixed_value(_uint32, _msgpack_load32(uint32_t,n));
  254. case CS_UINT_64:
  255. push_fixed_value(_uint64, _msgpack_load64(uint64_t,n));
  256. case CS_INT_8:
  257. push_fixed_value(_int8, *(int8_t*)n);
  258. case CS_INT_16:
  259. push_fixed_value(_int16, _msgpack_load16(int16_t,n));
  260. case CS_INT_32:
  261. push_fixed_value(_int32, _msgpack_load32(int32_t,n));
  262. case CS_INT_64:
  263. push_fixed_value(_int64, _msgpack_load64(int64_t,n));
  264. case CS_BIN_8:
  265. again_fixed_trail_if_zero(ACS_BIN_VALUE, *(uint8_t*)n, _bin_zero);
  266. case CS_BIN_16:
  267. again_fixed_trail_if_zero(ACS_BIN_VALUE, _msgpack_load16(uint16_t,n), _bin_zero);
  268. case CS_BIN_32:
  269. again_fixed_trail_if_zero(ACS_BIN_VALUE, _msgpack_load32(uint32_t,n), _bin_zero);
  270. case ACS_BIN_VALUE:
  271. _bin_zero:
  272. push_variable_value(_bin, data, n, trail);
  273. case CS_RAW_8:
  274. again_fixed_trail_if_zero(ACS_RAW_VALUE, *(uint8_t*)n, _raw_zero);
  275. case CS_RAW_16:
  276. again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load16(uint16_t,n), _raw_zero);
  277. case CS_RAW_32:
  278. again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load32(uint32_t,n), _raw_zero);
  279. case ACS_RAW_VALUE:
  280. _raw_zero:
  281. push_variable_value(_raw, data, n, trail);
  282. case ACS_EXT_VALUE:
  283. _ext_zero:
  284. push_variable_value(_ext, data, n, trail);
  285. case CS_ARRAY_16:
  286. start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM);
  287. case CS_ARRAY_32:
  288. /* FIXME security guard */
  289. start_container(_array, _msgpack_load32(uint32_t,n), CT_ARRAY_ITEM);
  290. case CS_MAP_16:
  291. start_container(_map, _msgpack_load16(uint16_t,n), CT_MAP_KEY);
  292. case CS_MAP_32:
  293. /* FIXME security guard */
  294. start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY);
  295. default:
  296. goto _failed;
  297. }
  298. }
  299. _push:
  300. if(top == 0) { goto _finish; }
  301. c = &stack[top-1];
  302. switch(c->ct) {
  303. case CT_ARRAY_ITEM:
  304. if(construct_cb(_array_item)(user, c->count, &c->obj, obj) < 0) { goto _failed; }
  305. if(++c->count == c->size) {
  306. obj = c->obj;
  307. if (construct_cb(_array_end)(user, &obj) < 0) { goto _failed; }
  308. --top;
  309. /*printf("stack pop %d\n", top);*/
  310. goto _push;
  311. }
  312. goto _header_again;
  313. case CT_MAP_KEY:
  314. c->map_key = obj;
  315. c->ct = CT_MAP_VALUE;
  316. goto _header_again;
  317. case CT_MAP_VALUE:
  318. if(construct_cb(_map_item)(user, c->count, &c->obj, c->map_key, obj) < 0) { goto _failed; }
  319. if(++c->count == c->size) {
  320. obj = c->obj;
  321. if (construct_cb(_map_end)(user, &obj) < 0) { goto _failed; }
  322. --top;
  323. /*printf("stack pop %d\n", top);*/
  324. goto _push;
  325. }
  326. c->ct = CT_MAP_KEY;
  327. goto _header_again;
  328. default:
  329. goto _failed;
  330. }
  331. _header_again:
  332. cs = CS_HEADER;
  333. ++p;
  334. } while(p != pe);
  335. goto _out;
  336. _finish:
  337. if (!construct)
  338. unpack_callback_nil(user, &obj);
  339. stack[0].obj = obj;
  340. ++p;
  341. ret = 1;
  342. /*printf("-- finish --\n"); */
  343. goto _end;
  344. _failed:
  345. /*printf("** FAILED **\n"); */
  346. ret = -1;
  347. goto _end;
  348. _out:
  349. ret = 0;
  350. goto _end;
  351. _end:
  352. ctx->cs = cs;
  353. ctx->trail = trail;
  354. ctx->top = top;
  355. *off = p - (const unsigned char*)data;
  356. return ret;
  357. #undef construct_cb
  358. }
  359. #undef SWITCH_RANGE_BEGIN
  360. #undef SWITCH_RANGE
  361. #undef SWITCH_RANGE_DEFAULT
  362. #undef SWITCH_RANGE_END
  363. #undef push_simple_value
  364. #undef push_fixed_value
  365. #undef push_variable_value
  366. #undef again_fixed_trail
  367. #undef again_fixed_trail_if_zero
  368. #undef start_container
  369. template <unsigned int fixed_offset, unsigned int var_offset>
  370. static inline int unpack_container_header(unpack_context* ctx, const char* data, size_t len, size_t* off)
  371. {
  372. assert(len >= *off);
  373. uint32_t size;
  374. const unsigned char *const p = (unsigned char*)data + *off;
  375. #define inc_offset(inc) \
  376. if (len - *off < inc) \
  377. return 0; \
  378. *off += inc;
  379. switch (*p) {
  380. case var_offset:
  381. inc_offset(3);
  382. size = _msgpack_load16(uint16_t, p + 1);
  383. break;
  384. case var_offset + 1:
  385. inc_offset(5);
  386. size = _msgpack_load32(uint32_t, p + 1);
  387. break;
  388. #ifdef USE_CASE_RANGE
  389. case fixed_offset + 0x0 ... fixed_offset + 0xf:
  390. #else
  391. case fixed_offset + 0x0:
  392. case fixed_offset + 0x1:
  393. case fixed_offset + 0x2:
  394. case fixed_offset + 0x3:
  395. case fixed_offset + 0x4:
  396. case fixed_offset + 0x5:
  397. case fixed_offset + 0x6:
  398. case fixed_offset + 0x7:
  399. case fixed_offset + 0x8:
  400. case fixed_offset + 0x9:
  401. case fixed_offset + 0xa:
  402. case fixed_offset + 0xb:
  403. case fixed_offset + 0xc:
  404. case fixed_offset + 0xd:
  405. case fixed_offset + 0xe:
  406. case fixed_offset + 0xf:
  407. #endif
  408. ++*off;
  409. size = ((unsigned int)*p) & 0x0f;
  410. break;
  411. default:
  412. PyErr_SetString(PyExc_ValueError, "Unexpected type header on stream");
  413. return -1;
  414. }
  415. unpack_callback_uint32(&ctx->user, size, &ctx->stack[0].obj);
  416. return 1;
  417. }
  418. #undef SWITCH_RANGE_BEGIN
  419. #undef SWITCH_RANGE
  420. #undef SWITCH_RANGE_DEFAULT
  421. #undef SWITCH_RANGE_END
  422. static const execute_fn unpack_construct = &unpack_execute<true>;
  423. static const execute_fn unpack_skip = &unpack_execute<false>;
  424. static const execute_fn read_array_header = &unpack_container_header<0x90, 0xdc>;
  425. static const execute_fn read_map_header = &unpack_container_header<0x80, 0xde>;
  426. #undef NEXT_CS
  427. /* vim: set ts=4 sw=4 sts=4 expandtab */