]> code.delx.au - pulseaudio/blob - polyp/strbuf.c
Make the whole stuff LGPL only
[pulseaudio] / 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 Lesser 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 Lesser 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 #include <xmalloc.h>
33
34 #include "strbuf.h"
35
36 #ifdef __STDC_VERSION__
37 #if __STDC_VERSION__ >= 199901L
38 #ifndef STDC99
39 #define STDC99
40 #endif
41 #endif
42 #endif
43
44 struct chunk {
45 struct chunk *next;
46 size_t length;
47 #ifdef STDC99
48 char text[];
49 #else
50 char text[0];
51 #endif
52 };
53
54 struct pa_strbuf {
55 size_t length;
56 struct chunk *head, *tail;
57 };
58
59 struct pa_strbuf *pa_strbuf_new(void) {
60 struct pa_strbuf *sb = pa_xmalloc(sizeof(struct pa_strbuf));
61 sb->length = 0;
62 sb->head = sb->tail = NULL;
63 return sb;
64 }
65
66 void pa_strbuf_free(struct pa_strbuf *sb) {
67 assert(sb);
68 while (sb->head) {
69 struct chunk *c = sb->head;
70 sb->head = sb->head->next;
71 pa_xfree(c);
72 }
73
74 pa_xfree(sb);
75 }
76
77 char *pa_strbuf_tostring(struct pa_strbuf *sb) {
78 char *t, *e;
79 struct chunk *c;
80 assert(sb);
81
82 t = pa_xmalloc(sb->length+1);
83
84 e = t;
85 for (c = sb->head; c; c = c->next) {
86 memcpy(e, c->text, c->length);
87 e += c->length;
88 }
89
90 *e = 0;
91
92 return t;
93 }
94
95 char *pa_strbuf_tostring_free(struct pa_strbuf *sb) {
96 char *t;
97 assert(sb);
98 t = pa_strbuf_tostring(sb);
99 pa_strbuf_free(sb);
100 return t;
101 }
102
103 void pa_strbuf_puts(struct pa_strbuf *sb, const char *t) {
104 assert(sb && t);
105 pa_strbuf_putsn(sb, t, strlen(t));
106 }
107
108 void pa_strbuf_putsn(struct pa_strbuf *sb, const char *t, size_t l) {
109 struct chunk *c;
110 assert(sb && t);
111
112 if (!l)
113 return;
114
115 c = pa_xmalloc(sizeof(struct chunk)+l);
116
117 c->next = NULL;
118 c->length = l;
119 memcpy(c->text, t, l);
120
121 if (sb->tail) {
122 assert(sb->head);
123 sb->tail->next = c;
124 } else {
125 assert(!sb->head);
126 sb->head = c;
127 }
128
129 sb->tail = c;
130 sb->length += l;
131 }
132
133 /* The following is based on an example from the GNU libc documentation */
134
135 int pa_strbuf_printf(struct pa_strbuf *sb, const char *format, ...) {
136 int r, size = 100;
137 struct chunk *c = NULL;
138
139 assert(sb);
140
141 for(;;) {
142 va_list ap;
143
144 c = pa_xrealloc(c, sizeof(struct chunk)+size);
145
146 va_start(ap, format);
147 r = vsnprintf(c->text, size, format, ap);
148 va_end(ap);
149
150 if (r > -1 && r < size) {
151 c->length = r;
152 c->next = NULL;
153
154 if (sb->tail) {
155 assert(sb->head);
156 sb->tail->next = c;
157 } else {
158 assert(!sb->head);
159 sb->head = c;
160 }
161
162 sb->tail = c;
163 sb->length += r;
164
165 return r;
166 }
167
168 if (r > -1) /* glibc 2.1 */
169 size = r+1;
170 else /* glibc 2.0 */
171 size *= 2;
172 }
173 }