basic cli interface
[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     char text[];
11 };
12
13 struct strbuf {
14     size_t length;
15     struct chunk *head, *tail;
16 };
17
18 struct strbuf *strbuf_new(void) {
19     struct strbuf *sb = malloc(sizeof(struct strbuf));
20     assert(sb);
21     sb->length = 0;
22     sb->head = sb->tail = NULL;
23     return sb;
24 }
25
26 void strbuf_free(struct strbuf *sb) {
27     assert(sb);
28     while (sb->head) {
29         struct chunk *c = sb->head;
30         sb->head = sb->head->next;
31         free(c);
32     }
33
34     free(sb);
35 }
36
37 char *strbuf_tostring(struct strbuf *sb) {
38     char *t, *e;
39     struct chunk *c;
40     assert(sb);
41
42     t = malloc(sb->length+1);
43     assert(t);
44
45     e = t;
46     *e = 0;
47     for (c = sb->head; c; c = c->next) {
48         strcpy(e, c->text);
49         e = strchr(e, 0);
50     }
51
52     return t;
53 }
54
55 char *strbuf_tostring_free(struct strbuf *sb) {
56     char *t;
57     assert(sb);
58     t = strbuf_tostring(sb);
59     strbuf_free(sb);
60     return t;
61 }
62
63 void strbuf_puts(struct strbuf *sb, const char *t) {
64     struct chunk *c;
65     size_t l;
66     assert(sb && t);
67
68     l = strlen(t);
69     c = malloc(sizeof(struct chunk)+l);
70     assert(c);
71
72     c->next = NULL;
73     strcpy(c->text, t);
74
75     if (sb->tail) {
76         assert(sb->head);
77         sb->tail->next = c;
78     } else {
79         assert(!sb->head);
80         sb->head = c;
81     }
82
83     sb->tail = c;
84     sb->length += l;
85 }
86
87 int strbuf_printf(struct strbuf *sb, const char *format, ...) {
88     int r, size = 100;
89     struct chunk *c = NULL;
90
91     assert(sb);
92     
93     for(;;) {
94         va_list ap;
95
96         c = realloc(c, sizeof(struct chunk)+size);
97         assert(c);
98
99         va_start(ap, format);
100         r = vsnprintf(c->text, size, format, ap);
101         va_end(ap);
102         
103         if (r > -1 && r < size) {
104             c->next = NULL;
105             
106             if (sb->tail) {
107                 assert(sb->head);
108                 sb->tail->next = c;
109             } else {
110                 assert(!sb->head);
111                 sb->head = c;
112             }
113             
114             sb->tail = c;
115             sb->length += r;
116             
117             return r;
118         }
119
120         if (r > -1)    /* glibc 2.1 */
121             size = r+1; 
122         else           /* glibc 2.0 */
123             size *= 2;
124     }
125 }