[Zope-Checkins] CVS: Zope3/lib/python/Persistence/BTrees - BTreeItemsTemplate.c:1.8

Tim Peters tim.one@comcast.net
Sat, 22 Jun 2002 14:00:36 -0400


Update of /cvs-repository/Zope3/lib/python/Persistence/BTrees
In directory cvs.zope.org:/tmp/cvs-serv14495

Modified Files:
	BTreeItemsTemplate.c 
Log Message:
BTreeItems_item(), BTreeIter_next():  refactored to use a new
getBucketEntry() helper function.  Getting all the error cases right is
too tedious to duplicate all this logic inline.


=== Zope3/lib/python/Persistence/BTrees/BTreeItemsTemplate.c 1.7 => 1.8 ===
 }
 
+
+/* Return the right kind ('k','v','i') of entry from bucket b at offset i.
+ *  b must be activated.  Returns NULL on error.
+ */
+static PyObject *
+getBucketEntry(Bucket *b, int i, char kind)
+{
+    PyObject *result = NULL;
+
+    assert(b);
+    assert(0 <= i && i < b->len);
+
+    switch (kind) {
+
+        case 'k':
+            COPY_KEY_TO_OBJECT(result, b->keys[i]);
+            break;
+
+        case 'v':
+            COPY_VALUE_TO_OBJECT(result, b->values[i]);
+            break;
+
+        case 'i': {
+            PyObject *key;
+            PyObject *value;;
+
+            COPY_KEY_TO_OBJECT(key, b->keys[i]);
+            if (!key) break;
+
+            COPY_VALUE_TO_OBJECT(value, b->values[i]);
+            if (!value) {
+                Py_DECREF(key);
+                break;
+            }
+
+            result = PyTuple_New(2);
+            if (result) {
+                PyTuple_SET_ITEM(result, 0, key);
+                PyTuple_SET_ITEM(result, 1, value);
+            }
+            else {
+                Py_DECREF(key);
+                Py_DECREF(value);
+            }
+            break;
+        }
+
+        default:
+            PyErr_SetString(PyExc_AssertionError,
+                            "getBucketEntry: unknown kind");
+            break;
+    }
+    return result;
+}
+
 /*
 ** BTreeItems_item
 **
@@ -235,44 +290,15 @@
 static PyObject *
 BTreeItems_item(BTreeItems *self, int i)
 {
-  PyObject *r, *k=0, *v=0;
-
-  if (BTreeItems_seek(self, i) < 0) return NULL;
-
-  PER_USE_OR_RETURN(self->currentbucket, NULL);
-
-  switch(self->kind) {
-
-  case 'v':
-    COPY_VALUE_TO_OBJECT(r, self->currentbucket->values[self->currentoffset]);
-    break;
-
-  case 'i':
-    COPY_KEY_TO_OBJECT(k, self->currentbucket->keys[self->currentoffset]);
-    UNLESS (k) return NULL;
-
-    COPY_VALUE_TO_OBJECT(v, self->currentbucket->values[self->currentoffset]);
-    UNLESS (v) return NULL;
-
-    UNLESS (r=PyTuple_New(2)) goto err;
+    PyObject *result;
 
-    PyTuple_SET_ITEM(r, 0, k);
-    PyTuple_SET_ITEM(r, 1, v);
-    break;
+    if (BTreeItems_seek(self, i) < 0) return NULL;
 
-  default:
-    COPY_KEY_TO_OBJECT(r, self->currentbucket->keys[self->currentoffset]);
-    break;
-  }
-
-  PER_UNUSE(self->currentbucket);
-  return r;
-
- err:
-  Py_DECREF(k);
-  Py_XDECREF(v);
-  PER_UNUSE(self->currentbucket);
-  return NULL;
+    PER_USE_OR_RETURN(self->currentbucket, NULL);
+    result = getBucketEntry(self->currentbucket, self->currentoffset,
+                            self->kind);
+    PER_UNUSE(self->currentbucket);
+    return result;
 }
 
 /*
@@ -607,34 +633,7 @@
 	}
 
         /* Build the result object, from bucket at offset i. */
-        switch (items->kind) {
-
-        case 'k':
-            COPY_KEY_TO_OBJECT(result, bucket->keys[i]);
-            break;
-
-        case 'v':
-            COPY_VALUE_TO_OBJECT(result, bucket->values[i]);
-            break;
-
-        case 'i': {
-            PyObject *key;
-            PyObject *value;
-
-            COPY_KEY_TO_OBJECT(key, bucket->keys[i]);
-            COPY_VALUE_TO_OBJECT(value, bucket->values[i]);
-
-            result = PyTuple_New(2);
-            if (result == NULL) goto Done;
-            PyTuple_SET_ITEM(result, 0, key);
-            PyTuple_SET_ITEM(result, 1, value);
-            break;
-        }
-
-        default:
-            assert(!"unknown items->kind value");
-            goto Done;
-        }
+        result = getBucketEntry(bucket, i, items->kind);
 
         /* Advance position for next call. */
         if (bucket == items->lastbucket && i >= items->last) {