#include #include #include /* Up to 128 tables can be defined */ #define MAX 128 static struct table db[MAX] = { 0 }; /* Number of tables currently used */ static int db_size = 0; /* table_free(): Free a table and its contents @t Table pointer */ static void table_free(struct table *t) { if(!t) return; free(t->name); if(t->items) for(int i = 0; i < t->count; i++) { t->free_item(t->items + i * t->size); } free(t->items); } /* table_quit(): Destroy all allocated tables and release memory */ __attribute__((destructor)) static void table_quit(void) { for(int i = 0; i < db_size; i++) table_free(&db[i]); } /* table_available(): Whether a table can be allocated */ int table_available(void) { return db_size < MAX; } /* table_create(): Create a new table */ void table_create(char const *type, char *name, void (*free_item)(void *), int count, size_t size, void *items) { if(!table_available()) return; struct table *t = &db[db_size++]; t->type = type; t->name = name; t->free_item = free_item; t->count = count; t->size = size; t->items = items; } /* table_find(): Find matching entries in the database tables */ void *table_find(char const *type, int (*match)(void *), char const **name, int next) { static int table = 0; static int index = 0; if(!next) table = index = 0; while(table < db_size) { struct table const *t = &db[table]; if(!strcmp(t->type, type)) while(index < t->count) { void *entry = t->items + index * t->size; index++; if(match(entry)) { if(name) *name = t->name; return entry; } } table++; index = 0; } return NULL; }