mirror of https://github.com/mgba-emu/mgba.git
Util: Table cleanup, add HashTableEnumerateBinary
This commit is contained in:
parent
ff1e5f2de8
commit
b6a3133a13
|
@ -17,9 +17,10 @@ struct Table {
|
||||||
size_t tableSize;
|
size_t tableSize;
|
||||||
size_t size;
|
size_t size;
|
||||||
void (*deinitializer)(void*);
|
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 TableDeinit(struct Table*);
|
||||||
|
|
||||||
void* TableLookup(const struct Table*, uint32_t key);
|
void* TableLookup(const struct Table*, uint32_t key);
|
||||||
|
@ -28,10 +29,10 @@ void TableInsert(struct Table*, uint32_t key, void* value);
|
||||||
void TableRemove(struct Table*, uint32_t key);
|
void TableRemove(struct Table*, uint32_t key);
|
||||||
void TableClear(struct Table*);
|
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*);
|
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 HashTableDeinit(struct Table* table);
|
||||||
|
|
||||||
void* HashTableLookup(const struct Table*, const char* key);
|
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 HashTableRemoveBinary(struct Table*, const void* key, size_t keylen);
|
||||||
void HashTableClear(struct Table*);
|
void HashTableClear(struct Table*);
|
||||||
|
|
||||||
void HashTableEnumerate(const struct Table*, void (handler(const char* key, void* value, void* user)), void* user);
|
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 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* HashTableSearchPointer(const struct Table* table, const void* value);
|
||||||
const char* HashTableSearchData(const struct Table* table, const void* value, size_t bytes);
|
const char* HashTableSearchData(const struct Table* table, const void* value, size_t bytes);
|
||||||
const char* HashTableSearchString(const struct Table* table, const char* value);
|
const char* HashTableSearchString(const struct Table* table, const char* value);
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mgba-util/table.h>
|
#include <mgba-util/table.h>
|
||||||
|
|
||||||
#include <mgba-util/hash.h>
|
#include <mgba-util/hash.h>
|
||||||
|
#include <mgba-util/math.h>
|
||||||
#include <mgba-util/string.h>
|
#include <mgba-util/string.h>
|
||||||
|
|
||||||
#define LIST_INITIAL_SIZE 8
|
#define LIST_INITIAL_SIZE 8
|
||||||
|
@ -15,9 +16,7 @@
|
||||||
#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_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 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) \
|
#define TABLE_LOOKUP_START(COMPARATOR, LIST) \
|
||||||
uint32_t entry = (KEY) & (table->tableSize - 1); \
|
|
||||||
LIST = &table->table[entry]; \
|
|
||||||
size_t i; \
|
size_t i; \
|
||||||
for (i = 0; i < LIST->nEntries; ++i) { \
|
for (i = 0; i < LIST->nEntries; ++i) { \
|
||||||
if (COMPARATOR(LIST, i)) { \
|
if (COMPARATOR(LIST, i)) { \
|
||||||
|
@ -42,6 +41,16 @@ struct TableList {
|
||||||
size_t listSize;
|
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) {
|
static struct TableList* _resizeAsNeeded(struct Table* table, struct TableList* list, uint32_t key) {
|
||||||
UNUSED(table);
|
UNUSED(table);
|
||||||
UNUSED(key);
|
UNUSED(key);
|
||||||
|
@ -65,14 +74,17 @@ static void _removeItemFromList(struct Table* table, struct TableList* list, siz
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableInit(struct Table* table, size_t initialSize, void (deinitializer(void*))) {
|
void TableInit(struct Table* table, size_t initialSize, void (*deinitializer)(void*)) {
|
||||||
if (initialSize < 2 || (initialSize & (initialSize - 1))) {
|
if (initialSize < 2) {
|
||||||
initialSize = TABLE_INITIAL_SIZE;
|
initialSize = TABLE_INITIAL_SIZE;
|
||||||
|
} else if (initialSize & (initialSize - 1)) {
|
||||||
|
initialSize = toPow2(initialSize);
|
||||||
}
|
}
|
||||||
table->tableSize = initialSize;
|
table->tableSize = initialSize;
|
||||||
table->table = calloc(table->tableSize, sizeof(struct TableList));
|
table->table = calloc(table->tableSize, sizeof(struct TableList));
|
||||||
table->size = 0;
|
table->size = 0;
|
||||||
table->deinitializer = deinitializer;
|
table->deinitializer = deinitializer;
|
||||||
|
table->seed = 0;
|
||||||
|
|
||||||
size_t i;
|
size_t i;
|
||||||
for (i = 0; i < table->tableSize; ++i) {
|
for (i = 0; i < table->tableSize; ++i) {
|
||||||
|
@ -101,16 +113,16 @@ void TableDeinit(struct Table* table) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* TableLookup(const struct Table* table, uint32_t key) {
|
void* TableLookup(const struct Table* table, uint32_t key) {
|
||||||
const struct TableList* list;
|
const struct TableList* list = _getConstList(table, key);
|
||||||
TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) {
|
TABLE_LOOKUP_START(TABLE_COMPARATOR, list) {
|
||||||
return lookupResult->value;
|
return lookupResult->value;
|
||||||
} TABLE_LOOKUP_END;
|
} TABLE_LOOKUP_END;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableInsert(struct Table* table, uint32_t key, void* value) {
|
void TableInsert(struct Table* table, uint32_t key, void* value) {
|
||||||
struct TableList* list;
|
struct TableList* list = _getList(table, key);
|
||||||
TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) {
|
TABLE_LOOKUP_START(TABLE_COMPARATOR, list) {
|
||||||
if (value != lookupResult->value) {
|
if (value != lookupResult->value) {
|
||||||
if (table->deinitializer) {
|
if (table->deinitializer) {
|
||||||
table->deinitializer(lookupResult->value);
|
table->deinitializer(lookupResult->value);
|
||||||
|
@ -128,8 +140,8 @@ void TableInsert(struct Table* table, uint32_t key, void* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void TableRemove(struct Table* table, uint32_t key) {
|
void TableRemove(struct Table* table, uint32_t key) {
|
||||||
struct TableList* list;
|
struct TableList* list = _getList(table, key);
|
||||||
TABLE_LOOKUP_START(TABLE_COMPARATOR, list, key) {
|
TABLE_LOOKUP_START(TABLE_COMPARATOR, list) {
|
||||||
_removeItemFromList(table, list, i); // TODO: Move i out of the macro
|
_removeItemFromList(table, list, i); // TODO: Move i out of the macro
|
||||||
} TABLE_LOOKUP_END;
|
} TABLE_LOOKUP_END;
|
||||||
}
|
}
|
||||||
|
@ -151,7 +163,7 @@ void TableClear(struct Table* table) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
size_t i;
|
||||||
for (i = 0; i < table->tableSize; ++i) {
|
for (i = 0; i < table->tableSize; ++i) {
|
||||||
const struct TableList* list = &table->table[i];
|
const struct TableList* list = &table->table[i];
|
||||||
|
@ -166,7 +178,7 @@ size_t TableSize(const struct Table* table) {
|
||||||
return table->size;
|
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);
|
TableInit(table, initialSize, deinitializer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -175,27 +187,27 @@ void HashTableDeinit(struct Table* table) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void* HashTableLookup(const struct Table* table, const char* key) {
|
void* HashTableLookup(const struct Table* table, const char* key) {
|
||||||
uint32_t hash = hash32(key, strlen(key), 0);
|
uint32_t hash = hash32(key, strlen(key), table->seed);
|
||||||
const struct TableList* list;
|
const struct TableList* list = _getConstList(table, hash);
|
||||||
TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) {
|
TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list) {
|
||||||
return lookupResult->value;
|
return lookupResult->value;
|
||||||
} TABLE_LOOKUP_END;
|
} TABLE_LOOKUP_END;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void* HashTableLookupBinary(const struct Table* table, const void* key, size_t keylen) {
|
void* HashTableLookupBinary(const struct Table* table, const void* key, size_t keylen) {
|
||||||
uint32_t hash = hash32(key, keylen, 0);
|
uint32_t hash = hash32(key, keylen, table->seed);
|
||||||
const struct TableList* list;
|
const struct TableList* list = _getConstList(table, hash);
|
||||||
TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) {
|
TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list) {
|
||||||
return lookupResult->value;
|
return lookupResult->value;
|
||||||
} TABLE_LOOKUP_END;
|
} TABLE_LOOKUP_END;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashTableInsert(struct Table* table, const char* key, void* value) {
|
void HashTableInsert(struct Table* table, const char* key, void* value) {
|
||||||
uint32_t hash = hash32(key, strlen(key), 0);
|
uint32_t hash = hash32(key, strlen(key), table->seed);
|
||||||
struct TableList* list;
|
struct TableList* list = _getList(table, hash);
|
||||||
TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) {
|
TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list) {
|
||||||
if (value != lookupResult->value) {
|
if (value != lookupResult->value) {
|
||||||
if (table->deinitializer) {
|
if (table->deinitializer) {
|
||||||
table->deinitializer(lookupResult->value);
|
table->deinitializer(lookupResult->value);
|
||||||
|
@ -214,9 +226,9 @@ void HashTableInsert(struct Table* table, const char* key, void* value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashTableInsertBinary(struct Table* table, const void* key, size_t keylen, void* value) {
|
void HashTableInsertBinary(struct Table* table, const void* key, size_t keylen, void* value) {
|
||||||
uint32_t hash = hash32(key, keylen, 0);
|
uint32_t hash = hash32(key, keylen, table->seed);
|
||||||
struct TableList* list;
|
struct TableList* list = _getList(table, hash);
|
||||||
TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) {
|
TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list) {
|
||||||
if (value != lookupResult->value) {
|
if (value != lookupResult->value) {
|
||||||
if (table->deinitializer) {
|
if (table->deinitializer) {
|
||||||
table->deinitializer(lookupResult->value);
|
table->deinitializer(lookupResult->value);
|
||||||
|
@ -236,17 +248,17 @@ void HashTableInsertBinary(struct Table* table, const void* key, size_t keylen,
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashTableRemove(struct Table* table, const char* key) {
|
void HashTableRemove(struct Table* table, const char* key) {
|
||||||
uint32_t hash = hash32(key, strlen(key), 0);
|
uint32_t hash = hash32(key, strlen(key), table->seed);
|
||||||
struct TableList* list;
|
struct TableList* list = _getList(table, hash);
|
||||||
TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list, hash) {
|
TABLE_LOOKUP_START(HASH_TABLE_STRNCMP_COMPARATOR, list) {
|
||||||
_removeItemFromList(table, list, i); // TODO: Move i out of the macro
|
_removeItemFromList(table, list, i); // TODO: Move i out of the macro
|
||||||
} TABLE_LOOKUP_END;
|
} TABLE_LOOKUP_END;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HashTableRemoveBinary(struct Table* table, const void* key, size_t keylen) {
|
void HashTableRemoveBinary(struct Table* table, const void* key, size_t keylen) {
|
||||||
uint32_t hash = hash32(key, keylen, 0);
|
uint32_t hash = hash32(key, keylen, table->seed);
|
||||||
struct TableList* list;
|
struct TableList* list = _getList(table, hash);
|
||||||
TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list, hash) {
|
TABLE_LOOKUP_START(HASH_TABLE_MEMCMP_COMPARATOR, list) {
|
||||||
_removeItemFromList(table, list, i); // TODO: Move i out of the macro
|
_removeItemFromList(table, list, i); // TODO: Move i out of the macro
|
||||||
} TABLE_LOOKUP_END;
|
} TABLE_LOOKUP_END;
|
||||||
}
|
}
|
||||||
|
@ -269,7 +281,7 @@ void HashTableClear(struct Table* table) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
size_t i;
|
||||||
for (i = 0; i < table->tableSize; ++i) {
|
for (i = 0; i < table->tableSize; ++i) {
|
||||||
const struct TableList* list = &table->table[i];
|
const struct TableList* list = &table->table[i];
|
||||||
|
@ -280,7 +292,18 @@ void HashTableEnumerate(const struct Table* table, void (handler(const char* key
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
size_t i;
|
||||||
const char* result = NULL;
|
const char* result = NULL;
|
||||||
for (i = 0; i < table->tableSize; ++i) {
|
for (i = 0; i < table->tableSize; ++i) {
|
||||||
|
|
Loading…
Reference in New Issue