247 lines
6.2 KiB
C
247 lines
6.2 KiB
C
|
|
||
|
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;
|
||
|
}
|