]> code.delx.au - pulseaudio/blob - polyp/tagstruct.c
rename src to polyp
[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
33 enum tags {
34 TAG_STRING = 't',
35 TAG_U32 = 'L',
36 TAG_S32 = 'l',
37 TAG_U16 = 'S',
38 TAG_S16 = 's',
39 TAG_U8 = 'B',
40 TAG_S8 = 'b',
41 TAG_SAMPLE_SPEC = 'a',
42 TAG_ARBITRARY = 'x'
43 };
44
45 struct pa_tagstruct {
46 uint8_t *data;
47 size_t length, allocated;
48 size_t rindex;
49
50 int dynamic;
51 };
52
53 struct pa_tagstruct *pa_tagstruct_new(const uint8_t* data, size_t length) {
54 struct pa_tagstruct*t;
55
56 assert(!data || (data && length));
57
58 t = malloc(sizeof(struct pa_tagstruct));
59 assert(t);
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 free(t->data);
71 free(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 free(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 (l <= t->allocated)
87 return;
88
89 t->data = realloc(t->data, t->allocated = l+100);
90 assert(t->data);
91 }
92
93 void pa_tagstruct_puts(struct pa_tagstruct*t, const char *s) {
94 size_t l;
95 assert(t && s);
96 l = strlen(s)+2;
97 extend(t, l);
98 t->data[t->length] = TAG_STRING;
99 strcpy(t->data+t->length+1, s);
100 t->length += l;
101 }
102
103 void pa_tagstruct_putu32(struct pa_tagstruct*t, uint32_t i) {
104 assert(t);
105 extend(t, 5);
106 t->data[t->length] = TAG_U32;
107 *((uint32_t*) (t->data+t->length+1)) = htonl(i);
108 t->length += 5;
109 }
110
111 void pa_tagstruct_putu8(struct pa_tagstruct*t, uint8_t c) {
112 assert(t);
113 extend(t, 2);
114 t->data[t->length] = TAG_U8;
115 *(t->data+t->length+1) = c;
116 t->length += 2;
117 }
118
119 void pa_tagstruct_put_sample_spec(struct pa_tagstruct *t, const struct pa_sample_spec *ss) {
120 assert(t && ss);
121 extend(t, 7);
122 t->data[t->length] = TAG_SAMPLE_SPEC;
123 t->data[t->length+1] = (uint8_t) ss->format;
124 t->data[t->length+2] = ss->channels;
125 *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate);
126 t->length += 7;
127 }
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 int pa_tagstruct_gets(struct pa_tagstruct*t, const char **s) {
142 int error = 0;
143 size_t n;
144 char *c;
145 assert(t && s);
146
147 if (t->rindex+2 > t->length)
148 return -1;
149
150 if (t->data[t->rindex] != TAG_STRING)
151 return -1;
152
153 error = 1;
154 for (n = 0, c = (char*) (t->data+t->rindex+1); t->rindex+1+n < t->length; n++, c++)
155 if (!*c) {
156 error = 0;
157 break;
158 }
159
160 if (error)
161 return -1;
162
163 *s = (char*) (t->data+t->rindex+1);
164
165 t->rindex += n+2;
166 return 0;
167 }
168
169 int pa_tagstruct_getu32(struct pa_tagstruct*t, uint32_t *i) {
170 assert(t && i);
171
172 if (t->rindex+5 > t->length)
173 return -1;
174
175 if (t->data[t->rindex] != TAG_U32)
176 return -1;
177
178 *i = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
179 t->rindex += 5;
180 return 0;
181 }
182
183 int pa_tagstruct_getu8(struct pa_tagstruct*t, uint8_t *c) {
184 assert(t && c);
185
186 if (t->rindex+2 > t->length)
187 return -1;
188
189 if (t->data[t->rindex] != TAG_U8)
190 return -1;
191
192 *c = t->data[t->rindex+1];
193 t->rindex +=2;
194 return 0;
195 }
196
197 int pa_tagstruct_get_sample_spec(struct pa_tagstruct *t, struct pa_sample_spec *ss) {
198 assert(t && ss);
199
200 if (t->rindex+7 > t->length)
201 return -1;
202
203 if (t->data[t->rindex] != TAG_SAMPLE_SPEC)
204 return -1;
205
206 ss->format = t->data[t->rindex+1];
207 ss->channels = t->data[t->rindex+2];
208 ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3));
209
210 t->rindex += 7;
211 return 0;
212 }
213
214 int pa_tagstruct_get_arbitrary(struct pa_tagstruct *t, const void **p, size_t length) {
215 assert(t && p);
216
217 if (t->rindex+5+length > t->length)
218 return -1;
219
220 if (t->data[t->rindex] != TAG_ARBITRARY)
221 return -1;
222
223 if (ntohl(*((uint32_t*) (t->data+t->rindex+1))) != length)
224 return -1;
225
226 *p = t->data+t->rindex+5;
227 t->rindex += 5+length;
228 return 0;
229 }
230
231 int pa_tagstruct_eof(struct pa_tagstruct*t) {
232 assert(t);
233 return t->rindex >= t->length;
234 }
235
236 const uint8_t* pa_tagstruct_data(struct pa_tagstruct*t, size_t *l) {
237 assert(t && t->dynamic && l);
238 *l = t->length;
239 return t->data;
240 }
241