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