views.h 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. #ifndef _MULTIDICT_VIEWS_H
  2. #define _MULTIDICT_VIEWS_H
  3. #ifdef __cplusplus
  4. extern "C" {
  5. #endif
  6. static PyTypeObject multidict_itemsview_type;
  7. static PyTypeObject multidict_valuesview_type;
  8. static PyTypeObject multidict_keysview_type;
  9. static PyObject *viewbaseset_richcmp_func;
  10. static PyObject *viewbaseset_and_func;
  11. static PyObject *viewbaseset_or_func;
  12. static PyObject *viewbaseset_sub_func;
  13. static PyObject *viewbaseset_xor_func;
  14. static PyObject *abc_itemsview_register_func;
  15. static PyObject *abc_keysview_register_func;
  16. static PyObject *abc_valuesview_register_func;
  17. static PyObject *itemsview_isdisjoint_func;
  18. static PyObject *itemsview_repr_func;
  19. static PyObject *keysview_repr_func;
  20. static PyObject *keysview_isdisjoint_func;
  21. static PyObject *valuesview_repr_func;
  22. typedef struct {
  23. PyObject_HEAD
  24. PyObject *md;
  25. } _Multidict_ViewObject;
  26. /********** Base **********/
  27. static inline void
  28. _init_view(_Multidict_ViewObject *self, PyObject *md)
  29. {
  30. Py_INCREF(md);
  31. self->md = md;
  32. }
  33. static inline void
  34. multidict_view_dealloc(_Multidict_ViewObject *self)
  35. {
  36. PyObject_GC_UnTrack(self);
  37. Py_XDECREF(self->md);
  38. PyObject_GC_Del(self);
  39. }
  40. static inline int
  41. multidict_view_traverse(_Multidict_ViewObject *self, visitproc visit, void *arg)
  42. {
  43. Py_VISIT(self->md);
  44. return 0;
  45. }
  46. static inline int
  47. multidict_view_clear(_Multidict_ViewObject *self)
  48. {
  49. Py_CLEAR(self->md);
  50. return 0;
  51. }
  52. static inline Py_ssize_t
  53. multidict_view_len(_Multidict_ViewObject *self)
  54. {
  55. return pair_list_len(&((MultiDictObject*)self->md)->pairs);
  56. }
  57. static inline PyObject *
  58. multidict_view_richcompare(PyObject *self, PyObject *other, int op)
  59. {
  60. PyObject *ret;
  61. PyObject *op_obj = PyLong_FromLong(op);
  62. if (op_obj == NULL) {
  63. return NULL;
  64. }
  65. ret = PyObject_CallFunctionObjArgs(
  66. viewbaseset_richcmp_func, self, other, op_obj, NULL);
  67. Py_DECREF(op_obj);
  68. return ret;
  69. }
  70. static inline PyObject *
  71. multidict_view_and(PyObject *self, PyObject *other)
  72. {
  73. return PyObject_CallFunctionObjArgs(
  74. viewbaseset_and_func, self, other, NULL);
  75. }
  76. static inline PyObject *
  77. multidict_view_or(PyObject *self, PyObject *other)
  78. {
  79. return PyObject_CallFunctionObjArgs(
  80. viewbaseset_or_func, self, other, NULL);
  81. }
  82. static inline PyObject *
  83. multidict_view_sub(PyObject *self, PyObject *other)
  84. {
  85. return PyObject_CallFunctionObjArgs(
  86. viewbaseset_sub_func, self, other, NULL);
  87. }
  88. static inline PyObject *
  89. multidict_view_xor(PyObject *self, PyObject *other)
  90. {
  91. return PyObject_CallFunctionObjArgs(
  92. viewbaseset_xor_func, self, other, NULL);
  93. }
  94. static PyNumberMethods multidict_view_as_number = {
  95. .nb_subtract = (binaryfunc)multidict_view_sub,
  96. .nb_and = (binaryfunc)multidict_view_and,
  97. .nb_xor = (binaryfunc)multidict_view_xor,
  98. .nb_or = (binaryfunc)multidict_view_or,
  99. };
  100. /********** Items **********/
  101. static inline PyObject *
  102. multidict_itemsview_new(PyObject *md)
  103. {
  104. _Multidict_ViewObject *mv = PyObject_GC_New(
  105. _Multidict_ViewObject, &multidict_itemsview_type);
  106. if (mv == NULL) {
  107. return NULL;
  108. }
  109. _init_view(mv, md);
  110. PyObject_GC_Track(mv);
  111. return (PyObject *)mv;
  112. }
  113. static inline PyObject *
  114. multidict_itemsview_iter(_Multidict_ViewObject *self)
  115. {
  116. return multidict_items_iter_new((MultiDictObject*)self->md);
  117. }
  118. static inline PyObject *
  119. multidict_itemsview_repr(_Multidict_ViewObject *self)
  120. {
  121. return PyObject_CallFunctionObjArgs(
  122. itemsview_repr_func, self, NULL);
  123. }
  124. static inline PyObject *
  125. multidict_itemsview_isdisjoint(_Multidict_ViewObject *self, PyObject *other)
  126. {
  127. return PyObject_CallFunctionObjArgs(
  128. itemsview_isdisjoint_func, self, other, NULL);
  129. }
  130. PyDoc_STRVAR(itemsview_isdisjoint_doc,
  131. "Return True if two sets have a null intersection.");
  132. static PyMethodDef multidict_itemsview_methods[] = {
  133. {
  134. "isdisjoint",
  135. (PyCFunction)multidict_itemsview_isdisjoint,
  136. METH_O,
  137. itemsview_isdisjoint_doc
  138. },
  139. {
  140. NULL,
  141. NULL
  142. } /* sentinel */
  143. };
  144. static inline int
  145. multidict_itemsview_contains(_Multidict_ViewObject *self, PyObject *obj)
  146. {
  147. PyObject *akey = NULL,
  148. *aval = NULL,
  149. *bkey = NULL,
  150. *bval = NULL,
  151. *iter = NULL,
  152. *item = NULL;
  153. int ret1, ret2;
  154. if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 2) {
  155. return 0;
  156. }
  157. bkey = PyTuple_GET_ITEM(obj, 0);
  158. bval = PyTuple_GET_ITEM(obj, 1);
  159. iter = multidict_itemsview_iter(self);
  160. if (iter == NULL) {
  161. return 0;
  162. }
  163. while ((item = PyIter_Next(iter)) != NULL) {
  164. akey = PyTuple_GET_ITEM(item, 0);
  165. aval = PyTuple_GET_ITEM(item, 1);
  166. ret1 = PyObject_RichCompareBool(akey, bkey, Py_EQ);
  167. if (ret1 < 0) {
  168. Py_DECREF(iter);
  169. Py_DECREF(item);
  170. return -1;
  171. }
  172. ret2 = PyObject_RichCompareBool(aval, bval, Py_EQ);
  173. if (ret2 < 0) {
  174. Py_DECREF(iter);
  175. Py_DECREF(item);
  176. return -1;
  177. }
  178. if (ret1 > 0 && ret2 > 0)
  179. {
  180. Py_DECREF(iter);
  181. Py_DECREF(item);
  182. return 1;
  183. }
  184. Py_DECREF(item);
  185. }
  186. Py_DECREF(iter);
  187. if (PyErr_Occurred()) {
  188. return -1;
  189. }
  190. return 0;
  191. }
  192. static PySequenceMethods multidict_itemsview_as_sequence = {
  193. .sq_length = (lenfunc)multidict_view_len,
  194. .sq_contains = (objobjproc)multidict_itemsview_contains,
  195. };
  196. static PyTypeObject multidict_itemsview_type = {
  197. PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
  198. "multidict._multidict._ItemsView", /* tp_name */
  199. sizeof(_Multidict_ViewObject), /* tp_basicsize */
  200. .tp_dealloc = (destructor)multidict_view_dealloc,
  201. .tp_repr = (reprfunc)multidict_itemsview_repr,
  202. .tp_as_number = &multidict_view_as_number,
  203. .tp_as_sequence = &multidict_itemsview_as_sequence,
  204. .tp_getattro = PyObject_GenericGetAttr,
  205. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  206. .tp_traverse = (traverseproc)multidict_view_traverse,
  207. .tp_clear = (inquiry)multidict_view_clear,
  208. .tp_richcompare = multidict_view_richcompare,
  209. .tp_iter = (getiterfunc)multidict_itemsview_iter,
  210. .tp_methods = multidict_itemsview_methods,
  211. };
  212. /********** Keys **********/
  213. static inline PyObject *
  214. multidict_keysview_new(PyObject *md)
  215. {
  216. _Multidict_ViewObject *mv = PyObject_GC_New(
  217. _Multidict_ViewObject, &multidict_keysview_type);
  218. if (mv == NULL) {
  219. return NULL;
  220. }
  221. _init_view(mv, md);
  222. PyObject_GC_Track(mv);
  223. return (PyObject *)mv;
  224. }
  225. static inline PyObject *
  226. multidict_keysview_iter(_Multidict_ViewObject *self)
  227. {
  228. return multidict_keys_iter_new(((MultiDictObject*)self->md));
  229. }
  230. static inline PyObject *
  231. multidict_keysview_repr(_Multidict_ViewObject *self)
  232. {
  233. return PyObject_CallFunctionObjArgs(
  234. keysview_repr_func, self, NULL);
  235. }
  236. static inline PyObject *
  237. multidict_keysview_isdisjoint(_Multidict_ViewObject *self, PyObject *other)
  238. {
  239. return PyObject_CallFunctionObjArgs(
  240. keysview_isdisjoint_func, self, other, NULL);
  241. }
  242. PyDoc_STRVAR(keysview_isdisjoint_doc,
  243. "Return True if two sets have a null intersection.");
  244. static PyMethodDef multidict_keysview_methods[] = {
  245. {
  246. "isdisjoint",
  247. (PyCFunction)multidict_keysview_isdisjoint,
  248. METH_O,
  249. keysview_isdisjoint_doc
  250. },
  251. {
  252. NULL,
  253. NULL
  254. } /* sentinel */
  255. };
  256. static inline int
  257. multidict_keysview_contains(_Multidict_ViewObject *self, PyObject *key)
  258. {
  259. return pair_list_contains(&((MultiDictObject*)self->md)->pairs, key);
  260. }
  261. static PySequenceMethods multidict_keysview_as_sequence = {
  262. .sq_length = (lenfunc)multidict_view_len,
  263. .sq_contains = (objobjproc)multidict_keysview_contains,
  264. };
  265. static PyTypeObject multidict_keysview_type = {
  266. PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
  267. "multidict._multidict._KeysView", /* tp_name */
  268. sizeof(_Multidict_ViewObject), /* tp_basicsize */
  269. .tp_dealloc = (destructor)multidict_view_dealloc,
  270. .tp_repr = (reprfunc)multidict_keysview_repr,
  271. .tp_as_number = &multidict_view_as_number,
  272. .tp_as_sequence = &multidict_keysview_as_sequence,
  273. .tp_getattro = PyObject_GenericGetAttr,
  274. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  275. .tp_traverse = (traverseproc)multidict_view_traverse,
  276. .tp_clear = (inquiry)multidict_view_clear,
  277. .tp_richcompare = multidict_view_richcompare,
  278. .tp_iter = (getiterfunc)multidict_keysview_iter,
  279. .tp_methods = multidict_keysview_methods,
  280. };
  281. /********** Values **********/
  282. static inline PyObject *
  283. multidict_valuesview_new(PyObject *md)
  284. {
  285. _Multidict_ViewObject *mv = PyObject_GC_New(
  286. _Multidict_ViewObject, &multidict_valuesview_type);
  287. if (mv == NULL) {
  288. return NULL;
  289. }
  290. _init_view(mv, md);
  291. PyObject_GC_Track(mv);
  292. return (PyObject *)mv;
  293. }
  294. static inline PyObject *
  295. multidict_valuesview_iter(_Multidict_ViewObject *self)
  296. {
  297. return multidict_values_iter_new(((MultiDictObject*)self->md));
  298. }
  299. static inline PyObject *
  300. multidict_valuesview_repr(_Multidict_ViewObject *self)
  301. {
  302. return PyObject_CallFunctionObjArgs(
  303. valuesview_repr_func, self, NULL);
  304. }
  305. static PySequenceMethods multidict_valuesview_as_sequence = {
  306. .sq_length = (lenfunc)multidict_view_len,
  307. };
  308. static PyTypeObject multidict_valuesview_type = {
  309. PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
  310. "multidict._multidict._ValuesView", /* tp_name */
  311. sizeof(_Multidict_ViewObject), /* tp_basicsize */
  312. .tp_dealloc = (destructor)multidict_view_dealloc,
  313. .tp_repr = (reprfunc)multidict_valuesview_repr,
  314. .tp_as_sequence = &multidict_valuesview_as_sequence,
  315. .tp_getattro = PyObject_GenericGetAttr,
  316. .tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC,
  317. .tp_traverse = (traverseproc)multidict_view_traverse,
  318. .tp_clear = (inquiry)multidict_view_clear,
  319. .tp_iter = (getiterfunc)multidict_valuesview_iter,
  320. };
  321. static inline int
  322. multidict_views_init()
  323. {
  324. PyObject *reg_func_call_result = NULL;
  325. PyObject *module = PyImport_ImportModule("multidict._multidict_base");
  326. if (module == NULL) {
  327. goto fail;
  328. }
  329. #define GET_MOD_ATTR(VAR, NAME) \
  330. VAR = PyObject_GetAttrString(module, NAME); \
  331. if (VAR == NULL) { \
  332. goto fail; \
  333. }
  334. GET_MOD_ATTR(viewbaseset_richcmp_func, "_viewbaseset_richcmp");
  335. GET_MOD_ATTR(viewbaseset_and_func, "_viewbaseset_and");
  336. GET_MOD_ATTR(viewbaseset_or_func, "_viewbaseset_or");
  337. GET_MOD_ATTR(viewbaseset_sub_func, "_viewbaseset_sub");
  338. GET_MOD_ATTR(viewbaseset_xor_func, "_viewbaseset_xor");
  339. GET_MOD_ATTR(abc_itemsview_register_func, "_abc_itemsview_register");
  340. GET_MOD_ATTR(abc_keysview_register_func, "_abc_keysview_register");
  341. GET_MOD_ATTR(abc_valuesview_register_func, "_abc_valuesview_register");
  342. GET_MOD_ATTR(itemsview_repr_func, "_itemsview_isdisjoint");
  343. GET_MOD_ATTR(itemsview_repr_func, "_itemsview_repr");
  344. GET_MOD_ATTR(keysview_repr_func, "_keysview_repr");
  345. GET_MOD_ATTR(keysview_isdisjoint_func, "_keysview_isdisjoint");
  346. GET_MOD_ATTR(valuesview_repr_func, "_valuesview_repr");
  347. if (PyType_Ready(&multidict_itemsview_type) < 0 ||
  348. PyType_Ready(&multidict_valuesview_type) < 0 ||
  349. PyType_Ready(&multidict_keysview_type) < 0)
  350. {
  351. goto fail;
  352. }
  353. // abc.ItemsView.register(_ItemsView)
  354. reg_func_call_result = PyObject_CallFunctionObjArgs(
  355. abc_itemsview_register_func, (PyObject*)&multidict_itemsview_type, NULL);
  356. if (reg_func_call_result == NULL) {
  357. goto fail;
  358. }
  359. Py_DECREF(reg_func_call_result);
  360. // abc.KeysView.register(_KeysView)
  361. reg_func_call_result = PyObject_CallFunctionObjArgs(
  362. abc_keysview_register_func, (PyObject*)&multidict_keysview_type, NULL);
  363. if (reg_func_call_result == NULL) {
  364. goto fail;
  365. }
  366. Py_DECREF(reg_func_call_result);
  367. // abc.ValuesView.register(_KeysView)
  368. reg_func_call_result = PyObject_CallFunctionObjArgs(
  369. abc_valuesview_register_func, (PyObject*)&multidict_valuesview_type, NULL);
  370. if (reg_func_call_result == NULL) {
  371. goto fail;
  372. }
  373. Py_DECREF(reg_func_call_result);
  374. Py_DECREF(module);
  375. return 0;
  376. fail:
  377. Py_CLEAR(module);
  378. return -1;
  379. #undef GET_MOD_ATTR
  380. }
  381. #ifdef __cplusplus
  382. }
  383. #endif
  384. #endif