PageRenderTime 50ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 0ms

/pandas/src/msgpack/unpack_template.h

http://github.com/pydata/pandas
C Header | 492 lines | 339 code | 55 blank | 98 comment | 34 complexity | 0210e1bcc85c78ea4baab3d685df9273 MD5 | raw file
Possible License(s): BSD-3-Clause, Apache-2.0
  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 msgpack_unpack_func
  19. #error msgpack_unpack_func template is not defined
  20. #endif
  21. #ifndef msgpack_unpack_callback
  22. #error msgpack_unpack_callback template is not defined
  23. #endif
  24. #ifndef msgpack_unpack_struct
  25. #error msgpack_unpack_struct template is not defined
  26. #endif
  27. #ifndef msgpack_unpack_struct_decl
  28. #define msgpack_unpack_struct_decl(name) msgpack_unpack_struct(name)
  29. #endif
  30. #ifndef msgpack_unpack_object
  31. #error msgpack_unpack_object type is not defined
  32. #endif
  33. #ifndef msgpack_unpack_user
  34. #error msgpack_unpack_user type is not defined
  35. #endif
  36. #ifndef USE_CASE_RANGE
  37. #if !defined(_MSC_VER)
  38. #define USE_CASE_RANGE
  39. #endif
  40. #endif
  41. msgpack_unpack_struct_decl(_stack) {
  42. msgpack_unpack_object obj;
  43. size_t size;
  44. size_t count;
  45. unsigned int ct;
  46. msgpack_unpack_object map_key;
  47. };
  48. msgpack_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. msgpack_unpack_func(void, _init)(msgpack_unpack_struct(_context)* ctx)
  61. {
  62. ctx->cs = CS_HEADER;
  63. ctx->trail = 0;
  64. ctx->top = 0;
  65. /*
  66. ctx->stack = ctx->embed_stack;
  67. ctx->stack_size = MSGPACK_EMBED_STACK_SIZE;
  68. */
  69. ctx->stack[0].obj = msgpack_unpack_callback(_root)(&ctx->user);
  70. }
  71. /*
  72. msgpack_unpack_func(void, _destroy)(msgpack_unpack_struct(_context)* ctx)
  73. {
  74. if(ctx->stack_size != MSGPACK_EMBED_STACK_SIZE) {
  75. free(ctx->stack);
  76. }
  77. }
  78. */
  79. msgpack_unpack_func(msgpack_unpack_object, _data)(msgpack_unpack_struct(_context)* ctx)
  80. {
  81. return (ctx)->stack[0].obj;
  82. }
  83. template <bool construct>
  84. msgpack_unpack_func(int, _execute)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off)
  85. {
  86. assert(len >= *off);
  87. const unsigned char* p = (unsigned char*)data + *off;
  88. const unsigned char* const pe = (unsigned char*)data + len;
  89. const void* n = NULL;
  90. unsigned int trail = ctx->trail;
  91. unsigned int cs = ctx->cs;
  92. unsigned int top = ctx->top;
  93. msgpack_unpack_struct(_stack)* stack = ctx->stack;
  94. /*
  95. unsigned int stack_size = ctx->stack_size;
  96. */
  97. msgpack_unpack_user* user = &ctx->user;
  98. msgpack_unpack_object obj;
  99. msgpack_unpack_struct(_stack)* c = NULL;
  100. int ret;
  101. #define construct_cb(name) \
  102. construct && msgpack_unpack_callback(name)
  103. #define push_simple_value(func) \
  104. if(construct_cb(func)(user, &obj) < 0) { goto _failed; } \
  105. goto _push
  106. #define push_fixed_value(func, arg) \
  107. if(construct_cb(func)(user, arg, &obj) < 0) { goto _failed; } \
  108. goto _push
  109. #define push_variable_value(func, base, pos, len) \
  110. if(construct_cb(func)(user, \
  111. (const char*)base, (const char*)pos, len, &obj) < 0) { goto _failed; } \
  112. goto _push
  113. #define again_fixed_trail(_cs, trail_len) \
  114. trail = trail_len; \
  115. cs = _cs; \
  116. goto _fixed_trail_again
  117. #define again_fixed_trail_if_zero(_cs, trail_len, ifzero) \
  118. trail = trail_len; \
  119. if(trail == 0) { goto ifzero; } \
  120. cs = _cs; \
  121. goto _fixed_trail_again
  122. #define start_container(func, count_, ct_) \
  123. if(top >= MSGPACK_EMBED_STACK_SIZE) { goto _failed; } /* FIXME */ \
  124. if(construct_cb(func)(user, count_, &stack[top].obj) < 0) { goto _failed; } \
  125. if((count_) == 0) { obj = stack[top].obj; \
  126. if (construct_cb(func##_end)(user, &obj) < 0) { goto _failed; } \
  127. goto _push; } \
  128. stack[top].ct = ct_; \
  129. stack[top].size = count_; \
  130. stack[top].count = 0; \
  131. ++top; \
  132. /*printf("container %d count %d stack %d\n",stack[top].obj,count_,top);*/ \
  133. /*printf("stack push %d\n", top);*/ \
  134. /* FIXME \
  135. if(top >= stack_size) { \
  136. if(stack_size == MSGPACK_EMBED_STACK_SIZE) { \
  137. size_t csize = sizeof(msgpack_unpack_struct(_stack)) * MSGPACK_EMBED_STACK_SIZE; \
  138. size_t nsize = csize * 2; \
  139. msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)malloc(nsize); \
  140. if(tmp == NULL) { goto _failed; } \
  141. memcpy(tmp, ctx->stack, csize); \
  142. ctx->stack = stack = tmp; \
  143. ctx->stack_size = stack_size = MSGPACK_EMBED_STACK_SIZE * 2; \
  144. } else { \
  145. size_t nsize = sizeof(msgpack_unpack_struct(_stack)) * ctx->stack_size * 2; \
  146. msgpack_unpack_struct(_stack)* tmp = (msgpack_unpack_struct(_stack)*)realloc(ctx->stack, nsize); \
  147. if(tmp == NULL) { goto _failed; } \
  148. ctx->stack = stack = tmp; \
  149. ctx->stack_size = stack_size = stack_size * 2; \
  150. } \
  151. } \
  152. */ \
  153. goto _header_again
  154. #define NEXT_CS(p) \
  155. ((unsigned int)*p & 0x1f)
  156. #ifdef USE_CASE_RANGE
  157. #define SWITCH_RANGE_BEGIN switch(*p) {
  158. #define SWITCH_RANGE(FROM, TO) case FROM ... TO:
  159. #define SWITCH_RANGE_DEFAULT default:
  160. #define SWITCH_RANGE_END }
  161. #else
  162. #define SWITCH_RANGE_BEGIN { if(0) {
  163. #define SWITCH_RANGE(FROM, TO) } else if(FROM <= *p && *p <= TO) {
  164. #define SWITCH_RANGE_DEFAULT } else {
  165. #define SWITCH_RANGE_END } }
  166. #endif
  167. if(p == pe) { goto _out; }
  168. do {
  169. switch(cs) {
  170. case CS_HEADER:
  171. SWITCH_RANGE_BEGIN
  172. SWITCH_RANGE(0x00, 0x7f) // Positive Fixnum
  173. push_fixed_value(_uint8, *(uint8_t*)p);
  174. SWITCH_RANGE(0xe0, 0xff) // Negative Fixnum
  175. push_fixed_value(_int8, *(int8_t*)p);
  176. SWITCH_RANGE(0xc0, 0xdf) // Variable
  177. switch(*p) {
  178. case 0xc0: // nil
  179. push_simple_value(_nil);
  180. //case 0xc1: // string
  181. // again_terminal_trail(NEXT_CS(p), p+1);
  182. case 0xc2: // false
  183. push_simple_value(_false);
  184. case 0xc3: // true
  185. push_simple_value(_true);
  186. //case 0xc4:
  187. //case 0xc5:
  188. //case 0xc6:
  189. //case 0xc7:
  190. //case 0xc8:
  191. //case 0xc9:
  192. case 0xca: // float
  193. case 0xcb: // double
  194. case 0xcc: // unsigned int 8
  195. case 0xcd: // unsigned int 16
  196. case 0xce: // unsigned int 32
  197. case 0xcf: // unsigned int 64
  198. case 0xd0: // signed int 8
  199. case 0xd1: // signed int 16
  200. case 0xd2: // signed int 32
  201. case 0xd3: // signed int 64
  202. again_fixed_trail(NEXT_CS(p), 1 << (((unsigned int)*p) & 0x03));
  203. //case 0xd4:
  204. //case 0xd5:
  205. //case 0xd6: // big integer 16
  206. //case 0xd7: // big integer 32
  207. //case 0xd8: // big float 16
  208. //case 0xd9: // big float 32
  209. case 0xda: // raw 16
  210. case 0xdb: // raw 32
  211. case 0xdc: // array 16
  212. case 0xdd: // array 32
  213. case 0xde: // map 16
  214. case 0xdf: // map 32
  215. again_fixed_trail(NEXT_CS(p), 2 << (((unsigned int)*p) & 0x01));
  216. default:
  217. goto _failed;
  218. }
  219. SWITCH_RANGE(0xa0, 0xbf) // FixRaw
  220. again_fixed_trail_if_zero(ACS_RAW_VALUE, ((unsigned int)*p & 0x1f), _raw_zero);
  221. SWITCH_RANGE(0x90, 0x9f) // FixArray
  222. start_container(_array, ((unsigned int)*p) & 0x0f, CT_ARRAY_ITEM);
  223. SWITCH_RANGE(0x80, 0x8f) // FixMap
  224. start_container(_map, ((unsigned int)*p) & 0x0f, CT_MAP_KEY);
  225. SWITCH_RANGE_DEFAULT
  226. goto _failed;
  227. SWITCH_RANGE_END
  228. // end CS_HEADER
  229. _fixed_trail_again:
  230. ++p;
  231. default:
  232. if((size_t)(pe - p) < trail) { goto _out; }
  233. n = p; p += trail - 1;
  234. switch(cs) {
  235. //case CS_
  236. //case CS_
  237. case CS_FLOAT: {
  238. union { uint32_t i; float f; } mem;
  239. mem.i = _msgpack_load32(uint32_t,n);
  240. push_fixed_value(_float, mem.f); }
  241. case CS_DOUBLE: {
  242. union { uint64_t i; double f; } mem;
  243. mem.i = _msgpack_load64(uint64_t,n);
  244. #if defined(__arm__) && !(__ARM_EABI__) // arm-oabi
  245. // https://github.com/msgpack/msgpack-perl/pull/1
  246. mem.i = (mem.i & 0xFFFFFFFFUL) << 32UL | (mem.i >> 32UL);
  247. #endif
  248. push_fixed_value(_double, mem.f); }
  249. case CS_UINT_8:
  250. push_fixed_value(_uint8, *(uint8_t*)n);
  251. case CS_UINT_16:
  252. push_fixed_value(_uint16, _msgpack_load16(uint16_t,n));
  253. case CS_UINT_32:
  254. push_fixed_value(_uint32, _msgpack_load32(uint32_t,n));
  255. case CS_UINT_64:
  256. push_fixed_value(_uint64, _msgpack_load64(uint64_t,n));
  257. case CS_INT_8:
  258. push_fixed_value(_int8, *(int8_t*)n);
  259. case CS_INT_16:
  260. push_fixed_value(_int16, _msgpack_load16(int16_t,n));
  261. case CS_INT_32:
  262. push_fixed_value(_int32, _msgpack_load32(int32_t,n));
  263. case CS_INT_64:
  264. push_fixed_value(_int64, _msgpack_load64(int64_t,n));
  265. //case CS_
  266. //case CS_
  267. //case CS_BIG_INT_16:
  268. // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load16(uint16_t,n), _big_int_zero);
  269. //case CS_BIG_INT_32:
  270. // again_fixed_trail_if_zero(ACS_BIG_INT_VALUE, _msgpack_load32(uint32_t,n), _big_int_zero);
  271. //case ACS_BIG_INT_VALUE:
  272. //_big_int_zero:
  273. // // FIXME
  274. // push_variable_value(_big_int, data, n, trail);
  275. //case CS_BIG_FLOAT_16:
  276. // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load16(uint16_t,n), _big_float_zero);
  277. //case CS_BIG_FLOAT_32:
  278. // again_fixed_trail_if_zero(ACS_BIG_FLOAT_VALUE, _msgpack_load32(uint32_t,n), _big_float_zero);
  279. //case ACS_BIG_FLOAT_VALUE:
  280. //_big_float_zero:
  281. // // FIXME
  282. // push_variable_value(_big_float, data, n, trail);
  283. case CS_RAW_16:
  284. again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load16(uint16_t,n), _raw_zero);
  285. case CS_RAW_32:
  286. again_fixed_trail_if_zero(ACS_RAW_VALUE, _msgpack_load32(uint32_t,n), _raw_zero);
  287. case ACS_RAW_VALUE:
  288. _raw_zero:
  289. push_variable_value(_raw, data, n, trail);
  290. case CS_ARRAY_16:
  291. start_container(_array, _msgpack_load16(uint16_t,n), CT_ARRAY_ITEM);
  292. case CS_ARRAY_32:
  293. /* FIXME security guard */
  294. start_container(_array, _msgpack_load32(uint32_t,n), CT_ARRAY_ITEM);
  295. case CS_MAP_16:
  296. start_container(_map, _msgpack_load16(uint16_t,n), CT_MAP_KEY);
  297. case CS_MAP_32:
  298. /* FIXME security guard */
  299. start_container(_map, _msgpack_load32(uint32_t,n), CT_MAP_KEY);
  300. default:
  301. goto _failed;
  302. }
  303. }
  304. _push:
  305. if(top == 0) { goto _finish; }
  306. c = &stack[top-1];
  307. switch(c->ct) {
  308. case CT_ARRAY_ITEM:
  309. if(construct_cb(_array_item)(user, c->count, &c->obj, obj) < 0) { goto _failed; }
  310. if(++c->count == c->size) {
  311. obj = c->obj;
  312. if (construct_cb(_array_end)(user, &obj) < 0) { goto _failed; }
  313. --top;
  314. /*printf("stack pop %d\n", top);*/
  315. goto _push;
  316. }
  317. goto _header_again;
  318. case CT_MAP_KEY:
  319. c->map_key = obj;
  320. c->ct = CT_MAP_VALUE;
  321. goto _header_again;
  322. case CT_MAP_VALUE:
  323. if(construct_cb(_map_item)(user, c->count, &c->obj, c->map_key, obj) < 0) { goto _failed; }
  324. if(++c->count == c->size) {
  325. obj = c->obj;
  326. if (construct_cb(_map_end)(user, &obj) < 0) { goto _failed; }
  327. --top;
  328. /*printf("stack pop %d\n", top);*/
  329. goto _push;
  330. }
  331. c->ct = CT_MAP_KEY;
  332. goto _header_again;
  333. default:
  334. goto _failed;
  335. }
  336. _header_again:
  337. cs = CS_HEADER;
  338. ++p;
  339. } while(p != pe);
  340. goto _out;
  341. _finish:
  342. if (!construct)
  343. msgpack_unpack_callback(_nil)(user, &obj);
  344. stack[0].obj = obj;
  345. ++p;
  346. ret = 1;
  347. /*printf("-- finish --\n"); */
  348. goto _end;
  349. _failed:
  350. /*printf("** FAILED **\n"); */
  351. ret = -1;
  352. goto _end;
  353. _out:
  354. ret = 0;
  355. goto _end;
  356. _end:
  357. ctx->cs = cs;
  358. ctx->trail = trail;
  359. ctx->top = top;
  360. *off = p - (const unsigned char*)data;
  361. return ret;
  362. #undef construct_cb
  363. }
  364. #undef SWITCH_RANGE_BEGIN
  365. #undef SWITCH_RANGE
  366. #undef SWITCH_RANGE_DEFAULT
  367. #undef SWITCH_RANGE_END
  368. #undef push_simple_value
  369. #undef push_fixed_value
  370. #undef push_variable_value
  371. #undef again_fixed_trail
  372. #undef again_fixed_trail_if_zero
  373. #undef start_container
  374. template <unsigned int fixed_offset, unsigned int var_offset>
  375. msgpack_unpack_func(int, _container_header)(msgpack_unpack_struct(_context)* ctx, const char* data, size_t len, size_t* off)
  376. {
  377. assert(len >= *off);
  378. uint32_t size;
  379. const unsigned char *const p = (unsigned char*)data + *off;
  380. #define inc_offset(inc) \
  381. if (len - *off < inc) \
  382. return 0; \
  383. *off += inc;
  384. switch (*p) {
  385. case var_offset:
  386. inc_offset(3);
  387. size = _msgpack_load16(uint16_t, p + 1);
  388. break;
  389. case var_offset + 1:
  390. inc_offset(5);
  391. size = _msgpack_load32(uint32_t, p + 1);
  392. break;
  393. #ifdef USE_CASE_RANGE
  394. case fixed_offset + 0x0 ... fixed_offset + 0xf:
  395. #else
  396. case fixed_offset + 0x0:
  397. case fixed_offset + 0x1:
  398. case fixed_offset + 0x2:
  399. case fixed_offset + 0x3:
  400. case fixed_offset + 0x4:
  401. case fixed_offset + 0x5:
  402. case fixed_offset + 0x6:
  403. case fixed_offset + 0x7:
  404. case fixed_offset + 0x8:
  405. case fixed_offset + 0x9:
  406. case fixed_offset + 0xa:
  407. case fixed_offset + 0xb:
  408. case fixed_offset + 0xc:
  409. case fixed_offset + 0xd:
  410. case fixed_offset + 0xe:
  411. case fixed_offset + 0xf:
  412. #endif
  413. ++*off;
  414. size = ((unsigned int)*p) & 0x0f;
  415. break;
  416. default:
  417. PyErr_SetString(PyExc_ValueError, "Unexpected type header on stream");
  418. return -1;
  419. }
  420. msgpack_unpack_callback(_uint32)(&ctx->user, size, &ctx->stack[0].obj);
  421. return 1;
  422. }
  423. #undef SWITCH_RANGE_BEGIN
  424. #undef SWITCH_RANGE
  425. #undef SWITCH_RANGE_DEFAULT
  426. #undef SWITCH_RANGE_END
  427. static const execute_fn template_construct = &template_execute<true>;
  428. static const execute_fn template_skip = &template_execute<false>;
  429. static const execute_fn read_array_header = &template_container_header<0x90, 0xdc>;
  430. static const execute_fn read_map_header = &template_container_header<0x80, 0xde>;
  431. #undef msgpack_unpack_func
  432. #undef msgpack_unpack_callback
  433. #undef msgpack_unpack_struct
  434. #undef msgpack_unpack_object
  435. #undef msgpack_unpack_user
  436. #undef NEXT_CS
  437. /* vim: set ts=4 sw=4 noexpandtab */