summaryrefslogtreecommitdiffstats
path: root/Objects/enumobject.c
diff options
context:
space:
mode:
authorRaymond Hettinger <python@rcn.com>2003-11-06 14:06:48 (GMT)
committerRaymond Hettinger <python@rcn.com>2003-11-06 14:06:48 (GMT)
commit85c20a41dfcec04d161ad7da7260e7b94c62d228 (patch)
tree0d9e5b294ab4890b72ddc61d193036ac1d4b5ca4 /Objects/enumobject.c
parentf607fc5395883ff924c76739e9b0921953568e54 (diff)
downloadcpython-85c20a41dfcec04d161ad7da7260e7b94c62d228.zip
cpython-85c20a41dfcec04d161ad7da7260e7b94c62d228.tar.gz
cpython-85c20a41dfcec04d161ad7da7260e7b94c62d228.tar.bz2
Implement and apply PEP 322, reverse iteration
Diffstat (limited to 'Objects/enumobject.c')
-rw-r--r--Objects/enumobject.c125
1 files changed, 125 insertions, 0 deletions
diff --git a/Objects/enumobject.c b/Objects/enumobject.c
index 17a6282..998e381 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 */
+};