Skip to content

Instantly share code, notes, and snippets.

@Chubek
Last active August 18, 2025 20:52
Show Gist options
  • Save Chubek/2bd34073809085aa980e9b4deff9f3fb to your computer and use it in GitHub Desktop.
Save Chubek/2bd34073809085aa980e9b4deff9f3fb to your computer and use it in GitHub Desktop.
Small symbol table in C
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "object.h"
#include "symtbl.h"
symtbl_t *
symtbl_new (size_t max_buckets)
{
symtbl_t *stab = malloc (sizeof (symtbl_t));
stab->buckets = calloc (max_buckets, sizeof (entry_t));
stab->count = 0;
stab->max_buckets = max_buckets;
}
void
symtbl_delete (symtbl_t *stab)
{
for (size_t i = 0; i < stab->max_buckets; i++)
{
entry_t *e = &stab->buckets[i];
while (e)
{
entry_t *next = e->next;
free (e->key);
free (e->value);
free (e);
e = e->next;
}
}
free (stab->buckets);
free (stab);
}
void
symtbl_install (symtbl_t *stab, const object_t *key, object_t *value)
{
if (stab->count / stab->max_buckets >= SYMTBL_GROWTH_FACTOR)
{
size_t new_max_buckets = stab->max_buckets * 2;
symtbl_t *new_stab = symtbl_new (new_max_buckets);
for (size_t i = 0; i < stab->max_buckets; i++)
{
entry_t *e = &stab->buckets[i];
while (e)
{
symtbl_install (new_stab, e->key, e->value);
e = e->next;
}
}
symtbl_t **stabp = &stab;
symtbl_delete (stab);
*stabp = new_stab;
}
size_t idx = object_hash (key) % stab->max_buckets;
entry_t *e = &stab->buckets[idx];
while (e->next)
{
if (object_equals (e->key, key))
{
object_delete (e->value);
e->value = object_copy (value);
return;
}
e = e->next;
}
e->next->key = object_copy (key);
e->next->value = object_copy (value);
e->next->next = NULL;
stab->count++;
}
object_t *
symtbl_retrieve (symtbl_t *stab, const object_t *key)
{
size_t idx = object_hash (key) % stab->max_buckets;
entry_t *e = &stab->buckets[idx];
while (e)
{
if (object_equals (e->key, key))
return e->value;
e = e->next;
}
return NULL;
}
void
symtbl_remove (symtbl_t *stab, const object_t *key)
{
size_t idx = object_hash (key) % stab->max_buckets;
entry_t *e = &stab->buckets[idx], *e_prev = e;
while (e)
{
if (object_equals (e->key, key))
break;
e_prev = e;
e = e->next;
}
free (e->key);
free (e->value);
if (e == e_prev)
{
entry_t **ep = &e;
entry_t *next = e->next;
free (e);
*ep = next;
}
else
{
entry_t *next = e->next;
free (e);
e_prev->next = next;
}
}
void
symtbl_serialize (symtbl_t *stab, const char *fpath)
{
FILE *fstream = fopen (fpath, "wb");
if (fstream == NULL)
fatalf ("Error opening file: %s", fpath);
fprintf (fstream, "%lu\n", stab->max_buckets);
fprintf (fstream, "%lu\n", stab->num_buckets);
for (size_t i = 0; i < stab->max_buckets; i++)
{
fprintf (fstream, "B::%d::\n", i);
entry_t *e = &stab->buckets[i];
size_t j = 0;
while (e)
{
fprintf (fstream, "E::%d\n", j);
object_serialize (e->key, fstream);
object_serialize (e->value, fstream);
fprintf (fstream, "E::%d;;\n\n", j);
j++;
e = e->next;
}
fprintf (fstream, "B::%d;;\n\n", i);
}
fclose (fstream);
}
symtbl_t *
symtbl_deserialize (const char *fpath)
{
// TODO
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment