c6a3772db5892b0392b1f59bbcfbfde37aa85bf9
[profile/ivi/pulseaudio-panda.git] / polyp / strbuf.c
1 /* $Id$ */
2
3 /***
4   This file is part of polypaudio.
5  
6   polypaudio is free software; you can redistribute it and/or modify
7   it under the terms of the GNU General Public License as published
8   by the Free Software Foundation; either version 2 of the License,
9   or (at your option) any later version.
10  
11   polypaudio is distributed in the hope that it will be useful, but
12   WITHOUT ANY WARRANTY; without even the implied warranty of
13   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14   General Public License for more details.
15  
16   You should have received a copy of the GNU General Public License
17   along with polypaudio; 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 <sys/types.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 #include <string.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32
33 #include "strbuf.h"
34
35 struct chunk {
36     struct chunk *next;
37     size_t length;
38     char text[];
39 };
40
41 struct pa_strbuf {
42     size_t length;
43     struct chunk *head, *tail;
44 };
45
46 struct pa_strbuf *pa_strbuf_new(void) {
47     struct pa_strbuf *sb = malloc(sizeof(struct pa_strbuf));
48     assert(sb);
49     sb->length = 0;
50     sb->head = sb->tail = NULL;
51     return sb;
52 }
53
54 void pa_strbuf_free(struct pa_strbuf *sb) {
55     assert(sb);
56     while (sb->head) {
57         struct chunk *c = sb->head;
58         sb->head = sb->head->next;
59         free(c);
60     }
61
62     free(sb);
63 }
64
65 char *pa_strbuf_tostring(struct pa_strbuf *sb) {
66     char *t, *e;
67     struct chunk *c;
68     assert(sb);
69
70     t = malloc(sb->length+1);
71     assert(t);
72
73     e = t;
74     for (c = sb->head; c; c = c->next) {
75         memcpy(e, c->text, c->length);
76         e += c->length;
77     }
78
79     *e = 0;
80     
81     return t;
82 }
83
84 char *pa_strbuf_tostring_free(struct pa_strbuf *sb) {
85     char *t;
86     assert(sb);
87     t = pa_strbuf_tostring(sb);
88     pa_strbuf_free(sb);
89     return t;
90 }
91
92 void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) {
93     assert(sb && t);
94     pa_strbuf_putsn(sb, t, strlen(t));
95
96
97 void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) {
98     struct chunk *c;
99     assert(sb && t);
100     
101     if (!l)
102        return;
103    
104     c = malloc(sizeof(struct chunk)+l);
105     assert(c);
106
107     c->next = NULL;
108     c->length = l;
109     memcpy(c->text, t, l);
110
111     if (sb->tail) {
112         assert(sb->head);
113         sb->tail->next = c;
114     } else {
115         assert(!sb->head);
116         sb->head = c;
117     }
118
119     sb->tail = c;
120     sb->length += l;
121 }
122
123 /* The following is based on an example from the GNU libc documentation */
124
125 int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) {
126     int r, size = 100;
127     struct chunk *c = NULL;
128
129     assert(sb);
130     
131     for(;;) {
132         va_list ap;
133
134         c = realloc(c, sizeof(struct chunk)+size);
135         assert(c);
136
137         va_start(ap, format);
138         r = vsnprintf(c->text, size, format, ap);
139         va_end(ap);
140         
141         if (r > -1 && r < size) {
142             c->length = r;
143             c->next = NULL;
144             
145             if (sb->tail) {
146                 assert(sb->head);
147                 sb->tail->next = c;
148             } else {
149                 assert(!sb->head);
150                 sb->head = c;
151             }
152             
153             sb->tail = c;
154             sb->length += r;
155             
156             return r;
157         }
158
159         if (r > -1)    /* glibc 2.1 */
160             size = r+1; 
161         else           /* glibc 2.0 */
162             size *= 2;
163     }
164 }