diff options
Diffstat (limited to 'Objects')
-rw-r--r-- | Objects/enumobject.c | 125 | ||||
-rw-r--r-- | Objects/rangeobject.c | 37 |
2 files changed, 161 insertions, 1 deletions
diff --git a/Objects/enumobject.c b/Objects/enumobject.c index 17a62825a0..998e3810a1 100644 --- a/Objects/enumobject.c +++ b/Objects/enumobject.c @@ -155,3 +155,128 @@ PyTypeObject PyEnum_Type = { enum_new, /* tp_new */ PyObject_GC_Del, /* tp_free */ }; + +/* Reversed Object ***************************************************************/ + +typedef struct { + PyObject_HEAD + long index; + PyObject* seq; +} reversedobject; + +static PyObject * +reversed_new(PyTypeObject *type, PyObject *args, PyObject *kwds) +{ + long n; + PyObject *seq; + reversedobject *ro; + + if (!PyArg_UnpackTuple(args, "reversed", 1, 1, &seq)) + return NULL; + + /* Special case optimization for xrange */ + if (PyRange_Check(seq)) + return PyObject_CallMethod(seq, "__reversed__", NULL); + + if (!PySequence_Check(seq)) { + PyErr_SetString(PyExc_TypeError, + "argument to reversed() must be a sequence"); + return NULL; + } + + n = PySequence_Size(seq); + if (n == -1) + return NULL; + + ro = (reversedobject *)type->tp_alloc(type, 0); + if (ro == NULL) + return NULL; + + ro->index = n-1; + Py_INCREF(seq); + ro->seq = seq; + return (PyObject *)ro; +} + +static void +reversed_dealloc(reversedobject *ro) +{ + PyObject_GC_UnTrack(ro); + Py_XDECREF(ro->seq); + ro->ob_type->tp_free(ro); +} + +static int +reversed_traverse(reversedobject *ro, visitproc visit, void *arg) +{ + if (ro->seq) + return visit((PyObject *)(ro->seq), arg); + return 0; +} + +static PyObject * +reversed_next(reversedobject *ro) +{ + PyObject *item; + + if (ro->index < 0) + return NULL; + + assert(PySequence_Check(ro->seq)); + item = PySequence_GetItem(ro->seq, ro->index); + if (item == NULL) + return NULL; + + ro->index--; + return item; +} + +PyDoc_STRVAR(reversed_doc, +"reverse(sequence) -> reverse iterator over values of the sequence\n" +"\n" +"Return a reverse iterator"); + +PyTypeObject PyReversed_Type = { + PyObject_HEAD_INIT(&PyType_Type) + 0, /* ob_size */ + "reversed", /* tp_name */ + sizeof(reversedobject), /* tp_basicsize */ + 0, /* tp_itemsize */ + /* methods */ + (destructor)reversed_dealloc, /* tp_dealloc */ + 0, /* tp_print */ + 0, /* tp_getattr */ + 0, /* tp_setattr */ + 0, /* tp_compare */ + 0, /* tp_repr */ + 0, /* tp_as_number */ + 0, /* tp_as_sequence */ + 0, /* tp_as_mapping */ + 0, /* tp_hash */ + 0, /* tp_call */ + 0, /* tp_str */ + PyObject_GenericGetAttr, /* tp_getattro */ + 0, /* tp_setattro */ + 0, /* tp_as_buffer */ + Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | + 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 */ + (iternextfunc)reversed_next, /* tp_iternext */ + 0, /* tp_methods */ + 0, /* tp_members */ + 0, /* tp_getset */ + 0, /* tp_base */ + 0, /* tp_dict */ + 0, /* tp_descr_get */ + 0, /* tp_descr_set */ + 0, /* tp_dictoffset */ + 0, /* tp_init */ + PyType_GenericAlloc, /* tp_alloc */ + reversed_new, /* tp_new */ + PyObject_GC_Del, /* tp_free */ +}; diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c index 299f4a651f..1f5672804f 100644 --- a/Objects/rangeobject.c +++ b/Objects/rangeobject.c @@ -171,6 +171,15 @@ static PySequenceMethods range_as_sequence = { }; static PyObject * range_iter(PyObject *seq); +static PyObject * range_reverse(PyObject *seq); + +PyDoc_STRVAR(reverse_doc, +"Returns a reverse iterator."); + +static PyMethodDef range_methods[] = { + {"__reversed__", (PyCFunction)range_reverse, METH_NOARGS, reverse_doc}, + {NULL, NULL} /* sentinel */ +}; PyTypeObject PyRange_Type = { PyObject_HEAD_INIT(&PyType_Type) @@ -201,7 +210,7 @@ PyTypeObject PyRange_Type = { 0, /* tp_weaklistoffset */ (getiterfunc)range_iter, /* tp_iter */ 0, /* tp_iternext */ - 0, /* tp_methods */ + range_methods, /* tp_methods */ 0, /* tp_members */ 0, /* tp_getset */ 0, /* tp_base */ @@ -246,6 +255,32 @@ range_iter(PyObject *seq) } static PyObject * +range_reverse(PyObject *seq) +{ + rangeiterobject *it; + long start, step, len; + + if (!PyRange_Check(seq)) { + PyErr_BadInternalCall(); + return NULL; + } + it = PyObject_New(rangeiterobject, &Pyrangeiter_Type); + if (it == NULL) + return NULL; + + start = ((rangeobject *)seq)->start; + step = ((rangeobject *)seq)->step; + len = ((rangeobject *)seq)->len; + + it->index = 0; + it->start = start + (len-1) * step; + it->step = -step; + it->len = len; + + return (PyObject *)it; +} + +static PyObject * rangeiter_next(rangeiterobject *r) { if (r->index < r->len) |