unpack.h 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. /*
  2. * MessagePack for Python unpacking routine
  3. *
  4. * Copyright (C) 2009 Naoki INADA
  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. #define MSGPACK_EMBED_STACK_SIZE (1024)
  19. #include "unpack_define.h"
  20. typedef struct unpack_user {
  21. int use_list;
  22. PyObject *object_hook;
  23. bool has_pairs_hook;
  24. PyObject *list_hook;
  25. PyObject *ext_hook;
  26. const char *encoding;
  27. const char *unicode_errors;
  28. } unpack_user;
  29. typedef PyObject* msgpack_unpack_object;
  30. struct unpack_context;
  31. typedef struct unpack_context unpack_context;
  32. typedef int (*execute_fn)(unpack_context *ctx, const char* data, size_t len, size_t* off);
  33. static inline msgpack_unpack_object unpack_callback_root(unpack_user* u)
  34. {
  35. return NULL;
  36. }
  37. static inline int unpack_callback_uint16(unpack_user* u, uint16_t d, msgpack_unpack_object* o)
  38. {
  39. PyObject *p = PyInt_FromLong((long)d);
  40. if (!p)
  41. return -1;
  42. *o = p;
  43. return 0;
  44. }
  45. static inline int unpack_callback_uint8(unpack_user* u, uint8_t d, msgpack_unpack_object* o)
  46. {
  47. return unpack_callback_uint16(u, d, o);
  48. }
  49. static inline int unpack_callback_uint32(unpack_user* u, uint32_t d, msgpack_unpack_object* o)
  50. {
  51. PyObject *p;
  52. #if UINT32_MAX > LONG_MAX
  53. if (d > LONG_MAX) {
  54. p = PyLong_FromUnsignedLong((unsigned long)d);
  55. } else
  56. #endif
  57. {
  58. p = PyInt_FromLong((long)d);
  59. }
  60. if (!p)
  61. return -1;
  62. *o = p;
  63. return 0;
  64. }
  65. static inline int unpack_callback_uint64(unpack_user* u, uint64_t d, msgpack_unpack_object* o)
  66. {
  67. PyObject *p;
  68. if (d > LONG_MAX) {
  69. p = PyLong_FromUnsignedLongLong((unsigned PY_LONG_LONG)d);
  70. } else {
  71. p = PyInt_FromLong((long)d);
  72. }
  73. if (!p)
  74. return -1;
  75. *o = p;
  76. return 0;
  77. }
  78. static inline int unpack_callback_int32(unpack_user* u, int32_t d, msgpack_unpack_object* o)
  79. {
  80. PyObject *p = PyInt_FromLong(d);
  81. if (!p)
  82. return -1;
  83. *o = p;
  84. return 0;
  85. }
  86. static inline int unpack_callback_int16(unpack_user* u, int16_t d, msgpack_unpack_object* o)
  87. {
  88. return unpack_callback_int32(u, d, o);
  89. }
  90. static inline int unpack_callback_int8(unpack_user* u, int8_t d, msgpack_unpack_object* o)
  91. {
  92. return unpack_callback_int32(u, d, o);
  93. }
  94. static inline int unpack_callback_int64(unpack_user* u, int64_t d, msgpack_unpack_object* o)
  95. {
  96. PyObject *p;
  97. if (d > LONG_MAX || d < LONG_MIN) {
  98. p = PyLong_FromLongLong((unsigned PY_LONG_LONG)d);
  99. } else {
  100. p = PyInt_FromLong((long)d);
  101. }
  102. *o = p;
  103. return 0;
  104. }
  105. static inline int unpack_callback_double(unpack_user* u, double d, msgpack_unpack_object* o)
  106. {
  107. PyObject *p = PyFloat_FromDouble(d);
  108. if (!p)
  109. return -1;
  110. *o = p;
  111. return 0;
  112. }
  113. static inline int unpack_callback_float(unpack_user* u, float d, msgpack_unpack_object* o)
  114. {
  115. return unpack_callback_double(u, d, o);
  116. }
  117. static inline int unpack_callback_nil(unpack_user* u, msgpack_unpack_object* o)
  118. { Py_INCREF(Py_None); *o = Py_None; return 0; }
  119. static inline int unpack_callback_true(unpack_user* u, msgpack_unpack_object* o)
  120. { Py_INCREF(Py_True); *o = Py_True; return 0; }
  121. static inline int unpack_callback_false(unpack_user* u, msgpack_unpack_object* o)
  122. { Py_INCREF(Py_False); *o = Py_False; return 0; }
  123. static inline int unpack_callback_array(unpack_user* u, unsigned int n, msgpack_unpack_object* o)
  124. {
  125. PyObject *p = u->use_list ? PyList_New(n) : PyTuple_New(n);
  126. if (!p)
  127. return -1;
  128. *o = p;
  129. return 0;
  130. }
  131. static inline int unpack_callback_array_item(unpack_user* u, unsigned int current, msgpack_unpack_object* c, msgpack_unpack_object o)
  132. {
  133. if (u->use_list)
  134. PyList_SET_ITEM(*c, current, o);
  135. else
  136. PyTuple_SET_ITEM(*c, current, o);
  137. return 0;
  138. }
  139. static inline int unpack_callback_array_end(unpack_user* u, msgpack_unpack_object* c)
  140. {
  141. if (u->list_hook) {
  142. PyObject *new_c = PyObject_CallFunctionObjArgs(u->list_hook, *c, NULL);
  143. if (!new_c)
  144. return -1;
  145. Py_DECREF(*c);
  146. *c = new_c;
  147. }
  148. return 0;
  149. }
  150. static inline int unpack_callback_map(unpack_user* u, unsigned int n, msgpack_unpack_object* o)
  151. {
  152. PyObject *p;
  153. if (u->has_pairs_hook) {
  154. p = PyList_New(n); // Or use tuple?
  155. }
  156. else {
  157. p = PyDict_New();
  158. }
  159. if (!p)
  160. return -1;
  161. *o = p;
  162. return 0;
  163. }
  164. static inline int unpack_callback_map_item(unpack_user* u, unsigned int current, msgpack_unpack_object* c, msgpack_unpack_object k, msgpack_unpack_object v)
  165. {
  166. if (u->has_pairs_hook) {
  167. msgpack_unpack_object item = PyTuple_Pack(2, k, v);
  168. if (!item)
  169. return -1;
  170. Py_DECREF(k);
  171. Py_DECREF(v);
  172. PyList_SET_ITEM(*c, current, item);
  173. return 0;
  174. }
  175. else if (PyDict_SetItem(*c, k, v) == 0) {
  176. Py_DECREF(k);
  177. Py_DECREF(v);
  178. return 0;
  179. }
  180. return -1;
  181. }
  182. static inline int unpack_callback_map_end(unpack_user* u, msgpack_unpack_object* c)
  183. {
  184. if (u->object_hook) {
  185. PyObject *new_c = PyObject_CallFunctionObjArgs(u->object_hook, *c, NULL);
  186. if (!new_c)
  187. return -1;
  188. Py_DECREF(*c);
  189. *c = new_c;
  190. }
  191. return 0;
  192. }
  193. static inline int unpack_callback_raw(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_unpack_object* o)
  194. {
  195. PyObject *py;
  196. if(u->encoding) {
  197. py = PyUnicode_Decode(p, l, u->encoding, u->unicode_errors);
  198. } else {
  199. py = PyBytes_FromStringAndSize(p, l);
  200. }
  201. if (!py)
  202. return -1;
  203. *o = py;
  204. return 0;
  205. }
  206. static inline int unpack_callback_bin(unpack_user* u, const char* b, const char* p, unsigned int l, msgpack_unpack_object* o)
  207. {
  208. PyObject *py = PyBytes_FromStringAndSize(p, l);
  209. if (!py)
  210. return -1;
  211. *o = py;
  212. return 0;
  213. }
  214. static inline int unpack_callback_ext(unpack_user* u, const char* base, const char* pos,
  215. unsigned int lenght, msgpack_unpack_object* o)
  216. {
  217. PyObject *py;
  218. int8_t typecode = (int8_t)*pos++;
  219. if (!u->ext_hook) {
  220. PyErr_SetString(PyExc_AssertionError, "u->ext_hook cannot be NULL");
  221. return -1;
  222. }
  223. // length also includes the typecode, so the actual data is lenght-1
  224. #if PY_MAJOR_VERSION == 2
  225. py = PyObject_CallFunction(u->ext_hook, "(is#)", typecode, pos, lenght-1);
  226. #else
  227. py = PyObject_CallFunction(u->ext_hook, "(iy#)", typecode, pos, lenght-1);
  228. #endif
  229. if (!py)
  230. return -1;
  231. *o = py;
  232. return 0;
  233. }
  234. #include "unpack_template.h"