]> code.delx.au - pulseaudio/blob - polyp/tagstruct.c
make module-combine autoloadable
[pulseaudio] / polyp / tagstruct.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 <stdlib.h>
27 #include <string.h>
28 #include <netinet/in.h>
29 #include <assert.h>
30
31 #include "tagstruct.h"
32 #include "xmalloc.h"
33
34 enum tags {
35 TAG_STRING = 't',
36 TAG_U32 = 'L',
37 TAG_S32 = 'l',
38 TAG_U16 = 'S',
39 TAG_S16 = 's',
40 TAG_U8 = 'B',
41 TAG_S8 = 'b',
42 TAG_U64 = 'R',
43 TAG_S64 = 'r',
44 TAG_SAMPLE_SPEC = 'a',
45 TAG_ARBITRARY = 'x',
46 TAG_BOOLEAN_TRUE = '1',
47 TAG_BOOLEAN_FALSE = '0',
48 TAG_TIMEVAL = 'T',
49 TAG_USEC = 'U', /* 64bit unsigned */
50 };
51
52 struct pa_tagstruct {
53 uint8_t *data;
54 size_t length, allocated;
55 size_t rindex;
56
57 int dynamic;
58 };
59
60 struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
61 struct pa_tagstruct*t;
62
63 assert(!data || (data && length));
64
65 t = pa_xmalloc(sizeof(struct pa_tagstruct));
66 t->data = (uint8_t*) data;
67 t->allocated = t->length = data ? length : 0;
68 t->rindex = 0;
69 t->dynamic = !data;
70 return t;
71 }
72
73 void pa_tagstruct_free(struct pa_tagstruct*t) {
74 assert(t);
75 if (t->dynamic)
76 pa_xfree(t->data);
77 pa_xfree(t);
78 }
79
80 uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) {
81 uint8_t *p;
82 assert(t && t->dynamic && l);
83 p = t->data;
84 *l = t->length;
85 pa_xfree(t);
86 return p;
87 }
88
89 static void extend(struct pa_tagstruct*t, size_t l) {
90 assert(t && t->dynamic);
91
92 if (t->length+l <= t->allocated)
93 return;
94
95 t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100);
96 }
97
98 void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) {
99 size_t l;
100 assert(t && s);
101 l = strlen(s)+2;
102 extend(t, l);
103 t->data[t->length] = TAG_STRING;
104 strcpy((char*) (t->data+t->length+1), s);
105 t->length += l;
106 }
107
108 void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) {
109 assert(t);
110 extend(t, 5);
111 t->data[t->length] = TAG_U32;
112 *((uint32_t*) (t->data+t->length+1)) = htonl(i);
113 t->length += 5;
114 }
115
116 void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) {
117 assert(t);
118 extend(t, 2);
119 t->data[t->length] = TAG_U8;
120 *(t->data+t->length+1) = c;
121 t->length += 2;
122 }
123
124 void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) {
125 assert(t && ss);
126 extend(t, 7);
127 t->data[t->length] = TAG_SAMPLE_SPEC;
128 t->data[t->length+1] = (uint8_t) ss->format;
129 t->data[t->length+2] = ss->channels;
130 *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate);
131 t->length += 7;
132 }
133
134 void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
135 assert(t && p);
136
137 extend(t, 5+length);
138 t->data[t->length] = TAG_ARBITRARY;
139 *((uint32_t*) (t->data+t->length+1)) = htonl(length);
140 if (length)
141 memcpy(t->data+t->length+5, p, length);
142 t->length += 5+length;
143 }
144
145 void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) {
146 assert(t);
147 extend(t, 1);
148 t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE;
149 t->length += 1;
150 }
151
152 void pa_tagstruct_put_timeval(struct pa_tagstruct*t, const struct timeval *tv) {
153 assert(t);
154 extend(t, 9);
155 t->data[t->length] = TAG_TIMEVAL;
156 *((uint32_t*) (t->data+t->length+1)) = htonl(tv->tv_sec);
157 *((uint32_t*) (t->data+t->length+5)) = htonl(tv->tv_usec);
158 t->length += 9;
159 }
160
161 void pa_tagstruct_put_usec(struct pa_tagstruct*t, pa_usec_t u) {
162 assert(t);
163 extend(t, 9);
164 t->data[t->length] = TAG_USEC;
165 *((uint32_t*) (t->data+t->length+1)) = htonl((uint32_t) (u >> 32));
166 *((uint32_t*) (t->data+t->length+5)) = htonl((uint32_t) u);
167 t->length += 9;
168 }
169
170 int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) {
171 int error = 0;
172 size_t n;
173 char *c;
174 assert(t && s);
175
176 if (t->rindex+2 > t->length)
177 return -1;
178
179 if (t->data[t->rindex] != TAG_STRING)
180 return -1;
181
182 error = 1;
183 for (n = 0, c = (char*) (t->data+t->rindex+1); t->rindex+1+n < t->length; n++, c++)
184 if (!*c) {
185 error = 0;
186 break;
187 }
188
189 if (error)
190 return -1;
191
192 *s = (char*) (t->data+t->rindex+1);
193
194 t->rindex += n+2;
195 return 0;
196 }
197
198 int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) {
199 assert(t && i);
200
201 if (t->rindex+5 > t->length)
202 return -1;
203
204 if (t->data[t->rindex] != TAG_U32)
205 return -1;
206
207 *i = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
208 t->rindex += 5;
209 return 0;
210 }
211
212 int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c) {
213 assert(t && c);
214
215 if (t->rindex+2 > t->length)
216 return -1;
217
218 if (t->data[t->rindex] != TAG_U8)
219 return -1;
220
221 *c = t->data[t->rindex+1];
222 t->rindex +=2;
223 return 0;
224 }
225
226 int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss) {
227 assert(t && ss);
228
229 if (t->rindex+7 > t->length)
230 return -1;
231
232 if (t->data[t->rindex] != TAG_SAMPLE_SPEC)
233 return -1;
234
235 ss->format = t->data[t->rindex+1];
236 ss->channels = t->data[t->rindex+2];
237 ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3));
238
239 t->rindex += 7;
240 return 0;
241 }
242
243 int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
244 assert(t && p);
245
246 if (t->rindex+5+length > t->length)
247 return -1;
248
249 if (t->data[t->rindex] != TAG_ARBITRARY)
250 return -1;
251
252 if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length)
253 return -1;
254
255 *p = t->data+t->rindex+5;
256 t->rindex += 5+length;
257 return 0;
258 }
259
260 int pa_tagstruct_eof(struct pa_tagstruct*t) {
261 assert(t);
262 return t->rindex >= t->length;
263 }
264
265 const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) {
266 assert(t && t->dynamic && l);
267 *l = t->length;
268 return t->data;
269 }
270
271 int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) {
272 assert(t && b);
273
274 if (t->rindex+1 > t->length)
275 return -1;
276
277 if (t->data[t->rindex] == TAG_BOOLEAN_TRUE)
278 *b = 1;
279 else if (t->data[t->rindex] == TAG_BOOLEAN_FALSE)
280 *b = 0;
281 else
282 return -1;
283
284 t->rindex +=1;
285 return 0;
286 }
287
288 int pa_tagstruct_get_timeval(struct pa_tagstruct*t, struct timeval *tv) {
289
290 if (t->rindex+9 > t->length)
291 return -1;
292
293 if (t->data[t->rindex] != TAG_TIMEVAL)
294 return -1;
295
296 tv->tv_sec = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
297 tv->tv_usec = ntohl(*((uint32_t*) (t->data+t->rindex+5)));
298 t->rindex += 9;
299 return 0;
300
301 }
302
303 int pa_tagstruct_get_usec(struct pa_tagstruct*t, pa_usec_t *u) {
304 assert(t && u);
305
306 if (t->rindex+9 > t->length)
307 return -1;
308
309 if (t->data[t->rindex] != TAG_USEC)
310 return -1;
311
312 *u = (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+1))) << 32;
313 *u |= (pa_usec_t) ntohl(*((uint32_t*) (t->data+t->rindex+5)));
314 t->rindex +=9;
315 return 0;
316 }