81 lines
1.5 KiB
C
81 lines
1.5 KiB
C
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#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, Z len) {
|
|
U32 hash = 2166136261u;
|
|
for (Z 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;
|
|
}
|