Skip to content

Instantly share code, notes, and snippets.

@easyaspi314
Last active November 24, 2018 07:57
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save easyaspi314/b836692b065e3c446b1ee9c749695d1c to your computer and use it in GitHub Desktop.
Save easyaspi314/b836692b065e3c446b1ee9c749695d1c to your computer and use it in GitHub Desktop.
My failed attempt at a hash map.
/* Copyright (C) 2018 easyaspi314
* MIT license.
* Please don't use this code, it is BAD.
* Use an actual hash map. Please.
*/
#include <stdlib.h>
#include <stdio.h>
#include <limits.h>
#include <stdint.h>
#define FATAL_ERROR(...) do { \
fprintf(stderr, __VA_ARGS__); \
abort(); \
} while (0)
struct HashMap
{
int32_t *keys;
char **values;
unsigned count;
unsigned capacity;
};
static int Hash(const char *str)
{
uint32_t hash = 5381;
while (*str)
hash = (hash * 33) ^ (uint8_t)*str++;
return (int)hash;
}
HashMap *HashMap_New(void)
{
HashMap *m = (HashMap *)malloc(sizeof(HashMap));
m->keys = (int *)malloc(16 * sizeof(int));
m->values = (char **)malloc(16 * sizeof(char *));
m->count = 0;
m->capacity = 16;
return m;
}
void HashMap_Delete(HashMap *m)
{
for (unsigned i = 0; i < m->count; i++)
free(m->values[i]);
free(m->keys);
free(m->values);
free(m);
}
char *HashMap_FindInt(HashMap *m, int key)
{
for (unsigned i = 0; i < m->count; i++)
if (m->keys[i] == key)
return m->values[i];
return NULL;
}
char *HashMap_FindString(HashMap *restrict m, const char *restrict key)
{
int hash = Hash(key);
return HashMap_FindInt(m, hash);
}
static void Grow(HashMap *m)
{
if (m->capacity > UINT_MAX / 2)
FATAL_ERROR("HashMap: Out of memory!\n");
unsigned newcap = m->capacity * 2;
m->keys = (int *)realloc(m->keys, newcap * sizeof(int));
m->values = (char **)realloc(m->values, newcap * sizeof(char *));
if (!m->keys || !m->values)
FATAL_ERROR("HashMap: Out of memory!\n");
m->capacity = newcap;
}
void HashMap_PutInt(HashMap *restrict m, int key, char *restrict value)
{
for (unsigned i = 0; i < m->count; i++)
{
if (m->keys[i] == key)
{
free(m->values[i]);
m->values[i] = value;
return;
}
}
if (m->capacity > 0 && m->count >= m->capacity)
Grow(m);
m->keys[m->count] = key;
m->values[m->count] = value;
m->count++;
}
void HashMap_PutString(HashMap *restrict m, const char *restrict key, char *restrict value)
{
int hash = Hash(key);
HashMap_PutInt(m, hash, value);
}
char *HashMap_FindInt(HashMap *m, int key)
{
// linear lookup
for (unsigned i = 0; i < m->count; i++)
if (m->keys[i] == key)
return m->values[i];
return NULL;
}
void HashMap_PutInt(HashMap *restrict m, int key, char *restrict value)
{
// yet again linear search
for (unsigned i = 0; i < m->count; i++)
{
if (m->keys[i] == key)
{
// Collision must mean I want to overwrite
free(m->values[i]);
m->values[i] = value;
return;
}
}
if (m->capacity > 0 && m->count >= m->capacity)
Grow(m);
m->keys[m->count] = key;
m->values[m->count] = value;
m->count++;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment