renamed strndup to strdup_n.
[swftools.git] / lib / 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* strdup_n(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 strdup_n(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 } ringbuffer_internal_t;
110
111 void ringbuffer_init(ringbuffer_t*r)
112 {
113     ringbuffer_internal_t*i = (ringbuffer_internal_t*)malloc(sizeof(ringbuffer_internal_t)); 
114     memset(r, 0, sizeof(ringbuffer_t));
115     memset(i, 0, sizeof(ringbuffer_internal_t));
116     r->internal = i;
117     i->buffer = (unsigned char*)malloc(1024);
118     i->buffersize = 1024;
119 }
120 int ringbuffer_read(ringbuffer_t*r, void*buf, int len)
121 {
122     unsigned char* data = (unsigned char*)buf;
123     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
124     if(r->available < len)
125         len = r->available;
126     if(!len)
127         return 0;
128     if(i->readpos + len > i->buffersize) {
129         int read1 = i->buffersize-i->readpos;
130         memcpy(data, &i->buffer[i->readpos], read1);
131         memcpy(&data[read1], &i->buffer[0], len - read1);
132         i->readpos = len - read1;
133     } else {
134         memcpy(data, &i->buffer[i->readpos], len);
135         i->readpos += len;
136         i->readpos %= i->buffersize;
137     }
138     r->available -= len;
139     return len;
140 }
141 void ringbuffer_put(ringbuffer_t*r, void*buf, int len)
142 {
143     unsigned char* data = (unsigned char*)buf;
144     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
145     
146     if(i->buffersize - r->available < len)
147     {
148         unsigned char* buf2;
149         int newbuffersize = i->buffersize;
150         int oldavailable = r->available;
151         newbuffersize*=3;newbuffersize/=2; /*grow at least by 50% each time */
152
153         if(newbuffersize < r->available + len)
154             newbuffersize = r->available + len + 1024;
155
156         buf2 = (unsigned char*)malloc(newbuffersize);
157         ringbuffer_read(r, buf2, r->available);
158         free(i->buffer);
159         i->buffer = buf2;
160         i->buffersize = newbuffersize;
161         i->readpos = 0;
162         i->writepos = oldavailable;
163         r->available = oldavailable;
164     }
165     if(i->writepos + len > i->buffersize) {
166         int read1 = i->buffersize-i->writepos;
167         memcpy(&i->buffer[i->writepos], data, read1);
168         memcpy(&i->buffer[0], &data[read1], len - read1);
169         i->writepos = len - read1;
170     } else {
171         memcpy(&i->buffer[i->writepos], data, len);
172         i->writepos += len;
173         i->writepos %= i->buffersize;
174     }
175     r->available += len;
176 }
177 void ringbuffer_clear(ringbuffer_t*r)
178 {
179     ringbuffer_internal_t*i = (ringbuffer_internal_t*)r->internal;
180     free(i->buffer);
181     free(i);
182 }
183
184 // ------------------------------- string_t -----------------------------------
185
186 void string_set2(string_t*str, char*text, int len)
187 {
188     str->len = len;
189     str->str = text;
190 }
191 void string_set(string_t*str, char*text)
192 {
193     str->len = strlen(text);
194     str->str = text;
195 }
196 void string_dup2(string_t*str, const char*text, int len)
197 {
198     str->len = len;
199     str->str = strdup_n(text, len);
200 }
201 void string_dup(string_t*str, const char*text)
202 {
203     str->len = strlen(text);
204     str->str = strdup(text);
205 }
206 int string_equals(string_t*str, const char*text)
207 {
208     int l = strlen(text);
209     if(str->len == l && !strncmp(str->str, text, l))
210         return 1;
211     return 0;
212 }
213 int string_equals2(string_t*str, string_t*str2)
214 {
215     if(str->len == str2->len && !strncmp(str->str, str2->str, str->len))
216         return 1;
217     return 0;
218 }
219 char* string_cstr(string_t*str)
220 {
221     return strdup_n(str->str, str->len);
222 }
223
224 // ------------------------------- stringarray_t ------------------------------
225
226 typedef struct _stringarray_internal_t
227 {
228     mem_t data;
229     mem_t pos;
230     int num;
231 } stringarray_internal_t;
232 void stringarray_init(stringarray_t*sa)
233 {
234     stringarray_internal_t*s;
235     sa->internal = (stringarray_internal_t*)malloc(sizeof(stringarray_internal_t)); 
236     memset(sa->internal, 0, sizeof(stringarray_internal_t));
237     s = (stringarray_internal_t*)sa->internal;
238     mem_init(&s->data);
239     mem_init(&s->pos);
240 }
241 void stringarray_put(stringarray_t*sa, string_t str)
242 {
243     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
244     int pos;
245     pos = mem_putstring(&s->data, str);
246     mem_put(&s->pos, &pos, sizeof(int));
247     s->num++;
248 }
249 char* stringarray_at(stringarray_t*sa, int pos)
250 {
251     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
252     int p;
253     if(pos<0 || pos>=s->num)
254         return 0;
255     p = *(int*)&s->pos.buffer[pos*sizeof(int)];
256     if(p<0)
257         return 0;
258     return &s->data.buffer[p];
259 }
260 string_t stringarray_at2(stringarray_t*sa, int pos)
261 {
262     string_t s;
263     s.str = stringarray_at(sa, pos);
264     s.len = s.str?strlen(s.str):0;
265     return s;
266 }
267 void stringarray_del(stringarray_t*sa, int pos)
268 {
269     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
270     *(int*)&s->pos.buffer[pos*sizeof(int)] = -1;
271 }
272 int stringarray_find(stringarray_t*sa, string_t* str)
273 {
274     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
275     int t;
276     for(t=0;t<s->num;t++) {
277         string_t s = stringarray_at2(sa, t);
278         if(s.str && string_equals2(&s, str)) {
279             return t;
280         }
281     }
282     return -1;
283 }
284 void stringarray_clear(stringarray_t*sa)
285 {
286     stringarray_internal_t*s = (stringarray_internal_t*)sa->internal;
287     mem_clear(&s->data);
288     mem_clear(&s->pos);
289     free(s);
290 }
291 void stringarray_destroy(stringarray_t*sa)
292 {
293     stringarray_clear(sa);
294     free(sa);
295 }
296
297
298 // ------------------------------- map_t --------------------------------------
299
300 typedef struct _map_internal_t
301 {
302     stringarray_t keys;
303     stringarray_t values;
304     int num;
305 } map_internal_t;
306
307 void map_init(map_t*map)
308 {
309     map_internal_t*m;
310     map->internal = (map_internal_t*)malloc(sizeof(map_internal_t));
311     memset(map->internal, 0, sizeof(map_internal_t));
312     m = (map_internal_t*)map->internal;
313     stringarray_init(&m->keys);
314     stringarray_init(&m->values);
315 }
316 void map_put(map_t*map, string_t t1, string_t t2)
317 {
318     map_internal_t*m = (map_internal_t*)map->internal;
319     stringarray_put(&m->keys, t1);
320     stringarray_put(&m->values, t2);
321     m->num++;
322 }
323 char* map_lookup(map_t*map, const char*name)
324 {
325     int s;
326     map_internal_t*m = (map_internal_t*)map->internal;
327     string_t str;
328     string_set(&str, (char*)name);
329     s = stringarray_find(&m->keys, &str);
330     if(s>=0) {
331         string_t s2 = stringarray_at2(&m->values, s);
332         return s2.str;
333     }
334     return 0;
335 }
336 void map_dump(map_t*map, FILE*fi, const char*prefix)
337 {
338     int t;
339     map_internal_t*m = (map_internal_t*)map->internal;
340     for(t=0;t<m->num;t++) {
341         string_t s1 = stringarray_at2(&m->keys, t);
342         string_t s2 = stringarray_at2(&m->values, t);
343         fprintf(fi, "%s%s=%s\n", prefix, s1.str, s2.str);
344     }
345 }
346 void map_clear(map_t*map)
347 {
348     map_internal_t*m = (map_internal_t*)map->internal;
349     stringarray_clear(&m->keys);
350     stringarray_clear(&m->values);
351     free(m);
352 }
353 void map_destroy(map_t*map)
354 {
355     map_clear(map);
356     free(map);
357 }
358
359 // ------------------------------- dictionary_t -------------------------------
360
361 typedef struct _dictionary_internal_t
362 {
363     stringarray_t keys;
364     mem_t values;
365     int num;
366 } dictionary_internal_t;
367
368 void dictionary_init(dictionary_t*dict)
369 {
370     dictionary_internal_t*d;
371     dict->internal = (dictionary_internal_t*)malloc(sizeof(dictionary_internal_t));
372     memset(dict->internal, 0, sizeof(dictionary_internal_t));
373     d = (dictionary_internal_t*)dict->internal;
374     stringarray_init(&d->keys);
375     mem_init(&d->values);
376 }
377 void dictionary_put(dictionary_t*dict, string_t t1, void* t2)
378 {
379     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
380     int s=0;
381     s = stringarray_find(&d->keys, &t1);
382     if(s>=0) {
383         /* replace */
384         *(void**)(&d->values.buffer[s*sizeof(void*)]) = t2;
385     } else {
386         stringarray_put(&d->keys, t1);
387         mem_put(&d->values, &t2, sizeof(void*));
388         d->num++;
389     }
390 }
391 void dictionary_put2(dictionary_t*dict, const char*t1, void* t2)
392 {
393     string_t s;
394     string_set(&s, (char*)t1);
395     dictionary_put(dict, s, t2);
396 }
397 void* dictionary_lookup(dictionary_t*dict, const char*name)
398 {
399     int s;
400     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
401     string_t str;
402     string_set(&str, (char*)name);
403     s = stringarray_find(&d->keys, &str);
404     if(s>=0) {
405         return *(void**)&d->values.buffer[sizeof(void*)*s];
406     }
407     return 0;
408 }
409 void dictionary_dump(dictionary_t*dict, FILE*fi, const char*prefix)
410 {
411     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
412     int t;
413     for(t=0;t<d->num;t++) {
414         string_t s1 = stringarray_at2(&d->keys, t);
415         fprintf(fi, "%s%s=%08x\n", prefix, s1.str, *(void**)&d->values.buffer[sizeof(void*)*t]);
416     }
417 }
418 void dictionary_del(dictionary_t*dict, const char* name)
419 {
420     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
421     int s;
422     string_t str;
423     string_set(&str, (char*)name);
424     s = stringarray_find(&d->keys, &str);
425     if(s>=0) {
426         *(void**)(&d->values.buffer[s*sizeof(void*)]) = 0;
427         stringarray_del(&d->keys, s);
428     }
429 }
430 void dictionary_clear(dictionary_t*dict)
431 {
432     dictionary_internal_t*d = (dictionary_internal_t*)dict->internal;
433     stringarray_clear(&d->keys);
434     mem_clear(&d->values);
435     free(d);
436 }
437 void dictionary_destroy(dictionary_t*dict)
438 {
439     dictionary_clear(dict);
440     free(dict);
441 }