|
|
- #include "_pair_list.h"
-
- #include <Python.h>
-
- // fix for VisualC complier used by Python 3.4
- #ifdef __GNUC__
- #define INLINE inline
- #else
- #define INLINE
- #endif
-
- static PyTypeObject multidict_items_iter_type;
- static PyTypeObject multidict_values_iter_type;
- static PyTypeObject multidict_keys_iter_type;
-
- typedef struct multidict_iter {
- PyObject_HEAD
- PyObject *impl;
- Py_ssize_t current;
- uint64_t version;
- } MultidictIter;
-
- static INLINE void
- _init_iter(MultidictIter *it, PyObject *impl)
- {
- Py_INCREF(impl);
-
- it->impl = impl;
- it->current = 0;
- it->version = pair_list_version(impl);
- }
-
- PyObject *
- multidict_items_iter_new(PyObject *impl)
- {
- MultidictIter *it = PyObject_GC_New(
- MultidictIter, &multidict_items_iter_type);
- if (it == NULL) {
- return NULL;
- }
-
- _init_iter(it, impl);
-
- return (PyObject *)it;
- }
-
- PyObject *
- multidict_keys_iter_new(PyObject *impl)
- {
- MultidictIter *it = PyObject_GC_New(
- MultidictIter, &multidict_keys_iter_type);
- if (it == NULL) {
- return NULL;
- }
-
- _init_iter(it, impl);
-
- return (PyObject *)it;
- }
-
- PyObject *
- multidict_values_iter_new(PyObject *impl)
- {
- MultidictIter *it = PyObject_GC_New(
- MultidictIter, &multidict_values_iter_type);
- if (it == NULL) {
- return NULL;
- }
-
- _init_iter(it, impl);
-
- return (PyObject *)it;
- }
-
- static PyObject *
- multidict_items_iter_iternext(MultidictIter *self)
- {
- PyObject *key = NULL;
- PyObject *value = NULL;
- PyObject *ret = NULL;
-
- if (self->version != pair_list_version(self->impl)) {
- PyErr_SetString(PyExc_RuntimeError, "Dictionary changed during iteration");
- return NULL;
- }
-
- if (!_pair_list_next(self->impl, &self->current, NULL, &key, &value, NULL)) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
-
- ret = PyTuple_Pack(2, key, value);
- if (ret == NULL) {
- return NULL;
- }
-
- return ret;
- }
-
- static PyObject *
- multidict_values_iter_iternext(MultidictIter *self)
- {
- PyObject *value = NULL;
-
- if (self->version != pair_list_version(self->impl)) {
- PyErr_SetString(PyExc_RuntimeError, "Dictionary changed during iteration");
- return NULL;
- }
-
- if (!pair_list_next(self->impl, &self->current, NULL, NULL, &value)) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
-
- Py_INCREF(value);
-
- return value;
- }
-
- static PyObject *
- multidict_keys_iter_iternext(MultidictIter *self)
- {
- PyObject *key = NULL;
-
- if (self->version != pair_list_version(self->impl)) {
- PyErr_SetString(PyExc_RuntimeError, "Dictionary changed during iteration");
- return NULL;
- }
-
- if (!pair_list_next(self->impl, &self->current, NULL, &key, NULL)) {
- PyErr_SetNone(PyExc_StopIteration);
- return NULL;
- }
-
- Py_INCREF(key);
-
- return key;
- }
-
- static void
- multidict_iter_dealloc(MultidictIter *self)
- {
- PyObject_GC_UnTrack(self);
- Py_XDECREF(self->impl);
- PyObject_GC_Del(self);
- }
-
- static int
- multidict_iter_traverse(MultidictIter *self, visitproc visit, void *arg)
- {
- Py_VISIT(self->impl);
- return 0;
- }
-
- static int
- multidict_iter_clear(MultidictIter *self)
- {
- Py_CLEAR(self->impl);
- return 0;
- }
-
- /***********************************************************************/
-
- /* We link this module statically for convenience. If compiled as a shared
- library instead, some compilers don't allow addresses of Python objects
- defined in other libraries to be used in static initializers here. The
- DEFERRED_ADDRESS macro is used to tag the slots where such addresses
- appear; the module init function must fill in the tagged slots at runtime.
- The argument is for documentation -- the macro ignores it.
- */
- #define DEFERRED_ADDRESS(ADDR) 0
-
- static PyTypeObject multidict_items_iter_type = {
- PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
- "multidict._multidict_iter._itemsiter", /* tp_name */
- sizeof(MultidictIter), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)multidict_iter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)multidict_iter_traverse, /* tp_traverse */
- (inquiry)multidict_iter_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)multidict_items_iter_iternext, /* tp_iternext */
- };
-
- static PyTypeObject multidict_values_iter_type = {
- PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
- "multidict._multidict_iter._valuesiter", /* tp_name */
- sizeof(MultidictIter), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)multidict_iter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)multidict_iter_traverse, /* tp_traverse */
- (inquiry)multidict_iter_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)multidict_values_iter_iternext, /* tp_iternext */
- };
-
- static PyTypeObject multidict_keys_iter_type = {
- PyVarObject_HEAD_INIT(DEFERRED_ADDRESS(&PyType_Type), 0)
- "multidict._multidict_iter._keysiter", /* tp_name */
- sizeof(MultidictIter), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)multidict_iter_dealloc, /* tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- 0, /* tp_reserved */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- 0, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- 0, /* tp_doc */
- (traverseproc)multidict_iter_traverse, /* tp_traverse */
- (inquiry)multidict_iter_clear, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)multidict_keys_iter_iternext, /* tp_iternext */
- };
-
- int
- multidict_iter_init()
- {
- if (PyType_Ready(&multidict_items_iter_type) < 0 ||
- PyType_Ready(&multidict_values_iter_type) < 0 ||
- PyType_Ready(&multidict_keys_iter_type) < 0) {
- return -1;
- }
- return 0;
- }
|