aboutsummaryrefslogtreecommitdiff
path: root/hashtab.c
diff options
context:
space:
mode:
authorThomas Schmucker <ts@its1.de>2020-07-22 17:30:45 +0200
committerThomas Schmucker <ts@its1.de>2020-07-22 17:30:45 +0200
commitac55496d881e0a17b3eff85f1faae5aafbc53b50 (patch)
tree65b954e994d7bbfc76bc959876e28f7ea9fa708c /hashtab.c
downloaddata-structures-ac55496d881e0a17b3eff85f1faae5aafbc53b50.tar.gz
data-structures-ac55496d881e0a17b3eff85f1faae5aafbc53b50.tar.bz2
data-structures-ac55496d881e0a17b3eff85f1faae5aafbc53b50.zip
erster Commit
Diffstat (limited to 'hashtab.c')
-rw-r--r--hashtab.c198
1 files changed, 198 insertions, 0 deletions
diff --git a/hashtab.c b/hashtab.c
new file mode 100644
index 0000000..6b35c89
--- /dev/null
+++ b/hashtab.c
@@ -0,0 +1,198 @@
1#include <stdio.h>
2#include <stdlib.h>
3#include <string.h>
4#include <stdbool.h>
5#include <ctype.h>
6
7#include "util.h"
8
9typedef int T;
10
11struct hash_item {
12 struct hash_item *next;
13 char *key;
14 T data;
15};
16
17struct hash_tab {
18 struct hash_item *table[251]; // fit for your needs...
19};
20
21static unsigned long
22hash_key(const unsigned char *str)
23{
24 unsigned long hash = 5381;
25 int c;
26
27 while ( (c = *str++) != '\0' )
28 hash = ((hash << 5) + hash) + c; /* hash * 33 + c */
29
30 return hash;
31}
32
33void
34hash_init(struct hash_tab *ht)
35{
36 for ( int i = 0; i != NELEM(ht->table); ++i )
37 ht->table[i] = NULL;
38}
39
40static struct hash_item *
41hash_add(struct hash_item *next, const char *key, T data)
42{
43 struct hash_item *new_item;
44 char *new_key;
45
46 new_key = strdup(key); // strdup: not standard but commonly used...
47 new_item = malloc(sizeof(*new_item));
48
49 if ( new_key == NULL || new_item == NULL ) {
50 free(new_key);
51 free(new_item);
52 ERROR("out of memory");
53 return NULL;
54 }
55
56 new_item->next = next;
57 new_item->key = new_key;
58 new_item->data = data;
59
60 return new_item;
61}
62
63T *
64hash_lookup(struct hash_tab *ht, const char *key, T data, int create)
65{
66 unsigned long h;
67 struct hash_item *item;
68
69 h = hash_key((const unsigned char *) key) % NELEM(ht->table);
70 for ( item = ht->table[h]; item; item = item->next )
71 if ( strcmp(key, item->key) == 0 )
72 return &item->data;
73
74 // not found! create?
75 if ( create ) {
76 item = hash_add(ht->table[h], key, data);
77 if ( item != NULL )
78 ht->table[h] = item;
79 else
80 ERROR("can't create item");
81 }
82
83 return item ? &item->data : NULL;
84}
85
86bool
87hash_delete(struct hash_tab *ht, const char *key)
88{
89 unsigned long h;
90 struct hash_item *prev, *p;
91
92 h = hash_key((const unsigned char *) key) % NELEM(ht->table);
93 prev = NULL;
94 for ( p = ht->table[h]; p; p = p->next ) {
95 if ( strcmp(key, p->key) == 0 ) {
96 if ( prev == NULL )
97 ht->table[h] = p->next;
98 else
99 prev->next = p->next;
100
101 free(p->key);
102 free(p);
103
104 return true; // successfully removed!
105 }
106 prev = p;
107 }
108
109 return false;
110}
111
112void
113hash_apply(struct hash_tab *ht, void (*visit)(const char *key, T data, void *cl), void *cl)
114{
115 struct hash_item *item;
116
117 for ( int i = 0; i != NELEM(ht->table); ++i )
118 for ( item = ht->table[i]; item; item = item->next )
119 visit(item->key, item->data, cl);
120}
121
122void
123hash_free(struct hash_tab *ht)
124{
125 struct hash_item *p, *next;
126
127 for ( int i = 0; i != NELEM(ht->table); ++i ) {
128 for ( p = ht->table[i]; p; p = next ) {
129 next = p->next;
130 free(p->key);
131 free(p);
132 }
133 ht->table[i] = NULL;
134 }
135}
136
137int getword(FILE *fp, char *buf, int size, int first(int c), int rest(int c))
138{
139 int i = 0, c;
140
141 c = getc(fp);
142 for ( ; c != EOF; c = getc(fp) )
143 if ( first(c) ) {
144 if ( i < size-1 )
145 buf[i++] = c;
146 c = getc(fp);
147 break;
148 }
149
150 for ( ; c != EOF && rest(c); c = getc(fp) )
151 if ( i < size-1)
152 buf[i++] = c;
153
154 if ( i < size )
155 buf[i] = 0;
156 else
157 buf[size-1] = 0;
158
159 if ( c != EOF )
160 ungetc(c, fp);
161
162 return c > 0;
163}
164
165int first(int c) {
166 return isalpha(c);
167}
168
169int rest(int c) {
170 return isalpha(c) || c == '_';
171}
172
173void print(const char *key, T data, void *cl)
174{
175 fprintf(cl, "%s: %d\n", key, data);
176}
177
178int
179main()
180{
181 struct hash_tab ht[1];
182 char word[100];
183
184 hash_init(ht);
185
186 while ( getword(stdin, word, sizeof word, first, rest) ) {
187 int *p = hash_lookup(ht, word, 0, 1);
188 if ( p != NULL )
189 ++(*p);
190 }
191
192 hash_delete(ht, "new_item");
193
194 hash_apply(ht, print, stdout);
195
196 hash_free(ht);
197}
198