holey-toys/hash.c
2024-03-11 05:21:52 -05:00

74 lines
1.7 KiB
C

// Instruction Hash table, for faster lookups
typedef struct InstHtNode_s
{
uint8_t index1;
uint8_t index2;
} InstHtNode;
typedef InstHtNode *InstHt;
uint32_t inst_hash(const char *s, size_t len)
{
uint32_t hash = 0;
uint32_t mul = 75;
for (size_t ii = 0; ii < len; ii += 1)
{
hash ^= s[ii] * mul;
hash *= mul;
}
return hash;
}
InstHt build_lookup(void)
{
const size_t size = 256;
InstHt table = (InstHt)malloc(size * sizeof(InstHtNode));
if (table == NULL)
{
return table;
}
for (size_t ii = 0; ii < size; ii += 1)
{
table[ii] = (InstHtNode){0xff, 0xff};
}
for (size_t ii = 0; ii < INST_CNT; ii += 1)
{
const char *mnemonic = INST[ii].mnemonic;
uint32_t hash = inst_hash(mnemonic, strlen(mnemonic));
InstHtNode *node = &table[hash & 0xff];
if (node->index1 == 0xff)
{
node->index1 = ii;
}
else if (node->index2 == 0xff)
{
node->index2 = ii;
}
else
{
fprintf(stderr, "more than 1 collision in hash table\n");
exit(1);
}
}
return table;
}
size_t inst_lookup(InstHt ht, const char *s, size_t len)
{
uint32_t hash = inst_hash(s, len);
uint8_t *node = (uint8_t *)&ht[(size_t)(hash & 0xff)];
for (size_t ii = 0; ii < 2; ii += 1)
{
size_t idx = (size_t)node[ii];
if (idx == 0xff)
{
break;
}
const char *mnemonic = INST[idx].mnemonic;
if (strncmp(s, mnemonic, len) == 0 && mnemonic[len] == 0)
{
return idx;
}
}
return INVALID;
}