]> code.delx.au - pulseaudio/blob - polyp/strbuf.c
rename src to polyp
[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 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 }