[Zope-Checkins] CVS: Zope3/lib/python/Persistence/BTrees - BTreeTemplate.c:1.36 BucketTemplate.c:1.14

Tim Peters tim.one@comcast.net
Sat, 22 Jun 2002 15:35:27 -0400


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

Modified Files:
	BTreeTemplate.c BucketTemplate.c 
Log Message:
Like Python 2.2 dicts, all flavors of BTree and Bucket (but not Set or
TreeSet) in Zope3 now support new .iterkeys(), .itervalues() and
.iteritems() methods.  These return iterators for the object's keys,
values or items.  Unlike Python dicts, but like BTree and Bucket .keys(),
.values() and .items() methods, .iter{key,value,item}s support optional
lo and hi range arguments (to restrict the elements generated to those
whose keys are in lo thru hi inclusive).

For BTrees, the .iterXYZ versions are a little faster than their
non-iter versions.  Both are "lazy" (elements are generated as needed,
not materialized in one gulp at the start).

The .iterXYZ versions are also "lazy" for Buckets, but the non-iter
versions are not.  That is, bucket.items() has always materialized a
possibly giant list of two-tuples, but bucket.iteritems() yields a
small iterator object that knows how to produce the right pairs as
needed.  So, for example, the peak memory use for

    for k, v in bucket.iteritems():

is small and independent of len(bucket), while

    for k, v in bucket.items():

requires memory proportional to len(bucket) right at the start.


=== Zope3/lib/python/Persistence/BTrees/BTreeTemplate.c 1.35 => 1.36 ===
 }
 
+/**************************************************************************/
+/* Iterator support. */
+
+/* A helper to build all the iterators for BTrees and TreeSets.
+ * If args is NULL, the iterator spans the entire structure.  Else it's an
+ * argument tuple, with optional low and high arguments.
+ * kind is 'k', 'v' or 'i'.
+ * Returns a BTreeIter object, or NULL if error.
+ */
+static PyObject *
+buildBTreeIter(BTree *self, PyObject *args, char kind)
+{
+    BTreeIter *result = NULL;
+    BTreeItems *items = (BTreeItems *)BTree_rangeSearch(self, args, kind);
+
+    if (items) {
+        result = BTreeIter_new(items);
+        Py_DECREF(items);
+    }
+    return (PyObject *)result;
+}
+
+/* The implementation of iter(BTree_or_TreeSet); the BTree tp_iter slot. */
+static PyObject *
+BTree_getiter(BTree *self)
+{
+    return buildBTreeIter(self, NULL, 'k');
+}
+
+/* The implementation of BTree.iterkeys(). */
+static PyObject *
+BTree_iterkeys(BTree *self, PyObject *args)
+{
+    return buildBTreeIter(self, args, 'k');
+}
+
+/* The implementation of BTree.itervalues(). */
+static PyObject *
+BTree_itervalues(BTree *self, PyObject *args)
+{
+    return buildBTreeIter(self, args, 'v');
+}
+
+/* The implementation of BTree.iteritems(). */
+static PyObject *
+BTree_iteritems(BTree *self, PyObject *args)
+{
+    return buildBTreeIter(self, args, 'i');
+}
+
+/* End of iterator support. */
+
+
 /* XXX Even though the _firstbucket attribute is read-only, a program
    could probably do arbitrary damage to a the btree internals.  For
    example, it could call clear() on a bucket inside a BTree.
@@ -1714,6 +1767,12 @@
      "added, or 0 otherwise."},
     {"update",	(PyCFunction) Mapping_update,	METH_O,
      "update(collection)\n\n Add the items from the given collection."},
+    {"iterkeys", (PyCFunction) BTree_iterkeys,  METH_VARARGS,
+     "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
+    {"itervalues", (PyCFunction) BTree_itervalues,  METH_VARARGS,
+     "B.itervalues([min[,max]]) -> an iterator over the values of B"},
+    {"iteritems", (PyCFunction) BTree_iteritems,    METH_VARARGS,
+     "B.iteritems([min[,max]]) -> an iterator over the (key, value) items of B"},
     {"_check", (PyCFunction) BTree_check,       METH_NOARGS,
      "Perform sanity check on BTree, and raise exception if flawed."},
 #ifdef PERSISTENT
@@ -1879,20 +1938,6 @@
 BTree_nonzero(BTree *self)
 {
   return BTree_length_or_nonzero(self, 1);
-}
-
-/* The implementation of iter(BTree_or_TreeSet). */
-static PyObject *
-BTree_getiter(BTree *self)
-{
-    BTreeIter *result = NULL;
-    BTreeItems *items = (BTreeItems *)BTree_rangeSearch(self, NULL, 'k');
-
-    if (items) {
-        result = BTreeIter_new(items);
-        Py_DECREF(items);
-    }
-    return (PyObject *)result;
 }
 
 static PyNumberMethods BTree_as_number_for_nonzero = {


=== Zope3/lib/python/Persistence/BTrees/BucketTemplate.c 1.13 => 1.14 ===
 }
 
