Commit f108be3a authored by Tres Seaver's avatar Tres Seaver

All modules compiling under Py3k.

parent 6cb58ca0
......@@ -41,7 +41,8 @@
* a search finger weren't being used at all, but is still quadratic time
* in the number of buckets in the slice.
*/
typedef struct {
typedef struct
{
PyObject_HEAD
Bucket *firstbucket; /* First bucket */
Bucket *currentbucket; /* Current bucket (search finger) */
......@@ -90,7 +91,8 @@ BTreeItems_length_or_nonzero(BTreeItems *self, int nonzero)
Py_INCREF(b);
PER_USE_OR_RETURN(b, -1);
while ((next = b->next)) {
while ((next = b->next))
{
r += b->len;
if (nonzero && r > 0)
/* Short-circuit if all we care about is nonempty */
......@@ -141,10 +143,12 @@ BTreeItems_seek(BTreeItems *self, Py_ssize_t i)
pseudoindex = self->pseudoindex;
currentoffset = self->currentoffset;
currentbucket = self->currentbucket;
if (currentbucket == NULL) goto no_match;
if (currentbucket == NULL)
goto no_match;
delta = i - pseudoindex;
while (delta > 0) { /* move right */
while (delta > 0) /* move right */
{
int max;
/* Want to move right delta positions; the most we can move right in
* this bucket is currentbucket->len - currentoffset - 1 positions.
......@@ -153,34 +157,41 @@ BTreeItems_seek(BTreeItems *self, Py_ssize_t i)
max = currentbucket->len - currentoffset - 1;
b = currentbucket->next;
PER_UNUSE(currentbucket);
if (delta <= max) {
if (delta <= max)
{
currentoffset += delta;
pseudoindex += delta;
if (currentbucket == self->lastbucket
&& currentoffset > self->last) goto no_match;
&& currentoffset > self->last)
goto no_match;
break;
}
/* Move to start of next bucket. */
if (currentbucket == self->lastbucket || b == NULL) goto no_match;
if (currentbucket == self->lastbucket || b == NULL)
goto no_match;
currentbucket = b;
pseudoindex += max + 1;
delta -= max + 1;
currentoffset = 0;
}
while (delta < 0) { /* move left */
while (delta < 0) /* move left */
{
int status;
/* Want to move left -delta positions; the most we can move left in
* this bucket is currentoffset positions.
*/
if ((-delta) <= currentoffset) {
if ((-delta) <= currentoffset)
{
currentoffset += delta;
pseudoindex += delta;
if (currentbucket == self->firstbucket
&& currentoffset < self->first) goto no_match;
&& currentoffset < self->first)
goto no_match;
break;
}
/* Move to end of previous bucket. */
if (currentbucket == self->firstbucket) goto no_match;
if (currentbucket == self->firstbucket)
goto no_match;
status = PreviousBucket(&currentbucket, self->firstbucket);
if (status == 0)
goto no_match;
......@@ -202,7 +213,8 @@ BTreeItems_seek(BTreeItems *self, Py_ssize_t i)
PER_USE_OR_RETURN(currentbucket, -1);
error = currentoffset < 0 || currentoffset >= currentbucket->len;
PER_UNUSE(currentbucket);
if (error) {
if (error)
{
PyErr_SetString(PyExc_RuntimeError,
"the bucket being iterated changed size");
return -1;
......@@ -232,8 +244,8 @@ getBucketEntry(Bucket *b, int i, char kind)
assert(b);
assert(0 <= i && i < b->len);
switch (kind) {
switch (kind)
{
case 'k':
COPY_KEY_TO_OBJECT(result, b->keys[i]);
break;
......@@ -242,25 +254,30 @@ getBucketEntry(Bucket *b, int i, char kind)
COPY_VALUE_TO_OBJECT(result, b->values[i]);
break;
case 'i': {
case 'i':
{
PyObject *key;
PyObject *value;;
COPY_KEY_TO_OBJECT(key, b->keys[i]);
if (!key) break;
if (!key)
break;
COPY_VALUE_TO_OBJECT(value, b->values[i]);
if (!value) {
if (!value)
{
Py_DECREF(key);
break;
}
result = PyTuple_New(2);
if (result) {
if (result)
{
PyTuple_SET_ITEM(result, 0, key);
PyTuple_SET_ITEM(result, 1, value);
}
else {
else
{
Py_DECREF(key);
Py_DECREF(value);
}
......@@ -289,7 +306,8 @@ BTreeItems_item(BTreeItems *self, Py_ssize_t i)
{
PyObject *result;
if (BTreeItems_seek(self, i) < 0) return NULL;
if (BTreeItems_seek(self, i) < 0)
return NULL;
PER_USE_OR_RETURN(self->currentbucket, NULL);
result = getBucketEntry(self->currentbucket, self->currentoffset,
......@@ -334,7 +352,8 @@ BTreeItems_slice(BTreeItems *self, Py_ssize_t ilow, Py_ssize_t ihigh)
*/
if (ilow < 0)
ilow = 0;
else {
else
{
if (length < 0)
length = BTreeItems_length(self);
if (ilow > length)
......@@ -343,7 +362,8 @@ BTreeItems_slice(BTreeItems *self, Py_ssize_t ilow, Py_ssize_t ihigh)
if (ihigh < ilow)
ihigh = ilow;
else {
else
{
if (length < 0)
length = BTreeItems_length(self);
if (ihigh > length)
......@@ -362,21 +382,24 @@ BTreeItems_slice(BTreeItems *self, Py_ssize_t ilow, Py_ssize_t ihigh)
* if we attempt to seek to ilow==1 when the underlying sequence is empty.
* It seems simplest to deal with empty slices as a special case here.
*/
if (ilow == ihigh) {
/* empty slice */
if (ilow == ihigh) /* empty slice */
{
lowbucket = highbucket = NULL;
lowoffset = 1;
highoffset = 0;
}
else {
else
{
assert(ilow < ihigh);
--ihigh; /* exclusive -> inclusive */
if (BTreeItems_seek(self, ilow) < 0) return NULL;
if (BTreeItems_seek(self, ilow) < 0)
return NULL;
lowbucket = self->currentbucket;
lowoffset = self->currentoffset;
if (BTreeItems_seek(self, ihigh) < 0) return NULL;
if (BTreeItems_seek(self, ihigh) < 0)
return NULL;
highbucket = self->currentbucket;
highoffset = self->currentoffset;
......@@ -385,12 +408,13 @@ BTreeItems_slice(BTreeItems *self, Py_ssize_t ilow, Py_ssize_t ihigh)
lowbucket, lowoffset, highbucket, highoffset);
}
static PySequenceMethods BTreeItems_as_sequence = {
(lenfunc) BTreeItems_length,
(binaryfunc)0,
(ssizeargfunc)0,
(ssizeargfunc) BTreeItems_item,
(ssizessizeargfunc) BTreeItems_slice,
static PySequenceMethods BTreeItems_as_sequence =
{
(lenfunc) BTreeItems_length, /* sq_length */
(binaryfunc)0, /* sq_concat */
(ssizeargfunc)0, /* sq_repeat */
(ssizeargfunc) BTreeItems_item, /* sq_item */
(ssizessizeargfunc) BTreeItems_slice, /* sq_slice */
};
/* Number Method items (just for nb_nonzero!) */
......@@ -402,31 +426,41 @@ BTreeItems_nonzero(BTreeItems *self)
}
static PyNumberMethods BTreeItems_as_number_for_nonzero = {
0,0,0,0,0,0,0,0,0,0,
(inquiry)BTreeItems_nonzero};
0, /* nb_add */
0, /* nb_subtract */
0, /* nb_multiply */
#ifndef PY3K
0, /* nb_divide */
#endif
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
0, /* nb_negative */
0, /* nb_positive */
0, /* nb_absolute */
(inquiry)BTreeItems_nonzero /* nb_nonzero */
};
static PyTypeObject BTreeItemsType = {
PyObject_HEAD_INIT(NULL)
0, /*ob_size*/
MOD_NAME_PREFIX "BTreeItems", /*tp_name*/
sizeof(BTreeItems), /*tp_basicsize*/
0, /*tp_itemsize*/
PyVarObject_HEAD_INIT(NULL, 0)
MOD_NAME_PREFIX "BTreeItems", /* tp_name */
sizeof(BTreeItems), /* tp_basicsize */
0, /* tp_itemsize */
/* methods */
(destructor) BTreeItems_dealloc, /*tp_dealloc*/
(printfunc)0, /*tp_print*/
(getattrfunc)0, /*obsolete tp_getattr*/
(setattrfunc)0, /*obsolete tp_setattr*/
(cmpfunc)0, /*tp_compare*/
(reprfunc)0, /*tp_repr*/
&BTreeItems_as_number_for_nonzero, /*tp_as_number*/
&BTreeItems_as_sequence, /*tp_as_sequence*/
0, /*tp_as_mapping*/
(hashfunc)0, /*tp_hash*/
(ternaryfunc)0, /*tp_call*/
(reprfunc)0, /*tp_str*/
0, /*tp_getattro*/
0, /*tp_setattro*/
(destructor) BTreeItems_dealloc, /* tp_dealloc */
0, /* tp_print */
0, /* obsolete tp_getattr */
0, /* obsolete tp_setattr */
0, /* tp_compare */
0, /* tp_repr */
&BTreeItems_as_number_for_nonzero, /* tp_as_number */
&BTreeItems_as_sequence, /* tp_as_sequence */
0, /* tp_as_mapping */
(hashfunc)0, /* tp_hash */
(ternaryfunc)0, /* tp_call */
(reprfunc)0, /* tp_str */
0, /* tp_getattro */
0, /* tp_setattro */
/* Space for future expansion */
0L,0L,
"Sequence type used to iterate over BTree items." /* Documentation string */
......@@ -445,7 +479,8 @@ newBTreeItems(char kind,
{
BTreeItems *self;
UNLESS (self = PyObject_NEW(BTreeItems, &BTreeItemsType)) return NULL;
UNLESS (self = PyObject_NEW(BTreeItems, &BTreeItemsType))
return NULL;
self->kind=kind;
self->first=lowoffset;
......@@ -564,7 +599,8 @@ nextTreeSetItems(SetIteration *i)
static PyTypeObject BTreeIter_Type;
/* The type of iterator objects, returned by e.g. iter(IIBTree()). */
typedef struct {
typedef struct
{
PyObject_HEAD
/* We use a BTreeItems object because it's convenient and flexible.
* We abuse it two ways:
......@@ -584,7 +620,8 @@ BTreeIter_new(BTreeItems *pitems)
assert(pitems != NULL);
result = PyObject_New(BTreeIter, &BTreeIter_Type);
if (result) {
if (result)
{
Py_INCREF(pitems);
result->pitems = pitems;
}
......@@ -615,7 +652,8 @@ BTreeIter_next(BTreeIter *bi, PyObject *args)
return NULL;
PER_USE_OR_RETURN(bucket, NULL);
if (i >= bucket->len) {
if (i >= bucket->len)
{
/* We never leave this routine normally with i >= len: somebody
* else mutated the current bucket.
*/
......@@ -630,14 +668,17 @@ BTreeIter_next(BTreeIter *bi, PyObject *args)
result = getBucketEntry(bucket, i, items->kind);
/* Advance position for next call. */
if (bucket == items->lastbucket && i >= items->last) {
if (bucket == items->lastbucket && i >= items->last)
{
/* Next call should terminate the iteration. */
Py_DECREF(items->currentbucket);
items->currentbucket = NULL;
}
else {
else
{
++i;
if (i >= bucket->len) {
if (i >= bucket->len)
{
Py_XINCREF(bucket->next);
items->currentbucket = bucket->next;
Py_DECREF(bucket);
......@@ -659,8 +700,7 @@ BTreeIter_getiter(PyObject *it)
}
static PyTypeObject BTreeIter_Type = {
PyObject_HEAD_INIT(NULL)
0, /* ob_size */
PyVarObject_HEAD_INIT(NULL, 0)
MOD_NAME_PREFIX "-iterator", /* tp_name */
sizeof(BTreeIter), /* tp_basicsize */
0, /* tp_itemsize */
......
......@@ -15,6 +15,7 @@
#include "Python.h"
/* include structmember.h for offsetof */
#include "structmember.h"
#include "bytesobject.h"
#ifdef PERSISTENT
#include "persistent/cPersistence.h"
......@@ -27,7 +28,7 @@
#define PER_ACCESSED(O) 1
#endif
#include "py24compat.h"
#include "_compat.h"
/* So sue me. This pair gets used all over the place, so much so that it
* interferes with understanding non-persistence parts of algorithms.
......@@ -65,7 +66,7 @@ static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
#define MAX_BTREE_SIZE(B) DEFAULT_MAX_BTREE_SIZE
#define MAX_BUCKET_SIZE(B) DEFAULT_MAX_BUCKET_SIZE
#define SameType_Check(O1, O2) ((O1)->ob_type==(O2)->ob_type)
#define SameType_Check(O1, O2) (Py_TYPE((O1))==Py_TYPE((O2)))
#define ASSERT(C, S, R) if (! (C)) { \
PyErr_SetString(PyExc_AssertionError, (S)); return (R); }
......@@ -81,7 +82,7 @@ static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
static int
longlong_check(PyObject *ob)
{
if (PyInt_Check(ob))
if (INT_CHECK(ob))
return 1;
if (PyLong_Check(ob)) {
......@@ -101,10 +102,10 @@ longlong_as_object(PY_LONG_LONG val)
static PY_LONG_LONG maxint = 0;
if (maxint == 0)
maxint = PyInt_GetMax();
maxint = INT_GETMAX();
if ((val > maxint) || (val < (-maxint-1)))
return PyLong_FromLongLong(val);
return PyInt_FromLong((long)val);
return INT_FROM_LONG((long)val);
}
#endif
......@@ -291,7 +292,7 @@ IndexError(int i)
{
PyObject *v;
v = PyInt_FromLong(i);
v = INT_FROM_LONG(i);
if (!v) {
v = Py_None;
Py_INCREF(v);
......@@ -451,7 +452,11 @@ BTREEITEMSTEMPLATE_C
int
init_persist_type(PyTypeObject *type)
{
#ifdef PY3K
((PyObject*)type)->ob_type = &PyType_Type;
#else
type->ob_type = &PyType_Type;
#endif
type->tp_base = cPersistenceCAPI->pertype;
if (PyType_Ready(type) < 0)
......@@ -460,6 +465,21 @@ init_persist_type(PyTypeObject *type)
return 1;
}
#ifdef PY3K
static struct PyModuleDef moduledef = {
PyModuleDef_HEAD_INIT,
"_" MOD_NAME_PREFIX "BTree", /* m_name */
BTree_module_documentation, /* m_doc */
-1, /* m_size */
module_methods, /* m_methods */
NULL, /* m_reload */
NULL, /* m_traverse */
NULL, /* m_clear */
NULL, /* m_free */
};
#endif
void
INITMODULE (void)
{
......@@ -471,40 +491,53 @@ INITMODULE (void)
return;
#endif
sort_str = PyString_InternFromString("sort");
sort_str = INTERN("sort");
if (!sort_str)
return;
reverse_str = PyString_InternFromString("reverse");
reverse_str = INTERN("reverse");
if (!reverse_str)
return;
__setstate___str = PyString_InternFromString("__setstate__");
__setstate___str = INTERN("__setstate__");
if (!__setstate___str)
return;
_bucket_type_str = PyString_InternFromString("_bucket_type");
_bucket_type_str = INTERN("_bucket_type");
if (!_bucket_type_str)
return;
/* Grab the ConflictError class */
m = PyImport_ImportModule("BTrees.Interfaces");
if (m != NULL) {
if (m != NULL)
{
c = PyObject_GetAttrString(m, "BTreesConflictError");
if (c != NULL)
ConflictError = c;
Py_DECREF(m);
}
if (ConflictError == NULL) {
if (ConflictError == NULL)
{
Py_INCREF(PyExc_ValueError);
ConflictError=PyExc_ValueError;
}
/* Initialize the PyPersist_C_API and the type objects. */
cPersistenceCAPI = PyCObject_Import("persistent.cPersistence", "CAPI");
#ifdef PY3K
cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCapsule_Import(
"persistent.cPersistence.CAPI", 0);
#else
cPersistenceCAPI = (cPersistenceCAPIstruct *)PyCObject_Import(
"persistent.cPersistence", "CAPI");
#endif
if (cPersistenceCAPI == NULL)
return;
BTreeItemsType.ob_type = &PyType_Type;
BTreeIter_Type.ob_type = &PyType_Type;
#ifdef PY3K
#define _SET_TYPE(typ) ((PyObject*)(&typ))->ob_type = &PyType_Type
#else
#define _SET_TYPE(typ) (typ).ob_type = &PyType_Type
#endif
_SET_TYPE(BTreeItemsType);
_SET_TYPE(BTreeIter_Type);
BTreeIter_Type.tp_getattro = PyObject_GenericGetAttr;
BucketType.tp_new = PyType_GenericNew;
SetType.tp_new = PyType_GenericNew;
......@@ -520,20 +553,26 @@ INITMODULE (void)
return;
if (PyDict_SetItem(BTreeType.tp_dict, _bucket_type_str,
(PyObject *)&BucketType) < 0) {
(PyObject *)&BucketType) < 0)
{
fprintf(stderr, "btree failed\n");
return;
}
if (PyDict_SetItem(TreeSetType.tp_dict, _bucket_type_str,
(PyObject *)&SetType) < 0) {
(PyObject *)&SetType) < 0)
{
fprintf(stderr, "bucket failed\n");
return;
}
#ifdef PY3K
m = PyModule_Create(&moduledef);
#else
/* Create the module and add the functions */
m = Py_InitModule4("_" MOD_NAME_PREFIX "BTree",
module_methods, BTree_module_documentation,
(PyObject *)NULL, PYTHON_API_VERSION);
#endif
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
......
......@@ -11,6 +11,7 @@
FOR A PARTICULAR PURPOSE
****************************************************************************/
#include "_compat.h"
#define BTREETEMPLATE_C "$Id$\n"
......@@ -42,8 +43,8 @@ BTree_check_inner(BTree *self, Bucket *nextbucket)
PER_USE_OR_RETURN(self, -1);
CHECK(self->len >= 0, "BTree len < 0");
CHECK(self->len <= self->size, "BTree len > size");
if (self->len == 0) {
/* Empty BTree. */
if (self->len == 0) /* Empty BTree. */
{
CHECK(self->firstbucket == NULL,
"Empty BTree has non-NULL firstbucket");
result = 0;
......@@ -59,58 +60,67 @@ BTree_check_inner(BTree *self, Bucket *nextbucket)
* on self's pointers being intact.
*/
#ifdef PERSISTENT
CHECK(self->firstbucket->ob_refcnt >= 1,
CHECK(Py_REFCNT(self->firstbucket) >= 1,
"Non-empty BTree firstbucket has refcount < 1");
#else
CHECK(self->firstbucket->ob_refcnt >= 2,
CHECK(Py_REFCNT(self->firstbucket) >= 2,
"Non-empty BTree firstbucket has refcount < 2");
#endif
for (i = 0; i < self->len; ++i) {
for (i = 0; i < self->len; ++i)
{
CHECK(self->data[i].child != NULL, "BTree has NULL child");
}
if (SameType_Check(self, self->data[0].child)) {
if (SameType_Check(self, self->data[0].child))
{
/* Our children are also BTrees. */
child = self->data[0].child;
UNLESS (PER_USE(child)) goto Done;
UNLESS (PER_USE(child))
goto Done;
activated_child = child;
CHECK(self->firstbucket == BTREE(child)->firstbucket,
"BTree has firstbucket different than "
"its first child's firstbucket");
PER_ALLOW_DEACTIVATION(child);
activated_child = NULL;
for (i = 0; i < self->len; ++i) {
for (i = 0; i < self->len; ++i)
{
child = self->data[i].child;
CHECK(SameType_Check(self, child),
"BTree children have different types");
if (i == self->len - 1)
bucketafter = nextbucket;
else {
else
{
BTree *child2 = BTREE(self->data[i+1].child);
UNLESS (PER_USE(child2)) goto Done;
UNLESS (PER_USE(child2))
goto Done;
bucketafter = child2->firstbucket;
PER_ALLOW_DEACTIVATION(child2);
}
if (BTree_check_inner(BTREE(child), bucketafter) < 0) goto Done;
if (BTree_check_inner(BTREE(child), bucketafter) < 0)
goto Done;
}
}
else {
/* Our children are buckets. */
else /* Our children are buckets. */
{
CHECK(self->firstbucket == BUCKET(self->data[0].child),
"Bottom-level BTree node has inconsistent firstbucket belief");
for (i = 0; i < self->len; ++i) {
for (i = 0; i < self->len; ++i)
{
child = self->data[i].child;
UNLESS (PER_USE(child)) goto Done;
UNLESS (PER_USE(child))
goto Done;
activated_child = child;
CHECK(!SameType_Check(self, child),
"BTree children have different types");
CHECK(child->len >= 1, "Bucket length < 1"); /* no empty buckets! */
CHECK(child->len >= 1, "Bucket length < 1");/* no empty buckets! */
CHECK(child->len <= child->size, "Bucket len > size");
#ifdef PERSISTENT
CHECK(child->ob_refcnt >= 1, "Bucket has refcount < 1");
CHECK(Py_REFCNT(child) >= 1, "Bucket has refcount < 1");
#else
CHECK(child->ob_refcnt >= 2, "Bucket has refcount < 2");
CHECK(Py_REFCNT(child) >= 2, "Bucket has refcount < 2");
#endif
if (i == self->len - 1)
bucketafter = nextbucket;
......@@ -125,13 +135,15 @@ BTree_check_inner(BTree *self, Bucket *nextbucket)
result = 0;
goto Done;
Error:
Error:
PyErr_SetString(PyExc_AssertionError, errormsg);
result = -1;
Done:
Done:
/* No point updating access time -- this isn't a "real" use. */
PER_ALLOW_DEACTIVATION(self);
if (activated_child) {
if (activated_child)
{
PER_ALLOW_DEACTIVATION(activated_child);
}
return result;
......@@ -150,7 +162,8 @@ BTree_check(BTree *self)
PyObject *result = NULL;
int i = BTree_check_inner(self, NULL);
if (i >= 0) {
if (i >= 0)
{
result = Py_None;
Py_INCREF(result);
}
......@@ -187,34 +200,39 @@ _BTree_get(BTree *self, PyObject *keyarg, int has_key)
UNLESS (copied) return NULL;
PER_USE_OR_RETURN(self, NULL);
if (self->len == 0) {
if (self->len == 0)
{
/* empty BTree */
if (has_key)
result = PyInt_FromLong(0);
result = INT_FROM_LONG(0);
else
PyErr_SetObject(PyExc_KeyError, keyarg);
}
else {
for (;;) {
else
{
for (;;)
{
int i;
Sized *child;
BTREE_SEARCH(i, self, key, goto Done);
child = self->data[i].child;
has_key += has_key != 0; /* bump depth counter, maybe */
if (SameType_Check(self, child)) {
if (SameType_Check(self, child))
{
PER_UNUSE(self);
self = BTREE(child);
PER_USE_OR_RETURN(self, NULL);
}
else {
else
{
result = _bucket_get(BUCKET(child), keyarg, has_key);
break;
}
}
}
Done:
Done:
PER_UNUSE(self);
return result;
}
......@@ -236,7 +254,7 @@ BTree_newBucket(BTree *self)
Sized *result;
/* _bucket_type_str defined in BTreeModuleTemplate.c */
factory = PyObject_GetAttr((PyObject *)self->ob_type, _bucket_type_str);
factory = PyObject_GetAttr((PyObject *)Py_TYPE(self), _bucket_type_str);
if (factory == NULL)
return NULL;
/* TODO: Should we check that the factory actually returns something
......@@ -282,7 +300,8 @@ BTree_split(BTree *self, int index, BTree *next)
/* Set next's firstbucket. self->firstbucket is still correct. */
child = next->data[0].child;
if (SameType_Check(self, child)) {
if (SameType_Check(self, child))
{
PER_USE_OR_RETURN(child, -1);
next->firstbucket = BTREE(child)->firstbucket;
PER_UNUSE(child);
......@@ -318,8 +337,9 @@ BTree_split_root(BTree *self, int noval)
BTreeItem *d;
/* Create a child BTree, and a new data vector for self. */
child = BTREE(PyObject_CallObject(OBJECT(self->ob_type), NULL));
if (!child) return -1;
child = BTREE(PyObject_CallObject(OBJECT(Py_TYPE(self)), NULL));
if (!child)
return -1;
d = BTree_Malloc(sizeof(BTreeItem) * 2);
if (!d) {
......@@ -368,15 +388,18 @@ BTree_grow(BTree *self, int index, int noval)
Sized *v, *e = 0;
BTreeItem *d;
if (self->len == self->size) {
if (self->size) {
if (self->len == self->size)
{
if (self->size)
{
d = BTree_Realloc(self->data, sizeof(BTreeItem) * self->size * 2);
if (d == NULL)
return -1;
self->data = d;
self->size *= 2;
}
else {
else
{
d = BTree_Malloc(sizeof(BTreeItem) * 2);
if (d == NULL)
return -1;
......@@ -385,15 +408,17 @@ BTree_grow(BTree *self, int index, int noval)
}
}
if (self->len) {
if (self->len)
{
d = self->data + index;
v = d->child;
/* Create a new object of the same type as the target value */
e = (Sized *)PyObject_CallObject((PyObject *)v->ob_type, NULL);
e = (Sized *)PyObject_CallObject((PyObject *)Py_TYPE(v), NULL);
if (e == NULL)
return -1;
UNLESS(PER_USE(v)) {
UNLESS(PER_USE(v))
{
Py_DECREF(e);
return -1;
}
......@@ -405,7 +430,8 @@ BTree_grow(BTree *self, int index, int noval)
i = bucket_split((Bucket *)v, -1, (Bucket *)e);
PER_ALLOW_DEACTIVATION(v);
if (i < 0) {
if (i < 0)
{
Py_DECREF(e);
assert(PyErr_Occurred());
return -1;
......@@ -416,7 +442,8 @@ BTree_grow(BTree *self, int index, int noval)
if (self->len > index) /* Shift up the old values one array slot */
memmove(d+1, d, sizeof(BTreeItem)*(self->len-index));
if (SameType_Check(self, v)) {
if (SameType_Check(self, v))
{
COPY_KEY(d->key, BTREE(e)->data->key);
/* We take the unused reference from e, so there's no
......@@ -424,7 +451,8 @@ BTree_grow(BTree *self, int index, int noval)
*/
/* INCREF_KEY(self->data[1].key); */
}
else {
else
{
COPY_KEY(d->key, BUCKET(e)->keys[0]);
INCREF_KEY(d->key);
}
......@@ -434,7 +462,8 @@ BTree_grow(BTree *self, int index, int noval)
if (self->len >= MAX_BTREE_SIZE(self) * 2) /* the root is huge */
return BTree_split_root(self, noval);
}
else {
else
{
/* The BTree is empty. Create an empty bucket. See CAUTION in
* the comments preceding.
*/
......@@ -468,19 +497,22 @@ BTree_lastBucket(BTree *self)
Sized *pchild;
Bucket *result;
UNLESS (self->data && self->len) {
UNLESS (self->data && self->len)
{
IndexError(-1); /* is this the best action to take? */
return NULL;
}
pchild = self->data[self->len - 1].child;
if (SameType_Check(self, pchild)) {
if (SameType_Check(self, pchild))
{
self = BTREE(pchild);
PER_USE_OR_RETURN(self, NULL);
result = BTree_lastBucket(self);
PER_UNUSE(self);
}
else {
else
{
Py_INCREF(pchild);
result = BUCKET(pchild);
}
......@@ -492,7 +524,8 @@ BTree_deleteNextBucket(BTree *self)
{
Bucket *b;
UNLESS (PER_USE(self)) return -1;
UNLESS (PER_USE(self))
return -1;
b = BTree_lastBucket(self);
if (b == NULL)
......@@ -505,7 +538,7 @@ BTree_deleteNextBucket(BTree *self)
return 0;
err:
err:
Py_XDECREF(b);
PER_ALLOW_DEACTIVATION(self);
return -1;
......@@ -538,7 +571,8 @@ _BTree_clear(BTree *self)
{
const int len = self->len;
if (self->firstbucket) {
if (self->firstbucket)
{
/* Obscure: The first bucket is pointed to at least by
* self->firstbucket and data[0].child of whichever BTree node it's
* a child of. However, if persistence is enabled then the latter
......@@ -546,23 +580,26 @@ _BTree_clear(BTree *self)
* count": we can only rely on self's pointers being intact.
*/
#ifdef PERSISTENT
ASSERT(self->firstbucket->ob_refcnt > 0,
ASSERT(Py_REFCNT(self->firstbucket) > 0,
"Invalid firstbucket pointer", -1);
#else
ASSERT(self->firstbucket->ob_refcnt > 1,
ASSERT(Py_REFCNT(self->firstbucket) > 1,
"Invalid firstbucket pointer", -1);
#endif
Py_DECREF(self->firstbucket);
self->firstbucket = NULL;
}
if (self->data) {
if (self->data)
{
int i;
if (len > 0) { /* 0 is special because key 0 is trash */
if (len > 0) /* 0 is special because key 0 is trash */
{
Py_DECREF(self->data[0].child);
}
for (i = 1; i < len; i++) {
for (i = 1; i < len; i++)
{
#ifdef KEY_TYPE_IS_PYOBJECT
DECREF_KEY(self->data[i].key);
#endif
......@@ -617,18 +654,22 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
int copied = 1;
COPY_KEY_FROM_ARG(key, keyarg, copied);
if (!copied) return -1;
if (!copied)
return -1;
PER_USE_OR_RETURN(self, -1);
self_was_empty = self->len == 0;
if (self_was_empty) {
if (self_was_empty)
{
/* We're empty. Make room. */
if (value) {
if (value)
{
if (BTree_grow(self, 0, noval) < 0)
goto Error;
}
else {
else
{
/* Can't delete a key from an empty BTree. */
PyErr_SetObject(PyExc_KeyError, keyarg);
goto Error;
......@@ -645,7 +686,8 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
if (SameType_Check(self, d->child))
status = _BTree_set(BTREE(d->child), keyarg, value, unique, noval);
else {
else
{
int bucket_changed = 0;
status = _bucket_set(BUCKET(d->child), keyarg,
value, unique, noval, &bucket_changed);
......@@ -664,19 +706,23 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
}
#endif
}
if (status == 0) goto Done;
if (status < 0) goto Error;
if (status == 0)
goto Done;
if (status < 0)
goto Error;
assert(status == 1 || status == 2);
/* The child changed size. Get its new size. Note that since the tree
* rooted at the child changed size, so did the tree rooted at self:
* our status must be >= 1 too.
*/
UNLESS(PER_USE(d->child)) goto Error;
UNLESS(PER_USE(d->child))
goto Error;
childlength = d->child->len;
PER_UNUSE(d->child);
if (value) {
if (value)
{
/* A bucket got bigger -- if it's "too big", split it. */
int toobig;
......@@ -687,7 +733,8 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
toobig = childlength > MAX_BUCKET_SIZE(d->child);
if (toobig) {
if (BTree_grow(self, min, noval) < 0) goto Error;
if (BTree_grow(self, min, noval) < 0)
goto Error;
changed = 1; /* BTree_grow mutated self */
}
goto Done; /* and status still == 1 */
......@@ -706,45 +753,53 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
*/
int _cmp = 1;
TEST_KEY_SET_OR(_cmp, key, d->key) goto Error;
if (_cmp == 0)
{ /* Need to replace key with first key from child */
if (_cmp == 0) /* Need to replace key with first key from child */
{
Bucket *bucket;
if (SameType_Check(self, d->child))
{
UNLESS(PER_USE(d->child)) goto Error;
UNLESS(PER_USE(d->child))
goto Error;
bucket = BTREE(d->child)->firstbucket;
PER_UNUSE(d->child);
}
else
bucket = BUCKET(d->child);
UNLESS(PER_USE(bucket)) goto Error;
UNLESS(PER_USE(bucket))
goto Error;
DECREF_KEY(d->key);
COPY_KEY(d->key, bucket->keys[0]);
INCREF_KEY(d->key);
PER_UNUSE(bucket);
if (PER_CHANGED(self) < 0) goto Error;
if (PER_CHANGED(self) < 0)
goto Error;
}
}
if (status == 2) {
if (status == 2)
{
/* The child must be a BTree because bucket.set never returns 2 */
/* Two problems to solve: May have to adjust our own firstbucket,
* and the bucket that went away needs to get unlinked.
*/
if (min) {
if (min)
{
/* This wasn't our firstbucket, so no need to adjust ours (note
* that it can't be the firstbucket of any node above us either).
* Tell "the tree to the left" to do the unlinking.
*/
if (BTree_deleteNextBucket(BTREE(d[-1].child)) < 0) goto Error;
if (BTree_deleteNextBucket(BTREE(d[-1].child)) < 0)
goto Error;
status = 1; /* we solved the child's firstbucket problem */
}
else {
else
{
/* This was our firstbucket. Update to new firstbucket value. */
Bucket *nextbucket;
UNLESS(PER_USE(d->child)) goto Error;
UNLESS(PER_USE(d->child))
goto Error;
nextbucket = BTREE(d->child)->firstbucket;
PER_UNUSE(d->child);
......@@ -764,30 +819,36 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
* us to do with the firstbucket problems the child gave us, and since the
* child isn't empty don't create any new firstbucket problems of our own.
*/
if (childlength) goto Done;
if (childlength)
goto Done;
/* The child became empty: we need to remove it from self->data.
* But first, if we're a bottom-level node, we've got more bucket-fiddling
* to set up.
*/
if (! SameType_Check(self, d->child)) {
if (! SameType_Check(self, d->child))
{
/* We're about to delete a bucket, so need to adjust bucket pointers. */
if (min) {
if (min)
{
/* It's not our first bucket, so we can tell the previous
* bucket to adjust its reference to it. It can't be anyone
* else's first bucket either, so the caller needn't do anything.
*/
if (Bucket_deleteNextBucket(BUCKET(d[-1].child)) < 0) goto Error;
if (Bucket_deleteNextBucket(BUCKET(d[-1].child)) < 0)
goto Error;
/* status should be 1, and already is: if it were 2, the
* block above would have set it to 1 in its min != 0 branch.
*/
assert(status == 1);
}
else {
else
{
Bucket *nextbucket;
/* It's our first bucket. We can't unlink it directly. */
/* 'changed' will be set true by the deletion code following. */
UNLESS(PER_USE(d->child)) goto Error;
UNLESS(PER_USE(d->child))
goto Error;
nextbucket = BUCKET(d->child)->next;
PER_UNUSE(d->child);
......@@ -802,10 +863,12 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
/* Remove the child from self->data. */
Py_DECREF(d->child);
#ifdef KEY_TYPE_IS_PYOBJECT
if (min) {
if (min)
{
DECREF_KEY(d->key);
}
else if (self->len > 1) {
else if (self->len > 1)
{
/* We're deleting the first child of a BTree with more than one
* child. The key at d+1 is about to be shifted into slot 0,
* and hence never to be referenced again (the key in slot 0 is
......@@ -822,18 +885,21 @@ _BTree_set(BTree *self, PyObject *keyarg, PyObject *value,
memmove(d, d+1, (self->len - min) * sizeof(BTreeItem));
changed = 1;
Done:
Done:
#ifdef PERSISTENT
if (changed) {
if (PER_CHANGED(self) < 0) goto Error;
if (changed)
{
if (PER_CHANGED(self) < 0)
goto Error;
}
#endif
PER_UNUSE(self);
return status;
Error:
Error:
assert(PyErr_Occurred());
if (self_was_empty) {
if (self_was_empty)
{
/* BTree_grow may have left the BTree in an invalid state. Make
* sure the tree is a legitimate empty tree.
*/
......@@ -870,32 +936,38 @@ BTree__p_deactivate(BTree *self, PyObject *args, PyObject *keywords)
int ghostify = 1;
PyObject *force = NULL;
if (args && PyTuple_GET_SIZE(args) > 0) {
if (args && PyTuple_GET_SIZE(args) > 0)
{
PyErr_SetString(PyExc_TypeError,
"_p_deactivate takes not positional arguments");
return NULL;
}
if (keywords) {
if (keywords)
{
int size = PyDict_Size(keywords);
force = PyDict_GetItemString(keywords, "force");
if (force)
size--;
if (size) {
if (size)
{
PyErr_SetString(PyExc_TypeError,
"_p_deactivate only accepts keyword arg force");
return NULL;
}
}
if (self->jar && self->oid) {
if (self->jar && self->oid)
{
ghostify = self->state == cPersistent_UPTODATE_STATE;
if (!ghostify && force) {
if (!ghostify && force)
{
if (PyObject_IsTrue(force))
ghostify = 1;
if (PyErr_Occurred())
return NULL;
}
if (ghostify) {
if (ghostify)
{
if (_BTree_clear(self) < 0)
return NULL;
PER_GHOSTIFY(self);
......@@ -925,7 +997,7 @@ BTree_clear(BTree *self)
Py_INCREF(Py_None);
return Py_None;
err:
err:
PER_UNUSE(self);
return NULL;
}
......@@ -964,19 +1036,22 @@ BTree_getstate(BTree *self)
PyObject *o;
int i, l;
UNLESS (PER_USE(self)) return NULL;
UNLESS (PER_USE(self))
return NULL;
if (self->len) {
if (self->len)
{
r = PyTuple_New(self->len * 2 - 1);
if (r == NULL)
goto err;
if (self->len == 1
&& self->data->child->ob_type != self->ob_type
&& Py_TYPE(self->data->child) != Py_TYPE(self)
#ifdef PERSISTENT
&& BUCKET(self->data->child)->oid == NULL
#endif
) {
)
{
/* We have just one bucket. Save its data directly. */
o = bucket_getstate((Bucket *)self->data->child);
if (o == NULL)
......@@ -984,9 +1059,12 @@ BTree_getstate(BTree *self)
PyTuple_SET_ITEM(r, 0, o);
ASSIGN(r, Py_BuildValue("(O)", r));
}
else {
for (i=0, l=0; i < self->len; i++) {
if (i) {
else
{
for (i=0, l=0; i < self->len; i++)
{
if (i)
{
COPY_KEY_TO_OBJECT(o, self->data[i].key);
PyTuple_SET_ITEM(r, l, o);
l++;
......@@ -1000,7 +1078,8 @@ BTree_getstate(BTree *self)
}
}
else {
else
{
r = Py_None;
Py_INCREF(r);
}
......@@ -1009,7 +1088,7 @@ BTree_getstate(BTree *self)
return r;
err:
err:
PER_UNUSE(self);
Py_XDECREF(r);
return NULL;
......@@ -1038,7 +1117,8 @@ _BTree_setstate(BTree *self, PyObject *state, int noval)
if (!PyArg_ParseTuple(state, "O|O:__setstate__", &items, &firstbucket))
return -1;
if (!PyTuple_Check(items)) {
if (!PyTuple_Check(items))
{
PyErr_SetString(PyExc_TypeError,
"tuple required for first state element");
return -1;
......@@ -1057,9 +1137,11 @@ _BTree_setstate(BTree *self, PyObject *state, int noval)
return -1;
self->size = len;
for (i = 0, d = self->data, l = 0; i < len; i++, d++) {
for (i = 0, d = self->data, l = 0; i < len; i++, d++)
{
PyObject *v;
if (i) { /* skip the first key slot */
if (i)
{ /* skip the first key slot */
COPY_KEY_FROM_ARG(d->key, PyTuple_GET_ITEM(items, l), copied);
l++;
if (!copied)
......@@ -1067,22 +1149,26 @@ _BTree_setstate(BTree *self, PyObject *state, int noval)
INCREF_KEY(d->key);
}
v = PyTuple_GET_ITEM(items, l);
if (PyTuple_Check(v)) {
if (PyTuple_Check(v))
{
/* Handle the special case in __getstate__() for a BTree
with a single bucket. */
d->child = BTree_newBucket(self);
if (!d->child)
return -1;
if (noval) {
if (noval)
{
if (_set_setstate(BUCKET(d->child), v) < 0)
return -1;
}
else {
else
{
if (_bucket_setstate(BUCKET(d->child), v) < 0)
return -1;
}
}
else {
else
{
d->child = (Sized *)v;
Py_INCREF(v);
}
......@@ -1093,7 +1179,8 @@ _BTree_setstate(BTree *self, PyObject *state, int noval)
firstbucket = (PyObject *)self->data->child;
if (!PyObject_IsInstance(firstbucket, (PyObject *)
(noval ? &SetType : &BucketType))) {
(noval ? &SetType : &BucketType)))
{
PyErr_SetString(PyExc_TypeError,
"No firstbucket in non-empty BTree");
return -1;
......@@ -1104,7 +1191,7 @@ _BTree_setstate(BTree *self, PyObject *state, int noval)
/* firstbucket is also the child of some BTree node, but that node may
* be a ghost if persistence is enabled.
*/
assert(self->firstbucket->ob_refcnt > 1);
assert(Py_REFCNT(self->firstbucket) > 1);
#endif
self->len = len;
......@@ -1149,27 +1236,31 @@ get_bucket_state(PyObject *t)
{
if (t == Py_None)
return Py_None; /* an empty BTree */
if (! PyTuple_Check(t)) {
if (! PyTuple_Check(t))
{
PyErr_SetString(PyExc_TypeError,
"_p_resolveConflict: expected tuple or None for state");
return NULL;
}
if (PyTuple_GET_SIZE(t) == 2) {
if (PyTuple_GET_SIZE(t) == 2)
{
/* A non-degenerate BTree. */
return merge_error(-1, -1, -1, 11);
}
/* We're in the one-bucket case. */
if (PyTuple_GET_SIZE(t) != 1) {
if (PyTuple_GET_SIZE(t) != 1)
{
PyErr_SetString(PyExc_TypeError,
"_p_resolveConflict: expected 1- or 2-tuple for state");
return NULL;
}
t = PyTuple_GET_ITEM(t, 0);
if (! PyTuple_Check(t) || PyTuple_GET_SIZE(t) != 1) {
if (! PyTuple_Check(t) || PyTuple_GET_SIZE(t) != 1)
{
PyErr_SetString(PyExc_TypeError,
"_p_resolveConflict: expected 1-tuple containing "
"bucket state");
......@@ -1177,7 +1268,8 @@ get_bucket_state(PyObject *t)
}
t = PyTuple_GET_ITEM(t, 0);
if (! PyTuple_Check(t)) {
if (! PyTuple_Check(t))
{
PyErr_SetString(PyExc_TypeError,
"_p_resolveConflict: expected tuple for bucket state");
return NULL;
......@@ -1279,7 +1371,8 @@ BTree__p_resolveConflict(BTree *self, PyObject *args)
*/
static int
BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low, int exclude_equal,
Bucket **bucket, int *offset) {
Bucket **bucket, int *offset)
{
Sized *deepest_smaller = NULL; /* last possibility to move left */
int deepest_smaller_is_btree = 0; /* Boolean; if false, it's a bucket */
Bucket *pbucket;
......@@ -1290,34 +1383,41 @@ BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low, int exclude_equal,
int copied = 1;
COPY_KEY_FROM_ARG(key, keyarg, copied);
UNLESS (copied) return -1;
UNLESS (copied)
return -1;
/* We don't need to: PER_USE_OR_RETURN(self, -1);
because the caller does. */
UNLESS (self->data && self->len) return 0;
UNLESS (self->data && self->len)
return 0;
/* Search downward until hitting a bucket, stored in pbucket. */
for (;;) {
for (;;)
{
Sized *pchild;
int pchild_is_btree;
BTREE_SEARCH(i, self, key, goto Done);
pchild = self->data[i].child;
pchild_is_btree = SameType_Check(self, pchild);
if (i) {
if (i)
{
deepest_smaller = self->data[i-1].child;
deepest_smaller_is_btree = pchild_is_btree;
}
if (pchild_is_btree) {
if (self_got_rebound) {
if (pchild_is_btree)
{
if (self_got_rebound)
{
PER_UNUSE(self);
}
self = BTREE(pchild);
self_got_rebound = 1;
PER_USE_OR_RETURN(self, -1);
}
else {
else
{
pbucket = BUCKET(pchild);
break;
}
......@@ -1327,14 +1427,16 @@ BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low, int exclude_equal,
i = Bucket_findRangeEnd(pbucket, keyarg, low, exclude_equal, offset);
if (i < 0)
goto Done;
if (i > 0) {
if (i > 0)
{
Py_INCREF(pbucket);
*bucket = pbucket;
result = 1;
goto Done;
}
/* This may be one of the two difficult cases detailed in the comments. */
if (low) {
if (low)
{
Bucket *next;
UNLESS(PER_USE(pbucket)) goto Done;
......@@ -1350,19 +1452,25 @@ BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low, int exclude_equal,
PER_UNUSE(pbucket);
}
/* High-end search: if it's possible to go left, do so. */
else if (deepest_smaller) {
if (deepest_smaller_is_btree) {
UNLESS(PER_USE(deepest_smaller)) goto Done;
else if (deepest_smaller)
{
if (deepest_smaller_is_btree)
{
UNLESS(PER_USE(deepest_smaller))
goto Done;
/* We own the reference this returns. */
pbucket = BTree_lastBucket(BTREE(deepest_smaller));
PER_UNUSE(deepest_smaller);
if (pbucket == NULL) goto Done; /* error */
if (pbucket == NULL)
goto Done; /* error */
}
else {
else
{
pbucket = BUCKET(deepest_smaller);
Py_INCREF(pbucket);
}
UNLESS(PER_USE(pbucket)) goto Done;
UNLESS(PER_USE(pbucket))
goto Done;
result = 1;
*bucket = pbucket; /* transfer ownership to caller */
*offset = pbucket->len - 1;
......@@ -1371,8 +1479,9 @@ BTree_findRangeEnd(BTree *self, PyObject *keyarg, int low, int exclude_equal,
else
result = 0; /* simply not found */
Done:
if (self_got_rebound) {
Done:
if (self_got_rebound)
{
PER_UNUSE(self);
}
return result;
......@@ -1386,11 +1495,14 @@ BTree_maxminKey(BTree *self, PyObject *args, int min)
int offset, rc;
int empty_tree = 1;
UNLESS (PyArg_ParseTuple(args, "|O", &key)) return NULL;
UNLESS (PyArg_ParseTuple(args, "|O", &key))
return NULL;
UNLESS (PER_USE(self)) return NULL;
UNLESS (PER_USE(self))
return NULL;
UNLESS (self->data && self->len) goto empty;
UNLESS (self->data && self->len)
goto empty;
/* Find the range */
......@@ -1398,7 +1510,8 @@ BTree_maxminKey(BTree *self, PyObject *args, int min)
{
if ((rc = BTree_findRangeEnd(self, key, min, 0, &bucket, &offset)) <= 0)
{
if (rc < 0) goto err;
if (rc < 0)
goto err;
empty_tree = 0;
goto empty;
}
......@@ -1436,11 +1549,11 @@ BTree_maxminKey(BTree *self, PyObject *args, int min)
return key;
empty:
empty:
PyErr_SetString(PyExc_ValueError,
empty_tree ? "empty tree" :
"no key satisfies the conditions");
err:
err:
PER_UNUSE(self);
if (bucket)
{
......@@ -1483,7 +1596,8 @@ BTree_rangeSearch(BTree *self, PyObject *args, PyObject *kw, char type)
int highoffset;
PyObject *result;
if (args) {
if (args)
{
if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords,
&min,
&max,
......@@ -1492,33 +1606,43 @@ BTree_rangeSearch(BTree *self, PyObject *args, PyObject *kw, char type)
return NULL;
}
UNLESS (PER_USE(self)) return NULL;
UNLESS (PER_USE(self))
return NULL;
UNLESS (self->data && self->len) goto empty;
UNLESS (self->data && self->len)
goto empty;
/* Find the low range */
if (min != Py_None) {
if (min != Py_None)
{
if ((rc = BTree_findRangeEnd(self, min, 1, excludemin,
&lowbucket, &lowoffset)) <= 0) {
if (rc < 0) goto err;
&lowbucket, &lowoffset)) <= 0)
{
if (rc < 0)
goto err;
goto empty;
}
}
else {
else
{
lowbucket = self->firstbucket;
lowoffset = 0;
if (excludemin) {
if (excludemin)
{
int bucketlen;
UNLESS (PER_USE(lowbucket)) goto err;
UNLESS (PER_USE(lowbucket))
goto err;
bucketlen = lowbucket->len;
PER_UNUSE(lowbucket);
if (bucketlen > 1)
lowoffset = 1;
else if (self->len < 2)
goto empty;
else { /* move to first item in next bucket */
else
{ /* move to first item in next bucket */
Bucket *next;
UNLESS (PER_USE(lowbucket)) goto err;
UNLESS (PER_USE(lowbucket))
goto err;
next = lowbucket->next;
PER_UNUSE(lowbucket);
assert(next != NULL);
......@@ -1531,39 +1655,48 @@ BTree_rangeSearch(BTree *self, PyObject *args, PyObject *kw, char type)
}
/* Find the high range */
if (max != Py_None) {
if (max != Py_None)
{
if ((rc = BTree_findRangeEnd(self, max, 0, excludemax,
&highbucket, &highoffset)) <= 0) {
&highbucket, &highoffset)) <= 0)
{
Py_DECREF(lowbucket);
if (rc < 0) goto err;
if (rc < 0)
goto err;
goto empty;
}
}
else {
else
{
int bucketlen;
highbucket = BTree_lastBucket(self);
assert(highbucket != NULL); /* we know self isn't empty */
UNLESS (PER_USE(highbucket)) goto err_and_decref_buckets;
UNLESS (PER_USE(highbucket))
goto err_and_decref_buckets;
bucketlen = highbucket->len;
PER_UNUSE(highbucket);
highoffset = bucketlen - 1;
if (excludemax) {
if (excludemax)
{
if (highoffset > 0)
--highoffset;
else if (self->len < 2)
goto empty_and_decref_buckets;
else { /* move to last item of preceding bucket */
else /* move to last item of preceding bucket */
{
int status;
assert(highbucket != self->firstbucket);
Py_DECREF(highbucket);
status = PreviousBucket(&highbucket, self->firstbucket);
if (status < 0) {
if (status < 0)
{
Py_DECREF(lowbucket);
goto err;
}
assert(status > 0);
Py_INCREF(highbucket);
UNLESS (PER_USE(highbucket)) goto err_and_decref_buckets;
UNLESS (PER_USE(highbucket))
goto err_and_decref_buckets;
highoffset = highbucket->len - 1;
PER_UNUSE(highbucket);
}
......@@ -1585,22 +1718,27 @@ BTree_rangeSearch(BTree *self, PyObject *args, PyObject *kw, char type)
* empty range.
*/
if (min != Py_None && max != Py_None && /* both args user-supplied */
lowbucket != highbucket) /* and different buckets */ {
lowbucket != highbucket) /* and different buckets */
{
KEY_TYPE first;
KEY_TYPE last;
int cmp;
/* Have to check the hard way: see how the endpoints compare. */
UNLESS (PER_USE(lowbucket)) goto err_and_decref_buckets;
UNLESS (PER_USE(lowbucket))
goto err_and_decref_buckets;
COPY_KEY(first, lowbucket->keys[lowoffset]);
PER_UNUSE(lowbucket);
UNLESS (PER_USE(highbucket)) goto err_and_decref_buckets;
UNLESS (PER_USE(highbucket))
goto err_and_decref_buckets;
COPY_KEY(last, highbucket->keys[highoffset]);
PER_UNUSE(highbucket);
TEST_KEY_SET_OR(cmp, first, last) goto err_and_decref_buckets;
if (cmp > 0) goto empty_and_decref_buckets;
TEST_KEY_SET_OR(cmp, first, last)
goto err_and_decref_buckets;
if (cmp > 0)
goto empty_and_decref_buckets;
}
PER_UNUSE(self);
......@@ -1610,19 +1748,19 @@ BTree_rangeSearch(BTree *self, PyObject *args, PyObject *kw, char type)
Py_DECREF(highbucket);
return result;
err_and_decref_buckets:
err_and_decref_buckets:
Py_DECREF(lowbucket);
Py_DECREF(highbucket);
err:
err:
PER_UNUSE(self);
return NULL;
empty_and_decref_buckets:
empty_and_decref_buckets:
Py_DECREF(lowbucket);
Py_DECREF(highbucket);
empty:
empty:
PER_UNUSE(self);
return newBTreeItems(type, 0, 0, 0, 0);
}
......@@ -1663,57 +1801,71 @@ BTree_byValue(BTree *self, PyObject *omin)
int copied=1;
SetIteration it = {0, 0, 1};
UNLESS (PER_USE(self)) return NULL;
UNLESS (PER_USE(self))
return NULL;
COPY_VALUE_FROM_ARG(min, omin, copied);
UNLESS(copied) return NULL;
UNLESS(copied)
return NULL;
UNLESS (r=PyList_New(0)) goto err;
UNLESS (r=PyList_New(0))
goto err;
it.set=BTree_rangeSearch(self, NULL, NULL, 'i');
UNLESS(it.set) goto err;
UNLESS(it.set)
goto err;
if (nextBTreeItems(&it) < 0) goto err;
if (nextBTreeItems(&it) < 0)
goto err;
while (it.position >= 0)
{
if (TEST_VALUE(it.value, min) >= 0)
{
UNLESS (item = PyTuple_New(2)) goto err;
UNLESS (item = PyTuple_New(2))
goto err;
COPY_KEY_TO_OBJECT(o, it.key);
UNLESS (o) goto err;
UNLESS (o)
goto err;
PyTuple_SET_ITEM(item, 1, o);
COPY_VALUE(v, it.value);
NORMALIZE_VALUE(v, min);
COPY_VALUE_TO_OBJECT(o, v);
DECREF_VALUE(v);
UNLESS (o) goto err;
UNLESS (o)
goto err;
PyTuple_SET_ITEM(item, 0, o);
if (PyList_Append(r, item) < 0) goto err;
if (PyList_Append(r, item) < 0)
goto err;
Py_DECREF(item);
item = 0;
}
if (nextBTreeItems(&it) < 0) goto err;
if (nextBTreeItems(&it) < 0)
goto err;
}
item=PyObject_GetAttr(r,sort_str);
UNLESS (item) goto err;
UNLESS (item)
goto err;
ASSIGN(item, PyObject_CallObject(item, NULL));
UNLESS (item) goto err;
UNLESS (item)
goto err;
ASSIGN(item, PyObject_GetAttr(r, reverse_str));
UNLESS (item) goto err;
UNLESS (item)
goto err;
ASSIGN(item, PyObject_CallObject(item, NULL));
UNLESS (item) goto err;
UNLESS (item)
goto err;
Py_DECREF(item);
finiSetIteration(&it);
PER_UNUSE(self);
return r;
err:
err:
PER_UNUSE(self);
Py_XDECREF(r);
finiSetIteration(&it);
......@@ -1729,9 +1881,12 @@ BTree_getm(BTree *self, PyObject *args)
{
PyObject *key, *d=Py_None, *r;
UNLESS (PyArg_ParseTuple(args, "O|O", &key, &d)) return NULL;
if ((r=_BTree_get(self, key, 0))) return r;
UNLESS (PyErr_ExceptionMatches(PyExc_KeyError)) return NULL;
UNLESS (PyArg_ParseTuple(args, "O|O", &key, &d))
return NULL;
if ((r=_BTree_get(self, key, 0)))
return r;
UNLESS (PyErr_ExceptionMatches(PyExc_KeyError))
return NULL;
PyErr_Clear();
Py_INCREF(d);
return d;
......@@ -1787,9 +1942,11 @@ BTree_pop(BTree *self, PyObject *args)
return NULL;
value = _BTree_get(self, key, 0);
if (value != NULL) {
if (value != NULL)
{
/* Delete key and associated value. */
if (_BTree_set(self, key, NULL, 0, 0) < 0) {
if (_BTree_set(self, key, NULL, 0, 0) < 0)
{
Py_DECREF(value);
return NULL;;
}
......@@ -1802,7 +1959,8 @@ BTree_pop(BTree *self, PyObject *args)
if (! PyErr_ExceptionMatches(PyExc_KeyError))
return NULL;
if (failobj != NULL) {
if (failobj != NULL)
{
/* Clear the KeyError and return the explicit default. */
PyErr_Clear();
Py_INCREF(failobj);
......@@ -1831,8 +1989,9 @@ BTree_contains(BTree *self, PyObject *key)
PyObject *asobj = _BTree_get(self, key, 1);
int result = -1;
if (asobj != NULL) {
result = PyInt_AsLong(asobj) ? 1 : 0;
if (asobj != NULL)
{
result = INT_AS_LONG(asobj) ? 1 : 0;
Py_DECREF(asobj);
}
return result;
......@@ -1844,10 +2003,12 @@ BTree_addUnique(BTree *self, PyObject *args)
int grew;
PyObject *key, *v;
UNLESS (PyArg_ParseTuple(args, "OO", &key, &v)) return NULL;
UNLESS (PyArg_ParseTuple(args, "OO", &key, &v))
return NULL;
if ((grew=_BTree_set(self, key, v, 1, 0)) < 0) return NULL;
return PyInt_FromLong(grew);
if ((grew=_BTree_set(self, key, v, 1, 0)) < 0)
return NULL;
return INT_FROM_LONG(grew);
}
/**************************************************************************/
......@@ -1865,7 +2026,8 @@ buildBTreeIter(BTree *self, PyObject *args, PyObject *kw, char kind)
BTreeIter *result = NULL;
BTreeItems *items = (BTreeItems *)BTree_rangeSearch(self, args, kw, kind);
if (items) {
if (items)
{
result = BTreeIter_new(items);
Py_DECREF(items);
}
......@@ -1912,7 +2074,7 @@ BTree_iteritems(BTree *self, PyObject *args, PyObject *kw)
*/
static struct PyMemberDef BTree_members[] = {
{"_firstbucket", T_OBJECT, offsetof(BTree, firstbucket), RO},
{"_firstbucket", T_OBJECT, offsetof(BTree, firstbucket), READONLY},
{NULL}
};
......@@ -1993,14 +2155,15 @@ static struct PyMethodDef BTree_methods[] = {
"B.itervalues([min[,max]]) -> an iterator over the values of B"},
{"iteritems", (PyCFunction) BTree_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"},
{"_check", (PyCFunction) BTree_check, METH_NOARGS,
"Perform sanity check on BTree, and raise exception if flawed."},
#ifdef PERSISTENT
{"_p_resolveConflict", (PyCFunction) BTree__p_resolveConflict,
METH_VARARGS,
{"_p_resolveConflict",
(PyCFunction) BTree__p_resolveConflict, METH_VARARGS,
"_p_resolveConflict() -- Reinitialize from a newly created copy"},
{"_p_deactivate", (PyCFunction) BTree__p_deactivate, METH_KEYWORDS,
......@@ -2044,8 +2207,8 @@ BTree_traverse(BTree *self, visitproc visit, void *arg)
goto Done; \
}
if (self->ob_type == &BTreeType)
assert(self->ob_type->tp_dictoffset == 0);
if (Py_TYPE(self) == &BTreeType)
assert(Py_TYPE(self)->tp_dictoffset == 0);
/* Call our base type's traverse function. Because BTrees are
* subclasses of Peristent, there must be one.
......@@ -2076,7 +2239,7 @@ BTree_traverse(BTree *self, visitproc visit, void *arg)
VISIT(self->firstbucket);
Done:
Done:
return err;
#undef VISIT
......@@ -2119,7 +2282,8 @@ BTree_length_or_nonzero(BTree *self, int nonzero)
return b != NULL;
result = 0;
while (b) {
while (b)
{
PER_USE_OR_RETURN(b, -1);
result += b->len;
next = b->next;
......@@ -2136,9 +2300,9 @@ BTree_length(BTree *self)
}
static PyMappingMethods BTree_as_mapping = {
(lenfunc)BTree_length, /*mp_length*/
(binaryfunc)BTree_get, /*mp_subscript*/
(objobjargproc)BTree_setitem, /*mp_ass_subscript*/
(lenfunc)BTree_length, /* mp_length */
(binaryfunc)BTree_get, /* mp_subscript */
(objobjargproc)BTree_setitem, /* mp_ass_subscript */
};
static PySequenceMethods BTree_as_sequence = {
......@@ -2161,13 +2325,24 @@ BTree_nonzero(BTree *self)
}
static PyNumberMethods BTree_as_number_for_nonzero = {
0,0,0,0,0,0,0,0,0,0,
(inquiry)BTree_nonzero};
0, /* nb_add */
0, /* nb_subtract */
0, /* nb_multiply */
#ifndef PY3K
0, /* nb_divide */
#endif
0, /* nb_remainder */
0, /* nb_divmod */
0, /* nb_power */
0, /* nb_negative */
0, /* nb_positive */
0, /* nb_absolute */
(inquiry)BTree_nonzero /* nb_nonzero */
};
static PyTypeObject BTreeType = {
PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
0, /* ob_size */
MODULE_NAME MOD_NAME_PREFIX "BTree",/* tp_name */
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME MOD_NAME_PREFIX "BTree", /* tp_name */
sizeof(BTree), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)BTree_dealloc, /* tp_dealloc */
......@@ -2185,7 +2360,8 @@ static PyTypeObject BTreeType = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
(traverseproc)BTree_traverse, /* tp_traverse */
......
......@@ -87,19 +87,20 @@ _bucket_get(Bucket *self, PyObject *keyarg, int has_key)
BUCKET_SEARCH(i, cmp, self, key, goto Done);
if (has_key)
r = PyInt_FromLong(cmp ? 0 : has_key);
else {
if (cmp == 0) {
r = INT_FROM_LONG(cmp ? 0 : has_key);
else
{
if (cmp == 0)
{
COPY_VALUE_TO_OBJECT(r, self->values[i]);
}
else
PyErr_SetObject(PyExc_KeyError, keyarg);
}
Done:
Done:
PER_UNUSE(self);
return r;
}
static PyObject *
......@@ -129,7 +130,8 @@ Bucket_grow(Bucket *self, int newsize, int noval)
KEY_TYPE *keys;
VALUE_TYPE *values;
if (self->size) {
if (self->size)
{
if (newsize < 0)
newsize = self->size * 2;
if (newsize < 0) /* int overflow */
......@@ -137,9 +139,11 @@ Bucket_grow(Bucket *self, int newsize, int noval)
UNLESS (keys = BTree_Realloc(self->keys, sizeof(KEY_TYPE) * newsize))
return -1;
UNLESS (noval) {
UNLESS (noval)
{
values = BTree_Realloc(self->values, sizeof(VALUE_TYPE) * newsize);
if (values == NULL) {
if (values == NULL)
{
free(keys);
return -1;
}
......@@ -147,14 +151,17 @@ Bucket_grow(Bucket *self, int newsize, int noval)
}
self->keys = keys;
}
else {
else
{
if (newsize < 0)
newsize = MIN_BUCKET_ALLOC;
UNLESS (self->keys = BTree_Malloc(sizeof(KEY_TYPE) * newsize))
return -1;
UNLESS (noval) {
UNLESS (noval)
{
self->values = BTree_Malloc(sizeof(VALUE_TYPE) * newsize);
if (self->values == NULL) {
if (self->values == NULL)
{
free(self->keys);
self->keys = NULL;
return -1;
......@@ -164,7 +171,7 @@ Bucket_grow(Bucket *self, int newsize, int noval)
self->size = newsize;
return 0;
Overflow:
Overflow:
PyErr_NoMemory();
return -1;
}
......@@ -222,7 +229,8 @@ bucket_append(Bucket *self, Bucket *from, int i, int n,
/* Make room. */
newlen = self->len + n;
if (newlen > self->size) {
if (newlen > self->size)
{
int newsize = newlen;
if (overallocate) /* boost by 25% -- pretty arbitrary */
newsize += newsize >> 2;
......@@ -233,7 +241,8 @@ bucket_append(Bucket *self, Bucket *from, int i, int n,
/* Copy stuff. */
memcpy(self->keys + self->len, from->keys + i, n * sizeof(KEY_TYPE));
if (copyValues) {
if (copyValues)
{
assert(self->values);
assert(from->values);
memcpy(self->values + self->len, from->values + i,
......@@ -246,16 +255,19 @@ bucket_append(Bucket *self, Bucket *from, int i, int n,
{
int j;
PyObject **p = from->keys + i;
for (j = 0; j < n; ++j, ++p) {
for (j = 0; j < n; ++j, ++p)
{
Py_INCREF(*p);
}
}
#endif
#ifdef VALUE_TYPE_IS_PYOBJECT
if (copyValues) {
if (copyValues)
{
int j;
PyObject **p = from->values + i;
for (j = 0; j < n; ++j, ++p) {
for (j = 0; j < n; ++j, ++p)
{
Py_INCREF(*p);
}
}
......@@ -309,28 +321,33 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
int copied = 1;
COPY_KEY_FROM_ARG(key, keyarg, copied);
UNLESS(copied) return -1;
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;
}
UNLESS (PER_USE(self)) return -1;
UNLESS (PER_USE(self))
return -1;
BUCKET_SEARCH(i, cmp, self, key, goto Done);
if (cmp == 0) {
if (cmp == 0)
{
/* The key exists, at index i. */
if (v) {
if (v)
{
/* The key exists at index i, and there's a new value.
* 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 (unique || noval || self->values == NULL) {
if (unique || noval || self->values == NULL)
{
result = 0;
goto Done;
}
......@@ -338,7 +355,8 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
/* The key exists at index i, and we need to replace the value. */
#ifdef VALUE_SAME
/* short-circuit if no change */
if (VALUE_SAME(self->values[i], value)) {
if (VALUE_SAME(self->values[i], value))
{
result = 0;
goto Done;
}
......@@ -360,18 +378,21 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
memmove(self->keys + i, self->keys + i+1,
sizeof(KEY_TYPE)*(self->len - i));
if (self->values) {
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) {
if (! self->len)
{
self->size = 0;
free(self->keys);
self->keys = NULL;
if (self->values) {
if (self->values)
{
free(self->values);
self->values = NULL;
}
......@@ -385,7 +406,8 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
}
/* The key doesn't exist, and belongs at index i. */
if (!v) {
if (!v)
{
/* Can't delete a non-existent key. */
PyErr_SetObject(PyExc_KeyError, keyarg);
goto Done;
......@@ -395,10 +417,12 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
if (self->len == self->size && Bucket_grow(self, -1, noval) < 0)
goto Done;
if (self->len > i) {
if (self->len > i)
{
memmove(self->keys + i + 1, self->keys + i,
sizeof(KEY_TYPE) * (self->len - i));
if (self->values) {
if (self->values)
{
memmove(self->values + i + 1, self->values + i,
sizeof(VALUE_TYPE) * (self->len - i));
}
......@@ -407,7 +431,8 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
COPY_KEY(self->keys[i], key);
INCREF_KEY(self->keys[i]);
if (! noval) {
if (! noval)
{
COPY_VALUE(self->values[i], value);
INCREF_VALUE(self->values[i]);
}
......@@ -418,7 +443,7 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
if (PER_CHANGED(self) >= 0)
result = 1;
Done:
Done:
PER_UNUSE(self);
return result;
}
......@@ -462,7 +487,8 @@ update_from_seq(PyObject *map, PyObject *seq)
* want to use items() in those cases too.
*/
if (!PySequence_Check(seq) || /* or it "looks like a dict" */
PyObject_HasAttrString(seq, "iteritems")) {
PyObject_HasAttrString(seq, "iteritems"))
{
PyObject *items;
items = PyObject_GetAttrString(seq, "items");
if (items == NULL)
......@@ -478,15 +504,18 @@ update_from_seq(PyObject *map, PyObject *seq)
iter = PyObject_GetIter(seq);
if (iter == NULL)
goto err;
while (1) {
while (1)
{
o = PyIter_Next(iter);
if (o == NULL) {
if (o == NULL)
{
if (PyErr_Occurred())
goto err;
else
break;
}
if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != 2) {
if (!PyTuple_Check(o) || PyTuple_GET_SIZE(o) != 2)
{
Py_DECREF(o);
PyErr_SetString(PyExc_TypeError,
"Sequence must contain 2-item tuples");
......@@ -494,7 +523,8 @@ update_from_seq(PyObject *map, PyObject *seq)
}
k = PyTuple_GET_ITEM(o, 0);
v = PyTuple_GET_ITEM(o, 1);
if (PyObject_SetItem(map, k, v) < 0) {
if (PyObject_SetItem(map, k, v) < 0)
{
Py_DECREF(o);
goto err;
}
......@@ -502,7 +532,7 @@ update_from_seq(PyObject *map, PyObject *seq)
}
err = 0;
err:
err:
Py_DECREF(iter);
Py_DECREF(seq);
return err;
......@@ -585,12 +615,14 @@ Bucket_deleteNextBucket(Bucket *self)
PER_USE_OR_RETURN(self, -1);
successor = self->next;
if (successor) {
if (successor)
{
Bucket *next;
/* Before: self -> successor -> next
* After: self --------------> next
*/
UNLESS (PER_USE(successor)) goto Done;
UNLESS (PER_USE(successor))
goto Done;
next = successor->next;
PER_UNUSE(successor);
......@@ -602,7 +634,7 @@ Bucket_deleteNextBucket(Bucket *self)
}
result = 0;
Done:
Done:
PER_UNUSE(self);
return result;
}
......@@ -653,14 +685,17 @@ Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int exclude_equal,
int copied = 1;
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);
if (cmp == 0) {
/* exact match at index i */
if (exclude_equal) {
if (exclude_equal)
{
/* but we don't want an exact match */
if (low)
++i;
......@@ -679,7 +714,7 @@ Bucket_findRangeEnd(Bucket *self, PyObject *keyarg, int low, int exclude_equal,
if (result)
*offset = i;
Done:
Done:
PER_UNUSE(self);
return result;
}
......@@ -691,31 +726,36 @@ Bucket_maxminKey(Bucket *self, PyObject *args, int min)
int rc, offset = 0;
int empty_bucket = 1;
if (args && ! PyArg_ParseTuple(args, "|O", &key)) return NULL;
if (args && ! PyArg_ParseTuple(args, "|O", &key))
return NULL;
PER_USE_OR_RETURN(self, NULL);
UNLESS (self->len) goto empty;
UNLESS (self->len)
goto empty;
/* Find the low range */
if (key)
{
if ((rc = Bucket_findRangeEnd(self, key, min, 0, &offset)) <= 0)
{
if (rc < 0) return NULL;
if (rc < 0)
return NULL;
empty_bucket = 0;
goto empty;
}
}
else if (min) offset = 0;
else offset = self->len -1;
else if (min)
offset = 0;
else
offset = self->len -1;
COPY_KEY_TO_OBJECT(key, self->keys[offset]);
PER_UNUSE(self);
return key;
empty:
empty:
PyErr_SetString(PyExc_ValueError,
empty_bucket ? "empty bucket" :
"no key satisfies the conditions");
......@@ -745,7 +785,8 @@ Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
int excludemax = 0;
int rc;
if (args) {
if (args)
{
if (! PyArg_ParseTupleAndKeywords(args, kw, "|OOii", search_keywords,
&min,
&max,
......@@ -754,19 +795,23 @@ Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
return -1;
}
UNLESS (self->len) goto empty;
UNLESS (self->len)
goto empty;
/* Find the low range */
if (min != Py_None) {
if (min != Py_None)
{
rc = Bucket_findRangeEnd(self, min, 1, excludemin, low);
if (rc < 0)
return -1;
if (rc == 0)
goto empty;
}
else {
else
{
*low = 0;
if (excludemin) {
if (excludemin)
{
if (self->len < 2)
goto empty;
++*low;
......@@ -774,16 +819,19 @@ Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
}
/* Find the high range */
if (max != Py_None) {
if (max != Py_None)
{
rc = Bucket_findRangeEnd(self, max, 0, excludemax, high);
if (rc < 0)
return -1;
if (rc == 0)
goto empty;
}
else {
else
{
*high = self->len - 1;
if (excludemax) {
if (excludemax)
{
if (self->len < 2)
goto empty;
--*high;
......@@ -794,7 +842,7 @@ Bucket_rangeSearch(Bucket *self, PyObject *args, PyObject *kw,
if (*low <= *high)
return 0;
empty:
empty:
*low = 0;
*high = -1;
return 0;
......@@ -825,7 +873,8 @@ bucket_keys(Bucket *self, PyObject *args, PyObject *kw)
if (r == NULL)
goto err;
for (i=low; i <= high; i++) {
for (i=low; i <= high; i++)
{
COPY_KEY_TO_OBJECT(key, self->keys[i]);
if (PyList_SetItem(r, i-low , key) < 0)
goto err;
......@@ -834,7 +883,7 @@ bucket_keys(Bucket *self, PyObject *args, PyObject *kw)
PER_UNUSE(self);
return r;
err:
err:
PER_UNUSE(self);
Py_XDECREF(r);
return NULL;
......@@ -858,21 +907,25 @@ bucket_values(Bucket *self, PyObject *args, PyObject *kw)
PER_USE_OR_RETURN(self, NULL);
if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0) goto err;
if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
goto err;
UNLESS (r=PyList_New(high-low+1)) goto err;
UNLESS (r=PyList_New(high-low+1))
goto err;
for (i=low; i <= high; i++)
{
COPY_VALUE_TO_OBJECT(v, self->values[i]);
UNLESS (v) goto err;
if (PyList_SetItem(r, i-low, v) < 0) goto err;
UNLESS (v)
goto err;
if (PyList_SetItem(r, i-low, v) < 0)
goto err;
}
PER_UNUSE(self);
return r;
err:
err:
PER_UNUSE(self);
Py_XDECREF(r);
return NULL;
......@@ -896,23 +949,29 @@ bucket_items(Bucket *self, PyObject *args, PyObject *kw)
PER_USE_OR_RETURN(self, NULL);
if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0) goto err;
if (Bucket_rangeSearch(self, args, kw, &low, &high) < 0)
goto err;
UNLESS (r=PyList_New(high-low+1)) goto err;
UNLESS (r=PyList_New(high-low+1))
goto err;
for (i=low; i <= high; i++)
{
UNLESS (item = PyTuple_New(2)) goto err;
UNLESS (item = PyTuple_New(2))
goto err;
COPY_KEY_TO_OBJECT(o, self->keys[i]);
UNLESS (o) goto err;
UNLESS (o)
goto err;
PyTuple_SET_ITEM(item, 0, o);
COPY_VALUE_TO_OBJECT(o, self->values[i]);
UNLESS (o) goto err;
UNLESS (o)
goto err;
PyTuple_SET_ITEM(item, 1, o);
if (PyList_SetItem(r, i-low, item) < 0) goto err;
if (PyList_SetItem(r, i-low, item) < 0)
goto err;
item = 0;
}
......@@ -920,7 +979,7 @@ bucket_items(Bucket *self, PyObject *args, PyObject *kw)
PER_UNUSE(self);
return r;
err:
err:
PER_UNUSE(self);
Py_XDECREF(r);
Py_XDECREF(item);
......@@ -938,51 +997,62 @@ bucket_byValue(Bucket *self, PyObject *omin)
PER_USE_OR_RETURN(self, NULL);
COPY_VALUE_FROM_ARG(min, omin, copied);
UNLESS(copied) return NULL;
UNLESS(copied)
return NULL;
for (i=0, l=0; i < self->len; i++)
if (TEST_VALUE(self->values[i], min) >= 0)
l++;
UNLESS (r=PyList_New(l)) goto err;
UNLESS (r=PyList_New(l))
goto err;
for (i=0, l=0; i < self->len; i++)
{
if (TEST_VALUE(self->values[i], min) < 0) continue;
if (TEST_VALUE(self->values[i], min) < 0)
continue;
UNLESS (item = PyTuple_New(2)) goto err;
UNLESS (item = PyTuple_New(2))
goto err;
COPY_KEY_TO_OBJECT(o, self->keys[i]);
UNLESS (o) goto err;
UNLESS (o)
goto err;
PyTuple_SET_ITEM(item, 1, o);
COPY_VALUE(v, self->values[i]);
NORMALIZE_VALUE(v, min);
COPY_VALUE_TO_OBJECT(o, v);
DECREF_VALUE(v);
UNLESS (o) goto err;
UNLESS (o)
goto err;
PyTuple_SET_ITEM(item, 0, o);
if (PyList_SetItem(r, l, item) < 0) goto err;
if (PyList_SetItem(r, l, item) < 0)
goto err;
l++;
item = 0;
}
item=PyObject_GetAttr(r,sort_str);
UNLESS (item) goto err;
UNLESS (item)
goto err;
ASSIGN(item, PyObject_CallObject(item, NULL));
UNLESS (item) goto err;
UNLESS (item)
goto err;
ASSIGN(item, PyObject_GetAttr(r, reverse_str));
UNLESS (item) goto err;
UNLESS (item)
goto err;
ASSIGN(item, PyObject_CallObject(item, NULL));
UNLESS (item) goto err;
UNLESS (item)
goto err;
Py_DECREF(item);
PER_UNUSE(self);
return r;
err:
err:
PER_UNUSE(self);
Py_XDECREF(r);
Py_XDECREF(item);
......@@ -999,7 +1069,8 @@ _bucket_clear(Bucket *self)
*/
self->len = self->size = 0;
if (self->next) {
if (self->next)
{
Py_DECREF(self->next);
self->next = NULL;
}
......@@ -1008,7 +1079,8 @@ _bucket_clear(Bucket *self)
when neither key nor value is an object, i.e. II. */
(void)len;
if (self->keys) {
if (self->keys)
{
#ifdef KEY_TYPE_IS_PYOBJECT
int i;
for (i = 0; i < len; ++i)
......@@ -1018,7 +1090,8 @@ _bucket_clear(Bucket *self)
self->keys = NULL;
}
if (self->values) {
if (self->values)
{
#ifdef VALUE_TYPE_IS_PYOBJECT
int i;
for (i = 0; i < len; ++i)
......@@ -1037,12 +1110,14 @@ bucket__p_deactivate(Bucket *self, PyObject *args, PyObject *keywords)
int ghostify = 1;
PyObject *force = NULL;
if (args && PyTuple_GET_SIZE(args) > 0) {
if (args && PyTuple_GET_SIZE(args) > 0)
{
PyErr_SetString(PyExc_TypeError,
"_p_deactivate takes no positional arguments");
return NULL;
}
if (keywords) {
if (keywords)
{
int size = PyDict_Size(keywords);
force = PyDict_GetItemString(keywords, "force");
if (force)
......@@ -1054,7 +1129,8 @@ bucket__p_deactivate(Bucket *self, PyObject *args, PyObject *keywords)
}
}
if (self->jar && self->oid) {
if (self->jar && self->oid)
{
ghostify = self->state == cPersistent_UPTODATE_STATE;
if (!ghostify && force) {
if (PyObject_IsTrue(force))
......@@ -1078,7 +1154,8 @@ bucket_clear(Bucket *self, PyObject *args)
{
PER_USE_OR_RETURN(self, NULL);
if (self->len) {
if (self->len)
{
if (_bucket_clear(self) < 0)
return NULL;
if (PER_CHANGED(self) < 0)
......@@ -1088,7 +1165,7 @@ bucket_clear(Bucket *self, PyObject *args)
Py_INCREF(Py_None);
return Py_None;
err:
err:
PER_UNUSE(self);
return NULL;
}
......@@ -1126,7 +1203,8 @@ bucket_getstate(Bucket *self)
len = self->len;
if (self->values) { /* Bucket */
if (self->values) /* Bucket */
{
items = PyTuple_New(len * 2);
if (items == NULL)
goto err;
......@@ -1143,7 +1221,9 @@ bucket_getstate(Bucket *self)
PyTuple_SET_ITEM(items, l, o);
l++;
}
} else { /* Set */
}
else /* Set */
{
items = PyTuple_New(len);
if (items == NULL)
goto err;
......@@ -1164,7 +1244,7 @@ bucket_getstate(Bucket *self)
PER_UNUSE(self);
return state;
err:
err:
PER_UNUSE(self);
Py_XDECREF(items);
return NULL;
......@@ -1355,7 +1435,7 @@ bucket_contains(Bucket *self, PyObject *key)
int result = -1;
if (asobj != NULL) {
result = PyInt_AsLong(asobj) ? 1 : 0;
result = INT_AS_LONG(asobj) ? 1 : 0;
Py_DECREF(asobj);
}
return result;
......@@ -1404,12 +1484,13 @@ buildBucketIter(Bucket *self, PyObject *args, PyObject *kw, char kind)
items = (BTreeItems *)newBTreeItems(kind, self, lowoffset,
self, highoffset);
if (items == NULL) goto Done;
if (items == NULL)
goto Done;
result = BTreeIter_new(items); /* win or lose, we're done */
Py_DECREF(items);
Done:
Done:
PER_UNUSE(self);
return (PyObject *)result;
}
......@@ -1487,7 +1568,7 @@ _bucket__p_resolveConflict(PyObject *ob_type, PyObject *s[3])
else
result = bucket_merge(b[0], b[1], b[2]);
Done:
Done:
Py_XDECREF(meth);
Py_XDECREF(a);
Py_XDECREF(b[0]);
......@@ -1505,7 +1586,7 @@ bucket__p_resolveConflict(Bucket *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OOO", &s[0], &s[1], &s[2]))
return NULL;
return _bucket__p_resolveConflict((PyObject *)self->ob_type, s);
return _bucket__p_resolveConflict((PyObject *)Py_TYPE(self), s);
}
#endif
......@@ -1580,15 +1661,16 @@ static struct PyMethodDef Bucket_methods[] = {
"B.itervalues([min[,max]]) -> an iterator over the values of B"},
{"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
EXTRA_BUCKET_METHODS
#endif
#ifdef PERSISTENT
{"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict,
METH_VARARGS,
{"_p_resolveConflict",
(PyCFunction) bucket__p_resolveConflict, METH_VARARGS,
"_p_resolveConflict() -- Reinitialize from a newly created copy"},
{"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_KEYWORDS,
......@@ -1648,8 +1730,10 @@ bucket_traverse(Bucket *self, visitproc visit, void *arg)
goto Done;
len = self->len;
(void)i; /* if neither keys nor values are PyObject*, "i" is otherwise
/* if neither keys nor values are PyObject*, "i" is otherwise
unreferenced and we get a nuisance compiler wng */
(void)i;
(void)len;
#ifdef KEY_TYPE_IS_PYOBJECT
/* Keys are Python objects so need to be traversed. */
for (i = 0; i < len; i++)
......@@ -1667,7 +1751,7 @@ bucket_traverse(Bucket *self, visitproc visit, void *arg)
VISIT(self->next);
Done:
Done:
return err;
#undef VISIT
......@@ -1686,7 +1770,8 @@ static int
Bucket_length( Bucket *self)
{
int r;
UNLESS (PER_USE(self)) return -1;
UNLESS (PER_USE(self))
return -1;
r = self->len;
PER_UNUSE(self);
return r;
......@@ -1720,42 +1805,46 @@ bucket_repr(Bucket *self)
i = bucket_items(self, NULL, NULL);
if (!i)
{
return NULL;
}
r = PyObject_Repr(i);
Py_DECREF(i);
if (!r) {
if (!r)
{
return NULL;
}
rv = PyOS_snprintf(repr, sizeof(repr),
"%s(%s)", self->ob_type->tp_name,
PyString_AS_STRING(r));
if (rv > 0 && rv < sizeof(repr)) {
"%s(%s)", Py_TYPE(self)->tp_name,
PyBytes_AS_STRING(r));
if (rv > 0 && rv < sizeof(repr))
{
Py_DECREF(r);
return PyString_FromStringAndSize(repr, strlen(repr));
return PyBytes_FromStringAndSize(repr, strlen(repr));
}
else {
else
{
/* The static buffer wasn't big enough */
int size;
PyObject *s;
/* 3 for the parens and the null byte */
size = strlen(self->ob_type->tp_name) + PyString_GET_SIZE(r) + 3;
s = PyString_FromStringAndSize(NULL, size);
size = strlen(Py_TYPE(self)->tp_name) + PyBytes_GET_SIZE(r) + 3;
s = PyBytes_FromStringAndSize(NULL, size);
if (!s) {
Py_DECREF(r);
return r;
}
PyOS_snprintf(PyString_AS_STRING(s), size,
"%s(%s)", self->ob_type->tp_name, PyString_AS_STRING(r));
PyOS_snprintf(PyBytes_AS_STRING(s), size,
"%s(%s)", Py_TYPE(self)->tp_name, PyBytes_AS_STRING(r));
Py_DECREF(r);
return s;
}
}
static PyTypeObject BucketType = {
PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
0, /* ob_size */
MODULE_NAME MOD_NAME_PREFIX "Bucket",/* tp_name */
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME MOD_NAME_PREFIX "Bucket", /* tp_name */
sizeof(Bucket), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)bucket_dealloc, /* tp_dealloc */
......@@ -1773,7 +1862,8 @@ static PyTypeObject BucketType = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
(traverseproc)bucket_traverse, /* tp_traverse */
......@@ -1800,7 +1890,8 @@ nextBucket(SetIteration *i)
{
if (i->position >= 0)
{
UNLESS(PER_USE(BUCKET(i->set))) return -1;
UNLESS(PER_USE(BUCKET(i->set)))
return -1;
if (i->position)
{
......@@ -1825,6 +1916,5 @@ nextBucket(SetIteration *i)
PER_ALLOW_DEACTIVATION(BUCKET(i->set));
}
return 0;
}
......@@ -11,6 +11,7 @@
FOR A PARTICULAR PURPOSE
****************************************************************************/
#include "_compat.h"
#define SETTEMPLATE_C "$Id$\n"
......@@ -20,9 +21,11 @@ Set_insert(Bucket *self, PyObject *args)
PyObject *key;
int i;
UNLESS (PyArg_ParseTuple(args, "O", &key)) return NULL;
if ( (i=_bucket_set(self, key, Py_None, 1, 1, 0)) < 0) return NULL;
return PyInt_FromLong(i);
UNLESS (PyArg_ParseTuple(args, "O", &key))
return NULL;
if ( (i=_bucket_set(self, key, Py_None, 1, 1, 0)) < 0)
return NULL;
return INT_FROM_LONG(i);
}
/* _Set_update and _TreeSet_update are identical except for the
......@@ -55,7 +58,7 @@ _Set_update(Bucket *self, PyObject *seq)
n += ind;
}
err:
err:
Py_DECREF(iter);
if (ind < 0)
return -1;
......@@ -77,7 +80,7 @@ Set_update(Bucket *self, PyObject *args)
return NULL;
}
return PyInt_FromLong(n);
return INT_FROM_LONG(n);
}
static PyObject *
......@@ -85,8 +88,10 @@ Set_remove(Bucket *self, PyObject *args)
{
PyObject *key;
UNLESS (PyArg_ParseTuple(args, "O", &key)) return NULL;
if (_bucket_set(self, key, NULL, 0, 1, 0) < 0) return NULL;
UNLESS (PyArg_ParseTuple(args, "O", &key))
return NULL;
if (_bucket_set(self, key, NULL, 0, 1, 0) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
......@@ -109,7 +114,8 @@ _set_setstate(Bucket *self, PyObject *args)
return -1;
}
if ((l=PyTuple_Size(items)) < 0) return -1;
if ((l=PyTuple_Size(items)) < 0)
return -1;
for (i=self->len; --i >= 0; )
{
......@@ -125,7 +131,8 @@ _set_setstate(Bucket *self, PyObject *args)
if (l > self->size)
{
UNLESS (keys=BTree_Realloc(self->keys, sizeof(KEY_TYPE)*l)) return -1;
UNLESS (keys=BTree_Realloc(self->keys, sizeof(KEY_TYPE)*l))
return -1;
self->keys=keys;
self->size=l;
}
......@@ -134,7 +141,8 @@ _set_setstate(Bucket *self, PyObject *args)
{
k=PyTuple_GET_ITEM(items, i);
COPY_KEY_FROM_ARG(self->keys[i], k, copied);
UNLESS (copied) return -1;
UNLESS (copied)
return -1;
INCREF_KEY(self->keys[i]);
}
......@@ -154,13 +162,15 @@ set_setstate(Bucket *self, PyObject *args)
{
int r;
UNLESS (PyArg_ParseTuple(args, "O", &args)) return NULL;
UNLESS (PyArg_ParseTuple(args, "O", &args))
return NULL;
PER_PREVENT_DEACTIVATION(self);
r=_set_setstate(self, args);
PER_UNUSE(self);
if (r < 0) return NULL;
if (r < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -190,7 +200,8 @@ static struct PyMethodDef Set_methods[] = {
"If an argument is given, find the minimum >= the argument"},
#ifdef PERSISTENT
{"_p_resolveConflict", (PyCFunction) bucket__p_resolveConflict, METH_VARARGS,
{"_p_resolveConflict",
(PyCFunction) bucket__p_resolveConflict, METH_VARARGS,
"_p_resolveConflict() -- Reinitialize from a newly created copy"},
{"_p_deactivate", (PyCFunction) bucket__p_deactivate, METH_KEYWORDS,
......@@ -235,12 +246,14 @@ set_repr(Bucket *self)
PyObject *r, *t;
if (!format)
format = PyString_FromString(MOD_NAME_PREFIX "Set(%s)");
UNLESS (t = PyTuple_New(1)) return NULL;
UNLESS (r = bucket_keys(self, NULL, NULL)) goto err;
format = TEXT_FROM_STRING(MOD_NAME_PREFIX "Set(%s)");
UNLESS (t = PyTuple_New(1))
return NULL;
UNLESS (r = bucket_keys(self, NULL, NULL))
goto err;
PyTuple_SET_ITEM(t, 0, r);
r = t;
ASSIGN(r, PyString_Format(format, r));
ASSIGN(r, TEXT_FORMAT(format, r));
return r;
err:
Py_DECREF(t);
......@@ -291,8 +304,7 @@ static PySequenceMethods set_as_sequence = {
};
static PyTypeObject SetType = {
PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
0, /* ob_size */
PyVarObject_HEAD_INIT(NULL, 0) /* PyPersist_Type */
MODULE_NAME MOD_NAME_PREFIX "Set", /* tp_name */
sizeof(Bucket), /* tp_basicsize */
0, /* tp_itemsize */
......@@ -311,7 +323,8 @@ static PyTypeObject SetType = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
(traverseproc)bucket_traverse, /* tp_traverse */
......@@ -339,7 +352,8 @@ nextSet(SetIteration *i)
if (i->position >= 0)
{
UNLESS(PER_USE(BUCKET(i->set))) return -1;
UNLESS(PER_USE(BUCKET(i->set)))
return -1;
if (i->position)
{
......
......@@ -11,6 +11,7 @@
FOR A PARTICULAR PURPOSE
****************************************************************************/
#include "_compat.h"
#define TREESETTEMPLATE_C "$Id$\n"
......@@ -25,7 +26,7 @@ TreeSet_insert(BTree *self, PyObject *args)
i = _BTree_set(self, key, Py_None, 1, 1);
if (i < 0)
return NULL;
return PyInt_FromLong(i);
return INT_FROM_LONG(i);
}
/* _Set_update and _TreeSet_update are identical except for the
......@@ -42,9 +43,11 @@ _TreeSet_update(BTree *self, PyObject *seq)
if (iter == NULL)
return -1;
while (1) {
while (1)
{
v = PyIter_Next(iter);
if (v == NULL) {
if (v == NULL)
{
if (PyErr_Occurred())
goto err;
else
......@@ -58,7 +61,7 @@ _TreeSet_update(BTree *self, PyObject *seq)
n += ind;
}
err:
err:
Py_DECREF(iter);
if (ind < 0)
return -1;
......@@ -74,13 +77,14 @@ TreeSet_update(BTree *self, PyObject *args)
if (!PyArg_ParseTuple(args, "|O:update", &seq))
return NULL;
if (seq) {
if (seq)
{
n = _TreeSet_update(self, seq);
if (n < 0)
return NULL;
}
return PyInt_FromLong(n);
return INT_FROM_LONG(n);
}
......@@ -89,8 +93,10 @@ TreeSet_remove(BTree *self, PyObject *args)
{
PyObject *key;
UNLESS (PyArg_ParseTuple(args, "O", &key)) return NULL;
if (_BTree_set(self, key, NULL, 0, 1) < 0) return NULL;
UNLESS (PyArg_ParseTuple(args, "O", &key))
return NULL;
if (_BTree_set(self, key, NULL, 0, 1) < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
......@@ -100,18 +106,21 @@ TreeSet_setstate(BTree *self, PyObject *args)
{
int r;
if (!PyArg_ParseTuple(args,"O",&args)) return NULL;
if (!PyArg_ParseTuple(args,"O",&args))
return NULL;
PER_PREVENT_DEACTIVATION(self);
r=_BTree_setstate(self, args, 1);
PER_UNUSE(self);
if (r < 0) return NULL;
if (r < 0)
return NULL;
Py_INCREF(Py_None);
return Py_None;
}
static struct PyMethodDef TreeSet_methods[] = {
static struct PyMethodDef TreeSet_methods[] =
{
{"__getstate__", (PyCFunction) BTree_getstate, METH_NOARGS,
"__getstate__() -> state\n\n"
"Return the picklable state of the TreeSet."},
......@@ -158,7 +167,8 @@ static struct PyMethodDef TreeSet_methods[] = {
"Perform sanity check on TreeSet, and raise exception if flawed."},
#ifdef PERSISTENT
{"_p_resolveConflict", (PyCFunction) BTree__p_resolveConflict, METH_VARARGS,
{"_p_resolveConflict",
(PyCFunction) BTree__p_resolveConflict, METH_VARARGS,
"_p_resolveConflict() -- Reinitialize from a newly created copy"},
{"_p_deactivate", (PyCFunction) BTree__p_deactivate, METH_KEYWORDS,
......@@ -198,10 +208,10 @@ TreeSet_init(PyObject *self, PyObject *args, PyObject *kwds)
return 0;
}
static PyTypeObject TreeSetType = {
PyObject_HEAD_INIT(NULL) /* PyPersist_Type */
0, /* ob_size */
MODULE_NAME MOD_NAME_PREFIX "TreeSet",/* tp_name */
static PyTypeObject TreeSetType =
{
PyVarObject_HEAD_INIT(NULL, 0)
MODULE_NAME MOD_NAME_PREFIX "TreeSet", /* tp_name */
sizeof(BTree), /* tp_basicsize */
0, /* tp_itemsize */
(destructor)BTree_dealloc, /* tp_dealloc */
......@@ -219,7 +229,8 @@ static PyTypeObject TreeSetType = {
0, /* tp_getattro */
0, /* tp_setattro */
0, /* tp_as_buffer */
Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_DEFAULT |
Py_TPFLAGS_HAVE_GC |
Py_TPFLAGS_BASETYPE, /* tp_flags */
0, /* tp_doc */
(traverseproc)BTree_traverse, /* tp_traverse */
......
/* Straddle Python 2 / 3 */
#ifndef BTREES__COMPAT_H
#define BTREES__COMPAT_H
#if PY_MAJOR_VERSION >= 3
#ifdef INTERN
#undef INTERN
#endif
#ifdef INT_FROM_LONG
#undef INT_FROM_LONG
#endif
#ifdef INT_CHECK
#undef INT_CHECK
#endif
#define PY3K
#define INTERN PyUnicode_InternFromString
#define INT_FROM_LONG(x) PyLong_FromLong(x)
#define INT_CHECK(x) PyLong_Check(x)
#define INT_AS_LONG(x) PyLong_AS_LONG(x)
#define INT_GETMAX(x) 2<<31
#define TEXT_FROM_STRING PyUnicode_FromString
#define TEXT_FORMAT PyUnicode_Format
#define COMPARE(lhs, rhs) \
PyObject_RichCompareBool((lhs), (rhs), Py_LT) > 0 ? -1 : \
(PyObject_RichCompareBool((lhs), (rhs), Py_EQ) > 0 ? 0 : 1)
#else
#define INTERN PyString_InternFromString
#define INT_FROM_LONG(x) PyInt_FromLong(x)
#define INT_CHECK(x) PyInt_Check(x)
#define INT_AS_LONG(x) PyInt_AS_LONG(x)
#define INT_GETMAX(x) PyInt_GetMax(x)
#define TEXT_FROM_STRING PyString_FromString
#define TEXT_FORMAT PyString_Format
#define COMPARE(lhs, rhs) PyObject_Compare((lhs), (rhs))
#endif
#endif /* BTREES__COMPAT_H */
......@@ -40,14 +40,14 @@ typedef unsigned char char6[6];
#define KEYMACROS_H "$Id$\n"
#define KEY_TYPE char2
#undef KEY_TYPE_IS_PYOBJECT
#define KEY_CHECK(K) (PyString_Check(K) && PyString_GET_SIZE(K)==2)
#define KEY_CHECK(K) (PyBytes_Check(K) && PyBytes_GET_SIZE(K)==2)
#define TEST_KEY_SET_OR(V, K, T) if ( ( (V) = ((*(K) < *(T) || (*(K) == *(T) && (K)[1] < (T)[1])) ? -1 : ((*(K) == *(T) && (K)[1] == (T)[1]) ? 0 : 1)) ), 0 )
#define DECREF_KEY(KEY)
#define INCREF_KEY(k)
#define COPY_KEY(KEY, E) (*(KEY)=*(E), (KEY)[1]=(E)[1])
#define COPY_KEY_TO_OBJECT(O, K) O=PyString_FromStringAndSize((const char*)K,2)
#define COPY_KEY_TO_OBJECT(O, K) O=PyBytes_FromStringAndSize((const char*)K,2)
#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \
if (KEY_CHECK(ARG)) memcpy(TARGET, PyString_AS_STRING(ARG), 2); else { \
if (KEY_CHECK(ARG)) memcpy(TARGET, PyBytes_AS_STRING(ARG), 2); else { \
PyErr_SetString(PyExc_TypeError, "expected two-character string key"); \
(STATUS)=0; }
......@@ -59,10 +59,10 @@ typedef unsigned char char6[6];
#define DECREF_VALUE(k)
#define INCREF_VALUE(k)
#define COPY_VALUE(V, E) (memcpy(V, E, 6))
#define COPY_VALUE_TO_OBJECT(O, K) O=PyString_FromStringAndSize((const char*)K,6)
#define COPY_VALUE_TO_OBJECT(O, K) O=PyBytes_FromStringAndSize((const char*)K,6)
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
if ((PyString_Check(ARG) && PyString_GET_SIZE(ARG)==6)) \
memcpy(TARGET, PyString_AS_STRING(ARG), 6); else { \
if ((PyBytes_Check(ARG) && PyBytes_GET_SIZE(ARG)==6)) \
memcpy(TARGET, PyBytes_AS_STRING(ARG), 6); else { \
PyErr_SetString(PyExc_TypeError, "expected six-character string key"); \
(STATUS)=0; }
......@@ -93,11 +93,11 @@ bucket_toString(PyObject *oself)
len = self->len;
items = PyString_FromStringAndSize(NULL, len*8);
items = PyBytes_FromStringAndSize(NULL, len*8);
if (items == NULL)
goto err;
memcpy(PyString_AS_STRING(items), self->keys, len*2);
memcpy(PyString_AS_STRING(items)+len*2, self->values, len*6);
memcpy(PyBytes_AS_STRING(items), self->keys, len*2);
memcpy(PyBytes_AS_STRING(items)+len*2, self->values, len*6);
PER_UNUSE(self);
return items;
......@@ -116,7 +116,7 @@ bucket_fromString(PyObject *oself, PyObject *state)
KEY_TYPE *keys;
VALUE_TYPE *values;
len = PyString_Size(state);
len = PyBytes_Size(state);
if (len < 0)
return NULL;
......@@ -144,8 +144,8 @@ bucket_fromString(PyObject *oself, PyObject *state)
self->size = len;
}
memcpy(self->keys, PyString_AS_STRING(state), len*2);
memcpy(self->values, PyString_AS_STRING(state)+len*2, len*6);
memcpy(self->keys, PyBytes_AS_STRING(state), len*2);
memcpy(self->values, PyBytes_AS_STRING(state)+len*2, len*6);
self->len = len;
......
......@@ -13,7 +13,7 @@
#define COPY_VALUE_TO_OBJECT(O, K) O=PyFloat_FromDouble(K)
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
if (PyFloat_Check(ARG)) TARGET = (float)PyFloat_AsDouble(ARG); \
else if (PyInt_Check(ARG)) TARGET = (float)PyInt_AsLong(ARG); \
else if (INT_CHECK(ARG)) TARGET = (float)INT_AS_LONG(ARG); \
else { \
PyErr_SetString(PyExc_TypeError, "expected float or int value"); \
(STATUS)=0; (TARGET)=0; }
......
......@@ -8,7 +8,7 @@
#define KEY_CHECK longlong_check
#define COPY_KEY_TO_OBJECT(O, K) O=longlong_as_object(K)
#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \
if (PyInt_Check(ARG)) TARGET=PyInt_AS_LONG(ARG); else \
if (INT_CHECK(ARG)) TARGET=INT_AS_LONG(ARG); else \
if (longlong_check(ARG)) TARGET=PyLong_AsLongLong(ARG); else \
if (PyLong_Check(ARG)) { \
PyErr_SetString(PyExc_ValueError, "long integer out of range"); \
......@@ -19,11 +19,11 @@
#else
/* C int as key */
#define KEY_TYPE int
#define KEY_CHECK PyInt_Check
#define COPY_KEY_TO_OBJECT(O, K) O=PyInt_FromLong(K)
#define KEY_CHECK INT_CHECK
#define COPY_KEY_TO_OBJECT(O, K) O=INT_FROM_LONG(K)
#define COPY_KEY_FROM_ARG(TARGET, ARG, STATUS) \
if (PyInt_Check(ARG)) { \
long vcopy = PyInt_AS_LONG(ARG); \
if (INT_CHECK(ARG)) { \
long vcopy = INT_AS_LONG(ARG); \
if ((int)vcopy != vcopy) { \
PyErr_SetString(PyExc_TypeError, "integer out of range"); \
(STATUS)=0; (TARGET)=0; \
......
......@@ -7,7 +7,7 @@
#define VALUE_PARSE "L"
#define COPY_VALUE_TO_OBJECT(O, K) O=longlong_as_object(K)
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
if (PyInt_Check(ARG)) TARGET=PyInt_AS_LONG(ARG); else \
if (INT_CHECK(ARG)) TARGET=INT_AS_LONG(ARG); else \
if (longlong_check(ARG)) TARGET=PyLong_AsLongLong(ARG); else \
if (PyLong_Check(ARG)) { \
PyErr_SetString(PyExc_ValueError, "long integer out of range"); \
......@@ -18,11 +18,11 @@
#else
#define VALUE_TYPE int
#define VALUE_PARSE "i"
#define COPY_VALUE_TO_OBJECT(O, K) O=PyInt_FromLong(K)
#define COPY_VALUE_TO_OBJECT(O, K) O=INT_FROM_LONG(K)
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
if (PyInt_Check(ARG)) { \
long vcopy = PyInt_AS_LONG(ARG); \
if (INT_CHECK(ARG)) { \
long vcopy = INT_AS_LONG(ARG); \
if ((int)vcopy != vcopy) { \
PyErr_SetString(PyExc_TypeError, "integer out of range"); \
(STATUS)=0; (TARGET)=0; \
......
......@@ -3,6 +3,7 @@
#define KEY_TYPE_IS_PYOBJECT
#include "Python.h"
#include "_compat.h"
static PyObject *object_;
......@@ -15,12 +16,9 @@ check_argument_cmp(PyObject *arg)
/* arg->ob_type->tp_compare, */
/* ((PyTypeObject *)object_)->ob_type->tp_compare); */
if (arg->ob_type->tp_richcompare == NULL
&&
#if PY_MAJOR_VERSION==2 && PY_MINOR_VERSION < 6
arg->ob_type->tp_compare == NULL
#else
arg->ob_type->tp_compare ==
if (Py_TYPE(arg)->tp_richcompare == NULL
#ifndef PY3K
&& Py_TYPE(arg)->tp_compare ==
((PyTypeObject *)object_)->ob_type->tp_compare
#endif
)
......@@ -31,7 +29,8 @@ check_argument_cmp(PyObject *arg)
return 1;
}
#define TEST_KEY_SET_OR(V, KEY, TARGET) if ( ( (V) = PyObject_Compare((KEY),(TARGET)) ), PyErr_Occurred() )
#define TEST_KEY_SET_OR(V, KEY, TARGET) \
if ( ( (V) = COMPARE((KEY),(TARGET)) ), PyErr_Occurred() )
#define INCREF_KEY(k) Py_INCREF(k)
#define DECREF_KEY(KEY) Py_DECREF(KEY)
#define COPY_KEY(KEY, E) KEY=(E)
......
#define VALUEMACROS_H "$Id$\n"
#define VALUE_TYPE PyObject *
#define VALUE_TYPE_IS_PYOBJECT
#define TEST_VALUE(VALUE, TARGET) PyObject_Compare((VALUE),(TARGET))
#define TEST_VALUE(VALUE, TARGET) COMPARE((VALUE),(TARGET))
#define DECLARE_VALUE(NAME) VALUE_TYPE NAME
#define INCREF_VALUE(k) Py_INCREF(k)
#define DECREF_VALUE(k) Py_DECREF(k)
......
/* Backport type definitions from Python 2.5's object.h */
#ifndef BTREE_PY24COMPATH_H
#define BTREE_PY24COMPAT_H
#if PY_VERSION_HEX < 0x02050000
typedef Py_ssize_t (*lenfunc)(PyObject *);
typedef PyObject *(*ssizeargfunc)(PyObject *, Py_ssize_t);
typedef PyObject *(*ssizessizeargfunc)(PyObject *, Py_ssize_t, Py_ssize_t);
typedef int(*ssizeobjargproc)(PyObject *, Py_ssize_t, PyObject *);
typedef int(*ssizessizeobjargproc)(PyObject *, Py_ssize_t, Py_ssize_t, PyObject *);
#endif /* PY_VERSION_HEX */
#endif /* BTREE_PY24COMPAT_H */
......@@ -100,16 +100,22 @@ is_jython = 'java' in sys.platform
# Jython cannot build the C optimizations, while on PyPy they are
# anti-optimizations (the C extension compatibility layer is known-slow,
# and defeats JIT opportunities).
if pure_python or is_pypy or is_jython or sys.version_info[0] > 2:
if pure_python or is_pypy or is_jython:
ext_modules = []
else:
ext_modules = [BTreeExtension(family) for family in FAMILIES]
REQUIRES = [
if sys.version_info[0] > 3:
REQUIRES = [
'persistent>=4.0.4',
'zope.interface',
]
else:
REQUIRES = [
'persistent',
'zope.interface',
]
]
TESTS_REQUIRE = REQUIRES + ['transaction']
setup(name='BTrees',
......
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