1#include <stdlib.h>
2#include <string.h>
3
4#include "env.h"
5#include "util.h"
6
7env*
8newenv(int size)
9{
10 env *tbl;
11
12 tbl = emalloc(sizeof(env));
13 tbl->size = size;
14 tbl->entries = emalloc(sizeof(entry) * size);
15
16 for (int i = 0; i < size; i++)
17 tbl->entries[i] = NULL;
18
19 return tbl;
20}
21
22void
23freeentry(entry *ent)
24{
25 entry *next;
26
27 if (!ent) return;
28 free(ent->key);
29
30 for (next = ent->next; next != NULL; next = next->next)
31 freeentry(next);
32
33 free(ent);
34}
35
36void
37freeenv(env *tbl)
38{
39 if (!tbl) return;
40 for (int i = 0; i < tbl->size; i++)
41 freeentry(tbl->entries[i]);
42
43 free(tbl->entries);
44 free(tbl);
45}
46
47int
48hash(env *tbl, char *str)
49{
50 int c;
51 unsigned long hash = 5381;
52
53 /**
54 * Borrowed from DJB http://www.cse.yorku.ca/~oz/hash.html
55 */
56
57 while ((c = *str++))
58 /* hash * 33 + c */
59 hash = ((hash << 5) + hash) + c;
60
61 return hash % tbl->size;
62}
63
64int
65setval(env *tbl, char *key, int val)
66{
67 int keyh;
68 entry *ent, *buck, *last, *next;
69
70 ent = emalloc(sizeof(entry));
71 ent->key = estrdup(key);
72 ent->value = val;
73 ent->next = NULL;
74
75 keyh = hash(tbl, key);
76 if (!(buck = tbl->entries[keyh])) {
77 tbl->entries[keyh] = ent;
78 return 0;
79 }
80
81 for (next = buck; next != NULL; next = next->next) {
82 if (!strcmp(next->key, key))
83 return -1;
84 last = next;
85 }
86
87 last->next = ent;
88 return 0;
89}
90
91int
92updval(env *tbl, char *key, int val)
93{
94 int keyh;
95 entry *buck, *next;
96
97 keyh = hash(tbl, key);
98 if (!(buck = tbl->entries[keyh]))
99 return -1;
100
101 for (next = buck; next != NULL; next = next->next)
102 if (!strcmp(next->key, key))
103 break;
104
105 if (!next) return -1;
106 next->value = val;
107
108 return 0;
109}
110
111int
112getval(env *tbl, char *key, int *dest)
113{
114 int keyh;
115 entry *buck, *next;
116
117 keyh = hash(tbl, key);
118 if (!(buck = tbl->entries[keyh]))
119 return -1;
120
121 for (next = buck; next != NULL; next = next->next)
122 if (!strcmp(next->key, key))
123 break;
124
125 *dest = next->value;
126 return 0;
127}