Allow non-null terminated strings
This commit is contained in:
parent
34f7eaea19
commit
3ea9100d78
57
hashtable.c
57
hashtable.c
@ -4,6 +4,19 @@
|
||||
#include "sdbm.h"
|
||||
#include "hashtable.h"
|
||||
|
||||
bool streq(char* str1, size_t len1, char* str2, size_t len2) {
|
||||
if (len1 == 0 && len2 == 0) {
|
||||
return !strcmp(str1, str2);
|
||||
} else if (len1 == len2) {
|
||||
return !memcmp(str1, str2, len1);
|
||||
} else if (len1 == 0) {
|
||||
return !memcmp(str1, str2, len2);
|
||||
} else if (len2 == 0) {
|
||||
return !memcmp(str1, str2, len1);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool hashtable_recreate(hashtable* table) {
|
||||
size_t oldcapacity = table->capacity;
|
||||
hashtable_item* olditems = table->items;
|
||||
@ -17,7 +30,7 @@ bool hashtable_recreate(hashtable* table) {
|
||||
for (size_t i = 0; i < oldcapacity; i++) {
|
||||
if (olditems[i].name == NULL || olditems[i].name == (void*)1)
|
||||
continue;
|
||||
size_t_optional index = hashtable_insert(&temptable, olditems[i].name);
|
||||
size_t_optional index = hashtable_insert(&temptable, olditems[i].name, olditems[i].size);
|
||||
if (!index.exists) {
|
||||
hashtable_item* array = temptable.items;
|
||||
for (size_t i = 0; i < temptable.capacity; i++)
|
||||
@ -42,21 +55,29 @@ hashtable* hashtable_create(void) {
|
||||
return table;
|
||||
}
|
||||
|
||||
size_t_optional hashtable_key(hashtable* table, char* name) {
|
||||
size_t index = sdbm(name) & (table->capacity - 1);
|
||||
size_t_optional hashtable_key(hashtable* table, char* name, size_t size) {
|
||||
size_t index;
|
||||
if (size)
|
||||
index = sdbm_clean(name, size) & (table->capacity - 1);
|
||||
else
|
||||
index = sdbm(name) & (table->capacity - 1);
|
||||
hashtable_item* array = table->items;
|
||||
while (1) {
|
||||
if (array[index].name == NULL)
|
||||
return (size_t_optional) { false, 0 };
|
||||
if (array[index].name != (void*)(1))
|
||||
if (!strcmp(name, array[index].name))
|
||||
if (streq(name, size, array[index].name, array[index].size))
|
||||
return (size_t_optional) { true, index };
|
||||
index = (index + 1) & (table->capacity - 1);
|
||||
}
|
||||
}
|
||||
|
||||
size_t_optional hashtable_insert(hashtable* table, char* name) {
|
||||
size_t index = sdbm(name) & (table->capacity - 1);
|
||||
size_t_optional hashtable_insert(hashtable* table, char* name, size_t size) {
|
||||
size_t index;
|
||||
if (size)
|
||||
index = sdbm_clean(name, size) & (table->capacity - 1);
|
||||
else
|
||||
index = sdbm(name) & (table->capacity - 1);
|
||||
hashtable_item* array = table->items;
|
||||
if ((table->capacity >> 2) * 3 < table->filled) {
|
||||
hashtable_recreate(table);
|
||||
@ -64,12 +85,16 @@ size_t_optional hashtable_insert(hashtable* table, char* name) {
|
||||
while (1) {
|
||||
if (array[index].name == NULL || array[index].name == (void*)1) {
|
||||
array[index].name = malloc(strlen(name) + sizeof(name));
|
||||
strcpy(array[index].name, name);
|
||||
array[index].size = size;
|
||||
if (size)
|
||||
memcpy(array[index].name, name, size);
|
||||
else
|
||||
strcpy(array[index].name, name);
|
||||
table->filled++;
|
||||
return (size_t_optional) {true, index};
|
||||
}
|
||||
else
|
||||