Commit b08f8e50 authored by Jim Fulton's avatar Jim Fulton

Updated indentation.

parent ec66d629
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE FOR A PARTICULAR PURPOSE
****************************************************************************/ ****************************************************************************/
#define BUCKETTEMPLATE_C "$Id$\n" #define BUCKETTEMPLATE_C "$Id$\n"
...@@ -38,15 +38,15 @@ ...@@ -38,15 +38,15 @@
int _i; \ int _i; \
int _cmp = 1; \ int _cmp = 1; \
for (_i = _hi >> 1; _lo < _hi; _i = (_lo + _hi) >> 1) { \ for (_i = _hi >> 1; _lo < _hi; _i = (_lo + _hi) >> 1) { \
TEST_KEY_SET_OR(_cmp, (SELF)->keys[_i], (KEY)) \ TEST_KEY_SET_OR(_cmp, (SELF)->keys[_i], (KEY)) \
ONERROR; \ ONERROR; \
if (_cmp < 0) _lo = _i + 1; \ if (_cmp < 0) _lo = _i + 1; \
else if (_cmp == 0) break; \ else if (_cmp == 0) break; \
else _hi = _i; \ else _hi = _i; \
} \ } \
(INDEX) = _i; \ (INDEX) = _i; \
(ABSENT) = _cmp; \ (ABSENT) = _cmp; \
} }
/* /*
** _bucket_get ** _bucket_get
...@@ -75,30 +75,30 @@ ...@@ -75,30 +75,30 @@
static PyObject * static PyObject *
_bucket_get(Bucket *self, PyObject *keyarg, int has_key) _bucket_get(Bucket *self, PyObject *keyarg, int has_key)
{ {
int i, cmp; int i, cmp;
KEY_TYPE key; KEY_TYPE key;
PyObject *r = NULL; PyObject *r = NULL;
int copied = 1; int copied = 1;
COPY_KEY_FROM_ARG(key, keyarg, copied); COPY_KEY_FROM_ARG(key, keyarg, copied);
UNLESS (copied) return NULL; UNLESS (copied) return NULL;
UNLESS (PER_USE(self)) return NULL; UNLESS (PER_USE(self)) return NULL;
BUCKET_SEARCH(i, cmp, self, key, goto Done); BUCKET_SEARCH(i, cmp, self, key, goto Done);
if (has_key) if (has_key)
r = PyInt_FromLong(cmp ? 0 : has_key); r = PyInt_FromLong(cmp ? 0 : has_key);
else { else {
if (cmp == 0) { if (cmp == 0) {
COPY_VALUE_TO_OBJECT(r, self->values[i]); COPY_VALUE_TO_OBJECT(r, self->values[i]);
}
else
PyErr_SetObject(PyExc_KeyError, keyarg);
} }
else
PyErr_SetObject(PyExc_KeyError, keyarg);
}
Done: Done:
PER_UNUSE(self); PER_UNUSE(self);
return r; return r;
} }
...@@ -126,45 +126,45 @@ bucket_getitem(Bucket *self, PyObject *key) ...@@ -126,45 +126,45 @@ bucket_getitem(Bucket *self, PyObject *key)
static int static int
Bucket_grow(Bucket *self, int newsize, int noval) Bucket_grow(Bucket *self, int newsize, int noval)
{ {
KEY_TYPE *keys; KEY_TYPE *keys;
VALUE_TYPE *values; VALUE_TYPE *values;
if (self->size) { if (self->size) {
if (newsize < 0) if (newsize < 0)
newsize = self->size * 2; newsize = self->size * 2;
if (newsize < 0) /* int overflow */ if (newsize < 0) /* int overflow */
goto Overflow; goto Overflow;
UNLESS (keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE) * newsize)) UNLESS (keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE) * newsize))
return -1; return -1;
UNLESS (noval) { UNLESS (noval) {
values = BTree_Realloc(self->values, sizeof(VALUE_TYPE) * newsize); values = BTree_Realloc(self->values, sizeof(VALUE_TYPE) * newsize);
if (values == NULL) { if (values == NULL) {
free(keys); free(keys);
return -1; return -1;
} }
self->values = values; self->values = values;
}
self->keys = keys;
} }
else { self->keys = keys;
if (newsize < 0) }
newsize = MIN_BUCKET_ALLOC; else {
UNLESS (self->keys = BTree_Malloc(sizeof(KEY_TYPE) * newsize)) if (newsize < 0)
return -1; newsize = MIN_BUCKET_ALLOC;
UNLESS (noval) { UNLESS (self->keys = BTree_Malloc(sizeof(KEY_TYPE) * newsize))
self->values = BTree_Malloc(sizeof(VALUE_TYPE) * newsize); return -1;
if (self->values == NULL) { UNLESS (noval) {
free(self->keys); self->values = BTree_Malloc(sizeof(VALUE_TYPE) * newsize);
self->keys = NULL; if (self->values == NULL) {
return -1; free(self->keys);
} self->keys = NULL;
} return -1;
}
} }
self->size = newsize; }
return 0; self->size = newsize;
return 0;
Overflow: Overflow:
PyErr_NoMemory(); PyErr_NoMemory();
return -1; return -1;
} }
...@@ -213,54 +213,54 @@ static int ...@@ -213,54 +213,54 @@ static int
bucket_append(Bucket *self, Bucket *from, int i, int n, bucket_append(Bucket *self, Bucket *from, int i, int n,
int copyValues, int overallocate) int copyValues, int overallocate)
{ {
int newlen; int newlen;
assert(self && from && self != from); assert(self && from && self != from);
assert(i >= 0); assert(i >= 0);
assert(n > 0); assert(n > 0);
assert(i+n <= from->len); assert(i+n <= from->len);
/* Make room. */ /* Make room. */
newlen = self->len + n; newlen = self->len + n;
if (newlen > self->size) { if (newlen > self->size) {
int newsize = newlen; int newsize = newlen;
if (overallocate) /* boost by 25% -- pretty arbitrary */ if (overallocate) /* boost by 25% -- pretty arbitrary */
newsize += newsize >> 2; newsize += newsize >> 2;
if (Bucket_grow(self, newsize, ! copyValues) < 0) if (Bucket_grow(self, newsize, ! copyValues) < 0)
return -1; return -1;
} }
assert(newlen <= self->size); assert(newlen <= self->size);
/* Copy stuff. */ /* Copy stuff. */
memcpy(self->keys + self->len, from->keys + i, n * sizeof(KEY_TYPE)); memcpy(self->keys + self->len, from->keys + i, n * sizeof(KEY_TYPE));
if (copyValues) { if (copyValues) {
assert(self->values); assert(self->values);
assert(from->values); assert(from->values);
memcpy(self->values + self->len, from->values + i, memcpy(self->values + self->len, from->values + i,
n * sizeof(VALUE_TYPE)); n * sizeof(VALUE_TYPE));
} }
self->len = newlen; self->len = newlen;
/* Bump refcounts. */ /* Bump refcounts. */
#ifdef KEY_TYPE_IS_PYOBJECT #ifdef KEY_TYPE_IS_PYOBJECT
{ {
int j; int j;
PyObject **p = from->keys + i; PyObject **p = from->keys + i;
for (j = 0; j < n; ++j, ++p) { for (j = 0; j < n; ++j, ++p) {
Py_INCREF(*p); Py_INCREF(*p);
}
} }
}
#endif #endif
#ifdef VALUE_TYPE_IS_PYOBJECT #ifdef VALUE_TYPE_IS_PYOBJECT
if (copyValues) { if (copyValues) {
int j; int j;
PyObject **p = from->values + i; PyObject **p = from->values + i;
for (j = 0; j < n; ++j, ++p) { for (j = 0; j < n; ++j, ++p) {
Py_INCREF(*p); Py_INCREF(*p);
}
} }
}
#endif #endif
return 0; return 0;
} }
#endif /* MULTI_INT_UNION */ #endif /* MULTI_INT_UNION */
...@@ -291,136 +291,136 @@ static int ...@@ -291,136 +291,136 @@ static int
_bucket_set(Bucket *self, PyObject *keyarg, PyObject *v, _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
int unique, int noval, int *changed) int unique, int noval, int *changed)
{ {
int i, cmp; int i, cmp;
KEY_TYPE key; KEY_TYPE key;
/* Subtle: there may or may not be a value. If there is, we need to /* Subtle: there may or may not be a value. If there is, we need to
* check its type early, so that in case of error we can get out before * check its type early, so that in case of error we can get out before
* mutating the bucket. But because value isn't used on all paths, if * mutating the bucket. But because value isn't used on all paths, if
* we don't initialize value then gcc gives a nuisance complaint that * we don't initialize value then gcc gives a nuisance complaint that
* value may be used initialized (it can't be, but gcc doesn't know * value may be used initialized (it can't be, but gcc doesn't know
* that). So we initialize it. However, VALUE_TYPE can be various types, * that). So we initialize it. However, VALUE_TYPE can be various types,
* including int, PyObject*, and char[6], so it's a puzzle to spell * including int, PyObject*, and char[6], so it's a puzzle to spell
* initialization. It so happens that {0} is a valid initializer for all * initialization. It so happens that {0} is a valid initializer for all
* these types. * these types.
*/ */
VALUE_TYPE value = {0}; /* squash nuisance warning */ VALUE_TYPE value = {0}; /* squash nuisance warning */
int result = -1; /* until proven innocent */ int result = -1; /* until proven innocent */
int copied = 1; int copied = 1;
COPY_KEY_FROM_ARG(key, keyarg, copied); COPY_KEY_FROM_ARG(key, keyarg, copied);
UNLESS(copied) return -1;
/* Copy the value early (if needed), so that in case of error a
* pile of bucket mutations don't need to be undone.
*/
if (v && !noval) {
COPY_VALUE_FROM_ARG(value, v, copied);
UNLESS(copied) return -1; UNLESS(copied) return -1;
}
/* Copy the value early (if needed), so that in case of error a UNLESS (PER_USE(self)) return -1;
* pile of bucket mutations don't need to be undone.
*/
if (v && !noval) {
COPY_VALUE_FROM_ARG(value, v, copied);
UNLESS(copied) return -1;
}
UNLESS (PER_USE(self)) return -1; BUCKET_SEARCH(i, cmp, self, key, goto Done);
if (cmp == 0) {
/* The key exists, at index i. */
BUCKET_SEARCH(i, cmp, self, key, goto Done); if (v) {
if (cmp == 0) { /* The key exists at index i, and there's a new value.
/* The key exists, at index i. */ * If unique, we're not supposed to replace it. If noval, or this
* is a set bucket (self->values is NULL), there's nothing to do.
if (v) { */
/* The key exists at index i, and there's a new value. if (unique || noval || self->values == NULL) {
* If unique, we're not supposed to replace it. If noval, or this result = 0;
* is a set bucket (self->values is NULL), there's nothing to do. goto Done;
*/ }
if (unique || noval || self->values == NULL) {
result = 0; /* The key exists at index i, and we need to replace the value. */
goto Done;
}
/* The key exists at index i, and we need to replace the value. */
#ifdef VALUE_SAME #ifdef VALUE_SAME
/* short-circuit if no change */ /* short-circuit if no change */
if (VALUE_SAME(self->values[i], value)) { if (VALUE_SAME(self->values[i], value)) {
result = 0; result = 0;
goto Done; goto Done;
} }
#endif #endif
if (changed) if (changed)
*changed = 1; *changed = 1;
DECREF_VALUE(self->values[i]); DECREF_VALUE(self->values[i]);
COPY_VALUE(self->values[i], value); COPY_VALUE(self->values[i], value);
INCREF_VALUE(self->values[i]); INCREF_VALUE(self->values[i]);
if (PER_CHANGED(self) >= 0) if (PER_CHANGED(self) >= 0)
result = 0; result = 0;
goto Done; goto Done;
} }
/* The key exists at index i, and should be deleted. */
DECREF_KEY(self->keys[i]);
self->len--;
if (i < self->len)
memmove(self->keys + i, self->keys + i+1,
sizeof(KEY_TYPE)*(self->len - i));
if (self->values) {
DECREF_VALUE(self->values[i]);
if (i < self->len)
memmove(self->values + i, self->values + i+1,
sizeof(VALUE_TYPE)*(self->len - i));
}
if (! self->len) { /* The key exists at index i, and should be deleted. */
self->size = 0; DECREF_KEY(self->keys[i]);
free(self->keys); self->len--;
self->keys = NULL; if (i < self->len)
if (self->values) { memmove(self->keys + i, self->keys + i+1,
free(self->values); sizeof(KEY_TYPE)*(self->len - i));
self->values = NULL;
}
}
if (changed) if (self->values) {
*changed = 1; DECREF_VALUE(self->values[i]);
if (PER_CHANGED(self) >= 0) if (i < self->len)
result = 1; memmove(self->values + i, self->values + i+1,
goto Done; sizeof(VALUE_TYPE)*(self->len - i));
} }
/* The key doesn't exist, and belongs at index i. */ if (! self->len) {
if (!v) { self->size = 0;
/* Can't delete a non-existent key. */ free(self->keys);
PyErr_SetObject(PyExc_KeyError, keyarg); self->keys = NULL;
goto Done; if (self->values) {
free(self->values);
self->values = NULL;
}
} }
/* The key doesn't exist and should be inserted at index i. */ if (changed)
if (self->len == self->size && Bucket_grow(self, -1, noval) < 0) *changed = 1;
goto Done; if (PER_CHANGED(self) >= 0)
result = 1;
goto Done;
}
if (self->len > i) { /* The key doesn't exist, and belongs at index i. */
memmove(self->keys + i + 1, self->keys + i, if (!v) {
sizeof(KEY_TYPE) * (self->len - i)); /* Can't delete a non-existent key. */
if (self->values) { PyErr_SetObject(PyExc_KeyError, keyarg);
memmove(self->values + i + 1, self->values + i, goto Done;
sizeof(VALUE_TYPE) * (self->len - i)); }
}
}
COPY_KEY(self->keys[i], key); /* The key doesn't exist and should be inserted at index i. */
INCREF_KEY(self->keys[i]); if (self->len == self->size && Bucket_grow(self, -1, noval) < 0)
goto Done;
if (! noval) { if (self->len > i) {
COPY_VALUE(self->values[i], value); memmove(self->keys + i + 1, self->keys + i,
INCREF_VALUE(self->values[i]); sizeof(KEY_TYPE) * (self->len - i));
if (self->values) {
memmove(self->values + i + 1, self->values + i,
sizeof(VALUE_TYPE) * (self->len - i));
} }
}
self->len++; COPY_KEY(self->keys[i], key);
if (changed) INCREF_KEY(self->keys[i]);
*changed = 1;
if (PER_CHANGED(self) >= 0) if (! noval) {
result = 1; COPY_VALUE(self->values[i], value);
INCREF_VALUE(self->values[i]);
}
Done: self->len++;
PER_UNUSE(self); if (changed)
return result; *changed = 1;
if (PER_CHANGED(self) >= 0)
result = 1;
Done:
PER_UNUSE(self);
return result;
} }
/* /*
...@@ -438,9 +438,9 @@ Done: ...@@ -438,9 +438,9 @@ Done:
static int static int
bucket_setitem(Bucket *self, PyObject *key, PyObject *v) bucket_setitem(Bucket *self, PyObject *key, PyObject *v)
{ {
if (_bucket_set(self, key, v, 0, 0, 0) < 0) if (_bucket_set(self, key, v, 0, 0, 0) < 0)
return -1; return -1;
return 0; return 0;
} }
/** /**
...@@ -450,71 +450,71 @@ bucket_setitem(Bucket *self, PyObject *key, PyObject *v) ...@@ -450,71 +450,71 @@ bucket_setitem(Bucket *self, PyObject *key, PyObject *v)
static int static int
update_from_seq(PyObject *map, PyObject *seq) update_from_seq(PyObject *map, PyObject *seq)
{ {
PyObject *iter, *o, *k, *v; PyObject *iter, *o, *k, *v;
int err = -1; int err = -1;
/* One path creates a new seq object. The other path has an /* One path creates a new seq object. The other path has an
INCREF of the seq argument. So seq must always be DECREFed on INCREF of the seq argument. So seq must always be DECREFed on
the way out. the way out.
*/ */
/* Use items() if it's not a sequence. Alas, PySequence_Check() /* Use items() if it's not a sequence. Alas, PySequence_Check()
* returns true for a PeristentMapping or PersistentDict, and we * returns true for a PeristentMapping or PersistentDict, and we
* want to use items() in those cases too. * want to use items() in those cases too.
*/ */
if (!PySequence_Check(seq) || /* or it "looks like a dict" */ if (!PySequence_Check(seq) || /* or it "looks like a dict" */
PyObject_HasAttrString(seq, "iteritems")) { PyObject_HasAttrString(seq, "iteritems")) {
PyObject *items; PyObject *items;
items = PyObject_GetAttrString(seq, "items"); items = PyObject_GetAttrString(seq, "items");
if (items == NULL) if (items == NULL)
return -1; return -1;
seq = PyObject_CallObject(items, NULL); seq = PyObject_CallObject(items, NULL);
Py_DECREF(items); Py_DECREF(items);
if (seq == NULL) if (seq == NULL)
return -1; return -1;
} }
else else
Py_INCREF(seq); Py_INCREF(seq);
iter = PyObject_GetIter(seq); iter = PyObject_GetIter(seq);
if (iter == NULL) if (iter == NULL)
goto err; goto err;
while (1) { while (1) {
o = PyIter_Next(iter); o = PyIter_Next(iter);
if (o == NULL) { if (o == NULL) {
if (PyErr_Occurred()) if (PyErr_Occurred())
goto err; goto err;
else else
break; break;
} }
if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != 2) { if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != 2) {
Py_DECREF(o); Py_DECREF(o);
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"Sequence must contain 2-item tuples"); "Sequence must contain 2-item tuples");
goto err; goto err;
} }
k = PyTuple_GET_ITEM(o, 0); k = PyTuple_GET_ITEM(o, 0);
v = PyTuple_GET_ITEM(o, 1); v = PyTuple_GET_ITEM(o, 1);
if (PyObject_SetItem(map, k, v) < 0) { if (PyObject_SetItem(map, k, v) < 0) {
Py_DECREF(o); Py_DECREF(o);
goto err; goto err;
}
Py_DECREF(o);
} }
Py_DECREF(o);
}
err = 0; err = 0;
err: err:
Py_DECREF(iter); Py_DECREF(iter);
Py_DECREF(seq); Py_DECREF(seq);
return err; return err;
} }
static PyObject * static PyObject *
Mapping_update(PyObject *self, PyObject *seq) Mapping_update(PyObject *self, PyObject *seq)
{ {
if (update_from_seq(self, seq) < 0) if (update_from_seq(self, seq) < 0)
return NULL; return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
/* /*
...@@ -532,42 +532,42 @@ Mapping_update(PyObject *self, PyObject *seq) ...@@ -532,42 +532,42 @@ Mapping_update(PyObject *self, PyObject *seq)
static int static int
bucket_split(Bucket *self, int index, Bucket *next) bucket_split(Bucket *self, int index, Bucket *next)
{ {
int next_size; int next_size;
ASSERT(self->len > 1, "split of empty bucket", -1); ASSERT(self->len > 1, "split of empty bucket", -1);
if (index < 0 || index >= self->len) if (index < 0 || index >= self->len)
index = self->len / 2; index = self->len / 2;
next_size = self->len - index; next_size = self->len - index;
next->keys = BTree_Malloc(sizeof(KEY_TYPE) * next_size); next->keys = BTree_Malloc(sizeof(KEY_TYPE) * next_size);
if (!next->keys) if (!next->keys)
return -1; return -1;
memcpy(next->keys, self->keys + index, sizeof(KEY_TYPE) * next_size); memcpy(next->keys, self->keys + index, sizeof(KEY_TYPE) * next_size);
if (self->values) { if (self->values) {
next->values = BTree_Malloc(sizeof(VALUE_TYPE) * next_size); next->values = BTree_Malloc(sizeof(VALUE_TYPE) * next_size);
if (!next->values) { if (!next->values) {
free(next->keys); free(next->keys);
next->keys = NULL; next->keys = NULL;
return -1; return -1;
}
memcpy(next->values, self->values + index,
sizeof(VALUE_TYPE) * next_size);
} }
next->size = next_size; memcpy(next->values, self->values + index,
next->len = next_size; sizeof(VALUE_TYPE) * next_size);
self->len = index; }
next->size = next_size;
next->len = next_size;
self->len = index;
next->next = self->next; next->next = self->next;
Py_INCREF(next); Py_INCREF(next);
self->next = next; self->next = next;
if (PER_CHANGED(self) < 0) if (PER_CHANGED(self) < 0)
return -1; return -1;
return 0; return 0;
} }
/* Set self->next to self->next->next, i.e. unlink self's successor from /* Set self->next to self->next->next, i.e. unlink self's successor from
...@@ -580,106 +580,106 @@ bucket_split(Bucket *self, int index, Bucket *next) ...@@ -580,106 +580,106 @@ bucket_split(Bucket *self, int index, Bucket *next)
static int static int
Bucket_deleteNextBucket(Bucket *self) Bucket_deleteNextBucket(Bucket *self)
{ {
int result = -1; /* until proven innocent */ int result = -1; /* until proven innocent */
Bucket *successor; Bucket *successor;
PER_USE_OR_RETURN(self, -1); PER_USE_OR_RETURN(self, -1);
successor = self->next; successor = self->next;
if (successor) { if (successor) {
Bucket *next; Bucket *next;
/* Before: self -> successor -> next /* Before: self -> successor -> next
* After: self --------------> next * After: self --------------> next
*/ */
UNLESS (PER_USE(successor)) goto Done; UNLESS (PER_USE(successor)) goto Done;
next = successor->next; next = successor->next;
PER_UNUSE(successor); PER_UNUSE(successor);
Py_XINCREF(next); /* it may be NULL, of course */ Py_XINCREF(next); /* it may be NULL, of course */
self->next = next; self->next = next;
Py_DECREF(successor); Py_DECREF(successor);
if (PER_CHANGED(self) < 0) if (PER_CHANGED(self) < 0)
goto Done; goto Done;
} }
result = 0; result = 0;
Done: Done:
PER_UNUSE(self); PER_UNUSE(self);
return result; return result;
} }
/* /*
Bucket_findRangeEnd -- Find the index of a range endpoint Bucket_findRangeEnd -- Find the index of a range endpoint
(possibly) contained in a bucket. (possibly) contained in a bucket.
Arguments: self The bucket Arguments: self The bucket
keyarg The key to match against keyarg The key to match against
low Boolean; true for low end of range, false for high low Boolean; true for low end of range, false for high
exclude_equal Boolean; if true, don't accept an exact match, exclude_equal Boolean; if true, don't accept an exact match,
and if there is one then move right if low and and if there is one then move right if low and
left if !low. left if !low.
offset The output offset offset The output offset
If low true, *offset <- index of the smallest item >= key, If low true, *offset <- index of the smallest item >= key,
if low false the index of the largest item <= key. In either case, if there if low false the index of the largest item <= key. In either case, if there
is no such index, *offset is left alone and 0 is returned. is no such index, *offset is left alone and 0 is returned.
Return: Return:
0 No suitable index exists; *offset has not been changed 0 No suitable index exists; *offset has not been changed
1 The correct index was stored into *offset 1 The correct index was stored into *offset
-1 Error -1 Error
Example: Suppose the keys are [2, 4], and exclude_equal is false. Searching Example: Suppose the keys are [2, 4], and exclude_equal is false. Searching
for 2 sets *offset to 0 and returns 1 regardless of low. Searching for 4 for 2 sets *offset to 0 and returns 1 regardless of low. Searching for 4
sets *offset to 1 and returns 1 regardless of low. sets *offset to 1 and returns 1 regardless of low.
Searching for 1: Searching for 1:
If low true, sets *offset to 0, returns 1. If low true, sets *offset to 0, returns 1.
If low false, returns 0. If low false, returns 0.
Searching for 3: Searching for 3:
If low true, sets *offset to 1, returns 1. If low true, sets *offset to 1, returns 1.
If low false, sets *offset to 0, returns 1. If low false, sets *offset to 0, returns 1.
Searching for 5: Searching for 5:
If low true, returns 0. If low true, returns 0.
If low false, sets *offset to 1, returns 1. If low false, sets *offset to 1, returns 1.
The 1, 3 and 5 examples are the same when exclude_equal is true. The 1, 3 and 5 examples are the same when exclude_equal is true.
*/ */
static int static int
Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int exclude_equal, Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int exclude_equal,
int *offset) int *offset)
{ {
int i, cmp; int i, cmp;
int result = -1; /* until proven innocent */ int result = -1; /* until proven innocent */
KEY_TYPE key; KEY_TYPE key;
int copied = 1; int copied = 1;
COPY_KEY_FROM_ARG(key, keyarg, copied); COPY_KEY_FROM_ARG(key, keyarg, copied);
UNLESS (copied) return -1; UNLESS (copied) return -1;
UNLESS (PER_USE(self)) return -1; UNLESS (PER_USE(self)) return -1;
BUCKET_SEARCH(i, cmp, self, key, goto Done); BUCKET_SEARCH(i, cmp, self, key, goto Done);
if (cmp == 0) { if (cmp == 0) {
/* exact match at index i */ /* exact match at index i */
if (exclude_equal) { if (exclude_equal) {
/* but we don't want an exact match */ /* but we don't want an exact match */
if (low) if (low)
++i; ++i;
else else
--i;
}
}
/* Else keys[i-1] < key < keys[i], picturing infinities at OOB indices,
* and i has the smallest item > key, which is correct for low.
*/
else if (! low)
/* i-1 has the largest item < key (unless i-1 is 0OB) */
--i; --i;
}
result = 0 <= i && i < self->len; }
if (result) /* Else keys[i-1] < key < keys[i], picturing infinities at OOB indices,
*offset = i; * and i has the smallest item > key, which is correct for low.
*/
Done: else if (! low)
/* i-1 has the largest item < key (unless i-1 is 0OB) */
--i;
result = 0 <= i && i < self->len;
if (result)
*offset = i;
Done:
PER_UNUSE(self); PER_UNUSE(self);
return result; return result;
} }
...@@ -717,8 +717,8 @@ Bucket_maxminKey(Bucket *self, PyObject *args, int min) ...@@ -717,8 +717,8 @@ Bucket_maxminKey(Bucket *self, PyObject *args, int min)
empty: empty:
PyErr_SetString(PyExc_ValueError, PyErr_SetString(PyExc_ValueError,
empty_bucket ? "empty bucket" : empty_bucket ? "empty bucket" :
"no key satisfies the conditions"); "no key satisfies the conditions");
PER_UNUSE(self); PER_UNUSE(self);
return NULL; return NULL;
} }
...@@ -737,67 +737,67 @@ Bucket_maxKey(Bucket *self, PyObject *args) ...@@ -737,67 +737,67 @@ Bucket_maxKey(Bucket *self, PyObject *args)
static int static int
Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw, Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
int *low, int *high) int *low, int *high)
{ {
PyObject *min = Py_None; PyObject *min = Py_None;
PyObject *max = Py_None; PyObject *max = Py_None;
int excludemin = 0; int excludemin = 0;
int excludemax = 0; int excludemax = 0;
int rc; int rc;
if (args) { if (args) {
if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords, if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords,
&min, &min,
&max, &max,
&excludemin, &excludemin,
&excludemax)) &excludemax))
return -1; return -1;
} }
UNLESS (self->len) goto empty; UNLESS (self->len) goto empty;
/* Find the low range */ /* Find the low range */
if (min != Py_None) { if (min != Py_None) {
rc = Bucket_findRangeEnd(self, min, 1, excludemin, low); rc = Bucket_findRangeEnd(self, min, 1, excludemin, low);
if (rc < 0) if (rc < 0)
return -1; return -1;
if (rc == 0) if (rc == 0)
goto empty; goto empty;
} }
else { else {
*low = 0; *low = 0;
if (excludemin) { if (excludemin) {
if (self->len < 2) if (self->len < 2)
goto empty; goto empty;
++*low; ++*low;
}
} }
}
/* Find the high range */ /* Find the high range */
if (max != Py_None) { if (max != Py_None) {
rc = Bucket_findRangeEnd(self, max, 0, excludemax, high); rc = Bucket_findRangeEnd(self, max, 0, excludemax, high);
if (rc < 0) if (rc < 0)
return -1; return -1;
if (rc == 0) if (rc == 0)
goto empty; goto empty;
} }
else { else {
*high = self->len - 1; *high = self->len - 1;
if (excludemax) { if (excludemax) {
if (self->len < 2) if (self->len < 2)
goto empty; goto empty;
--*high; --*high;
}
} }
}
/* If min < max to begin with, it's quite possible that low > high now. */ /* If min < max to begin with, it's quite possible that low > high now. */
if (*low <= *high) if (*low <= *high)
return 0; return 0;
empty: empty:
*low = 0; *low = 0;
*high = -1; *high = -1;
return 0; return 0;
} }
/* /*
...@@ -819,16 +819,16 @@ bucket_keys(Bucket *self, PyObject *args, PyObject *kw) ...@@ -819,16 +819,16 @@ bucket_keys(Bucket *self, PyObject *args, PyObject *kw)
PER_USE_OR_RETURN(self, NULL); PER_USE_OR_RETURN(self, NULL);
if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0) if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
goto err; goto err;
r = PyList_New(high-low+1); r = PyList_New(high-low+1);
if (r == NULL) if (r == NULL)
goto err; goto err;
for (i=low; i <= high; i++) { for (i=low; i <= high; i++) {
COPY_KEY_TO_OBJECT(key, self->keys[i]); COPY_KEY_TO_OBJECT(key, self->keys[i]);
if (PyList_SetItem(r, i-low , key) < 0) if (PyList_SetItem(r, i-low , key) < 0)
goto err; goto err;
} }
PER_UNUSE(self); PER_UNUSE(self);
...@@ -992,84 +992,84 @@ bucket_byValue(Bucket *self, PyObject *omin) ...@@ -992,84 +992,84 @@ bucket_byValue(Bucket *self, PyObject *omin)
static int static int
_bucket_clear(Bucket *self) _bucket_clear(Bucket *self)
{ {
const int len = self->len; const int len = self->len;
/* Don't declare i at this level. If neither keys nor values are /* Don't declare i at this level. If neither keys nor values are
* PyObject*, i won't be referenced, and you'll get a nuisance compiler * PyObject*, i won't be referenced, and you'll get a nuisance compiler
* wng for declaring it here. * wng for declaring it here.
*/ */
self->len = self->size = 0; self->len = self->size = 0;
if (self->next) { if (self->next) {
Py_DECREF(self->next); Py_DECREF(self->next);
self->next = NULL; self->next = NULL;
} }
/* Silence compiler warning about unused variable len for the case /* Silence compiler warning about unused variable len for the case
when neither key nor value is an object, i.e. II. */ when neither key nor value is an object, i.e. II. */
(void)len; (void)len;
if (self->keys) { if (self->keys) {
#ifdef KEY_TYPE_IS_PYOBJECT #ifdef KEY_TYPE_IS_PYOBJECT
int i; int i;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
DECREF_KEY(self->keys[i]); DECREF_KEY(self->keys[i]);
#endif #endif
free(self->keys); free(self->keys);
self->keys = NULL; self->keys = NULL;
} }
if (self->values) { if (self->values) {
#ifdef VALUE_TYPE_IS_PYOBJECT #ifdef VALUE_TYPE_IS_PYOBJECT
int i; int i;
for (i = 0; i < len; ++i) for (i = 0; i < len; ++i)
DECREF_VALUE(self->values[i]); DECREF_VALUE(self->values[i]);
#endif #endif
free(self->values); free(self->values);
self->values = NULL; self->values = NULL;
} }
return 0; return 0;
} }
#ifdef PERSISTENT #ifdef PERSISTENT
static PyObject * static PyObject *
bucket__p_deactivate(Bucket *self, PyObject *args, PyObject *keywords) bucket__p_deactivate(Bucket *self, PyObject *args, PyObject *keywords)
{ {
int ghostify = 1; int ghostify = 1;
PyObject *force = NULL; PyObject *force = NULL;
if (args && PyTuple_GET_SIZE(args) > 0) { if (args && PyTuple_GET_SIZE(args) > 0) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"_p_deactivate takes not positional arguments"); "_p_deactivate takes no positional arguments");
return NULL; return NULL;
} }
if (keywords) { if (keywords) {
int size = PyDict_Size(keywords); int size = PyDict_Size(keywords);
force = PyDict_GetItemString(keywords, "force"); force = PyDict_GetItemString(keywords, "force");
if (force) if (force)
size--; size--;
if (size) { if (size) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"_p_deactivate only accepts keyword arg force"); "_p_deactivate only accepts keyword arg force");
return NULL; return NULL;
}
} }
}
if (self->jar && self->oid) { if (self->jar && self->oid) {
ghostify = self->state == cPersistent_UPTODATE_STATE; ghostify = self->state == cPersistent_UPTODATE_STATE;
if (!ghostify && force) { if (!ghostify && force) {
if (PyObject_IsTrue(force)) if (PyObject_IsTrue(force))
ghostify = 1; ghostify = 1;
if (PyErr_Occurred()) if (PyErr_Occurred())
return NULL; return NULL;
} }
if (ghostify) { if (ghostify) {
if (_bucket_clear(self) < 0) if (_bucket_clear(self) < 0)
return NULL; return NULL;
PER_GHOSTIFY(self); PER_GHOSTIFY(self);
}
} }
Py_INCREF(Py_None); }
return Py_None; Py_INCREF(Py_None);
return Py_None;
} }
#endif #endif
...@@ -1079,16 +1079,16 @@ bucket_clear(Bucket *self, PyObject *args) ...@@ -1079,16 +1079,16 @@ bucket_clear(Bucket *self, PyObject *args)
PER_USE_OR_RETURN(self, NULL); PER_USE_OR_RETURN(self, NULL);
if (self->len) { if (self->len) {
if (_bucket_clear(self) < 0) if (_bucket_clear(self) < 0)
return NULL; return NULL;
if (PER_CHANGED(self) < 0) if (PER_CHANGED(self) < 0)
goto err; goto err;
} }
PER_UNUSE(self); PER_UNUSE(self);
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
err: err:
PER_UNUSE(self); PER_UNUSE(self);
return NULL; return NULL;
} }
...@@ -1119,178 +1119,178 @@ err: ...@@ -1119,178 +1119,178 @@ err:
static PyObject * static PyObject *
bucket_getstate(Bucket *self) bucket_getstate(Bucket *self)
{ {
PyObject *o = NULL, *items = NULL, *state; PyObject *o = NULL, *items = NULL, *state;
int i, len, l; int i, len, l;
PER_USE_OR_RETURN(self, NULL); PER_USE_OR_RETURN(self, NULL);
len = self->len; len = self->len;
if (self->values) { /* Bucket */ if (self->values) { /* Bucket */
items = PyTuple_New(len * 2); items = PyTuple_New(len * 2);
if (items == NULL) if (items == NULL)
goto err; goto err;
for (i = 0, l = 0; i < len; i++) { for (i = 0, l = 0; i < len; i++) {
COPY_KEY_TO_OBJECT(o, self->keys[i]); COPY_KEY_TO_OBJECT(o, self->keys[i]);
if (o == NULL) if (o == NULL)
goto err; goto err;
PyTuple_SET_ITEM(items, l, o); PyTuple_SET_ITEM(items, l, o);
l++; l++;
COPY_VALUE_TO_OBJECT(o, self->values[i]); COPY_VALUE_TO_OBJECT(o, self->values[i]);
if (o == NULL) if (o == NULL)
goto err; goto err;
PyTuple_SET_ITEM(items, l, o); PyTuple_SET_ITEM(items, l, o);
l++; l++;
} }
} else { /* Set */ } else { /* Set */
items = PyTuple_New(len); items = PyTuple_New(len);
if (items == NULL) if (items == NULL)
goto err; goto err;
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
COPY_KEY_TO_OBJECT(o, self->keys[i]); COPY_KEY_TO_OBJECT(o, self->keys[i]);
if (o == NULL) if (o == NULL)
goto err; goto err;
PyTuple_SET_ITEM(items, i, o); PyTuple_SET_ITEM(items, i, o);
}
} }
}
if (self->next) if (self->next)
state = Py_BuildValue("OO", items, self->next); state = Py_BuildValue("OO", items, self->next);
else else
state = Py_BuildValue("(O)", items); state = Py_BuildValue("(O)", items);
Py_DECREF(items); Py_DECREF(items);
PER_UNUSE(self); PER_UNUSE(self);
return state; return state;
err: err:
PER_UNUSE(self); PER_UNUSE(self);
Py_XDECREF(items); Py_XDECREF(items);
return NULL; return NULL;
} }
static int static int
_bucket_setstate(Bucket *self, PyObject *state) _bucket_setstate(Bucket *self, PyObject *state)
{ {
PyObject *k, *v, *items; PyObject *k, *v, *items;
Bucket *next = NULL; Bucket *next = NULL;
int i, l, len, copied=1; int i, l, len, copied=1;
KEY_TYPE *keys; KEY_TYPE *keys;
VALUE_TYPE *values; VALUE_TYPE *values;
if (!PyArg_ParseTuple(state, "O|O:__setstate__", &items, &next)) if (!PyArg_ParseTuple(state, "O|O:__setstate__", &items, &next))
return -1; return -1;
if (!PyTuple_Check(items)) { if (!PyTuple_Check(items)) {
PyErr_SetString(PyExc_TypeError, PyErr_SetString(PyExc_TypeError,
"tuple required for first state element"); "tuple required for first state element");
return -1; return -1;
} }
len = PyTuple_Size(items); len = PyTuple_Size(items);
if (len < 0) if (len < 0)
return -1; return -1;
len /= 2; len /= 2;
for (i = self->len; --i >= 0; ) { for (i = self->len; --i >= 0; ) {
DECREF_KEY(self->keys[i]); DECREF_KEY(self->keys[i]);
DECREF_VALUE(self->values[i]); DECREF_VALUE(self->values[i]);
} }
self->len = 0; self->len = 0;
if (self->next) { if (self->next) {
Py_DECREF(self->next); Py_DECREF(self->next);
self->next = NULL; self->next = NULL;
} }
if (len > self->size) { if (len > self->size) {
keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE)*len); keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE)*len);
if (keys == NULL) if (keys == NULL)
return -1; return -1;
values = BTree_Realloc(self->values, sizeof(VALUE_TYPE)*len); values = BTree_Realloc(self->values, sizeof(VALUE_TYPE)*len);
if (values == NULL) if (values == NULL)
return -1; return -1;
self->keys = keys; self->keys = keys;
self->values = values; self->values = values;
self->size = len; self->size = len;
} }
for (i=0, l=0; i < len; i++) { for (i=0, l=0; i < len; i++) {
k = PyTuple_GET_ITEM(items, l); k = PyTuple_GET_ITEM(items, l);
l++; l++;
v = PyTuple_GET_ITEM(items, l); v = PyTuple_GET_ITEM(items, l);
l++; l++;
COPY_KEY_FROM_ARG(self->keys[i], k, copied); COPY_KEY_FROM_ARG(self->keys[i], k, copied);
if (!copied) if (!copied)
return -1; return -1;
COPY_VALUE_FROM_ARG(self->values[i], v, copied); COPY_VALUE_FROM_ARG(self->values[i], v, copied);
if (!copied) if (!copied)
return -1; return -1;
INCREF_KEY(self->keys[i]); INCREF_KEY(self->keys[i]);
INCREF_VALUE(self->values[i]); INCREF_VALUE(self->values[i]);
} }
self->len = len; self->len = len;
if (next) { if (next) {
self->next = next; self->next = next;
Py_INCREF(next); Py_INCREF(next);
} }
return 0; return 0;
} }
static PyObject * static PyObject *
bucket_setstate(Bucket *self, PyObject *state) bucket_setstate(Bucket *self, PyObject *state)
{ {
int r; int r;
PER_PREVENT_DEACTIVATION(self); PER_PREVENT_DEACTIVATION(self);
r = _bucket_setstate(self, state); r = _bucket_setstate(self, state);
PER_UNUSE(self); PER_UNUSE(self);
if (r < 0) if (r < 0)
return NULL; return NULL;
Py_INCREF(Py_None); Py_INCREF(Py_None);
return Py_None; return Py_None;
} }
static PyObject * static PyObject *
bucket_has_key(Bucket *self, PyObject *key) bucket_has_key(Bucket *self, PyObject *key)
{ {
return _bucket_get(self, key, 1); return _bucket_get(self, key, 1);
} }
static PyObject * static PyObject *
bucket_setdefault(Bucket *self, PyObject *args) bucket_setdefault(Bucket *self, PyObject *args)
{ {
PyObject *key; PyObject *key;
PyObject *failobj; /* default */ PyObject *failobj; /* default */
PyObject *value; /* return value */ PyObject *value; /* return value */
int dummy_changed; /* in order to call _bucket_set */ int dummy_changed; /* in order to call _bucket_set */
if (! PyArg_UnpackTuple(args, "setdefault", 2, 2, &key, &failobj))
return NULL;
value = _bucket_get(self, key, 0); if (! PyArg_UnpackTuple(args, "setdefault", 2, 2, &key, &failobj))
if (value != NULL) return NULL;
return value;
/* The key isn't in the bucket. If that's not due to a KeyError exception,
* pass back the unexpected exception.
*/
if (! PyErr_ExceptionMatches(PyExc_KeyError))
return NULL;
PyErr_Clear();
/* Associate `key` with `failobj` in the bucket, and return `failobj`. */ value = _bucket_get(self, key, 0);
value = failobj; if (value != NULL)
if (_bucket_set(self, key, failobj, 0, 0, &dummy_changed) < 0)
value = NULL;
Py_XINCREF(value);
return value; return value;
/* The key isn't in the bucket. If that's not due to a KeyError exception,
* pass back the unexpected exception.
*/
if (! PyErr_ExceptionMatches(PyExc_KeyError))
return NULL;
PyErr_Clear();
/* Associate `key` with `failobj` in the bucket, and return `failobj`. */
value = failobj;
if (_bucket_set(self, key, failobj, 0, 0, &dummy_changed) < 0)
value = NULL;
Py_XINCREF(value);
return value;
} }
...@@ -1301,44 +1301,44 @@ Bucket_length(Bucket *self); ...@@ -1301,44 +1301,44 @@ Bucket_length(Bucket *self);
static PyObject * static PyObject *
bucket_pop(Bucket *self, PyObject *args) bucket_pop(Bucket *self, PyObject *args)
{ {
PyObject *key; PyObject *key;
PyObject *failobj = NULL; /* default */ PyObject *failobj = NULL; /* default */
PyObject *value; /* return value */ PyObject *value; /* return value */
int dummy_changed; /* in order to call _bucket_set */ int dummy_changed; /* in order to call _bucket_set */
if (! PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj))
return NULL;
value = _bucket_get(self, key, 0);
if (value != NULL) {
/* Delete key and associated value. */
if (_bucket_set(self, key, NULL, 0, 0, &dummy_changed) < 0) {
Py_DECREF(value);
return NULL;
}
return value;
}
/* The key isn't in the bucket. If that's not due to a KeyError exception, if (! PyArg_UnpackTuple(args, "pop", 1, 2, &key, &failobj))
* pass back the unexpected exception. return NULL;
*/
if (! PyErr_ExceptionMatches(PyExc_KeyError))
return NULL;
if (failobj != NULL) { value = _bucket_get(self, key, 0);
/* Clear the KeyError and return the explicit default. */ if (value != NULL) {
PyErr_Clear(); /* Delete key and associated value. */
Py_INCREF(failobj); if (_bucket_set(self, key, NULL, 0, 0, &dummy_changed) < 0) {
return failobj; Py_DECREF(value);
return NULL;
} }
return value;
}
/* No default given. The only difference in this case is the error /* The key isn't in the bucket. If that's not due to a KeyError exception,
* message, which depends on whether the bucket is empty. * pass back the unexpected exception.
*/ */
if (Bucket_length(self) == 0) if (! PyErr_ExceptionMatches(PyExc_KeyError))
PyErr_SetString(PyExc_KeyError, "pop(): Bucket is empty");
return NULL; return NULL;
}
if (failobj != NULL) {
/* Clear the KeyError and return the explicit default. */
PyErr_Clear();
Py_INCREF(failobj);
return failobj;
}
/* No default given. The only difference in this case is the error
* message, which depends on whether the bucket is empty.
*/
if (Bucket_length(self) == 0)
PyErr_SetString(PyExc_KeyError, "pop(): Bucket is empty");
return NULL;
}
/* Search bucket self for key. This is the sq_contains slot of the /* Search bucket self for key. This is the sq_contains slot of the
* PySequenceMethods. * PySequenceMethods.
...@@ -1351,14 +1351,14 @@ bucket_pop(Bucket *self, PyObject *args) ...@@ -1351,14 +1351,14 @@ bucket_pop(Bucket *self, PyObject *args)
static int static int
bucket_contains(Bucket *self, PyObject *key) bucket_contains(Bucket *self, PyObject *key)
{ {
PyObject *asobj = _bucket_get(self, key, 1); PyObject *asobj = _bucket_get(self, key, 1);
int result = -1; int result = -1;
if (asobj != NULL) { if (asobj != NULL) {
result = PyInt_AsLong(asobj) ? 1 : 0; result = PyInt_AsLong(asobj) ? 1 : 0;
Py_DECREF(asobj); Py_DECREF(asobj);
} }
return result; return result;
} }
/* /*
...@@ -1368,18 +1368,18 @@ bucket_contains(Bucket *self, PyObject *key) ...@@ -1368,18 +1368,18 @@ bucket_contains(Bucket *self, PyObject *key)
static PyObject * static PyObject *
bucket_getm(Bucket *self, PyObject *args) bucket_getm(Bucket *self, PyObject *args)
{ {
PyObject *key, *d=Py_None, *r; PyObject *key, *d=Py_None, *r;
if (!PyArg_ParseTuple(args, "O|O:get", &key, &d)) if (!PyArg_ParseTuple(args, "O|O:get", &key, &d))
return NULL; return NULL;
r = _bucket_get(self, key, 0); r = _bucket_get(self, key, 0);
if (r) if (r)
return r; return r;
if (!PyErr_ExceptionMatches(PyExc_KeyError)) if (!PyErr_ExceptionMatches(PyExc_KeyError))
return NULL; return NULL;
PyErr_Clear(); PyErr_Clear();
Py_INCREF(d); Py_INCREF(d);
return d; return d;
} }
/**************************************************************************/ /**************************************************************************/
...@@ -1394,52 +1394,52 @@ bucket_getm(Bucket *self, PyObject *args) ...@@ -1394,52 +1394,52 @@ bucket_getm(Bucket *self, PyObject *args)
static PyObject * static PyObject *
buildBucketIter(Bucket *self, PyObject *args, PyObject *kw, char kind) buildBucketIter(Bucket *self, PyObject *args, PyObject *kw, char kind)
{ {
BTreeItems *items; BTreeItems *items;
int lowoffset, highoffset; int lowoffset, highoffset;
BTreeIter *result = NULL; BTreeIter *result = NULL;
PER_USE_OR_RETURN(self, NULL); PER_USE_OR_RETURN(self, NULL);
if (Bucket_rangeSearch(self, args, kw, &lowoffset, &highoffset) < 0) if (Bucket_rangeSearch(self, args, kw, &lowoffset, &highoffset) < 0)
goto Done; goto Done;
items = (BTreeItems *)newBTreeItems(kind, self, lowoffset, items = (BTreeItems *)newBTreeItems(kind, self, lowoffset,
self, highoffset); self, highoffset);
if (items == NULL) goto Done; if (items == NULL) goto Done;
result = BTreeIter_new(items); /* win or lose, we're done */ result = BTreeIter_new(items); /* win or lose, we're done */
Py_DECREF(items); Py_DECREF(items);
Done: Done:
PER_UNUSE(self); PER_UNUSE(self);
return (PyObject *)result; return (PyObject *)result;
} }
/* The implementation of iter(Bucket_or_Set); the Bucket tp_iter slot. */ /* The implementation of iter(Bucket_or_Set); the Bucket tp_iter slot. */
static PyObject * static PyObject *
Bucket_getiter(Bucket *self) Bucket_getiter(Bucket *self)
{ {
return buildBucketIter(self, NULL, NULL, 'k'); return buildBucketIter(self, NULL, NULL, 'k');
} }
/* The implementation of Bucket.iterkeys(). */ /* The implementation of Bucket.iterkeys(). */
static PyObject * static PyObject *
Bucket_iterkeys(Bucket *self, PyObject *args, PyObject *kw) Bucket_iterkeys(Bucket *self, PyObject *args, PyObject *kw)
{ {
return buildBucketIter(self, args, kw, 'k'); return buildBucketIter(self, args, kw, 'k');
} }
/* The implementation of Bucket.itervalues(). */ /* The implementation of Bucket.itervalues(). */
static PyObject * static PyObject *
Bucket_itervalues(Bucket *self, PyObject *args, PyObject *kw) Bucket_itervalues(Bucket *self, PyObject *args, PyObject *kw)
{ {
return buildBucketIter(self, args, kw, 'v'); return buildBucketIter(self, args, kw, 'v');
} }
/* The implementation of Bucket.iteritems(). */ /* The implementation of Bucket.iteritems(). */
static PyObject * static PyObject *
Bucket_iteritems(Bucket *self, PyObject *args, PyObject *kw) Bucket_iteritems(Bucket *self, PyObject *args, PyObject *kw)
{ {
return buildBucketIter(self, args, kw, 'i'); return buildBucketIter(self, args, kw, 'i');
} }
/* End of iterator support. */ /* End of iterator support. */
...@@ -1451,61 +1451,61 @@ static PyObject *bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3); ...@@ -1451,61 +1451,61 @@ static PyObject *bucket_merge(Bucket *s1, Bucket *s2, Bucket *s3);
static PyObject * static PyObject *
_bucket__p_resolveConflict(PyObject *ob_type, PyObject *s[3]) _bucket__p_resolveConflict(PyObject *ob_type, PyObject *s[3])
{ {
PyObject *result = NULL; /* guilty until proved innocent */ PyObject *result = NULL; /* guilty until proved innocent */
Bucket *b[3] = {NULL, NULL, NULL}; Bucket *b[3] = {NULL, NULL, NULL};
PyObject *meth = NULL; PyObject *meth = NULL;
PyObject *a = NULL; PyObject *a = NULL;
int i; int i;
for (i = 0; i < 3; i++) { for (i = 0; i < 3; i++) {
PyObject *r; PyObject *r;
b[i] = (Bucket*)PyObject_CallObject((PyObject *)ob_type, NULL); b[i] = (Bucket*)PyObject_CallObject((PyObject *)ob_type, NULL);
if (b[i] == NULL) if (b[i] == NULL)
goto Done; goto Done;
if (s[i] == Py_None) /* None is equivalent to empty, for BTrees */ if (s[i] == Py_None) /* None is equivalent to empty, for BTrees */
continue; continue;
meth = PyObject_GetAttr((PyObject *)b[i], __setstate___str); meth = PyObject_GetAttr((PyObject *)b[i], __setstate___str);
if (meth == NULL) if (meth == NULL)
goto Done; goto Done;
a = PyTuple_New(1); a = PyTuple_New(1);
if (a == NULL) if (a == NULL)
goto Done; goto Done;
PyTuple_SET_ITEM(a, 0, s[i]); PyTuple_SET_ITEM(a, 0, s[i]);
Py_INCREF(s[i]); Py_INCREF(s[i]);
r = PyObject_CallObject(meth, a); /* b[i].__setstate__(s[i]) */ r = PyObject_CallObject(meth, a); /* b[i].__setstate__(s[i]) */
if (r == NULL) if (r == NULL)
goto Done; goto Done;
Py_DECREF(r); Py_DECREF(r);
Py_DECREF(a); Py_DECREF(a);
Py_DECREF(meth); Py_DECREF(meth);
a = meth = NULL; a = meth = NULL;
} }
if (b[0]->next != b[1]->next || b[0]->next != b[2]->next) if (b[0]->next != b[1]->next || b[0]->next != b[2]->next)
merge_error(-1, -1, -1, 0); merge_error(-1, -1, -1, 0);
else else
result = bucket_merge(b[0], b[1], b[2]); result = bucket_merge(b[0], b[1], b[2]);
Done: Done:
Py_XDECREF(meth); Py_XDECREF(meth);
Py_XDECREF(a); Py_XDECREF(a);
Py_XDECREF(b[0]); Py_XDECREF(b[0]);
Py_XDECREF(b[1]); Py_XDECREF(b[1]);
Py_XDECREF(b[2]); Py_XDECREF(b[2]);
return result; return result;
} }
static PyObject * static PyObject *
bucket__p_resolveConflict(Bucket *self, PyObject *args) bucket__p_resolveConflict(Bucket *self, PyObject *args)
{ {
PyObject *s[3]; PyObject *s[3];
if (!PyArg_ParseTuple(args, "OOO", &s[0], &s[1], &s[2])) if (!PyArg_ParseTuple(args, "OOO", &s[0], &s[1], &s[2]))
return NULL; return NULL;
return _bucket__p_resolveConflict((PyObject *)self->ob_type, s); return _bucket__p_resolveConflict((PyObject *)self->ob_type, s);
} }
#endif #endif
...@@ -1518,157 +1518,157 @@ bucket__p_resolveConflict(Bucket *self, PyObject *args) ...@@ -1518,157 +1518,157 @@ bucket__p_resolveConflict(Bucket *self, PyObject *args)
*/ */
static struct PyMemberDef Bucket_members[] = { static struct PyMemberDef Bucket_members[] = {
{"_next", T_OBJECT, offsetof(Bucket, next)}, {"_next", T_OBJECT, offsetof(Bucket, next)},
{NULL} {NULL}
}; };
static struct PyMethodDef Bucket_methods[] = { static struct PyMethodDef Bucket_methods[] = {
{"__getstate__", (PyCFunction) bucket_getstate, METH_NOARGS, {"__getstate__", (PyCFunction) bucket_getstate, METH_NOARGS,
"__getstate__() -- Return the picklable state of the object"}, "__getstate__() -- Return the picklable state of the object"},
{"__setstate__", (PyCFunction) bucket_setstate, METH_O, {"__setstate__", (PyCFunction) bucket_setstate, METH_O,
"__setstate__() -- Set the state of the object"}, "__setstate__() -- Set the state of the object"},
{"keys", (PyCFunction) bucket_keys, METH_KEYWORDS, {"keys", (PyCFunction) bucket_keys, METH_KEYWORDS,
"keys([min, max]) -- Return the keys"}, "keys([min, max]) -- Return the keys"},
{"has_key", (PyCFunction) bucket_has_key, METH_O, {"has_key", (PyCFunction) bucket_has_key, METH_O,
"has_key(key) -- Test whether the bucket contains the given key"}, "has_key(key) -- Test whether the bucket contains the given key"},
{"clear", (PyCFunction) bucket_clear, METH_VARARGS, {"clear", (PyCFunction) bucket_clear, METH_VARARGS,
"clear() -- Remove all of the items from the bucket"}, "clear() -- Remove all of the items from the bucket"},
{"update", (PyCFunction) Mapping_update, METH_O, {"update", (PyCFunction) Mapping_update, METH_O,
"update(collection) -- Add the items from the given collection"}, "update(collection) -- Add the items from the given collection"},
{"maxKey", (PyCFunction) Bucket_maxKey, METH_VARARGS, {"maxKey", (PyCFunction) Bucket_maxKey, METH_VARARGS,
"maxKey([key]) -- Find the maximum key\n\n" "maxKey([key]) -- Find the maximum key\n\n"
"If an argument is given, find the maximum <= the argument"}, "If an argument is given, find the maximum <= the argument"},
{"minKey", (PyCFunction) Bucket_minKey, METH_VARARGS, {"minKey", (PyCFunction) Bucket_minKey, METH_VARARGS,
"minKey([key]) -- Find the minimum key\n\n" "minKey([key]) -- Find the minimum key\n\n"
"If an argument is given, find the minimum >= the argument"}, "If an argument is given, find the minimum >= the argument"},
{"values", (PyCFunction) bucket_values, METH_KEYWORDS, {"values", (PyCFunction) bucket_values, METH_KEYWORDS,
"values([min, max]) -- Return the values"}, "values([min, max]) -- Return the values"},
{"items", (PyCFunction) bucket_items, METH_KEYWORDS, {"items", (PyCFunction) bucket_items, METH_KEYWORDS,
"items([min, max])) -- Return the items"}, "items([min, max])) -- Return the items"},
{"byValue", (PyCFunction) bucket_byValue, METH_O, {"byValue", (PyCFunction) bucket_byValue, METH_O,
"byValue(min) -- " "byValue(min) -- "
"Return value-keys with values >= min and reverse sorted by values"}, "Return value-keys with values >= min and reverse sorted by values"},
{"get", (PyCFunction) bucket_getm, METH_VARARGS, {"get", (PyCFunction) bucket_getm, METH_VARARGS,
"get(key[,default]) -- Look up a value\n\n" "get(key[,default]) -- Look up a value\n\n"
"Return the default (or None) if the key is not found."}, "Return the default (or None) if the key is not found."},
{"setdefault", (PyCFunction) bucket_setdefault, METH_VARARGS, {"setdefault", (PyCFunction) bucket_setdefault, METH_VARARGS,
"D.setdefault(k, d) -> D.get(k, d), also set D[k]=d if k not in D.\n\n" "D.setdefault(k, d) -> D.get(k, d), also set D[k]=d if k not in D.\n\n"
"Return the value like get() except that if key is missing, d is both\n" "Return the value like get() except that if key is missing, d is both\n"
"returned and inserted into the bucket as the value of k."}, "returned and inserted into the bucket as the value of k."},
{"pop", (PyCFunction) bucket_pop, METH_VARARGS, {"pop", (PyCFunction) bucket_pop, METH_VARARGS,
"D.pop(k[, d]) -> v, remove key and return the corresponding value.\n\n" "D.pop(k[, d]) -> v, remove key and return the corresponding value.\n\n"
"If key is not found, d is returned if given, otherwise KeyError\n" "If key is not found, d is returned if given, otherwise KeyError\n"
"is raised."}, "is raised."},
{"iterkeys", (PyCFunction) Bucket_iterkeys, METH_KEYWORDS, {"iterkeys", (PyCFunction) Bucket_iterkeys, METH_KEYWORDS,
"B.iterkeys([min[,max]]) -> an iterator over the keys of B"}, "B.iterkeys([min[,max]]) -> an iterator over the keys of B"},
{"itervalues", (PyCFunction) Bucket_itervalues, METH_KEYWORDS, {"itervalues", (PyCFunction) Bucket_itervalues, METH_KEYWORDS,
"B.itervalues([min[,max]]) -> an iterator over the values of B"}, "B.itervalues([min[,max]]) -> an iterator over the values of B"},
{"iteritems", (PyCFunction) Bucket_iteritems, METH_KEYWORDS, {"iteritems", (PyCFunction) Bucket_iteritems, METH_KEYWORDS,
"B.iteritems([min[,max]]) -> an iterator over the (key, value) items of B"}, "B.iteritems([min[,max]]) -> an iterator over the (key, value) items of B"},
#ifdef EXTRA_BUCKET_METHODS #ifdef EXTRA_BUCKET_METHODS
EXTRA_BUCKET_METHODS EXTRA_BUCKET_METHODS
#endif #endif
#ifdef PERSISTENT #ifdef PERSISTENT
{"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict, {"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict,
METH_VARARGS, METH_VARARGS,
"_p_resolveConflict() -- Reinitialize from a newly created copy"}, "_p_resolveConflict() -- Reinitialize from a newly created copy"},
{"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_KEYWORDS, {"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_KEYWORDS,
"_p_deactivate() -- Reinitialize from a newly created copy"}, "_p_deactivate() -- Reinitialize from a newly created copy"},
#endif #endif
{NULL, NULL} {NULL, NULL}
}; };
static int static int
Bucket_init(PyObject *self, PyObject *args, PyObject *kwds) Bucket_init(PyObject *self, PyObject *args, PyObject *kwds)
{ {
PyObject *v = NULL; PyObject *v = NULL;
if (!PyArg_ParseTuple(args, "|O:" MOD_NAME_PREFIX "Bucket", &v)) if (!PyArg_ParseTuple(args, "|O:" MOD_NAME_PREFIX "Bucket", &v))
return -1; return -1;
if (v) if (v)
return update_from_seq(self, v); return update_from_seq(self, v);
else else
return 0; return 0;
} }
static void static void
bucket_dealloc(Bucket *self) bucket_dealloc(Bucket *self)
{ {
if (self->state != cPersistent_GHOST_STATE) if (self->state != cPersistent_GHOST_STATE)
_bucket_clear(self); _bucket_clear(self);
cPersistenceCAPI->pertype->tp_dealloc((PyObject *)self); cPersistenceCAPI->pertype->tp_dealloc((PyObject *)self);
} }
static int static int
bucket_traverse(Bucket *self, visitproc visit, void *arg) bucket_traverse(Bucket *self, visitproc visit, void *arg)
{ {
int err = 0; int err = 0;
int i, len; int i, len;
#define VISIT(SLOT) \ #define VISIT(SLOT) \
if (SLOT) { \ if (SLOT) { \
err = visit((PyObject *)(SLOT), arg); \ err = visit((PyObject *)(SLOT), arg); \
if (err) \ if (err) \
goto Done; \ goto Done; \
} }
/* Call our base type's traverse function. Because buckets are
* subclasses of Peristent, there must be one.
*/
err = cPersistenceCAPI->pertype->tp_traverse((PyObject *)self, visit, arg);
if (err)
goto Done;
/* If this is registered with the persistence system, cleaning up cycles
* is the database's problem. It would be horrid to unghostify buckets
* here just to chase pointers every time gc runs.
*/
if (self->state == cPersistent_GHOST_STATE)
goto Done;
len = self->len; /* Call our base type's traverse function. Because buckets are
(void)i; /* if neither keys nor values are PyObject*, "i" is otherwise * subclasses of Peristent, there must be one.
unreferenced and we get a nuisance compiler wng */ */
err = cPersistenceCAPI->pertype->tp_traverse((PyObject *)self, visit, arg);
if (err)
goto Done;
/* If this is registered with the persistence system, cleaning up cycles
* is the database's problem. It would be horrid to unghostify buckets
* here just to chase pointers every time gc runs.
*/
if (self->state == cPersistent_GHOST_STATE)
goto Done;
len = self->len;
(void)i; /* if neither keys nor values are PyObject*, "i" is otherwise
unreferenced and we get a nuisance compiler wng */
#ifdef KEY_TYPE_IS_PYOBJECT #ifdef KEY_TYPE_IS_PYOBJECT
/* Keys are Python objects so need to be traversed. */ /* Keys are Python objects so need to be traversed. */
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
VISIT(self->keys[i]); VISIT(self->keys[i]);
#endif #endif
#ifdef VALUE_TYPE_IS_PYOBJECT #ifdef VALUE_TYPE_IS_PYOBJECT
if (self->values != NULL) { if (self->values != NULL) {
/* self->values exists (this is a mapping bucket, not a set bucket), /* self->values exists (this is a mapping bucket, not a set bucket),
* and are Python objects, so need to be traversed. */ * and are Python objects, so need to be traversed. */
for (i = 0; i < len; i++) for (i = 0; i < len; i++)
VISIT(self->values[i]); VISIT(self->values[i]);
} }
#endif #endif
VISIT(self->next); VISIT(self->next);
Done: Done:
return err; return err;
#undef VISIT #undef VISIT
} }
...@@ -1676,20 +1676,20 @@ Done: ...@@ -1676,20 +1676,20 @@ Done:
static int static int
bucket_tp_clear(Bucket *self) bucket_tp_clear(Bucket *self)
{ {
if (self->state != cPersistent_GHOST_STATE) if (self->state != cPersistent_GHOST_STATE)
_bucket_clear(self); _bucket_clear(self);
return 0; return 0;
} }
/* Code to access Bucket objects as mappings */ /* Code to access Bucket objects as mappings */
static int static int
Bucket_length( Bucket *self) Bucket_length( Bucket *self)
{ {
int r; int r;
UNLESS (PER_USE(self)) return -1; UNLESS (PER_USE(self)) return -1;
r = self->len; r = self->len;
PER_UNUSE(self); PER_UNUSE(self);
return r; return r;
} }
static PyMappingMethods Bucket_as_mapping = { static PyMappingMethods Bucket_as_mapping = {
...@@ -1699,100 +1699,100 @@ static PyMappingMethods Bucket_as_mapping = { ...@@ -1699,100 +1699,100 @@ static PyMappingMethods Bucket_as_mapping = {
}; };
static PySequenceMethods Bucket_as_sequence = { static PySequenceMethods Bucket_as_sequence = {
(lenfunc)0, /* sq_length */ (lenfunc)0, /* sq_length */
(binaryfunc)0, /* sq_concat */ (binaryfunc)0, /* sq_concat */
(ssizeargfunc)0, /* sq_repeat */ (ssizeargfunc)0, /* sq_repeat */
(ssizeargfunc)0, /* sq_item */ (ssizeargfunc)0, /* sq_item */
(ssizessizeargfunc)0, /* sq_slice */ (ssizessizeargfunc)0, /* sq_slice */
(ssizeobjargproc)0, /* sq_ass_item */ (ssizeobjargproc)0, /* sq_ass_item */
(ssizessizeobjargproc)0, /* sq_ass_slice */ (ssizessizeobjargproc)0, /* sq_ass_slice */
(objobjproc)bucket_contains, /* sq_contains */ (objobjproc)bucket_contains, /* sq_contains */
0, /* sq_inplace_concat */ 0, /* sq_inplace_concat */
0, /* sq_inplace_repeat */ 0, /* sq_inplace_repeat */
}; };
static PyObject * static PyObject *
bucket_repr(Bucket *self) bucket_repr(Bucket *self)
{ {
PyObject *i, *r; PyObject *i, *r;
char repr[10000]; char repr[10000];
int rv; int rv;
i = bucket_items(self, NULL, NULL); i = bucket_items(self, NULL, NULL);
if (!i) if (!i)
return NULL; return NULL;
r = PyObject_Repr(i); r = PyObject_Repr(i);
Py_DECREF(i); Py_DECREF(i);
if (!r) { if (!r) {
return NULL; return NULL;
} }
rv = PyOS_snprintf(repr, sizeof(repr), rv = PyOS_snprintf(repr, sizeof(repr),
"%s(%s)", self->ob_type->tp_name, "%s(%s)", self->ob_type->tp_name,
PyString_AS_STRING(r)); PyString_AS_STRING(r));
if (rv > 0 && rv < sizeof(repr)) { if (rv > 0 && rv < sizeof(repr)) {
Py_DECREF(r); Py_DECREF(r);
return PyString_FromStringAndSize(repr, strlen(repr)); return PyString_FromStringAndSize(repr, strlen(repr));
} }
else { else {
/* The static buffer wasn't big enough */ /* The static buffer wasn't big enough */
int size; int size;
PyObject *s; PyObject *s;
/* 3 for the parens and the null byte */ /* 3 for the parens and the null byte */
size = strlen(self->ob_type->tp_name) + PyString_GET_SIZE(r) + 3; size = strlen(self->ob_type->tp_name) + PyString_GET_SIZE(r) + 3;
s = PyString_FromStringAndSize(NULL, size); s = PyString_FromStringAndSize(NULL, size);
if (!s) { if (!s) {
Py_DECREF(r); Py_DECREF(r);
return r; return r;
}
PyOS_snprintf(PyString_AS_STRING(s), size,
"%s(%s)", self->ob_type->tp_name, PyString_AS_STRING(r));
Py_DECREF(r);
return s;
} }
PyOS_snprintf(PyString_AS_STRING(s), size,
"%s(%s)", self->ob_type->tp_name, PyString_AS_STRING(r));
Py_DECREF(r);
return s;
}
} }
static PyTypeObject BucketType = { static PyTypeObject BucketType = {
PyObject_HEAD_INIT(NULL) /* PyPersist_Type */ PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
0, /* ob_size */ 0, /* ob_size */
MODULE_NAME MOD_NAME_PREFIX "Bucket",/* tp_name */ MODULE_NAME MOD_NAME_PREFIX "Bucket",/* tp_name */
sizeof(Bucket), /* tp_basicsize */ sizeof(Bucket), /* tp_basicsize */
0, /* tp_itemsize */ 0, /* tp_itemsize */
(destructor)bucket_dealloc, /* tp_dealloc */ (destructor)bucket_dealloc, /* tp_dealloc */
0, /* tp_print */ 0, /* tp_print */
0, /* tp_getattr */ 0, /* tp_getattr */
0, /* tp_setattr */ 0, /* tp_setattr */
0, /* tp_compare */ 0, /* tp_compare */
(reprfunc)bucket_repr, /* tp_repr */ (reprfunc)bucket_repr, /* tp_repr */
0, /* tp_as_number */ 0, /* tp_as_number */
&Bucket_as_sequence, /* tp_as_sequence */ &Bucket_as_sequence, /* tp_as_sequence */
&Bucket_as_mapping, /* tp_as_mapping */ &Bucket_as_mapping, /* tp_as_mapping */
0, /* tp_hash */ 0, /* tp_hash */
0, /* tp_call */ 0, /* tp_call */
0, /* tp_str */ 0, /* tp_str */
0, /* tp_getattro */ 0, /* tp_getattro */
0, /* tp_setattro */ 0, /* tp_setattro */
0, /* tp_as_buffer */ 0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC | Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */ Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */ 0, /* tp_doc */
(traverseproc)bucket_traverse, /* tp_traverse */ (traverseproc)bucket_traverse, /* tp_traverse */
(inquiry)bucket_tp_clear, /* tp_clear */ (inquiry)bucket_tp_clear, /* tp_clear */
0, /* tp_richcompare */ 0, /* tp_richcompare */
0, /* tp_weaklistoffset */ 0, /* tp_weaklistoffset */
(getiterfunc)Bucket_getiter, /* tp_iter */ (getiterfunc)Bucket_getiter, /* tp_iter */
0, /* tp_iternext */ 0, /* tp_iternext */
Bucket_methods, /* tp_methods */ Bucket_methods, /* tp_methods */
Bucket_members, /* tp_members */ Bucket_members, /* tp_members */
0, /* tp_getset */ 0, /* tp_getset */
0, /* tp_base */ 0, /* tp_base */
0, /* tp_dict */ 0, /* tp_dict */
0, /* tp_descr_get */ 0, /* tp_descr_get */
0, /* tp_descr_set */ 0, /* tp_descr_set */
0, /* tp_dictoffset */ 0, /* tp_dictoffset */
Bucket_init, /* tp_init */ Bucket_init, /* tp_init */
0, /* tp_alloc */ 0, /* tp_alloc */
0, /*PyType_GenericNew,*/ /* tp_new */ 0, /*PyType_GenericNew,*/ /* tp_new */
}; };
static int static int
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment