1 /*****************************************************************************
2 
3   Copyright (c) 2001, 2002 Zope Foundation and Contributors.
4   All Rights Reserved.
5 
6   This software is subject to the provisions of the Zope Public License,
7   Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
8   THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9   WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10   WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11   FOR A PARTICULAR PURPOSE
12 
13 ****************************************************************************/
14 
15 #include "SetOpTemplate.h"
16 #define BUCKETTEMPLATE_C "$Id$\n"
17 
18 /* Use BUCKET_SEARCH to find the index at which a key belongs.
19  * INDEX    An int lvalue to hold the index i such that KEY belongs at
20  *          SELF->keys[i].  Note that this will equal SELF->len if KEY
21  *          is larger than the bucket's largest key.  Else it's the
22  *          smallest i such that SELF->keys[i] >= KEY.
23  * ABSENT   An int lvalue to hold a Boolean result, true (!= 0) if the
24  *          key is absent, false (== 0) if the key is at INDEX.
25  * SELF     A pointer to a Bucket node.
26  * KEY      The key you're looking for, of type KEY_TYPE.
27  * ONERROR  What to do if key comparison raises an exception; for example,
28  *          perhaps 'return NULL'.
29  *
30  * See Maintainer.txt for discussion:  this is optimized in subtle ways.
31  * It's recommended that you call this at the start of a routine, waiting
32  * to check for self->len == 0 after (if an empty bucket is special in
33  * context; INDEX becomes 0 and ABSENT becomes true if this macro is run
34  * with an empty SELF, and that may be all the invoker needs to know).
35  */
36 #define BUCKET_SEARCH(INDEX, ABSENT, SELF, KEY, ONERROR) {  \
37     int _lo = 0;                                            \
38     int _hi = (SELF)->len;                                  \
39     int _i;                                                 \
40     int _cmp = 1;                                           \
41     for (_i = _hi >> 1; _lo < _hi; _i = (_lo + _hi) >> 1) { \
42       TEST_KEY_SET_OR(_cmp, (SELF)->keys[_i], (KEY))        \
43         ONERROR;                                            \
44       if      (_cmp < 0)  _lo = _i + 1;                     \
45       else if (_cmp == 0) break;                            \
46       else                _hi = _i;                         \
47     }                                                       \
48     (INDEX) = _i;                                           \
49     (ABSENT) = _cmp;                                        \
50   }
51 
52 /*
53 ** _bucket_get
54 **
55 ** Search a bucket for a given key.
56 **
57 ** Arguments
58 **     self    The bucket
59 **     keyarg    The key to look for
60 **     has_key    Boolean; if true, return a true/false result; else return
61 **              the value associated with the key. When true, ignore the TypeError from
62 **              a key conversion issue, instead
63 **              transforming it into a KeyError.
64 **
65 ** Return
66 **     If has_key:
67 **         Returns the Python int 0 if the key is absent, else returns
68 **         has_key itself as a Python int.  A BTree caller generally passes
69 **         the depth of the bucket for has_key, so a true result returns
70 **         the bucket depth then.
71 **         Note that has_key should be true when searching set buckets.
72 **     If not has_key:
73 **         If the key is present, returns the associated value, and the
74 **         caller owns the reference.  Else returns NULL and sets KeyError.
75 **     Whether or not has_key:
76 **         If a comparison sets an exception, returns NULL.
77 */
78 static PyObject *
_bucket_get(Bucket * self,PyObject * keyarg,int has_key)79 _bucket_get(Bucket *self, PyObject *keyarg, int has_key)
80 {
81     int i, cmp;
82     KEY_TYPE key;
83     PyObject *r = NULL;
84     int copied = 1;
85 
86     COPY_KEY_FROM_ARG(key, keyarg, copied);
87     UNLESS (copied)
88     {
89         if (has_key && PyErr_ExceptionMatches(PyExc_TypeError))
90         {
91             PyErr_Clear();
92             PyErr_SetObject(PyExc_KeyError, keyarg);
93         }
94         return NULL;
95     }
96 
97     UNLESS (PER_USE(self)) return NULL;
98 
99     BUCKET_SEARCH(i, cmp, self, key, goto Done);
100     if (has_key)
101         r = INT_FROM_LONG(cmp ? 0 : has_key);
102     else
103     {
104         if (cmp == 0)
105         {
106             COPY_VALUE_TO_OBJECT(r, self->values[i]);
107         }
108         else
109             PyErr_SetObject(PyExc_KeyError, keyarg);
110     }
111 
112 Done:
113     PER_UNUSE(self);
114     return r;
115 }
116 
117 static PyObject *
bucket_getitem(Bucket * self,PyObject * key)118 bucket_getitem(Bucket *self, PyObject *key)
119 {
120     PyObject* result;
121 
122     result = _bucket_get(self, key, 0);
123 
124     if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError))
125     {
126         PyErr_Clear();
127         PyErr_SetObject(PyExc_KeyError, key);
128     }
129 
130     return result;
131 }
132 
133 /*
134 ** Bucket_grow
135 **
136 ** Resize a bucket.
137 **
138 ** Arguments:   self    The bucket.
139 **              newsize The new maximum capacity.  If < 0, double the
140 **                      current size unless the bucket is currently empty,
141 **                      in which case use MIN_BUCKET_ALLOC.
142 **              noval   Boolean; if true, allocate only key space and not
143 **                      value space
144 **
145 ** Returns:     -1      on error, and MemoryError exception is set
146 **               0      on success
147 */
148 static int
Bucket_grow(Bucket * self,int newsize,int noval)149 Bucket_grow(Bucket *self, int newsize, int noval)
150 {
151     KEY_TYPE *keys;
152     VALUE_TYPE *values;
153 
154     if (self->size)
155     {
156         if (newsize < 0)
157             newsize = self->size * 2;
158         if (newsize < 0)    /* int overflow */
159             goto Overflow;
160         UNLESS (keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE) * newsize))
161             return -1;
162 
163         UNLESS (noval)
164         {
165             values = BTree_Realloc(self->values, sizeof(VALUE_TYPE) * newsize);
166             if (values == NULL)
167             {
168                 free(keys);
169                 return -1;
170             }
171             self->values = values;
172         }
173         self->keys = keys;
174     }
175     else
176     {
177         if (newsize < 0)
178             newsize = MIN_BUCKET_ALLOC;
179         UNLESS (self->keys = BTree_Malloc(sizeof(KEY_TYPE) * newsize))
180             return -1;
181         UNLESS (noval)
182         {
183             self->values = BTree_Malloc(sizeof(VALUE_TYPE) * newsize);
184             if (self->values == NULL)
185             {
186                 free(self->keys);
187                 self->keys = NULL;
188                 return -1;
189             }
190         }
191     }
192     self->size = newsize;
193     return 0;
194 
195 Overflow:
196     PyErr_NoMemory();
197     return -1;
198 }
199 
200 /* So far, bucket_append is called only by multiunion_m(), so is called
201  * only when MULTI_INT_UNION is defined.  Flavors of BTree/Bucket that
202  * don't support MULTI_INT_UNION don't call bucket_append (yet), and
203  * gcc complains if bucket_append is compiled in those cases.  So only
204  * compile bucket_append if it's going to be used.
205  */
206 #ifdef MULTI_INT_UNION
207 /*
208  * Append a slice of the "from" bucket to self.
209  *
210  * self         Append (at least keys) to this bucket.  self must be activated
211  *              upon entry, and remains activated at exit.  If copyValues
212  *              is true, self must be empty or already have a non-NULL values
213  *              pointer.  self's access and modification times aren't updated.
214  * from         The bucket from which to take keys, and possibly values.  from
215  *              must be activated upon entry, and remains activated at exit.
216  *              If copyValues is true, from must have a non-NULL values
217  *              pointer.  self and from must not be the same.  from's access
218  *              time isn't updated.
219  * i, n         The slice from[i : i+n] is appended to self.  Must have
220  *              i >= 0, n > 0 and i+n <= from->len.
221  * copyValues   Boolean.  If true, copy values from the slice as well as keys.
222  *              In this case, from must have a non-NULL values pointer, and
223  *              self must too (unless self is empty, in which case a values
224  *              vector will be allocated for it).
225  * overallocate Boolean.  If self doesn't have enough room upon entry to hold
226  *              all the appended stuff, then if overallocate is false exactly
227  *              enough room will be allocated to hold the new stuff, else if
228  *              overallocate is true an excess will be allocated.  overallocate
229  *              may be a good idea if you expect to append more stuff to self
230  *              later; else overallocate should be false.
231  *
232  * CAUTION:  If self is empty upon entry (self->size == 0), and copyValues is
233  * false, then no space for values will get allocated.  This can be a trap if
234  * the caller intends to copy values itself.
235  *
236  * Return
237  *    -1        Error.
238  *     0        OK.
239  */
240 static int
bucket_append(Bucket * self,Bucket * from,int i,int n,int copyValues,int overallocate)241 bucket_append(Bucket *self, Bucket *from, int i, int n,
242               int copyValues, int overallocate)
243 {
244     int newlen;
245 
246     assert(self && from && self != from);
247     assert(i >= 0);
248     assert(n > 0);
249     assert(i+n <= from->len);
250 
251     /* Make room. */
252     newlen = self->len + n;
253     if (newlen > self->size)
254     {
255         int newsize = newlen;
256         if (overallocate)   /* boost by 25% -- pretty arbitrary */
257         newsize += newsize >> 2;
258         if (Bucket_grow(self, newsize, ! copyValues) < 0)
259         return -1;
260     }
261     assert(newlen <= self->size);
262 
263     /* Copy stuff. */
264     memcpy(self->keys + self->len, from->keys + i, n * sizeof(KEY_TYPE));
265     if (copyValues)
266     {
267         assert(self->values);
268         assert(from->values);
269         memcpy(self->values + self->len, from->values + i,
270             n * sizeof(VALUE_TYPE));
271     }
272     self->len = newlen;
273 
274     /* Bump refcounts. */
275 #ifdef KEY_TYPE_IS_PYOBJECT
276     {
277         int j;
278         PyObject **p = from->keys + i;
279         for (j = 0; j < n; ++j, ++p)
280         {
281             Py_INCREF(*p);
282         }
283     }
284 #endif
285 #ifdef VALUE_TYPE_IS_PYOBJECT
286     if (copyValues)
287     {
288         int j;
289         PyObject **p = from->values + i;
290         for (j = 0; j < n; ++j, ++p)
291         {
292             Py_INCREF(*p);
293         }
294     }
295 #endif
296     return 0;
297 }
298 #endif /* MULTI_INT_UNION */
299 
300 /*
301 ** _bucket_set: Assign a value to a key in a bucket, delete a key+value
302 **  pair, or just insert a key.
303 **
304 ** Arguments
305 **     self     The bucket
306 **     keyarg   The key to look for
307 **     v        The value to associate with key; NULL means delete the key.
308 **              If NULL, it's an error (KeyError) if the key isn't present.
309 **              Note that if this is a set bucket, and you want to insert
310 **              a new set element, v must be non-NULL although its exact
311 **              value will be ignored.  Passing Py_None is good for this.
312 **     unique   Boolean; when true, don't replace the value if the key is
313 **              already present.
314 **     noval    Boolean; when true, operate on keys only (ignore values)
315 **     changed  ignored on input
316 **
317 ** Return
318 **     -1       on error
319 **      0       on success and the # of bucket entries didn't change
320 **      1       on success and the # of bucket entries did change
321 **  *changed    If non-NULL, set to 1 on any mutation of the bucket.
322 */
323 static int
_bucket_set(Bucket * self,PyObject * keyarg,PyObject * v,int unique,int noval,int * changed)324 _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
325             int unique, int noval, int *changed)
326 {
327     int i, cmp;
328     KEY_TYPE key;
329 
330     /* Subtle:  there may or may not be a value.  If there is, we need to
331      * check its type early, so that in case of error we can get out before
332      * mutating the bucket.  But because value isn't used on all paths, if
333      * we don't initialize value then gcc gives a nuisance complaint that
334      * value may be used initialized (it can't be, but gcc doesn't know
335      * that).  So we initialize it.  However, VALUE_TYPE can be various types,
336      * including int, PyObject*, and char[6], so it's a puzzle to spell
337      * initialization.  It so happens that {0} is a valid initializer for all
338      * these types.
339      */
340     VALUE_TYPE value = {0};    /* squash nuisance warning */
341     int result = -1;    /* until proven innocent */
342     int copied = 1;
343 
344     COPY_KEY_FROM_ARG(key, keyarg, copied);
345     UNLESS(copied)
346         return -1;
347 #ifdef KEY_CHECK_ON_SET
348     if (v && !KEY_CHECK_ON_SET(keyarg))
349         return -1;
350 #endif
351 
352     /* Copy the value early (if needed), so that in case of error a
353      * pile of bucket mutations don't need to be undone.
354      */
355     if (v && !noval) {
356         COPY_VALUE_FROM_ARG(value, v, copied);
357         UNLESS(copied)
358             return -1;
359     }
360 
361     UNLESS (PER_USE(self))
362         return -1;
363 
364     BUCKET_SEARCH(i, cmp, self, key, goto Done);
365     if (cmp == 0)
366     {
367         /* The key exists, at index i. */
368         if (v)
369         {
370             /* The key exists at index i, and there's a new value.
371              * If unique, we're not supposed to replace it.  If noval, or this
372              * is a set bucket (self->values is NULL), there's nothing to do.
373              */
374             if (unique || noval || self->values == NULL)
375             {
376                 result = 0;
377                 goto Done;
378             }
379 
380             /* The key exists at index i, and we need to replace the value. */
381 #ifdef VALUE_SAME
382             /* short-circuit if no change */
383             if (VALUE_SAME(self->values[i], value))
384             {
385                 result = 0;
386                 goto Done;
387             }
388 #endif
389             if (changed)
390                 *changed = 1;
391             DECREF_VALUE(self->values[i]);
392             COPY_VALUE(self->values[i], value);
393             INCREF_VALUE(self->values[i]);
394             if (PER_CHANGED(self) >= 0)
395                 result = 0;
396             goto Done;
397         }
398 
399         /* The key exists at index i, and should be deleted. */
400         DECREF_KEY(self->keys[i]);
401         self->len--;
402         if (i < self->len)
403             memmove(self->keys + i, self->keys + i+1,
404                     sizeof(KEY_TYPE)*(self->len - i));
405 
406         if (self->values)
407         {
408             DECREF_VALUE(self->values[i]);
409             if (i < self->len)
410                 memmove(self->values + i, self->values + i+1,
411                         sizeof(VALUE_TYPE)*(self->len - i));
412         }
413 
414         if (! self->len)
415         {
416             self->size = 0;
417             free(self->keys);
418             self->keys = NULL;
419             if (self->values)
420             {
421                 free(self->values);
422                 self->values = NULL;
423             }
424         }
425 
426         if (changed)
427             *changed = 1;
428         if (PER_CHANGED(self) >= 0)
429             result = 1;
430         goto Done;
431     }
432 
433     /* The key doesn't exist, and belongs at index i. */
434     if (!v)
435     {
436         /* Can't delete a non-existent key. */
437         PyErr_SetObject(PyExc_KeyError, keyarg);
438         goto Done;
439     }
440 
441     /* The key doesn't exist and should be inserted at index i. */
442     if (self->len == self->size && Bucket_grow(self, -1, noval) < 0)
443         goto Done;
444 
445     if (self->len > i)
446     {
447         memmove(self->keys + i + 1, self->keys + i,
448                 sizeof(KEY_TYPE) * (self->len - i));
449         if (self->values)
450         {
451             memmove(self->values + i + 1, self->values + i,
452                     sizeof(VALUE_TYPE) * (self->len - i));
453         }
454     }
455 
456     COPY_KEY(self->keys[i], key);
457     INCREF_KEY(self->keys[i]);
458 
459     if (! noval)
460     {
461         COPY_VALUE(self->values[i], value);
462         INCREF_VALUE(self->values[i]);
463     }
464 
465     self->len++;
466     if (changed)
467         *changed = 1;
468     if (PER_CHANGED(self) >= 0)
469         result = 1;
470 
471 Done:
472     PER_UNUSE(self);
473     return result;
474 }
475 
476 /*
477 ** bucket_setitem
478 **
479 ** wrapper for _bucket_set (eliminates +1 return code)
480 **
481 ** Arguments:    self    The bucket
482 **        key    The key to insert under
483 **        v    The value to insert
484 **
485 ** Returns     0     on success
486 **        -1    on failure
487 */
488 static int
bucket_setitem(Bucket * self,PyObject * key,PyObject * v)489 bucket_setitem(Bucket *self, PyObject *key, PyObject *v)
490 {
491     if (_bucket_set(self, key, v, 0, 0, 0) < 0)
492         return -1;
493     return 0;
494 }
495 
496 /**
497  ** Accepts a sequence of 2-tuples, or any object with an items()
498  ** method that returns an iterable object producing 2-tuples.
499  */
500 static int
update_from_seq(PyObject * map,PyObject * seq)501 update_from_seq(PyObject *map, PyObject *seq)
502 {
503     PyObject *iter, *o, *k, *v;
504     int err = -1;
505 
506     /* One path creates a new seq object.  The other path has an
507         INCREF of the seq argument.  So seq must always be DECREFed on
508         the way out.
509     */
510     /* Use items() if it's not a sequence.  Alas, PySequence_Check()
511      * returns true for a PeristentMapping or PersistentDict, and we
512      * want to use items() in those cases too.
513      */
514 #ifdef PY3K
515 #define ITERITEMS "items"
516 #else
517 #define ITERITEMS "iteritems"
518 #endif
519     if (!PySequence_Check(seq) || /* or it "looks like a dict" */
520         PyObject_HasAttrString(seq, ITERITEMS))
521 #undef ITERITEMS
522     {
523         PyObject *items;
524         items = PyObject_GetAttrString(seq, "items");
525         if (items == NULL)
526             return -1;
527         seq = PyObject_CallObject(items, NULL);
528         Py_DECREF(items);
529         if (seq == NULL)
530             return -1;
531     }
532     else
533         Py_INCREF(seq);
534 
535     iter = PyObject_GetIter(seq);
536     if (iter == NULL)
537         goto err;
538     while (1)
539     {
540         o = PyIter_Next(iter);
541         if (o == NULL)
542         {
543             if (PyErr_Occurred())
544                 goto err;
545             else
546                 break;
547         }
548         if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != 2)
549         {
550             Py_DECREF(o);
551             PyErr_SetString(PyExc_TypeError,
552                         "Sequence must contain 2-item tuples");
553             goto err;
554         }
555         k = PyTuple_GET_ITEM(o, 0);
556         v = PyTuple_GET_ITEM(o, 1);
557         if (PyObject_SetItem(map, k, v) < 0)
558         {
559             Py_DECREF(o);
560             goto err;
561         }
562         Py_DECREF(o);
563     }
564 
565     err = 0;
566 err:
567     Py_DECREF(iter);
568     Py_DECREF(seq);
569     return err;
570 }
571 
572 static PyObject *
Mapping_update(PyObject * self,PyObject * seq)573 Mapping_update(PyObject *self, PyObject *seq)
574 {
575     if (update_from_seq(self, seq) < 0)
576         return NULL;
577     Py_INCREF(Py_None);
578     return Py_None;
579 }
580 
581 /*
582 ** bucket_split
583 **
584 ** Splits one bucket into two
585 **
586 ** Arguments:    self    The bucket
587 **        index    the index of the key to split at (O.O.B use midpoint)
588 **        next    the new bucket to split into
589 **
590 ** Returns:     0    on success
591 **        -1    on failure
592 */
593 static int
bucket_split(Bucket * self,int index,Bucket * next)594 bucket_split(Bucket *self, int index, Bucket *next)
595 {
596     int next_size;
597 
598     ASSERT(self->len > 1, "split of empty bucket", -1);
599 
600     if (index < 0 || index >= self->len)
601         index = self->len / 2;
602 
603     next_size = self->len - index;
604 
605     next->keys = BTree_Malloc(sizeof(KEY_TYPE) * next_size);
606     if (!next->keys)
607         return -1;
608     memcpy(next->keys, self->keys + index, sizeof(KEY_TYPE) * next_size);
609     if (self->values) {
610         next->values = BTree_Malloc(sizeof(VALUE_TYPE) * next_size);
611         if (!next->values) {
612         free(next->keys);
613         next->keys = NULL;
614         return -1;
615         }
616         memcpy(next->values, self->values + index,
617             sizeof(VALUE_TYPE) * next_size);
618     }
619     next->size = next_size;
620     next->len = next_size;
621     self->len = index;
622 
623     next->next = self->next;
624 
625     Py_INCREF(next);
626     self->next = next;
627 
628     if (PER_CHANGED(self) < 0)
629         return -1;
630 
631     return 0;
632 }
633 
634 /* Set self->next to self->next->next, i.e. unlink self's successor from
635  * the chain.
636  *
637  * Return:
638  *     -1       error
639  *      0       OK
640  */
641 static int
Bucket_deleteNextBucket(Bucket * self)642 Bucket_deleteNextBucket(Bucket *self)
643 {
644     int result = -1;    /* until proven innocent */
645     Bucket *successor;
646 
647     PER_USE_OR_RETURN(self, -1);
648     successor = self->next;
649     if (successor)
650     {
651         Bucket *next;
652         /* Before:  self -> successor -> next
653         * After:   self --------------> next
654         */
655         UNLESS (PER_USE(successor))
656             goto Done;
657         next = successor->next;
658         PER_UNUSE(successor);
659 
660         Py_XINCREF(next);       /* it may be NULL, of course */
661         self->next = next;
662         Py_DECREF(successor);
663         if (PER_CHANGED(self) < 0)
664             goto Done;
665     }
666     result = 0;
667 
668 Done:
669     PER_UNUSE(self);
670     return result;
671 }
672 
673 /*
674   Bucket_findRangeEnd -- Find the index of a range endpoint
675   (possibly) contained in a bucket.
676 
677   Arguments:     self        The bucket
678   keyarg      The key to match against
679   low         Boolean; true for low end of range, false for high
680   exclude_equal  Boolean; if true, don't accept an exact match,
681   and if there is one then move right if low and
682   left if !low.
683   offset      The output offset
684 
685   If low true, *offset <- index of the smallest item >= key,
686   if low false the index of the largest item <= key.  In either case, if there
687   is no such index, *offset is left alone and 0 is returned.
688 
689   Return:
690   0     No suitable index exists; *offset has not been changed
691   1     The correct index was stored into *offset
692   -1     Error
693 
694   Example:  Suppose the keys are [2, 4], and exclude_equal is false.  Searching
695   for 2 sets *offset to 0 and returns 1 regardless of low.  Searching for 4
696   sets *offset to 1 and returns 1 regardless of low.
697   Searching for 1:
698   If low true, sets *offset to 0, returns 1.
699   If low false, returns 0.
700   Searching for 3:
701   If low true, sets *offset to 1, returns 1.
702   If low false, sets *offset to 0, returns 1.
703   Searching for 5:
704   If low true, returns 0.
705   If low false, sets *offset to 1, returns 1.
706 
707   The 1, 3 and 5 examples are the same when exclude_equal is true.
708 */
709 static int
Bucket_findRangeEnd(Bucket * self,PyObject * keyarg,int low,int exclude_equal,int * offset)710 Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int exclude_equal,
711                     int *offset)
712 {
713     int i, cmp;
714     int result = -1;    /* until proven innocent */
715     KEY_TYPE key;
716     int copied = 1;
717 
718     COPY_KEY_FROM_ARG(key, keyarg, copied);
719     UNLESS (copied)
720         return -1;
721 
722     UNLESS (PER_USE(self))
723         return -1;
724 
725     BUCKET_SEARCH(i, cmp, self, key, goto Done);
726     if (cmp == 0) {
727         /* exact match at index i */
728         if (exclude_equal)
729         {
730             /* but we don't want an exact match */
731             if (low)
732                 ++i;
733             else
734                 --i;
735         }
736     }
737     /* Else keys[i-1] < key < keys[i], picturing infinities at OOB indices,
738     * and i has the smallest item > key, which is correct for low.
739     */
740     else if (! low)
741         /* i-1 has the largest item < key (unless i-1 is 0OB) */
742         --i;
743 
744     result = 0 <= i && i < self->len;
745     if (result)
746         *offset = i;
747 
748 Done:
749     PER_UNUSE(self);
750     return result;
751 }
752 
753 static PyObject *
Bucket_maxminKey(Bucket * self,PyObject * args,int min)754 Bucket_maxminKey(Bucket *self, PyObject *args, int min)
755 {
756     PyObject *key=0;
757     int rc, offset = 0;
758     int empty_bucket = 1;
759 
760     if (args && ! PyArg_ParseTuple(args, "|O", &key))
761         return NULL;
762 
763     PER_USE_OR_RETURN(self, NULL);
764 
765     UNLESS (self->len)
766         goto empty;
767 
768     /* Find the low range */
769     if (key && key != Py_None)
770     {
771         if ((rc = Bucket_findRangeEnd(self, key, min, 0, &offset)) <= 0)
772         {
773             if (rc < 0)
774                 return NULL;
775             empty_bucket = 0;
776             goto empty;
777         }
778     }
779     else if (min)
780         offset = 0;
781     else
782         offset = self->len -1;
783 
784     COPY_KEY_TO_OBJECT(key, self->keys[offset]);
785     PER_UNUSE(self);
786 
787     return key;
788 
789 empty:
790     PyErr_SetString(PyExc_ValueError,
791                     empty_bucket ? "empty bucket" :
792                     "no key satisfies the conditions");
793     PER_UNUSE(self);
794     return NULL;
795 }
796 
797 static PyObject *
Bucket_minKey(Bucket * self,PyObject * args)798 Bucket_minKey(Bucket *self, PyObject *args)
799 {
800     return Bucket_maxminKey(self, args, 1);
801 }
802 
803 static PyObject *
Bucket_maxKey(Bucket * self,PyObject * args)804 Bucket_maxKey(Bucket *self, PyObject *args)
805 {
806     return Bucket_maxminKey(self, args, 0);
807 }
808 
809 static int
Bucket_rangeSearch(Bucket * self,PyObject * args,PyObject * kw,int * low,int * high)810 Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
811                    int *low, int *high)
812 {
813     PyObject *min = Py_None;
814     PyObject *max = Py_None;
815     int excludemin = 0;
816     int excludemax = 0;
817     int rc;
818 
819     if (args)
820     {
821         if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords,
822                                           &min,
823                                           &max,
824                                           &excludemin,
825                                           &excludemax))
826             return -1;
827     }
828 
829     UNLESS (self->len)
830         goto empty;
831 
832     /* Find the low range */
833     if (min != Py_None)
834     {
835         rc = Bucket_findRangeEnd(self, min, 1, excludemin, low);
836         if (rc < 0)
837             return -1;
838         if (rc == 0)
839             goto empty;
840     }
841     else
842     {
843         *low = 0;
844         if (excludemin)
845         {
846             if (self->len < 2)
847                 goto empty;
848             ++*low;
849         }
850     }
851 
852     /* Find the high range */
853     if (max != Py_None)
854     {
855         rc = Bucket_findRangeEnd(self, max, 0, excludemax, high);
856         if (rc < 0)
857             return -1;
858         if (rc == 0)
859             goto empty;
860     }
861     else
862     {
863         *high = self->len - 1;
864         if (excludemax)
865         {
866             if (self->len < 2)
867                 goto empty;
868             --*high;
869         }
870     }
871 
872     /* If min < max to begin with, it's quite possible that low > high now. */
873     if (*low <= *high)
874         return 0;
875 
876 empty:
877     *low = 0;
878     *high = -1;
879     return 0;
880 }
881 
882 /*
883 ** bucket_keys
884 **
885 ** Generate a list of all keys in the bucket
886 **
887 ** Arguments:    self    The Bucket
888 **        args    (unused)
889 **
890 ** Returns:    list of bucket keys
891 */
892 static PyObject *
bucket_keys(Bucket * self,PyObject * args,PyObject * kw)893 bucket_keys(Bucket *self, PyObject *args, PyObject *kw)
894 {
895     PyObject *r = NULL, *key;
896     int i, low, high;
897 
898     PER_USE_OR_RETURN(self, NULL);
899 
900     if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
901         goto err;
902 
903     r = PyList_New(high-low+1);
904     if (r == NULL)
905         goto err;
906 
907     for (i=low; i <= high; i++)
908     {
909         COPY_KEY_TO_OBJECT(key, self->keys[i]);
910         if (PyList_SetItem(r, i-low , key) < 0)
911             goto err;
912     }
913 
914     PER_UNUSE(self);
915     return r;
916 
917 err:
918     PER_UNUSE(self);
919     Py_XDECREF(r);
920     return NULL;
921 }
922 
923 /*
924 ** bucket_values
925 **
926 ** Generate a list of all values in the bucket
927 **
928 ** Arguments:    self    The Bucket
929 **        args    (unused)
930 **
931 ** Returns    list of values
932 */
933 static PyObject *
bucket_values(Bucket * self,PyObject * args,PyObject * kw)934 bucket_values(Bucket *self, PyObject *args, PyObject *kw)
935 {
936     PyObject *r=0, *v;
937     int i, low, high;
938 
939     PER_USE_OR_RETURN(self, NULL);
940 
941     if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
942         goto err;
943 
944     UNLESS (r=PyList_New(high-low+1))
945         goto err;
946 
947     for (i=low; i <= high; i++)
948     {
949         COPY_VALUE_TO_OBJECT(v, self->values[i]);
950         UNLESS (v)
951             goto err;
952         if (PyList_SetItem(r, i-low, v) < 0)
953             goto err;
954     }
955 
956     PER_UNUSE(self);
957     return r;
958 
959 err:
960     PER_UNUSE(self);
961     Py_XDECREF(r);
962     return NULL;
963 }
964 
965 /*
966 ** bucket_items
967 **
968 ** Returns a list of all items in a bucket
969 **
970 ** Arguments:    self    The Bucket
971 **        args    (unused)
972 **
973 ** Returns:    list of all items in the bucket
974 */
975 static PyObject *
bucket_items(Bucket * self,PyObject * args,PyObject * kw)976 bucket_items(Bucket *self, PyObject *args, PyObject *kw)
977 {
978     PyObject *r=0, *o=0, *item=0;
979     int i, low, high;
980 
981     PER_USE_OR_RETURN(self, NULL);
982 
983     if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
984         goto err;
985 
986     UNLESS (r=PyList_New(high-low+1))
987         goto err;
988 
989     for (i=low; i <= high; i++)
990     {
991         UNLESS (item = PyTuple_New(2))
992             goto err;
993 
994         COPY_KEY_TO_OBJECT(o, self->keys[i]);
995         UNLESS (o)
996             goto err;
997         PyTuple_SET_ITEM(item, 0, o);
998 
999         COPY_VALUE_TO_OBJECT(o, self->values[i]);
1000         UNLESS (o)
1001             goto err;
1002         PyTuple_SET_ITEM(item, 1, o);
1003 
1004         if (PyList_SetItem(r, i-low, item) < 0)
1005             goto err;
1006 
1007         item = 0;
1008     }
1009 
1010     PER_UNUSE(self);
1011     return r;
1012 
1013 err:
1014     PER_UNUSE(self);
1015     Py_XDECREF(r);
1016     Py_XDECREF(item);
1017     return NULL;
1018 }
1019 
1020 static PyObject *
bucket_byValue(Bucket * self,PyObject * omin)1021 bucket_byValue(Bucket *self, PyObject *omin)
1022 {
1023     PyObject *r=0, *o=0, *item=0;
1024     VALUE_TYPE min;
1025     VALUE_TYPE v;
1026     int i, l, copied=1;
1027 
1028     PER_USE_OR_RETURN(self, NULL);
1029 
1030     COPY_VALUE_FROM_ARG(min, omin, copied);
1031     UNLESS(copied)
1032         return NULL;
1033 
1034     for (i=0, l=0; i < self->len; i++)
1035         if (TEST_VALUE(self->values[i], min) >= 0)
1036         l++;
1037 
1038     UNLESS (r=PyList_New(l))
1039         goto err;
1040 
1041     for (i=0, l=0; i < self->len; i++)
1042     {
1043         if (TEST_VALUE(self->values[i], min) < 0)
1044             continue;
1045 
1046         UNLESS (item = PyTuple_New(2))
1047             goto err;
1048 
1049         COPY_KEY_TO_OBJECT(o, self->keys[i]);
1050         UNLESS (o)
1051             goto err;
1052         PyTuple_SET_ITEM(item, 1, o);
1053 
1054         COPY_VALUE(v, self->values[i]);
1055         NORMALIZE_VALUE(v, min);
1056         COPY_VALUE_TO_OBJECT(o, v);
1057         DECREF_VALUE(v);
1058         UNLESS (o)
1059             goto err;
1060         PyTuple_SET_ITEM(item, 0, o);
1061 
1062         if (PyList_SetItem(r, l, item) < 0)
1063             goto err;
1064         l++;
1065 
1066         item = 0;
1067     }
1068 
1069     item=PyObject_GetAttr(r,sort_str);
1070     UNLESS (item)
1071         goto err;
1072     ASSIGN(item, PyObject_CallObject(item, NULL));
1073     UNLESS (item)
1074         goto err;
1075     ASSIGN(item, PyObject_GetAttr(r, reverse_str));
1076     UNLESS (item)
1077         goto err;
1078     ASSIGN(item, PyObject_CallObject(item, NULL));
1079     UNLESS (item)
1080         goto err;
1081     Py_DECREF(item);
1082 
1083     PER_UNUSE(self);
1084     return r;
1085 
1086 err:
1087     PER_UNUSE(self);
1088     Py_XDECREF(r);
1089     Py_XDECREF(item);
1090     return NULL;
1091 }
1092 
1093 static int
_bucket_clear(Bucket * self)1094 _bucket_clear(Bucket *self)
1095 {
1096     const int len = self->len;
1097     /* Don't declare i at this level.  If neither keys nor values are
1098      * PyObject*, i won't be referenced, and you'll get a nuisance compiler
1099      * wng for declaring it here.
1100      */
1101     self->len = self->size = 0;
1102 
1103     if (self->next)
1104     {
1105         Py_DECREF(self->next);
1106         self->next = NULL;
1107     }
1108 
1109     /* Silence compiler warning about unused variable len for the case
1110         when neither key nor value is an object, i.e. II. */
1111     (void)len;
1112 
1113     if (self->keys)
1114     {
1115 #ifdef KEY_TYPE_IS_PYOBJECT
1116         int i;
1117         for (i = 0; i < len; ++i)
1118             DECREF_KEY(self->keys[i]);
1119 #endif
1120         free(self->keys);
1121         self->keys = NULL;
1122     }
1123 
1124     if (self->values)
1125     {
1126 #ifdef VALUE_TYPE_IS_PYOBJECT
1127         int i;
1128         for (i = 0; i < len; ++i)
1129             DECREF_VALUE(self->values[i]);
1130 #endif
1131         free(self->values);
1132         self->values = NULL;
1133     }
1134     return 0;
1135 }
1136 
1137 #ifdef PERSISTENT
1138 static PyObject *
bucket__p_deactivate(Bucket * self,PyObject * args,PyObject * keywords)1139 bucket__p_deactivate(Bucket *self, PyObject *args, PyObject *keywords)
1140 {
1141     int ghostify = 1;
1142     PyObject *force = NULL;
1143 
1144     if (args && PyTuple_GET_SIZE(args) > 0)
1145     {
1146         PyErr_SetString(PyExc_TypeError,
1147                         "_p_deactivate takes no positional arguments");
1148         return NULL;
1149     }
1150     if (keywords)
1151     {
1152         int size = PyDict_Size(keywords);
1153         force = PyDict_GetItemString(keywords, "force");
1154         if (force)
1155             size--;
1156         if (size) {
1157             PyErr_SetString(PyExc_TypeError,
1158                         "_p_deactivate only accepts keyword arg force");
1159             return NULL;
1160         }
1161     }
1162 
1163     if (self->jar && self->oid)
1164     {
1165         ghostify = self->state == cPersistent_UPTODATE_STATE;
1166         if (!ghostify && force) {
1167             if (PyObject_IsTrue(force))
1168             ghostify = 1;
1169             if (PyErr_Occurred())
1170             return NULL;
1171         }
1172         if (ghostify) {
1173             if (_bucket_clear(self) < 0)
1174             return NULL;
1175             PER_GHOSTIFY(self);
1176         }
1177     }
1178     Py_INCREF(Py_None);
1179     return Py_None;
1180 }
1181 #endif
1182 
1183 static PyObject *
bucket_clear(Bucket * self,PyObject * args)1184 bucket_clear(Bucket *self, PyObject *args)
1185 {
1186     PER_USE_OR_RETURN(self, NULL);
1187 
1188     if (self->len)
1189     {
1190         if (_bucket_clear(self) < 0)
1191         return NULL;
1192         if (PER_CHANGED(self) < 0)
1193         goto err;
1194     }
1195     PER_UNUSE(self);
1196     Py_INCREF(Py_None);
1197     return Py_None;
1198 
1199 err:
1200     PER_UNUSE(self);
1201     return NULL;
1202 }
1203 
1204 /*
1205  * Return:
1206  *
1207  * For a set bucket (self->values is NULL), a one-tuple or two-tuple.  The
1208  * first element is a tuple of keys, of length self->len.  The second element
1209  * is the next bucket, present if and only if next is non-NULL:
1210  *
1211  *     (
1212  *          (keys[0], keys[1], ..., keys[len-1]),
1213  *          <self->next iff non-NULL>
1214  *     )
1215  *
1216  * For a mapping bucket (self->values is not NULL), a one-tuple or two-tuple.
1217  * The first element is a tuple interleaving keys and values, of length
1218  * 2 * self->len.  The second element is the next bucket, present iff next is
1219  * non-NULL:
1220  *
1221  *     (
1222  *          (keys[0], values[0], keys[1], values[1], ...,
1223  *                               keys[len-1], values[len-1]),
1224  *          <self->next iff non-NULL>
1225  *     )
1226  */
1227 static PyObject *
bucket_getstate(Bucket * self)1228 bucket_getstate(Bucket *self)
1229 {
1230     PyObject *o = NULL, *items = NULL, *state;
1231     int i, len, l;
1232 
1233     PER_USE_OR_RETURN(self, NULL);
1234 
1235     len = self->len;
1236 
1237     if (self->values) /* Bucket */
1238     {
1239         items = PyTuple_New(len * 2);
1240         if (items == NULL)
1241             goto err;
1242         for (i = 0, l = 0; i < len; i++) {
1243             COPY_KEY_TO_OBJECT(o, self->keys[i]);
1244             if (o == NULL)
1245             goto err;
1246             PyTuple_SET_ITEM(items, l, o);
1247             l++;
1248 
1249             COPY_VALUE_TO_OBJECT(o, self->values[i]);
1250             if (o == NULL)
1251             goto err;
1252             PyTuple_SET_ITEM(items, l, o);
1253             l++;
1254         }
1255     }
1256     else /* Set */
1257     {
1258         items = PyTuple_New(len);
1259         if (items == NULL)
1260             goto err;
1261         for (i = 0; i < len; i++) {
1262             COPY_KEY_TO_OBJECT(o, self->keys[i]);
1263             if (o == NULL)
1264             goto err;
1265             PyTuple_SET_ITEM(items, i, o);
1266         }
1267     }
1268 
1269     if (self->next)
1270         state = Py_BuildValue("OO", items, self->next);
1271     else
1272         state = Py_BuildValue("(O)", items);
1273     Py_DECREF(items);
1274 
1275     PER_UNUSE(self);
1276     return state;
1277 
1278 err:
1279     PER_UNUSE(self);
1280     Py_XDECREF(items);
1281     return NULL;
1282 }
1283 
1284 static int
_bucket_setstate(Bucket * self,PyObject * state)1285 _bucket_setstate(Bucket *self, PyObject *state)
1286 {
1287     PyObject *k, *v, *items;
1288     Bucket *next = NULL;
1289     int i, l, len, copied=1;
1290     KEY_TYPE *keys;
1291     VALUE_TYPE *values;
1292 
1293     if (!PyArg_ParseTuple(state, "O|O:__setstate__", &items, &next))
1294         return -1;
1295 
1296     if (!PyTuple_Check(items)) {
1297         PyErr_SetString(PyExc_TypeError,
1298                         "tuple required for first state element");
1299         return -1;
1300     }
1301 
1302     len = PyTuple_Size(items);
1303     ASSERT(len >= 0, "_bucket_setstate: items tuple has negative size", -1);
1304     len /= 2;
1305 
1306     for (i = self->len; --i >= 0; ) {
1307         DECREF_KEY(self->keys[i]);
1308         DECREF_VALUE(self->values[i]);
1309     }
1310     self->len = 0;
1311 
1312     if (self->next) {
1313         Py_DECREF(self->next);
1314         self->next = NULL;
1315     }
1316 
1317     if (len > self->size) {
1318         keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE)*len);
1319         if (keys == NULL)
1320             return -1;
1321         values = BTree_Realloc(self->values, sizeof(VALUE_TYPE)*len);
1322         if (values == NULL)
1323             return -1;
1324         self->keys = keys;
1325         self->values = values;
1326         self->size = len;
1327     }
1328 
1329     for (i=0, l=0; i < len; i++) {
1330         k = PyTuple_GET_ITEM(items, l);
1331         l++;
1332         v = PyTuple_GET_ITEM(items, l);
1333         l++;
1334 
1335         COPY_KEY_FROM_ARG(self->keys[i], k, copied);
1336         if (!copied)
1337             return -1;
1338         COPY_VALUE_FROM_ARG(self->values[i], v, copied);
1339         if (!copied)
1340             return -1;
1341         INCREF_KEY(self->keys[i]);
1342         INCREF_VALUE(self->values[i]);
1343     }
1344 
1345     self->len = len;
1346 
1347     if (next) {
1348         self->next = next;
1349         Py_INCREF(next);
1350     }
1351 
1352     return 0;
1353 }
1354 
1355 static PyObject *
bucket_setstate(Bucket * self,PyObject * state)1356 bucket_setstate(Bucket *self, PyObject *state)
1357 {
1358     int r;
1359 
1360     PER_PREVENT_DEACTIVATION(self);
1361     r = _bucket_setstate(self, state);
1362     PER_UNUSE(self);
1363 
1364     if (r < 0)
1365         return NULL;
1366     Py_INCREF(Py_None);
1367     return Py_None;
1368 }
1369 
1370 static PyObject *
bucket_sub(PyObject * self,PyObject * other)1371 bucket_sub(PyObject *self, PyObject *other)
1372 {
1373     PyObject *args = Py_BuildValue("OO", self, other);
1374     return difference_m(NULL, args);
1375 }
1376 
1377 static PyObject *
bucket_or(PyObject * self,PyObject * other)1378 bucket_or(PyObject *self, PyObject *other)
1379 {
1380     PyObject *args = Py_BuildValue("OO", self, other);
1381     return union_m(NULL, args);
1382 }
1383 
1384 static PyObject *
bucket_and(PyObject * self,PyObject * other)1385 bucket_and(PyObject *self, PyObject *other)
1386 {
1387     PyObject *args = Py_BuildValue("OO", self, other);
1388     return intersection_m(NULL, args);
1389 }
1390 
1391 static PyObject *
bucket_setdefault(Bucket * self,PyObject * args)1392 bucket_setdefault(Bucket *self, PyObject *args)
1393 {
1394     PyObject *key;
1395     PyObject *failobj; /* default */
1396     PyObject *value;   /* return value */
1397     int dummy_changed; /* in order to call _bucket_set */
1398 
1399     if (! PyArg_UnpackTuple(args, "setdefault", 2, 2, &key, &failobj))
1400         return NULL;
1401 
1402     value = _bucket_get(self, key, 0);
1403     if (value != NULL)
1404         return value;
1405 
1406     /* The key isn't in the bucket.  If that's not due to a KeyError exception,
1407      * pass back the unexpected exception.
1408      */
1409     if (! BTree_ShouldSuppressKeyError())
1410         return NULL;
1411     PyErr_Clear();
1412 
1413     /* Associate `key` with `failobj` in the bucket, and return `failobj`. */
1414     value = failobj;
1415     if (_bucket_set(self, key, failobj, 0, 0, &dummy_changed) < 0)
1416         value = NULL;
1417     Py_XINCREF(value);
1418     return value;
1419 }
1420 
1421 
1422 /* forward declaration */
1423 static int
1424 Bucket_length(Bucket *self);
1425 
1426 static PyObject *
bucket_pop(Bucket * self,PyObject * args)1427 bucket_pop(Bucket *self, PyObject *args)
1428 {
1429     PyObject *key;
1430     PyObject *failobj = NULL; /* default */
1431     PyObject *value;          /* return value */
1432     int dummy_changed;        /* in order to call _bucket_set */
1433 
1434     if (! PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj))
1435         return NULL;
1436 
1437     value = _bucket_get(self, key, 0);
1438     if (value != NULL) {
1439         /* Delete key and associated value. */
1440         if (_bucket_set(self, key, NULL, 0, 0, &dummy_changed) < 0) {
1441         Py_DECREF(value);
1442         return NULL;
1443         }
1444         return value;
1445     }
1446 
1447     /* The key isn't in the bucket.  If that's not due to a KeyError exception,
1448      * pass back the unexpected exception.
1449      */
1450     if (! BTree_ShouldSuppressKeyError())
1451         return NULL;
1452 
1453     if (failobj != NULL) {
1454         /* Clear the KeyError and return the explicit default. */
1455         PyErr_Clear();
1456         Py_INCREF(failobj);
1457         return failobj;
1458     }
1459 
1460     /* No default given.  The only difference in this case is the error
1461      * message, which depends on whether the bucket is empty.
1462      */
1463     if (Bucket_length(self) == 0)
1464         PyErr_SetString(PyExc_KeyError, "pop(): Bucket is empty");
1465     return NULL;
1466 }
1467 
1468 static PyObject*
bucket_popitem(Bucket * self,PyObject * args)1469 bucket_popitem(Bucket* self, PyObject* args)
1470 {
1471     PyObject* key = NULL;
1472     PyObject* pop_args = NULL;
1473     PyObject* result_val = NULL;
1474     PyObject* result = NULL;
1475 
1476     if (PyTuple_Size(args) != 0) {
1477         PyErr_SetString(PyExc_TypeError, "popitem(): Takes no arguments.");
1478         return NULL;
1479     }
1480 
1481     key = Bucket_minKey(self, args); /* reuse existing empty tuple. */
1482     if (!key) {
1483         PyErr_Clear();
1484         PyErr_SetString(PyExc_KeyError, "popitem(): empty bucket.");
1485         return NULL;
1486     }
1487 
1488     pop_args = PyTuple_Pack(1, key);
1489     if (pop_args) {
1490         result_val = bucket_pop(self, pop_args);
1491         Py_DECREF(pop_args);
1492         if (result_val) {
1493             result = PyTuple_Pack(2, key, result_val);
1494             Py_DECREF(result_val);
1495         }
1496     }
1497 
1498     Py_DECREF(key);
1499     return result;
1500 }
1501 
1502 
1503 /* Search bucket self for key.  This is the sq_contains slot of the
1504  * PySequenceMethods.
1505  *
1506  * Return:
1507  *     -1     error
1508  *      0     not found
1509  *      1     found
1510  */
1511 static int
bucket_contains(Bucket * self,PyObject * key)1512 bucket_contains(Bucket *self, PyObject *key)
1513 {
1514     PyObject *asobj = _bucket_get(self, key, 1);
1515     int result = -1;
1516 
1517     if (asobj != NULL) {
1518         result = INT_AS_LONG(asobj) ? 1 : 0;
1519         Py_DECREF(asobj);
1520     }
1521     else if (BTree_ShouldSuppressKeyError()) {
1522         PyErr_Clear();
1523         result = 0;
1524     }
1525     return result;
1526 }
1527 
1528 static PyObject *
bucket_has_key(Bucket * self,PyObject * key)1529 bucket_has_key(Bucket *self, PyObject *key)
1530 {
1531     int result = -1;
1532     result = bucket_contains(self, key);
1533     if (result == -1) {
1534         return NULL;
1535     }
1536 
1537     if (result)
1538         Py_RETURN_TRUE;
1539     Py_RETURN_FALSE;
1540 }
1541 
1542 /*
1543 ** bucket_getm
1544 **
1545 */
1546 static PyObject *
bucket_getm(Bucket * self,PyObject * args)1547 bucket_getm(Bucket *self, PyObject *args)
1548 {
1549     PyObject *key, *d=Py_None, *r;
1550 
1551     if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
1552         return NULL;
1553     r = _bucket_get(self, key, 0);
1554     if (r)
1555         return r;
1556     if (PyErr_ExceptionMatches(PyExc_TypeError)) {
1557         PyErr_Clear();
1558         PyErr_SetObject(PyExc_KeyError, key);
1559     }
1560     if (!BTree_ShouldSuppressKeyError())
1561         return NULL;
1562     PyErr_Clear();
1563     Py_INCREF(d);
1564     return d;
1565 }
1566 
1567 /**************************************************************************/
1568 /* Iterator support. */
1569 
1570 /* A helper to build all the iterators for Buckets and Sets.
1571  * If args is NULL, the iterator spans the entire structure.  Else it's an
1572  * argument tuple, with optional low and high arguments.
1573  * kind is 'k', 'v' or 'i'.
1574  * Returns a BTreeIter object, or NULL if error.
1575  */
1576 static PyObject *
buildBucketIter(Bucket * self,PyObject * args,PyObject * kw,char kind)1577 buildBucketIter(Bucket *self, PyObject *args, PyObject *kw, char kind)
1578 {
1579     BTreeItems *items;
1580     int lowoffset, highoffset;
1581     BTreeIter *result = NULL;
1582 
1583     PER_USE_OR_RETURN(self, NULL);
1584     if (Bucket_rangeSearch(self, args, kw, &lowoffset, &highoffset) < 0)
1585         goto Done;
1586 
1587     items = (BTreeItems *)newBTreeItems(kind, self, lowoffset,
1588                                         self, highoffset);
1589     if (items == NULL)
1590         goto Done;
1591 
1592     result = BTreeIter_new(items);      /* win or lose, we're done */
1593     Py_DECREF(items);
1594 
1595 Done:
1596     PER_UNUSE(self);
1597     return (PyObject *)result;
1598 }
1599 
1600 /* The implementation of iter(Bucket_or_Set); the Bucket tp_iter slot. */
1601 static PyObject *
Bucket_getiter(Bucket * self)1602 Bucket_getiter(Bucket *self)
1603 {
1604     return buildBucketIter(self, NULL, NULL, 'k');
1605 }
1606 
1607 /* The implementation of Bucket.iterkeys(). */
1608 static PyObject *
Bucket_iterkeys(Bucket * self,PyObject * args,PyObject * kw)1609 Bucket_iterkeys(Bucket *self, PyObject *args, PyObject *kw)
1610 {
1611     return buildBucketIter(self, args, kw, 'k');
1612 }
1613 
1614 /* The implementation of Bucket.itervalues(). */
1615 static PyObject *
Bucket_itervalues(Bucket * self,PyObject * args,PyObject * kw)1616 Bucket_itervalues(Bucket *self, PyObject *args, PyObject *kw)
1617 {
1618     return buildBucketIter(self, args, kw, 'v');
1619 }
1620 
1621 /* The implementation of Bucket.iteritems(). */
1622 static PyObject *
Bucket_iteritems(Bucket * self,PyObject * args,PyObject * kw)1623 Bucket_iteritems(Bucket *self, PyObject *args, PyObject *kw)
1624 {
1625     return buildBucketIter(self, args, kw, 'i');
1626 }
1627 
1628 /* End of iterator support. */
1629 
1630 #ifdef PERSISTENT
1631 static PyObject *merge_error(int p1, int p2, int p3, int reason);
1632 static PyObject *bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3);
1633 
1634 static PyObject *
_bucket__p_resolveConflict(PyObject * ob_type,PyObject * s[3])1635 _bucket__p_resolveConflict(PyObject *ob_type, PyObject *s[3])
1636 {
1637     PyObject *result = NULL;    /* guilty until proved innocent */
1638     Bucket *b[3] = {NULL, NULL, NULL};
1639     PyObject *meth = NULL;
1640     PyObject *a = NULL;
1641     int i;
1642 
1643     for (i = 0; i < 3; i++) {
1644         PyObject *r;
1645 
1646         b[i] = (Bucket*)PyObject_CallObject((PyObject *)ob_type, NULL);
1647         if (b[i] == NULL)
1648             goto Done;
1649         if (s[i] == Py_None) /* None is equivalent to empty, for BTrees */
1650             continue;
1651         meth = PyObject_GetAttr((PyObject *)b[i], __setstate___str);
1652         if (meth == NULL)
1653             goto Done;
1654         a = PyTuple_New(1);
1655         if (a == NULL)
1656             goto Done;
1657         PyTuple_SET_ITEM(a, 0, s[i]);
1658         Py_INCREF(s[i]);
1659         r = PyObject_CallObject(meth, a);  /* b[i].__setstate__(s[i]) */
1660         if (r == NULL)
1661             goto Done;
1662         Py_DECREF(r);
1663         Py_DECREF(a);
1664         Py_DECREF(meth);
1665         a = meth = NULL;
1666     }
1667 
1668     if (b[0]->next != b[1]->next || b[0]->next != b[2]->next)
1669         merge_error(-1, -1, -1, 0);
1670     else
1671         result = bucket_merge(b[0], b[1], b[2]);
1672 
1673 Done:
1674     Py_XDECREF(meth);
1675     Py_XDECREF(a);
1676     Py_XDECREF(b[0]);
1677     Py_XDECREF(b[1]);
1678     Py_XDECREF(b[2]);
1679 
1680     return result;
1681 }
1682 
1683 static PyObject *
bucket__p_resolveConflict(Bucket * self,PyObject * args)1684 bucket__p_resolveConflict(Bucket *self, PyObject *args)
1685 {
1686     PyObject *s[3];
1687 
1688     if (!PyArg_ParseTuple(args, "OOO", &s[0], &s[1], &s[2]))
1689         return NULL;
1690 
1691     return _bucket__p_resolveConflict((PyObject *)Py_TYPE(self), s);
1692 }
1693 #endif
1694 
1695 /* Caution:  Even though the _next attribute is read-only, a program could
1696    do arbitrary damage to the btree internals.  For example, it could call
1697    clear() on a bucket inside a BTree.
1698 
1699    We need to decide if the convenience for inspecting BTrees is worth
1700    the risk.
1701 */
1702 
1703 static struct PyMemberDef Bucket_members[] = {
1704     {"_next", T_OBJECT, offsetof(Bucket, next)},
1705     {NULL}
1706 };
1707 
1708 static struct PyMethodDef Bucket_methods[] = {
1709     {"__getstate__", (PyCFunction) bucket_getstate, METH_NOARGS,
1710      "__getstate__() -- Return the picklable state of the object"},
1711 
1712     {"__setstate__", (PyCFunction) bucket_setstate, METH_O,
1713      "__setstate__() -- Set the state of the object"},
1714 
1715     {"keys", (PyCFunction) bucket_keys, METH_VARARGS | METH_KEYWORDS,
1716      "keys([min, max]) -- Return the keys"},
1717 
1718     {"has_key", (PyCFunction) bucket_has_key, METH_O,
1719      "has_key(key) -- Test whether the bucket contains the given key"},
1720 
1721     {"clear", (PyCFunction) bucket_clear, METH_VARARGS,
1722      "clear() -- Remove all of the items from the bucket"},
1723 
1724     {"update", (PyCFunction) Mapping_update, METH_O,
1725      "update(collection) -- Add the items from the given collection"},
1726 
1727     {"maxKey", (PyCFunction) Bucket_maxKey, METH_VARARGS,
1728      "maxKey([key]) -- Find the maximum key\n\n"
1729      "If an argument is given, find the maximum <= the argument"},
1730 
1731     {"minKey", (PyCFunction) Bucket_minKey, METH_VARARGS,
1732      "minKey([key]) -- Find the minimum key\n\n"
1733      "If an argument is given, find the minimum >= the argument"},
1734 
1735     {"values", (PyCFunction) bucket_values, METH_VARARGS | METH_KEYWORDS,
1736      "values([min, max]) -- Return the values"},
1737 
1738     {"items", (PyCFunction) bucket_items, METH_VARARGS | METH_KEYWORDS,
1739      "items([min, max])) -- Return the items"},
1740 
1741     {"byValue", (PyCFunction) bucket_byValue, METH_O,
1742      "byValue(min) -- "
1743      "Return value-keys with values >= min and reverse sorted by values"},
1744 
1745     {"get", (PyCFunction) bucket_getm, METH_VARARGS,
1746      "get(key[,default]) -- Look up a value\n\n"
1747      "Return the default (or None) if the key is not found."},
1748 
1749     {"setdefault", (PyCFunction) bucket_setdefault, METH_VARARGS,
1750      "D.setdefault(k, d) -> D.get(k, d), also set D[k]=d if k not in D.\n\n"
1751      "Return the value like get() except that if key is missing, d is both\n"
1752      "returned and inserted into the bucket as the value of k."},
1753 
1754     {"pop", (PyCFunction) bucket_pop, METH_VARARGS,
1755      "D.pop(k[, d]) -> v, remove key and return the corresponding value.\n\n"
1756      "If key is not found, d is returned if given, otherwise KeyError\n"
1757      "is raised."},
1758 
1759     {"popitem", (PyCFunction)bucket_popitem, METH_VARARGS,
1760      "D.popitem() -> (k, v), remove and return some (key, value) pair\n"
1761      "as a 2-tuple; but raise KeyError if D is empty."},
1762 
1763     {"iterkeys", (PyCFunction) Bucket_iterkeys, METH_VARARGS | METH_KEYWORDS,
1764      "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
1765 
1766     {"itervalues",
1767      (PyCFunction) Bucket_itervalues, METH_VARARGS | METH_KEYWORDS,
1768      "B.itervalues([min[,max]]) -> an iterator over the values of B"},
1769 
1770     {"iteritems", (PyCFunction) Bucket_iteritems, METH_VARARGS | METH_KEYWORDS,
1771      "B.iteritems([min[,max]]) -> an iterator over the (key, value) "
1772      "items of B"},
1773 
1774 #ifdef EXTRA_BUCKET_METHODS
1775     EXTRA_BUCKET_METHODS
1776 #endif
1777 
1778 #ifdef PERSISTENT
1779     {"_p_resolveConflict",
1780      (PyCFunction) bucket__p_resolveConflict, METH_VARARGS,
1781      "_p_resolveConflict() -- Reinitialize from a newly created copy"},
1782 
1783     {"_p_deactivate",
1784      (PyCFunction) bucket__p_deactivate, METH_VARARGS | METH_KEYWORDS,
1785      "_p_deactivate() -- Reinitialize from a newly created copy"},
1786 #endif
1787     {NULL, NULL}
1788 };
1789 
1790 static int
Bucket_init(PyObject * self,PyObject * args,PyObject * kwds)1791 Bucket_init(PyObject *self, PyObject *args, PyObject *kwds)
1792 {
1793     PyObject *v = NULL;
1794 
1795     if (!PyArg_ParseTuple(args, "|O:" MOD_NAME_PREFIX "Bucket", &v))
1796         return -1;
1797 
1798     if (v)
1799         return update_from_seq(self, v);
1800     else
1801         return 0;
1802 }
1803 
1804 static void
bucket_dealloc(Bucket * self)1805 bucket_dealloc(Bucket *self)
1806 {
1807     PyObject_GC_UnTrack((PyObject *)self);
1808     if (self->state != cPersistent_GHOST_STATE) {
1809         _bucket_clear(self);
1810     }
1811 
1812     cPersistenceCAPI->pertype->tp_dealloc((PyObject *)self);
1813 }
1814 
1815 static int
bucket_traverse(Bucket * self,visitproc visit,void * arg)1816 bucket_traverse(Bucket *self, visitproc visit, void *arg)
1817 {
1818     int err = 0;
1819     int i, len;
1820 
1821 #define VISIT(SLOT)                             \
1822   if (SLOT) {                                   \
1823     err = visit((PyObject *)(SLOT), arg);       \
1824     if (err)                                    \
1825       goto Done;                                \
1826   }
1827 
1828     /* Call our base type's traverse function.  Because buckets are
1829      * subclasses of Peristent, there must be one.
1830      */
1831     err = cPersistenceCAPI->pertype->tp_traverse((PyObject *)self, visit, arg);
1832     if (err)
1833         goto Done;
1834 
1835     /* If this is registered with the persistence system, cleaning up cycles
1836      * is the database's problem.  It would be horrid to unghostify buckets
1837      * here just to chase pointers every time gc runs.
1838      */
1839     if (self->state == cPersistent_GHOST_STATE)
1840         goto Done;
1841 
1842     len = self->len;
1843     /* if neither keys nor values are PyObject*, "i" is otherwise
1844        unreferenced and we get a nuisance compiler wng */
1845     (void)i;
1846     (void)len;
1847 #ifdef KEY_TYPE_IS_PYOBJECT
1848     /* Keys are Python objects so need to be traversed. */
1849     for (i = 0; i < len; i++)
1850         VISIT(self->keys[i]);
1851 #endif
1852 
1853 #ifdef VALUE_TYPE_IS_PYOBJECT
1854     if (self->values != NULL) {
1855         /* self->values exists (this is a mapping bucket, not a set bucket),
1856         * and are Python objects, so need to be traversed. */
1857         for (i = 0; i < len; i++)
1858             VISIT(self->values[i]);
1859     }
1860 #endif
1861 
1862     VISIT(self->next);
1863 
1864 Done:
1865     return err;
1866 
1867 #undef VISIT
1868 }
1869 
1870 static int
bucket_tp_clear(Bucket * self)1871 bucket_tp_clear(Bucket *self)
1872 {
1873     if (self->state != cPersistent_GHOST_STATE)
1874         _bucket_clear(self);
1875     return 0;
1876 }
1877 
1878 /* Code to access Bucket objects as mappings */
1879 static int
Bucket_length(Bucket * self)1880 Bucket_length( Bucket *self)
1881 {
1882     int r;
1883     UNLESS (PER_USE(self))
1884         return -1;
1885     r = self->len;
1886     PER_UNUSE(self);
1887     return r;
1888 }
1889 
1890 static PyMappingMethods Bucket_as_mapping = {
1891     (lenfunc)Bucket_length,             /*mp_length*/
1892     (binaryfunc)bucket_getitem,         /*mp_subscript*/
1893     (objobjargproc)bucket_setitem,      /*mp_ass_subscript*/
1894 };
1895 
1896 static PySequenceMethods Bucket_as_sequence = {
1897     (lenfunc)0,                         /* sq_length */
1898     (binaryfunc)0,                      /* sq_concat */
1899     (ssizeargfunc)0,                    /* sq_repeat */
1900     (ssizeargfunc)0,                    /* sq_item */
1901     (ssizessizeargfunc)0,               /* sq_slice */
1902     (ssizeobjargproc)0,                 /* sq_ass_item */
1903     (ssizessizeobjargproc)0,            /* sq_ass_slice */
1904     (objobjproc)bucket_contains,        /* sq_contains */
1905     0,                                  /* sq_inplace_concat */
1906     0,                                  /* sq_inplace_repeat */
1907 };
1908 
1909 static PyNumberMethods Bucket_as_number = {
1910      (binaryfunc)0,                     /* nb_add */
1911      bucket_sub,                        /* nb_subtract */
1912      (binaryfunc)0,                     /* nb_multiply */
1913 #ifndef PY3K
1914      0,                                 /* nb_divide */
1915 #endif
1916      (binaryfunc)0,                     /* nb_remainder */
1917      (binaryfunc)0,                     /* nb_divmod */
1918      (ternaryfunc)0,                    /* nb_power */
1919      (unaryfunc)0,                      /* nb_negative */
1920      (unaryfunc)0,                      /* nb_positive */
1921      (unaryfunc)0,                      /* nb_absolute */
1922      (inquiry)0,                        /* nb_bool */
1923      (unaryfunc)0,                      /* nb_invert */
1924      (binaryfunc)0,                     /* nb_lshift */
1925      (binaryfunc)0,                     /* nb_rshift */
1926      bucket_and,                        /* nb_and */
1927      (binaryfunc)0,                     /* nb_xor */
1928      bucket_or,                         /* nb_or */
1929 };
1930 
1931 
1932 static PyObject *
bucket_repr(Bucket * self)1933 bucket_repr(Bucket *self)
1934 {
1935     PyObject *i, *r;
1936 #ifndef PY3K
1937     char repr[10000];
1938     int rv;
1939 #endif
1940 
1941     i = bucket_items(self, NULL, NULL);
1942     if (!i)
1943     {
1944         return NULL;
1945     }
1946 #ifdef PY3K
1947     r = PyUnicode_FromFormat("%s(%R)", Py_TYPE(self)->tp_name, i);
1948     Py_DECREF(i);
1949     return r;
1950 #else
1951     r = PyObject_Repr(i);
1952     Py_DECREF(i);
1953     if (!r)
1954     {
1955         return NULL;
1956     }
1957     rv = PyOS_snprintf(repr, sizeof(repr),
1958                        "%s(%s)", Py_TYPE(self)->tp_name,
1959                        PyBytes_AS_STRING(r));
1960     if (rv > 0 && (size_t)rv < sizeof(repr))
1961     {
1962         Py_DECREF(r);
1963         return PyBytes_FromStringAndSize(repr, strlen(repr));
1964     }
1965     else
1966     {
1967         /* The static buffer wasn't big enough */
1968         int size;
1969         PyObject *s;
1970         /* 3 for the parens and the null byte */
1971         size = strlen(Py_TYPE(self)->tp_name) + PyBytes_GET_SIZE(r) + 3;
1972         s = PyBytes_FromStringAndSize(NULL, size);
1973         if (!s) {
1974             Py_DECREF(r);
1975             return r;
1976         }
1977         PyOS_snprintf(PyBytes_AS_STRING(s), size,
1978                     "%s(%s)", Py_TYPE(self)->tp_name, PyBytes_AS_STRING(r));
1979         Py_DECREF(r);
1980         return s;
1981     }
1982 #endif
1983 }
1984 
1985 static PyTypeObject BucketType = {
1986     PyVarObject_HEAD_INIT(NULL, 0)
1987     MODULE_NAME MOD_NAME_PREFIX "Bucket",   /* tp_name */
1988     sizeof(Bucket),                         /* tp_basicsize */
1989     0,                                      /* tp_itemsize */
1990     (destructor)bucket_dealloc,             /* tp_dealloc */
1991     0,                                      /* tp_print */
1992     0,                                      /* tp_getattr */
1993     0,                                      /* tp_setattr */
1994     0,                                      /* tp_compare */
1995     (reprfunc)bucket_repr,                  /* tp_repr */
1996     &Bucket_as_number,                      /* tp_as_number */
1997     &Bucket_as_sequence,                    /* tp_as_sequence */
1998     &Bucket_as_mapping,                     /* tp_as_mapping */
1999     0,                                      /* tp_hash */
2000     0,                                      /* tp_call */
2001     0,                                      /* tp_str */
2002     0,                                      /* tp_getattro */
2003     0,                                      /* tp_setattro */
2004     0,                                      /* tp_as_buffer */
2005 #ifndef PY3K
2006     Py_TPFLAGS_CHECKTYPES |
2007 #endif
2008     Py_TPFLAGS_DEFAULT |
2009     Py_TPFLAGS_HAVE_GC |
2010     Py_TPFLAGS_BASETYPE,                    /* tp_flags */
2011     0,                                      /* tp_doc */
2012     (traverseproc)bucket_traverse,          /* tp_traverse */
2013     (inquiry)bucket_tp_clear,               /* tp_clear */
2014     0,                                      /* tp_richcompare */
2015     0,                                      /* tp_weaklistoffset */
2016     (getiterfunc)Bucket_getiter,            /* tp_iter */
2017     0,                                      /* tp_iternext */
2018     Bucket_methods,                         /* tp_methods */
2019     Bucket_members,                         /* tp_members */
2020     0,                                      /* tp_getset */
2021     0,                                      /* tp_base */
2022     0,                                      /* tp_dict */
2023     0,                                      /* tp_descr_get */
2024     0,                                      /* tp_descr_set */
2025     0,                                      /* tp_dictoffset */
2026     Bucket_init,                            /* tp_init */
2027     0,                                      /* tp_alloc */
2028     0, /*PyType_GenericNew,*/               /* tp_new */
2029 };
2030 
2031 static int
nextBucket(SetIteration * i)2032 nextBucket(SetIteration *i)
2033 {
2034     if (i->position >= 0)
2035     {
2036         UNLESS(PER_USE(BUCKET(i->set)))
2037             return -1;
2038 
2039         if (i->position)
2040         {
2041           DECREF_KEY(i->key);
2042           DECREF_VALUE(i->value);
2043         }
2044 
2045         if (i->position < BUCKET(i->set)->len)
2046         {
2047           COPY_KEY(i->key, BUCKET(i->set)->keys[i->position]);
2048           INCREF_KEY(i->key);
2049           COPY_VALUE(i->value, BUCKET(i->set)->values[i->position]);
2050           INCREF_VALUE(i->value);
2051           i->position ++;
2052         }
2053         else
2054         {
2055           i->position = -1;
2056           PER_ACCESSED(BUCKET(i->set));
2057         }
2058 
2059         PER_ALLOW_DEACTIVATION(BUCKET(i->set));
2060     }
2061 
2062     return 0;
2063 }
2064