]> code.delx.au - pulseaudio/blob - src/tagstruct.c
429dd40885a61682e65b0b8c6302086839c4e5fe
[pulseaudio] / src / tagstruct.c
1 #include <stdlib.h>
2 #include <string.h>
3 #include <netinet/in.h>
4 #include <assert.h>
5
6 #include "tagstruct.h"
7
8 enum tags {
9 TAG_STRING = 't',
10 TAG_U32 = 'L',
11 TAG_S32 = 'l',
12 TAG_U16 = 'S',
13 TAG_S16 = 's',
14 TAG_U8 = 'B',
15 TAG_S8 = 'b',
16 TAG_SAMPLE_SPEC = 'a'
17 };
18
19 struct tagstruct {
20 uint8_t *data;
21 size_t length, allocated;
22 size_t rindex;
23
24 int dynamic;
25 };
26
27 struct tagstruct *tagstruct_new(const uint8_t* data, size_t length) {
28 struct tagstruct*t;
29
30 assert(!data || (data && length));
31
32 t = malloc(sizeof(struct tagstruct));
33 assert(t);
34 t->data = (uint8_t*) data;
35 t->allocated = t->length = data ? length : 0;
36 t->rindex = 0;
37 t->dynamic = !!data;
38 return t;
39 }
40
41 void tagstruct_free(struct tagstruct*t) {
42 assert(t);
43 if (t->dynamic)
44 free(t->data);
45 free(t);
46 }
47
48 uint8_t* tagstruct_free_data(struct tagstruct*t, size_t *l) {
49 uint8_t *p;
50 assert(t && t->dynamic && l);
51 p = t->data;
52 *l = t->length;
53 free(t);
54 return p;
55 }
56
57 static void extend(struct tagstruct*t, size_t l) {
58 assert(t && t->dynamic);
59
60 if (t->allocated <= l)
61 return;
62
63 t->data = realloc(t->data, t->allocated = l+100);
64 assert(t->data);
65 }
66
67 void tagstruct_puts(struct tagstruct*t, const char *s) {
68 size_t l;
69 assert(t && s);
70 l = strlen(s)+2;
71 extend(t, l);
72 t->data[t->length] = TAG_STRING;
73 strcpy(t->data+t->length+1, s);
74 t->length += l;
75 }
76
77 void tagstruct_putu32(struct tagstruct*t, uint32_t i) {
78 assert(t && i);
79 extend(t, 5);
80 t->data[t->length] = TAG_U32;
81 *((uint32_t*) (t->data+t->length+1)) = htonl(i);
82 t->length += 5;
83 }
84
85 void tagstruct_putu8(struct tagstruct*t, uint8_t c) {
86 assert(t && c);
87 extend(t, 2);
88 t->data[t->length] = TAG_U8;
89 *(t->data+t->length+1) = c;
90 t->length += 2;
91 }
92
93 void tagstruct_put_sample_spec(struct tagstruct *t, struct sample_spec *ss) {
94 assert(t && ss);
95 extend(t, 7);
96 t->data[t->length] = TAG_SAMPLE_SPEC;
97 t->data[t->length+1] = (uint8_t) ss->format;
98 t->data[t->length+2] = ss->channels;
99 *(uint32_t*) (t->data+t->length+3) = htonl(ss->rate);
100 t->length += 7;
101 }
102
103 int tagstruct_gets(struct tagstruct*t, const char **s) {
104 int error = 0;
105 size_t n;
106 char *c;
107 assert(t && s);
108
109 if (t->rindex+2 > t->length)
110 return -1;
111
112 if (t->data[t->rindex] != TAG_STRING)
113 return -1;
114
115 error = 1;
116 for (n = 0, c = (char*) (t->data+t->rindex+1); n < t->length-t->rindex-1; c++)
117 if (!*c) {
118 error = 0;
119 break;
120 }
121
122 if (error)
123 return -1;
124
125 *s = (char*) (t->data+t->rindex+1);
126
127 t->rindex += n+1;
128 return 0;
129 }
130
131 int tagstruct_getu32(struct tagstruct*t, uint32_t *i) {
132 assert(t && i);
133
134 if (t->rindex+5 > t->length)
135 return -1;
136
137 if (t->data[t->rindex] != TAG_U32)
138 return -1;
139
140 *i = ntohl(*((uint32_t*) (t->data+t->rindex+1)));
141 t->rindex += 5;
142 return 0;
143 }
144
145 int tagstruct_getu8(struct tagstruct*t, uint8_t *c) {
146 assert(t && c);
147
148 if (t->rindex+2 > t->length)
149 return -1;
150
151 if (t->data[t->rindex] != TAG_U8)
152 return -1;
153
154 *c = t->data[t->rindex+1];
155 t->rindex +=2;
156 return 0;
157 }
158
159 int tagstruct_get_sample_spec(struct tagstruct *t, struct sample_spec *ss) {
160 assert(t && ss);
161
162 if (t->rindex+7 > t->length)
163 return -1;
164
165 if (t->data[t->rindex] != TAG_SAMPLE_SPEC)
166 return -1;
167
168 ss->format = t->data[t->rindex+1];
169 ss->channels = t->data[t->rindex+2];
170 ss->rate = ntohl(*(uint32_t*) (t->data+t->rindex+3));
171
172 t->rindex += 7;
173 return 0;
174 }
175
176
177 int tagstruct_eof(struct tagstruct*t) {
178 assert(t);
179 return t->rindex >= t->length;
180 }
181
182 const uint8_t* tagstruct_data(struct tagstruct*t, size_t *l) {
183 assert(t && t->dynamic && l);
184 *l = t->length;
185 return t->data;
186 }
187