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