[Zodb-checkins] CVS: Zope/lib/python/BTrees - BTreeModuleTemplate.c:1.37 MergeTemplate.c:1.15 SetOpTemplate.c:1.26

Tim Peters tim.one@comcast.net
Tue, 25 Jun 2002 18:02:27 -0400


Update of /cvs-repository/Zope/lib/python/BTrees
In directory cvs.zope.org:/tmp/cvs-serv8056

Modified Files:
	BTreeModuleTemplate.c MergeTemplate.c SetOpTemplate.c 
Log Message:
A step on the way to repairing negative weights used with the weighted
intersection and union functions:  get the concept of weight entirely out
of the internal set iteration protocol.  The caller wants values, or
doesn't, and that's just a Boolean.  This makes for some nice little
internal simplifications, but doesn't yet change any semantics.


=== Zope/lib/python/BTrees/BTreeModuleTemplate.c 1.36 => 1.37 ===
  * When you want to iterate over a set or bucket or BTree (even an
  * individual key!),
- * 1. Declare a new iterator and a "merge" int:
+ * 1. Declare a new iterator:
  *        SetIteration si = {0,0,0};
- *        int merge = 0;
  *    Using "{0,0,0}" or "{0,0}" appear most common.  Only one {0} is
  *    necssary.  At least one must be given so that finiSetIteration() works
  *    correctly even if you don't get around to calling initSetIteration().
  * 2. Initialize it via
- *        initSetIteration(&si, PyObject *s, int weight, &merge)
+ *        initSetIteration(&si, PyObject *s, useValues)
  *    It's an error if that returns an int < 0.  In case of error on the
  *    init call, calling finiSetIteration(&si) is optional.  But if the
  *    init call succeeds, you must eventually call finiSetIteration(),
@@ -200,8 +199,7 @@
  *    If the set isn't empty, this sets si.position to an int >= 0,
  *    si.key to the element's key (of type KEY_TYPE), and maybe si.value to
  *    the element's value (of type VALUE_TYPE).  si.value is defined
