X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fq.c;h=615f2fe252cdaef1911b0b62183e4307eaf3f34a;hb=e4687b3aa2aed49fb16ba9e9561344d808750297;hp=e57810770e430b82319e4a6de5e078261d8d294f;hpb=067b8f578c7b189840383b979ea4ca8ccc88ebe9;p=swftools.git diff --git a/lib/q.c b/lib/q.c index e578107..615f2fe 100644 --- a/lib/q.c +++ b/lib/q.c @@ -21,6 +21,7 @@ #include #include +#include #include #include #include @@ -47,6 +48,21 @@ char*qstrndup(const char*string, int len) { return strdup_n(string, len); } +char* allocprintf(const char*format, ...) +{ + va_list arglist1; + va_start(arglist1, format); + char dummy; + int l = vsnprintf(&dummy, 1, format, arglist1); + va_end(arglist1); + + va_list arglist2; + va_start(arglist2, format); + char*buf = malloc(l+1); + vsnprintf(buf, l+1, format, arglist2); + va_end(arglist2); + return buf; +} // ------------------------------- mem_t -------------------------------------- @@ -280,38 +296,193 @@ void** heap_flatten(heap_t*h) // ------------------------------- trie -------------------------------------- -void trie_put(trie_t**t, unsigned const char*id) +trie_t*trie_new() +{ + return (trie_t*)rfx_calloc(sizeof(trie_t)); +} +static char _trie_put(trielayer_t**t, unsigned const char*id, void*data) { if(!*t) { - (*t) = rfx_calloc(sizeof(trie_t)); + (*t) = rfx_calloc(sizeof(trielayer_t)); (*t)->rest = (unsigned char*)strdup(id); - return; + (*t)->data = data; + return 0; } if((*t)->rest && (*t)->rest[0]) { - // shift whatever's currently in here one node down - trie_put(&(*t)->row[(*t)->rest[0]], (*t)->rest+1); + // make room: shift whatever's currently in here one node down + _trie_put(&(*t)->row[(*t)->rest[0]], (*t)->rest+1, (*t)->data); (*t)->rest = 0; } if(id[0]) { - trie_put(&(*t)->row[id[0]], id+1); + return _trie_put(&(*t)->row[id[0]], id+1, data); } else { - (*t)->rest = ""; + char overwrite = 0; + if((*t)->rest) + overwrite = 1; + (*t)->rest = strdup(""); + (*t)->data = data; + return overwrite; } } +static char _trie_remove(trielayer_t*t, unsigned const char*id) +{ + while(t) { + if(t->rest && !strcmp(t->rest, id)) { + free(t->rest); + t->rest = 0; + return 1; + } + if(!*id) + return 0; + t = t->row[*id++]; + } + return 0; +} + +static void trie_rollback_removes(trie_t*t, unsigned const char*id, void*data); +static void trie_rollback_adds(trie_t*t, unsigned const char*id, void*data); -int trie_lookup(trie_t*t, unsigned const char*id) +void trie_put(trie_t*t, unsigned const char*id, void*data) { + if(!t->rollback) { + _trie_put(&t->start, id, data); + } else { + char contains = trie_contains(t, id); + void*olddata = contains?trie_lookup(t, id):0; + _trie_put(&t->start, id, data); + if(contains) { + trie_rollback_adds(t, id, olddata); + } + trie_rollback_removes(t, id, data); + } +} +char trie_remove(trie_t*t, unsigned const char*id) +{ + if(!t->rollback) { + return _trie_remove(t->start, id); + } else { + void*olddata = trie_lookup(t, id); + char exists = _trie_remove(t->start, id); + if(exists) { + trie_rollback_adds(t, id, olddata); + } + return exists; + } +} +int trie_contains(trie_t*trie, unsigned const char*id) +{ + trielayer_t*t = trie->start; while(t) { if(t->rest && !strcmp(t->rest, id)) return 1; - t = t->row[id[0]]; if(!*id) return 0; - id++; + t = t->row[*id++]; + } + return 0; +} +void* trie_lookup(trie_t*trie, unsigned const char*id) +{ + trielayer_t*t = trie->start; + while(t) { + if(t->rest && !strcmp(t->rest, id)) + return t->data; + if(!*id) + return 0; + t = t->row[*id++]; } return 0; } +typedef struct _triememory { + const unsigned char*key; + void*data; + char del; // 0/1 + struct _triememory*next; +} triememory_t; + +typedef struct _trierollback { + triememory_t*ops; + struct _trierollback*prev; +} trierollback_t; + +static void trie_rollback_adds(trie_t*t, unsigned const char*id, void*data) +{ + trierollback_t*rollback = (trierollback_t*)t->rollback; + triememory_t*m = (triememory_t*)rfx_calloc(sizeof(triememory_t)); + m->key = id; + m->data = data; + m->del = 0; + m->next = rollback->ops; + rollback->ops = m; +} +static void trie_rollback_removes(trie_t*t, unsigned const char*id, void*data) +{ + trierollback_t*rollback = (trierollback_t*)t->rollback; + triememory_t*m = (triememory_t*)rfx_calloc(sizeof(triememory_t)); + m->key = id; + m->data = data; + m->del = 1; + m->next = rollback->ops; + rollback->ops = m; +} + +void _trie_dump(trielayer_t*t, char*buffer, int pos) +{ + int i; + for(i=0;i<256;i++) { + if(t->row[i]) { + buffer[pos]=i; + _trie_dump(t->row[i], buffer, pos+1); + } + } + if(t->rest) { + buffer[pos]=0; + printf("%s%s %08x\n", buffer, t->rest, t->data); + } +} + +void trie_dump(trie_t*t) +{ + char buffer[256]; + _trie_dump(t->start, buffer, 0); +} + + +void trie_remember(trie_t*t) +{ + trierollback_t*old = (trierollback_t*)t->rollback; + t->rollback = (trierollback_t*)rfx_calloc(sizeof(trierollback_t)); + ((trierollback_t*)t->rollback)->prev = old; +} + +void trie_rollback(trie_t*t) +{ + trierollback_t*rollback = (trierollback_t*)t->rollback; + if(!rollback) { + fprintf(stderr, "Internal error: can't roll back this trie any further\n"); + return; + } + t->rollback = ((trierollback_t*)t->rollback)->prev; + + triememory_t*op = rollback->ops; + while(op) { + triememory_t*next = op->next; + if(op->del) { + if(!_trie_remove(t->start, op->key)) { + fprintf(stderr, "Internal error: can't delete key %s in trie during rollback\n", op->key); + } + } else { + if(_trie_put(&t->start, op->key, op->data)) { + fprintf(stderr, "Internal error: overwrote key %s in trie during rollback\n", op->key); + } + } + free(op); + op = next; + } +} + + // ------------------------------- crc32 -------------------------------------- static unsigned int*crc32 = 0; static void crc32_init(void) @@ -764,6 +935,14 @@ void dict_init(dict_t*h, int size) h->num = 0; h->key_type = &charptr_type; } +void dict_init2(dict_t*h, type_t*t, int size) +{ + memset(h, 0, sizeof(dict_t)); + h->hashsize = size; + h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0; + h->num = 0; + h->key_type = t; +} dict_t*dict_clone(dict_t*o) { @@ -925,7 +1104,7 @@ char dict_del(dict_t*h, const void*key) memset(e, 0, sizeof(dictentry_t)); rfx_free(e); if(e == head) { - h->slots[hash] = 0; + h->slots[hash] = next; } else { assert(prev); prev->next = next; @@ -1094,7 +1273,6 @@ array_t* array_new2(type_t*type) { void*array_getkey(array_t*array, int nr) { if(nr > array->num || nr<0) { printf("error: reference to element %d in array[%d]\n", nr, array->num); - *(int*)0 = 0xdead; return 0; } return array->d[nr].name; @@ -1102,7 +1280,6 @@ void*array_getkey(array_t*array, int nr) { void*array_getvalue(array_t*array, int nr) { if(nr > array->num || nr<0) { printf("error: reference to element %d in array[%d]\n", nr, array->num); - *(int*)0 = 0xdead; return 0; } return array->d[nr].data; @@ -1275,3 +1452,4 @@ void*list_clone_(void*_list) return dest; } +