]> granicus.if.org Git - python/commitdiff
Fixed support for containment test when a negative step is used; this
authorFred Drake <fdrake@acm.org>
Wed, 8 Nov 2000 19:42:43 +0000 (19:42 +0000)
committerFred Drake <fdrake@acm.org>
Wed, 8 Nov 2000 19:42:43 +0000 (19:42 +0000)
*really* closes bug #121965.

Added three attributes to the xrange object: start, stop, and step.  These
are the same as for the slice objects.

Objects/rangeobject.c

index 0deabe90cbe71339e9f16be7d198b259958eea2a..1aac2dced4e0bc8438e2a2680eec630d9343db00 100644 (file)
@@ -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*/
 };