1#include <stdlib.h>2#include <string.h>34#include "env.h"5#include "util.h"67env*8newenv(int size)9{10 env *tbl;1112 tbl = emalloc(sizeof(env));13 tbl->size = size;14 tbl->entries = emalloc(sizeof(entry) * size);1516 for (int i = 0; i < size; i++)17 tbl->entries[i] = NULL;1819 return tbl;20}2122void23freeentry(entry *ent)24{25 entry *next;2627 if (!ent) return;28 free(ent->key);2930 for (next = ent->next; next != NULL; next = next->next)31 freeentry(next);3233 free(ent);34}3536void37freeenv(env *tbl)38{39 if (!tbl) return;40 for (int i = 0; i < tbl->size; i++)41 freeentry(tbl->entries[i]);4243 free(tbl->entries);44 free(tbl);45}4647int48hash(env *tbl, char *str)49{50 int c;51 unsigned long hash = 5381;5253 /**54 * Borrowed from DJB http://www.cse.yorku.ca/~oz/hash.html55 */5657 while ((c = *str++))58 /* hash * 33 + c */59 hash = ((hash << 5) + hash) + c;6061 return hash % tbl->size;62}6364int65setval(env *tbl, char *key, int val)66{67 int keyh;68 entry *ent, *buck, *last, *next;6970 ent = emalloc(sizeof(entry));71 ent->key = estrdup(key);72 ent->value = val;73 ent->next = NULL;7475 keyh = hash(tbl, key);76 if (!(buck = tbl->entries[keyh])) {77 tbl->entries[keyh] = ent;78 return 0;79 }8081 for (next = buck; next != NULL; next = next->next) {82 if (!strcmp(next->key, key))83 return -1;84 last = next;85 }8687 last->next = ent;88 return 0;89}9091int92updval(env *tbl, char *key, int val)93{94 int keyh;95 entry *buck, *next;9697 keyh = hash(tbl, key);98 if (!(buck = tbl->entries[keyh]))99 return -1;100101 for (next = buck; next != NULL; next = next->next)102 if (!strcmp(next->key, key))103 break;104105 if (!next) return -1;106 next->value = val;107108 return 0;109}110111int112getval(env *tbl, char *key, int *dest)113{114 int keyh;115 entry *buck, *next;116117 keyh = hash(tbl, key);118 if (!(buck = tbl->entries[keyh]))119 return -1;120121 for (next = buck; next != NULL; next = next->next)122 if (!strcmp(next->key, key))123 break;124125 *dest = next->value;126 return 0;127}