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.
This commit is contained in:
Fred Drake 2000-11-08 19:42:43 +00:00
parent a91e1650aa
commit 0b796fa5c5
1 changed files with 34 additions and 8 deletions

View File

@ -2,6 +2,8 @@
/* Range object implementation */ /* Range object implementation */
#include "Python.h" #include "Python.h"
#include "structmember.h"
#include <string.h>
typedef struct { typedef struct {
PyObject_HEAD PyObject_HEAD
@ -175,14 +177,30 @@ range_tolist(rangeobject *self, PyObject *args)
static PyObject * static PyObject *
range_getattr(rangeobject *r, char *name) range_getattr(rangeobject *r, char *name)
{ {
PyObject *result;
static PyMethodDef range_methods[] = { static PyMethodDef range_methods[] = {
{"tolist", (PyCFunction)range_tolist, METH_VARARGS, {"tolist", (PyCFunction)range_tolist, METH_VARARGS,
"tolist() -> list\n" "tolist() -> list\n"
"Return a list object with the same values."}, "Return a list object with the same values."},
{NULL, NULL} {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 static int
@ -193,21 +211,29 @@ range_contains(rangeobject *r, PyObject *obj)
if (num < 0 && PyErr_Occurred()) if (num < 0 && PyErr_Occurred())
return -1; return -1;
if ((num < r->start) || ((num - r->start) % r->step)) if (r->step > 0) {
return 0; if ((num < r->start) || ((num - r->start) % r->step))
if (num >= (r->start + (r->len * r->step))) return 0;
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; return 1;
} }
static PySequenceMethods range_as_sequence = { static PySequenceMethods range_as_sequence = {
(inquiry)range_length, /*sq_length*/ (inquiry)range_length, /*sq_length*/
(binaryfunc)range_concat, /*sq_concat*/ (binaryfunc)range_concat, /*sq_concat*/
(intargfunc)range_repeat, /*sq_repeat*/ (intargfunc)range_repeat, /*sq_repeat*/
(intargfunc)range_item, /*sq_item*/ (intargfunc)range_item, /*sq_item*/
(intintargfunc)range_slice, /*sq_slice*/ (intintargfunc)range_slice, /*sq_slice*/
0, /*sq_ass_item*/ 0, /*sq_ass_item*/
0, /*sq_ass_slice*/ 0, /*sq_ass_slice*/
(objobjproc)range_contains, /*sq_contains*/ (objobjproc)range_contains, /*sq_contains*/
}; };