- *    iff merge was set to true by the initSetIteration() call, which is
- *    equivalent to whether si.usesValue is true.
+ *    iff si.usesValue is true.
  * 4. Process all the elements:
  *        while (si.position >= 0) {
  *            do something with si.key and/or si.value;
@@ -219,7 +217,6 @@
   PyObject *set;    /* the set, bucket, BTree, ..., being iterated */
   int position;     /* initialized to 0; set to -1 by next() when done */
   int usesValue;    /* true iff 'set' has values & we iterate them */
-  int hasValue;     /* true iff 'set' has values (as well as keys) */
   KEY_TYPE key;     /* next() sets to next key */
   VALUE_TYPE value; /* next() may set to next value */
   int (*next)(struct SetIteration_s*);  /* function to get next key+value */


=== Zope/lib/python/BTrees/MergeTemplate.c 1.14 => 1.15 ===
   PyObject *s;
   SetIteration i1 = {0,0,0}, i2 = {0,0,0}, i3 = {0,0,0};
-  int cmp12, cmp13, cmp23, mapping=0, set;
+  int cmp12, cmp13, cmp23, mapping, set;
 
-  if (initSetIteration(&i1, OBJECT(s1), 0, &mapping) < 0) goto err;
-  if (initSetIteration(&i2, OBJECT(s2), 0, &mapping) < 0) goto err;
-  if (initSetIteration(&i3, OBJECT(s3), 0, &mapping) < 0) goto err;
+  if (initSetIteration(&i1, OBJECT(s1), 1) < 0) goto err;
+  if (initSetIteration(&i2, OBJECT(s2), 1) < 0) goto err;
+  if (initSetIteration(&i3, OBJECT(s3), 1) < 0) goto err;
 
+  mapping = i1.usesValue | i2.usesValue | i3.usesValue;
   set = ! mapping;
 
   if (mapping)


=== Zope/lib/python/BTrees/SetOpTemplate.c 1.25 => 1.26 ===
  *
  * Arguments
- *      i       The address of a SetIteration control struct.
- *      s       The address of the set, bucket, BTree, ..., to be iterated.
- *      w       If w < 0, ignore values when iterating.
- *      merge   Is set to 1 if s has values (as well as keys) and w >= 0.
- *              The value on input is ignored.
+ *      i           The address of a SetIteration control struct.
+ *      s           The address of the set, bucket, BTree, ..., to be iterated.
+ *      useValues   Boolean; if true, and s has values (is a mapping), copy
+ *                  them into i->value each time i->next() is called; else
+ *                  ignore s's values even if s is a mapping.
  *
  * Return
  *      0 on success; -1 and an exception set if error.
- *      *merge is set to 1 if s has values and w >= 0, else merge is left
- *          alone.
- *      i.usesValue is also set to 1 if s has values and w >= 0, else
- *          .usesValue is set to 0.
+ *      i.usesValue is set to 1 (true) if s has values and useValues was
+ *          true; else usesValue is set to 0 (false).
  *      i.set gets a new reference to s, or to some other object used to
  *          iterate over s.
  *      i.position is set to 0.
- *      i.hasValue is set to true if s has values, and to false otherwise.
- *          Note that this is done independent of w's value, and when w < 0
- *          may differ from i.usesValue.
  *      i.next is set to an appropriate iteration function.
  *      i.key and i.value are left alone.
  *
@@ -102,20 +97,18 @@
  *          A SetIteration struct has been cleaned up iff i.set is NULL.
  */
 static int
-initSetIteration(SetIteration *i, PyObject *s, int w, int *merge)
+initSetIteration(SetIteration *i, PyObject *s, int useValues)
 {
   i->set = NULL;
   i->position = -1;     /* set to 0 only on normal return */
-  i->hasValue = 0;      /* assume it's a set */
   i->usesValue = 0;     /* assume it's a set or that values aren't iterated */
 
   if (ExtensionClassSubclassInstance_Check(s, &BucketType))
     {
       i->set = s;
       Py_INCREF(s);
-      i->hasValue = 1;
 
-      if (w >= 0)
+      if (useValues)
         {
           i->usesValue = 1;
           i->next = nextBucket;
@@ -133,9 +126,8 @@
     {
       i->set = BTree_rangeSearch(BTREE(s), NULL, 'i');
       UNLESS(i->set) return -1;
-      i->hasValue = 1;
 
-      if (w >= 0)
+      if (useValues)
         {
           i->usesValue = 1;
           i->next = nextBTreeItems;
@@ -176,7 +168,6 @@
       return -1;
     }
 
-  *merge |= i->usesValue;
   i->position = 0;
 
   return 0;
@@ -214,17 +205,18 @@
 {
   Bucket *r=0;
   SetIteration i1 = {0,0,0}, i2 = {0,0,0};
-  int cmp, merge=0;
+  int cmp, merge;
 
-  if (initSetIteration(&i1, s1, w1, &merge) < 0) goto err;
-  if (initSetIteration(&i2, s2, w2, &merge) < 0) goto err;
+  if (initSetIteration(&i1, s1, w1 >= 0) < 0) goto err;
+  if (initSetIteration(&i2, s2, w2 >= 0) < 0) goto err;
+  merge = i1.usesValue | i2.usesValue;
 
   if (merge)
     {
 #ifndef MERGE
-      if (c12 && i1.hasValue && i2.hasValue) goto invalid_set_operation;
+      if (c12 && i1.usesValue && i2.usesValue) goto invalid_set_operation;
 #endif
-      if (! i1.hasValue && i2.hasValue)
+      if (! i1.usesValue && i2.usesValue)
         {
           SetIteration t;
           int i;
@@ -237,9 +229,9 @@
       i1.value=MERGE_DEFAULT;
       i2.value=MERGE_DEFAULT;
 #else
-      if (i1.hasValue)
+      if (i1.usesValue)
         {
-          if (! i2.hasValue && c2) goto invalid_set_operation;
+          if (! i2.usesValue && c2) goto invalid_set_operation;
         }
       else
         {
@@ -506,9 +498,7 @@
         }
         else {
             /* No cheap way:  iterate over set's elements one at a time. */
-            int merge;  /* dummy needed for initSetIteration */
-
-            if (initSetIteration(&setiter, set, -1, &merge) < 0) goto Error;
+            if (initSetIteration(&setiter, set, 0) < 0) goto Error;
             if (setiter.next(&setiter) < 0) goto Error;
             while (setiter.position >= 0) {
                 if (result->len >= result->size && Bucket_grow(result, -1, 1) < 0)