#include "hash.h" #include "env.h" #include static unsigned long hash(const char *str) { unsigned long hash = 5381; int c; while ((c = *str++)) { hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ } return hash; } struct ObjectTable buildTable(size_t capacity) { struct ObjectTable table = { .count = 0, .capacity = capacity, .elements = capacity ? malloc(sizeof(struct EnvElement) * capacity) : NULL, }; for (int i = 0; i < table.capacity; i++) { table.elements[i].symbol = NULL; } return table; } /// /// \param table /// \param name Should be a new allocation /// \param object Should already be cloned void addToTable(struct ObjectTable* table, char* name, Object object) { if (table->capacity < (table->count + 1) * 2) { struct ObjectTable newTable = buildTable(table->capacity ? table->capacity * 2 : 4); for (int i = 0; i < table->capacity; i++) { if (table->elements[i].symbol) { addToTable(&newTable, table->elements[i].symbol, table->elements[i].object); } } free(table->elements); *table = newTable; } size_t h = hash(name) % table->capacity; while(table->elements[h].symbol) { h = (h + 1) % table->capacity; } table->elements[h].symbol = name; table->elements[h].object = object; table->count += 1; } Object* getFromTable(struct ObjectTable* table, const char* name) { if (table->capacity == 0) { return NULL; } size_t h = hash(name) % table->capacity; while(table->elements[h].symbol) { if (strcmp(name, table->elements[h].symbol) == 0) { return &table->elements[h].object; } h = (h + 1) % table->capacity; } return NULL; } void deleteTable(struct ObjectTable* table) { for (int i = 0; i < table->capacity; i++) { if (table->elements[i].symbol) { free(table->elements[i].symbol); cleanObject(&table->elements[i].object); } } free(table->elements); }