-
Notifications
You must be signed in to change notification settings - Fork 0
/
symtable.c
105 lines (90 loc) · 2.51 KB
/
symtable.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
/**
* @file symtable.c
* @author Vladimír Hucovič (xhucov00), Ondřej Zobal (xzobal01), Marek Havel (xhavel46)
* @brief implementation of symtable
*
*/
#include "symtable.h"
#include <stdlib.h>
#include <string.h>
#include "misc.h"
int SYMTABLE_SIZE = MAX_SYMTABLE_SIZE;
/*
* This implementation of the djb2 hash function was taken from:
* http://www.cse.yorku.ca/~oz/hash.html
*/
long get_hash(unsigned char *key) {
unsigned long hash = 5381;
int c;
while ((c = *key++)) {
// hash * 33 + c
hash = ((hash << 5) + hash) + c;
}
return (hash % SYMTABLE_SIZE);
}
void symtable_init(sym_table_t *table) {
for (int i = 0; i < MAX_SYMTABLE_SIZE; i++){
(*table)[i] = NULL;
}
}
symtable_item_t *symtable_search(sym_table_t *table, char *key) {
symtable_item_t* current = (*table)[get_hash((unsigned char*) key)];
while (current != NULL) {
if (!strcmp(current->key, key)) {
return current;
}
current = current->next;
}
return NULL;
}
void symtable_insert(sym_table_t *table, char *key, symtableElem* value) {
int hash = get_hash((unsigned char*) key);
// Update the element if it already exists.
symtable_item_t** current = &((*table)[hash]);
while (*current != NULL) {
if (!strcmp((*current)->key, key)) {
(*current)->value = value;
return;
}
current = &((*current)->next);
}
// Init the new element.
symtable_item_t* new = malloc(sizeof(symtable_item_t));
CHECK_ALLOCATION(new)
char* new_key = malloc(strlen(key)+1);
CHECK_ALLOCATION(new_key)
strcpy(new_key, key);
new->key = new_key;
new->value = value;
// Link it into the list.
new->next = (*table)[hash];
(*table)[hash] = new;
}
symtableElem* symtable_get(sym_table_t *table, char *key) {
symtable_item_t* item = symtable_search(table, key);
return item == NULL ? NULL : item->value;
}
void symtable_delete(sym_table_t *table, char *key) {
symtable_item_t** current = &(*table)[get_hash((unsigned char *) key)];
if (current == NULL) return;
while (strcmp((*current)->key, key)) {
current = &(*current)->next;
if (current == NULL) break;
}
symtable_item_t* delete = *current;
*current = (*current)->next;
free(delete->key);
free(delete);
}
void symtable_delete_all(sym_table_t *table) {
for (int i = 0; i < SYMTABLE_SIZE; i++) {
symtable_item_t* current = (*table)[i];
while (current != NULL) {
symtable_item_t* old = current;
current = current->next;
free(old->key);
free(old);
}
((*table)[i]) = NULL;
}
}