Commit b42660d6 authored by Tim Peters's avatar Tim Peters

"Derive" bucket and BTree nodes from a new Sized struct, capturing

the common initial fields (pyobject hair, persistence hair, 'size',
and 'len').  I think Jim wants the data decls split into a separate
file, but I'm unclear on why so am not doing that now.

Renamed stuff for consistency.

Added some comments.  More BTree comments will end up in Maintainer.txt.
parent e7c7adc2
...@@ -2,14 +2,14 @@ ...@@ -2,14 +2,14 @@
Copyright (c) 2001, 2002 Zope Corporation and Contributors. Copyright (c) 2001, 2002 Zope Corporation and Contributors.
All Rights Reserved. All Rights Reserved.
This software is subject to the provisions of the Zope Public License, This software is subject to the provisions of the Zope Public License,
Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution. Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
FOR A PARTICULAR PURPOSE FOR A PARTICULAR PURPOSE
****************************************************************************/ ****************************************************************************/
#ifdef PERSISTENT #ifdef PERSISTENT
...@@ -17,7 +17,7 @@ ...@@ -17,7 +17,7 @@
/*************************************************************** /***************************************************************
The following are macros that ought to be in cPersistence.h */ The following are macros that ought to be in cPersistence.h */
#ifndef PER_USE #ifndef PER_USE
#define PER_USE(O) \ #define PER_USE(O) \
(((O)->state != cPersistent_GHOST_STATE \ (((O)->state != cPersistent_GHOST_STATE \
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
? (((O)->state==cPersistent_UPTODATE_STATE) \ ? (((O)->state==cPersistent_UPTODATE_STATE) \
? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0) ? ((O)->state=cPersistent_STICKY_STATE) : 1) : 0)
#define PER_ACCESSED(O) ((O)->atime=((long)(time(NULL)/3))%65536) #define PER_ACCESSED(O) ((O)->atime=((long)(time(NULL)/3))%65536)
#endif #endif
...@@ -42,7 +42,6 @@ ...@@ -42,7 +42,6 @@
#define PER_CHANGED(O) 0 #define PER_CHANGED(O) 0
#endif #endif
static PyObject *sort_str, *reverse_str, *items_str, *__setstate___str; static PyObject *sort_str, *reverse_str, *items_str, *__setstate___str;
static PyObject *ConflictError = NULL; static PyObject *ConflictError = NULL;
...@@ -63,47 +62,92 @@ static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;} ...@@ -63,47 +62,92 @@ static void PyVar_Assign(PyObject **v, PyObject *e) { Py_XDECREF(*v); *v=e;}
#define ASSERT(C, S, R) if (! (C)) { \ #define ASSERT(C, S, R) if (! (C)) { \
PyErr_SetString(PyExc_AssertionError, (S)); return (R); } PyErr_SetString(PyExc_AssertionError, (S)); return (R); }
typedef struct BTreeItemStruct { /* Various kinds of BTree and Bucket structs are instances of
KEY_TYPE key; * "sized containers", and have a common initial layout:
PyObject *value; * The stuff needed for all Python objects, or all Persistent objects.
} BTreeItem; * int size: The maximum number of things that could be contained
* without growing the container.
typedef struct Bucket_s { * int len: The number of things currently contained.
*
* Invariant: 0 <= len <= size.
*
* A sized container typically goes on to declare one or more pointers
* to contiguous arrays with 'size' elements each, the initial 'len' of
* which are currently in use.
*/
#ifdef PERSISTENT #ifdef PERSISTENT
cPersistent_HEAD #define sizedcontainer_HEAD \
cPersistent_HEAD \
int size; \
int len;
#else #else
PyObject_HEAD #define sizedcontainer_HEAD \
PyObject_HEAD \
int size; \
int len;
#endif #endif
int size, len;
struct Bucket_s *next; /* Nothing is actually of type Sized, but (pointers to) BTree nodes and
KEY_TYPE *keys; * Buckets can be cast to Sized* in contexts that only need to examine
VALUE_TYPE *values; * the members common to all sized containers.
*/
typedef struct Sized_s {
sizedcontainer_HEAD
} Sized;
#define SIZED(O) ((Sized*)(O))
/* A Bucket wraps contiguous vectors of keys and values. Keys are unique,
* and stored in sorted order. The 'values' pointer may be NULL if the
* Bucket is used to implement a set. Buckets serving as leafs of BTrees
* are chained together via 'next', so that the entire BTree contents
* can be traversed in sorted order quickly and easily.
*/
typedef struct Bucket_s {
sizedcontainer_HEAD
struct Bucket_s *next; /* the bucket with the next-larger keys */
KEY_TYPE *keys; /* 'len' keys, in increasing order */
VALUE_TYPE *values; /* 'len' corresponding values; NULL if a set */
} Bucket; } Bucket;
#define BUCKET(O) ((Bucket*)(O)) #define BUCKET(O) ((Bucket*)(O))
#define SIZED(O) ((Bucket*)(O))
static void PyVar_AssignB(Bucket **v, Bucket *e) { Py_XDECREF(*v); *v=e;} static void PyVar_AssignB(Bucket **v, Bucket *e) { Py_XDECREF(*v); *v=e;}
#define ASSIGNB(V,E) PyVar_AssignB(&(V),(E)) #define ASSIGNB(V,E) PyVar_AssignB(&(V),(E))
#define ASSIGNBC(V,E) (Py_INCREF((E)), PyVar_AssignB(&(V),(E))) #define ASSIGNBC(V,E) (Py_INCREF((E)), PyVar_AssignB(&(V),(E)))
typedef struct { /* A BTree is complicated. See Maintainer.txt.
#ifdef PERSISTENT */
cPersistent_HEAD
#else typedef struct BTreeItem_s {
PyObject_HEAD KEY_TYPE key;
#endif PyObject *value;
int size, len; } BTreeItem;
typedef struct BTree_s {
sizedcontainer_HEAD
/* firstbucket points to the bucket containing the smallest key in
* the BTree. This is found by traversing leftmost child pointers
* (data[0].value) until reaching a Bucket.
*/
Bucket *firstbucket; Bucket *firstbucket;
/* The BTree points to 'len' children, via the oddly named "value" fields
* of the data array. There are len-1 keys in the 'key' fields, stored
* in increasing order. data[0].key is unused. For i in 0 .. len-1,
* all keys reachable from data[i].value are >= data[i].key and <
* data[i+1].key, at the endpoints pretending that data[0].key is minus
* infinity and data[len].key is positive infinity.
*/
BTreeItem *data; BTreeItem *data;
} BTree; } BTree;
staticforward PyExtensionClass BTreeType; staticforward PyExtensionClass BTreeType;
#define BTREE(O) ((BTree*)(O)) #define BTREE(O) ((BTree*)(O))
typedef struct SetIteration_s typedef struct SetIteration_s
{ {
PyObject *set; PyObject *set;
int position; int position;
...@@ -115,7 +159,7 @@ typedef struct SetIteration_s ...@@ -115,7 +159,7 @@ typedef struct SetIteration_s
static PyObject * static PyObject *
IndexError(int i) IndexError(int i)
{ {
PyObject *v; PyObject *v;
v=PyInt_FromLong(i); v=PyInt_FromLong(i);
...@@ -142,7 +186,7 @@ PreviousBucket(Bucket *current, Bucket *first, int i) ...@@ -142,7 +186,7 @@ PreviousBucket(Bucket *current, Bucket *first, int i)
while (1) while (1)
{ {
PER_USE_OR_RETURN(first,NULL); PER_USE_OR_RETURN(first,NULL);
if (first->next==current) if (first->next==current)
{ {
PER_ALLOW_DEACTIVATION(first); PER_ALLOW_DEACTIVATION(first);
PER_ACCESSED(first); PER_ACCESSED(first);
...@@ -168,7 +212,7 @@ PreviousBucket(Bucket *current, Bucket *first, int i) ...@@ -168,7 +212,7 @@ PreviousBucket(Bucket *current, Bucket *first, int i)
} }
} }
static int static int
firstBucketOffset(Bucket **bucket, int *offset) firstBucketOffset(Bucket **bucket, int *offset)
{ {
Bucket *b; Bucket *b;
...@@ -187,7 +231,7 @@ firstBucketOffset(Bucket **bucket, int *offset) ...@@ -187,7 +231,7 @@ firstBucketOffset(Bucket **bucket, int *offset)
return 1; return 1;
} }
static int static int
lastBucketOffset(Bucket **bucket, int *offset, Bucket *firstbucket, int i) lastBucketOffset(Bucket **bucket, int *offset, Bucket *firstbucket, int i)
{ {
Bucket *b; Bucket *b;
...@@ -275,11 +319,11 @@ static struct PyMethodDef module_methods[] = { ...@@ -275,11 +319,11 @@ static struct PyMethodDef module_methods[] = {
{NULL, NULL} /* sentinel */ {NULL, NULL} /* sentinel */
}; };
static char BTree_module_documentation[] = static char BTree_module_documentation[] =
"\n" "\n"
MASTER_ID MASTER_ID
BTREEITEMSTEMPLATE_C BTREEITEMSTEMPLATE_C
"$Id: BTreeModuleTemplate.c,v 1.22 2002/05/30 21:00:30 tim_one Exp $\n" "$Id: BTreeModuleTemplate.c,v 1.23 2002/05/31 16:28:03 tim_one Exp $\n"
BTREETEMPLATE_C BTREETEMPLATE_C
BUCKETTEMPLATE_C BUCKETTEMPLATE_C
KEYMACROS_H KEYMACROS_H
...@@ -291,7 +335,7 @@ VALUEMACROS_H ...@@ -291,7 +335,7 @@ VALUEMACROS_H
BTREEITEMSTEMPLATE_C BTREEITEMSTEMPLATE_C
; ;
void void
INITMODULE (void) INITMODULE (void)
{ {
PyObject *m, *d, *c; PyObject *m, *d, *c;
...@@ -331,10 +375,10 @@ INITMODULE (void) ...@@ -331,10 +375,10 @@ INITMODULE (void)
if (m != NULL) { if (m != NULL) {
c = PyObject_GetAttrString(m, "BTreesConflictError"); c = PyObject_GetAttrString(m, "BTreesConflictError");
if (c != NULL) if (c != NULL)
ConflictError = c; ConflictError = c;
Py_DECREF(m); Py_DECREF(m);
} }
if (ConflictError == NULL) { if (ConflictError == NULL) {
Py_INCREF(PyExc_ValueError); Py_INCREF(PyExc_ValueError);
...@@ -353,7 +397,7 @@ INITMODULE (void) ...@@ -353,7 +397,7 @@ INITMODULE (void)
#ifdef INTSET_H #ifdef INTSET_H
UNLESS(d = PyImport_ImportModule("intSet")) return; UNLESS(d = PyImport_ImportModule("intSet")) return;
UNLESS(intSetType = PyObject_GetAttrString (d, "intSet")) return; UNLESS(intSetType = PyObject_GetAttrString (d, "intSet")) return;
Py_DECREF (d); Py_DECREF (d);
#endif #endif
/* Create the module and add the functions */ /* Create the module and add the functions */
......
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