diff options
Diffstat (limited to 'Objects/enumobject.c')
-rw-r--r-- | Objects/enumobject.c | 247 |
1 files changed, 94 insertions, 153 deletions
diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 4786297..73b656b 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -2,14 +2,6 @@ #include "Python.h" -#include "clinic/enumobject.c.h" - -/*[clinic input] -class enumerate "enumobject *" "&PyEnum_Type" -class reversed "reversedobject *" "&PyReversed_Type" -[clinic start generated code]*/ -/*[clinic end generated code: output=da39a3ee5e6b4b0d input=d2dfdf1a88c88975]*/ - typedef struct { PyObject_HEAD Py_ssize_t en_index; /* current index of enumeration */ @@ -18,29 +10,17 @@ typedef struct { PyObject* en_longindex; /* index for sequences >= PY_SSIZE_T_MAX */ } enumobject; - -/*[clinic input] -@classmethod -enumerate.__new__ as enum_new - - iterable: object - an object supporting iteration - start: object = 0 - -Return an enumerate object. - -The enumerate object yields pairs containing a count (from start, which -defaults to zero) and a value yielded by the iterable argument. - -enumerate is useful for obtaining an indexed list: - (0, seq[0]), (1, seq[1]), (2, seq[2]), ... -[clinic start generated code]*/ - static PyObject * -enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start) -/*[clinic end generated code: output=e95e6e439f812c10 input=782e4911efcb8acf]*/ +enum_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { enumobject *en; + PyObject *seq = NULL; + PyObject *start = NULL; + static char *kwlist[] = {"sequence", "start", 0}; + + if (!PyArg_ParseTupleAndKeywords(args, kwds, "O|O:enumerate", kwlist, + &seq, &start)) + return NULL; en = (enumobject *)type->tp_alloc(type, 0); if (en == NULL) @@ -51,8 +31,8 @@ enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start) Py_DECREF(en); return NULL; } - assert(PyLong_Check(start)); - en->en_index = PyLong_AsSsize_t(start); + assert(_PyAnyInt_Check(start)); + en->en_index = PyInt_AsSsize_t(start); if (en->en_index == -1 && PyErr_Occurred()) { PyErr_Clear(); en->en_index = PY_SSIZE_T_MAX; @@ -65,7 +45,7 @@ enum_new_impl(PyTypeObject *type, PyObject *iterable, PyObject *start) en->en_index = 0; en->en_longindex = NULL; } - en->en_sit = PyObject_GetIter(iterable); + en->en_sit = PyObject_GetIter(seq); if (en->en_sit == NULL) { Py_DECREF(en); return NULL; @@ -100,22 +80,28 @@ enum_traverse(enumobject *en, visitproc visit, void *arg) static PyObject * enum_next_long(enumobject *en, PyObject* next_item) { + static PyObject *one = NULL; PyObject *result = en->en_result; PyObject *next_index; PyObject *stepped_up; - PyObject *old_index; - PyObject *old_item; if (en->en_longindex == NULL) { - en->en_longindex = PyLong_FromSsize_t(PY_SSIZE_T_MAX); + en->en_longindex = PyInt_FromSsize_t(PY_SSIZE_T_MAX); if (en->en_longindex == NULL) { Py_DECREF(next_item); return NULL; } } + if (one == NULL) { + one = PyInt_FromLong(1); + if (one == NULL) { + Py_DECREF(next_item); + return NULL; + } + } next_index = en->en_longindex; assert(next_index != NULL); - stepped_up = PyNumber_Add(next_index, _PyLong_One); + stepped_up = PyNumber_Add(next_index, one); if (stepped_up == NULL) { Py_DECREF(next_item); return NULL; @@ -124,19 +110,15 @@ enum_next_long(enumobject *en, PyObject* next_item) if (result->ob_refcnt == 1) { Py_INCREF(result); - old_index = PyTuple_GET_ITEM(result, 0); - old_item = PyTuple_GET_ITEM(result, 1); - PyTuple_SET_ITEM(result, 0, next_index); - PyTuple_SET_ITEM(result, 1, next_item); - Py_DECREF(old_index); - Py_DECREF(old_item); - return result; - } - result = PyTuple_New(2); - if (result == NULL) { - Py_DECREF(next_index); - Py_DECREF(next_item); - return NULL; + Py_DECREF(PyTuple_GET_ITEM(result, 0)); + Py_DECREF(PyTuple_GET_ITEM(result, 1)); + } else { + result = PyTuple_New(2); + if (result == NULL) { + Py_DECREF(next_index); + Py_DECREF(next_item); + return NULL; + } } PyTuple_SET_ITEM(result, 0, next_index); PyTuple_SET_ITEM(result, 1, next_item); @@ -150,8 +132,6 @@ enum_next(enumobject *en) PyObject *next_item; PyObject *result = en->en_result; PyObject *it = en->en_sit; - PyObject *old_index; - PyObject *old_item; next_item = (*Py_TYPE(it)->tp_iternext)(it); if (next_item == NULL) @@ -160,7 +140,7 @@ enum_next(enumobject *en) if (en->en_index == PY_SSIZE_T_MAX) return enum_next_long(en, next_item); - next_index = PyLong_FromSsize_t(en->en_index); + next_index = PyInt_FromSsize_t(en->en_index); if (next_index == NULL) { Py_DECREF(next_item); return NULL; @@ -169,40 +149,29 @@ enum_next(enumobject *en) if (result->ob_refcnt == 1) { Py_INCREF(result); - old_index = PyTuple_GET_ITEM(result, 0); - old_item = PyTuple_GET_ITEM(result, 1); - PyTuple_SET_ITEM(result, 0, next_index); - PyTuple_SET_ITEM(result, 1, next_item); - Py_DECREF(old_index); - Py_DECREF(old_item); - return result; - } - result = PyTuple_New(2); - if (result == NULL) { - Py_DECREF(next_index); - Py_DECREF(next_item); - return NULL; + Py_DECREF(PyTuple_GET_ITEM(result, 0)); + Py_DECREF(PyTuple_GET_ITEM(result, 1)); + } else { + result = PyTuple_New(2); + if (result == NULL) { + Py_DECREF(next_index); + Py_DECREF(next_item); + return NULL; + } } PyTuple_SET_ITEM(result, 0, next_index); PyTuple_SET_ITEM(result, 1, next_item); return result; } -static PyObject * -enum_reduce(enumobject *en, PyObject *Py_UNUSED(ignored)) -{ - if (en->en_longindex != NULL) - return Py_BuildValue("O(OO)", Py_TYPE(en), en->en_sit, en->en_longindex); - else - return Py_BuildValue("O(On)", Py_TYPE(en), en->en_sit, en->en_index); -} - -PyDoc_STRVAR(reduce_doc, "Return state information for pickling."); - -static PyMethodDef enum_methods[] = { - {"__reduce__", (PyCFunction)enum_reduce, METH_NOARGS, reduce_doc}, - {NULL, NULL} /* sentinel */ -}; +PyDoc_STRVAR(enum_doc, +"enumerate(iterable[, start]) -> iterator for index, value of iterable\n" +"\n" +"Return an enumerate object. iterable must be another object that supports\n" +"iteration. The enumerate object yields pairs containing a count (from\n" +"start, which defaults to zero) and a value yielded by the iterable argument.\n" +"enumerate is useful for obtaining an indexed list:\n" +" (0, seq[0]), (1, seq[1]), (2, seq[2]), ..."); PyTypeObject PyEnum_Type = { PyVarObject_HEAD_INIT(&PyType_Type, 0) @@ -211,10 +180,10 @@ PyTypeObject PyEnum_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)enum_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ 0, /* tp_as_sequence */ @@ -226,15 +195,15 @@ PyTypeObject PyEnum_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - enum_new__doc__, /* tp_doc */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ + enum_doc, /* tp_doc */ (traverseproc)enum_traverse, /* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ + PyObject_SelfIter, /* tp_iter */ (iternextfunc)enum_next, /* tp_iternext */ - enum_methods, /* tp_methods */ + 0, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -256,45 +225,44 @@ typedef struct { PyObject* seq; } reversedobject; -/*[clinic input] -@classmethod -reversed.__new__ as reversed_new - - sequence as seq: object - / - -Return a reverse iterator over the values of the given sequence. -[clinic start generated code]*/ - static PyObject * -reversed_new_impl(PyTypeObject *type, PyObject *seq) -/*[clinic end generated code: output=f7854cc1df26f570 input=aeb720361e5e3f1d]*/ +reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) { Py_ssize_t n; - PyObject *reversed_meth; + PyObject *seq, *reversed_meth; + static PyObject *reversed_cache = NULL; reversedobject *ro; - _Py_IDENTIFIER(__reversed__); - reversed_meth = _PyObject_LookupSpecial(seq, &PyId___reversed__); - if (reversed_meth == Py_None) { - Py_DECREF(reversed_meth); - PyErr_Format(PyExc_TypeError, - "'%.200s' object is not reversible", - Py_TYPE(seq)->tp_name); + if (type == &PyReversed_Type && !_PyArg_NoKeywords("reversed()", kwds)) + return NULL; + + if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq) ) return NULL; + + if (PyInstance_Check(seq)) { + reversed_meth = PyObject_GetAttrString(seq, "__reversed__"); + if (reversed_meth == NULL) { + if (PyErr_ExceptionMatches(PyExc_AttributeError)) + PyErr_Clear(); + else + return NULL; + } + } + else { + reversed_meth = _PyObject_LookupSpecial(seq, "__reversed__", + &reversed_cache); + if (reversed_meth == NULL && PyErr_Occurred()) + return NULL; } if (reversed_meth != NULL) { - PyObject *res = _PyObject_CallNoArg(reversed_meth); + PyObject *res = PyObject_CallFunctionObjArgs(reversed_meth, NULL); Py_DECREF(reversed_meth); return res; } - else if (PyErr_Occurred()) - return NULL; if (!PySequence_Check(seq)) { - PyErr_Format(PyExc_TypeError, - "'%.200s' object is not reversible", - Py_TYPE(seq)->tp_name); + PyErr_SetString(PyExc_TypeError, + "argument to reversed() must be a sequence"); return NULL; } @@ -348,56 +316,29 @@ reversed_next(reversedobject *ro) return NULL; } +PyDoc_STRVAR(reversed_doc, +"reversed(sequence) -> reverse iterator over values of the sequence\n" +"\n" +"Return a reverse iterator"); + static PyObject * -reversed_len(reversedobject *ro, PyObject *Py_UNUSED(ignored)) +reversed_len(reversedobject *ro) { Py_ssize_t position, seqsize; if (ro->seq == NULL) - return PyLong_FromLong(0); + return PyInt_FromLong(0); seqsize = PySequence_Size(ro->seq); if (seqsize == -1) return NULL; position = ro->index + 1; - return PyLong_FromSsize_t((seqsize < position) ? 0 : position); + return PyInt_FromSsize_t((seqsize < position) ? 0 : position); } PyDoc_STRVAR(length_hint_doc, "Private method returning an estimate of len(list(it))."); -static PyObject * -reversed_reduce(reversedobject *ro, PyObject *Py_UNUSED(ignored)) -{ - if (ro->seq) - return Py_BuildValue("O(O)n", Py_TYPE(ro), ro->seq, ro->index); - else - return Py_BuildValue("O(())", Py_TYPE(ro)); -} - -static PyObject * -reversed_setstate(reversedobject *ro, PyObject *state) -{ - Py_ssize_t index = PyLong_AsSsize_t(state); - if (index == -1 && PyErr_Occurred()) - return NULL; - if (ro->seq != 0) { - Py_ssize_t n = PySequence_Size(ro->seq); - if (n < 0) - return NULL; - if (index < -1) - index = -1; - else if (index > n-1) - index = n-1; - ro->index = index; - } - Py_RETURN_NONE; -} - -PyDoc_STRVAR(setstate_doc, "Set state information for unpickling."); - static PyMethodDef reversediter_methods[] = { {"__length_hint__", (PyCFunction)reversed_len, METH_NOARGS, length_hint_doc}, - {"__reduce__", (PyCFunction)reversed_reduce, METH_NOARGS, reduce_doc}, - {"__setstate__", (PyCFunction)reversed_setstate, METH_O, setstate_doc}, {NULL, NULL} /* sentinel */ }; @@ -408,13 +349,13 @@ PyTypeObject PyReversed_Type = { 0, /* tp_itemsize */ /* methods */ (destructor)reversed_dealloc, /* tp_dealloc */ - 0, /* tp_vectorcall_offset */ + 0, /* tp_print */ 0, /* tp_getattr */ 0, /* tp_setattr */ - 0, /* tp_as_async */ + 0, /* tp_compare */ 0, /* tp_repr */ 0, /* tp_as_number */ - 0, /* tp_as_sequence */ + 0, /* tp_as_sequence */ 0, /* tp_as_mapping */ 0, /* tp_hash */ 0, /* tp_call */ @@ -423,15 +364,15 @@ PyTypeObject PyReversed_Type = { 0, /* tp_setattro */ 0, /* tp_as_buffer */ Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | - Py_TPFLAGS_BASETYPE, /* tp_flags */ - reversed_new__doc__, /* tp_doc */ + Py_TPFLAGS_BASETYPE, /* tp_flags */ + reversed_doc, /* tp_doc */ (traverseproc)reversed_traverse,/* tp_traverse */ 0, /* tp_clear */ 0, /* tp_richcompare */ 0, /* tp_weaklistoffset */ - PyObject_SelfIter, /* tp_iter */ + PyObject_SelfIter, /* tp_iter */ (iternextfunc)reversed_next, /* tp_iternext */ - reversediter_methods, /* tp_methods */ + reversediter_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ |