Util: Table cleanup, add HashTableEnumerateBinary
@@ -17,9 +17,10 @@ struct TableList* table;
size_t tableSize; size_t size; void (*deinitializer)(void*); + uint32_t seed; }; -void TableInit(struct Table*, size_t initialSize, void (deinitializer(void*))); +void TableInit(struct Table*, size_t initialSize, void (*deinitializer)(void*)); void TableDeinit(struct Table*); void* TableLookup(const struct Table*, uint32_t key);@@ -28,10 +29,10 @@
void TableRemove(struct Table*, uint32_t key); void TableClear(struct Table*); -void TableEnumerate(const struct Table*, void (handler(uint32_t key, void* value, void* user)), void* user); +void TableEnumerate(const struct Table*, void (*handler)(uint32_t key, void* value, void* user), void* user); size_t TableSize(const struct Table*); -void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))); +void HashTableInit(struct Table* table, size_t initialSize, void (*deinitializer)(void*)); void HashTableDeinit(struct Table* table); void* HashTableLookup(const struct Table*, const char* key);@@ -43,8 +44,9 @@ void HashTableRemove(struct Table*, const char* key);
void HashTableRemoveBinary(struct Table*, const void* key, size_t keylen); void HashTableClear(struct Table*); -void HashTableEnumerate(const struct Table*, void (handler(const char* key, void* value, void* user)), void* user); -const char* HashTableSearch(const struct Table* table, bool (predicate(const char* key, const void* value, const void* user)), const void* user); +void HashTableEnumerate(const struct Table*, void (*handler)(const char* key, void* value, void* user), void* user); +void HashTableEnumerateBinary(const struct Table*, void (*handler)(const char* key, size_t keylen, void* value, void* user), void* user); +const char* HashTableSearch(const struct Table* table, bool (*predicate)(const char* key, const void* value, const void* user), const void* user); const char* HashTableSearchPointer(const struct Table* table, const void* value); const char* HashTableSearchData(const struct Table* table, const void* value, size_t bytes); const char* HashTableSearchString(const struct Table* table, const char* value);
@@ -6,6 +6,7 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include <mgba-util/table.h> #include <mgba-util/hash.h> +#include <mgba-util/math.h> #include <mgba-util/string.h> #define LIST_INITIAL_SIZE 8@@ -15,9 +16,7 @@ #define TABLE_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == key
#define HASH_TABLE_STRNCMP_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == hash && strncmp(LIST->list[(INDEX)].stringKey, key, LIST->list[(INDEX)].keylen) == 0 #define HASH_TABLE_MEMCMP_COMPARATOR(LIST, INDEX) LIST->list[(INDEX)].key == hash && memcmp(LIST->list[(INDEX)].stringKey, key, LIST->list[(INDEX)].keylen) == 0 -#define TABLE_LOOKUP_START(COMPARATOR, LIST, KEY) \ - uint32_t entry = (KEY) & (table->tableSize - 1); \ - LIST = &table->table[entry]; \ +#define TABLE_LOOKUP_START(COMPARATOR, LIST) \ size_t i; \ for (i = 0; i < LIST->nEntries; ++i) { \ if (COMPARATOR(LIST, i)) { \@@ -42,6 +41,16 @@ size_t nEntries;
size_t listSize; }; +static inline const struct TableList* _getConstList(const struct Table* table, uint32_t key) { + uint32_t entry = key & (table->tableSize - 1); + return &table->table[entry]; +} + +static inline struct TableList* _getList(struct Table* table, uint32_t key) { + uint32_t entry = key & (table->tableSize - 1); + return &table->table[entry]; +} + static struct TableList* _resizeAsNeeded(struct Table* table, struct TableList* list, uint32_t key) { UNUSED(table); UNUSED(key);@@ -65,14 +74,17 @@ list->list[item] = list->list[list->nEntries];
} } -void TableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) { - if (initialSize < 2 || (initialSize & (initialSize - 1))) { +void TableInit(struct Table* table, size_t initialSize, void (*deinitializer)(void*)) { + if (initialSize < 2) { initialSize = TABLE_INITIAL_SIZE; + } else if (initialSize & (initialSize - 1)) { + initialSize = toPow2(initialSize); } table->tableSize = initialSize; table->table = calloc(table->tableSize, sizeof(struct TableList)); table->size = 0; table->deinitializer = deinitializer; + table->seed = 0; size_t i; for (i = 0; i < table->tableSize; ++i) {@@ -101,16 +113,16 @@ table->tableSize = 0;
} void* TableLookup(const struct Table* table, uint32_t key) { - const struct TableList* list; - TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) { + const struct TableList* list = _getConstList(table, key); + TABLE_LOOKUP_START(TABLE_COMPARATOR, list) { return lookupResult->value; } TABLE_LOOKUP_END; return 0; } void TableInsert(struct Table* table, uint32_t key, void* value) { - struct TableList* list; - TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) { + struct TableList* list = _getList(table, key); + TABLE_LOOKUP_START(TABLE_COMPARATOR, list) { if (value != lookupResult->value) { if (table->deinitializer) { table->deinitializer(lookupResult->value);@@ -128,8 +140,8 @@ ++table->size;
} void TableRemove(struct Table* table, uint32_t key) { - struct TableList* list; - TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) { + struct TableList* list = _getList(table, key); + TABLE_LOOKUP_START(TABLE_COMPARATOR, list) { _removeItemFromList(table, list, i); // TODO: Move i out of the macro } TABLE_LOOKUP_END; }@@ -151,7 +163,7 @@ list->list = calloc(LIST_INITIAL_SIZE, sizeof(struct TableTuple));
} } -void TableEnumerate(const struct Table* table, void (handler(uint32_t key, void* value, void* user)), void* user) { +void TableEnumerate(const struct Table* table, void (*handler)(uint32_t key, void* value, void* user), void* user) { size_t i; for (i = 0; i < table->tableSize; ++i) { const struct TableList* list = &table->table[i];@@ -166,7 +178,7 @@ size_t TableSize(const struct Table* table) {
return table->size; } -void HashTableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) { +void HashTableInit(struct Table* table, size_t initialSize, void (*deinitializer)(void*)) { TableInit(table, initialSize, deinitializer); }@@ -175,27 +187,27 @@ TableDeinit(table);
} void* HashTableLookup(const struct Table* table, const char* key) { - uint32_t hash = hash32(key, strlen(key), 0); - const struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) { + uint32_t hash = hash32(key, strlen(key), table->seed); + const struct TableList* list = _getConstList(table, hash); + TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list) { return lookupResult->value; } TABLE_LOOKUP_END; return 0; } void* HashTableLookupBinary(const struct Table* table, const void* key, size_t keylen) { - uint32_t hash = hash32(key, keylen, 0); - const struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) { + uint32_t hash = hash32(key, keylen, table->seed); + const struct TableList* list = _getConstList(table, hash); + TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list) { return lookupResult->value; } TABLE_LOOKUP_END; return 0; } void HashTableInsert(struct Table* table, const char* key, void* value) { - uint32_t hash = hash32(key, strlen(key), 0); - struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) { + uint32_t hash = hash32(key, strlen(key), table->seed); + struct TableList* list = _getList(table, hash); + TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list) { if (value != lookupResult->value) { if (table->deinitializer) { table->deinitializer(lookupResult->value);@@ -214,9 +226,9 @@ ++table->size;
} void HashTableInsertBinary(struct Table* table, const void* key, size_t keylen, void* value) { - uint32_t hash = hash32(key, keylen, 0); - struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) { + uint32_t hash = hash32(key, keylen, table->seed); + struct TableList* list = _getList(table, hash); + TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list) { if (value != lookupResult->value) { if (table->deinitializer) { table->deinitializer(lookupResult->value);@@ -236,17 +248,17 @@ ++table->size;
} void HashTableRemove(struct Table* table, const char* key) { - uint32_t hash = hash32(key, strlen(key), 0); - struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) { + uint32_t hash = hash32(key, strlen(key), table->seed); + struct TableList* list = _getList(table, hash); + TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list) { _removeItemFromList(table, list, i); // TODO: Move i out of the macro } TABLE_LOOKUP_END; } void HashTableRemoveBinary(struct Table* table, const void* key, size_t keylen) { - uint32_t hash = hash32(key, keylen, 0); - struct TableList* list; - TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) { + uint32_t hash = hash32(key, keylen, table->seed); + struct TableList* list = _getList(table, hash); + TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list) { _removeItemFromList(table, list, i); // TODO: Move i out of the macro } TABLE_LOOKUP_END; }@@ -269,7 +281,7 @@ list->list = calloc(LIST_INITIAL_SIZE, sizeof(struct TableTuple));
} } -void HashTableEnumerate(const struct Table* table, void (handler(const char* key, void* value, void* user)), void* user) { +void HashTableEnumerate(const struct Table* table, void (*handler)(const char* key, void* value, void* user), void* user) { size_t i; for (i = 0; i < table->tableSize; ++i) { const struct TableList* list = &table->table[i];@@ -280,7 +292,18 @@ }
} } -const char* HashTableSearch(const struct Table* table, bool (predicate(const char* key, const void* value, const void* user)), const void* user) { +void HashTableEnumerateBinary(const struct Table* table, void (*handler)(const char* key, size_t keylen, void* value, void* user), void* user) { + size_t i; + for (i = 0; i < table->tableSize; ++i) { + const struct TableList* list = &table->table[i]; + size_t j; + for (j = 0; j < list->nEntries; ++j) { + handler(list->list[j].stringKey, list->list[j].keylen, list->list[j].value, user); + } + } +} + +const char* HashTableSearch(const struct Table* table, bool (*predicate)(const char* key, const void* value, const void* user), const void* user) { size_t i; const char* result = NULL; for (i = 0; i < table->tableSize; ++i) {