blob: 944c202f045d3c63a3d4dcf497e34afe5160ff7d [file] [log] [blame]
Juan Cespedescac15c32003-01-31 18:58:58 +01001#include <stdio.h>
2#include <stdlib.h>
Juan Cespedes7186e2a2003-01-31 19:56:34 +01003#include <string.h>
Juan Cespedesa0ccf392003-02-01 19:02:37 +01004#include <assert.h>
Juan Cespedescac15c32003-01-31 18:58:58 +01005
6#include "debug.h"
7
8/*
9 Dictionary based on code by Morten Eriksen <mortene@sim.no>.
10*/
11
12#include "dict.h"
13
14struct dict_entry {
15 unsigned int hash;
16 void * key;
17 void * value;
18 struct dict_entry * next;
19};
20
21/* #define DICTTABLESIZE 97 */
22#define DICTTABLESIZE 997 /* Semi-randomly selected prime number. */
23/* #define DICTTABLESIZE 9973 */
24/* #define DICTTABLESIZE 99991 */
25/* #define DICTTABLESIZE 999983 */
26
27struct dict {
28 struct dict_entry * buckets[DICTTABLESIZE];
29 unsigned int (*key2hash)(void *);
30 int (*key_cmp)(void *, void *);
31};
32
33struct dict *
34dict_init(unsigned int (*key2hash)(void *), int (*key_cmp)(void *, void *)) {
35 struct dict * d;
36 int i;
37
38 d = malloc(sizeof(struct dict));
39 if (!d) {
40 perror("malloc()");
41 exit(1);
42 }
43 for (i = 0; i < DICTTABLESIZE; i++) { /* better use memset()? */
44 d->buckets[i] = NULL;
45 }
46 d->key2hash = key2hash;
47 d->key_cmp = key_cmp;
48 return d;
49}
50
51void
52dict_clear(struct dict * d) {
53 int i;
54 struct dict_entry * entry, * nextentry;
55
Juan Cespedesa0ccf392003-02-01 19:02:37 +010056 assert(d);
Juan Cespedescac15c32003-01-31 18:58:58 +010057 for (i = 0; i < DICTTABLESIZE; i++) {
58 for (entry = d->buckets[i]; entry != NULL; entry = nextentry) {
59 nextentry = entry->next;
60 free(entry);
61 }
62 d->buckets[i] = NULL;
63 }
64 free(d);
65}
66
67int
68dict_enter(struct dict * d, void * key, void * value) {
69 struct dict_entry * entry, * newentry;
70 unsigned int hash = d->key2hash(key);
71 unsigned int bucketpos = hash % DICTTABLESIZE;
72
Juan Cespedesa0ccf392003-02-01 19:02:37 +010073 assert(d);
Juan Cespedescac15c32003-01-31 18:58:58 +010074 newentry = malloc(sizeof(struct dict_entry));
75 if (!newentry) {
76 perror("malloc");
77 exit(1);
78 }
79
80 newentry->hash = hash;
81 newentry->key = key;
82 newentry->value = value;
83 newentry->next = NULL;
84
85 entry = d->buckets[bucketpos];
86 while (entry && entry->next) entry = entry->next;
87
88 if (entry) entry->next = newentry;
89 else d->buckets[bucketpos] = newentry;
90
91 debug(3, "new dict entry at %p[%d]: (%p,%p)\n", d, bucketpos, key, value);
92 return 0;
93}
94
95void *
96dict_find_entry(struct dict * d, void * key) {
97 unsigned int hash = d->key2hash(key);
98 unsigned int bucketpos = hash % DICTTABLESIZE;
99 struct dict_entry * entry;
100
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100101 assert(d);
Juan Cespedescac15c32003-01-31 18:58:58 +0100102 for (entry = d->buckets[bucketpos]; entry; entry = entry->next) {
103 if (hash != entry->hash) {
104 continue;
105 }
106 if (!d->key_cmp(key, entry->key)) {
107 break;
108 }
109 }
110 return entry ? entry->value : NULL;
111}
112
113void
114dict_apply_to_all(struct dict * d, void (*func)(void *key, void *value, void *data), void *data) {
115 int i;
116
Juan Cespedesefe85f02004-04-04 01:31:38 +0200117 if (!d) {
118 return;
119 }
Juan Cespedescac15c32003-01-31 18:58:58 +0100120 for (i = 0; i < DICTTABLESIZE; i++) {
121 struct dict_entry * entry = d->buckets[i];
122 while (entry) {
123 func(entry->key, entry->value, data);
124 entry = entry->next;
125 }
126 }
127}
128
129/*****************************************************************************/
130
131unsigned int
132dict_key2hash_string(void * key) {
133 const char * s = (const char *)key;
134 unsigned int total = 0, shift = 0;
135
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100136 assert(key);
Juan Cespedescac15c32003-01-31 18:58:58 +0100137 while (*s) {
138 total = total ^ ((*s) << shift);
139 shift += 5;
140 if (shift > 24) shift -= 24;
141 s++;
142 }
143 return total;
144}
145
146int
147dict_key_cmp_string(void * key1, void * key2) {
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100148 assert(key1);
149 assert(key2);
Juan Cespedescac15c32003-01-31 18:58:58 +0100150 return strcmp((const char *)key1, (const char *)key2);
151}
152
153unsigned int
154dict_key2hash_int(void * key) {
Juan Cespedesd914a202004-11-10 00:15:33 +0100155 return (unsigned long)key;
Juan Cespedescac15c32003-01-31 18:58:58 +0100156}
157
158int
159dict_key_cmp_int(void * key1, void * key2) {
160 return key1 - key2;
161}
162