summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFred Drake <fdrake@acm.org>2000-11-08 19:42:43 (GMT)
committerFred Drake <fdrake@acm.org>2000-11-08 19:42:43 (GMT)
commit0b796fa5c56611341f039c5ab6ed17a2b63833d2 (patch)
treeff6832a88968ff22c90a139efa141dbb15fcf209
parenta91e1650aafd63e7940a1c838aa1377981ad459c (diff)
downloadcpython-0b796fa5c56611341f039c5ab6ed17a2b63833d2.zip
cpython-0b796fa5c56611341f039c5ab6ed17a2b63833d2.tar.gz
cpython-0b796fa5c56611341f039c5ab6ed17a2b63833d2.tar.bz2
Fixed support for containment test when a negative step is used; this
*really* closes bug #121965. Added three attributes to the xrange object: start, stop, and step. These are the same as for the slice objects.
-rw-r--r--Objects/rangeobject.c42
1 files changed, 34 insertions, 8 deletions
diff --git a/Objects/rangeobject.c b/Objects/rangeobject.c
index 0deabe9..1aac2dc 100644
--- a/Objects/rangeobject.c
+++ b/Objects/rangeobject.c
@@ -2,6 +2,8 @@
/* Range object implementation */
#include "Python.h"
+#include "structmember.h"
+#include <string.h>
typedef struct {
PyObject_HEAD
@@ -175,14 +177,30 @@ range_tolist(rangeobject *self, PyObject *args)
static PyObject *
range_getattr(rangeobject *r, char *name)
{
+ PyObject *result;
+
static PyMethodDef range_methods[] = {
{"tolist", (PyCFunction)range_tolist, METH_VARARGS,
"tolist() -> list\n"
"Return a list object with the same values."},
{NULL, NULL}
};
+ static struct memberlist range_members[] = {
+ {"step", T_LONG, offsetof(rangeobject, step), RO},
+ {"start", T_LONG, offsetof(rangeobject, start), RO},
+ {"stop", T_LONG, 0, RO},
+ {NULL, 0, 0, 0}
+ };
- return Py_FindMethod(range_methods, (PyObject *) r, name);
+ result = Py_FindMethod(range_methods, (PyObject *) r, name);
+ if (result == NULL) {
+ PyErr_Clear();
+ if (strcmp("stop", name) == 0)
+ result = PyInt_FromLong(r->start + (r->len * r->step));
+ else
+ result = PyMember_Get((char *)r, range_members, name);
+ }
+ return result;
}
static int
@@ -193,21 +211,29 @@ range_contains(rangeobject *r, PyObject *obj)
if (num < 0 && PyErr_Occurred())
return -1;
- if ((num < r->start) || ((num - r->start) % r->step))
- return 0;
- if (num >= (r->start + (r->len * r->step)))
- return 0;
+ if (r->step > 0) {
+ if ((num < r->start) || ((num - r->start) % r->step))
+ return 0;
+ if (num >= (r->start + (r->len * r->step)))
+ return 0;
+ }
+ else {
+ if ((num > r->start) || ((num - r->start) % r->step))
+ return 0;
+ if (num <= (r->start + (r->len * r->step)))
+ return 0;
+ }
return 1;
}
static PySequenceMethods range_as_sequence = {
- (inquiry)range_length, /*sq_length*/
+ (inquiry)range_length, /*sq_length*/
(binaryfunc)range_concat, /*sq_concat*/
(intargfunc)range_repeat, /*sq_repeat*/
(intargfunc)range_item, /*sq_item*/
(intintargfunc)range_slice, /*sq_slice*/
- 0, /*sq_ass_item*/
- 0, /*sq_ass_slice*/
+ 0, /*sq_ass_item*/
+ 0, /*sq_ass_slice*/
(objobjproc)range_contains, /*sq_contains*/
};