Archived
1
0
Fork 0
This repository has been archived on 2025-09-02. You can view files and clone it, but you cannot make any changes to it's state, such as pushing and creating new issues, pull requests or comments.
skcblitz/table.h

247 lines
6.2 KiB
C
Raw Normal View History

2025-09-02 14:43:36 +02:00
void *itbl_push(itable_t *table) {
table_e *elem = table->free;
uint *block;
int cid;
int eid;
if(elem == NULL) {
return NULL;
}
table->free = table->free->f_next ? table->free->f_next : table->free->f_prev;
if(elem->f_prev) {
elem->f_prev->f_next = elem->f_next;
}
if(elem->f_next) {
elem->f_next->f_prev = elem->f_prev;
}
elem->f_next = elem->f_prev = NULL;
if(table->used && table->used->u_prev) {
table->used->u_prev->u_next = elem;
}
elem->u_prev = table->used ? table->used->u_prev : NULL; // unused
elem->u_next = table->used;
if(table->used) {
table->used->u_prev = elem;
}
table->used = elem;
cid = elem->cid;
eid = elem->eid;
if(table->data[cid] == NULL) {
table->data[cid] = mem_alloc((sizeof(uint) * 2 + table->stride) * table->load, table->cat);
table->alloc += 1;
}
table->sizes[cid] += 1;
block = (uint *)(&((byte *)(table->data[cid]))[eid * (sizeof(uint) * 2 + table->stride)]);
block[0] = cid;
block[1] = eid;
block += 2;
table->stored += 1;
// elem->value = (void *)block;
return (void *)block;
}
void itbl_init(itable_t *table, uint size, uint load, uint stride, byte cat);
void *tbl_push(table_t *table) {
void *elem;
for(int z = 0; z < table->size; z++) {
if(elem = itbl_push(&table->nodes[z])) {
table->stored += 1;
return elem;
}
}
table->nodes = mem_realloc(table->nodes, sizeof(itable_t) * (table->size + 1), table->cat);
itbl_init(&table->nodes[table->size], table->block, table->load, table->stride, table->cat);
elem = itbl_push(&table->nodes[table->size]);
table->size += 1;
table->stored += 1;
return elem;
}
byte itbl_pop(itable_t *table, void *ptr) {
uint *block = ((uint *)ptr) - 2;
int cid = block[0];
int eid = block[1];
if(block != (uint *)(&((byte *)(table->data[cid]))[eid * (sizeof(uint) * 2 + table->stride)]))
return 0;
table_e *elem = &table->elems[cid * table->load + eid];
if(elem == table->used) {
table->used = table->used->u_next ? table->used->u_next : table->used->u_prev;
}
if(elem->u_prev) {
elem->u_prev->u_next = elem->u_next;
}
if(elem->u_next) {
elem->u_next->u_prev = elem->u_prev;
}
elem->u_next = elem->u_prev = NULL;
if(table->free && table->free->f_prev) {
table->free->f_prev->f_next = elem;
}
elem->f_prev = table->free ? table->free->f_prev : NULL;
elem->f_next = table->free;
if(table->free) {
table->free->f_prev = elem;
}
table->free = elem;
if((table->sizes[cid] -= 1) == 0) {
mem_free(table->data[cid]);
table->data[cid] = NULL;
table->alloc -= 1;
}
table->stored -= 1;
// elem->value = NULL;
return 1;
}
void itbl_free(itable_t *table);
byte tbl_pop(table_t *table, void *ptr) {
itable_t *itable;
for(int z = 0; z < table->size; z++) {
itable = &table->nodes[z];
if(itbl_pop(itable, ptr)) {
table->stored -= 1;
if(!itable->stored) {
itbl_free(&table->nodes[z]);
itable = table->size == 1 ? NULL : mem_alloc(sizeof(itable_t) * (table->size - 1), table->cat);
table->size -= 1;
if(z)
memcpy(itable, table->nodes, z * sizeof(itable_t));
if(z < table->size)
memcpy(&itable[z], &table->nodes[z+1], (table->size - z) * sizeof(itable_t));
mem_free(table->nodes);
table->nodes = itable;
}
return 1;
}
}
return 0;
}
void *itbl_iter(itable_t *table, uint *ptr) {
table_e *elem = ((*ptr) == 0xffffffff) ? NULL : (((*ptr) == 0) ? table->used : &table->elems[(*ptr)-1]);
if(elem == NULL) {
return NULL;
}
*ptr = elem->u_next ? ((elem->u_next->cid * table->load + elem->u_next->eid) + 1) : 0xffffffff;
return ((uint *)(&((byte *)(table->data[elem->cid]))[elem->eid * (sizeof(uint) * 2 + table->stride)])) + 2;
}
void *tbl_iter(table_t *table, ulong *ptr) {
uint tid = (uint)((*ptr) & 0xffffffff);
uint nid = (uint)((*ptr) >> 32);
void *elem;
if(tid >= table->size) {
return NULL;
}
elem = itbl_iter(&table->nodes[tid], &nid);
while(!elem) {
if(++tid >= table->size)
return NULL;
nid = 0;
elem = itbl_iter(&table->nodes[tid], &nid);
}
*ptr = (ulong)tid | ((ulong)nid << 32);
return elem;
}
void itbl_dealloc(itable_t *table) {
for(int z = 0; z < table->chunks; z++) {
if(table->data[z]) {
mem_free(table->data[z]);
table->data[z] = NULL;
table->sizes[z] = 0;
}
}
}
void itbl_clear(itable_t *table) {
table_e *elem;
itbl_dealloc(table);
table->stored = table->alloc = 0;
table->used = NULL;
table->free = table->elems;
for(int z = 0; z < table->size; z++) {
elem = &table->elems[z];
elem->f_prev = (z == 0) ? NULL : &table->elems[z-1];
elem->f_next = (z == (table->size - 1)) ? NULL : &table->elems[z+1];
elem->u_prev = elem->u_next = NULL;
// elem->value = NULL;
elem->cid = z / table->load;
elem->eid = z % table->load;
}
}
void itbl_init(itable_t *table, uint size, uint load, uint stride, byte cat) {
table->size = size * load;
table->load = load;
table->chunks = table->size / table->load;
table->stride = stride;
table->cat = cat;
table->elems = mem_alloc(table->size * sizeof(table_e), cat);
table->data = mem_alloc(table->chunks * sizeof(void *), cat);
memset(table->data, 0, table->chunks * sizeof(void *));
table->sizes = mem_alloc(table->chunks * sizeof(uint), cat);
memset(table->sizes, 0, table->chunks * sizeof(uint));
itbl_clear(table);
}
void tbl_init(table_t *table, uint block, uint load, uint stride, byte cat) {
table->load = load;
table->block = block;
table->stride = stride;
table->cat = cat;
table->nodes = NULL;
table->size = table->stored = 0;
}
void itbl_free(itable_t *table) {
itbl_dealloc(table);
mem_free(table->elems);
mem_free(table->data);
mem_free(table->sizes);
}
void tbl_clear(table_t *table) {
for(int z = 0; z < table->size; z++) {
itbl_free(&table->nodes[z]);
}
if(table->nodes) {
mem_free(table->nodes);
table->nodes = NULL;
}
table->size = table->stored = 0;
}
int tbl_clear_func(table_t *table, clear_func *func) {
ulong iter = 0;
int pos = 0;
void *elem;
while(elem = tbl_iter(table, &iter)) {
func(elem);
pos++;
}
tbl_clear(table);
return pos;
}
int tbl_clear_func_sel(table_t *table, clear_sfunc *func, int count) {
ulong iter = 0;
int pos = 0;
void *elem;
void **clr = mem_alloc(sizeof(void*) * count, table->cat);
while(elem = tbl_iter(table, &iter)) {
if(func(elem))
clr[pos++] = elem;
}
for(iter = 0; iter < pos; iter++) {
tbl_pop(table, clr[iter]);
}
mem_free(clr);
return pos;
}