struct table_head { int reclen; int cmplen; unsigned char *buffer; int size; int alloc; }; #define table_get(tab, idx) (void*) ((tab)->buffer + ((idx) * (tab)->reclen)) void table_init(struct table_head *tab, int reclen, int cmplen) { tab->reclen = reclen; tab->cmplen = cmplen; tab->size = 0; tab->alloc = 1; tab->buffer = malloc(reclen); if (tab->buffer == NULL) err("error allocating memory"); } void table_resize(struct table_head *tab, int ned) { int siz = -1; if ((ned + 512) < tab->alloc) siz = ned + 128; if (ned > tab->alloc) siz = ned + 512; if (siz < 0) return; unsigned char *old = tab->buffer; unsigned char *new = malloc((size_t)tab->reclen * siz); if (new == NULL) err("error allocating memory"); memcpy(new, old, (size_t)tab->reclen * tab->size); tab->buffer = new; tab->alloc = siz; usleep(10000); free(old); } void table_deinit(struct table_head *tab) { tab->reclen = 0; tab->cmplen = 0; tab->size = 0; free(tab->buffer); tab->buffer = NULL; } int table_find(struct table_head *tab, void *ntry) { int lower = 0; int upper = tab->size - 1; unsigned int*entry = (unsigned int*)ntry; int cmpln = tab->cmplen; while (lower <= upper) { int mid = (lower + upper) >> 1; unsigned int*curr = (unsigned int*)table_get(tab, mid); long cmp; for (int i = 0;;) { #if UINT_MAX >= ULONG_MAX int val1 = curr[i]; int val2 = entry[i]; cmp = (val1 > val2) - (val1 < val2); #else cmp = (long)curr[i] - (long)entry[i]; #endif if (cmp != 0) break; i++; if (i >= cmpln) return mid; } if (cmp < 0) { lower = mid + 1; } else { upper = mid - 1; } } return - lower - 1; } void table_add(struct table_head *tab, void *ntry) { int idx = table_find(tab, ntry); if (idx >= 0) { memmove(table_get(tab, idx), ntry, tab->reclen); return; } table_resize(tab, tab->size + 1); idx = -idx - 1; memmove(table_get(tab, idx + 1), table_get(tab, idx), (size_t)tab->reclen * (tab->size - idx)); tab->size++; memmove(table_get(tab, idx), ntry, tab->reclen); } void table_del(struct table_head *tab, void *ntry) { int idx = table_find(tab, ntry); if (idx < 0) return; if (idx < (tab->size - 1)) memmove(table_get(tab, idx), table_get(tab, idx + 1), (size_t)tab->reclen * (tab->size - idx - 1)); tab->size--; table_resize(tab, tab->size); } void* table_addinited(struct table_head *tab, void *ntry, struct table_head *tab2, int reclen, int cmplen) { int index = table_find(tab, ntry); if (index < 0) { table_add(tab, ntry); index = table_find(tab, ntry); } void *res = table_get(tab, index); struct table_head *tab3 = res + ((char*)tab2 - (char*)ntry); if (tab3->reclen == reclen) return res; table_init(tab3, reclen, cmplen); return res; }