/**************************************************************************
*
- * Copyright 2007 Tungsten Graphics, Inc., Cedar Park, Texas.
+ * Copyright 2007 VMware, Inc.
* All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
* ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
/*
* Authors:
- * Zack Rusin <zack@tungstengraphics.com>
+ * Zack Rusin <zackr@vmware.com>
*/
-#include "pipe/p_debug.h"
+#include "util/u_debug.h"
#include "util/u_memory.h"
#include "cso_hash.h"
+#ifndef MAX
#define MAX(a, b) ((a > b) ? (a) : (b))
+#endif
static const int MinNumBits = 4;
return numBits;
}
-struct cso_node {
- struct cso_node *next;
- unsigned key;
- void *value;
-};
-
-struct cso_hash_data {
- struct cso_node *fakeNext;
- struct cso_node **buckets;
- int size;
- int nodeSize;
- short userNumBits;
- short numBits;
- int numBuckets;
-};
-
-struct cso_hash {
- union {
- struct cso_hash_data *d;
- struct cso_node *e;
- } data;
-};
-
-static void *cso_data_allocate_node(struct cso_hash_data *hash)
-{
- return MALLOC(hash->nodeSize);
-}
-
-static void cso_free_node(struct cso_node *node)
-{
- FREE(node);
-}
-
static struct cso_node *
cso_hash_create_node(struct cso_hash *hash,
- unsigned akey, void *avalue,
- struct cso_node **anextNode)
+ unsigned akey, void *avalue,
+ struct cso_node **anextNode)
{
- struct cso_node *node = cso_data_allocate_node(hash->data.d);
+ struct cso_node *node = MALLOC(sizeof(struct cso_node));
if (!node)
return NULL;
node->key = akey;
node->value = avalue;
- node->next = (struct cso_node*)(*anextNode);
+ node->next = *anextNode;
*anextNode = node;
- ++hash->data.d->size;
+ ++hash->data.size;
return node;
}
}
if (hash->numBits != hint) {
- struct cso_node *e = (struct cso_node *)(hash);
+ struct cso_node *e = (struct cso_node *)hash;
struct cso_node **oldBuckets = hash->buckets;
int oldNumBuckets = hash->numBuckets;
int i = 0;
static struct cso_node *cso_data_first_node(struct cso_hash_data *hash)
{
- struct cso_node *e = (struct cso_node *)(hash);
+ struct cso_node *e = (struct cso_node *)hash;
struct cso_node **bucket = hash->buckets;
int n = hash->numBuckets;
+
while (n--) {
if (*bucket != e)
return *bucket;
return e;
}
-static struct cso_node **cso_hash_find_node(struct cso_hash *hash, unsigned akey)
-{
- struct cso_node **node;
-
- if (hash->data.d->numBuckets) {
- node = (struct cso_node **)(&hash->data.d->buckets[akey % hash->data.d->numBuckets]);
- assert(*node == hash->data.e || (*node)->next);
- while (*node != hash->data.e && (*node)->key != akey)
- node = &(*node)->next;
- } else {
- node = (struct cso_node **)((const struct cso_node * const *)(&hash->data.e));
- }
- return node;
-}
-
struct cso_hash_iter cso_hash_insert(struct cso_hash *hash,
- unsigned key, void *data)
+ unsigned key, void *data)
{
- cso_data_might_grow(hash->data.d);
-
- {
- struct cso_node **nextNode = cso_hash_find_node(hash, key);
- struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode);
- if (!node) {
- struct cso_hash_iter null_iter = {hash, 0};
- return null_iter;
- }
+ cso_data_might_grow(&hash->data);
- {
- struct cso_hash_iter iter = {hash, node};
- return iter;
- }
+ struct cso_node **nextNode = cso_hash_find_node(hash, key);
+ struct cso_node *node = cso_hash_create_node(hash, key, data, nextNode);
+ if (!node) {
+ struct cso_hash_iter null_iter = {hash, 0};
+ return null_iter;
}
+
+ struct cso_hash_iter iter = {hash, node};
+ return iter;
}
-struct cso_hash * cso_hash_create(void)
+void cso_hash_init(struct cso_hash *hash)
{
- struct cso_hash *hash = MALLOC_STRUCT(cso_hash);
- if (!hash)
- return NULL;
-
- hash->data.d = MALLOC_STRUCT(cso_hash_data);
- if (!hash->data.d) {
- FREE(hash);
- return NULL;
- }
-
- hash->data.d->fakeNext = 0;
- hash->data.d->buckets = 0;
- hash->data.d->size = 0;
- hash->data.d->nodeSize = sizeof(struct cso_node);
- hash->data.d->userNumBits = (short)MinNumBits;
- hash->data.d->numBits = 0;
- hash->data.d->numBuckets = 0;
-
- return hash;
+ hash->data.fakeNext = 0;
+ hash->data.buckets = 0;
+ hash->data.size = 0;
+ hash->data.userNumBits = (short)MinNumBits;
+ hash->data.numBits = 0;
+ hash->data.numBuckets = 0;
+ hash->end = (struct cso_node*)&hash->data;
}
-void cso_hash_delete(struct cso_hash *hash)
+void cso_hash_deinit(struct cso_hash *hash)
{
- struct cso_node *e_for_x = (struct cso_node *)(hash->data.d);
- struct cso_node **bucket = (struct cso_node **)(hash->data.d->buckets);
- int n = hash->data.d->numBuckets;
+ struct cso_node *e_for_x = hash->end;
+ struct cso_node **bucket = hash->data.buckets;
+ int n = hash->data.numBuckets;
+
while (n--) {
struct cso_node *cur = *bucket++;
while (cur != e_for_x) {
struct cso_node *next = cur->next;
- cso_free_node(cur);
+ FREE(cur);
cur = next;
}
}
- FREE(hash->data.d->buckets);
- FREE(hash->data.d);
- FREE(hash);
-}
-
-struct cso_hash_iter cso_hash_find(struct cso_hash *hash,
- unsigned key)
-{
- struct cso_node **nextNode = cso_hash_find_node(hash, key);
- struct cso_hash_iter iter = {hash, *nextNode};
- return iter;
+ FREE(hash->data.buckets);
}
unsigned cso_hash_iter_key(struct cso_hash_iter iter)
{
- if (!iter.node || iter.hash->data.e == iter.node)
+ if (!iter.node || iter.hash->end == iter.node)
return 0;
return iter.node->key;
}
-void * cso_hash_iter_data(struct cso_hash_iter iter)
-{
- if (!iter.node || iter.hash->data.e == iter.node)
- return 0;
- return iter.node->value;
-}
-
-static struct cso_node *cso_hash_data_next(struct cso_node *node)
+struct cso_node *cso_hash_data_next(struct cso_node *node)
{
union {
struct cso_node *next;
a.next = node->next;
if (!a.next) {
debug_printf("iterating beyond the last element\n");
- return 0;
+ return NULL;
}
if (a.next->next)
return a.next;
return a.e;
}
-struct cso_hash_iter cso_hash_iter_next(struct cso_hash_iter iter)
-{
- struct cso_hash_iter next = {iter.hash, cso_hash_data_next(iter.node)};
- return next;
-}
-
-int cso_hash_iter_is_null(struct cso_hash_iter iter)
-{
- if (!iter.node || iter.node == iter.hash->data.e)
- return 1;
- return 0;
-}
-
-void * cso_hash_take(struct cso_hash *hash,
- unsigned akey)
+void *cso_hash_take(struct cso_hash *hash, unsigned akey)
{
struct cso_node **node = cso_hash_find_node(hash, akey);
- if (*node != hash->data.e) {
+
+ if (*node != hash->end) {
void *t = (*node)->value;
struct cso_node *next = (*node)->next;
- cso_free_node(*node);
+ FREE(*node);
*node = next;
- --hash->data.d->size;
- cso_data_has_shrunk(hash->data.d);
+ --hash->data.size;
+ cso_data_has_shrunk(&hash->data);
return t;
}
- return 0;
+ return NULL;
}
struct cso_hash_iter cso_hash_iter_prev(struct cso_hash_iter iter)
{
struct cso_hash_iter prev = {iter.hash,
- cso_hash_data_prev(iter.node)};
+ cso_hash_data_prev(iter.node)};
return prev;
}
struct cso_hash_iter cso_hash_first_node(struct cso_hash *hash)
{
- struct cso_hash_iter iter = {hash, cso_data_first_node(hash->data.d)};
+ struct cso_hash_iter iter = {hash, cso_data_first_node(&hash->data)};
return iter;
}
int cso_hash_size(struct cso_hash *hash)
{
- return hash->data.d->size;
+ return hash->data.size;
}
struct cso_hash_iter cso_hash_erase(struct cso_hash *hash, struct cso_hash_iter iter)
struct cso_node *node = iter.node;
struct cso_node **node_ptr;
- if (node == hash->data.e)
+ if (node == hash->end)
return iter;
ret = cso_hash_iter_next(ret);
- node_ptr = (struct cso_node**)(&hash->data.d->buckets[node->key % hash->data.d->numBuckets]);
+ node_ptr = &hash->data.buckets[node->key % hash->data.numBuckets];
while (*node_ptr != node)
node_ptr = &(*node_ptr)->next;
*node_ptr = node->next;
- cso_free_node(node);
- --hash->data.d->size;
+ FREE(node);
+ --hash->data.size;
return ret;
}
-boolean cso_hash_contains(struct cso_hash *hash, unsigned key)
+bool cso_hash_contains(struct cso_hash *hash, unsigned key)
{
struct cso_node **node = cso_hash_find_node(hash, key);
- return (*node != hash->data.e);
+ return *node != hash->end;
}