added ringbuffer routines.
[swftools.git] / src / q.c
1 /* q.c
2
3    Part of the swftools package.
4    
5    Copyright (c) 2001 Matthias Kramm <kramm@quiss.org>
6
7    This file is distributed under the GPL, see file COPYING for details */
8 #include <stdlib.h>
9 #include <stdio.h>
10 #include <string.h>
11 #include <memory.h>
12 #include "q.h"
13
14 // ------------------------------- malloc, alloc routines ---------------------
15
16 #ifndef STRNDUP
17 char* strndup(const char*str, int size)
18 {
19     char*m = (char*)malloc(size+1);
20     memcpy(m, str, size);
21     m[size] = 0;
22     return m;
23 }
24 #endif
25 void* qmalloc_internal(int len)
26 {
27     void*val = malloc(len);
28     if(!val) {
29         printf("memory error! Couldn't reserve %d bytes\n", len);
30         fprintf(stderr, "memory error! Couldn't reserve %d bytes\n", len);
31         exit(1);
32     }
33     return val;
34 }
35 void* qrealloc_internal(void*old, int len)
36 {
37     void*val = realloc(old, len);
38     if(!val) {
39         printf("memory error! Couldn't reserve %d bytes\n", len);
40         fprintf(stderr, "memory error! Couldn't reserve %d bytes\n", len);
41         exit(1);
42     }
43     return val;
44 }
45 void qfree_internal(void*old)
46 {
47     free(old);
48 }
49 char*qstrdup(const char*string)
50 {
51     return strdup(string);
52 }
53 char*qstrndup(const char*string, int len)
54 {
55     return strndup(string, len);
56 }
57
58 // ------------------------------- mem_t --------------------------------------
59
60 void mem_init(mem_t*mem)
61 {
62     memset(mem, 0, sizeof(mem_t));
63 }
64 void mem_clear(mem_t*mem)
65 {
66     free(mem->buffer);
67 }
68 void mem_destroy(mem_t*mem)
69 {
70     mem_clear(mem);
71     free(mem);
72 }
73 static int mem_put_(mem_t*m,void*data, int length, int null)
74 {
75     int n = m->pos;
76     m->pos += length + (null?1:0);
77     if(m->pos > m->len)
78     { 
79         //m->len += 1024>length?1024:(null?length*2:length);
80
81         m->len *= 2;
82         while(m->len < m->pos)
83             m->len += 64;
84
85         m->buffer = m->buffer?(char*)realloc(m->buffer,m->len):(char*)malloc(m->len);
86     }
87     memcpy(&m->buffer[n], data, length);
88     if(null)
89         m->buffer[n + length] = 0;
90     return n;
91 }
92 int mem_put(mem_t*m,void*data, int length)
93 {
94     return mem_put_(m, data, length, 0);
95 }
96 int mem_putstring(mem_t*m,string_t str)
97 {
98     return mem_put_(m, str.str, str.len, 1);
99 }
100
101 // ------------------------------- ringbuffer_t -------------------------------
102
103 typedef struct _ringbuffer_internal_t
104 {
105     unsigned char*buffer;
106     int readpos;
107     int writepos;
108     int buffersize;
109     int available;
110 } ringbuffer_internal_t;
111
112 void ringbuffer_init(ringbuffer_t*r)
113 {
114     ringbuffer_internal_t*i = (ringbuffer_internal_t*)malloc(sizeof(ringbuffer_internal_t)); 
115     memset(r, 0, sizeof(ringbuffer_t));
116     memset(i, 0, sizeof(ringbuffer_internal_t));
117     r->internal = i;
118     i->buffer = (unsigned char*)malloc(1024);
119     i->buffersize = 1024;
120 }
121 int ringbuffer_read(ringbuffer_t*r, void*buf, int len)
122 {
123     unsigned char* data = (unsigned char*)buf;
124     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
125     if(i->available < len)
126         len = i->available;
127     if(!len)
128         return 0;
129     if(i->readpos + len > i->buffersize) {
130         int read1 = i->buffersize-i->readpos;
131         memcpy(data, &i->buffer[i->readpos], read1);
132         memcpy(&data[read1], &i->buffer[0], len - read1);
133         i->readpos = len - read1;
134     } else {
135         memcpy(data, &i->buffer[i->readpos], len);
136         i->readpos += len;
137         i->readpos %= i->buffersize;
138     }
139     i->available -= len;
140     return len;
141 }
142 void ringbuffer_put(ringbuffer_t*r, void*buf, int len)
143 {
144     unsigned char* data = (unsigned char*)buf;
145     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
146     
147 /*    if( (i->writepos < i->readpos && i->writepos + len >= i->readpos) ||
148         (i->writepos >  i->readpos && i->writepos + len >= i->buffersize && 
149          (i->writepos + len) % i->buffersize >= i->readpos)
150       ) */
151     if(i->buffersize - i->available < len)
152     {
153         unsigned char* buf2;
154         int newbuffersize = i->buffersize;
155         newbuffersize*=3;newbuffersize/=2; /*grow by 50% each time */
156
157         if(newbuffersize < i->available + len)
158             newbuffersize = i->available + len;
159
160         buf2 = (unsigned char*)malloc(newbuffersize);
161         ringbuffer_read(r, buf2, i->available);
162         free(i->buffer);
163         i->buffer = buf2;
164         i->buffersize = newbuffersize;
165         i->writepos = 0;
166         i->readpos = i->available;
167     }
168     if(i->writepos + len > i->buffersize) {
169         int read1 = i->buffersize-i->writepos;
170         memcpy(&i->buffer[i->writepos], data, read1);
171         memcpy(&i->buffer[0], &data[read1], len - read1);
172         i->writepos = len - read1;
173     } else {
174         memcpy(&i->buffer[i->writepos], data, len);
175         i->writepos += len;
176         i->writepos %= i->buffersize;
177     }
178     i->available += len;
179 }
180 void ringbuffer_clear(ringbuffer_t*r)
181 {
182     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
183     free(i->buffer);
184     free(i);
185 }
186
187 // ------------------------------- string_t -----------------------------------
188
189 void string_set2(string_t*str, char*text, int len)
190 {
191     str->len = len;
192     str->str = text;
193 }
194 void string_set(string_t*str, char*text)
195 {
196     str->len = strlen(text);
197     str->str = text;
198 }
199 void string_dup2(string_t*str, const char*text, int len)
200 {
201     str->len = len;
202     str->str = strndup(text, len);
203 }
204 void string_dup(string_t*str, const char*text)
205 {
206     str->len = strlen(text);
207     str->str = strdup(text);
208 }
209 int string_equals(string_t*str, const char*text)
210 {
211     int l = strlen(text);
212     if(str->len == l && !strncmp(str->str, text, l))
213         return 1;
214     return 0;
215 }
216 int string_equals2(string_t*str, string_t*str2)
217 {
218     if(str->len == str2->len && !strncmp(str->str, str2->str, str->len))
219         return 1;
220     return 0;
221 }
222 char* string_cstr(string_t*str)
223 {
224     return strndup(str->str, str->len);
225 }
226
227 // ------------------------------- stringarray_t ------------------------------
228
229 typedef struct _stringarray_internal_t
230 {
231     mem_t data;
232     mem_t pos;
233     int num;
234 } stringarray_internal_t;
235 void stringarray_init(stringarray_t*sa)
236 {
237     stringarray_internal_t*s;
238     sa->internal = (stringarray_internal_t*)malloc(sizeof(stringarray_internal_t)); 
239     memset(sa->internal, 0, sizeof(stringarray_internal_t));
240     s = (stringarray_internal_t*)sa->internal;
241     mem_init(&s->data);
242     mem_init(&s->pos);
243 }
244 void stringarray_put(stringarray_t*sa, string_t str)
245 {
246     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
247     int pos;
248     pos = mem_putstring(&s->data, str);
249     mem_put(&s->pos, &pos, sizeof(int));
250     s->num++;
251 }
252 char* stringarray_at(stringarray_t*sa, int pos)
253 {
254     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
255     int p;
256     if(pos<0 || pos>=s->num)
257         return 0;
258     p = *(int*)&s->pos.buffer[pos*sizeof(int)];
259     if(p<0)
260         return 0;
261     return &s->data.buffer[p];
262 }
263 string_t stringarray_at2(stringarray_t*sa, int pos)
264 {
265     string_t s;
266     s.str = stringarray_at(sa, pos);
267     s.len = s.str?strlen(s.str):0;
268     return s;
269 }
270 void stringarray_del(stringarray_t*sa, int pos)
271 {
272     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
273     *(int*)&s->pos.buffer[pos*sizeof(int)] = -1;
274 }
275 int stringarray_find(stringarray_t*sa, string_t* str)
276 {
277     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
278     int t;
279     for(t=0;t<s->num;t++) {
280         string_t s = stringarray_at2(sa, t);
281         if(s.str && string_equals2(&s, str)) {
282             return t;
283         }
284     }
285     return -1;
286 }
287 void stringarray_clear(stringarray_t*sa)
288 {
289     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
290     mem_clear(&s->data);
291     mem_clear(&s->pos);
292     free(s);
293 }
294 void stringarray_destroy(stringarray_t*sa)
295 {
296     stringarray_clear(sa);
297     free(sa);
298 }
299
300
301 // ------------------------------- map_t --------------------------------------
302
303 typedef struct _map_internal_t
304 {
305     stringarray_t keys;
306     stringarray_t values;
307     int num;
308 } map_internal_t;
309
310 void map_init(map_t*map)
311 {
312     map_internal_t*m;
313     map->internal = (map_internal_t*)malloc(sizeof(map_internal_t));
314     memset(map->internal, 0, sizeof(map_internal_t));
315     m = (map_internal_t*)map->internal;
316     stringarray_init(&m->keys);
317     stringarray_init(&m->values);
318 }
319 void map_put(map_t*map, string_t t1, string_t t2)
320 {
321     map_internal_t*m = (map_internal_t*)map->internal;
322     stringarray_put(&m->keys, t1);
323     stringarray_put(&m->values, t2);
324     m->num++;
325 }
326 char* map_lookup(map_t*map, const char*name)
327 {
328     int s;
329     map_internal_t*m = (map_internal_t*)map->internal;
330     string_t str;
331     string_set(&str, (char*)name);
332     s = stringarray_find(&m->keys, &str);
333     if(s>=0) {
334         string_t s2 = stringarray_at2(&m->values, s);
335         return s2.str;
336     }
337     return 0;
338 }
339 void map_dump(map_t*map, FILE*fi, const char*prefix)
340 {
341     int t;
342     map_internal_t*m = (map_internal_t*)map->internal;
343     for(t=0;t<m->num;t++) {
344         string_t s1 = stringarray_at2(&m->keys, t);
345         string_t s2 = stringarray_at2(&m->values, t);
346         fprintf(fi, "%s%s=%s\n", prefix, s1.str, s2.str);
347     }
348 }
349 void map_clear(map_t*map)
350 {
351     map_internal_t*m = (map_internal_t*)map->internal;
352     stringarray_clear(&m->keys);
353     stringarray_clear(&m->values);
354     free(m);
355 }
356 void map_destroy(map_t*map)
357 {
358     map_clear(map);
359     free(map);
360 }
361
362 // ------------------------------- dictionary_t -------------------------------
363
364 typedef struct _dictionary_internal_t
365 {
366     stringarray_t keys;
367     mem_t values;
368     int num;
369 } dictionary_internal_t;
370
371 void dictionary_init(dictionary_t*dict)
372 {
373     dictionary_internal_t*d;
374     dict->internal = (dictionary_internal_t*)malloc(sizeof(dictionary_internal_t));
375     memset(dict->internal, 0, sizeof(dictionary_internal_t));
376     d = (dictionary_internal_t*)dict->internal;
377     stringarray_init(&d->keys);
378     mem_init(&d->values);
379 }
380 void dictionary_put(dictionary_t*dict, string_t t1, void* t2)
381 {
382     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
383     int s=0;
384     s = stringarray_find(&d->keys, &t1);
385     if(s>=0) {
386         /* replace */
387         *(void**)(&d->values.buffer[s*sizeof(void*)]) = t2;
388     } else {
389         stringarray_put(&d->keys, t1);
390         mem_put(&d->values, &t2, sizeof(void*));
391         d->num++;
392     }
393 }
394 void dictionary_put2(dictionary_t*dict, const char*t1, void* t2)
395 {
396     string_t s;
397     string_set(&s, (char*)t1);
398     dictionary_put(dict, s, t2);
399 }
400 void* dictionary_lookup(dictionary_t*dict, const char*name)
401 {
402     int s;
403     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
404     string_t str;
405     string_set(&str, (char*)name);
406     s = stringarray_find(&d->keys, &str);
407     if(s>=0) {
408         return *(void**)&d->values.buffer[sizeof(void*)*s];
409     }
410     return 0;
411 }
412 void dictionary_dump(dictionary_t*dict, FILE*fi, const char*prefix)
413 {
414     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
415     int t;
416     for(t=0;t<d->num;t++) {
417         string_t s1 = stringarray_at2(&d->keys, t);
418         fprintf(fi, "%s%s=%08x\n", prefix, s1.str, *(void**)&d->values.buffer[sizeof(void*)*t]);
419     }
420 }
421 void dictionary_del(dictionary_t*dict, const char* name)
422 {
423     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
424     int s;
425     string_t str;
426     string_set(&str, (char*)name);
427     s = stringarray_find(&d->keys, &str);
428     if(s>=0) {
429         *(void**)(&d->values.buffer[s*sizeof(void*)]) = 0;
430         stringarray_del(&d->keys, s);
431     }
432 }
433 void dictionary_clear(dictionary_t*dict)
434 {
435     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
436     stringarray_clear(&d->keys);
437     mem_clear(&d->values);
438     free(d);
439 }
440 void dictionary_destroy(dictionary_t*dict)
441 {
442     dictionary_clear(dict);
443     free(dict);
444 }