blob: a1ec8c1a6612cbec6d8b6575fe7fdcf30b31a794 [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;
Ian Wienand3219f322006-02-16 06:00:00 +010016 void *key;
17 void *value;
18 struct dict_entry *next;
Juan Cespedescac15c32003-01-31 18:58:58 +010019};
20
21/* #define DICTTABLESIZE 97 */
Ian Wienand3219f322006-02-16 06:00:00 +010022#define DICTTABLESIZE 997 /* Semi-randomly selected prime number. */
Juan Cespedescac15c32003-01-31 18:58:58 +010023/* #define DICTTABLESIZE 9973 */
24/* #define DICTTABLESIZE 99991 */
25/* #define DICTTABLESIZE 999983 */
26
27struct dict {
Ian Wienand3219f322006-02-16 06:00:00 +010028 struct dict_entry *buckets[DICTTABLESIZE];
29 unsigned int (*key2hash) (void *);
30 int (*key_cmp) (void *, void *);
Juan Cespedescac15c32003-01-31 18:58:58 +010031};
32
Ian Wienand3219f322006-02-16 06:00:00 +010033struct dict *dict_init(unsigned int (*key2hash) (void *),
34 int (*key_cmp) (void *, void *))
35{
36 struct dict *d;
Juan Cespedescac15c32003-01-31 18:58:58 +010037 int i;
38
39 d = malloc(sizeof(struct dict));
40 if (!d) {
41 perror("malloc()");
42 exit(1);
43 }
Ian Wienand3219f322006-02-16 06:00:00 +010044 for (i = 0; i < DICTTABLESIZE; i++) { /* better use memset()? */
Juan Cespedescac15c32003-01-31 18:58:58 +010045 d->buckets[i] = NULL;
46 }
47 d->key2hash = key2hash;
48 d->key_cmp = key_cmp;
49 return d;
50}
51
Ian Wienand3219f322006-02-16 06:00:00 +010052void dict_clear(struct dict *d)
53{
Juan Cespedescac15c32003-01-31 18:58:58 +010054 int i;
Ian Wienand3219f322006-02-16 06:00:00 +010055 struct dict_entry *entry, *nextentry;
Juan Cespedescac15c32003-01-31 18:58:58 +010056
Juan Cespedesa0ccf392003-02-01 19:02:37 +010057 assert(d);
Juan Cespedescac15c32003-01-31 18:58:58 +010058 for (i = 0; i < DICTTABLESIZE; i++) {
59 for (entry = d->buckets[i]; entry != NULL; entry = nextentry) {
60 nextentry = entry->next;
61 free(entry);
62 }
63 d->buckets[i] = NULL;
64 }
65 free(d);
66}
67
Ian Wienand3219f322006-02-16 06:00:00 +010068int dict_enter(struct dict *d, void *key, void *value)
69{
70 struct dict_entry *entry, *newentry;
Juan Cespedescac15c32003-01-31 18:58:58 +010071 unsigned int hash = d->key2hash(key);
72 unsigned int bucketpos = hash % DICTTABLESIZE;
73
Juan Cespedesa0ccf392003-02-01 19:02:37 +010074 assert(d);
Juan Cespedescac15c32003-01-31 18:58:58 +010075 newentry = malloc(sizeof(struct dict_entry));
76 if (!newentry) {
77 perror("malloc");
78 exit(1);
79 }
80
Ian Wienand3219f322006-02-16 06:00:00 +010081 newentry->hash = hash;
82 newentry->key = key;
Juan Cespedescac15c32003-01-31 18:58:58 +010083 newentry->value = value;
Ian Wienand3219f322006-02-16 06:00:00 +010084 newentry->next = NULL;
Juan Cespedescac15c32003-01-31 18:58:58 +010085
86 entry = d->buckets[bucketpos];
Ian Wienand3219f322006-02-16 06:00:00 +010087 while (entry && entry->next)
88 entry = entry->next;
Juan Cespedescac15c32003-01-31 18:58:58 +010089
Ian Wienand3219f322006-02-16 06:00:00 +010090 if (entry)
91 entry->next = newentry;
92 else
93 d->buckets[bucketpos] = newentry;
Juan Cespedescac15c32003-01-31 18:58:58 +010094
Ian Wienand3219f322006-02-16 06:00:00 +010095 debug(3, "new dict entry at %p[%d]: (%p,%p)\n", d, bucketpos, key,
96 value);
Juan Cespedescac15c32003-01-31 18:58:58 +010097 return 0;
98}
99
Ian Wienand3219f322006-02-16 06:00:00 +0100100void *dict_find_entry(struct dict *d, void *key)
101{
Juan Cespedescac15c32003-01-31 18:58:58 +0100102 unsigned int hash = d->key2hash(key);
103 unsigned int bucketpos = hash % DICTTABLESIZE;
Ian Wienand3219f322006-02-16 06:00:00 +0100104 struct dict_entry *entry;
Juan Cespedescac15c32003-01-31 18:58:58 +0100105
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100106 assert(d);
Juan Cespedescac15c32003-01-31 18:58:58 +0100107 for (entry = d->buckets[bucketpos]; entry; entry = entry->next) {
108 if (hash != entry->hash) {
109 continue;
110 }
111 if (!d->key_cmp(key, entry->key)) {
112 break;
113 }
114 }
115 return entry ? entry->value : NULL;
116}
117
118void
Ian Wienand3219f322006-02-16 06:00:00 +0100119dict_apply_to_all(struct dict *d,
120 void (*func) (void *key, void *value, void *data), void *data)
121{
Juan Cespedescac15c32003-01-31 18:58:58 +0100122 int i;
123
Juan Cespedesefe85f02004-04-04 01:31:38 +0200124 if (!d) {
125 return;
126 }
Juan Cespedescac15c32003-01-31 18:58:58 +0100127 for (i = 0; i < DICTTABLESIZE; i++) {
Ian Wienand3219f322006-02-16 06:00:00 +0100128 struct dict_entry *entry = d->buckets[i];
Juan Cespedescac15c32003-01-31 18:58:58 +0100129 while (entry) {
130 func(entry->key, entry->value, data);
131 entry = entry->next;
132 }
133 }
134}
135
136/*****************************************************************************/
137
Ian Wienand3219f322006-02-16 06:00:00 +0100138unsigned int dict_key2hash_string(void *key)
139{
140 const char *s = (const char *)key;
Juan Cespedescac15c32003-01-31 18:58:58 +0100141 unsigned int total = 0, shift = 0;
142
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100143 assert(key);
Juan Cespedescac15c32003-01-31 18:58:58 +0100144 while (*s) {
145 total = total ^ ((*s) << shift);
146 shift += 5;
Ian Wienand3219f322006-02-16 06:00:00 +0100147 if (shift > 24)
148 shift -= 24;
Juan Cespedescac15c32003-01-31 18:58:58 +0100149 s++;
150 }
151 return total;
152}
153
Ian Wienand3219f322006-02-16 06:00:00 +0100154int dict_key_cmp_string(void *key1, void *key2)
155{
Juan Cespedesa0ccf392003-02-01 19:02:37 +0100156 assert(key1);
157 assert(key2);
Juan Cespedescac15c32003-01-31 18:58:58 +0100158 return strcmp((const char *)key1, (const char *)key2);
159}
160
Ian Wienand3219f322006-02-16 06:00:00 +0100161unsigned int dict_key2hash_int(void *key)
162{
Juan Cespedesd914a202004-11-10 00:15:33 +0100163 return (unsigned long)key;
Juan Cespedescac15c32003-01-31 18:58:58 +0100164}
165
Ian Wienand3219f322006-02-16 06:00:00 +0100166int dict_key_cmp_int(void *key1, void *key2)
167{
Juan Cespedescac15c32003-01-31 18:58:58 +0100168 return key1 - key2;
169}