(file) Return to strhash.c CVS log (file) (dir) Up to [RizwankCVS] / testProject / afmlib

  1 rizwank 1.1 /*
  2              * String hash table.
  3              * Copyright (c) 1995-1999 Markku Rossi.
  4              *
  5              * Author: Markku Rossi <mtr@iki.fi>
  6              */
  7             
  8             /*
  9              * This program is free software; you can redistribute it and/or modify
 10              * it under the terms of the GNU General Public License as published by
 11              * the Free Software Foundation; either version 2, or (at your option)
 12              * any later version.
 13              *
 14              * This program is distributed in the hope that it will be useful,
 15              * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16              * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 17              * GNU General Public License for more details.
 18              *
 19              * You should have received a copy of the GNU General Public License
 20              * along with this program; see the file COPYING.  If not, write to
 21              * the Free Software Foundation, 59 Temple Place - Suite 330,
 22 rizwank 1.1  * Boston, MA 02111-1307, USA.
 23              */
 24             
 25             #include <afmint.h>
 26             #include <strhash.h>
 27             
 28             /*
 29              * Types and definitions.
 30              */
 31             
 32             #define STRHASH_DEBUG 0
 33             
 34             #define HASH_SIZE 8192
 35             
 36             struct hash_list_st
 37             {
 38               struct hash_list_st *next;
 39               char *key;			/* malloc()ated copy of key. */
 40               int keylen;
 41               void *data;
 42             };
 43 rizwank 1.1 
 44             typedef struct hash_list_st HashList;
 45             
 46             typedef HashList *HashTable;
 47             
 48             typedef struct stringhash_st
 49             {
 50               HashTable *hash_table;
 51             
 52               /* Scan support. */
 53               unsigned int next_idx;
 54               HashList *next_item;
 55             
 56             #if STRHASH_DEBUG
 57               int items_in_hash;
 58             #endif /* STRHASH_DEBUG */
 59             } *hash_t;
 60             
 61             
 62             /*
 63              * Prototypes for static functions.
 64 rizwank 1.1  */
 65             
 66             static int count_hash ___P ((const char *key, int keylen));
 67             
 68             
 69             /*
 70              * Global functions.
 71              */
 72             
 73             StringHashPtr
 74             strhash_init ()
 75             {
 76               StringHashPtr tmp;
 77             
 78               tmp = (StringHashPtr) calloc (1, sizeof (*tmp));
 79               if (!tmp)
 80                 return NULL;
 81             
 82               tmp->hash_table = (HashTable *) calloc (HASH_SIZE, sizeof (HashTable));
 83               if (!tmp->hash_table)
 84                 {
 85 rizwank 1.1       free (tmp);
 86                   return NULL;
 87                 }
 88             
 89             #if STRHASH_DEBUG
 90               tmp->items_in_hash = 0;
 91             #endif /* STRHASH_DEBUG */
 92               return tmp;
 93             }
 94             
 95             
 96             void
 97             strhash_free (StringHashPtr hash)
 98             {
 99               HashList *list, *list_next;
100               int i;
101             
102               if (!hash)
103                 return;
104             
105               /* Free chains. */
106 rizwank 1.1   for (i = 0; i < HASH_SIZE; i++)
107                 for (list = hash->hash_table[i]; list; list = list_next)
108                   {
109             	list_next = list->next;
110             	free (list->key);
111             	free (list);
112                   }
113             
114               /* Free hash. */
115               free (hash->hash_table);
116               free (hash);
117             }
118             
119             
120             int
121             strhash_put (StringHashPtr hash, char *key, int keylen, void *data,
122             	     void **old_data)
123             {
124               HashList *list, *prev = NULL;
125               int pos, cmp_val;
126             
127 rizwank 1.1   if (!hash || !key || keylen <= 0)
128                 return 0;
129             
130               if (old_data)
131                 *old_data = NULL;
132               pos = count_hash (key, keylen);
133             
134               /* Is it already here? */
135               for (list = hash->hash_table[pos]; list; prev = list, list = list->next)
136                 if (list->keylen == keylen)
137                   {
138             	cmp_val = memcmp (key, list->key, keylen);
139             	if (cmp_val == 0)
140             	  {
141             	    /* We had an old occurence. */
142             	    if (old_data)
143             	      *old_data = list->data;
144             	    list->data = data;
145             	    return 1;
146             	  }
147             	else if (cmp_val < 0)
148 rizwank 1.1 	  {
149             	    /* Run over. Correct position is prev->next. */
150             	    break;
151             	  }
152                   }
153                 else if (list->keylen > keylen)
154                   /* Lists are kept sorted so that smallest keys are at the head and
155             	 keys with equal length are in normal sorted order. */
156                   break;
157             
158               /* No old data. */
159               list = (HashList *) calloc (1, sizeof (HashList));
160               if (!list)
161                 return 0;
162               list->key = (char *) malloc (keylen);
163               if (!list->key)
164                 {
165                   free (list);
166                   return 0;
167                 }
168             
169 rizwank 1.1   memcpy (list->key, key, keylen);
170               list->keylen = keylen;
171               list->data = data;
172             
173               /* Insert list to the correct position. */
174               if (!prev)
175                 {
176                   list->next = hash->hash_table[pos];
177                   hash->hash_table[pos] = list;
178                 }
179               else
180                 {
181                   list->next = prev->next;
182                   prev->next = list;
183                 }
184             #if STRHASH_DEBUG
185               hash->items_in_hash++;
186             #endif /* STRHASH_DEBUG */
187               return 1;
188             }
189             
190 rizwank 1.1 
191             int
192             strhash_get (StringHashPtr hash, const char *key, int keylen, void **data)
193             {
194               HashList *list;
195               int pos, cmp_val;
196             
197               if (!hash || !key || keylen <= 0 || !data)
198                 return 0;
199             
200               *data = NULL;
201               pos = count_hash (key, keylen);
202               for (list = hash->hash_table[pos]; list; list = list->next)
203                 if (list->keylen == keylen)
204                   {
205             	cmp_val = memcmp (key, list->key, keylen);
206             	if (cmp_val == 0)
207             	  {
208             	    *data = list->data;
209             	    return 1;
210             	  }
211 rizwank 1.1 	else if (cmp_val < 0)
212             	  /* Run over. */
213             	  break;
214                   }
215                 else if (list->keylen > keylen)
216                   /* Run over. */
217                   break;
218             
219               return 0;
220             }
221             
222             
223             int
224             strhash_delete (StringHashPtr hash, const char *key, int keylen, void **data)
225             {
226               HashList *list, *prev = NULL;
227               int pos, cmp_val;
228             
229               if (!hash || !key || keylen <= 0 || !data)
230                 return 0;
231             
232 rizwank 1.1   *data = NULL;
233               pos = count_hash (key, keylen);
234               for (list = hash->hash_table[pos]; list; prev = list, list = list->next)
235                 if (list->keylen == keylen)
236                   {
237             	cmp_val = memcmp (key, list->key, keylen);
238             	if (cmp_val == 0)
239             	  {
240             	    /* Value found. */
241             	    if (prev == NULL)
242             	      hash->hash_table[pos] = list->next;
243             	    else
244             	      prev->next = list->next;
245             
246             	    *data = list->data;
247             	    free (list->key);
248             	    free (list);
249             
250             	    /* Init scan. */
251             	    hash->next_idx = 0;
252             	    hash->next_item = NULL;
253 rizwank 1.1 
254             #if STRHASH_DEBUG
255             	    hash->items_in_hash--;
256             #endif /* STRHASH_DEBUG */
257             	    return 1;
258             	  }
259             	else if (cmp_val < 0)
260             	  /* Not found. */
261             	  break;
262                   }
263                 else if (list->keylen > keylen)
264                   /* Run over. */
265                   break;
266             
267               return 0;
268             }
269             
270             
271             int
272             strhash_get_first (StringHashPtr hash, char **key_return,
273             		   int *keylen_return, void **data_return)
274 rizwank 1.1 {
275               if (!hash || !key_return || !keylen_return || !data_return)
276                 return 0;
277             
278               for (hash->next_idx = 0; hash->next_idx < HASH_SIZE; hash->next_idx++)
279                 {
280                   hash->next_item = hash->hash_table[hash->next_idx];
281                   if (hash->next_item)
282             	{
283             	  *key_return = hash->next_item->key;
284             	  *keylen_return = hash->next_item->keylen;
285             	  *data_return = hash->next_item->data;
286             	  return 1;
287             	}
288                 }
289               return 0;
290             }
291             
292             
293             int
294             strhash_get_next (StringHashPtr hash, char **key_return,
295 rizwank 1.1 		  int *keylen_return, void **data_return)
296             {
297               if (!hash || !key_return || !keylen_return || !data_return)
298                 return 0;
299             
300               for (; hash->next_idx < HASH_SIZE; hash->next_idx++)
301                 {
302                   if (hash->next_item == NULL)
303             	hash->next_item = hash->hash_table[hash->next_idx];
304                   else
305             	hash->next_item = hash->next_item->next;
306             
307                   if (hash->next_item)
308             	{
309             	  *key_return = hash->next_item->key;
310             	  *keylen_return = hash->next_item->keylen;
311             	  *data_return = hash->next_item->data;
312             	  return 1;
313             	}
314                 }
315               return 0;
316 rizwank 1.1 }
317             
318             
319             #if STRHASH_DEBUG
320             void
321             strhash_debug (StringHashPtr hash)
322             {
323               int i, count = 0, max = 0;
324               HashList *tmp;
325             
326               if (!hash)
327                 {
328                   fprintf (stderr, "Invalid hash handle!\n");
329                   return;
330                 }
331               fprintf (stderr, "hash_size\t%d\n", HASH_SIZE);
332               fprintf (stderr, "items_in_hash\t%d\n", hash->items_in_hash);
333             
334               for (i = 0; i < HASH_SIZE; i++)
335                 if (hash->hash_table[i] == NULL)
336                   count++;
337 rizwank 1.1   fprintf (stderr, "empty entries\t%d\n", count);
338             
339               count = 0;
340               for (i = 0; i < HASH_SIZE; i++)
341                 {
342                   for (tmp = hash->hash_table[i]; tmp; tmp = tmp->next)
343             	count++;
344                   max = count > max ? count : max;
345                   count = 0;
346                 }
347               fprintf (stderr, "longest list\t%d\n", max);
348             
349               if (max > 0)
350                 {
351                   /* Print the first longest list. */
352                   for (i = 0; i < HASH_SIZE; i++)
353             	{
354             	  count = 0;
355             	  for (tmp = hash->hash_table[i]; tmp; tmp = tmp->next)
356             	    count++;
357             	  if (count == max)
358 rizwank 1.1 	    {
359             	      for (count = 0, tmp = hash->hash_table[i]; tmp;
360             		   tmp = tmp->next, count++)
361             		{
362             		  fprintf (stderr, "%d\t", count);
363             		  for (i = 0; i < tmp->keylen; i++)
364             		    fprintf (stderr, "%c", tmp->key[i]);
365             		}
366             	      break;
367             	    }
368             	}
369                 }
370             }
371             #endif /* STRHASH_DEBUG */
372             
373             
374             /*
375              * Static functions.
376              */
377             
378             static int
379 rizwank 1.1 count_hash (const char *key, int keylen)
380             {
381               unsigned int val = 0;
382               int i;
383             
384               for (i = 0; i < keylen; i++)
385                 val = (val << 5) ^ (unsigned char) key[i]
386                   ^ (val >> 16) ^ (val >> 7);
387               return val % HASH_SIZE;
388             }

Rizwan Kassim
Powered by
ViewCVS 0.9.2