Created
April 22, 2018 21:21
-
-
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
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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