#include #include #include "wscm.h" St syms = {0, 0, NULL}; static S *findsym(const char *str, Z len, U32 hash) { if (syms.capacity == 0) return NULL; Z ix = hash % syms.capacity; for (Z i = 0; i < syms.capacity; i++) { S *s = syms.data[ix]; if (!s) return NULL; if (s->hash == hash && s->len == len) return s; ix = (ix + 1) % syms.capacity; } return NULL; } static void symtabresize(void) { Z cap = syms.capacity; if (cap == 0) { syms.capacity = 16; } else { syms.capacity *= 2; } S **nb = calloc(syms.capacity, sizeof(S *)); for (Z i = 0; i < cap; i++) { if (syms.data[i]) { S *s = syms.data[i]; Z ix = s->hash % syms.capacity; while (nb[ix]) ix = (ix + 1) % syms.capacity; nb[ix] = s; } } if (syms.data != NULL) free(syms.data); syms.data = nb; } U32 hashstring(const char *data, I len) { U32 hash = 2166136261u; for (I i = 0; i < len; i++) { hash ^= (uint8_t)data[i]; hash *= 16777619u; } return hash; } S *intern(const char *str, I len) { if (len < 0) len = strlen(str); U32 hash = hashstring(str, len); S *s = findsym(str, len, hash); if (s) return s; s = malloc(sizeof(S)); s->data = malloc(len); memcpy(s->data, str, len); s->len = len; s->hash = hash; if (syms.count + 1 > syms.capacity) symtabresize(); Z ix = hash % syms.capacity; while (syms.data[ix]) ix = (ix + 1) % syms.capacity; syms.data[ix] = s; syms.count++; return s; }