+/**************************************************************************/
+/* Iterator support. */
+
+/* A helper to build all the iterators for Buckets and Sets.
+ * If args is NULL, the iterator spans the entire structure.  Else it's an
+ * argument tuple, with optional low and high arguments.
+ * kind is 'k', 'v' or 'i'.
+ * Returns a BTreeIter object, or NULL if error.
+ */
+static PyObject *
+buildBucketIter(Bucket *self, PyObject *args, char kind)
+{
+    BTreeItems *items;
+    int lowoffset, highoffset;
+    BTreeIter *result = NULL;
+
+    PER_USE_OR_RETURN(self, NULL);
+    if (Bucket_rangeSearch(self, args, &lowoffset, &highoffset) < 0) goto Done;
+
+    items = (BTreeItems *)newBTreeItems(kind, self, lowoffset,
+                                              self, highoffset);
+    if (items == NULL) goto Done;
+
+    result = BTreeIter_new(items);      /* win or lose, we're done */
+    Py_DECREF(items);
+
+Done:
+    PER_UNUSE(self);
+    return (PyObject *)result;
+}
+
+/* The implementation of iter(Bucket_or_Set); the Bucket tp_iter slot. */
+static PyObject *
+Bucket_getiter(Bucket *self)
+{
+    return buildBucketIter(self, NULL, 'k');
+}
+
+/* The implementation of Bucket.iterkeys(). */
+static PyObject *
+Bucket_iterkeys(Bucket *self, PyObject *args)
+{
+    return buildBucketIter(self, args, 'k');
+}
+
+/* The implementation of Bucket.itervalues(). */
+static PyObject *
+Bucket_itervalues(Bucket *self, PyObject *args)
+{
+    return buildBucketIter(self, args, 'v');
+}
+
+/* The implementation of Bucket.iteritems(). */
+static PyObject *
+Bucket_iteritems(Bucket *self, PyObject *args)
+{
+    return buildBucketIter(self, args, 'i');
+}
+
+/* End of iterator support. */
+
 #ifdef PERSISTENT
 static PyObject *merge_error(int p1, int p2, int p3, int reason);
 static PyObject *bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3);
@@ -1250,6 +1311,12 @@
     {"get",	(PyCFunction) bucket_getm,	METH_VARARGS,
      "get(key[,default]) -- Look up a value\n\n"
      "Return the default (or None) if the key is not found."},
+    {"iterkeys", (PyCFunction) Bucket_iterkeys,  METH_VARARGS,
+     "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
+    {"itervalues", (PyCFunction) Bucket_itervalues,  METH_VARARGS,
+     "B.itervalues([min[,max]]) -> an iterator over the values of B"},
+    {"iteritems", (PyCFunction) Bucket_iteritems,    METH_VARARGS,
+     "B.iteritems([min[,max]]) -> an iterator over the (key, value) items of B"},
 #ifdef PERSISTENT
     {"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict,
      METH_VARARGS,
@@ -1422,28 +1489,6 @@
 	Py_DECREF(r);
 	return s;
     }
-}
-
-/* The implementation of iter(Bucket_or_Set). */
-static PyObject *
-Bucket_getiter(Bucket *self)
-{
-    BTreeItems *items;
-    int lowoffset, highoffset;
-    BTreeIter *result = NULL;
-
-    PER_USE_OR_RETURN(self, NULL);
-    if (Bucket_rangeSearch(self, NULL, &lowoffset, &highoffset) < 0) goto Done;
-
-    items = (BTreeItems *)newBTreeItems('k', self, lowoffset, self, highoffset);
-    if (items == NULL) goto Done;
-
-    result = BTreeIter_new(items);      /* win or lose, we're done */
-    Py_DECREF(items);
-
-Done:
-    PER_UNUSE(self);
-    return (PyObject *)result;
 }
 
 static PyTypeObject BucketType = {