#include "hash.h" #include "env.h" #include 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; } 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); } #ifndef HASHLESS_ENV static unsigned long hash(const char* str, struct ObjectTable* table) { unsigned long hash = 5381; int c; while ((c = *str++)) { hash = ((hash << 5) + hash) + c; /* hash * 33 + c */ } return hash % table->capacity; } void extendTable(struct ObjectTable* table) { 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; } } Object* getFromTable(struct ObjectTable* table, const char* name) { if (table->capacity == 0) { return NULL; } size_t h = hash(name, table); 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; } #else void extendTable(struct ObjectTable* table) { if (table->count == (table->capacity - 1)) { struct EnvElement* oldElements = table->elements; size_t oldCapacity = table->capacity; table->capacity *= 2; table->elements = malloc(sizeof(struct EnvElement) * table->capacity); for (int i = 0; i < oldCapacity; i++) { table->elements[i] = oldElements[i]; } for (size_t i = oldCapacity; i < table->capacity; i++) { table->elements[i].symbol = NULL; } } } Object* getFromTable(struct ObjectTable* table, const char* name) { for (size_t i = 0; i < table->count; i++) { if (strcmp(name, table->elements[i].symbol) == 0) { return &table->elements[i].object; } } return NULL; } static unsigned long hash(unused const char* str, struct ObjectTable* table) { return table->count; } #endif /// /// \param table /// \param name Should be a new allocation /// \param object Should already be cloned void addToTable(struct ObjectTable* table, char* name, Object object) { extendTable(table); size_t h = hash(name, table); while (table->elements[h].symbol) { h = (h + 1) % table->capacity; } table->elements[h].symbol = name; table->elements[h].object = object; table->count += 1; }