The LevAWC Project
 All Data Structures Files Functions Variables Typedefs Enumerations Macros Pages
chashtbl.c
Go to the documentation of this file.
1 /*
2  * _____
3  * ANSI / ___/
4  * / /__
5  * \___/
6  *
7  * Filename: chashtbl.c
8  * Author : Kyle Loudon/Dan Levin
9  * Date : Fri Mar 22 12:40:45 GMT 2013
10  * Version : 0.51
11  * ---
12  * Description: A chained hash table - implemented as a pure, generic ADT container.
13  *
14  * Revision history - coming up below:
15  *
16  * Date Revision message
17  * 2013-01-30 Created this file initially
18  * 2013-02-19 Made some revision to the Doxygen documentation. Enhanced the description of
19  * in/out parameters - i.e. double-pointers.
20  * 2015-03-31 This code ready for version 0.51
21  *
22  */
23 
28 #include <stdio.h>
29 #include <stdlib.h>
30 
31 #include "chashtbl.h"
32 
33 
34 struct CHtbl_
35 {
36 
37  int buckets;
38  int (*h)(const void *key);
39  int (*match)(const void *key1, const void *key2);
40  void (*destroy)(void *data);
41  int size;
42  Slist *table;
43 };
44 
45 
46 
47 /* FUNCTION DEFINITIONS --------------------------------------------------- */
48 
49 CHtbl CHTBLinit(int buckets, int (*h)(const void *key), int (*match)(const void *key1, const void *key2), void (*destroy)(void *data))
50 {
51  CHtbl htbl;
52  int i;
53 
54  if ((htbl = (CHtbl)malloc(sizeof(struct CHtbl_)))==NULL)
55  return NULL;
56 
57  if ((htbl->table = (Slist *)malloc(buckets * sizeof(Slist))) == NULL)
58  return NULL;
59 
60  htbl->buckets = buckets;
61 
62  for (i = 0; i < htbl->buckets; i++)
63  {
64  if ((htbl->table[i] = SLISTinit(destroy)) == NULL)
65  return NULL;
66  SLISTsetmatch(htbl->table[i], match);
67  }
68 
69  htbl->h = h;
70  htbl->match = match;
71  htbl->destroy = destroy;
72  htbl->size = 0;
73 
74  return htbl;
75 }
76 
77 void CHTBLdestroy(CHtbl htbl)
78 {
79  int i;
80 
81  for (i = 0; i < htbl->buckets; ++i)
82  {
83  SLISTdestroy(htbl->table[i]);
84  }
85 
86  free(htbl->table);
87  free(htbl);
88 }
89 
90 int CHTBLinsert(CHtbl htbl, const void *data)
91 {
92  int bucket, retval;
93  void *tmp;
94 
95  tmp = (void *)data;
96 
97  if (CHTBLlookup(htbl, &tmp) == 0)
98  return 1;
99 
100  /* Hash the key */
101  bucket = htbl->h(data) % htbl->buckets;
102 
103  if ((retval = SLISTinsnext(htbl->table[bucket], NULL, data)) == 0)
104  htbl->size++;
105 
106  return retval;
107 }
108 
109 int CHTBLremove(CHtbl htbl, void **data)
110 {
111  int bucket, retval;
112 
113  /* Hash the key */
114  bucket = htbl->h(*data) % htbl->buckets;
115 
116  /* Remove the node */
117  if ((retval = SLISTfind_remove(htbl->table[bucket], data)) == 0) /* Node removal successful.. */
118  htbl->size--;
119 
120  return retval;
121 }
122 
123 int CHTBLlookup(const CHtbl htbl, void **data)
124 {
125  int bucket;
126  SlistNode tmpnode;
127 
128  /* Hash the key */
129  bucket = htbl->h(*data) % htbl->buckets;
130 
131  if ((tmpnode = SLISTfindnode(htbl->table[bucket], *data))) /* Data found */
132  {
133  *data = SLISTdata(tmpnode); /* Pass data back to caller */
134  return 0;
135  }
136 
137  return -1;
138 }
139 
140 void CHTBLprint(CHtbl htbl, void (*callback)(const void *data))
141 {
142  int i;
143 
144  for (i = 0; i < htbl->buckets; ++i)
145  {
146  printf("\nBucket #%03d: ", i);
147  SLISTtraverse(htbl->table[i], callback, SLIST_FWD);
148  }
149 }
150 
151 int CHTBLsize(CHtbl htbl)
152 {
153  return htbl->size;
154 }