Main Page   Compound List   File List   Compound Members   File Members  

hash.c

00001 /*
00002 GOCR Copyright (C) 2000  Joerg Schulenburg Joerg.Schulenburg@physik.uni-magdeburg.de 
00003 GOCR API Copyright (C) 2001 Bruno Barberi Gnecco <brunobg@sourceforge.net>
00004 
00005 This program is free software; you can redistribute it and/or
00006 modify it under the terms of the GNU General Public License
00007 as published by the Free Software Foundation; either version 2
00008 of the License, or (at your option) any later version.
00009 
00010 This program is distributed in the hope that it will be useful,
00011 but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 GNU General Public License for more details.
00014 
00015 You should have received a copy of the GNU General Public License
00016 along with this program; if not, write to the Free Software
00017 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00018 
00019 */
00020 
00021 /* This file was adapted by Bruno Barberi Gnecco for DICElib */
00022 
00023 
00024 #include "hash.h"
00025 #include <stdlib.h>
00026 #include <string.h>
00027 #include <stdio.h>
00028 
00029 /* internal Hash generator */
00030 static int hash ( char *key ) {
00031   unsigned int hash = 0;
00032 
00033   while ( *key ) {
00034     /* this algorithm is from Bob Stout's Snippets collection, and was written
00035       by Jerry Coffin and HenkJan Wolthuis and released under public domain */
00036     hash ^= *key++;
00037     hash <<= 1;
00038   }
00039 
00040   return hash;
00041 }
00042 
00043 /* Given a key, returns the data associated with it. */
00044 void *hash_data ( HashTable *t, char *key ) {
00045   unsigned int index;
00046   hashItem *h;
00047   
00048   if ( t == NULL || t->size <= 0 || t->hash_func == NULL || key == NULL )
00049     return NULL;
00050 
00051   index = t->hash_func(key);
00052   index %= t->size;
00053 
00054   for ( h = t->item[index]; h != NULL; h = h->next )
00055     if ( key && strcmp(key, h->key) == 0 )
00056       return h->data;
00057 
00058   return NULL;
00059 }
00060 
00061 /* Deletes the entry associated with key. Returns a pointer to the data 
00062 structure, which is not freed. */
00063 void *hash_del ( HashTable *t, char *key ) {
00064   unsigned int index;
00065   void *data;
00066   hashItem *h, *last = NULL;
00067   
00068   if ( t == NULL || t->size <= 0 || t->hash_func == NULL || key == NULL )
00069     return NULL;
00070 
00071   index = t->hash_func(key) % t->size;
00072 
00073   for ( h = t->item[index]; h != NULL; h = h->next ) {
00074     if ( strcmp(key, h->key) == 0 ) {
00075       /* fix list */
00076       if ( last )
00077         last->next = h->next;
00078       else /* is first item */
00079         t->item[index] = h->next;
00080       free(h->key);
00081       data = h->data;
00082       free(h);
00083       h = NULL;
00084       return data;
00085     }
00086     last = h;
00087   }
00088 
00089   return NULL;
00090 }
00091 
00092 /* Frees the hash table contents (but not the table). If free_func is not NULL,
00093 it's called for every data stored in the table */
00094 int hash_free ( HashTable *t, void (*free_func)(void *) ) {
00095   int i;
00096   hashItem *h, *next = NULL;
00097 
00098   if ( t == NULL || t->size <= 0 || t->hash_func == NULL )
00099     return -1;
00100 
00101   for ( i = 0; i < t->size; i++ ) {
00102     for ( h = t->item[i]; h != NULL; h = next ) {
00103       next = h->next;
00104       if ( h->key )
00105         free(h->key); 
00106       if ( free_func )
00107         free_func(h->data);
00108       free(h);
00109     }
00110   }
00111   free(t->item);
00112 
00113   t->size = 0;
00114   return 0;
00115 }
00116 
00117 /* Initialize a hash table, with size entries, using hash_func as the hash
00118 generator func. If t is NULL, the function automaticall mallocs memory for it.
00119 If hash_func is NULL, the default internal is used. Returns -1 on error, 0 if
00120 OK. */
00121 int hash_init ( HashTable *t, int size, int (* hash_func)(char *) ) {
00122   if ( size <= 0 )
00123     return -1;
00124 
00125   if ( t == NULL ) {
00126     t = (HashTable *)malloc(sizeof(HashTable));
00127     if ( t == NULL )
00128       return -1;
00129   }
00130 
00131   t->size = size;
00132   t->item = (hashItem **)malloc(sizeof(hashItem *)*size);
00133   if ( t->item == NULL ) {
00134     t->size = 0;
00135     return -1;
00136   }
00137   for ( --size; size >= 0; size-- )
00138     t->item[size] = NULL;
00139 
00140   if ( hash_func )
00141     t->hash_func = hash_func;
00142   else
00143     t->hash_func = hash;
00144 
00145   return 0;
00146 }
00147 
00148 /* Inserts a new entry in table t, with key key, which will contain data.
00149 Returns -2 if data already exists, -1 on error, else the hash. */
00150 int hash_insert ( HashTable *t, char *key, void *data ) {
00151   unsigned int index;
00152   hashItem *h, *hh;
00153 
00154   if ( t == NULL || t->size <= 0 || t->hash_func == NULL || key == NULL )
00155     return -1;
00156 
00157   index = t->hash_func(key) % t->size;
00158 
00159   /* if index is free, fill it */
00160   if ( t->item[index] == NULL ) { 
00161     t->item[index] = (hashItem *)malloc(sizeof(hashItem));
00162     if ( t->item[index] == NULL )
00163       return -1;
00164 
00165     t->item[index]->key  = strdup(key);
00166     if ( !t->item[index]->key )
00167             return -1;
00168     t->item[index]->data = data;
00169     t->item[index]->next = NULL;
00170 
00171     return index;
00172   }
00173 
00174   /* no, then find if the key already exists, and reach the last link */
00175   for ( h = t->item[index]; h != NULL; h = h->next ) {
00176     if ( strcmp(key, h->key) == 0 )
00177       return -2;
00178     hh = h;
00179   }
00180 
00181   hh->next = (hashItem *)malloc(sizeof(hashItem));
00182   if ( hh->next == NULL )
00183     return -1;
00184 
00185   hh->next->key  = strdup(key);
00186   if ( !hh->next->key ) {
00187           return -1;
00188   }
00189   hh->next->data = data;
00190   hh->next->next = NULL;
00191 
00192   return index;
00193 }
00194 
00195 /* Given data, searches the table t for its first occurrence, and returns the 
00196 key related to it. */
00197 char *hash_key ( HashTable *t, void *data ) {
00198   int i;
00199   hashItem *h;
00200 
00201   for ( i = 0; i < t->size; i++ ) {
00202     h = t->item[i];
00203     while ( h ) {
00204       if ( h->data == data )
00205         return h->key;
00206       h = h->next;
00207     }
00208   }
00209   return NULL;
00210 }

Generated at Sun Dec 9 16:13:18 2001 for dicelib by doxygen1.2.9.1 written by Dimitri van Heesch, © 1997-2001