add description field for sinks/sources
[profile/ivi/pulseaudio.git] / src / strbuf.c
1 #include <sys/types.h>
2 #include <stdlib.h>
3 #include <assert.h>
4 #include <string.h>
5 #include <stdarg.h>
6 #include <stdio.h>
7
8 struct chunk {
9     struct chunk *next;
10     size_t length;
11     char text[];
12 };
13
14 struct pa_strbuf {
15     size_t length;
16     struct chunk *head, *tail;
17 };
18
19 struct pa_strbuf *pa_strbuf_new(void) {
20     struct pa_strbuf *sb = malloc(sizeof(struct pa_strbuf));
21     assert(sb);
22     sb->length = 0;
23     sb->head = sb->tail = NULL;
24     return sb;
25 }
26
27 void pa_strbuf_free(struct pa_strbuf *sb) {
28     assert(sb);
29     while (sb->head) {
30         struct chunk *c = sb->head;
31         sb->head = sb->head->next;
32         free(c);
33     }
34
35     free(sb);
36 }
37
38 char *pa_strbuf_tostring(struct pa_strbuf *sb) {
39     char *t, *e;
40     struct chunk *c;
41     assert(sb);
42
43     t = malloc(sb->length+1);
44     assert(t);
45
46     e = t;
47     for (c = sb->head; c; c = c->next) {
48         memcpy(e, c->text, c->length);
49         e += c->length;
50     }
51
52     *e = 0;
53     
54     return t;
55 }
56
57 char *pa_strbuf_tostring_free(struct pa_strbuf *sb) {
58     char *t;
59     assert(sb);
60     t = pa_strbuf_tostring(sb);
61     pa_strbuf_free(sb);
62     return t;
63 }
64
65 void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) {
66     struct chunk *c;
67     size_t l;
68     assert(sb && t);
69
70     l = strlen(t);
71     c = malloc(sizeof(struct chunk)+l);
72     assert(c);
73
74     c->next = NULL;
75     c->length = l;
76     memcpy(c->text, t, l);
77
78     if (sb->tail) {
79         assert(sb->head);
80         sb->tail->next = c;
81     } else {
82         assert(!sb->head);
83         sb->head = c;
84     }
85
86     sb->tail = c;
87     sb->length += l;
88 }
89
90 /* The following is based on an example from the GNU libc documentation */
91
92 int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) {
93     int r, size = 100;
94     struct chunk *c = NULL;
95
96     assert(sb);
97     
98     for(;;) {
99         va_list ap;
100
101         c = realloc(c, sizeof(struct chunk)+size);
102         assert(c);
103
104         va_start(ap, format);
105         r = vsnprintf(c->text, size, format, ap);
106         va_end(ap);
107         
108         if (r > -1 && r < size) {
109             c->length = r;
110             c->next = NULL;
111             
112             if (sb->tail) {
113                 assert(sb->head);
114                 sb->tail->next = c;
115             } else {
116                 assert(!sb->head);
117                 sb->head = c;
118             }
119             
120             sb->tail = c;
121             sb->length += r;
122             
123             return r;
124         }
125
126         if (r > -1)    /* glibc 2.1 */
127             size = r+1; 
128         else           /* glibc 2.0 */
129             size *= 2;
130     }
131 }