Commit e7c7adc2 authored by Tim Peters's avatar Tim Peters

Bucket_grow():

+ Added interface docs.
+ Gave it a new "newsize" argument, for when the caller can gain speed
  by knowing in advance how many additional elements are needed.  This
  isn't used yet, but will be by multiunion and planned "lopsided merge"
  optimizations (the intent is to grow the bucket big enough in one
  shot, then memcpy a large slice into the bucket).
+ When doubling the size, now sets a MemoryError exception on int
  overflow.
parent bfdd90aa
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
****************************************************************************/ ****************************************************************************/
#define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.30 2002/05/31 09:41:07 htrd Exp $\n" #define BUCKETTEMPLATE_C "$Id: BucketTemplate.c,v 1.31 2002/05/31 14:58:29 tim_one Exp $\n"
/* /*
** _bucket_get ** _bucket_get
...@@ -74,39 +74,63 @@ bucket_getitem(Bucket *self, PyObject *key) ...@@ -74,39 +74,63 @@ bucket_getitem(Bucket *self, PyObject *key)
return _bucket_get(self, key, 0); return _bucket_get(self, key, 0);
} }
/*
** Bucket_grow
**
** Resize a bucket.
**
** Arguments: self The bucket.
** newsize The new maximum capacity. If < 0, double the
** current size unless the bucket is currently empty,
** in which case use MIN_BUCKET_ALLOC.
** noval Boolean; if true, allocate only key space and not
** value space
**
** Returns: -1 on error, and MemoryError exception is set
** 0 on success
*/
static int static int
Bucket_grow(Bucket *self, int noval) Bucket_grow(Bucket *self, int newsize, int noval)
{ {
KEY_TYPE *keys; KEY_TYPE *keys;
VALUE_TYPE *values; VALUE_TYPE *values;
if (self->size) if (self->size)
{ {
UNLESS (keys=PyRealloc(self->keys, sizeof(KEY_TYPE)*self->size*2)) if (newsize < 0)
newsize = self->size * 2;
if (newsize < 0) /* int overflow */
goto Overflow;
UNLESS (keys = PyRealloc(self->keys, sizeof(KEY_TYPE) * newsize))
return -1; return -1;
UNLESS (noval) UNLESS (noval)
{ {
UNLESS (values=PyRealloc(self->values, UNLESS (values = PyRealloc(self->values,
sizeof(VALUE_TYPE)*self->size*2)) sizeof(VALUE_TYPE) * newsize))
return -1; return -1;
self->values=values; self->values = values;
} }
self->keys=keys; self->keys = keys;
self->size*=2;
} }
else else
{ {
UNLESS (self->keys=PyMalloc(sizeof(KEY_TYPE)*MIN_BUCKET_ALLOC)) if (newsize < 0)
newsize = MIN_BUCKET_ALLOC;
UNLESS (self->keys = PyMalloc(sizeof(KEY_TYPE) * newsize))
return -1; return -1;
UNLESS (noval || UNLESS (noval)
(self->values=PyMalloc(sizeof(VALUE_TYPE)*MIN_BUCKET_ALLOC)) {
) UNLESS (self->values = PyMalloc(sizeof(VALUE_TYPE) * newsize))
return -1; return -1;
self->size=MIN_BUCKET_ALLOC; }
} }
self->size = newsize;
return 0; return 0;
Overflow:
PyErr_NoMemory();
return -1;
} }
/* /*
...@@ -213,7 +237,7 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v, ...@@ -213,7 +237,7 @@ _bucket_set(Bucket *self, PyObject *keyarg, PyObject *v,
goto err; goto err;
} }
if (self->len==self->size && Bucket_grow(self, noval) < 0) goto err; if (self->len==self->size && Bucket_grow(self, -1, noval) < 0) goto err;
if (max != i) i++; if (max != i) i++;
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
****************************************************************************/ ****************************************************************************/
#define MERGETEMPLATE_C "$Id: MergeTemplate.c,v 1.10 2002/05/31 09:41:07 htrd Exp $\n" #define MERGETEMPLATE_C "$Id: MergeTemplate.c,v 1.11 2002/05/31 14:58:29 tim_one Exp $\n"
/**************************************************************************** /****************************************************************************
Set operations Set operations
...@@ -21,7 +21,7 @@ ...@@ -21,7 +21,7 @@
static int static int
merge_output(Bucket *r, SetIteration *i, int mapping) merge_output(Bucket *r, SetIteration *i, int mapping)
{ {
if(r->len >= r->size && Bucket_grow(r, ! mapping) < 0) return -1; if(r->len >= r->size && Bucket_grow(r, -1, ! mapping) < 0) return -1;
COPY_KEY(r->keys[r->len], i->key); COPY_KEY(r->keys[r->len], i->key);
INCREF_KEY(r->keys[r->len]); INCREF_KEY(r->keys[r->len]);
if (mapping) if (mapping)
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
Set operations Set operations
****************************************************************************/ ****************************************************************************/
#define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.14 2002/05/31 09:41:07 htrd Exp $\n" #define SETOPTEMPLATE_C "$Id: SetOpTemplate.c,v 1.15 2002/05/31 14:58:29 tim_one Exp $\n"
#ifdef INTSET_H #ifdef INTSET_H
static int static int
...@@ -153,7 +153,7 @@ copyRemaining(Bucket *r, SetIteration *i, int merge, int w) ...@@ -153,7 +153,7 @@ copyRemaining(Bucket *r, SetIteration *i, int merge, int w)
{ {
while (i->position >= 0) while (i->position >= 0)
{ {
if(r->len >= r->size && Bucket_grow(r, ! merge) < 0) return -1; if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) return -1;
COPY_KEY(r->keys[r->len], i->key); COPY_KEY(r->keys[r->len], i->key);
INCREF_KEY(r->keys[r->len]); INCREF_KEY(r->keys[r->len]);
...@@ -228,7 +228,7 @@ set_operation(PyObject *s1, PyObject *s2, ...@@ -228,7 +228,7 @@ set_operation(PyObject *s1, PyObject *s2,
{ {
if(c1) if(c1)
{ {
if(r->len >= r->size && Bucket_grow(r, ! merge) < 0) goto err; if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) goto err;
COPY_KEY(r->keys[r->len], i1.key); COPY_KEY(r->keys[r->len], i1.key);
INCREF_KEY(r->keys[r->len]); INCREF_KEY(r->keys[r->len]);
if (merge) if (merge)
...@@ -244,7 +244,7 @@ set_operation(PyObject *s1, PyObject *s2, ...@@ -244,7 +244,7 @@ set_operation(PyObject *s1, PyObject *s2,
{ {
if(c12) if(c12)
{ {
if(r->len >= r->size && Bucket_grow(r, ! merge) < 0) goto err; if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) goto err;
COPY_KEY(r->keys[r->len], i1.key); COPY_KEY(r->keys[r->len], i1.key);
INCREF_KEY(r->keys[r->len]); INCREF_KEY(r->keys[r->len]);
if (merge) if (merge)
...@@ -265,7 +265,7 @@ set_operation(PyObject *s1, PyObject *s2, ...@@ -265,7 +265,7 @@ set_operation(PyObject *s1, PyObject *s2,
{ {
if(c2) if(c2)
{ {
if(r->len >= r->size && Bucket_grow(r, ! merge) < 0) goto err; if(r->len >= r->size && Bucket_grow(r, -1, ! merge) < 0) goto err;
COPY_KEY(r->keys[r->len], i2.key); COPY_KEY(r->keys[r->len], i2.key);
INCREF_KEY(r->keys[r->len]); INCREF_KEY(r->keys[r->len]);
if (merge) if (merge)
...@@ -447,7 +447,7 @@ multiunion_m(PyObject *ignored, PyObject *args) ...@@ -447,7 +447,7 @@ multiunion_m(PyObject *ignored, PyObject *args)
if (setiter.next(&setiter) < 0) if (setiter.next(&setiter) < 0)
goto Error; goto Error;
while (setiter.position >= 0) { while (setiter.position >= 0) {
if (result->len >= result->size && Bucket_grow(result, 1) < 0) if (result->len >= result->size && Bucket_grow(result, -1, 1) < 0)
goto Error; goto Error;
COPY_KEY(result->keys[result->len], setiter.key); COPY_KEY(result->keys[result->len], setiter.key);
++result->len; ++result->len;
......
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