3 Part of the swftools package.
5 Copyright (c) 2001,2002,2003,2004 Matthias Kramm <kramm@quiss.org>
7 This program is rfx_free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the rfx_free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the rfx_free Software
19 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
30 // ------------------------------- malloc, alloc routines ---------------------
33 char* strdup_n(const char*str, int size)
35 char*m = (char*)rfx_alloc(size+1);
41 char*qstrdup(const char*string)
43 return strdup(string);
45 char*qstrndup(const char*string, int len)
47 return strdup_n(string, len);
50 // ------------------------------- mem_t --------------------------------------
52 void mem_init(mem_t*mem)
54 memset(mem, 0, sizeof(mem_t));
56 void mem_clear(mem_t*mem)
58 rfx_free(mem->buffer);mem->buffer = 0;
60 void mem_destroy(mem_t*mem)
65 static int mem_put_(mem_t*m,const void*data, int length, int null)
68 m->pos += length + (null?1:0);
70 m->len = (m->pos+63)&~63;
71 m->buffer = m->buffer?(char*)rfx_realloc(m->buffer,m->len):(char*)rfx_alloc(m->len);
73 assert(n+length <= m->len);
74 memcpy(&m->buffer[n], data, length);
76 m->buffer[n + length] = 0;
79 int mem_put(mem_t*m,void*data, int length)
81 return mem_put_(m, data, length, 0);
83 int mem_putstring(mem_t*m,string_t str)
85 return mem_put_(m, str.str, str.len, 1);
88 // ------------------------------- ringbuffer_t -------------------------------
90 typedef struct _ringbuffer_internal_t
96 } ringbuffer_internal_t;
98 void ringbuffer_init(ringbuffer_t*r)
100 ringbuffer_internal_t*i = (ringbuffer_internal_t*)rfx_calloc(sizeof(ringbuffer_internal_t));
101 memset(r, 0, sizeof(ringbuffer_t));
103 i->buffer = (unsigned char*)rfx_alloc(1024);
104 i->buffersize = 1024;
106 int ringbuffer_read(ringbuffer_t*r, void*buf, int len)
108 unsigned char* data = (unsigned char*)buf;
109 ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
110 if(r->available < len)
114 if(i->readpos + len > i->buffersize) {
115 int read1 = i->buffersize-i->readpos;
116 memcpy(data, &i->buffer[i->readpos], read1);
117 memcpy(&data[read1], &i->buffer[0], len - read1);
118 i->readpos = len - read1;
120 memcpy(data, &i->buffer[i->readpos], len);
122 i->readpos %= i->buffersize;
127 void ringbuffer_put(ringbuffer_t*r, void*buf, int len)
129 unsigned char* data = (unsigned char*)buf;
130 ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
132 if(i->buffersize - r->available < len)
135 int newbuffersize = i->buffersize;
136 int oldavailable = r->available;
137 newbuffersize*=3;newbuffersize/=2; /*grow at least by 50% each time */
139 if(newbuffersize < r->available + len)
140 newbuffersize = r->available + len + 1024;
142 buf2 = (unsigned char*)rfx_alloc(newbuffersize);
143 ringbuffer_read(r, buf2, r->available);
146 i->buffersize = newbuffersize;
148 i->writepos = oldavailable;
149 r->available = oldavailable;
151 if(i->writepos + len > i->buffersize) {
152 int read1 = i->buffersize-i->writepos;
153 memcpy(&i->buffer[i->writepos], data, read1);
154 memcpy(&i->buffer[0], &data[read1], len - read1);
155 i->writepos = len - read1;
157 memcpy(&i->buffer[i->writepos], data, len);
159 i->writepos %= i->buffersize;
163 void ringbuffer_clear(ringbuffer_t*r)
165 ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
166 rfx_free(i->buffer);i->buffer = 0;
170 // ------------------------------- heap_t -------------------------------
172 void heap_init(heap_t*h,int n,int elem_size, int(*compare)(const void *, const void *))
174 memset(h, 0, sizeof(heap_t));
177 h->elem_size = elem_size;
178 h->compare = compare;
179 h->elements = (void**)rfx_calloc(n*sizeof(void*));
180 h->data = (char*)rfx_calloc(h->max_size*h->elem_size);
182 void heap_clear(heap_t*h)
184 rfx_free(h->elements);
188 #define HEAP_NODE_SMALLER(h,node1,node2) ((h)->compare((node1),(node2))>0)
190 static void up(heap_t*h, int node)
192 void*node_p = h->elements[node];
198 h->elements[node] = h->elements[parent];
199 } while(HEAP_NODE_SMALLER(h,h->elements[parent], node_p));
201 h->elements[node] = node_p;
203 static void down(heap_t*h, int node)
205 void*node_p = h->elements[node];
210 /* determine new child's position */
214 if(child+1 < h->size && HEAP_NODE_SMALLER(h,h->elements[child],h->elements[child+1])) // search for bigger child
217 h->elements[node] = h->elements[child];
218 } while(HEAP_NODE_SMALLER(h,node_p, h->elements[child]));
220 h->elements[node] = node_p;
222 void heap_put(heap_t*h, void*e)
225 memcpy(&h->data[pos*h->elem_size],e,h->elem_size);
226 h->elements[pos] = &h->data[pos];
229 int heap_size(heap_t*h)
233 void* heap_max(heap_t*h)
235 return h->elements[0];
237 void* heap_chopmax(heap_t*h)
239 void*p = h->elements[0];
240 h->elements[0] = h->elements[--h->size];
244 void heap_dump(heap_t*h, FILE*fi)
247 for(t=0;t<h->size;t++) {
249 for(s=0;s<=t;s=(s+1)*2-1) {
250 if(s==t) fprintf(fi,"\n");
252 //fprintf(fi,"%d ", h->elements[t]->x); //?
255 void** heap_flatten(heap_t*h)
257 void**nodes = (void**)rfx_alloc(h->size*sizeof(void*));
261 /*printf("Heap Size: %d\n", h->size);
262 heap_print(stdout, h);
264 *p++ = heap_chopmax(h);
269 // ------------------------------- crc32 --------------------------------------
270 static unsigned int*crc32 = 0;
271 static void crc32_init(void)
276 crc32= (unsigned int*)rfx_alloc(sizeof(unsigned int)*256);
277 for(t=0; t<256; t++) {
280 for (s = 0; s < 8; s++) {
281 c = (0xedb88320L*(c&1)) ^ (c >> 1);
286 // ------------------------------- string_t -----------------------------------
288 void string_set2(string_t*str, const char*text, int len)
293 void string_set(string_t*str, const char*text)
295 str->len = strlen(text);
298 string_t string_new(const char*text, int len)
305 string_t string_new2(const char*text)
308 s.len = strlen(text);
312 char* string_cstr(string_t*str)
314 return strdup_n(str->str, str->len);
316 unsigned int string_hash(string_t*str)
319 unsigned int checksum = 0;
322 for(t=0;t<str->len;t++) {
323 checksum = checksum>>8 ^ crc32[(str->str[t]^checksum)&0xff];
327 unsigned int string_hash2(const char*str)
329 unsigned int checksum = 0;
334 checksum = checksum>>8 ^ crc32[(*p^checksum)&0xff];
339 unsigned int string_hash3(const char*str, int len)
344 return string_hash(&s);
346 void string_dup2(string_t*str, const char*text, int len)
349 str->str = strdup_n(text, len);
351 void string_dup(string_t*str, const char*text)
353 str->len = strlen(text);
354 str->str = strdup(text);
356 int string_equals(string_t*str, const char*text)
358 int l = strlen(text);
359 if(str->len == l && !memcmp(str->str, text, l))
363 int string_equals2(string_t*str, string_t*str2)
365 if(str->len == str2->len && !memcmp(str->str, str2->str, str->len))
370 // ------------------------------- stringarray_t ------------------------------
372 typedef struct _stringlist {
374 struct _stringlist*next;
377 typedef struct _stringarray_internal_t
383 } stringarray_internal_t;
385 void stringarray_init(stringarray_t*sa, int hashsize)
387 stringarray_internal_t*s;
389 sa->internal = (stringarray_internal_t*)rfx_calloc(sizeof(stringarray_internal_t));
390 s = (stringarray_internal_t*)sa->internal;
392 s->hash = rfx_calloc(sizeof(stringlist_t*)*hashsize);
393 s->hashsize = hashsize;
395 void stringarray_put(stringarray_t*sa, string_t str)
397 stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
399 int hash = string_hash(&str) % s->hashsize;
401 char*ss = string_cstr(&str);
402 mem_put(&s->pos, &ss, sizeof(char*));
404 stringlist_t*l = rfx_alloc(sizeof(stringlist_t));
406 l->next = s->hash[hash];
411 char* stringarray_at(stringarray_t*sa, int pos)
413 stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
415 if(pos<0 || pos>=s->num)
417 p = *(char**)&s->pos.buffer[pos*sizeof(char*)];
422 string_t stringarray_at2(stringarray_t*sa, int pos)
425 s.str = stringarray_at(sa, pos);
426 s.len = s.str?strlen(s.str):0;
429 static stringlist_t* stringlist_del(stringarray_t*sa, stringlist_t*l, int index)
432 stringlist_t*old = l;
434 if(index==l->index) {
436 memset(l, 0, sizeof(stringlist_t));
446 fprintf(stderr, "Internal error: did not find string %d in hash\n", index);
450 void stringarray_del(stringarray_t*sa, int pos)
452 stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
453 string_t str = stringarray_at2(sa, pos);
454 int hash = string_hash(&str) % s->hashsize;
455 s->hash[hash] = stringlist_del(sa, s->hash[hash], pos);
456 *(char**)&s->pos.buffer[pos*sizeof(char*)] = 0;
458 int stringarray_find(stringarray_t*sa, string_t* str)
460 stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
461 int hash = string_hash(str) % s->hashsize;
463 stringlist_t*l = s->hash[hash];
466 string_t s = stringarray_at2(sa, l->index);
467 if(string_equals2(str, &s)) {
474 void stringarray_clear(stringarray_t*sa)
476 stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
479 for(t=0;t<s->hashsize;t++) {
480 stringlist_t*l = s->hash[t];
482 stringlist_t*next = l->next;
483 memset(l, 0, sizeof(stringlist_t));
488 rfx_free(s->hash);s->hash=0;
491 void stringarray_destroy(stringarray_t*sa)
493 stringarray_clear(sa);
498 // ------------------------------- dictionary_t -------------------------------
500 #define INITIAL_SIZE 1
502 static int max(int x, int y) {
508 dict_t*d = rfx_alloc(sizeof(dict_t));
512 void dict_init(dict_t*h)
514 memset(h, 0, sizeof(dict_t));
515 h->hashsize = INITIAL_SIZE;
516 h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0;
519 static void dict_expand(dict_t*h, int newlen)
521 assert(h->hashsize < newlen);
522 dictentry_t**newslots = (dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*newlen);
524 for(t=0;t<h->hashsize;t++) {
525 dictentry_t*e = h->slots[t];
527 dictentry_t*next = e->next;
528 unsigned int newhash = e->hash%newlen;
529 e->next = newslots[newhash];
530 newslots[newhash] = e;
537 h->hashsize = newlen;
539 void dict_put(dict_t*h, string_t s, void* data)
541 /* TODO: should we look for duplicates here? */
542 unsigned int hash = string_hash(&s);
543 dictentry_t*e = (dictentry_t*)rfx_alloc(sizeof(dictentry_t));
545 unsigned int hash2 = string_hash(&s) % h->hashsize;
546 char*sdata = rfx_alloc(s.len);
547 memcpy(sdata, s.str, s.len);
550 e->hash = hash; //for resizing
551 e->next = h->slots[hash2];
556 void dict_put2(dict_t*h, const char*s, void*data)
560 dict_put(h, s2, data);
562 void dict_put3(dict_t*h, const char* s, int len, void*data)
565 string_set2(&s3, s, len);
566 dict_put(h, s3, data);
568 void dict_dump(dict_t*h, FILE*fi, const char*prefix)
571 for(t=0;t<h->hashsize;t++) {
572 dictentry_t*e = h->slots[t];
574 char*s = strdup_n(e->s, e->len);
575 fprintf(fi, "%s%s=%08x\n", prefix, e->s, e->data);
581 int dict_count(dict_t*h)
585 void* dict_lookup2(dict_t*h, const char*s, int len)
590 unsigned int ohash = string_hash2(s);
591 unsigned int hash = ohash % h->hashsize;
593 /* check first entry for match */
594 dictentry_t*e = h->slots[hash];
595 if(e && e->len == len && !memcmp(e->s, s, len)) {
601 /* if dict is 2/3 filled, double the size. Do
602 this the first time we have to actually iterate
603 through a slot to find our data */
604 if(e && h->num*3 >= h->hashsize*2) {
605 int newsize = h->hashsize;
606 while(h->num*3 >= newsize*2) {
607 newsize = newsize<15?15:(newsize+1)*2-1;
609 dict_expand(h, newsize);
610 hash = ohash % h->hashsize;
614 /* check subsequent entries for a match */
616 if(e->len == len && !memcmp(e->s, s, len)) {
623 void* dict_lookup(dict_t*h, const char*s)
626 return dict_lookup2(h, s, l);
628 char dict_del(dict_t*h, const char*s)
632 unsigned int hash = string_hash2(s) % h->hashsize;
634 dictentry_t*head = h->slots[hash];
635 dictentry_t*e = head, *prev=0;
637 if(e->len ==l && !memcmp(e->s, s, l)) {
638 dictentry_t*next = e->next;
639 rfx_free((void*)e->s);
640 memset(e, 0, sizeof(dictentry_t));
656 void dict_foreach_keyvalue(dict_t*h, void (*runFunction)(void*data, const char*key, void*val), void*data)
659 for(t=0;t<h->hashsize;t++) {
660 dictentry_t*e = h->slots[t];
662 dictentry_t*next = e->next;
664 char*s = strdup_n(e->s, e->len); //append \0
665 runFunction(data, s, e->data);
672 void dict_foreach_value(dict_t*h, void (*runFunction)(void*))
675 for(t=0;t<h->hashsize;t++) {
676 dictentry_t*e = h->slots[t];
678 dictentry_t*next = e->next;
680 runFunction(e->data);
686 void dict_free_all(dict_t*h, void (*freeFunction)(void*))
689 for(t=0;t<h->hashsize;t++) {
690 dictentry_t*e = h->slots[t];
692 dictentry_t*next = e->next;
693 rfx_free((void*)e->s);
695 freeFunction(e->data);
697 memset(e, 0, sizeof(dictentry_t));
703 memset(h, 0, sizeof(dict_t));
705 void dict_clear(dict_t*h)
709 void dict_destroy(dict_t*dict)
715 // ------------------------------- map_t --------------------------------------
717 typedef struct _map_internal_t
722 void map_init(map_t*map)
725 map->internal = (map_internal_t*)rfx_calloc(sizeof(map_internal_t));
726 m = (map_internal_t*)map->internal;
729 void map_put(map_t*map, string_t t1, string_t t2)
731 map_internal_t*m = (map_internal_t*)map->internal;
733 char* s1 = string_cstr(&t1);
734 dict_put2(&m->d, s1, (void*)string_cstr(&t2));
737 const char* map_lookup(map_t*map, const char*name)
739 map_internal_t*m = (map_internal_t*)map->internal;
740 const char*value = dict_lookup(&m->d, name);
743 static void freestring(void*data)
747 static void dumpmapentry(void*data, const char*key, void*value)
749 FILE*fi = (FILE*)data;
750 fprintf(fi, "%s=%s\n", key, (char*)value);
752 void map_dump(map_t*map, FILE*fi, const char*prefix)
755 map_internal_t*m = (map_internal_t*)map->internal;
756 dict_foreach_keyvalue(&m->d, dumpmapentry, fi);
758 void map_clear(map_t*map)
760 map_internal_t*m = (map_internal_t*)map->internal;
761 dict_free_all(&m->d, freestring);
764 void map_destroy(map_t*map)