X-Git-Url: http://git.asbjorn.biz/?a=blobdiff_plain;f=lib%2Fq.c;h=b1553b5a126af3f335ddb517199f538d388135e2;hb=bb864e1a88e670c99d559c7dee4f74e9bf7d978b;hp=0d0d944529a40e7681b9ab895d99c39b26be1e23;hpb=35bef20c4bea1a43ea4072f0ea7ff5bbc68412ee;p=swftools.git diff --git a/lib/q.c b/lib/q.c index 0d0d944..b1553b5 100644 --- a/lib/q.c +++ b/lib/q.c @@ -68,7 +68,9 @@ static int mem_put_(mem_t*m,const void*data, int length, int null) int n = m->pos; m->pos += length + (null?1:0); if(m->pos > m->len) { - m->len = (m->pos+63)&~63; + int v1 = (m->pos+63)&~63; + int v2 = m->len + m->len / 2; + m->len = v1>v2?v1:v2; m->buffer = m->buffer?(char*)rfx_realloc(m->buffer,m->len):(char*)rfx_alloc(m->len); } assert(n+length <= m->len); @@ -85,6 +87,15 @@ int mem_putstring(mem_t*m,string_t str) { return mem_put_(m, str.str, str.len, 1); } +int mem_get(mem_t*m, void*data, int length) +{ + if(m->read_pos + length > m->pos) { + length = m->pos - m->read_pos; + } + memcpy(data, m->buffer+m->read_pos, length); + m->read_pos += length; + return length; +} // ------------------------------- ringbuffer_t ------------------------------- @@ -267,6 +278,54 @@ void** heap_flatten(heap_t*h) return nodes; } +// ------------------------------- trie -------------------------------------- + +void trie_put(trie_t**t, unsigned const char*id) +{ + if(!*t) { + (*t) = rfx_calloc(sizeof(trie_t)); + (*t)->rest = (unsigned char*)strdup(id); + return; + } + 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); + (*t)->rest = 0; + } + if(id[0]) { + trie_put(&(*t)->row[id[0]], id+1); + } else { + (*t)->rest = strdup(""); + } +} + +int trie_lookup(trie_t*t, unsigned const char*id) +{ + while(t) { + if(t->rest && !strcmp(t->rest, id)) + return 1; + if(!*id) + return 0; + t = t->row[*id++]; + } + return 0; +} + +char trie_remove(trie_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++]; + } +} + + // ------------------------------- crc32 -------------------------------------- static unsigned int*crc32 = 0; static void crc32_init(void) @@ -318,10 +377,72 @@ string_t string_new2(const char*text) s.str = text; return s; } +string_t* string_new3(const char*text, int len) +{ + if(!text) { + string_t*s = malloc(sizeof(string_t)); + s->len = 0; + s->str = 0; + return s; + } else { + string_t*s = malloc(sizeof(string_t)+len+1); + s->len = len; + s->str = (const char*)(s+1); + memcpy((char*)s->str, text, len); + ((char*)s->str)[len]=0; + return s; + } +} +string_t* string_new4(const char*text) +{ + int l = strlen(text); + return string_new3(text, l); +} + +void string_free(string_t*s) +{ + if(!s) + return; + s->len = 0; + if((string_t*)(s->str) == s+1) { + s->str = 0; + rfx_free(s); + } else { + rfx_free((char*)(s->str)); + s->str = 0; + rfx_free(s); + } +} char* string_cstr(string_t*str) { return strdup_n(str->str, str->len); } +char* string_escape(string_t*str) +{ + int t; + int len = 0; + for(t=0;tlen;t++) { + if(str->str[t]<0x20) + len+=3; + else + len++; + } + char*s = malloc(len+1); + char*p=s; + for(t=0;tlen;t++) { + if(str->str[t]<0x20) { + *p++ ='\\'; + unsigned char c = str->str[t]; + *p++ = "0123456789abcdef"[c>>4]; + *p++ = "0123456789abcdef"[c&0x0f]; + } else { + *p++ = str->str[t]; + } + } + *p++ = 0; + assert(p == &s[len+1]); + return s; +} unsigned int crc32_add_byte(unsigned int checksum, unsigned char b) { @@ -331,10 +452,12 @@ unsigned int crc32_add_byte(unsigned int checksum, unsigned char b) } unsigned int crc32_add_string(unsigned int checksum, const char*s) { + if(!crc32) + crc32_init(); if(!s) return checksum; while(*s) { - checksum = crc32_add_byte(checksum, *s); + checksum = checksum>>8 ^ crc32[(*s^checksum)&0xff]; s++; } return checksum; @@ -523,6 +646,23 @@ void stringarray_destroy(stringarray_t*sa) // ------------------------------- type_t ------------------------------- +char ptr_equals(const void*o1, const void*o2) +{ + return o1==o2; +} +unsigned int ptr_hash(const void*o) +{ + return string_hash3((const char*)&o, sizeof(o)); +} +void* ptr_dup(const void*o) +{ + return (void*)o; +} +void ptr_free(void*o) +{ + return; +} + char charptr_equals(const void*o1, const void*o2) { if(!o1 || !o2) @@ -547,8 +687,11 @@ void charptr_free(void*o) rfx_free(o); } } + char stringstruct_equals(const void*o1, const void*o2) { + if(!o1 || !o2) + return o1==o2; string_t*s1 = (string_t*)o1; string_t*s2 = (string_t*)o2; int l = s1->lenlen?s1->len:s2->len; @@ -560,20 +703,37 @@ char stringstruct_equals(const void*o1, const void*o2) } unsigned int stringstruct_hash(const void*o) { + if(!o) return 0; return string_hash(o); } -void*stringstruct_dup(const void*o) +string_t*string_dup3(string_t*o) { - string_t*s = malloc(sizeof(string_t)); - string_set2(s, ((string_t*)o)->str, ((string_t*)o)->len); + if(!o) return 0; + if(!o->str) { + string_t*s = malloc(sizeof(string_t)); + s->str=0; + s->len=0; + return s; + } + string_t*s = rfx_alloc(sizeof(string_t)+o->len+1); + s->len = o->len; + s->str = (const char*)(s+1); + memcpy((char*)s->str, o->str, s->len); + ((char*)s->str)[s->len]=0; return s; } void stringstruct_free(void*o) { - rfx_free((void*)(((string_t*)o)->str)); - rfx_free((void*)o); + if(o) + string_free(o); } +type_t ptr_type = { + equals: ptr_equals, + hash: ptr_hash, + dup: ptr_dup, + free: ptr_free, +}; type_t charptr_type = { equals: charptr_equals, @@ -585,7 +745,7 @@ type_t charptr_type = { type_t stringstruct_type = { equals: stringstruct_equals, hash: stringstruct_hash, - dup: stringstruct_dup, + dup: (dup_func)string_dup3, free: stringstruct_free, }; @@ -618,6 +778,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) { @@ -625,14 +793,16 @@ dict_t*dict_clone(dict_t*o) memcpy(h, o, sizeof(dict_t)); h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0; int t; - for(t=0;thashsize;t++) { - dictentry_t*e = h->slots[t]; + for(t=0;thashsize;t++) { + dictentry_t*e = o->slots[t]; while(e) { dictentry_t*n = (dictentry_t*)rfx_alloc(sizeof(dictentry_t)); memcpy(n, e, sizeof(dictentry_t)); - n->data = h->key_type->dup(e->data); + n->key = h->key_type->dup(e->key); + n->data = e->data; n->next = h->slots[t]; h->slots[t] = n; + e = e->next; } } return h; @@ -684,7 +854,7 @@ void dict_dump(dict_t*h, FILE*fi, const char*prefix) for(t=0;thashsize;t++) { dictentry_t*e = h->slots[t]; while(e) { - if(h->key_type==&charptr_type) { + if(h->key_type!=&charptr_type) { fprintf(fi, "%s%08x=%08x\n", prefix, e->key, e->data); } else { fprintf(fi, "%s%s=%08x\n", prefix, e->key, e->data); @@ -699,10 +869,11 @@ int dict_count(dict_t*h) return h->num; } -void* dict_lookup(dict_t*h, const void*key) +static inline dictentry_t* dict_do_lookup(dict_t*h, const void*key) { - if(!h->num) + if(!h->num) { return 0; + } unsigned int ohash = h->key_type->hash(key); unsigned int hash = ohash % h->hashsize; @@ -710,7 +881,7 @@ void* dict_lookup(dict_t*h, const void*key) /* check first entry for match */ dictentry_t*e = h->slots[hash]; if(e && h->key_type->equals(e->key, key)) { - return e->data; + return e; } else if(e) { e = e->next; } @@ -726,17 +897,42 @@ void* dict_lookup(dict_t*h, const void*key) dict_expand(h, newsize); hash = ohash % h->hashsize; e = h->slots[hash]; + if(e && h->key_type->equals(e->key, key)) { + // omit move to front + return e; + } else if(e) { + e = e->next; + } } /* check subsequent entries for a match */ + dictentry_t*last = h->slots[hash]; while(e) { if(h->key_type->equals(e->key, key)) { - return e->data; + /* move to front- makes a difference of about 10% in most applications */ + last->next = e->next; + e->next = h->slots[hash]; + h->slots[hash] = e; + return e; } + last=e; e = e->next; } return 0; } +void* dict_lookup(dict_t*h, const void*key) +{ + dictentry_t*e = dict_do_lookup(h, key); + if(e) + return e->data; + return 0; +} +char dict_contains(dict_t*h, const void*key) +{ + dictentry_t*e = dict_do_lookup(h, key); + return !!e; +} + char dict_del(dict_t*h, const void*key) { if(!h->num) @@ -751,7 +947,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; @@ -803,16 +999,18 @@ void dict_foreach_value(dict_t*h, void (*runFunction)(void*)) } } -void dict_free_all(dict_t*h, void (*freeFunction)(void*)) +void dict_free_all(dict_t*h, char free_keys, void (*free_data_function)(void*)) { int t; for(t=0;thashsize;t++) { dictentry_t*e = h->slots[t]; while(e) { dictentry_t*next = e->next; - h->key_type->free(e->key); - if(freeFunction) { - freeFunction(e->data); + if(free_keys) { + h->key_type->free(e->key); + } + if(free_data_function) { + free_data_function(e->data); } memset(e, 0, sizeof(dictentry_t)); rfx_free(e); @@ -824,9 +1022,20 @@ void dict_free_all(dict_t*h, void (*freeFunction)(void*)) memset(h, 0, sizeof(dict_t)); } +void dict_clear_shallow(dict_t*h) +{ + dict_free_all(h, 0, 0); +} + void dict_clear(dict_t*h) { - dict_free_all(h, 0); + dict_free_all(h, 1, 0); +} + +void dict_destroy_shallow(dict_t*dict) +{ + dict_clear_shallow(dict); + rfx_free(dict); } void dict_destroy(dict_t*dict) @@ -881,7 +1090,7 @@ void map_dump(map_t*map, FILE*fi, const char*prefix) void map_clear(map_t*map) { map_internal_t*m = (map_internal_t*)map->internal; - dict_free_all(&m->d, freestring); + dict_free_all(&m->d, 1, freestring); rfx_free(m); } void map_destroy(map_t*map) @@ -907,7 +1116,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; @@ -915,7 +1123,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; @@ -1002,6 +1209,20 @@ int list_length_(void*_list) return 0; return l->info[0].size; } +void list_concat_(void*_l1, void*_l2) +{ + commonlist_t**l1 = (commonlist_t**)_l1; + commonlist_t**l2 = (commonlist_t**)_l2; + + if(!*l1) { + *l1 = *l2; + } else if(*l2) { + (*l1)->info[0].last->next = *l2; + (*l1)->info[0].last = (*l2)->info[0].last; + (*l1)->info[0].size += (*l2)->info[0].size; + } + *l2 = 0; +} void list_append_(void*_list, void*entry) { commonlist_t**list = (commonlist_t**)_list; @@ -1047,6 +1268,20 @@ void list_free_(void*_list) } *list = 0; } +void list_deep_free_(void*_list) +{ + commonlist_t**list = (commonlist_t**)_list; + commonlist_t*l = *list; + while(l) { + commonlist_t*next = l->next; + if(l->entry) { + free(l->entry);l->entry=0; + } + free(l); + l = next; + } + *list = 0; +} void*list_clone_(void*_list) { commonlist_t*l = *(commonlist_t**)_list;