]> git.meshlink.io Git - catta/blob - avahi-common/strlst.c
* add four new AvahiStringList functions (this is four you, Sebastien!)
[catta] / avahi-common / strlst.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27 #include <stdarg.h>
28 #include <assert.h>
29 #include <stdio.h>
30
31 #include "strlst.h"
32 #include "malloc.h"
33
34 AvahiStringList*avahi_string_list_add_anonymous(AvahiStringList *l, size_t size) {
35     AvahiStringList *n;
36
37     if (!(n = avahi_malloc(sizeof(AvahiStringList) + size)))
38         return NULL;
39     
40     n->next = l;
41     n->size = size;
42
43     /* NUL terminate strings, just to make sure */
44     n->text[size] = 0;
45
46     return n;
47 }
48
49 AvahiStringList *avahi_string_list_add_arbitrary(AvahiStringList *l, const uint8_t*text, size_t size) {
50     AvahiStringList *n;
51
52     assert(text);
53
54     if (!(n = avahi_string_list_add_anonymous(l, size)))
55         return NULL;
56
57     if (size > 0)
58         memcpy(n->text, text, size);
59
60     return n;
61 }
62
63 AvahiStringList *avahi_string_list_add(AvahiStringList *l, const char *text) {
64     assert(text);
65
66     return avahi_string_list_add_arbitrary(l, (const uint8_t*) text, strlen(text));
67 }
68
69 AvahiStringList *avahi_string_list_parse(const void* data, size_t size) {
70     AvahiStringList *r = NULL;
71     const uint8_t *c;
72     
73     assert(data);
74
75     c = data;
76     for (;;) {
77         size_t k;
78         
79         if (size < 1)
80             break;
81
82         k = *(c++);
83         r = avahi_string_list_add_arbitrary(r, c, k);
84         c += k;
85
86         size -= 1 + k;
87     }
88
89     return r;
90 }
91
92 void avahi_string_list_free(AvahiStringList *l) {
93     AvahiStringList *n;
94
95     while (l) {
96         n = l->next;
97         avahi_free(l);
98         l = n;
99     }
100 }
101
102 AvahiStringList* avahi_string_list_reverse(AvahiStringList *l) {
103     AvahiStringList *r = NULL, *n;
104
105     while (l) {
106         n = l->next;
107         l->next = r;
108         r = l;
109         l = n;
110     }
111
112     return r;
113 }
114
115 char* avahi_string_list_to_string(AvahiStringList *l) {
116     AvahiStringList *n;
117     size_t s = 0;
118     char *t, *e;
119
120     for (n = l; n; n = n->next) {
121         if (n != l)
122             s ++;
123
124         s += n->size+2;
125     }
126
127     if (!(t = e = avahi_new(char, s+1)))
128         return NULL;
129
130     l = avahi_string_list_reverse(l);
131     
132     for (n = l; n; n = n->next) {
133         if (n != l)
134             *(e++) = ' ';
135
136         *(e++) = '"';
137         strncpy(e, (char*) n->text, n->size);
138         e[n->size] = 0;
139         e = strchr(e, 0);
140         *(e++) = '"';
141
142         assert(e);
143     }
144
145     l = avahi_string_list_reverse(l);
146     
147     *e = 0;
148
149     return t;
150 }
151
152 size_t avahi_string_list_serialize(AvahiStringList *l, void *data, size_t size) {
153     size_t used = 0;
154
155     if (data) {
156         uint8_t *c;
157         AvahiStringList *n;
158     
159         assert(data);
160         
161         l = avahi_string_list_reverse(l);
162         c = data;
163         
164         for (n = l; n; n = n->next) {
165             size_t k;
166             if (size < 1)
167                 break;
168             
169             k = n->size;
170             if (k > 255)
171                 k = 255;
172             
173             if (k > size-1)
174                 k = size-1;
175             
176             *(c++) = k;
177             memcpy(c, n->text, k);
178             c += k;
179             
180             used += 1+ k;
181         }
182         
183         l = avahi_string_list_reverse(l);
184     } else {
185         AvahiStringList *n;
186
187         for (n = l; n; n = n->next) {
188             size_t k;
189         
190             k = n->size;
191             if (k > 255)
192                 k = 255;
193             
194             used += 1+k;
195         }
196     }
197
198     return used;
199 }
200
201 int avahi_string_list_equal(const AvahiStringList *a, const AvahiStringList *b) {
202
203     for (;;) {
204         if (!a && !b)
205             return 1;
206
207         if (!a || !b)
208             return 0;
209
210         if (a->size != b->size)
211             return 0;
212
213         if (a->size != 0 && memcmp(a->text, b->text, a->size) != 0)
214             return 0;
215
216         a = a->next;
217         b = b->next;
218     }
219 }
220
221 AvahiStringList *avahi_string_list_add_many(AvahiStringList *r, ...) {
222     va_list va;
223
224     va_start(va, r);
225     r = avahi_string_list_add_many_va(r, va);
226     va_end(va);
227     
228     return r;
229 }
230
231 AvahiStringList *avahi_string_list_add_many_va(AvahiStringList *r, va_list va) {
232     const char *txt;
233
234     while ((txt = va_arg(va, const char*)))
235         r = avahi_string_list_add(r, txt);
236
237     return r;
238 }
239
240 AvahiStringList *avahi_string_list_new(const char *txt, ...) {
241     va_list va;
242     AvahiStringList *r = NULL;
243
244     if (txt) {
245         r = avahi_string_list_add(r, txt);
246
247         va_start(va, txt);
248         r = avahi_string_list_add_many_va(r, va);
249         va_end(va);
250     }
251
252     return r;
253 }
254
255 AvahiStringList *avahi_string_list_new_va(va_list va) {
256     return avahi_string_list_add_many_va(NULL, va);
257 }
258
259 AvahiStringList *avahi_string_list_copy(const AvahiStringList *l) {
260     AvahiStringList *r = NULL;
261
262     for (; l; l = l->next)
263         r = avahi_string_list_add_arbitrary(r, l->text, l->size);
264
265     return avahi_string_list_reverse(r);
266 }
267
268 AvahiStringList *avahi_string_list_new_from_array(const char *array[], int length) {
269     AvahiStringList *r = NULL;
270     int i;
271
272     assert(array);
273
274     for (i = 0; length >= 0 ? i < length : !!array[i]; i++)
275         r = avahi_string_list_add(r, array[i]);
276
277     return r;
278 }
279
280 unsigned avahi_string_list_length(const AvahiStringList *l) {
281     unsigned n = 0;
282
283     for (; l; l = l->next)
284         n++;
285
286     return n;
287 }
288
289 AvahiStringList *avahi_string_list_add_vprintf(AvahiStringList *l, const char *format, va_list va) {
290     size_t len = 80;
291     AvahiStringList *r;
292     
293     assert(format);
294
295     if (!(r = avahi_malloc(sizeof(AvahiStringList) + len)))
296         return NULL;
297
298     for (;;) {
299         int n;
300         AvahiStringList *nr;
301         
302         n = vsnprintf((char*) r->text, len+1, format, va);
303
304         if (n >= 0 && n < (int) len)
305             break;
306
307         if (n >= 0)
308             len = n+1;
309         else
310             len *= 2;
311
312         if (!(nr = avahi_realloc(r, sizeof(AvahiStringList) + len))) {
313             avahi_free(r);
314             return NULL;
315         }
316
317         r = nr;
318     }
319
320     
321     r->next = l;
322     r->size = strlen((char*) r->text); 
323
324     return r;
325 }
326
327 AvahiStringList *avahi_string_list_add_printf(AvahiStringList *l, const char *format, ...) {
328     va_list va;
329     
330     assert(format);
331
332     va_start(va, format);
333     l  = avahi_string_list_add_vprintf(l, format, va);
334     va_end(va);
335
336     return l;    
337 }
338
339 AvahiStringList *avahi_string_list_find(AvahiStringList *l, const char *key) {
340     size_t n;
341     
342     assert(key);
343     n = strlen(key);
344
345     for (; l; l = l->next) {
346         if (strcasecmp((char*) l->text, key) == 0)
347             return l;
348
349         if (strncasecmp((char*) l->text, key, n) == 0 && l->text[n] == '=')
350             return l;
351     }
352
353     return NULL;
354 }
355
356 AvahiStringList *avahi_string_list_add_pair(AvahiStringList *l, const char *key, const char *value) {
357     assert(key);
358
359     if (value)
360         return avahi_string_list_add_printf(l, "%s=%s", key, value);
361     else
362         return avahi_string_list_add(l, key);
363 }
364
365 AvahiStringList *avahi_string_list_add_pair_arbitrary(AvahiStringList *l, const char *key, const uint8_t *value, size_t size) {
366     size_t n;
367     assert(key);
368
369     if (!value)
370         return avahi_string_list_add(l, key);
371
372     n = strlen(key);
373     
374     if (!(l = avahi_string_list_add_anonymous(l, n + 1 + size)))
375         return NULL;
376
377     memcpy(l->text, key, n);
378     l->text[n] = '=';
379     memcpy(l->text + n + 1, value, size);
380
381     return l;
382 }
383
384
385 int avahi_string_list_get_pair(AvahiStringList *l, char **key, char **value, size_t *size) {
386     char *e;
387     
388     assert(l);
389     assert(key);
390
391     if (!(e = memchr(l->text, '=', l->size))) {
392         
393         if (!(*key = avahi_strdup((char*) l->text)))
394             return -1;
395
396         if (value)
397             *value = NULL;
398
399         if (size)
400             *size = 0;
401
402     } else {
403         size_t n;
404
405         if (!(*key = avahi_strndup((char*) l->text, e - (char *) l->text)))
406             return -1;
407
408         e++; /* Advance after '=' */
409         
410         n = l->size - (e - (char*) l->text);
411         
412         if (value) {
413
414             if (!(*value = avahi_memdup(e, n+1))) {
415                 avahi_free(*key);
416                 return -1;
417             }
418
419             (*value)[n] = 0;
420         }
421
422         if (size)
423             *size = n;
424     }
425
426     return 0;
427 }