]> code.delx.au - pulseaudio/blob - polyp/tagstruct.c
5aa79e6c203262c8bcabfb1247fb8a0de130538e
[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_SAMPLE_SPEC = 'a',
43 TAG_ARBITRARY = 'x',
44 TAG_BOOLEAN_TRUE = '1',
45 TAG_BOOLEAN_FALSE = '0',
46 };
47
48 struct pa_tagstruct {
49 uint8_t *data;
50 size_t length, allocated;
51 size_t rindex;
52
53 int dynamic;
54 };
55
56 struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
57 struct pa_tagstruct*t;
58
59 assert(!data || (data && length));
60
61 t = pa_xmalloc(sizeof(struct pa_tagstruct));
62 t->data = (uint8_t*) data;
63 t->allocated = t->length = data ? length : 0;
64 t->rindex = 0;
65 t->dynamic = !data;
66 return t;
67 }
68
69 void pa_tagstruct_free(struct pa_tagstruct*t) {
70 assert(t);
71 if (t->dynamic)
72 pa_xfree(t->data);
73 pa_xfree(t);
74 }
75
76 uint8_t* pa_tagstruct_free_data(struct pa_tagstruct*t, size_t *l) {
77 uint8_t *p;
78 assert(t && t->dynamic && l);
79 p = t->data;
80 *l = t->length;
81 pa_xfree(t);
82 return p;
83 }
84
85 static void extend(struct pa_tagstruct*t, size_t l) {
86 assert(t && t->dynamic);
87
88 if (t->length+l <= t->allocated)
89 return;
90
91 t->data = pa_xrealloc(t->data, t->allocated = t->length+l+100);
92 }
93
94 void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) {
95 size_t l;
96 assert(t && s);
97 l = strlen(s)+2;
98 extend(t, l);
99 t->data[t->length] = TAG_STRING;
100 strcpy((char*) (t->data+t->length+1), s);
101 t->length += l;
102 }
103
104 void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) {
105 assert(t);
106 extend(t, 5);
107 t->data[t->length] = TAG_U32;
108 *((uint32_t*) (t->data+t->length+1)) = htonl(i);
109 t->length += 5;
110 }
111
112 void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) {
113 assert(t);
114 extend(t, 2);
115 t->data[t->length] = TAG_U8;
116 *(t->data+t->length+1) = c;
117 t->length += 2;
118 }
119
120 void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) {
121 assert(t && ss);
122 extend(t, 7);
123 t->data[t->length] = TAG_SAMPLE_SPEC;
124 t->data[t->length+1] = (uint8_t) ss->format;
125 t->data[t->length+2] = ss->channels;
126 *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate);
127 t->length += 7;
128 }
129
130 void pa_tagstruct_put_arbitrary(struct pa_tagstruct *t, const void *p, size_t length) {
131 assert(t && p);
132
133 extend(t, 5+length);
134 t->data[t->length] = TAG_ARBITRARY;
135 *((uint32_t*) (t->data+t->length+1)) = htonl(length);
136 if (length)
137 memcpy(t->data+t->length+5, p, length);
138 t->length += 5+length;
139 }
140
141 void pa_tagstruct_put_boolean(struct pa_tagstruct*t, int b) {
142 assert(t);
143 extend(t, 1);
144 t->data[t->length] = b ? TAG_BOOLEAN_TRUE : TAG_BOOLEAN_FALSE;
145 t->length += 1;
146 }
147
148 int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) {
149 int error = 0;
150 size_t n;
151 char *c;
152 assert(t && s);
153
154 if (t->rindex+2 > t->length)
155 return -1;
156
157 if (t->data[t->rindex] != TAG_STRING)
158 return -1;
159
160 error = 1;
161 for (n = 0, c = (char*) (t->data+t->rindex+1); t->rindex+1+n < t->length; n++, c++)
162 if (!*c) {
163 error = 0;
164 break;
165 }
166
167 if (error)
168 return -1;
169
170 *s = (char*) (t->data+t->rindex+1);
171
172 t->rindex += n+2;
173 return 0;
174 }
175
176 int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) {
177 assert(t && i);
178
179 if (t->rindex+5 > t->length)
180 return -1;
181
182 if (t->data[t->rindex] != TAG_U32)
183 return -1;
184
185 *i = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
186 t->rindex += 5;
187 return 0;
188 }
189
190 int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c) {
191 assert(t && c);
192
193 if (t->rindex+2 > t->length)
194 return -1;
195
196 if (t->data[t->rindex] != TAG_U8)
197 return -1;
198
199 *c = t->data[t->rindex+1];
200 t->rindex +=2;
201 return 0;
202 }
203
204 int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss) {
205 assert(t && ss);
206
207 if (t->rindex+7 > t->length)
208 return -1;
209
210 if (t->data[t->rindex] != TAG_SAMPLE_SPEC)
211 return -1;
212
213 ss->format = t->data[t->rindex+1];
214 ss->channels = t->data[t->rindex+2];
215 ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3));
216
217 t->rindex += 7;
218 return 0;
219 }
220
221 int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
222 assert(t && p);
223
224 if (t->rindex+5+length > t->length)
225 return -1;
226
227 if (t->data[t->rindex] != TAG_ARBITRARY)
228 return -1;
229
230 if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length)
231 return -1;
232
233 *p = t->data+t->rindex+5;
234 t->rindex += 5+length;
235 return 0;
236 }
237
238 int pa_tagstruct_eof(struct pa_tagstruct*t) {
239 assert(t);
240 return t->rindex >= t->length;
241 }
242
243 const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) {
244 assert(t && t->dynamic && l);
245 *l = t->length;
246 return t->data;
247 }
248
249 int pa_tagstruct_get_boolean(struct pa_tagstruct*t, int *b) {
250 assert(t && b);
251
252 if (t->rindex+1 > t->length)
253 return -1;
254
255 if (t->data[t->rindex] == TAG_BOOLEAN_TRUE)
256 *b = 1;
257 else if (t->data[t->rindex] == TAG_BOOLEAN_FALSE)
258 *b = 0;
259 else
260 return -1;
261
262 t->rindex +=1;
263 return 0;
264 }
265
266