Commit c8d5ea24 authored by Tim Peters's avatar Tim Peters

Merge rev 28586 from Zope3/branches/jim-index-restructure-2004-12.

This adds a new IFBTree type, intended for use in indices.  Still
needs NEWS, still needs docs, and there are a pile of legitimate
compiler warnings on Windows that need fixing.
parent a561cc4e
......@@ -69,7 +69,7 @@ base_btrees_depends = [
"src/persistent/cPersistence.h",
]
_flavors = {"O": "object", "I": "int"}
_flavors = {"O": "object", "I": "int", "F": "float"}
KEY_H = "src/BTrees/%skeymacros.h"
VALUE_H = "src/BTrees/%svaluemacros.h"
......@@ -87,7 +87,8 @@ def BTreeExtension(flavor):
kwargs["define_macros"] = [('EXCLUDE_INTSET_SUPPORT', None)]
return Extension(name, sources, **kwargs)
exts = [BTreeExtension(flavor) for flavor in ["OO", "IO", "OI", "II", "fs"]]
exts = [BTreeExtension(flavor)
for flavor in ("OO", "IO", "OI", "II", "IF", "fs")]
cPersistence = Extension(name = 'persistent.cPersistence',
include_dirs = include,
......
##############################################################################
#
# Copyright (c) 2001, 2002 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
# hack to overcome dynamic-linking headache.
from _IFBTree import *
......@@ -40,6 +40,25 @@
depends-on sorters.c
</extension>
<extension _IFBTree>
source _IFBTree.c
# Specialization:
depends-on intkeymacros.h
depends-on floatvaluemacros.h
# Common btree includes:
depends-on BTreeItemsTemplate.c
depends-on BTreeModuleTemplate.c
depends-on BTreeTemplate.c
depends-on BucketTemplate.c
depends-on MergeTemplate.c
depends-on SetOpTemplate.c
depends-on SetTemplate.c
depends-on TreeSetTemplate.c
depends-on sorters.c
</extension>
<extension _IOBTree>
source _IOBTree.c
......
......@@ -143,7 +143,14 @@ initSetIteration(SetIteration *i, PyObject *s, int useValues)
#endif
static int
copyRemaining(Bucket *r, SetIteration *i, int merge, int w)
copyRemaining(Bucket *r, SetIteration *i, int merge,
/* See comment # 42 */
#ifdef MERGE
VALUE_TYPE w)
#else
int w)
#endif
{
while (i->position >= 0)
{
......@@ -193,8 +200,25 @@ copyRemaining(Bucket *r, SetIteration *i, int merge, int w)
static PyObject *
set_operation(PyObject *s1, PyObject *s2,
int usevalues1, int usevalues2,
/* Comment # 42
The following ifdef works around a template/type problem
Weights are passed as integers. In particular, the weight passed by
difference is one. This works find in the int value and float value
cases but makes no sense in the object value case. In the object
value case, we don't do merging, so we don't use the weights, so it
doesn't matter what they are.
*/
#ifdef MERGE
VALUE_TYPE w1, VALUE_TYPE w2,
#else
int w1, int w2,
#endif
int c1, int c12, int c2)
{
Bucket *r=0;
SetIteration i1 = {0,0,0}, i2 = {0,0,0};
......@@ -214,9 +238,16 @@ set_operation(PyObject *s1, PyObject *s2,
SetIteration t;
int i;
/* See comment # 42 above */
#ifdef MERGE
VALUE_TYPE v;
#else
int v;
#endif
t=i1; i1=i2; i2=t;
i=c1; c1=c2; c2=i;
i=w1; w1=w2; w2=i;
v=w1; w1=w2; w2=v;
}
#ifdef MERGE_DEFAULT
i1.value=MERGE_DEFAULT;
......@@ -394,17 +425,20 @@ static PyObject *
wunion_m(PyObject *ignored, PyObject *args)
{
PyObject *o1, *o2;
int w1 = 1, w2 = 1;
VALUE_TYPE w1 = 1, w2 = 1;
UNLESS(PyArg_ParseTuple(args, "OO|ii", &o1, &o2, &w1, &w2)) return NULL;
UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE,
&o1, &o2, &w1, &w2)
) return NULL;
if (o1 == Py_None)
return Py_BuildValue("iO", (o2 == Py_None ? 0 : w2), o2);
return Py_BuildValue(VALUE_PARSE "O", (o2 == Py_None ? 0 : w2), o2);
else if (o2 == Py_None)
return Py_BuildValue("iO", w1, o1);
return Py_BuildValue(VALUE_PARSE "O", w1, o1);
o1 = set_operation(o1, o2, 1, 1, w1, w2, 1, 1, 1);
if (o1) ASSIGN(o1, Py_BuildValue("iO", 1, o1));
if (o1)
ASSIGN(o1, Py_BuildValue(VALUE_PARSE "O", (VALUE_TYPE)1, o1));
return o1;
}
......@@ -413,18 +447,20 @@ static PyObject *
wintersection_m(PyObject *ignored, PyObject *args)
{
PyObject *o1, *o2;
int w1 = 1, w2 = 1;
VALUE_TYPE w1 = 1, w2 = 1;
UNLESS(PyArg_ParseTuple(args, "OO|ii", &o1, &o2, &w1, &w2)) return NULL;
UNLESS(PyArg_ParseTuple(args, "OO|" VALUE_PARSE VALUE_PARSE,
&o1, &o2, &w1, &w2)
) return NULL;
if (o1 == Py_None)
return Py_BuildValue("iO", (o2 == Py_None ? 0 : w2), o2);
return Py_BuildValue(VALUE_PARSE "O", (o2 == Py_None ? 0 : w2), o2);
else if (o2 == Py_None)
return Py_BuildValue("iO", w1, o1);
return Py_BuildValue(VALUE_PARSE "O", w1, o1);
o1 = set_operation(o1, o2, 1, 1, w1, w2, 0, 1, 0);
if (o1)
ASSIGN(o1, Py_BuildValue("iO",
ASSIGN(o1, Py_BuildValue(VALUE_PARSE "O",
((o1->ob_type == (PyTypeObject*)(&SetType)) ? w2+w1 : 1),
o1));
......
/*############################################################################
#
# Copyright (c) 2004 Zope Corporation and Contributors.
# All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
############################################################################*/
#define MASTER_ID "$Id$\n"
/* IIBTree - int key, int value BTree
Implements a collection using int type keys
and int type values
*/
/* Setup template macros */
#define PERSISTENT
#define MOD_NAME_PREFIX "IF"
#define INITMODULE init_IFBTree
#define DEFAULT_MAX_BUCKET_SIZE 120
#define DEFAULT_MAX_BTREE_SIZE 500
#include "intkeymacros.h"
#include "floatvaluemacros.h"
#include "BTreeModuleTemplate.c"
......@@ -38,6 +38,7 @@ from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
from ZODB.utils import positive_id, oid_repr
......@@ -45,21 +46,25 @@ TYPE_UNKNOWN, TYPE_BTREE, TYPE_BUCKET = range(3)
_type2kind = {IOBTree: (TYPE_BTREE, True),
IIBTree: (TYPE_BTREE, True),
IFBTree: (TYPE_BTREE, True),
OIBTree: (TYPE_BTREE, True),
OOBTree: (TYPE_BTREE, True),
IOBucket: (TYPE_BUCKET, True),
IIBucket: (TYPE_BUCKET, True),
IFBucket: (TYPE_BUCKET, True),
OIBucket: (TYPE_BUCKET, True),
OOBucket: (TYPE_BUCKET, True),
IOTreeSet: (TYPE_BTREE, False),
IITreeSet: (TYPE_BTREE, False),
IFTreeSet: (TYPE_BTREE, False),
OITreeSet: (TYPE_BTREE, False),
OOTreeSet: (TYPE_BTREE, False),
IOSet: (TYPE_BUCKET, False),
IISet: (TYPE_BUCKET, False),
IFSet: (TYPE_BUCKET, False),
OISet: (TYPE_BUCKET, False),
OOSet: (TYPE_BUCKET, False),
}
......@@ -118,6 +123,9 @@ _btree2bucket = {IOBTree: IOBucket,
IIBTree: IIBucket,
IITreeSet: IISet,
IFBTree: IFBucket,
IFTreeSet: IFSet,
OIBTree: OIBucket,
OITreeSet: OISet,
......
#define VALUEMACROS_H "$Id$\n"
#define VALUE_TYPE float
#undef VALUE_TYPE_IS_PYOBJECT
#define TEST_VALUE(K, T) (((K) < (T)) ? -1 : (((K) > (T)) ? 1: 0))
#define VALUE_SAME(VALUE, TARGET) ( (VALUE) == (TARGET) )
#define DECLARE_VALUE(NAME) VALUE_TYPE NAME
#define VALUE_PARSE "f"
#define DECREF_VALUE(k)
#define INCREF_VALUE(k)
#define COPY_VALUE(V, E) (V=(E))
#define COPY_VALUE_TO_OBJECT(O, K) O=PyFloat_FromDouble(K)
#define COPY_VALUE_FROM_ARG(TARGET, ARG, STATUS) \
if (PyFloat_Check(ARG)) TARGET = PyFloat_AsDouble(ARG); \
else if (PyInt_Check(ARG)) TARGET = PyInt_AsLong(ARG); \
else { \
PyErr_SetString(PyExc_TypeError, "expected float or int value"); \
(STATUS)=0; (TARGET)=0; }
#define NORMALIZE_VALUE(V, MIN) ((MIN) > 0) ? ((V)/=(MIN)) : 0
#define MERGE_DEFAULT 1.0f
#define MERGE(O1, w1, O2, w2) ((O1)*(w1)+(O2)*(w2))
#define MERGE_WEIGHT(O, w) ((O)*(w))
......@@ -17,6 +17,7 @@ from unittest import TestCase, TestSuite, TextTestRunner, makeSuite
from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
from BTrees.check import check
......@@ -1126,6 +1127,39 @@ class TestIIBTrees(TestCase):
def _noneraisesvalue(self):
self.t[1] = None
class TestIFBTrees(TestCase):
def setUp(self):
self.t = IFBTree()
def testNonIntegerKeyRaises(self):
self.assertRaises(TypeError, self._stringraiseskey)
self.assertRaises(TypeError, self._floatraiseskey)
self.assertRaises(TypeError, self._noneraiseskey)
def testNonNumericValueRaises(self):
self.assertRaises(TypeError, self._stringraisesvalue)
self.assertRaises(TypeError, self._noneraisesvalue)
self.t[1] = 1
self.t[1] = 1.0
def _stringraiseskey(self):
self.t['c'] = 1
def _floatraiseskey(self):
self.t[2.5] = 1
def _noneraiseskey(self):
self.t[None] = 1
def _stringraisesvalue(self):
self.t[1] = 'c'
def _floatraisesvalue(self):
self.t[1] = 1.4
def _noneraisesvalue(self):
self.t[1] = None
class TestIOSets(TestCase):
def setUp(self):
self.t = IOSet()
......@@ -1315,6 +1349,9 @@ class DegenerateBTree(TestCase):
class IIBucketTest(MappingBase):
def setUp(self):
self.t = IIBucket()
class IFBucketTest(MappingBase):
def setUp(self):
self.t = IFBucket()
class IOBucketTest(MappingBase):
def setUp(self):
self.t = IOBucket()
......@@ -1328,6 +1365,9 @@ class OOBucketTest(MappingBase):
class IITreeSetTest(NormalSetTests):
def setUp(self):
self.t = IITreeSet()
class IFTreeSetTest(NormalSetTests):
def setUp(self):
self.t = IFTreeSet()
class IOTreeSetTest(NormalSetTests):
def setUp(self):
self.t = IOTreeSet()
......@@ -1341,6 +1381,9 @@ class OOTreeSetTest(NormalSetTests):
class IISetTest(ExtendedSetTests):
def setUp(self):
self.t = IISet()
class IFSetTest(ExtendedSetTests):
def setUp(self):
self.t = IFSet()
class IOSetTest(ExtendedSetTests):
def setUp(self):
self.t = IOSet()
......@@ -1354,6 +1397,9 @@ class OOSetTest(ExtendedSetTests):
class IIBTreeTest(BTreeTests):
def setUp(self):
self.t = IIBTree()
class IFBTreeTest(BTreeTests):
def setUp(self):
self.t = IFBTree()
class IOBTreeTest(BTreeTests):
def setUp(self):
self.t = IOBTree()
......@@ -1385,17 +1431,20 @@ class TestCmpError(TestCase):
def test_suite():
s = TestSuite()
for klass in (IIBucketTest, IOBucketTest, OIBucketTest, OOBucketTest,
IITreeSetTest, IOTreeSetTest, OITreeSetTest, OOTreeSetTest,
IISetTest, IOSetTest, OISetTest, OOSetTest,
IIBTreeTest, IOBTreeTest, OIBTreeTest, OOBTreeTest,
# Note: there is no TestOOBTrees. The next three are
# checking for assorted TypeErrors, and when both keys
# and values oare objects (OO), there's nothing to test.
TestIIBTrees, TestIOBTrees, TestOIBTrees,
TestIOSets,
DegenerateBTree,
TestCmpError):
for klass in (
IIBucketTest, IIBTreeTest, IISetTest, IITreeSetTest,
IFBucketTest, IFBTreeTest, IFSetTest, IFTreeSetTest,
IOBucketTest, IOBTreeTest, IOSetTest, IOTreeSetTest,
OOBucketTest, OOBTreeTest, OOSetTest, OOTreeSetTest,
OIBucketTest, OIBTreeTest, OISetTest, OITreeSetTest,
# Note: there is no TestOOBTrees. The next three are
# checking for assorted TypeErrors, and when both keys
# and values oare objects (OO), there's nothing to test.
TestIIBTrees, TestIFBTrees, TestIOBTrees, TestOIBTrees,
TestIOSets,
DegenerateBTree,
TestCmpError):
s.addTest(makeSuite(klass))
return s
......
......@@ -17,6 +17,7 @@ from unittest import TestCase, TestSuite, makeSuite
from BTrees.OOBTree import OOBTree, OOBucket, OOSet, OOTreeSet
from BTrees.IOBTree import IOBTree, IOBucket, IOSet, IOTreeSet
from BTrees.IIBTree import IIBTree, IIBucket, IISet, IITreeSet
from BTrees.IFBTree import IFBTree, IFBucket, IFSet, IFTreeSet
from BTrees.OIBTree import OIBTree, OIBucket, OISet, OITreeSet
import transaction
......@@ -345,6 +346,10 @@ class TestIIBTrees(BTreeTests, TestCase):
def setUp(self):
self.t = IIBTree()
class TestIFBTrees(BTreeTests, TestCase):
def setUp(self):
self.t = IFBTree()
## Set tests
class TestIOSets(SetTests, TestCase):
......@@ -359,6 +364,10 @@ class TestIISets(SetTests, TestCase):
def setUp(self):
self.t = IISet()
class TestIFSets(SetTests, TestCase):
def setUp(self):
self.t = IFSet()
class TestOISets(SetTests, TestCase):
def setUp(self):
self.t = OISet()
......@@ -375,6 +384,10 @@ class TestIITreeSets(SetTests, TestCase):
def setUp(self):
self.t = IITreeSet()
class TestIFTreeSets(SetTests, TestCase):
def setUp(self):
self.t = IFTreeSet()
class TestOITreeSets(SetTests, TestCase):
def setUp(self):
self.t = OITreeSet()
......@@ -393,6 +406,10 @@ class TestIIBuckets(BucketTests, TestCase):
def setUp(self):
self.t = IIBucket()
class TestIFBuckets(BucketTests, TestCase):
def setUp(self):
self.t = IFBucket()
class TestOIBuckets(BucketTests, TestCase):
def setUp(self):
self.t = OIBucket()
......@@ -745,10 +762,12 @@ class NastyConfict(Base, TestCase):
def test_suite():
suite = TestSuite()
for k in (TestIOBTrees, TestOOBTrees, TestOIBTrees, TestIIBTrees,
TestIOSets, TestOOSets, TestOISets, TestIISets,
TestIOTreeSets, TestOOTreeSets, TestOITreeSets, TestIITreeSets,
TestIOBuckets, TestOOBuckets, TestOIBuckets, TestIIBuckets,
NastyConfict):
for k in (
TestIIBTrees, TestIISets, TestIITreeSets, TestIIBuckets,
TestIFBTrees, TestIFSets, TestIFTreeSets, TestIFBuckets,
TestIOBTrees, TestIOSets, TestIOTreeSets, TestIOBuckets,
TestOOBTrees, TestOOSets, TestOOTreeSets, TestOOBuckets,
TestOIBTrees, TestOISets, TestOITreeSets, TestOIBuckets,
NastyConfict):
suite.addTest(makeSuite(k))
return suite
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