Skip to content

Instantly share code, notes, and snippets.

@amyinorbit
Created April 22, 2018 21:21
Show Gist options
  • Save amyinorbit/d48263fbf7d2cac63567d76c4a2198af to your computer and use it in GitHub Desktop.
Save amyinorbit/d48263fbf7d2cac63567d76c4a2198af to your computer and use it in GitHub Desktop.
Naive, 20-minute string pool for the orbit compiler. Probably needs better indexing than what is currently implemented
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
typedef uint32_t StringID;
typedef struct _String String;
typedef struct _StringPool StringPool;
struct _String {
uint64_t length;
uint64_t next;
uint32_t hash;
char data[0];
};
struct _StringPool {
uint64_t size;
uint64_t capacity;
void* data;
};
StringPool pool = {
.size = 0,
.capacity = 0,
.data = NULL
};
#define STRADD(str) orbit_stringPoolIntern((str), strlen(str));
#define STRGET(id) orbit_stringPoolGet(id)
uint32_t hashString(const char* string, uint64_t length) {
uint32_t hash = 0x811C9DC5;
for(size_t i = 0; i < length; ++i) {
hash = (hash ^ string[i]) * 0x01000193;
}
return hash;
}
void orbit_stringPoolInit(uint64_t capacity) {
pool.capacity = capacity;
pool.size = 0;
pool.data = malloc(pool.capacity);
}
void orbit_stringPoolDeinit() {
pool.capacity = 0;
pool.size = 0;
free(pool.data);
}
bool orbit_stringEquals(String* a, const char* b, uint64_t length) {
uint32_t hash = hashString(b, length);
return hash == a->hash && length == a->length && strncmp(b, a->data, length) == 0;
}
String* orbit_stringPoolSearch(const char* data, uint64_t length) {
uint32_t hash = hashString(data, length);
uint64_t offset = 0;
while(offset < pool.size) {
String* str = (String*)(pool.data + offset);
if(hash == str->hash && length == str->length && strncmp(data, str->data, length) == 0) {
return str;
}
offset = str->next;
}
return NULL;
}
StringID orbit_stringPoolIntern(const char* data, uint64_t length) {
String* str = orbit_stringPoolSearch(data, length);
if(str) { return (StringID)((void*)str - pool.data); }
while(pool.size + length > pool.capacity) {
pool.capacity *= 2;
pool.data = realloc(pool.data, pool.capacity);
}
uint64_t id = pool.size;
str = (String*)(pool.data + pool.size);
pool.size += sizeof(String) + (length + 1) * sizeof(uint8_t);
memcpy(str->data, data, length+1);
str->data[length] = '\0';
str->length = length;
str->next = pool.size;
str->hash = hashString(data, length);
return id;
}
String* orbit_stringPoolGet(StringID id) {
return (String*)(pool.data + id);
}
int main(int argc, char const *argv[]) {
orbit_stringPoolInit(512);
StringID id1 = STRADD("Hello, World");
StringID id2 = STRADD("Hello, World");
StringID id3 = STRADD("Hello, World3");
StringID id4 = STRADD("Hello, World4");
printf("%d, %d, %d, %d\n", id1, id2, id3, id4);
printf("String #%d = %s\n", id1, orbit_stringPoolGet(id1)->data);
printf("Equality Test: %d\n", orbit_stringEquals(STRGET(id1), "Hello, World", strlen("Hello, World")));
orbit_stringPoolDeinit();
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment