1 /* q.c
2 
3    Part of the swftools package.
4 
5    Copyright (c) 2001,2002,2003,2004 Matthias Kramm <kramm@quiss.org>
6 
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.
11 
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.
16 
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 */
20 
21 
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <stdarg.h>
25 #include <string.h>
26 #include <assert.h>
27 #include <memory.h>
28 #include "mem.h"
29 #include "types.h"
30 #include "q.h"
31 
32 // ------------------------------- malloc, alloc routines ---------------------
33 
34 #ifndef STRNDUP
strdup_n(const char * str,int size)35 char* strdup_n(const char*str, int size)
36 {
37     char*m = (char*)rfx_alloc(size+1);
38     memcpy(m, str, size);
39     m[size] = 0;
40     return m;
41 }
42 #endif
qstrdup(const char * string)43 char*qstrdup(const char*string)
44 {
45     return strdup(string);
46 }
qstrndup(const char * string,int len)47 char*qstrndup(const char*string, int len)
48 {
49     return strdup_n(string, len);
50 }
allocprintf(const char * format,...)51 char* allocprintf(const char*format, ...)
52 {
53     va_list arglist1;
54     va_start(arglist1, format);
55     char dummy;
56     int l = vsnprintf(&dummy, 1, format, arglist1);
57     va_end(arglist1);
58 
59     va_list arglist2;
60     va_start(arglist2, format);
61     char*buf = malloc(l+1);
62     vsnprintf(buf, l+1, format, arglist2);
63     va_end(arglist2);
64     return buf;
65 }
66 
67 // ------------------------------- mem_t --------------------------------------
68 
mem_init(mem_t * mem)69 void mem_init(mem_t*mem)
70 {
71     memset(mem, 0, sizeof(mem_t));
72 }
mem_clear(mem_t * mem)73 void mem_clear(mem_t*mem)
74 {
75     rfx_free(mem->buffer);mem->buffer = 0;
76 }
mem_destroy(mem_t * mem)77 void mem_destroy(mem_t*mem)
78 {
79     mem_clear(mem);
80     rfx_free(mem);
81 }
mem_put_(mem_t * m,const void * data,int length,int null)82 static int mem_put_(mem_t*m,const void*data, int length, int null)
83 {
84     int n = m->pos;
85     m->pos += length + (null?1:0);
86     if(m->pos > m->len) {
87         int v1 = (m->pos+63)&~63;
88         int v2 = m->len + m->len / 2;
89         m->len = v1>v2?v1:v2;
90 	m->buffer = m->buffer?(char*)rfx_realloc(m->buffer,m->len):(char*)rfx_alloc(m->len);
91     }
92     assert(n+length <= m->len);
93     memcpy(&m->buffer[n], data, length);
94     if(null)
95 	m->buffer[n + length] = 0;
96     return n;
97 }
mem_put(mem_t * m,void * data,int length)98 int mem_put(mem_t*m,void*data, int length)
99 {
100     return mem_put_(m, data, length, 0);
101 }
mem_putstring(mem_t * m,string_t str)102 int mem_putstring(mem_t*m,string_t str)
103 {
104     return mem_put_(m, str.str, str.len, 1);
105 }
mem_get(mem_t * m,void * data,int length)106 int mem_get(mem_t*m, void*data, int length)
107 {
108     if(m->read_pos + length > m->pos) {
109         length = m->pos - m->read_pos;
110     }
111     memcpy(data, m->buffer+m->read_pos, length);
112     m->read_pos += length;
113     return length;
114 }
115 
116 // ------------------------------- median -------------------------------------
117 
medianf(float * a,int n)118 float medianf(float*a, int n)
119 {
120     int i,j,l,m;
121     float x;
122     int k=n&1?n/2:n/2-1;
123     l=0;
124     m=n-1;
125     while(l<m) {
126         x=a[k];
127         i=l;j=m;
128         do {
129             while(a[i]<x) i++;
130             while(x<a[j]) j--;
131             if(i<=j) {
132 		//swap
133 		float t = a[i];
134 		a[i] = a[j];
135 		a[j] = t;
136                 i++;
137 		j--;
138             }
139         } while(i<=j);
140         if(j<k) l=i;
141         if(k<i) m=j;
142     }
143     return a[k];
144 }
145 
146 // ------------------------------- ringbuffer_t -------------------------------
147 
148 typedef struct _ringbuffer_internal_t
149 {
150     unsigned char*buffer;
151     int readpos;
152     int writepos;
153     int buffersize;
154 } ringbuffer_internal_t;
155 
ringbuffer_init(ringbuffer_t * r)156 void ringbuffer_init(ringbuffer_t*r)
157 {
158     ringbuffer_internal_t*i = (ringbuffer_internal_t*)rfx_calloc(sizeof(ringbuffer_internal_t));
159     memset(r, 0, sizeof(ringbuffer_t));
160     r->internal = i;
161     i->buffer = (unsigned char*)rfx_alloc(1024);
162     i->buffersize = 1024;
163 }
ringbuffer_read(ringbuffer_t * r,void * buf,int len)164 int ringbuffer_read(ringbuffer_t*r, void*buf, int len)
165 {
166     unsigned char* data = (unsigned char*)buf;
167     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
168     if(r->available < len)
169 	len = r->available;
170     if(!len)
171 	return 0;
172     if(i->readpos + len > i->buffersize) {
173 	int read1 = i->buffersize-i->readpos;
174 	memcpy(data, &i->buffer[i->readpos], read1);
175 	memcpy(&data[read1], &i->buffer[0], len - read1);
176 	i->readpos = len - read1;
177     } else {
178 	memcpy(data, &i->buffer[i->readpos], len);
179 	i->readpos += len;
180 	i->readpos %= i->buffersize;
181     }
182     r->available -= len;
183     return len;
184 }
ringbuffer_put(ringbuffer_t * r,void * buf,int len)185 void ringbuffer_put(ringbuffer_t*r, void*buf, int len)
186 {
187     unsigned char* data = (unsigned char*)buf;
188     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
189 
190     if(i->buffersize - r->available < len)
191     {
192 	unsigned char* buf2;
193 	int newbuffersize = i->buffersize;
194 	int oldavailable = r->available;
195 	newbuffersize*=3;newbuffersize/=2; /*grow at least by 50% each time */
196 
197 	if(newbuffersize < r->available + len)
198 	    newbuffersize = r->available + len + 1024;
199 
200 	buf2 = (unsigned char*)rfx_alloc(newbuffersize);
201 	ringbuffer_read(r, buf2, r->available);
202 	rfx_free(i->buffer);
203 	i->buffer = buf2;
204 	i->buffersize = newbuffersize;
205 	i->readpos = 0;
206 	i->writepos = oldavailable;
207 	r->available = oldavailable;
208     }
209     if(i->writepos + len > i->buffersize) {
210 	int read1 = i->buffersize-i->writepos;
211 	memcpy(&i->buffer[i->writepos], data, read1);
212 	memcpy(&i->buffer[0], &data[read1], len - read1);
213 	i->writepos = len - read1;
214     } else {
215 	memcpy(&i->buffer[i->writepos], data, len);
216 	i->writepos += len;
217 	i->writepos %= i->buffersize;
218     }
219     r->available += len;
220 }
ringbuffer_clear(ringbuffer_t * r)221 void ringbuffer_clear(ringbuffer_t*r)
222 {
223     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
224     rfx_free(i->buffer);i->buffer = 0;
225     rfx_free(i);
226 }
227 
228 // ------------------------------- heap_t -------------------------------
229 
heap_init(heap_t * h,int elem_size,int (* compare)(const void *,const void *))230 void heap_init(heap_t*h,int elem_size, int(*compare)(const void *, const void *))
231 {
232     memset(h, 0, sizeof(heap_t));
233     h->size = 0;
234     h->elem_size = elem_size;
235     h->compare = compare;
236     h->elements = 0;
237     h->max_size = 0;
238 }
heap_new(int elem_size,int (* compare)(const void *,const void *))239 heap_t* heap_new(int elem_size, int(*compare)(const void *, const void *))
240 {
241     heap_t*h = malloc(sizeof(heap_t));
242     heap_init(h, elem_size, compare);
243     return h;
244 }
heap_clone(heap_t * o)245 heap_t* heap_clone(heap_t*o)
246 {
247     heap_t*h = malloc(sizeof(heap_t));
248     memcpy(h, o, sizeof(heap_t));
249     h->elements = rfx_alloc(sizeof(void*)*h->size);
250     int t;
251     for(t=0;t<h->size;t++) {
252         h->elements[t] = rfx_alloc(h->elem_size);
253         memcpy(h->elements[t], o->elements[t], h->elem_size);
254     }
255     return h;
256 }
heap_clear(heap_t * h)257 void heap_clear(heap_t*h)
258 {
259     int t;
260     for(t=0;t<h->size;t++) {
261         rfx_free(h->elements[t]);
262         h->elements[t]=0;
263     }
264     rfx_free(h->elements);
265 }
heap_destroy(heap_t * h)266 void heap_destroy(heap_t*h)
267 {
268     heap_clear(h);
269     free(h);
270 }
271 
272 #define HEAP_NODE_LARGER(h,node1,node2) ((h)->compare((node1),(node2))>0)
273 #define HEAP_NODE_SMALLER(h,node1,node2) ((h)->compare((node1),(node2))<0)
274 
up(heap_t * h,int node)275 static void up(heap_t*h, int node)
276 {
277     void*node_p = h->elements[node];
278     int parent = node;
279     int tmp = node;
280     do {
281 	node = parent;
282 	if(!node) break;
283 	parent = (node-1)/2;
284 	h->elements[node] = h->elements[parent];
285     } while(HEAP_NODE_SMALLER(h, h->elements[parent], node_p));
286     h->elements[node] = node_p;
287 }
down(heap_t * h,int node)288 static void down(heap_t*h, int node)
289 {
290     void*node_p = h->elements[node];
291     int child = node;
292     do {
293 	node = child;
294 
295 	/* determine new child's position */
296 	child = node<<1|1;
297 	if(child >= h->size)
298             break;
299         if(child+1 < h->size && HEAP_NODE_SMALLER(h,h->elements[child],h->elements[child+1])) // search for bigger child
300 	    child++;
301 
302 	h->elements[node] = h->elements[child];
303     } while(HEAP_NODE_SMALLER(h,node_p, h->elements[child]));
304 
305     h->elements[node] = node_p;
306 }
heap_put(heap_t * h,void * e)307 void heap_put(heap_t*h, void*e)
308 {
309     int pos = h->size++;
310     void*data = rfx_alloc(h->elem_size);
311     memcpy(data,e,h->elem_size);
312 
313     if(pos>=h->max_size) {
314         h->max_size = h->max_size<15?15:(h->max_size+1)*2-1;
315         h->elements = (void**)rfx_realloc(h->elements, h->max_size*sizeof(void*));
316         assert(pos<h->max_size);
317     }
318 
319     h->elements[pos] = data;
320     up(h, pos);
321 }
heap_size(heap_t * h)322 int heap_size(heap_t*h)
323 {
324     return h->size;
325 }
heap_peek(heap_t * h)326 void* heap_peek(heap_t*h)
327 {
328     if(!h || !h->size)
329         return 0;
330     return h->elements[0];
331 }
heap_chopmax(heap_t * h)332 void* heap_chopmax(heap_t*h)
333 {
334     if(!h->size)
335         return 0;
336     void*p = h->elements[0];
337     h->elements[0] = h->elements[--h->size];
338     down(h,0);
339     return p;
340 }
heap_dump(heap_t * h,FILE * fi)341 void heap_dump(heap_t*h, FILE*fi)
342 {
343     int t;
344     for(t=0;t<h->size;t++) {
345 	int s;
346 	for(s=0;s<=t;s=(s+1)*2-1) {
347 	    if(s==t) fprintf(fi,"\n");
348 	}
349 	//fprintf(fi,"%d ", h->elements[t]->x); //?
350     }
351 }
heap_flatten(heap_t * h)352 void** heap_flatten(heap_t*h)
353 {
354     void**nodes = (void**)rfx_alloc((h->size+1)*sizeof(void*));
355     void**p = nodes;
356 
357     while(h->size) {
358 	/*printf("Heap Size: %d\n", h->size);
359 	heap_print(stdout, h);
360 	printf("\n");*/
361 	*p++ = heap_chopmax(h);
362     }
363     *p++ = 0;
364     return nodes;
365 }
366 
367 // ------------------------------- trie --------------------------------------
368 
trie_new()369 trie_t*trie_new()
370 {
371     return (trie_t*)rfx_calloc(sizeof(trie_t));
372 }
_trie_put(trielayer_t ** t,unsigned const char * id,void * data)373 static char _trie_put(trielayer_t**t, unsigned const char*id, void*data)
374 {
375     if(!*t) {
376         (*t) = rfx_calloc(sizeof(trielayer_t));
377         (*t)->rest = (unsigned char*)strdup((char*)id);
378         (*t)->data = data;
379         return 0;
380     }
381     if((*t)->rest && (*t)->rest[0]) {
382         // make room: shift whatever's currently in here one node down
383         _trie_put(&(*t)->row[(*t)->rest[0]], (*t)->rest+1, (*t)->data);
384         (*t)->rest = 0;
385     }
386     if(id[0]) {
387         return _trie_put(&(*t)->row[id[0]], id+1, data);
388     } else {
389         char overwrite = 0;
390         if((*t)->rest)
391             overwrite = 1;
392         (*t)->rest = (unsigned char*)strdup("");
393         (*t)->data = data;
394         return overwrite;
395     }
396 }
_trie_remove(trielayer_t * t,unsigned const char * id)397 static char _trie_remove(trielayer_t*t, unsigned const char*id)
398 {
399     while(t) {
400         if(t->rest && !strcmp((char*)t->rest, (char*)id)) {
401             free(t->rest);
402             t->rest = 0;
403             return 1;
404         }
405         if(!*id)
406             return 0;
407         t = t->row[*id++];
408     }
409     return 0;
410 }
411 
412 static void trie_rollback_removes(trie_t*t, unsigned const char*id, void*data);
413 static void trie_rollback_adds(trie_t*t, unsigned const char*id, void*data);
414 
trie_put(trie_t * t,unsigned const char * id,void * data)415 void trie_put(trie_t*t, unsigned const char*id, void*data)
416 {
417     if(!t->rollback) {
418         _trie_put(&t->start, id, data);
419     } else {
420         char contains = trie_contains(t, id);
421         void*olddata = contains?trie_lookup(t, id):0;
422         _trie_put(&t->start, id, data);
423         if(contains) {
424             trie_rollback_adds(t, id, olddata);
425         }
426         trie_rollback_removes(t, id, data);
427     }
428 }
trie_remove(trie_t * t,unsigned const char * id)429 char trie_remove(trie_t*t, unsigned const char*id)
430 {
431     if(!t->rollback) {
432         return _trie_remove(t->start, id);
433     } else {
434         void*olddata = trie_lookup(t, id);
435         char exists = _trie_remove(t->start, id);
436         if(exists) {
437             trie_rollback_adds(t, id, olddata);
438         }
439         return exists;
440     }
441 }
trie_contains(trie_t * trie,unsigned const char * id)442 int trie_contains(trie_t*trie, unsigned const char*id)
443 {
444     trielayer_t*t = trie->start;
445     while(t) {
446         if(t->rest && !strcmp((char*)t->rest, (char*)id))
447             return 1;
448         if(!*id)
449             return 0;
450         t = t->row[*id++];
451     }
452     return 0;
453 }
trie_lookup(trie_t * trie,unsigned const char * id)454 void* trie_lookup(trie_t*trie, unsigned const char*id)
455 {
456     trielayer_t*t = trie->start;
457     while(t) {
458         if(t->rest && !strcmp((char*)t->rest, (char*)id))
459             return t->data;
460         if(!*id)
461             return 0;
462         t = t->row[*id++];
463     }
464     return 0;
465 }
466 
467 typedef struct _triememory {
468     const unsigned char*key;
469     void*data;
470     char del; // 0/1
471     struct _triememory*next;
472 } triememory_t;
473 
474 typedef struct _trierollback {
475     triememory_t*ops;
476     struct _trierollback*prev;
477 } trierollback_t;
478 
trie_rollback_adds(trie_t * t,unsigned const char * id,void * data)479 static void trie_rollback_adds(trie_t*t, unsigned const char*id, void*data)
480 {
481     trierollback_t*rollback = (trierollback_t*)t->rollback;
482     triememory_t*m = (triememory_t*)rfx_calloc(sizeof(triememory_t));
483     m->key = id;
484     m->data = data;
485     m->del = 0;
486     m->next = rollback->ops;
487     rollback->ops = m;
488 }
trie_rollback_removes(trie_t * t,unsigned const char * id,void * data)489 static void trie_rollback_removes(trie_t*t, unsigned const char*id, void*data)
490 {
491     trierollback_t*rollback = (trierollback_t*)t->rollback;
492     triememory_t*m = (triememory_t*)rfx_calloc(sizeof(triememory_t));
493     m->key = id;
494     m->data = data;
495     m->del = 1;
496     m->next = rollback->ops;
497     rollback->ops = m;
498 }
499 
_trie_dump(trielayer_t * t,char * buffer,int pos)500 void _trie_dump(trielayer_t*t, char*buffer, int pos)
501 {
502     int i;
503     for(i=0;i<256;i++) {
504         if(t->row[i]) {
505             buffer[pos]=i;
506             _trie_dump(t->row[i], buffer, pos+1);
507         }
508     }
509     if(t->rest) {
510         buffer[pos]=0;
511         printf("%s%s %08x\n", buffer, t->rest, (int)t->data);
512     }
513 }
514 
trie_dump(trie_t * t)515 void trie_dump(trie_t*t)
516 {
517     char buffer[256];
518     _trie_dump(t->start, buffer, 0);
519 }
520 
521 
trie_remember(trie_t * t)522 void trie_remember(trie_t*t)
523 {
524     trierollback_t*old = (trierollback_t*)t->rollback;
525     t->rollback = (trierollback_t*)rfx_calloc(sizeof(trierollback_t));
526     ((trierollback_t*)t->rollback)->prev = old;
527 }
528 
trie_rollback(trie_t * t)529 void trie_rollback(trie_t*t)
530 {
531     trierollback_t*rollback = (trierollback_t*)t->rollback;
532     if(!rollback) {
533         fprintf(stderr, "Internal error: can't roll back this trie any further\n");
534         return;
535     }
536     t->rollback = ((trierollback_t*)t->rollback)->prev;
537 
538     triememory_t*op = rollback->ops;
539     while(op) {
540         triememory_t*next = op->next;
541         if(op->del) {
542             if(!_trie_remove(t->start, op->key)) {
543                 fprintf(stderr, "Internal error: can't delete key %s in trie during rollback\n", op->key);
544             }
545         } else {
546             if(_trie_put(&t->start, op->key, op->data)) {
547                 fprintf(stderr, "Internal error: overwrote key %s in trie during rollback\n", op->key);
548             }
549         }
550         free(op);
551         op = next;
552     }
553 }
554 
555 
556 // ------------------------------- crc32 --------------------------------------
557 static unsigned int crc32[256];
558 static char crc32_initialized=0;
crc32_init(void)559 static void crc32_init(void)
560 {
561     int t;
562     if(crc32_initialized)
563         return;
564     crc32_initialized = 1;
565     for(t=0; t<256; t++) {
566         unsigned int c = t;
567         int s;
568         for (s = 0; s < 8; s++) {
569           c = (0xedb88320L*(c&1)) ^ (c >> 1);
570         }
571         crc32[t] = c;
572     }
573 }
574 static uint64_t crc64[256];
575 static char crc64_initialized=0;
crc64_init(void)576 static void crc64_init(void)
577 {
578     int t;
579     if(crc64_initialized)
580         return;
581     crc64_initialized = 1;
582     for(t=0; t<256; t++) {
583         unsigned int c = t;
584         int s;
585         for (s = 0; s < 8; s++) {
586           c = ((c&1)?0xC96C5795D7870F42ll:0) ^ (c >> 1);
587         }
588         crc64[t] = c;
589     }
590 }
591 // ------------------------------- string_t -----------------------------------
592 
string_set2(string_t * str,const char * text,int len)593 void string_set2(string_t*str, const char*text, int len)
594 {
595     str->len = len;
596     str->str = text;
597 }
string_set(string_t * str,const char * text)598 void string_set(string_t*str, const char*text)
599 {
600     if(text) {
601         str->len = strlen(text);
602     } else {
603         str->len = 0;
604     }
605     str->str = text;
606 }
string_new(const char * text,int len)607 string_t string_new(const char*text, int len)
608 {
609     string_t s;
610     s.len = len;
611     s.str = text;
612     return s;
613 }
string_new2(const char * text)614 string_t string_new2(const char*text)
615 {
616     string_t s;
617     if(text) {
618         s.len = strlen(text);
619     } else {
620         s.len = 0;
621     }
622     s.str = text;
623     return s;
624 }
string_new3(const char * text,int len)625 string_t* string_new3(const char*text, int len)
626 {
627     if(!text) {
628         string_t*s = malloc(sizeof(string_t));
629         s->len = 0;
630         s->str = 0;
631         return s;
632     } else {
633         string_t*s = malloc(sizeof(string_t)+len+1);
634         s->len = len;
635         s->str = (const char*)(s+1);
636         memcpy((char*)s->str, text, len);
637         ((char*)s->str)[len]=0;
638         return s;
639     }
640 }
string_new4(const char * text)641 string_t* string_new4(const char*text)
642 {
643     int l = strlen(text);
644     return string_new3(text, l);
645 }
646 
string_free(string_t * s)647 void string_free(string_t*s)
648 {
649     if(!s)
650         return;
651     s->len = 0;
652     if((string_t*)(s->str) == s+1) {
653         s->str = 0;
654         rfx_free(s);
655     } else {
656         rfx_free((char*)(s->str));
657         s->str = 0;
658         rfx_free(s);
659     }
660 }
string_cstr(string_t * str)661 char* string_cstr(string_t*str)
662 {
663     return strdup_n(str->str, str->len);
664 }
string_escape(string_t * str)665 char* string_escape(string_t*str)
666 {
667     int t;
668     int len = 0;
669     for(t=0;t<str->len;t++) {
670         if(str->str[t]<0x20)
671             len+=3;
672         else
673             len++;
674     }
675     char*s = malloc(len+1);
676     char*p=s;
677     for(t=0;t<str->len;t++) {
678         if(str->str[t]<0x20) {
679             *p++ ='\\';
680             unsigned char c = str->str[t];
681             *p++ = "0123456789abcdef"[c>>4];
682             *p++ = "0123456789abcdef"[c&0x0f];
683         } else {
684             *p++ = str->str[t];
685         }
686     }
687     *p++ = 0;
688     assert(p == &s[len+1]);
689     return s;
690 }
691 
crc32_add_byte(unsigned int checksum,unsigned char b)692 unsigned int crc32_add_byte(unsigned int checksum, unsigned char b)
693 {
694     crc32_init();
695     return checksum>>8 ^ crc32[(b^checksum)&0xff];
696 }
crc32_add_string(unsigned int checksum,const char * s)697 unsigned int crc32_add_string(unsigned int checksum, const char*s)
698 {
699     crc32_init();
700     if(!s)
701         return checksum;
702     while(*s) {
703         checksum = checksum>>8 ^ crc32[(*s^checksum)&0xff];
704         s++;
705     }
706     return checksum;
707 }
crc32_add_bytes(unsigned int checksum,const void * _s,int len)708 unsigned int crc32_add_bytes(unsigned int checksum, const void*_s, int len)
709 {
710     unsigned char*s = (unsigned char*)_s;
711     crc32_init();
712     if(!s || !len)
713         return checksum;
714     do {
715         checksum = checksum>>8 ^ crc32[(*s^checksum)&0xff];
716         s++;
717     } while(--len);
718     return checksum;
719 }
720 
string_hash(const string_t * str)721 unsigned int string_hash(const string_t*str)
722 {
723     int t;
724     unsigned int checksum = 0;
725     crc32_init();
726     for(t=0;t<str->len;t++) {
727         checksum = checksum>>8 ^ crc32[(str->str[t]^checksum)&0xff];
728     }
729     return checksum;
730 }
string_hash2(const char * str)731 unsigned int string_hash2(const char*str)
732 {
733     unsigned int checksum = 0;
734     const char*p = str;
735     crc32_init();
736     while(*p) {
737         checksum = checksum>>8 ^ crc32[(*p^checksum)&0xff];
738         p++;
739     }
740     return checksum;
741 }
string_hash64(const char * str)742 uint64_t string_hash64(const char*str)
743 {
744     uint64_t checksum = 0;
745     const char*p = str;
746     crc64_init();
747     while(*p) {
748         checksum = checksum>>8 ^ crc64[(*p^checksum)&0xff];
749         p++;
750     }
751     return checksum;
752 }
string_hash3(const char * str,int len)753 unsigned int string_hash3(const char*str, int len)
754 {
755     string_t s;
756     s.str = str;
757     s.len = len;
758     return string_hash(&s);
759 }
string_dup2(string_t * str,const char * text,int len)760 void string_dup2(string_t*str, const char*text, int len)
761 {
762     str->len = len;
763     str->str = strdup_n(text, len);
764 }
string_dup(string_t * str,const char * text)765 void string_dup(string_t*str, const char*text)
766 {
767     str->len = strlen(text);
768     str->str = strdup(text);
769 }
string_equals(string_t * str,const char * text)770 int string_equals(string_t*str, const char*text)
771 {
772     int l = strlen(text);
773     if(str->len == l && !memcmp(str->str, text, l))
774 	return 1;
775     return 0;
776 }
string_equals2(string_t * str,string_t * str2)777 int string_equals2(string_t*str, string_t*str2)
778 {
779     if(str->len == str2->len && !memcmp(str->str, str2->str, str->len))
780 	return 1;
781     return 0;
782 }
783 
concat2(const char * t1,const char * t2)784 char* concat2(const char* t1, const char* t2)
785 {
786     int l1 = strlen(t1);
787     int l2 = strlen(t2);
788     char*text = malloc(l1+l2+1);
789     memcpy(text   , t1, l1);
790     memcpy(text+l1, t2, l2);
791     text[l1+l2] = 0;
792     return text;
793 }
794 
concat3(const char * t1,const char * t2,const char * t3)795 char* concat3(const char* t1, const char* t2, const char* t3)
796 {
797     int l1 = strlen(t1);
798     int l2 = strlen(t2);
799     int l3 = strlen(t3);
800     char*text = malloc(l1+l2+l3+1);
801     memcpy(text   , t1, l1);
802     memcpy(text+l1, t2, l2);
803     memcpy(text+l1+l2, t3, l3);
804     text[l1+l2+l3] = 0;
805     return text;
806 }
807 
808 // ------------------------------- stringarray_t ------------------------------
809 
810 typedef struct _stringlist {
811     int index;
812     struct _stringlist*next;
813 } stringlist_t;
814 
815 typedef struct _stringarray_internal_t
816 {
817     mem_t pos;
818     stringlist_t**hash;
819     int num;
820     int hashsize;
821 } stringarray_internal_t;
822 
stringarray_init(stringarray_t * sa,int hashsize)823 void stringarray_init(stringarray_t*sa, int hashsize)
824 {
825     stringarray_internal_t*s;
826     int t;
827     sa->internal = (stringarray_internal_t*)rfx_calloc(sizeof(stringarray_internal_t));
828     s = (stringarray_internal_t*)sa->internal;
829     mem_init(&s->pos);
830     s->hash = rfx_calloc(sizeof(stringlist_t*)*hashsize);
831     s->hashsize = hashsize;
832 }
stringarray_put(stringarray_t * sa,string_t str)833 void stringarray_put(stringarray_t*sa, string_t str)
834 {
835     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
836     int pos;
837     int hash = string_hash(&str) % s->hashsize;
838 
839     char*ss = string_cstr(&str);
840     mem_put(&s->pos, &ss, sizeof(char*));
841 
842     stringlist_t*l = rfx_alloc(sizeof(stringlist_t));
843     l->index = s->num;
844     l->next = s->hash[hash];
845     s->hash[hash] = l;
846 
847     s->num++;
848 }
stringarray_at(stringarray_t * sa,int pos)849 char* stringarray_at(stringarray_t*sa, int pos)
850 {
851     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
852     char*p;
853     if(pos<0 || pos>=s->num)
854 	return 0;
855     p = *(char**)&s->pos.buffer[pos*sizeof(char*)];
856     if(p<0)
857 	return 0;
858     return p;
859 }
stringarray_at2(stringarray_t * sa,int pos)860 string_t stringarray_at2(stringarray_t*sa, int pos)
861 {
862     string_t s;
863     s.str = stringarray_at(sa, pos);
864     s.len = s.str?strlen(s.str):0;
865     return s;
866 }
stringlist_del(stringarray_t * sa,stringlist_t * l,int index)867 static stringlist_t* stringlist_del(stringarray_t*sa, stringlist_t*l, int index)
868 {
869     stringlist_t*ll = l;
870     stringlist_t*old = l;
871     while(l) {
872         if(index==l->index) {
873             old->next = l->next;
874             memset(l, 0, sizeof(stringlist_t));
875             rfx_free(l);
876             if(old==l)
877                 return 0;
878             else
879                 return ll;
880         }
881         old = l;
882         l = l->next;
883     }
884     fprintf(stderr, "Internal error: did not find string %d in hash\n", index);
885     return ll;
886 }
887 
stringarray_del(stringarray_t * sa,int pos)888 void stringarray_del(stringarray_t*sa, int pos)
889 {
890     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
891     string_t str = stringarray_at2(sa, pos);
892     int hash = string_hash(&str) % s->hashsize;
893     s->hash[hash] = stringlist_del(sa, s->hash[hash], pos);
894     *(char**)&s->pos.buffer[pos*sizeof(char*)] = 0;
895 }
stringarray_find(stringarray_t * sa,string_t * str)896 int stringarray_find(stringarray_t*sa, string_t* str)
897 {
898     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
899     int hash = string_hash(str) % s->hashsize;
900     int t;
901     stringlist_t*l = s->hash[hash];
902     //TODO: statistics
903     while(l) {
904         string_t s = stringarray_at2(sa, l->index);
905         if(string_equals2(str, &s)) {
906             return l->index;
907         }
908         l = l->next;
909     }
910     return -1;
911 }
stringarray_clear(stringarray_t * sa)912 void stringarray_clear(stringarray_t*sa)
913 {
914     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
915     mem_clear(&s->pos);
916     int t;
917     for(t=0;t<s->hashsize;t++) {
918         stringlist_t*l = s->hash[t];
919         while(l) {
920             stringlist_t*next = l->next;
921             memset(l, 0, sizeof(stringlist_t));
922             rfx_free(l);
923             l = next;
924         }
925     }
926     rfx_free(s->hash);s->hash=0;
927     rfx_free(s);
928 }
stringarray_destroy(stringarray_t * sa)929 void stringarray_destroy(stringarray_t*sa)
930 {
931     stringarray_clear(sa);
932     rfx_free(sa);
933 }
934 
935 // ------------------------------- type_t -------------------------------
936 
ptr_equals(const void * o1,const void * o2)937 char ptr_equals(const void*o1, const void*o2)
938 {
939     return o1==o2;
940 }
ptr_hash(const void * o)941 unsigned int ptr_hash(const void*o)
942 {
943     return string_hash3((const char*)&o, sizeof(o));
944 }
ptr_dup(const void * o)945 void* ptr_dup(const void*o)
946 {
947     return (void*)o;
948 }
ptr_free(void * o)949 void ptr_free(void*o)
950 {
951     return;
952 }
953 
int_equals(const void * o1,const void * o2)954 char int_equals(const void*o1, const void*o2)
955 {
956     return o1==o2;
957 }
int_hash(const void * o)958 unsigned int int_hash(const void*o)
959 {
960     return string_hash3((const char*)&o, sizeof(o));
961 }
int_dup(const void * o)962 void* int_dup(const void*o)
963 {
964     return (void*)o;
965 }
int_free(void * o)966 void int_free(void*o)
967 {
968     return;
969 }
970 
charptr_equals(const void * o1,const void * o2)971 char charptr_equals(const void*o1, const void*o2)
972 {
973     if(!o1 || !o2)
974         return o1==o2;
975     return !strcmp(o1,o2);
976 }
charptr_hash(const void * o)977 unsigned int charptr_hash(const void*o)
978 {
979     if(!o)
980         return 0;
981     return string_hash2(o);
982 }
charptr_dup(const void * o)983 void* charptr_dup(const void*o)
984 {
985     if(!o)
986         return 0;
987     return strdup(o);
988 }
charptr_free(void * o)989 void charptr_free(void*o)
990 {
991     if(o) {
992         rfx_free(o);
993     }
994 }
995 
stringstruct_equals(const void * o1,const void * o2)996 char stringstruct_equals(const void*o1, const void*o2)
997 {
998     if(!o1 || !o2)
999         return o1==o2;
1000     string_t*s1 = (string_t*)o1;
1001     string_t*s2 = (string_t*)o2;
1002     int l = s1->len<s2->len?s1->len:s2->len;
1003     int r = memcmp(s1->str, s2->str, l);
1004     if(r)
1005         return 0;
1006     else
1007         return s1->len==s2->len;
1008 }
stringstruct_hash(const void * o)1009 unsigned int stringstruct_hash(const void*o)
1010 {
1011     if(!o) return 0;
1012     return string_hash(o);
1013 }
string_dup3(string_t * o)1014 string_t*string_dup3(string_t*o)
1015 {
1016     if(!o) return 0;
1017     if(!o->str) {
1018         string_t*s = malloc(sizeof(string_t));
1019         s->str=0;
1020         s->len=0;
1021         return s;
1022     }
1023     string_t*s = rfx_alloc(sizeof(string_t)+o->len+1);
1024     s->len = o->len;
1025     s->str = (const char*)(s+1);
1026     memcpy((char*)s->str, o->str, s->len);
1027     ((char*)s->str)[s->len]=0;
1028     return s;
1029 }
stringstruct_free(void * o)1030 void stringstruct_free(void*o)
1031 {
1032     if(o)
1033         string_free(o);
1034 }
1035 
1036 type_t int_type = {
1037     equals: int_equals,
1038     hash: int_hash,
1039     dup: int_dup,
1040     free: int_free,
1041 };
1042 
1043 type_t ptr_type = {
1044     equals: ptr_equals,
1045     hash: ptr_hash,
1046     dup: ptr_dup,
1047     free: ptr_free,
1048 };
1049 
1050 type_t charptr_type = {
1051     equals: charptr_equals,
1052     hash: charptr_hash,
1053     dup: charptr_dup,
1054     free: charptr_free,
1055 };
1056 
1057 type_t stringstruct_type = {
1058     equals: stringstruct_equals,
1059     hash: stringstruct_hash,
1060     dup: (dup_func)string_dup3,
1061     free: stringstruct_free,
1062 };
1063 
1064 // ------------------------------- dictionary_t -------------------------------
1065 
1066 #define INITIAL_SIZE 1
1067 
max(int x,int y)1068 static int max(int x, int y) {
1069     return x>y?x:y;
1070 }
1071 
dict_new()1072 dict_t*dict_new()
1073 {
1074     dict_t*d = rfx_alloc(sizeof(dict_t));
1075     dict_init(d, INITIAL_SIZE);
1076     return d;
1077 }
dict_new2(type_t * t)1078 dict_t*dict_new2(type_t*t)
1079 {
1080     dict_t*d = rfx_alloc(sizeof(dict_t));
1081     dict_init(d, INITIAL_SIZE);
1082     d->key_type = t;
1083     return d;
1084 }
dict_init(dict_t * h,int size)1085 void dict_init(dict_t*h, int size)
1086 {
1087     memset(h, 0, sizeof(dict_t));
1088     h->hashsize = size;
1089     h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0;
1090     h->num = 0;
1091     h->key_type = &charptr_type;
1092 }
dict_init2(dict_t * h,type_t * t,int size)1093 void dict_init2(dict_t*h, type_t*t, int size)
1094 {
1095     memset(h, 0, sizeof(dict_t));
1096     h->hashsize = size;
1097     h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0;
1098     h->num = 0;
1099     h->key_type = t;
1100 }
1101 
dict_clone(dict_t * o)1102 dict_t*dict_clone(dict_t*o)
1103 {
1104     dict_t*h = rfx_alloc(sizeof(dict_t));
1105     memcpy(h, o, sizeof(dict_t));
1106     h->slots = h->hashsize?(dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*h->hashsize):0;
1107     int t;
1108     for(t=0;t<o->hashsize;t++) {
1109         dictentry_t*e = o->slots[t];
1110         while(e) {
1111             dictentry_t*n = (dictentry_t*)rfx_alloc(sizeof(dictentry_t));
1112             memcpy(n, e, sizeof(dictentry_t));
1113             n->key = h->key_type->dup(e->key);
1114             n->data = e->data;
1115             n->next = h->slots[t];
1116             h->slots[t] = n;
1117             e = e->next;
1118         }
1119     }
1120     return h;
1121 }
1122 
dict_expand(dict_t * h,int newlen)1123 static void dict_expand(dict_t*h, int newlen)
1124 {
1125     assert(h->hashsize < newlen);
1126     dictentry_t**newslots = (dictentry_t**)rfx_calloc(sizeof(dictentry_t*)*newlen);
1127     int t;
1128     for(t=0;t<h->hashsize;t++) {
1129         dictentry_t*e = h->slots[t];
1130         while(e) {
1131             dictentry_t*next = e->next;
1132             unsigned int newhash = e->hash%newlen;
1133             e->next = newslots[newhash];
1134             newslots[newhash] = e;
1135             e = next;
1136         }
1137     }
1138     if(h->slots)
1139         rfx_free(h->slots);
1140     h->slots = newslots;
1141     h->hashsize = newlen;
1142 }
1143 
dict_put(dict_t * h,const void * key,void * data)1144 dictentry_t* dict_put(dict_t*h, const void*key, void* data)
1145 {
1146     unsigned int hash = h->key_type->hash(key);
1147     dictentry_t*e = (dictentry_t*)rfx_alloc(sizeof(dictentry_t));
1148 
1149     if(!h->hashsize)
1150         dict_expand(h, 1);
1151 
1152     unsigned int hash2 = hash % h->hashsize;
1153 
1154     e->key = h->key_type->dup(key);
1155     e->hash = hash; //for resizing
1156     e->next = h->slots[hash2];
1157     e->data = data;
1158     h->slots[hash2] = e;
1159     h->num++;
1160     return e;
1161 }
dict_put2(dict_t * h,const char * s,void * data)1162 void dict_put2(dict_t*h, const char*s, void*data)
1163 {
1164     assert(h->key_type == &charptr_type);
1165     dict_put(h, s, data);
1166 }
dict_dump(dict_t * h,FILE * fi,const char * prefix)1167 void dict_dump(dict_t*h, FILE*fi, const char*prefix)
1168 {
1169     int t;
1170     for(t=0;t<h->hashsize;t++) {
1171         dictentry_t*e = h->slots[t];
1172         while(e) {
1173             if(h->key_type!=&charptr_type) {
1174                 fprintf(fi, "%s%08x=%08x\n", prefix, (int)e->key, (int)e->data);
1175             } else {
1176                 fprintf(fi, "%s%s=%08x\n", prefix, (char*)e->key, (int)e->data);
1177             }
1178             e = e->next;
1179         }
1180     }
1181 }
1182 
dict_count(dict_t * h)1183 int dict_count(dict_t*h)
1184 {
1185     return h->num;
1186 }
1187 
dict_do_lookup(dict_t * h,const void * key)1188 static inline dictentry_t* dict_do_lookup(dict_t*h, const void*key)
1189 {
1190     if(!h->num) {
1191         return 0;
1192     }
1193 
1194     unsigned int ohash = h->key_type->hash(key);
1195     unsigned int hash = ohash % h->hashsize;
1196 
1197     /* check first entry for match */
1198     dictentry_t*e = h->slots[hash];
1199     if(e && h->key_type->equals(e->key, key)) {
1200         return e;
1201     } else if(e) {
1202         e = e->next;
1203     }
1204 
1205     /* if dict is 2/3 filled, double the size. Do
1206        this the first time we have to actually iterate
1207        through a slot to find our data */
1208     if(e && h->num*3 >= h->hashsize*2) {
1209         int newsize = h->hashsize;
1210         while(h->num*3 >= newsize*2) {
1211             newsize = newsize<15?15:(newsize+1)*2-1;
1212         }
1213         dict_expand(h, newsize);
1214         hash = ohash % h->hashsize;
1215         e = h->slots[hash];
1216         if(e && h->key_type->equals(e->key, key)) {
1217             // omit move to front
1218             return e;
1219         } else if(e) {
1220             e = e->next;
1221         }
1222     }
1223 
1224     /* check subsequent entries for a match */
1225     dictentry_t*last = h->slots[hash];
1226     while(e) {
1227         if(h->key_type->equals(e->key, key)) {
1228             /* move to front- makes a difference of about 10% in most applications */
1229             last->next = e->next;
1230             e->next = h->slots[hash];
1231             h->slots[hash] = e;
1232             return e;
1233         }
1234         last=e;
1235         e = e->next;
1236     }
1237     return 0;
1238 }
dict_lookup(dict_t * h,const void * key)1239 void* dict_lookup(dict_t*h, const void*key)
1240 {
1241     dictentry_t*e = dict_do_lookup(h, key);
1242     if(e)
1243         return e->data;
1244     return 0;
1245 }
dict_contains(dict_t * h,const void * key)1246 char dict_contains(dict_t*h, const void*key)
1247 {
1248     dictentry_t*e = dict_do_lookup(h, key);
1249     return !!e;
1250 }
1251 
dict_del(dict_t * h,const void * key)1252 char dict_del(dict_t*h, const void*key)
1253 {
1254     if(!h->num)
1255         return 0;
1256     unsigned int hash = h->key_type->hash(key) % h->hashsize;
1257     dictentry_t*head = h->slots[hash];
1258     dictentry_t*e = head, *prev=0;
1259     while(e) {
1260         if(h->key_type->equals(e->key, key)) {
1261             dictentry_t*next = e->next;
1262             h->key_type->free(e->key);
1263             memset(e, 0, sizeof(dictentry_t));
1264             rfx_free(e);
1265             if(e == head) {
1266                 h->slots[hash] = next;
1267             } else {
1268                 assert(prev);
1269                 prev->next = next;
1270             }
1271             h->num--;
1272             return 1;
1273         }
1274         prev = e;
1275         e = e->next;
1276     }
1277     return 0;
1278 }
1279 
dict_del2(dict_t * h,const void * key,void * data)1280 char dict_del2(dict_t*h, const void*key, void*data)
1281 {
1282     if(!h->num)
1283         return 0;
1284     unsigned int hash = h->key_type->hash(key) % h->hashsize;
1285     dictentry_t*head = h->slots[hash];
1286     dictentry_t*e = head, *prev=0;
1287     while(e) {
1288         if(h->key_type->equals(e->key, key) && e->data == data) {
1289             dictentry_t*next = e->next;
1290             h->key_type->free(e->key);
1291             memset(e, 0, sizeof(dictentry_t));
1292             rfx_free(e);
1293             if(e == head) {
1294                 h->slots[hash] = next;
1295             } else {
1296                 assert(prev);
1297                 prev->next = next;
1298             }
1299             h->num--;
1300             return 1;
1301         }
1302         prev = e;
1303         e = e->next;
1304     }
1305     return 0;
1306 }
1307 
dict_get_slot(dict_t * h,const void * key)1308 dictentry_t* dict_get_slot(dict_t*h, const void*key)
1309 {
1310     if(!h->num)
1311         return 0;
1312     unsigned int ohash = h->key_type->hash(key);
1313     unsigned int hash = ohash % h->hashsize;
1314     return h->slots[hash];
1315 }
1316 
dict_foreach_keyvalue(dict_t * h,void (* runFunction)(void * data,const void * key,void * val),void * data)1317 void dict_foreach_keyvalue(dict_t*h, void (*runFunction)(void*data, const void*key, void*val), void*data)
1318 {
1319     int t;
1320     for(t=0;t<h->hashsize;t++) {
1321         dictentry_t*e = h->slots[t];
1322         while(e) {
1323             dictentry_t*next = e->next;
1324             if(runFunction) {
1325                 runFunction(data, e->key, e->data);
1326             }
1327             e = e->next;
1328         }
1329     }
1330 }
dict_foreach_value(dict_t * h,void (* runFunction)(void *))1331 void dict_foreach_value(dict_t*h, void (*runFunction)(void*))
1332 {
1333     int t;
1334     for(t=0;t<h->hashsize;t++) {
1335         dictentry_t*e = h->slots[t];
1336         while(e) {
1337             dictentry_t*next = e->next;
1338             if(runFunction) {
1339                 runFunction(e->data);
1340             }
1341             e = e->next;
1342         }
1343     }
1344 }
1345 
dict_free_all(dict_t * h,char free_keys,void (* free_data_function)(void *))1346 void dict_free_all(dict_t*h, char free_keys, void (*free_data_function)(void*))
1347 {
1348     int t;
1349     for(t=0;t<h->hashsize;t++) {
1350         dictentry_t*e = h->slots[t];
1351         while(e) {
1352             dictentry_t*next = e->next;
1353             if(free_keys) {
1354                 h->key_type->free(e->key);
1355             }
1356             if(free_data_function) {
1357                 free_data_function(e->data);
1358             }
1359             memset(e, 0, sizeof(dictentry_t));
1360             rfx_free(e);
1361             e = next;
1362         }
1363         h->slots[t]=0;
1364     }
1365     rfx_free(h->slots);
1366     memset(h, 0, sizeof(dict_t));
1367 }
1368 
dict_clear_shallow(dict_t * h)1369 void dict_clear_shallow(dict_t*h)
1370 {
1371     dict_free_all(h, 0, 0);
1372 }
1373 
dict_clear(dict_t * h)1374 void dict_clear(dict_t*h)
1375 {
1376     dict_free_all(h, 1, 0);
1377 }
1378 
dict_destroy_shallow(dict_t * dict)1379 void dict_destroy_shallow(dict_t*dict)
1380 {
1381     dict_clear_shallow(dict);
1382     rfx_free(dict);
1383 }
1384 
dict_destroy(dict_t * dict)1385 void dict_destroy(dict_t*dict)
1386 {
1387     if(!dict)
1388         return;
1389     dict_clear(dict);
1390     rfx_free(dict);
1391 }
1392 
1393 // ------------------------------- mtf_t --------------------------------------
mtf_new(type_t * type)1394 mtf_t* mtf_new(type_t*type)
1395 {
1396     NEW(mtf_t, mtf);
1397     mtf->type = type;
1398     return mtf;
1399 }
mtf_increase(mtf_t * m,const void * key)1400 void mtf_increase(mtf_t*m, const void*key)
1401 {
1402     mtf_item_t*item = m->first;
1403     mtf_item_t*last = 0;
1404     while(item) {
1405 	if(m->type->equals(item->key, key)) {
1406 	    item->num++;
1407 	    if(item->num>m->first->num) {
1408 		if(last) last->next = item->next;
1409 		else m->first = item->next;
1410 		item->next = m->first;
1411 		m->first = item;
1412 	    }
1413             return;
1414 	}
1415 	last = item;
1416 	item = item->next;
1417     }
1418     NEW(mtf_item_t,n);
1419     if(last) last->next = n;
1420     else m->first = n;
1421     n->key = key;
1422     n->num = 1;
1423 }
mtf_destroy(mtf_t * m)1424 void mtf_destroy(mtf_t*m)
1425 {
1426     if(!m) return;
1427     mtf_item_t*item = m->first;
1428     m->first = 0;
1429     while(item) {
1430 	mtf_item_t*next = item->next;
1431 	item->next = 0;
1432 	free(item);
1433 	item = next;
1434     }
1435     free(m);
1436 }
1437 
1438 // ------------------------------- map_t --------------------------------------
1439 
1440 typedef struct _map_internal_t
1441 {
1442     dict_t d;
1443 } map_internal_t;
1444 
map_init(map_t * map)1445 void map_init(map_t*map)
1446 {
1447     map_internal_t*m;
1448     map->internal = (map_internal_t*)rfx_calloc(sizeof(map_internal_t));
1449     m = (map_internal_t*)map->internal;
1450     dict_init(&m->d, INITIAL_SIZE);
1451 }
map_put(map_t * map,string_t t1,string_t t2)1452 void map_put(map_t*map, string_t t1, string_t t2)
1453 {
1454     map_internal_t*m = (map_internal_t*)map->internal;
1455     string_t s;
1456     char* s1 = string_cstr(&t1);
1457     dict_put2(&m->d, s1, (void*)string_cstr(&t2));
1458     rfx_free(s1);
1459 }
map_lookup(map_t * map,const char * name)1460 const char* map_lookup(map_t*map, const char*name)
1461 {
1462     map_internal_t*m = (map_internal_t*)map->internal;
1463     const char*value = dict_lookup(&m->d, name);
1464     return value;
1465 }
freestring(void * data)1466 static void freestring(void*data)
1467 {
1468     rfx_free(data);
1469 }
dumpmapentry(void * data,const void * key,void * value)1470 static void dumpmapentry(void*data, const void*key, void*value)
1471 {
1472     FILE*fi = (FILE*)data;
1473     fprintf(fi, "%s=%s\n", (char*)key, (char*)value);
1474 }
map_dump(map_t * map,FILE * fi,const char * prefix)1475 void map_dump(map_t*map, FILE*fi, const char*prefix)
1476 {
1477     int t;
1478     map_internal_t*m = (map_internal_t*)map->internal;
1479     dict_foreach_keyvalue(&m->d, dumpmapentry, fi);
1480 }
map_clear(map_t * map)1481 void map_clear(map_t*map)
1482 {
1483     map_internal_t*m = (map_internal_t*)map->internal;
1484     dict_free_all(&m->d, 1, freestring);
1485     rfx_free(m);
1486 }
map_destroy(map_t * map)1487 void map_destroy(map_t*map)
1488 {
1489     map_clear(map);
1490     rfx_free(map);
1491 }
1492 
1493 // ------------------------------- array_t --------------------------------------
1494 
array_new1()1495 array_t* array_new1() {
1496     array_t*d = malloc(sizeof(array_t));
1497     memset(d, 0, sizeof(array_t));
1498     d->entry2pos = dict_new();
1499     return d;
1500 }
array_new2(type_t * type)1501 array_t* array_new2(type_t*type) {
1502     array_t*d = malloc(sizeof(array_t));
1503     memset(d, 0, sizeof(array_t));
1504     d->entry2pos = dict_new2(type);
1505     return d;
1506 }
array_getkey(array_t * array,int nr)1507 void*array_getkey(array_t*array, int nr) {
1508     if(nr >= array->num || nr<0) {
1509 	fprintf(stderr, "error: reference to element %d in array[%d]\n", nr, array->num);
1510 	return 0;
1511     }
1512     return array->d[nr].name;
1513 }
array_getvalue(array_t * array,int nr)1514 void*array_getvalue(array_t*array, int nr) {
1515     if(nr >= array->num || nr<0) {
1516 	fprintf(stderr, "error: reference to element %d in array[%d]\n", nr, array->num);
1517 	return 0;
1518     }
1519     return array->d[nr].data;
1520 }
array_append(array_t * array,const void * name,void * data)1521 int array_append(array_t*array, const void*name, void*data) {
1522     while(array->size <= array->num) {
1523 	array->size += 64;
1524 	if(!array->d) {
1525 	    array->d = malloc(sizeof(array_entry_t)*array->size);
1526 	} else {
1527 	    array->d = realloc(array->d, sizeof(array_entry_t)*array->size);
1528 	}
1529     }
1530 
1531     dictentry_t*e = dict_put(array->entry2pos, name, (void*)(ptroff_t)(array->num+1));
1532 
1533     if(name) {
1534 	array->d[array->num].name = e->key;
1535     } else {
1536 	array->d[array->num].name = 0;
1537     }
1538     array->d[array->num].data = (void*)data;
1539     return array->num++;
1540 }
array_find(array_t * array,const void * name)1541 int array_find(array_t*array, const void*name)
1542 {
1543     int pos = (int)(ptroff_t)dict_lookup(array->entry2pos, name);
1544     return pos-1;
1545 }
array_find2(array_t * array,const void * name,void * data)1546 int array_find2(array_t*array, const void*name, void*data)
1547 {
1548     dict_t*h= array->entry2pos;
1549     dictentry_t*e = dict_get_slot(array->entry2pos, name);
1550 
1551     while(e) {
1552         int index = ((int)(ptroff_t)e->data) - 1;
1553         if(h->key_type->equals(e->key, name) && array->d[index].data == data) {
1554             return index;
1555         }
1556         e = e->next;
1557     }
1558     return -1;
1559 }
array_update(array_t * array,const void * name,void * data)1560 int array_update(array_t*array, const void*name, void*data) {
1561     int pos = array_find(array, name);
1562     if(pos>=0) {
1563 	array->d[pos].data = data;
1564 	return pos;
1565     }
1566     return array_append(array, name, data);
1567 }
array_append_if_new(array_t * array,const void * name,void * data)1568 int array_append_if_new(array_t*array, const void*name, void*data) {
1569     int pos = array_find(array, name);
1570     if(pos>=0)
1571 	return pos;
1572     return array_append(array, name, data);
1573 }
array_free(array_t * array)1574 void array_free(array_t*array) {
1575     dict_destroy(array->entry2pos);
1576     if(array->d) {
1577         free(array->d);array->d = 0;
1578     }
1579     free(array);
1580 }
1581 
1582 // ------------------------------- list_t --------------------------------------
1583 
1584 struct _commonlist;
1585 typedef struct _listinfo {
1586     int size;
1587     struct _commonlist*last;
1588 } listinfo_t;
1589 
1590 typedef struct _commonlist {
1591     void*entry;
1592     struct _commonlist*next;
1593     listinfo_t info[0];
1594 } commonlist_t;
1595 
list_length_(void * _list)1596 int list_length_(void*_list)
1597 {
1598     commonlist_t*l = (commonlist_t*)_list;
1599     if(!l)
1600         return 0;
1601     return l->info[0].size;
1602 }
list_concat_(void * _l1,void * _l2)1603 void list_concat_(void*_l1, void*_l2)
1604 {
1605     commonlist_t**l1 = (commonlist_t**)_l1;
1606     commonlist_t**l2 = (commonlist_t**)_l2;
1607 
1608     if(!*l1) {
1609         *l1 = *l2;
1610     } else if(*l2) {
1611         (*l1)->info[0].last->next = *l2;
1612         (*l1)->info[0].last = (*l2)->info[0].last;
1613         (*l1)->info[0].size += (*l2)->info[0].size;
1614     }
1615     *l2 = 0;
1616 }
list_append_(void * _list,void * entry)1617 void list_append_(void*_list, void*entry)
1618 {
1619     commonlist_t**list = (commonlist_t**)_list;
1620     commonlist_t* n = 0;
1621     if(!*list) {
1622         n = (commonlist_t*)malloc(sizeof(commonlist_t)+sizeof(listinfo_t));
1623         *list = n;
1624         (*list)->info[0].size = 0;
1625     } else {
1626         n = malloc(sizeof(commonlist_t));
1627         (*list)->info[0].last->next = n;
1628     }
1629     n->next = 0;
1630     n->entry = entry;
1631     (*list)->info[0].last = n;
1632     (*list)->info[0].size++;
1633 }
1634 /* notice: prepending uses slighly more space than appending */
list_prepend_(void * _list,void * entry)1635 void list_prepend_(void*_list, void*entry)
1636 {
1637     commonlist_t**list = (commonlist_t**)_list;
1638     commonlist_t* n = (commonlist_t*)malloc(sizeof(commonlist_t)+sizeof(listinfo_t));
1639     int size = 0;
1640     commonlist_t* last = 0;
1641     if(*list) {
1642         last = (*list)->info[0].last;
1643         size = (*list)->info[0].size;
1644     }
1645     n->next = *list;
1646     n->entry = entry;
1647     *list = n;
1648     (*list)->info[0].last = last;
1649     (*list)->info[0].size = size+1;
1650 }
list_free_(void * _list)1651 void list_free_(void*_list)
1652 {
1653     commonlist_t**list = (commonlist_t**)_list;
1654     commonlist_t*l = *list;
1655     while(l) {
1656         commonlist_t*next = l->next;
1657         free(l);
1658         l = next;
1659     }
1660     *list = 0;
1661 }
list_deep_free_(void * _list)1662 void list_deep_free_(void*_list)
1663 {
1664     commonlist_t**list = (commonlist_t**)_list;
1665     commonlist_t*l = *list;
1666     while(l) {
1667         commonlist_t*next = l->next;
1668         if(l->entry) {
1669             free(l->entry);l->entry=0;
1670         }
1671         free(l);
1672         l = next;
1673     }
1674     *list = 0;
1675 }
list_clone_(void * _list)1676 void*list_clone_(void*_list)
1677 {
1678     commonlist_t*l = *(commonlist_t**)_list;
1679 
1680     void*dest = 0;
1681     while(l) {
1682         commonlist_t*next = l->next;
1683         list_append_(&dest, l->entry);
1684         l = next;
1685     }
1686     return dest;
1687 
1688 }
1689 
1690