123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238 |
- /*
- * CDE - Common Desktop Environment
- *
- * Copyright (c) 1993-2012, The Open Group. All rights reserved.
- *
- * These libraries and programs are free software; you can
- * redistribute them and/or modify them under the terms of the GNU
- * Lesser General Public License as published by the Free Software
- * Foundation; either version 2 of the License, or (at your option)
- * any later version.
- *
- * These libraries and programs are distributed in the hope that
- * they will be useful, but WITHOUT ANY WARRANTY; without even the
- * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
- * PURPOSE. See the GNU Lesser General Public License for more
- * details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with these libraries and programs; if not, write
- * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
- * Floor, Boston, MA 02110-1301 USA
- */
- /* $XConsortium: hash.c /main/1 1996/04/21 19:23:21 drk $ */
- /*
- * (c) Copyright 1993, 1994 Hewlett-Packard Company
- * (c) Copyright 1993, 1994 International Business Machines Corp.
- * (c) Copyright 1993, 1994 Novell, Inc.
- * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
- */
- /*
- Synopsis:
- #include "hash.h"
- void * _DtCmMakeHash(int size)
- void * _DtCmMakeIHash(int size)
- void ** _DtCmGetHash(void * tbl, unsigned char * key)
- void ** _DtCmFindHash(void * tbl,unsigned char * key)
- void ** _DtCmDelHash(void * tbl, unsigned char * key)
- int _DtCmOperateHash(void * tbl, void (*op_func)(), void * usr_arg)
- void _DtCmDestroyHash(void * tbl, int (*des_func)(), void * usr_arg)
- Description:
- These routines provide a general purpose hash table facility that
- supports multiple open hash tables. Each entry in the table consists of a
- key and a data ptr. The key is a null terminated character string, while
- the data ptr is opaque. Since all the entries are maintained in a doubly
- linked lists, deletions and operations on entire table execute very quickly.
- This make these routines suitable for use when the tables may be very ephemeral.
- _DtCmMakeHash returns a pointer to the created table. The size argument
- indicate the number of buckets the routine is to allocate. This should be ~
- the max number of items expected in the table for maximum performance....
- but /2 or /3 should still be ok. Note that for maximum efficiency the hash
- table size should be a prime number (a side effect of the hash alorithm).
- _DtCmMakeIHash performs the same function as _DtCmMakeHash, except that the hash
- routines will use the key arguments as arbitrary integers rather than strings.
- _DtCmGetHash searches the specified hash table tbl for an entry with the
- specified key. If the entry does not exist, it is created with a NULL data
- ptr. The routine returns a ptr to the area where the data ptr is (can be)
- stored.
- _DtCmFindHash searchs the table for an entry with the specified key. If the
- entry is found, the address of the data pointer associated with the key is
- returned. If no such entry exists, the routine returns NULL.
- _DtCmDelHash deletes the specified table entry and returns the associated data
- ptr. If the entry did not exist ( or the data ptr was NULL), the routine
- returns NULL.
- _DtCmOperateHash calls the routine pointed to by op_func once for each entry
- in tbl, with three arguments: the data ptr, the usr_arg ptr and a ptr to the
- key for that entry (which should NOT be altered). This is useful for
- transversing a hash table quickly and operating on the entries. Note that
- the order of the traversal of the hash table is the reverse order of
- insertion.
- _DtCmDestroyHash destroys the specified hash table after operating on it
- with the specified des_func function as described for _DtCmOperateHash. All storage
- allocated by the hash routines is reclaimed.
- Author: Bart Smaalders 1/89
- */
- #include <EUSCompat.h>
- #include <stdio.h> /* grab NULL define */
- #include <stdlib.h>
- #include <string.h>
- #include "hash.h"
- static int hash_string(const char *s, int modulo);
- typedef struct hash_entry {
- struct hash_entry
- * next_entry,
- * right_entry,
- * left_entry;
- unsigned char * key;
- void * data;
- } hash_entry;
- typedef struct hash {
- int size;
- hash_entry ** table;
- hash_entry * start;
- enum hash_type { String_Key = 0 , Integer_Key = 1} hash_type;
- } hash;
- void * _DtCmMakeHash(int size)
- {
- hash * ptr;
- ptr = (hash *) malloc(sizeof(*ptr));
- ptr->size = size;
- ptr->table = (hash_entry **) malloc( (unsigned) (sizeof(hash_entry *) * size) );
- (void)memset((char *) ptr->table, (char) 0, sizeof(hash_entry *)*size);
- ptr->start = NULL;
- ptr->hash_type = String_Key;
- return((void*)ptr);
- }
- void ** _DtCmGetHash(void * t, const unsigned char * key)
- {
- hash * tbl = (hash *) t;
- int bucket;
- hash_entry * tmp;
- hash_entry * new;
- if(tbl->hash_type == String_Key)
- tmp = tbl->table[bucket = hash_string(key, tbl->size)];
- else
- tmp = tbl->table[bucket = abs((long)key) % tbl->size];
- if(tbl->hash_type == String_Key)
- while(tmp!=NULL)
- {
- if(strcmp((char *)tmp->key, (char *)key)==0)
- return(&tmp->data);
- tmp = tmp->next_entry;
- }
- else
- while(tmp!=NULL)
- {
- if(tmp->key == key)
- return(&tmp->data);
- tmp = tmp->next_entry;
- }
-
- /*
- not found....
- insert new entry into bucket...
- */
- new = (hash_entry *) malloc(sizeof(*new));
- new->key = (unsigned char *)((tbl->hash_type == String_Key)?(unsigned char *)strdup((char *)key):key);
- /*
- hook into chain from tbl...
- */
- new->right_entry = NULL;
- new->left_entry = tbl->start;
- tbl->start = new;
- /*
- hook into bucket chain
- */
- new->next_entry = tbl->table[bucket];
- tbl->table[bucket] = new;
- new->data = NULL; /* so we know that it is new */
- return((void*)& new->data);
- }
- void ** _DtCmFindHash(void * t, const unsigned char * key)
- {
- hash * tbl = (hash *) t;
- hash_entry * tmp;
- if(tbl->hash_type == String_Key)
- {
- tmp = tbl->table[hash_string(key, tbl->size)];
- for(;tmp!=NULL; tmp = tmp->next_entry)
- if(!strcmp((char *)tmp->key, (char *)key))
- return((void *)&tmp->data);
- }
- else
- {
- tmp = tbl->table[abs((long)key) % tbl->size];
- for(;tmp!=NULL; tmp = tmp->next_entry)
- if(tmp->key == key)
- return((void *)&tmp->data);
- }
- return(NULL);
- }
- void _DtCmDestroyHash(void * t, int (*ptr)(void *, void *, unsigned char *), void * usr_arg)
- {
- hash * tbl = (hash *) t;
- hash_entry * tmp = tbl->start, * prev;
- while(tmp)
- {
- if(ptr)
- (*ptr)(tmp->data,usr_arg, tmp->key);
- if(tbl->hash_type == String_Key)
- free(tmp->key);
- prev = tmp;
- tmp = tmp->left_entry;
- free((char *)prev);
- }
- free((char *)tbl->table);
- free(tbl);
- }
- static int hash_string(const char *s, int modulo)
- {
- unsigned result = 0;
- int i=1;
- while(*s!=0)
- result += (*s++ << i++);
- return(result % modulo);
- }
|