]> granicus.if.org Git - python/commitdiff
list_ass_slice(): Document the obscure new intent that deleting a slice
authorTim Peters <tim.peters@gmail.com>
Sat, 31 Jul 2004 21:53:19 +0000 (21:53 +0000)
committerTim Peters <tim.peters@gmail.com>
Sat, 31 Jul 2004 21:53:19 +0000 (21:53 +0000)
of no more than 8 elements cannot fail.

listpop():  Take advantage of that its calls to list_resize() and
list_ass_slice() can't fail.  This is assert'ed in a debug build now, but
in an icky way.  That is, you can't say:

assert(some_call() >= 0);

because then some_call() won't occur at all in a release build.  So it
has to be a big pile of #ifdefs on Py_DEBUG (yuck), or the pleasant:

        status = some_call();
        assert(status >= 0);

But in that case, compilers may whine in a release build, because status
appears unused then.  I'm not certain the ugly trick I used here will
convince all compilers to shut up about status (status is always "used" now,
as the first (ignored) clause in a comma expression).

Objects/listobject.c

index 91c0a1cbe9fb52fbdb13f2667a76d58218769dab..72b235629c6e9e580e8e7d211ba680718e7d2b3d 100644 (file)
@@ -519,6 +519,12 @@ list_clear(PyListObject *a)
        return 0;
 }
 
+/* a[ilow:ihigh] = v if v != NULL.
+ * del a[ilow:ihigh] if v == NULL.
+ *
+ * Special speed gimmick:  when v is NULL and ihigh - ilow <= 8, it's
+ * guaranteed the call cannot fail.
+ */
 static int
 list_ass_slice(PyListObject *a, int ilow, int ihigh, PyObject *v)
 {
@@ -823,6 +829,7 @@ listpop(PyListObject *self, PyObject *args)
 {
        int i = -1;
        PyObject *v, *arg = NULL;
+       int status;
 
        if (!PyArg_UnpackTuple(args, "pop", 0, 1, &arg))
                return NULL;
@@ -845,16 +852,17 @@ listpop(PyListObject *self, PyObject *args)
        }
        v = self->ob_item[i];
        if (i == self->ob_size - 1) {
-               if (list_resize(self, self->ob_size - 1) == -1)
-                       return NULL;
-               return v;
+               status = list_resize(self, self->ob_size - 1);
+               assert(status >= 0);
+               return v; /* and v now owns the reference the list had */
        }
        Py_INCREF(v);
-       if (list_ass_slice(self, i, i+1, (PyObject *)NULL) != 0) {
-               Py_DECREF(v);
-               return NULL;
-       }
-       return v;
+       status = list_ass_slice(self, i, i+1, (PyObject *)NULL);
+       assert(status >= 0);
+       /* Use status, so that in a release build compilers don't
+        * complain about the unused name.
+        */
+       return status, v;
 }
 
 /* Reverse a slice of a list in place, from lo up to (exclusive) hi. */