+++ /dev/null
-/* enumerate object */\r
-\r
-#include "Python.h"\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- Py_ssize_t en_index; /* current index of enumeration */\r
- PyObject* en_sit; /* secondary iterator of enumeration */\r
- PyObject* en_result; /* result tuple */\r
- PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */\r
-} enumobject;\r
-\r
-static PyObject *\r
-enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- enumobject *en;\r
- PyObject *seq = NULL;\r
- PyObject *start = NULL;\r
- static char *kwlist[] = {"sequence", "start", 0};\r
-\r
- if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:enumerate", kwlist,\r
- &seq, &start))\r
- return NULL;\r
-\r
- en = (enumobject *)type->tp_alloc(type, 0);\r
- if (en == NULL)\r
- return NULL;\r
- if (start != NULL) {\r
- start = PyNumber_Index(start);\r
- if (start == NULL) {\r
- Py_DECREF(en);\r
- return NULL;\r
- }\r
- assert(PyInt_Check(start) || PyLong_Check(start));\r
- en->en_index = PyInt_AsSsize_t(start);\r
- if (en->en_index == -1 && PyErr_Occurred()) {\r
- PyErr_Clear();\r
- en->en_index = PY_SSIZE_T_MAX;\r
- en->en_longindex = start;\r
- } else {\r
- en->en_longindex = NULL;\r
- Py_DECREF(start);\r
- }\r
- } else {\r
- en->en_index = 0;\r
- en->en_longindex = NULL;\r
- }\r
- en->en_sit = PyObject_GetIter(seq);\r
- if (en->en_sit == NULL) {\r
- Py_DECREF(en);\r
- return NULL;\r
- }\r
- en->en_result = PyTuple_Pack(2, Py_None, Py_None);\r
- if (en->en_result == NULL) {\r
- Py_DECREF(en);\r
- return NULL;\r
- }\r
- return (PyObject *)en;\r
-}\r
-\r
-static void\r
-enum_dealloc(enumobject *en)\r
-{\r
- PyObject_GC_UnTrack(en);\r
- Py_XDECREF(en->en_sit);\r
- Py_XDECREF(en->en_result);\r
- Py_XDECREF(en->en_longindex);\r
- Py_TYPE(en)->tp_free(en);\r
-}\r
-\r
-static int\r
-enum_traverse(enumobject *en, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(en->en_sit);\r
- Py_VISIT(en->en_result);\r
- Py_VISIT(en->en_longindex);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-enum_next_long(enumobject *en, PyObject* next_item)\r
-{\r
- static PyObject *one = NULL;\r
- PyObject *result = en->en_result;\r
- PyObject *next_index;\r
- PyObject *stepped_up;\r
-\r
- if (en->en_longindex == NULL) {\r
- en->en_longindex = PyInt_FromSsize_t(PY_SSIZE_T_MAX);\r
- if (en->en_longindex == NULL)\r
- return NULL;\r
- }\r
- if (one == NULL) {\r
- one = PyInt_FromLong(1);\r
- if (one == NULL)\r
- return NULL;\r
- }\r
- next_index = en->en_longindex;\r
- assert(next_index != NULL);\r
- stepped_up = PyNumber_Add(next_index, one);\r
- if (stepped_up == NULL)\r
- return NULL;\r
- en->en_longindex = stepped_up;\r
-\r
- if (result->ob_refcnt == 1) {\r
- Py_INCREF(result);\r
- Py_DECREF(PyTuple_GET_ITEM(result, 0));\r
- Py_DECREF(PyTuple_GET_ITEM(result, 1));\r
- } else {\r
- result = PyTuple_New(2);\r
- if (result == NULL) {\r
- Py_DECREF(next_index);\r
- Py_DECREF(next_item);\r
- return NULL;\r
- }\r
- }\r
- PyTuple_SET_ITEM(result, 0, next_index);\r
- PyTuple_SET_ITEM(result, 1, next_item);\r
- return result;\r
-}\r
-\r
-static PyObject *\r
-enum_next(enumobject *en)\r
-{\r
- PyObject *next_index;\r
- PyObject *next_item;\r
- PyObject *result = en->en_result;\r
- PyObject *it = en->en_sit;\r
-\r
- next_item = (*Py_TYPE(it)->tp_iternext)(it);\r
- if (next_item == NULL)\r
- return NULL;\r
-\r
- if (en->en_index == PY_SSIZE_T_MAX)\r
- return enum_next_long(en, next_item);\r
-\r
- next_index = PyInt_FromSsize_t(en->en_index);\r
- if (next_index == NULL) {\r
- Py_DECREF(next_item);\r
- return NULL;\r
- }\r
- en->en_index++;\r
-\r
- if (result->ob_refcnt == 1) {\r
- Py_INCREF(result);\r
- Py_DECREF(PyTuple_GET_ITEM(result, 0));\r
- Py_DECREF(PyTuple_GET_ITEM(result, 1));\r
- } else {\r
- result = PyTuple_New(2);\r
- if (result == NULL) {\r
- Py_DECREF(next_index);\r
- Py_DECREF(next_item);\r
- return NULL;\r
- }\r
- }\r
- PyTuple_SET_ITEM(result, 0, next_index);\r
- PyTuple_SET_ITEM(result, 1, next_item);\r
- return result;\r
-}\r
-\r
-PyDoc_STRVAR(enum_doc,\r
-"enumerate(iterable[, start]) -> iterator for index, value of iterable\n"\r
-"\n"\r
-"Return an enumerate object. iterable must be another object that supports\n"\r
-"iteration. The enumerate object yields pairs containing a count (from\n"\r
-"start, which defaults to zero) and a value yielded by the iterable argument.\n"\r
-"enumerate is useful for obtaining an indexed list:\n"\r
-" (0, seq[0]), (1, seq[1]), (2, seq[2]), ...");\r
-\r
-PyTypeObject PyEnum_Type = {\r
- PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
- "enumerate", /* tp_name */\r
- sizeof(enumobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)enum_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- enum_doc, /* tp_doc */\r
- (traverseproc)enum_traverse, /* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)enum_next, /* tp_iternext */\r
- 0, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- PyType_GenericAlloc, /* tp_alloc */\r
- enum_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r
-\r
-/* Reversed Object ***************************************************************/\r
-\r
-typedef struct {\r
- PyObject_HEAD\r
- Py_ssize_t index;\r
- PyObject* seq;\r
-} reversedobject;\r
-\r
-static PyObject *\r
-reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds)\r
-{\r
- Py_ssize_t n;\r
- PyObject *seq, *reversed_meth;\r
- static PyObject *reversed_cache = NULL;\r
- reversedobject *ro;\r
-\r
- if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds))\r
- return NULL;\r
-\r
- if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) )\r
- return NULL;\r
-\r
- if (PyInstance_Check(seq)) {\r
- reversed_meth = PyObject_GetAttrString(seq, "__reversed__");\r
- if (reversed_meth == NULL) {\r
- if (PyErr_ExceptionMatches(PyExc_AttributeError))\r
- PyErr_Clear();\r
- else\r
- return NULL;\r
- }\r
- }\r
- else {\r
- reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__",\r
- &reversed_cache);\r
- if (reversed_meth == NULL && PyErr_Occurred())\r
- return NULL;\r
- }\r
- if (reversed_meth != NULL) {\r
- PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL);\r
- Py_DECREF(reversed_meth);\r
- return res;\r
- }\r
-\r
- if (!PySequence_Check(seq)) {\r
- PyErr_SetString(PyExc_TypeError,\r
- "argument to reversed() must be a sequence");\r
- return NULL;\r
- }\r
-\r
- n = PySequence_Size(seq);\r
- if (n == -1)\r
- return NULL;\r
-\r
- ro = (reversedobject *)type->tp_alloc(type, 0);\r
- if (ro == NULL)\r
- return NULL;\r
-\r
- ro->index = n-1;\r
- Py_INCREF(seq);\r
- ro->seq = seq;\r
- return (PyObject *)ro;\r
-}\r
-\r
-static void\r
-reversed_dealloc(reversedobject *ro)\r
-{\r
- PyObject_GC_UnTrack(ro);\r
- Py_XDECREF(ro->seq);\r
- Py_TYPE(ro)->tp_free(ro);\r
-}\r
-\r
-static int\r
-reversed_traverse(reversedobject *ro, visitproc visit, void *arg)\r
-{\r
- Py_VISIT(ro->seq);\r
- return 0;\r
-}\r
-\r
-static PyObject *\r
-reversed_next(reversedobject *ro)\r
-{\r
- PyObject *item;\r
- Py_ssize_t index = ro->index;\r
-\r
- if (index >= 0) {\r
- item = PySequence_GetItem(ro->seq, index);\r
- if (item != NULL) {\r
- ro->index--;\r
- return item;\r
- }\r
- if (PyErr_ExceptionMatches(PyExc_IndexError) ||\r
- PyErr_ExceptionMatches(PyExc_StopIteration))\r
- PyErr_Clear();\r
- }\r
- ro->index = -1;\r
- Py_CLEAR(ro->seq);\r
- return NULL;\r
-}\r
-\r
-PyDoc_STRVAR(reversed_doc,\r
-"reversed(sequence) -> reverse iterator over values of the sequence\n"\r
-"\n"\r
-"Return a reverse iterator");\r
-\r
-static PyObject *\r
-reversed_len(reversedobject *ro)\r
-{\r
- Py_ssize_t position, seqsize;\r
-\r
- if (ro->seq == NULL)\r
- return PyInt_FromLong(0);\r
- seqsize = PySequence_Size(ro->seq);\r
- if (seqsize == -1)\r
- return NULL;\r
- position = ro->index + 1;\r
- return PyInt_FromSsize_t((seqsize < position) ? 0 : position);\r
-}\r
-\r
-PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it)).");\r
-\r
-static PyMethodDef reversediter_methods[] = {\r
- {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc},\r
- {NULL, NULL} /* sentinel */\r
-};\r
-\r
-PyTypeObject PyReversed_Type = {\r
- PyVarObject_HEAD_INIT(&PyType_Type, 0)\r
- "reversed", /* tp_name */\r
- sizeof(reversedobject), /* tp_basicsize */\r
- 0, /* tp_itemsize */\r
- /* methods */\r
- (destructor)reversed_dealloc, /* tp_dealloc */\r
- 0, /* tp_print */\r
- 0, /* tp_getattr */\r
- 0, /* tp_setattr */\r
- 0, /* tp_compare */\r
- 0, /* tp_repr */\r
- 0, /* tp_as_number */\r
- 0, /* tp_as_sequence */\r
- 0, /* tp_as_mapping */\r
- 0, /* tp_hash */\r
- 0, /* tp_call */\r
- 0, /* tp_str */\r
- PyObject_GenericGetAttr, /* tp_getattro */\r
- 0, /* tp_setattro */\r
- 0, /* tp_as_buffer */\r
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |\r
- Py_TPFLAGS_BASETYPE, /* tp_flags */\r
- reversed_doc, /* tp_doc */\r
- (traverseproc)reversed_traverse,/* tp_traverse */\r
- 0, /* tp_clear */\r
- 0, /* tp_richcompare */\r
- 0, /* tp_weaklistoffset */\r
- PyObject_SelfIter, /* tp_iter */\r
- (iternextfunc)reversed_next, /* tp_iternext */\r
- reversediter_methods, /* tp_methods */\r
- 0, /* tp_members */\r
- 0, /* tp_getset */\r
- 0, /* tp_base */\r
- 0, /* tp_dict */\r
- 0, /* tp_descr_get */\r
- 0, /* tp_descr_set */\r
- 0, /* tp_dictoffset */\r
- 0, /* tp_init */\r
- PyType_GenericAlloc, /* tp_alloc */\r
- reversed_new, /* tp_new */\r
- PyObject_GC_Del, /* tp_free */\r
-};\r