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