00001 00002 00003 00004 00005 00006 00007 00008 00009 00010 00011 00012 00013 00014 00015 00016 00017 00018 00019
00020
00021 #include "hash.h"
00022 #include <string.h>
00023
00024 #ifndef CHAIN
00025 static const hashItem deletednode = { NULL, NULL };
00026 #endif
00027
00028
00029 static int hash ( char *key ) {
00030 unsigned int hash = 0;
00031
00032 while ( *key ) {
00033 00034
00035 hash ^= *key++;
00036 hash <<= 1;
00037 }
00038
00039 return hash;
00040 }
00041
00042
00043 void *hash_data ( HashTable *t, char *key ) {
00044 unsigned int index, initial;
00045 #ifdef CHAIN
00046 hashItem *h;
00047 #endif
00048
00049 if ( t == NULL || t->size <= 0 || t->hash_func == NULL || key == NULL )
00050 return NULL;
00051
00052 index = t->hash_func(key) % t->size;
00053
00054 #ifdef CHAIN
00055 for ( h = t->item[index]; h != NULL; h = h->next )
00056 if ( strcmp(key, h->key) == 0 )
00057 return h->data;
00058 #else
00059 while ( t->item[index] ) {
00060 if ( t->item[index]->key == NULL || strcmp(key, t->item[index]->key) != 0 ) {
00061 index = (index+1)%t->size;
00062 if ( index == initial ) {
00063 return NULL;
00064 }
00065 }
00066 else {
00067 return t->item[index]->data;
00068 }
00069 }
00070 #endif
00071
00072 return NULL;
00073 }
00074
00075 00076
00077 void *hash_del ( HashTable *t, char *key ) {
00078 unsigned int initial, index;
00079 void *data;
00080 #ifdef CHAIN
00081 hashItem *h, *last = NULL;
00082 #endif
00083
00084 if ( t == NULL || t->size <= 0 || t->hash_func == NULL || key == NULL )
00085 return NULL;
00086
00087 initial = index = t->hash_func(key) % t->size;
00088
00089 #ifdef CHAIN
00090 for ( h = t->item[index]; h != NULL; h = h->next ) {
00091 if ( strcmp(key, h->key) == 0 ) {
00092
00093 if ( last )
00094 last->next = h->next;
00095 else
00096 t->item[index] = h->next;
00097 free(h->key);
00098 data = h->data;
00099 free(h);
00100 h = NULL;
00101 return data;
00102 }
00103 last = h;
00104 }
00105 #else
00106 while ( t->item[index] ) {
00107 if ( strcmp(key, t->item[index]->key) != 0 ) {
00108 index = (index+1)%t->size;
00109 if ( index == initial ) {
00110 return NULL;
00111 }
00112 }
00113 else {
00114 free(t->item[index]->key);
00115 data = t->item[index]->data;
00116 free(t->item[index]);
00117 t->item[index] = &deletednode;
00118 return data;
00119 }
00120 }
00121 #endif
00122
00123 return NULL;
00124 }
00125
00126 00127
00128 int hash_free ( HashTable *t, void (*free_func)(void *) ) {
00129 int i;
00130 #ifdef CHAIN
00131 hashItem *h, *next = NULL;
00132 #endif
00133
00134 if ( t == NULL || t->size <= 0 || t->hash_func == NULL )
00135 return -1;
00136
00137 for ( i = 0; i < t->size; i++ ) {
00138 #ifdef CHAIN
00139 for ( h = t->item[i]; h != NULL; h = next ) {
00140 next = h->next;
00141 if ( h->key )
00142 free(h->key);
00143 if ( free_func )
00144 free_func(h->data);
00145 free(h);
00146 }
00147 #else
00148 if ( t->item[i] != NULL && t->item[i] != &deletednode ) {
00149 if ( t->item[i]->key )
00150 free(t->item[i]->key);
00151 if ( free_func )
00152 free_func(t->item[i]->data);
00153 free(t->item[i]);
00154 }
00155 #endif
00156 }
00157
00158 t->size = 0;
00159 return 0;
00160 }
00161
00162 00163 00164 00165
00166 int hash_init ( HashTable *t, int size, int (* hash_func)(char *) ) {
00167 if ( size <= 0 )
00168 return -1;
00169
00170 if ( t == NULL ) {
00171 t = (HashTable *)malloc(sizeof(HashTable));
00172 if ( t == NULL )
00173 return -1;
00174 }
00175
00176 t->size = size;
00177 t->item = (hashItem **)malloc(sizeof(hashItem *)*size);
00178 if ( t->item == NULL ) {
00179 t->size = 0;
00180 return -1;
00181 }
00182 for ( size-- ; size >= 0; size-- )
00183 t->item[size] == NULL;
00184
00185 if ( hash_func )
00186 t->hash_func = hash_func;
00187 else
00188 t->hash_func = hash;
00189
00190 return 0;
00191 }
00192
00193 00194
00195 int hash_insert ( HashTable *t, char *key, void *data ) {
00196 unsigned int index, initial;
00197 #ifdef CHAIN
00198 hashItem *h;
00199 #endif
00200
00201 if ( t == NULL || t->size <= 0 || t->hash_func == NULL || key == NULL )
00202 return -1;
00203
00204 initial = index = t->hash_func(key) % t->size;
00205
00206
00207 if ( t->item[index] == NULL ) {
00208 t->item[index] = (hashItem *)malloc(sizeof(hashItem));
00209 if ( t->item[index] == NULL )
00210 return -1;
00211
00212 t->item[index]->key = strdup(key);
00213 t->item[index]->data = data;
00214 #ifdef CHAIN
00215 t->item[index]->next = NULL;
00216 #endif
00217
00218 return index;
00219 }
00220
00221 #ifdef CHAIN
00222
00223 for ( h = t->item[index]; h->next != NULL; h = h->next )
00224 if ( strcmp(key, h->key) == 0 )
00225 return -2;
00226
00227 h->next = (hashItem *)malloc(sizeof(hashItem));
00228 if ( h->next == NULL )
00229 return -1;
00230
00231 h->next->key = strdup(key);
00232 h->next->data = data;
00233 h->next->next = NULL;
00234 #else
00235
00236 while ( t->item[index] != NULL ) {
00237 index = (index+1) % t->size;
00238 if ( index == initial )
00239 return -1;
00240 if ( strcmp(key, t->item[index]->key) == 0 )
00241 return -2;
00242 }
00243
00244 t->item[index] = (hashItem *)malloc(sizeof(hashItem));
00245 if ( t->item[index] == NULL )
00246 return -1;
00247
00248 t->item[index]->key = strdup(key);
00249 t->item[index]->data = data;
00250 #endif
00251
00252 return index;
00253 }
00254
00255 00256
00257 char *hash_key ( HashTable *t, void *data ) {
00258 int i;
00259 #ifdef CHAIN
00260 hashItem *h;
00261 #endif
00262
00263 for ( i = 0; i < t->size; i++ ) {
00264 #ifdef CHAIN
00265 h = t->item[i];
00266 while ( h ) {
00267 if ( h->data == data )
00268 return h->key;
00269 h = h->next;
00270 }
00271 #else
00272 if ( t->item[i] && t->item[i]->data == data )
00273 return t->item[i]->key;
00274 #endif
00275 }
00276 return NULL;
00277 }