/tags/rel-1-3-15/SWIG/Source/DOH/Doh/hash.c
C | 565 lines | 406 code | 64 blank | 95 comment | 71 complexity | 98cd8eb9a48230cab185900d531a8750 MD5 | raw file
Possible License(s): LGPL-2.1, Cube, GPL-3.0, 0BSD, GPL-2.0
- /* -----------------------------------------------------------------------------
- * hash.c
- *
- * Implements a simple hash table object.
- *
- * Author(s) : David Beazley (beazley@cs.uchicago.edu)
- *
- * Copyright (C) 1999-2000. The University of Chicago
- * See the file LICENSE for information on usage and redistribution.
- * ----------------------------------------------------------------------------- */
- static char cvsroot[] = "$Header$";
- #include "dohint.h"
- extern DohObjInfo DohHashType;
- /* Hash node */
- typedef struct HashNode {
- DOH *key;
- DOH *object;
- struct HashNode *next;
- } HashNode;
- /* Hash object */
- typedef struct Hash {
- DOH *file;
- int line;
- HashNode **hashtable;
- int hashsize;
- int currentindex;
- int nitems;
- HashNode *current;
- } Hash;
- /* Key interning structure */
- typedef struct KeyValue {
- char *cstr;
- DOH *sstr;
- struct KeyValue *left;
- struct KeyValue *right;
- } KeyValue;
- static KeyValue *root = 0;
- /* Find or create a key in the interned key table */
- static DOH *find_key (DOH *doh_c) {
- char *c = (char *) doh_c;
- KeyValue *r, *s;
- int d = 0;
- /* OK, sure, we use a binary tree for maintaining interned
- symbols. Then we use their hash values for accessing secondary
- hash tables. */
- r = root;
- s = 0;
- while (r) {
- s = r;
- d = strcmp(r->cstr,c);
- if (d == 0) return r->sstr;
- if (d < 0) r = r->left;
- else r = r->right;
- }
- /* fprintf(stderr,"Interning '%s'\n", c);*/
- r = (KeyValue *) DohMalloc(sizeof(KeyValue));
- r->cstr = (char *) DohMalloc(strlen(c)+1);
- strcpy(r->cstr,c);
- r->sstr = NewString(c);
- DohIntern(r->sstr);
- r->left = 0;
- r->right = 0;
- if (!s) { root = r; }
- else {
- if (d < 0) s->left = r;
- else s->right = r;
- }
- return r->sstr;
- }
- #define HASH_INIT_SIZE 7
- /* Create a new hash node */
- static HashNode *NewNode(DOH *k, void *obj) {
- HashNode *hn = (HashNode *) DohMalloc(sizeof(HashNode));
- hn->key = k;
- Incref(hn->key);
- hn->object = obj;
- Incref(obj);
- hn->next = 0;
- return hn;
- }
- /* Delete a hash node */
- static void DelNode(HashNode *hn) {
- Delete(hn->key);
- Delete(hn->object);
- DohFree(hn);
- }
- /* -----------------------------------------------------------------------------
- * DelHash()
- *
- * Delete a hash table.
- * ----------------------------------------------------------------------------- */
- static void
- DelHash(DOH *ho) {
- Hash *h = (Hash *) ObjData(ho);
- HashNode *n,*next;
- int i;
- for (i = 0; i < h->hashsize; i++) {
- if ((n = h->hashtable[i])) {
- while (n) {
- next = n->next;
- DelNode(n);
- n = next;
- }
- }
- }
- DohFree(h->hashtable);
- h->hashtable = 0;
- h->hashsize = 0;
- DohFree(h);
- }
- /* -----------------------------------------------------------------------------
- * Hash_clear()
- *
- * Clear all of the entries in the hash table.
- * ----------------------------------------------------------------------------- */
- static void
- Hash_clear(DOH *ho) {
- Hash *h = (Hash *) ObjData(ho);
- HashNode *n,*next;
- int i;
- for (i = 0; i < h->hashsize; i++) {
- if ((n = h->hashtable[i])) {
- while (n) {
- next = n->next;
- DelNode(n);
- n = next;
- }
- }
- h->hashtable[i] = 0;
- }
- h->nitems = 0;
- }
- /* resize the hash table */
- static void resize(Hash *h) {
- HashNode *n, *next, **table;
- int oldsize, newsize;
- int i, p, hv;
- if (h->nitems < 2*h->hashsize) return;
- /* Too big. We have to rescale everything now */
- oldsize = h->hashsize;
- /* Calculate a new size */
- newsize = 2*oldsize+1;
- p = 3;
- while (p < (newsize >> 1)) {
- if (((newsize/p)*p) == newsize) {
- newsize+=2;
- p = 3;
- continue;
- }
- p = p + 2;
- }
- table = (HashNode **) DohMalloc(newsize*sizeof(HashNode *));
- for (i = 0; i < newsize; i++ ) {
- table[i] = 0;
- }
- /* Walk down the old set of nodes and re-place */
- h->hashsize = newsize;
- for (i = 0; i < oldsize; i++) {
- n = h->hashtable[i];
- while (n) {
- hv = Hashval(n->key) % newsize;
- next = n->next;
- n->next = table[hv];
- table[hv] = n;
- n = next;
- }
- }
- DohFree(h->hashtable);
- h->hashtable = table;
- }
- /* -----------------------------------------------------------------------------
- * Hash_setattr()
- *
- * Set an attribute in the hash table. Deletes the existing entry if it already
- * exists.
- * ----------------------------------------------------------------------------- */
- static int
- Hash_setattr(DOH *ho, DOH *k, DOH *obj) {
- int hv;
- HashNode *n, *prev;
- Hash *h = (Hash *) ObjData(ho);
-
- if (!obj) {
- return DohDelattr(ho,k);
- }
- if (!DohCheck(k)) k = find_key(k);
- if (!DohCheck(obj)) {
- obj = NewString((char *) obj);
- Decref(obj);
- }
- hv = (Hashval(k)) % h->hashsize;
- n = h->hashtable[hv];
- prev = 0;
- while (n) {
- if (Cmp(n->key,k) == 0) {
- /* Node already exists. Just replace its contents */
- if (n->object == obj) {
- /* Whoa. Same object. Do nothing */
- return 1;
- }
- Delete(n->object);
- n->object = obj;
- Incref(obj);
- return 1; /* Return 1 to indicate a replacement */
- } else {
- prev = n;
- n = n->next;
- }
- }
- /* Add this to the table */
- n = NewNode(k,obj);
- if (prev) prev->next = n;
- else h->hashtable[hv] = n;
- h->nitems++;
- resize(h);
- return 0;
- }
- /* -----------------------------------------------------------------------------
- * Hash_getattr()
- *
- * Get an attribute from the hash table. Returns 0 if it doesn't exist.