Bioplib
Protein Structure C Library
 All Data Structures Files Functions Variables Typedefs Macros Pages
hash.c
Go to the documentation of this file.
1 /************************************************************************/
2 /**
3 
4  \file hash.c
5 
6  \version V1.2
7  \date 23.08.15
8  \brief Flexible hash functions
9 
10  \copyright (c) Dr. Andrew C. R. Martin, UCL, 2015
11  \author Dr. Andrew C. R. Martin
12  \par
13  Institute of Structural & Molecular Biology,
14  University College London,
15  Gower Street,
16  London.
17  WC1E 6BT.
18  \par
19  andrew@bioinf.org.uk
20  andrew.martin@ucl.ac.uk
21 
22 **************************************************************************
23 
24  This code is NOT IN THE PUBLIC DOMAIN, but it may be copied
25  according to the conditions laid out in the accompanying file
26  COPYING.DOC.
27 
28  The code may be modified as required, but any modifications must be
29  documented so that the person responsible can be identified.
30 
31  The code may not be sold commercially or included as part of a
32  commercial product except as described in the file COPYING.DOC.
33 
34 **************************************************************************
35 
36  Description:
37  ============
38 
39  Based very loosely on code from
40  http://www.sourcecodesworld.com/source/show.asp?ScriptID=1188
41 
42 **************************************************************************
43 
44  Usage:
45  ======
46  Compile with -finline-functions
47 
48 **************************************************************************
49 
50  Revision History:
51  =================
52 - V1.0 14.05.15 Original By: ACRM
53 - V1.1 03.06.15 Added wrappers to blSetHashValue()
54 - V1.2 23.08.15 Cast NAN for int return
55 
56 *************************************************************************/
57 /* Doxygen
58  -------
59  #GROUP General Programming
60  #SUBGROUP Hashes / Dictionaries
61 
62  #FUNCTION blInitializeHash()
63  Initializes a hash structure
64 
65  #FUNCTION blFreeHashKeyList()
66  Frees a list of hash keys from blGetHashKeyList()
67 
68  #FUNCTION blGetHashKeyList()
69  Allocates an array containing the hash keys
70 
71  #FUNCTION blFreeHash()
72  Frees all memory associated with a hash
73 
74  #FUNCTION blSetHashValue()
75  Sets a hash key:value pair
76 
77  #FUNCTION blSetHashValueString()
78  Sets a hash key:value pair for a string value
79 
80  #FUNCTION blSetHashValueInt()
81  Sets a hash key:value pair for an int value
82 
83  #FUNCTION blSetHashValueDouble()
84  Sets a hash key:value pair for a double value
85 
86  #FUNCTION blSetHashValuePointer()
87  Sets a hash key:value pair for a general pointer (BPTR) value
88 
89  #FUNCTION blSetHashValueChar()
90  Sets a hash key:value pair for a char value
91 
92  #FUNCTION blGetHashValue()
93  Gets a hash value for a specified key
94 
95  #FUNCTION blGetHashValueInt()
96  Wrapper to blGetHashValue() specifically for ints
97 
98  #FUNCTION blGetHashValueDouble()
99  Wrapper to blGetHashValue() specifically for doubles
100 
101  #FUNCTION blGetHashValueChar()
102  Wrapper to blGetHashValue() specifically for chars
103 
104  #FUNCTION blGetHashValueString()
105  Wrapper to blGetHashValue() specifically for strings
106 
107  #FUNCTION blGetHashValuePointer()
108  Wrapper to blGetHashValue() specifically for pointers
109 
110  #FUNCTION blDumpHash()
111  Utility function to dump a hash to a file
112 
113  #FUNCTION blHashKeyDefined()
114  Tests if a key is defined in the hash
115 
116  #FUNCTION blDeleteHashKey()
117  Deletes an entry from the hash
118 
119 *************************************************************************/
120 /* Includes
121 */
122 #include <string.h>
123 #include <stdio.h>
124 #include <stdlib.h>
125 #include <stdarg.h>
126 #include "hash.h"
127 #include "macros.h"
128 #include "MathUtil.h"
129 
130 /************************************************************************/
131 /* Defines and macros
132 */
133 
134 /************************************************************************/
135 /* Globals
136 */
137 
138 /************************************************************************/
139 /* Prototypes
140 */
141 static ULONG hash(char *s, ULONG size);
142 static _HASHENTRY *lookup(HASHTABLE *hashtable, char *n);
143 static ULONG CalculateHashSize(ULONG hashsize);
144 #ifdef DEBUG
145 static void dumpHashTable(FILE *out, HASHTABLE *hashtable);
146 #endif
147 
148 /************************************************************************/
149 /*>HASHTABLE *blInitializeHash(ULONG hashsize)
150  -------------------------------------------
151 *//**
152  \param[in] hashsize An estimate of the size of the hash (or 0)
153  \return A pointer to a hashtable structure
154 
155  The size estimate is used to allocate a hash table. If too large you
156  waste memory; if too small lookups will take longer. You can use 0
157  for the default hash size of 1001
158 
159  A future version will implement dynamic hashing.
160 
161 - 12.05.15 Original By: ACRM
162 */
164 {
165  HASHTABLE *hashtable = NULL;
166 
167  /* Allocate the main structure */
168  if((hashtable = (HASHTABLE *)malloc(sizeof(HASHTABLE)))==NULL)
169  return(NULL);
170 
171  /* Allocate the table */
172  hashtable->size = CalculateHashSize(hashsize);
173  if((hashtable->table =
174  (_HASHENTRY **)malloc(hashtable->size*sizeof(_HASHENTRY)))!=NULL)
175  {
176  int i;
177  for(i=0; i<hashtable->size; i++)
178  hashtable->table[i] = NULL;
179  }
180  else
181  {
182  free(hashtable);
183  hashtable = NULL;
184  }
185 
186  return(hashtable);
187 }
188 
189 
190 /************************************************************************/
191 /*>void blFreeHashKeyList(char **keylist)
192  --------------------------------------
193 *//**
194  \param[in] keylist List of keys returned by blGetHashKeyList()
195 
196  Frees memory allocated for a list of keys in the hash
197 
198 - 12.05.15 Original By: ACRM
199 */
200 void blFreeHashKeyList(char **keylist)
201 {
202  int i;
203 
204  if(keylist == NULL)
205  return;
206 
207  for(i=0; keylist[i] != NULL; i++)
208  free(keylist[i]);
209 
210  free(keylist);
211 }
212 
213 
214 /************************************************************************/
215 /*>char **blGetHashKeyList(HASHTABLE *hashtable)
216  ---------------------------------------------
217 *//**
218  \param[in] hashtable The hashtable
219  \return Array of strings representing hash keys
220 
221  Gets a list of the keys in the hash. Allocates memory which must be
222  freed using blFreeHashKeyList()
223 
224 - 12.05.15 Original By: ACRM
225 */
226 char **blGetHashKeyList(HASHTABLE *hashtable)
227 {
228  int i, j,
229  nKeys;
230  _HASHENTRY **hashtab;
231  char **keys = NULL;
232 
233  if(hashtable==NULL)
234  return(NULL);
235 
236  hashtab = hashtable->table;
237 
238  /* First walk the hash table to see how many keys there are */
239  nKeys = 0;
240  for(i=0; i<hashtable->size; i++)
241  {
242  if(hashtab[i]!=NULL)
243  {
244  _HASHENTRY *hashEntry;
245 
246  for(hashEntry=hashtab[i]; hashEntry!=NULL; NEXT(hashEntry))
247  nKeys++;
248  }
249  }
250 
251  /* Allocate an array of this size (+1) */
252  if((keys = (char **)malloc((nKeys+1)*sizeof(char *)))==NULL)
253  return(NULL);
254 
255  /* Set the last one to NULL to indicate the end of the list */
256  keys[nKeys] = NULL;
257 
258  /* Walk the hash table again, copying in the keys */
259  for(i=0, j=0; i<hashtable->size && j<nKeys; i++)
260  {
261  if(hashtab[i]!=NULL)
262  {
263  _HASHENTRY *hashEntry;
264 
265  for(hashEntry=hashtab[i]; hashEntry!=NULL; NEXT(hashEntry))
266  {
267  keys[j] = blStrdup(hashEntry->key);
268  /* Free key list if allocation error and return NULL */
269  if(keys[j] == NULL)
270  {
271  blFreeHashKeyList(keys);
272  return(NULL);
273  }
274  j++;
275  }
276  }
277  }
278 
279  return(keys);
280 }
281 
282 
283 /************************************************************************/
284 /*>void blFreeHash(HASHTABLE *hashtable)
285  -------------------------------------
286 *//**
287  \param[in] hashtable The hash table
288 
289  Frees all memory used by the hash
290 
291 - 12.05.15 Original By: ACRM
292 */
293 void blFreeHash(HASHTABLE *hashtable)
294 {
295  int i;
296  _HASHENTRY *nextItem,
297  **hashtab;
298 
299  if(hashtable == NULL)
300  return;
301 
302  hashtab = hashtable->table;
303 
304  /* Walk the hash table */
305  for(i=0; i<hashtable->size; i++)
306  {
307  /* If this slot has been used */
308  if(hashtab[i]!=NULL)
309  {
310  _HASHENTRY *hashEntry;
311 
312  hashEntry=hashtab[i];
313 
314  /* Walk the linked list freeing entries */
315  while(hashEntry!=NULL)
316  {
317  nextItem=hashEntry->next;
318  if(hashEntry->key != NULL) free(hashEntry->key);
319  if(hashEntry->string != NULL) free(hashEntry->string);
320  free(hashEntry);
321  hashEntry=nextItem;
322  }
323  }
324  }
325  /* Finally free the table and the main hash structure */
326  free(hashtab);
327  free(hashtable);
328 }
329 
330 
331 /************************************************************************/
332 /*>BOOL blSetHashValue(HASHTABLE *hashtable, char *key, int type, ...)
333  -------------------------------------------------------------------
334 *//**
335  \param[in] hashtable The hash table
336  \param[in] key The hash key
337  \param[in] type The value type
338  \param[in] ... The value
339  \return Success
340 
341  Sets a value in the hash. 'type' is one of
342 - HASHTYPE_INT
343 - HASHTYPE_STRING
344 - HASHTYPE_DOUBLE
345 - HASHTYPE_CHAR
346 - HASHTYPE_POINTER
347 
348 - 12.05.15 Original By: ACRM
349 */
350 BOOL blSetHashValue(HASHTABLE *hashtable, char *key, int type, ...)
351 {
352  va_list ap;
353  ULONG hashIndex;
354  _HASHENTRY *hashEntry;
355  char *stringPtr;
356  int intValue,
357  charValue;
358  double doubleValue;
359  BPTR ptrValue;
360 
361  if(hashtable == NULL)
362  return(FALSE);
363 
364  /* If this key is not already in the hash */
365  if((hashEntry=lookup(hashtable, key))==NULL)
366  {
367  _HASHENTRY **hashtab = hashtable->table;
368 
369  /* Calculate a hash index for this key */
370  hashIndex = hash(key, hashtable->size);
371 
372  /* And allocate a structure to store the key and value */
373  if((hashEntry = (_HASHENTRY *)malloc(sizeof(_HASHENTRY)))==NULL)
374  return(FALSE);
375 
376  /* Copy in the key */
377  if((hashEntry->key = blStrdup(key))==NULL)
378  return(FALSE);
379 
380  /* Insert this entry at the start of the linked list for this
381  hashtable index
382  */
383  hashEntry->next=hashtab[hashIndex];
384  hashtab[hashIndex]=hashEntry;
385  }
386  else
387  {
388  /* The key is already in the hash. If it was a string, delete
389  its value
390  */
391  if((hashEntry->type == HASHTYPE_STRING) &&
392  (hashEntry->string != NULL))
393  free(hashEntry->string);
394  }
395 
396  /* Initialize values in the hash entry */
397  hashEntry->string = NULL;
398  hashEntry->intValue = 0;
399  hashEntry->doubleValue = 0.0;
400  hashEntry->charValue = '\0';
401  hashEntry->ptrValue = NULL;
402 
403 
404  /* Copy in the new value */
405  va_start(ap, type);
406  switch(type)
407  {
408  case HASHTYPE_STRING:
409  stringPtr = va_arg(ap, char *);
410  if((hashEntry->string=blStrdup(stringPtr))==NULL)
411  return(FALSE);
412  break;
413  case HASHTYPE_INT:
414  intValue = va_arg(ap, int);
415  hashEntry->intValue = intValue;
416  break;
417  case HASHTYPE_CHAR:
418  charValue = va_arg(ap, int);
419  hashEntry->charValue = (char)charValue;
420  break;
421  case HASHTYPE_DOUBLE:
422  doubleValue = va_arg(ap, double);
423  hashEntry->doubleValue = doubleValue;
424  break;
425  case HASHTYPE_POINTER:
426  ptrValue = va_arg(ap, BPTR);
427  hashEntry->ptrValue = ptrValue;
428  break;
429  }
430  va_end(ap);
431 
432  hashEntry->type = type;
433 
434  return(TRUE);
435 }
436 
437 
438 /************************************************************************/
439 /*>BOOL blSetHashValueString(HASHTABLE *hashtable, char *key, char *value)
440  -----------------------------------------------------------------------
441 *//**
442  \param[in] *hashtable The hash table
443  \param[in] *key The key for the hash entry
444  \param[in] *value The value for the hash entry
445  \return Success
446 
447  Set a string value in a hash
448  Wrapper to blSetHashValue()
449 
450 - 03.06.15 Original By: ACRM
451 */
452 BOOL blSetHashValueString(HASHTABLE *hashtable, char *key, char *value)
453 {
454  return(blSetHashValue(hashtable, key, HASHTYPE_STRING, value));
455 }
456 
457 
458 /************************************************************************/
459 /*>BOOL blSetHashValueInt(HASHTABLE *hashtable, char *key, int value)
460  ------------------------------------------------------------------
461 *//**
462  \param[in] *hashtable The hash table
463  \param[in] *key The key for the hash entry
464  \param[in] *value The value for the hash entry
465  \return Success
466 
467  Set an int value in a hash
468  Wrapper to blSetHashValue()
469 
470 - 03.06.15 Original By: ACRM
471 */
472 BOOL blSetHashValueInt(HASHTABLE *hashtable, char *key, int value)
473 {
474  return(blSetHashValue(hashtable, key, HASHTYPE_INT, value));
475 }
476 
477 
478 /************************************************************************/
479 /*>BOOL blSetHashValueDouble(HASHTABLE *hashtable, char *key,
480  double value)
481  ----------------------------------------------------------
482 *//**
483  \param[in] *hashtable The hash table
484  \param[in] *key The key for the hash entry
485  \param[in] *value The value for the hash entry
486  \return Success
487 
488  Set a double value in a hash
489  Wrapper to blSetHashValue()
490 
491 - 03.06.15 Original By: ACRM
492 */
493 BOOL blSetHashValueDouble(HASHTABLE *hashtable, char *key, double value)
494 {
495  return(blSetHashValue(hashtable, key, HASHTYPE_DOUBLE, value));
496 }
497 
498 
499 /************************************************************************/
500 /*>BOOL blSetHashValuePointer(HASHTABLE *hashtable, char *key, BPTR ptr)
501  ---------------------------------------------------------------------
502 *//**
503  \param[in] *hashtable The hash table
504  \param[in] *key The key for the hash entry
505  \param[in] *value The value for the hash entry
506  \return Success
507 
508  Set a general pointer (BPTR) value in a hash
509  Wrapper to blSetHashValue()
510 
511 - 03.06.15 Original By: ACRM
512 */
513 BOOL blSetHashValuePointer(HASHTABLE *hashtable, char *key, BPTR ptr)
514 {
515  return(blSetHashValue(hashtable, key, HASHTYPE_POINTER, ptr));
516 }
517 
518 
519 /************************************************************************/
520 /*>BOOL blSetHashValueChar(HASHTABLE *hashtable, char *key, char value)
521  --------------------------------------------------------------------
522 *//**
523  \param[in] *hashtable The hash table
524  \param[in] *key The key for the hash entry
525  \param[in] *value The value for the hash entry
526  \return Success
527 
528  Wrapper to blSetHashValue()
529 
530 - 03.06.15 Original By: ACRM
531 */
532 BOOL blSetHashValueChar(HASHTABLE *hashtable, char *key, char value)
533 {
534  return(blSetHashValue(hashtable, key, HASHTYPE_CHAR, value));
535 }
536 
537 
538 /************************************************************************/
539 /*>int blGetHashValueInt(HASHTABLE *hashtable, char *key)
540  ------------------------------------------------------
541 *//**
542  \param[in] hashtable The hash table
543  \param[in] key The hash key
544  \return The value
545 
546  Simple wrapper to blGetHashValue() for extracting integers
547 
548 - 12.05.15 Original By: ACRM
549 - 23.08.15 Added cast of NAN
550 */
551 int blGetHashValueInt(HASHTABLE *hashtable, char *key)
552 {
553  BPTR value;
554  if((value = blGetHashValue(hashtable, key, NULL))!=NULL)
555  return(*(int *)value);
556 #ifdef NAN
557  return((int)NAN);
558 #endif
559  return(0);
560 }
561 
562 
563 /************************************************************************/
564 /*>double blGetHashValueDouble(HASHTABLE *hashtable, char *key)
565  ------------------------------------------------------------
566 *//**
567  \param[in] hashtable The hash table
568  \param[in] key The hash key
569  \return The value
570 
571  Simple wrapper to blGetHashValue() for extracting doubles
572 
573 - 12.05.15 Original By: ACRM
574 */
575 double blGetHashValueDouble(HASHTABLE *hashtable, char *key)
576 {
577  BPTR value;
578  if((value = blGetHashValue(hashtable, key, NULL))!=NULL)
579  return(*(double *)value);
580 #ifdef NAN
581  return(NAN);
582 #endif
583  return(0.0);
584 }
585 
586 
587 /************************************************************************/
588 /*>char blGetHashValueChar(HASHTABLE *hashtable, char *key)
589  --------------------------------------------------------
590 *//**
591  \param[in] hashtable The hash table
592  \param[in] key The hash key
593  \return The value
594 
595  Simple wrapper to blGetHashValue() for extracting characters
596 
597 - 12.05.15 Original By: ACRM
598 */
599 char blGetHashValueChar(HASHTABLE *hashtable, char *key)
600 {
601  BPTR value;
602  if((value = blGetHashValue(hashtable, key, NULL))!=NULL)
603  return(*(char *)value);
604  return('\0');
605 }
606 
607 
608 /************************************************************************/
609 /*>char *blGetHashValueString(HASHTABLE *hashtable, char *key)
610  -----------------------------------------------------------
611 *//**
612  \param[in] hashtable The hash table
613  \param[in] key The hash key
614  \return The value
615 
616  Simple wrapper to blGetHashValue() for extracting strings
617 
618 - 12.05.15 Original By: ACRM
619 */
620 char *blGetHashValueString(HASHTABLE *hashtable, char *key)
621 {
622  return((char *)blGetHashValue(hashtable, key, NULL));
623 }
624 
625 
626 /************************************************************************/
627 /*>BPTR blGetHashValuePointer(HASHTABLE *hashtable, char *key)
628  -----------------------------------------------------------
629 *//**
630  \param[in] hashtable The hash table
631  \param[in] key The hash key
632  \return The value
633 
634  Simple wrapper to blGetHashValue() for extracting pointers
635 
636 - 12.05.15 Original By: ACRM
637 */
638 BPTR blGetHashValuePointer(HASHTABLE *hashtable, char *key)
639 {
640  return((BPTR)blGetHashValue(hashtable, key, NULL));
641 }
642 
643 
644 /************************************************************************/
645 /*>BPTR blGetHashValue(HASHTABLE *hashtable, char *key, int *type)
646  ---------------------------------------------------------------
647 *//**
648  \param[in] hashtable The hash table
649  \param[in] key The hash key
650  \param[out] type The type for that item (or NULL)
651  \return Pointer to the value
652 
653  Obtain an entry from the hash. Type 'type' parameter can be NULL
654  if you are sure you know what the type is and don't want to check.
655  The value is returned as a pointer. If the value is itself a pointer
656  or a string then this is what you want, but you will need to cast
657  it appropriately. If it is an int, double or char then you need to
658  cast and dereference this:
659 
660  string: (char *)value
661  pointer: (my-type *)value
662  int: *(int *)value
663  double: *(double *)value
664  char: *(char *)value
665 
666 - 12.05.15 Original By: ACRM
667 */
668 BPTR blGetHashValue(HASHTABLE *hashtable, char *key, int *type)
669 {
670  _HASHENTRY *hashEntry;
671 
672  if(hashtable == NULL)
673  return(FALSE);
674 
675  if((hashEntry = lookup(hashtable, key))==NULL)
676  {
677  return(NULL);
678  }
679  else
680  {
681  if(type != NULL)
682  *type = hashEntry->type;
683 
684  switch(hashEntry->type)
685  {
686  case HASHTYPE_INT:
687  return((BPTR)(&(hashEntry->intValue)));
688  break;
689  case HASHTYPE_DOUBLE:
690  return((BPTR)(&(hashEntry->doubleValue)));
691  break;
692  case HASHTYPE_CHAR:
693  return((BPTR)(&(hashEntry->charValue)));
694  break;
695  case HASHTYPE_STRING:
696  return((BPTR)(hashEntry->string));
697  break;
698  case HASHTYPE_POINTER:
699  return((BPTR)(hashEntry->ptrValue));
700  break;
701  }
702  }
703 
704  return(NULL);
705 }
706 
707 
708 /************************************************************************/
709 /*>BOOL blDumpHash(FILE *out, HASHTABLE *hashtable)
710  ------------------------------------------------
711 *//**
712  \param[in] out File pointer
713  \param[in] hashtable The hash table
714  \return Success
715 
716  Dumps the contents of the hash to the specified file pointer
717 
718 - 12.05.15 Original By: ACRM
719 */
720 BOOL blDumpHash(FILE *out, HASHTABLE *hashtable)
721 {
722  char **keyList = NULL;
723 
724  if((keyList = blGetHashKeyList(hashtable))!=NULL)
725  {
726  int i;
727  for(i=0; keyList[i]!=NULL; i++)
728  {
729  BPTR value;
730  int type;
731 
732  fprintf(out, "%s => ", keyList[i]);
733  value = blGetHashValue(hashtable, keyList[i], &type);
734  switch(type)
735  {
736  case HASHTYPE_INT:
737  fprintf(out, "%d\n", *(int *)value);
738  break;
739  case HASHTYPE_CHAR:
740  fprintf(out, "%c\n", *(char *)value);
741  break;
742  case HASHTYPE_DOUBLE:
743  fprintf(out, "%f\n", *(double *)value);
744  break;
745  case HASHTYPE_STRING:
746  fprintf(out, "%s\n", (char *)value);
747  break;
748  case HASHTYPE_POINTER:
749  default:
750  fprintf(out, "%lu\n", (unsigned long)value);
751  break;
752  }
753  }
754  blFreeHashKeyList(keyList);
755  keyList = NULL;
756  return(TRUE);
757  }
758 
759  return(FALSE);
760 }
761 
762 
763 /************************************************************************/
764 /*>BOOL blHashKeyDefined(HASHTABLE *hashtable, char *key)
765  ------------------------------------------------------
766 *//**
767  \param[in] hashtable The hash table
768  \param[in] key Key for which we are searching
769  \return Key found
770 
771  Checks whether a hash key has been defined
772 
773 - 14.05.15 Original By: ACRM
774 */
775 BOOL blHashKeyDefined(HASHTABLE *hashtable, char *key)
776 {
777 
778  /* If this key is not already in the hash */
779  if(lookup(hashtable, key)==NULL)
780  {
781  return(FALSE);
782  }
783  return(TRUE);
784 }
785 
786 
787 /************************************************************************/
788 /*>void blDeleteHashKey(HASHTABLE *hashtable, char *key)
789  -----------------------------------------------------
790 *//**
791  \param[in] hashtable The hash table
792  \param[in] key The hash key
793 
794  Deletes a hash key
795 
796 - 14.05.15 Original By: ACRM
797 */
798 void blDeleteHashKey(HASHTABLE *hashtable, char *key)
799 {
800  ULONG hashIndex;
801  _HASHENTRY *hashEntry,
802  *prev,
803  *h,
804  **hashtab;
805 
806  if(hashtable == NULL)
807  return;
808 
809  hashtab = hashtable->table;
810 
811  /* If this key is in the hash then we need to delete it. */
812  if((hashEntry=lookup(hashtable, key))!=NULL)
813  {
814  /* If it's a string, free the memory for it */
815  if((hashEntry->type == HASHTYPE_STRING) &&
816  (hashEntry->string != NULL))
817  free(hashEntry->string);
818 
819  hashIndex = hash(key, hashtable->size);
820  prev=NULL;
821  for(h=hashtab[hashIndex]; h!=NULL; NEXT(h))
822  {
823  if(h==hashEntry)
824  {
825  if(prev==NULL)
826  {
827  hashtab[hashIndex] = h->next;
828  }
829  else
830  {
831  prev->next = h->next;
832  }
833  break;
834  }
835  prev=h;
836  }
837 
838  free(hashEntry->key);
839  free(hashEntry);
840  }
841 }
842 
843 
844 /************************************************************************/
845 /** **/
846 /** Static functions below here **/
847 /** **/
848 /************************************************************************/
849 
850 #ifdef DEBUG
851 /************************************************************************/
852 /*>static void dumpHashTable(FILE *out, HASHTABLE *hashtable)
853  ----------------------------------------------------------
854 *//**
855  \param[in] out A file pointer
856  \param[in] hashtable The hash table
857  \return
858 
859  A simple debugging function to display the hash table as
860  (key => value) pairs. Prints the table itself with all entries in
861  each slot
862 
863 - 12.05.15 Original By: ACRM
864 */
865 static void dumpHashTable(FILE *out, HASHTABLE *hashtable)
866 {
867  int i;
868  _HASHENTRY **hashtab;
869 
870  if(hashtable == NULL)
871  return;
872 
873  hashtab = hashtable->table;
874 
875  for(i=0; i<hashtable->size; i++)
876  {
877  if(hashtab[i]==NULL)
878  {
879  fprintf(out, "()\n");
880  }
881  else
882  {
883  _HASHENTRY *hashEntry;
884 
885  fprintf(out, "(");
886  for(hashEntry=hashtab[i]; hashEntry!=NULL; NEXT(hashEntry))
887  {
888  switch(hashEntry->type)
889  {
890  case HASHTYPE_INT:
891  fprintf(out, "(%s => %d) ",
892  hashEntry->key, hashEntry->intValue);
893  break;
894  case HASHTYPE_STRING:
895  fprintf(out, "(%s => %s) ",
896  hashEntry->key, hashEntry->string);
897  break;
898  case HASHTYPE_DOUBLE:
899  fprintf(out, "(%s => %f) ",
900  hashEntry->key, hashEntry->doubleValue);
901  break;
902  case HASHTYPE_CHAR:
903  fprintf(out, "(%s => %c) ",
904  hashEntry->key, hashEntry->charValue);
905  break;
906  case HASHTYPE_POINTER:
907  fprintf(out, "(%s => %lu) ",
908  hashEntry->key, (unsigned long)hashEntry->ptrValue);
909  break;
910  default:
911  break;
912  }
913  }
914 
915  fprintf(out, ")\n");
916  }
917  }
918 }
919 #endif
920 
921 
922 /************************************************************************/
923 /*>static ULONG hash(char *string, ULONG size)
924  -------------------------------------------
925 *//**
926  \param[in] string The string to be hashed
927  \param[in] size The size of the hash table
928  \return Index into the hash table
929 
930  Simple hashing function for strings
931 
932 - 12.05.15 Original By: ACRM
933 */
934 static ULONG hash(char *string, ULONG size)
935 {
936  ULONG h;
937 
938  for(h=0; *string; string++)
939  h=(*string)+(h*31);
940 
941  return(h % size);
942 }
943 
944 
945 /************************************************************************/
946 /*>static _HASHENTRY *lookup(HASHTABLE *hashtable, char *key)
947  --------------------------------------------------------
948 *//**
949  \param[in] hashtable The hash table
950  \param[in] key A key in the table
951  \return A pointer to an entry in the hash
952 
953  Basic lookup function to access a _HASHENTRY structure in the hash.
954  First looks up what slot we are in using the hash() function then
955  searches that slot for the specified key.
956 
957 - 12.05.15 Original By: ACRM
958 */
959 static _HASHENTRY *lookup(HASHTABLE *hashtable, char *key)
960 {
961  ULONG hashIndex;
962  _HASHENTRY *hashEntry,
963  **hashtab;
964 
965  if(hashtable == NULL)
966  return(NULL);
967 
968  hashtab = hashtable->table;
969  hashIndex = hash(key, hashtable->size);
970 
971  for(hashEntry=hashtab[hashIndex]; hashEntry!=NULL; NEXT(hashEntry))
972  {
973  if(!strcmp(hashEntry->key,key))
974  return(hashEntry);
975  }
976 
977  return(NULL);
978 }
979 
980 
981 /************************************************************************/
982 /*>static ULONG CalculateHashSize(ULONG hashsize)
983  ----------------------------------------------
984 *//**
985  \param[in] hashsize Basic size of hash
986  \return Better size
987 
988  Calculates a good size for the hash - this is a prime number
989  greater than the specified size.
990 
991  Currently our prime numbers only go up to 60013, so in cases
992  larger than this we just return an odd number >= the specified
993  size.
994 
995 - 12.05.15 Original By: ACRM
996 - 15.05.15 Now returns the next largest prime
997 */
998 static ULONG CalculateHashSize(ULONG hashsize)
999 {
1000  ULONG newSize;
1001 
1002  if(hashsize == 0)
1003  return(DEF_HASHSIZE);
1004 
1005  if((newSize = blFindNextPrime(hashsize, FALSE)) == 0)
1006  return(1+(2*((int)(hashsize/2)))); /* Odd number >= hashsize */
1007 
1008  return(newSize);
1009 }
1010 
1011 #ifdef TEST
1012 /************************************************************************/
1013 /*>int main(int argc, char **argv)
1014  -------------------------------
1015 *//**
1016  Test code
1017 
1018 - 12.05.15 Original By: ACRM
1019 */
1020 int main(int argc, char **argv)
1021 {
1022  int i;
1023  char *keys[]={"name","address","phone","room101",NULL};
1024  char *values[]={"Andrew","London","02071234567","Contents",NULL};
1025  HASHTABLE *hashtable = NULL;
1026 
1027  if((hashtable = blInitializeHash(0))==NULL)
1028  {
1029  fprintf(stderr,"No memory for hash table\n");
1030  return(1);
1031  }
1032 
1033  for(i=0; keys[i]!=NULL; i++)
1034  blSetHashValue(hashtable, keys[i], HASHTYPE_STRING, values[i]);
1035 
1036  printf("\n\nInitial hash...\n");
1037  blDumpHash(stdout, hashtable);
1038 
1039  blSetHashValue(hashtable, "phone", HASHTYPE_STRING, "020898765432");
1040  blSetHashValue(hashtable, "an int", HASHTYPE_INT, 10);
1041  blSetHashValue(hashtable, "double", HASHTYPE_DOUBLE, 123.456);
1042  blSetHashValue(hashtable, "pointer", HASHTYPE_POINTER, &i);
1043  blSetHashValue(hashtable, "char", HASHTYPE_CHAR, 'a');
1044  /* Change this one again */
1045  blSetHashValue(hashtable, "an int", HASHTYPE_INT, 99);
1046 
1047  blSetHashValueString(hashtable, "phone2", "020898765432");
1048  blSetHashValueInt(hashtable, "int2", 10);
1049  blSetHashValueDouble(hashtable, "double2", 123.456);
1050  blSetHashValuePointer(hashtable, "pointer2", (BPTR)&i);
1051  blSetHashValueChar(hashtable, "char2", 'a');
1052 
1053  printf("\n\nAfter updating...\n");
1054  blDumpHash(stdout, hashtable);
1055 
1056 #ifdef DEBUG
1057  dumpHashTable(stdout, hashtable);
1058 #endif
1059 
1060  printf("\n\nSome individual values:\n");
1061  printf("an int : %d\n",
1062  blGetHashValueInt(hashtable, "an int"));
1063  printf("double : %f\n",
1064  blGetHashValueDouble(hashtable, "double"));
1065  printf("pointer : %lu\n",
1066  (unsigned long)blGetHashValuePointer(hashtable, "pointer"));
1067  printf("char : '%c'\n",
1068  blGetHashValueChar(hashtable, "char"));
1069  printf("phone : \"%s\"\n",
1070  blGetHashValueString(hashtable, "phone"));
1071 
1072 
1073  printf("\nChecking key existence:\n");
1074  printf("Key fubar: %s exist\n",
1075  (blHashKeyDefined(hashtable, "fubar")?"DOES":"does NOT"));
1076  printf("Key phone: %s exist\n",
1077  (blHashKeyDefined(hashtable, "phone")?"DOES":"does NOT"));
1078 
1079 
1080  printf("\nDeleting entries: \"phone\" and \"double\"\n");
1081  blDeleteHashKey(hashtable, "phone");
1082  blDeleteHashKey(hashtable, "double");
1083  blDumpHash(stdout, hashtable);
1084 
1085  blFreeHash(hashtable);
1086 
1087  return(0);
1088 }
1089 #endif
1090 
1091 
#define HASHTYPE_POINTER
Definition: hash.h:69
char * BPTR
Definition: SysDefs.h:60
int main(int argc, char **argv)
Definition: test.c:4
BOOL blSetHashValuePointer(HASHTABLE *hashtable, char *key, BPTR ptr)
Definition: hash.c:513
_HASHENTRY ** table
Definition: hash.h:87
double blGetHashValueDouble(HASHTABLE *hashtable, char *key)
Definition: hash.c:575
short BOOL
Definition: SysDefs.h:64
#define NULL
Definition: array2.c:99
BOOL blSetHashValueDouble(HASHTABLE *hashtable, char *key, double value)
Definition: hash.c:493
char ** blGetHashKeyList(HASHTABLE *hashtable)
Definition: hash.c:226
#define DEF_HASHSIZE
Definition: hash.h:64
Definition: hash.h:72
void blDeleteHashKey(HASHTABLE *hashtable, char *key)
Definition: hash.c:798
Defines for using hash functions.
struct _hashTab * next
Definition: hash.h:74
BOOL blDumpHash(FILE *out, HASHTABLE *hashtable)
Definition: hash.c:720
char * blGetHashValueString(HASHTABLE *hashtable, char *key)
Definition: hash.c:620
#define FALSE
Definition: macros.h:223
#define NEXT(x)
Definition: macros.h:249
char * blStrdup(char *instr)
Definition: stringutil.c:157
BOOL blSetHashValueString(HASHTABLE *hashtable, char *key, char *value)
Definition: hash.c:452
#define HASHTYPE_INT
Definition: hash.h:66
BOOL blSetHashValueInt(HASHTABLE *hashtable, char *key, int value)
Definition: hash.c:472
Useful macros.
BPTR blGetHashValuePointer(HASHTABLE *hashtable, char *key)
Definition: hash.c:638
unsigned long ULONG
Definition: SysDefs.h:66
HASHTABLE * blInitializeHash(ULONG hashsize)
Definition: hash.c:163
Definition: hash.h:85
#define HASHTYPE_DOUBLE
Definition: hash.h:68
double doubleValue
Definition: hash.h:78
void blFreeHashKeyList(char **keylist)
Definition: hash.c:200
#define HASHTYPE_CHAR
Definition: hash.h:67
int type
Definition: hash.h:80
void blFreeHash(HASHTABLE *hashtable)
Definition: hash.c:293
char * string
Definition: hash.h:76
#define HASHTYPE_STRING
Definition: hash.h:65
BPTR ptrValue
Definition: hash.h:77
int blGetHashValueInt(HASHTABLE *hashtable, char *key)
Definition: hash.c:551
#define TRUE
Definition: macros.h:219
Prototypes, etc. for maths utility routines.
BOOL blHashKeyDefined(HASHTABLE *hashtable, char *key)
Definition: hash.c:775
int intValue
Definition: hash.h:79
BOOL blSetHashValueChar(HASHTABLE *hashtable, char *key, char value)
Definition: hash.c:532
char charValue
Definition: hash.h:81
ULONG size
Definition: hash.h:88
char blGetHashValueChar(HASHTABLE *hashtable, char *key)
Definition: hash.c:599
BPTR blGetHashValue(HASHTABLE *hashtable, char *key, int *type)
Definition: hash.c:668
char * key
Definition: hash.h:75
char * string
Definition: general.h:85
ULONG blFindNextPrime(ULONG input, BOOL above)
Definition: prime.c:97
BOOL blSetHashValue(HASHTABLE *hashtable, char *key, int type,...)
Definition: hash.c:350