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