cannam@85
|
1 /*
|
cannam@85
|
2 * libid3tag - ID3 tag manipulation library
|
cannam@85
|
3 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
|
cannam@85
|
4 *
|
cannam@85
|
5 * This program is free software; you can redistribute it and/or modify
|
cannam@85
|
6 * it under the terms of the GNU General Public License as published by
|
cannam@85
|
7 * the Free Software Foundation; either version 2 of the License, or
|
cannam@85
|
8 * (at your option) any later version.
|
cannam@85
|
9 *
|
cannam@85
|
10 * This program is distributed in the hope that it will be useful,
|
cannam@85
|
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
cannam@85
|
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
cannam@85
|
13 * GNU General Public License for more details.
|
cannam@85
|
14 *
|
cannam@85
|
15 * You should have received a copy of the GNU General Public License
|
cannam@85
|
16 * along with this program; if not, write to the Free Software
|
cannam@85
|
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
cannam@85
|
18 *
|
cannam@85
|
19 * $Id: field.c,v 1.16 2004/01/23 09:41:32 rob Exp $
|
cannam@85
|
20 */
|
cannam@85
|
21
|
cannam@85
|
22 # ifdef HAVE_CONFIG_H
|
cannam@85
|
23 # include "config.h"
|
cannam@85
|
24 # endif
|
cannam@85
|
25
|
cannam@85
|
26 # include "global.h"
|
cannam@85
|
27
|
cannam@85
|
28 # include <stdlib.h>
|
cannam@85
|
29 # include <string.h>
|
cannam@85
|
30
|
cannam@85
|
31 # ifdef HAVE_ASSERT_H
|
cannam@85
|
32 # include <assert.h>
|
cannam@85
|
33 # endif
|
cannam@85
|
34
|
cannam@85
|
35 # include "id3tag.h"
|
cannam@85
|
36 # include "field.h"
|
cannam@85
|
37 # include "frame.h"
|
cannam@85
|
38 # include "render.h"
|
cannam@85
|
39 # include "ucs4.h"
|
cannam@85
|
40 # include "latin1.h"
|
cannam@85
|
41 # include "parse.h"
|
cannam@85
|
42
|
cannam@85
|
43 /*
|
cannam@85
|
44 * NAME: field->init()
|
cannam@85
|
45 * DESCRIPTION: initialize a field to a default value for the given type
|
cannam@85
|
46 */
|
cannam@85
|
47 void id3_field_init(union id3_field *field, enum id3_field_type type)
|
cannam@85
|
48 {
|
cannam@85
|
49 assert(field);
|
cannam@85
|
50
|
cannam@85
|
51 switch (field->type = type) {
|
cannam@85
|
52 case ID3_FIELD_TYPE_TEXTENCODING:
|
cannam@85
|
53 case ID3_FIELD_TYPE_INT8:
|
cannam@85
|
54 case ID3_FIELD_TYPE_INT16:
|
cannam@85
|
55 case ID3_FIELD_TYPE_INT24:
|
cannam@85
|
56 case ID3_FIELD_TYPE_INT32:
|
cannam@85
|
57 field->number.value = 0;
|
cannam@85
|
58 break;
|
cannam@85
|
59
|
cannam@85
|
60 case ID3_FIELD_TYPE_LATIN1:
|
cannam@85
|
61 case ID3_FIELD_TYPE_LATIN1FULL:
|
cannam@85
|
62 field->latin1.ptr = 0;
|
cannam@85
|
63 break;
|
cannam@85
|
64
|
cannam@85
|
65 case ID3_FIELD_TYPE_LATIN1LIST:
|
cannam@85
|
66 field->latin1list.nstrings = 0;
|
cannam@85
|
67 field->latin1list.strings = 0;
|
cannam@85
|
68
|
cannam@85
|
69 case ID3_FIELD_TYPE_STRING:
|
cannam@85
|
70 case ID3_FIELD_TYPE_STRINGFULL:
|
cannam@85
|
71 field->string.ptr = 0;
|
cannam@85
|
72 break;
|
cannam@85
|
73
|
cannam@85
|
74 case ID3_FIELD_TYPE_STRINGLIST:
|
cannam@85
|
75 field->stringlist.nstrings = 0;
|
cannam@85
|
76 field->stringlist.strings = 0;
|
cannam@85
|
77 break;
|
cannam@85
|
78
|
cannam@85
|
79 case ID3_FIELD_TYPE_LANGUAGE:
|
cannam@85
|
80 strcpy(field->immediate.value, "XXX");
|
cannam@85
|
81 break;
|
cannam@85
|
82
|
cannam@85
|
83 case ID3_FIELD_TYPE_FRAMEID:
|
cannam@85
|
84 strcpy(field->immediate.value, "XXXX");
|
cannam@85
|
85 break;
|
cannam@85
|
86
|
cannam@85
|
87 case ID3_FIELD_TYPE_DATE:
|
cannam@85
|
88 memset(field->immediate.value, 0, sizeof(field->immediate.value));
|
cannam@85
|
89 break;
|
cannam@85
|
90
|
cannam@85
|
91 case ID3_FIELD_TYPE_INT32PLUS:
|
cannam@85
|
92 case ID3_FIELD_TYPE_BINARYDATA:
|
cannam@85
|
93 field->binary.data = 0;
|
cannam@85
|
94 field->binary.length = 0;
|
cannam@85
|
95 break;
|
cannam@85
|
96 }
|
cannam@85
|
97 }
|
cannam@85
|
98
|
cannam@85
|
99 /*
|
cannam@85
|
100 * NAME: field->finish()
|
cannam@85
|
101 * DESCRIPTION: reset a field, deallocating memory if necessary
|
cannam@85
|
102 */
|
cannam@85
|
103 void id3_field_finish(union id3_field *field)
|
cannam@85
|
104 {
|
cannam@85
|
105 unsigned int i;
|
cannam@85
|
106
|
cannam@85
|
107 assert(field);
|
cannam@85
|
108
|
cannam@85
|
109 switch (field->type) {
|
cannam@85
|
110 case ID3_FIELD_TYPE_TEXTENCODING:
|
cannam@85
|
111 case ID3_FIELD_TYPE_INT8:
|
cannam@85
|
112 case ID3_FIELD_TYPE_INT16:
|
cannam@85
|
113 case ID3_FIELD_TYPE_INT24:
|
cannam@85
|
114 case ID3_FIELD_TYPE_INT32:
|
cannam@85
|
115 case ID3_FIELD_TYPE_LANGUAGE:
|
cannam@85
|
116 case ID3_FIELD_TYPE_FRAMEID:
|
cannam@85
|
117 case ID3_FIELD_TYPE_DATE:
|
cannam@85
|
118 break;
|
cannam@85
|
119
|
cannam@85
|
120 case ID3_FIELD_TYPE_LATIN1:
|
cannam@85
|
121 case ID3_FIELD_TYPE_LATIN1FULL:
|
cannam@85
|
122 if (field->latin1.ptr)
|
cannam@85
|
123 free(field->latin1.ptr);
|
cannam@85
|
124 break;
|
cannam@85
|
125
|
cannam@85
|
126 case ID3_FIELD_TYPE_LATIN1LIST:
|
cannam@85
|
127 for (i = 0; i < field->latin1list.nstrings; ++i)
|
cannam@85
|
128 free(field->latin1list.strings[i]);
|
cannam@85
|
129
|
cannam@85
|
130 if (field->latin1list.strings)
|
cannam@85
|
131 free(field->latin1list.strings);
|
cannam@85
|
132 break;
|
cannam@85
|
133
|
cannam@85
|
134 case ID3_FIELD_TYPE_STRING:
|
cannam@85
|
135 case ID3_FIELD_TYPE_STRINGFULL:
|
cannam@85
|
136 if (field->string.ptr)
|
cannam@85
|
137 free(field->string.ptr);
|
cannam@85
|
138 break;
|
cannam@85
|
139
|
cannam@85
|
140 case ID3_FIELD_TYPE_STRINGLIST:
|
cannam@85
|
141 for (i = 0; i < field->stringlist.nstrings; ++i)
|
cannam@85
|
142 free(field->stringlist.strings[i]);
|
cannam@85
|
143
|
cannam@85
|
144 if (field->stringlist.strings)
|
cannam@85
|
145 free(field->stringlist.strings);
|
cannam@85
|
146 break;
|
cannam@85
|
147
|
cannam@85
|
148 case ID3_FIELD_TYPE_INT32PLUS:
|
cannam@85
|
149 case ID3_FIELD_TYPE_BINARYDATA:
|
cannam@85
|
150 if (field->binary.data)
|
cannam@85
|
151 free(field->binary.data);
|
cannam@85
|
152 break;
|
cannam@85
|
153 }
|
cannam@85
|
154
|
cannam@85
|
155 id3_field_init(field, field->type);
|
cannam@85
|
156 }
|
cannam@85
|
157
|
cannam@85
|
158 /*
|
cannam@85
|
159 * NAME: field->type()
|
cannam@85
|
160 * DESCRIPTION: return the value type of a field
|
cannam@85
|
161 */
|
cannam@85
|
162 enum id3_field_type id3_field_type(union id3_field const *field)
|
cannam@85
|
163 {
|
cannam@85
|
164 assert(field);
|
cannam@85
|
165
|
cannam@85
|
166 return field->type;
|
cannam@85
|
167 }
|
cannam@85
|
168
|
cannam@85
|
169 /*
|
cannam@85
|
170 * NAME: field->parse()
|
cannam@85
|
171 * DESCRIPTION: parse a field value
|
cannam@85
|
172 */
|
cannam@85
|
173 int id3_field_parse(union id3_field *field, id3_byte_t const **ptr,
|
cannam@85
|
174 id3_length_t length, enum id3_field_textencoding *encoding)
|
cannam@85
|
175 {
|
cannam@85
|
176 assert(field);
|
cannam@85
|
177
|
cannam@85
|
178 id3_field_finish(field);
|
cannam@85
|
179
|
cannam@85
|
180 switch (field->type) {
|
cannam@85
|
181 case ID3_FIELD_TYPE_INT32:
|
cannam@85
|
182 if (length < 4)
|
cannam@85
|
183 goto fail;
|
cannam@85
|
184
|
cannam@85
|
185 field->number.value = id3_parse_uint(ptr, 4);
|
cannam@85
|
186 break;
|
cannam@85
|
187
|
cannam@85
|
188 case ID3_FIELD_TYPE_INT24:
|
cannam@85
|
189 if (length < 3)
|
cannam@85
|
190 goto fail;
|
cannam@85
|
191
|
cannam@85
|
192 field->number.value = id3_parse_uint(ptr, 3);
|
cannam@85
|
193 break;
|
cannam@85
|
194
|
cannam@85
|
195 case ID3_FIELD_TYPE_INT16:
|
cannam@85
|
196 if (length < 2)
|
cannam@85
|
197 goto fail;
|
cannam@85
|
198
|
cannam@85
|
199 field->number.value = id3_parse_uint(ptr, 2);
|
cannam@85
|
200 break;
|
cannam@85
|
201
|
cannam@85
|
202 case ID3_FIELD_TYPE_INT8:
|
cannam@85
|
203 case ID3_FIELD_TYPE_TEXTENCODING:
|
cannam@85
|
204 if (length < 1)
|
cannam@85
|
205 goto fail;
|
cannam@85
|
206
|
cannam@85
|
207 field->number.value = id3_parse_uint(ptr, 1);
|
cannam@85
|
208
|
cannam@85
|
209 if (field->type == ID3_FIELD_TYPE_TEXTENCODING)
|
cannam@85
|
210 *encoding = field->number.value;
|
cannam@85
|
211 break;
|
cannam@85
|
212
|
cannam@85
|
213 case ID3_FIELD_TYPE_LANGUAGE:
|
cannam@85
|
214 if (length < 3)
|
cannam@85
|
215 goto fail;
|
cannam@85
|
216
|
cannam@85
|
217 id3_parse_immediate(ptr, 3, field->immediate.value);
|
cannam@85
|
218 break;
|
cannam@85
|
219
|
cannam@85
|
220 case ID3_FIELD_TYPE_FRAMEID:
|
cannam@85
|
221 if (length < 4)
|
cannam@85
|
222 goto fail;
|
cannam@85
|
223
|
cannam@85
|
224 id3_parse_immediate(ptr, 4, field->immediate.value);
|
cannam@85
|
225 break;
|
cannam@85
|
226
|
cannam@85
|
227 case ID3_FIELD_TYPE_DATE:
|
cannam@85
|
228 if (length < 8)
|
cannam@85
|
229 goto fail;
|
cannam@85
|
230
|
cannam@85
|
231 id3_parse_immediate(ptr, 8, field->immediate.value);
|
cannam@85
|
232 break;
|
cannam@85
|
233
|
cannam@85
|
234 case ID3_FIELD_TYPE_LATIN1:
|
cannam@85
|
235 case ID3_FIELD_TYPE_LATIN1FULL:
|
cannam@85
|
236 {
|
cannam@85
|
237 id3_latin1_t *latin1;
|
cannam@85
|
238
|
cannam@85
|
239 latin1 = id3_parse_latin1(ptr, length,
|
cannam@85
|
240 field->type == ID3_FIELD_TYPE_LATIN1FULL);
|
cannam@85
|
241 if (latin1 == 0)
|
cannam@85
|
242 goto fail;
|
cannam@85
|
243
|
cannam@85
|
244 field->latin1.ptr = latin1;
|
cannam@85
|
245 }
|
cannam@85
|
246 break;
|
cannam@85
|
247
|
cannam@85
|
248 case ID3_FIELD_TYPE_LATIN1LIST:
|
cannam@85
|
249 {
|
cannam@85
|
250 id3_byte_t const *end;
|
cannam@85
|
251 id3_latin1_t *latin1, **strings;
|
cannam@85
|
252
|
cannam@85
|
253 end = *ptr + length;
|
cannam@85
|
254
|
cannam@85
|
255 while (end - *ptr > 0) {
|
cannam@85
|
256 latin1 = id3_parse_latin1(ptr, end - *ptr, 0);
|
cannam@85
|
257 if (latin1 == 0)
|
cannam@85
|
258 goto fail;
|
cannam@85
|
259
|
cannam@85
|
260 strings = realloc(field->latin1list.strings,
|
cannam@85
|
261 (field->latin1list.nstrings + 1) * sizeof(*strings));
|
cannam@85
|
262 if (strings == 0) {
|
cannam@85
|
263 free(latin1);
|
cannam@85
|
264 goto fail;
|
cannam@85
|
265 }
|
cannam@85
|
266
|
cannam@85
|
267 field->latin1list.strings = strings;
|
cannam@85
|
268 field->latin1list.strings[field->latin1list.nstrings++] = latin1;
|
cannam@85
|
269 }
|
cannam@85
|
270 }
|
cannam@85
|
271 break;
|
cannam@85
|
272
|
cannam@85
|
273 case ID3_FIELD_TYPE_STRING:
|
cannam@85
|
274 case ID3_FIELD_TYPE_STRINGFULL:
|
cannam@85
|
275 {
|
cannam@85
|
276 id3_ucs4_t *ucs4;
|
cannam@85
|
277
|
cannam@85
|
278 ucs4 = id3_parse_string(ptr, length, *encoding,
|
cannam@85
|
279 field->type == ID3_FIELD_TYPE_STRINGFULL);
|
cannam@85
|
280 if (ucs4 == 0)
|
cannam@85
|
281 goto fail;
|
cannam@85
|
282
|
cannam@85
|
283 field->string.ptr = ucs4;
|
cannam@85
|
284 }
|
cannam@85
|
285 break;
|
cannam@85
|
286
|
cannam@85
|
287 case ID3_FIELD_TYPE_STRINGLIST:
|
cannam@85
|
288 {
|
cannam@85
|
289 id3_byte_t const *end;
|
cannam@85
|
290 id3_ucs4_t *ucs4, **strings;
|
cannam@85
|
291
|
cannam@85
|
292 end = *ptr + length;
|
cannam@85
|
293
|
cannam@85
|
294 while (end - *ptr > 0) {
|
cannam@85
|
295 ucs4 = id3_parse_string(ptr, end - *ptr, *encoding, 0);
|
cannam@85
|
296 if (ucs4 == 0)
|
cannam@85
|
297 goto fail;
|
cannam@85
|
298
|
cannam@85
|
299 strings = realloc(field->stringlist.strings,
|
cannam@85
|
300 (field->stringlist.nstrings + 1) * sizeof(*strings));
|
cannam@85
|
301 if (strings == 0) {
|
cannam@85
|
302 free(ucs4);
|
cannam@85
|
303 goto fail;
|
cannam@85
|
304 }
|
cannam@85
|
305
|
cannam@85
|
306 field->stringlist.strings = strings;
|
cannam@85
|
307 field->stringlist.strings[field->stringlist.nstrings++] = ucs4;
|
cannam@85
|
308 }
|
cannam@85
|
309 }
|
cannam@85
|
310 break;
|
cannam@85
|
311
|
cannam@85
|
312 case ID3_FIELD_TYPE_INT32PLUS:
|
cannam@85
|
313 case ID3_FIELD_TYPE_BINARYDATA:
|
cannam@85
|
314 {
|
cannam@85
|
315 id3_byte_t *data;
|
cannam@85
|
316
|
cannam@85
|
317 data = id3_parse_binary(ptr, length);
|
cannam@85
|
318 if (data == 0)
|
cannam@85
|
319 goto fail;
|
cannam@85
|
320
|
cannam@85
|
321 field->binary.data = data;
|
cannam@85
|
322 field->binary.length = length;
|
cannam@85
|
323 }
|
cannam@85
|
324 break;
|
cannam@85
|
325 }
|
cannam@85
|
326
|
cannam@85
|
327 return 0;
|
cannam@85
|
328
|
cannam@85
|
329 fail:
|
cannam@85
|
330 return -1;
|
cannam@85
|
331 }
|
cannam@85
|
332
|
cannam@85
|
333 /*
|
cannam@85
|
334 * NAME: field->render()
|
cannam@85
|
335 * DESCRIPTION: render a field value
|
cannam@85
|
336 */
|
cannam@85
|
337 id3_length_t id3_field_render(union id3_field const *field, id3_byte_t **ptr,
|
cannam@85
|
338 enum id3_field_textencoding *encoding,
|
cannam@85
|
339 int terminate)
|
cannam@85
|
340 {
|
cannam@85
|
341 id3_length_t size;
|
cannam@85
|
342 unsigned int i;
|
cannam@85
|
343
|
cannam@85
|
344 assert(field && encoding);
|
cannam@85
|
345
|
cannam@85
|
346 switch (field->type) {
|
cannam@85
|
347 case ID3_FIELD_TYPE_INT32:
|
cannam@85
|
348 return id3_render_int(ptr, field->number.value, 4);
|
cannam@85
|
349
|
cannam@85
|
350 case ID3_FIELD_TYPE_INT24:
|
cannam@85
|
351 return id3_render_int(ptr, field->number.value, 3);
|
cannam@85
|
352
|
cannam@85
|
353 case ID3_FIELD_TYPE_INT16:
|
cannam@85
|
354 return id3_render_int(ptr, field->number.value, 2);
|
cannam@85
|
355
|
cannam@85
|
356 case ID3_FIELD_TYPE_TEXTENCODING:
|
cannam@85
|
357 *encoding = field->number.value;
|
cannam@85
|
358 case ID3_FIELD_TYPE_INT8:
|
cannam@85
|
359 return id3_render_int(ptr, field->number.value, 1);
|
cannam@85
|
360
|
cannam@85
|
361 case ID3_FIELD_TYPE_LATIN1:
|
cannam@85
|
362 case ID3_FIELD_TYPE_LATIN1FULL:
|
cannam@85
|
363 return id3_render_latin1(ptr, field->latin1.ptr, terminate);
|
cannam@85
|
364
|
cannam@85
|
365 case ID3_FIELD_TYPE_LATIN1LIST:
|
cannam@85
|
366 size = 0;
|
cannam@85
|
367 for (i = 0; i < field->latin1list.nstrings; ++i) {
|
cannam@85
|
368 size += id3_render_latin1(ptr, field->latin1list.strings[i],
|
cannam@85
|
369 (i < field->latin1list.nstrings - 1) ||
|
cannam@85
|
370 terminate);
|
cannam@85
|
371 }
|
cannam@85
|
372 return size;
|
cannam@85
|
373
|
cannam@85
|
374 case ID3_FIELD_TYPE_STRING:
|
cannam@85
|
375 case ID3_FIELD_TYPE_STRINGFULL:
|
cannam@85
|
376 return id3_render_string(ptr, field->string.ptr, *encoding, terminate);
|
cannam@85
|
377
|
cannam@85
|
378 case ID3_FIELD_TYPE_STRINGLIST:
|
cannam@85
|
379 size = 0;
|
cannam@85
|
380 for (i = 0; i < field->stringlist.nstrings; ++i) {
|
cannam@85
|
381 size += id3_render_string(ptr, field->stringlist.strings[i], *encoding,
|
cannam@85
|
382 (i < field->stringlist.nstrings - 1) ||
|
cannam@85
|
383 terminate);
|
cannam@85
|
384 }
|
cannam@85
|
385 return size;
|
cannam@85
|
386
|
cannam@85
|
387 case ID3_FIELD_TYPE_LANGUAGE:
|
cannam@85
|
388 return id3_render_immediate(ptr, field->immediate.value, 3);
|
cannam@85
|
389
|
cannam@85
|
390 case ID3_FIELD_TYPE_FRAMEID:
|
cannam@85
|
391 return id3_render_immediate(ptr, field->immediate.value, 4);
|
cannam@85
|
392
|
cannam@85
|
393 case ID3_FIELD_TYPE_DATE:
|
cannam@85
|
394 return id3_render_immediate(ptr, field->immediate.value, 8);
|
cannam@85
|
395
|
cannam@85
|
396 case ID3_FIELD_TYPE_INT32PLUS:
|
cannam@85
|
397 case ID3_FIELD_TYPE_BINARYDATA:
|
cannam@85
|
398 return id3_render_binary(ptr, field->binary.data, field->binary.length);
|
cannam@85
|
399 }
|
cannam@85
|
400
|
cannam@85
|
401 return 0;
|
cannam@85
|
402 }
|
cannam@85
|
403
|
cannam@85
|
404 /*
|
cannam@85
|
405 * NAME: field->setint()
|
cannam@85
|
406 * DESCRIPTION: set the value of an int field
|
cannam@85
|
407 */
|
cannam@85
|
408 int id3_field_setint(union id3_field *field, signed long number)
|
cannam@85
|
409 {
|
cannam@85
|
410 assert(field);
|
cannam@85
|
411
|
cannam@85
|
412 switch (field->type) {
|
cannam@85
|
413 case ID3_FIELD_TYPE_INT8:
|
cannam@85
|
414 if (number > 0x7f || number < -0x80)
|
cannam@85
|
415 return -1;
|
cannam@85
|
416 break;
|
cannam@85
|
417
|
cannam@85
|
418 case ID3_FIELD_TYPE_INT16:
|
cannam@85
|
419 if (number > 0x7fff || number < -0x8000)
|
cannam@85
|
420 return -1;
|
cannam@85
|
421 break;
|
cannam@85
|
422
|
cannam@85
|
423 case ID3_FIELD_TYPE_INT24:
|
cannam@85
|
424 if (number > 0x7fffffL || number < -0x800000L)
|
cannam@85
|
425 return -1;
|
cannam@85
|
426 break;
|
cannam@85
|
427
|
cannam@85
|
428 case ID3_FIELD_TYPE_INT32:
|
cannam@85
|
429 if (number > 0x7fffffffL || number < -0x80000000L)
|
cannam@85
|
430 return -1;
|
cannam@85
|
431 break;
|
cannam@85
|
432
|
cannam@85
|
433 default:
|
cannam@85
|
434 return -1;
|
cannam@85
|
435 }
|
cannam@85
|
436
|
cannam@85
|
437 id3_field_finish(field);
|
cannam@85
|
438
|
cannam@85
|
439 field->number.value = number;
|
cannam@85
|
440
|
cannam@85
|
441 return 0;
|
cannam@85
|
442 }
|
cannam@85
|
443
|
cannam@85
|
444 /*
|
cannam@85
|
445 * NAME: field->settextencoding()
|
cannam@85
|
446 * DESCRIPTION: set the value of a textencoding field
|
cannam@85
|
447 */
|
cannam@85
|
448 int id3_field_settextencoding(union id3_field *field,
|
cannam@85
|
449 enum id3_field_textencoding encoding)
|
cannam@85
|
450 {
|
cannam@85
|
451 assert(field);
|
cannam@85
|
452
|
cannam@85
|
453 if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
|
cannam@85
|
454 return -1;
|
cannam@85
|
455
|
cannam@85
|
456 id3_field_finish(field);
|
cannam@85
|
457
|
cannam@85
|
458 field->number.value = encoding;
|
cannam@85
|
459
|
cannam@85
|
460 return 0;
|
cannam@85
|
461 }
|
cannam@85
|
462
|
cannam@85
|
463 static
|
cannam@85
|
464 int set_latin1(union id3_field *field, id3_latin1_t const *latin1)
|
cannam@85
|
465 {
|
cannam@85
|
466 id3_latin1_t *data;
|
cannam@85
|
467
|
cannam@85
|
468 if (latin1 == 0 || *latin1 == 0)
|
cannam@85
|
469 data = 0;
|
cannam@85
|
470 else {
|
cannam@85
|
471 data = id3_latin1_duplicate(latin1);
|
cannam@85
|
472 if (data == 0)
|
cannam@85
|
473 return -1;
|
cannam@85
|
474 }
|
cannam@85
|
475
|
cannam@85
|
476 field->latin1.ptr = data;
|
cannam@85
|
477
|
cannam@85
|
478 return 0;
|
cannam@85
|
479 }
|
cannam@85
|
480
|
cannam@85
|
481 /*
|
cannam@85
|
482 * NAME: field->setlatin1()
|
cannam@85
|
483 * DESCRIPTION: set the value of a latin1 field
|
cannam@85
|
484 */
|
cannam@85
|
485 int id3_field_setlatin1(union id3_field *field, id3_latin1_t const *latin1)
|
cannam@85
|
486 {
|
cannam@85
|
487 assert(field);
|
cannam@85
|
488
|
cannam@85
|
489 if (field->type != ID3_FIELD_TYPE_LATIN1)
|
cannam@85
|
490 return -1;
|
cannam@85
|
491
|
cannam@85
|
492 id3_field_finish(field);
|
cannam@85
|
493
|
cannam@85
|
494 if (latin1) {
|
cannam@85
|
495 id3_latin1_t const *ptr;
|
cannam@85
|
496
|
cannam@85
|
497 for (ptr = latin1; *ptr; ++ptr) {
|
cannam@85
|
498 if (*ptr == '\n')
|
cannam@85
|
499 return -1;
|
cannam@85
|
500 }
|
cannam@85
|
501 }
|
cannam@85
|
502
|
cannam@85
|
503 return set_latin1(field, latin1);
|
cannam@85
|
504 }
|
cannam@85
|
505
|
cannam@85
|
506 /*
|
cannam@85
|
507 * NAME: field->setfulllatin1()
|
cannam@85
|
508 * DESCRIPTION: set the value of a full latin1 field
|
cannam@85
|
509 */
|
cannam@85
|
510 int id3_field_setfulllatin1(union id3_field *field, id3_latin1_t const *latin1)
|
cannam@85
|
511 {
|
cannam@85
|
512 assert(field);
|
cannam@85
|
513
|
cannam@85
|
514 if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
|
cannam@85
|
515 return -1;
|
cannam@85
|
516
|
cannam@85
|
517 id3_field_finish(field);
|
cannam@85
|
518
|
cannam@85
|
519 return set_latin1(field, latin1);
|
cannam@85
|
520 }
|
cannam@85
|
521
|
cannam@85
|
522 static
|
cannam@85
|
523 int set_string(union id3_field *field, id3_ucs4_t const *string)
|
cannam@85
|
524 {
|
cannam@85
|
525 id3_ucs4_t *data;
|
cannam@85
|
526
|
cannam@85
|
527 if (string == 0 || *string == 0)
|
cannam@85
|
528 data = 0;
|
cannam@85
|
529 else {
|
cannam@85
|
530 data = id3_ucs4_duplicate(string);
|
cannam@85
|
531 if (data == 0)
|
cannam@85
|
532 return -1;
|
cannam@85
|
533 }
|
cannam@85
|
534
|
cannam@85
|
535 field->string.ptr = data;
|
cannam@85
|
536
|
cannam@85
|
537 return 0;
|
cannam@85
|
538 }
|
cannam@85
|
539
|
cannam@85
|
540 /*
|
cannam@85
|
541 * NAME: field->setstring()
|
cannam@85
|
542 * DESCRIPTION: set the value of a string field
|
cannam@85
|
543 */
|
cannam@85
|
544 int id3_field_setstring(union id3_field *field, id3_ucs4_t const *string)
|
cannam@85
|
545 {
|
cannam@85
|
546 assert(field);
|
cannam@85
|
547
|
cannam@85
|
548 if (field->type != ID3_FIELD_TYPE_STRING)
|
cannam@85
|
549 return -1;
|
cannam@85
|
550
|
cannam@85
|
551 id3_field_finish(field);
|
cannam@85
|
552
|
cannam@85
|
553 if (string) {
|
cannam@85
|
554 id3_ucs4_t const *ptr;
|
cannam@85
|
555
|
cannam@85
|
556 for (ptr = string; *ptr; ++ptr) {
|
cannam@85
|
557 if (*ptr == '\n')
|
cannam@85
|
558 return -1;
|
cannam@85
|
559 }
|
cannam@85
|
560 }
|
cannam@85
|
561
|
cannam@85
|
562 return set_string(field, string);
|
cannam@85
|
563 }
|
cannam@85
|
564
|
cannam@85
|
565 /*
|
cannam@85
|
566 * NAME: field->setfullstring()
|
cannam@85
|
567 * DESCRIPTION: set the value of a full string field
|
cannam@85
|
568 */
|
cannam@85
|
569 int id3_field_setfullstring(union id3_field *field, id3_ucs4_t const *string)
|
cannam@85
|
570 {
|
cannam@85
|
571 assert(field);
|
cannam@85
|
572
|
cannam@85
|
573 if (field->type != ID3_FIELD_TYPE_STRINGFULL)
|
cannam@85
|
574 return -1;
|
cannam@85
|
575
|
cannam@85
|
576 id3_field_finish(field);
|
cannam@85
|
577
|
cannam@85
|
578 return set_string(field, string);
|
cannam@85
|
579 }
|
cannam@85
|
580
|
cannam@85
|
581 /*
|
cannam@85
|
582 * NAME: field->setstrings()
|
cannam@85
|
583 * DESCRIPTION: set the value of a stringlist field
|
cannam@85
|
584 */
|
cannam@85
|
585 int id3_field_setstrings(union id3_field *field,
|
cannam@85
|
586 unsigned int length, id3_ucs4_t **ptrs)
|
cannam@85
|
587 {
|
cannam@85
|
588 id3_ucs4_t **strings;
|
cannam@85
|
589 unsigned int i;
|
cannam@85
|
590
|
cannam@85
|
591 assert(field);
|
cannam@85
|
592
|
cannam@85
|
593 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
|
cannam@85
|
594 return -1;
|
cannam@85
|
595
|
cannam@85
|
596 id3_field_finish(field);
|
cannam@85
|
597
|
cannam@85
|
598 if (length == 0)
|
cannam@85
|
599 return 0;
|
cannam@85
|
600
|
cannam@85
|
601 strings = malloc(length * sizeof(*strings));
|
cannam@85
|
602 if (strings == 0)
|
cannam@85
|
603 return -1;
|
cannam@85
|
604
|
cannam@85
|
605 for (i = 0; i < length; ++i) {
|
cannam@85
|
606 strings[i] = id3_ucs4_duplicate(ptrs[i]);
|
cannam@85
|
607 if (strings[i] == 0) {
|
cannam@85
|
608 while (i--)
|
cannam@85
|
609 free(strings[i]);
|
cannam@85
|
610
|
cannam@85
|
611 free(strings);
|
cannam@85
|
612 return -1;
|
cannam@85
|
613 }
|
cannam@85
|
614 }
|
cannam@85
|
615
|
cannam@85
|
616 field->stringlist.strings = strings;
|
cannam@85
|
617 field->stringlist.nstrings = length;
|
cannam@85
|
618
|
cannam@85
|
619 return 0;
|
cannam@85
|
620 }
|
cannam@85
|
621
|
cannam@85
|
622 /*
|
cannam@85
|
623 * NAME: field->addstring()
|
cannam@85
|
624 * DESCRIPTION: add a string to a stringlist field
|
cannam@85
|
625 */
|
cannam@85
|
626 int id3_field_addstring(union id3_field *field, id3_ucs4_t const *string)
|
cannam@85
|
627 {
|
cannam@85
|
628 id3_ucs4_t *new, **strings;
|
cannam@85
|
629
|
cannam@85
|
630 assert(field);
|
cannam@85
|
631
|
cannam@85
|
632 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
|
cannam@85
|
633 return -1;
|
cannam@85
|
634
|
cannam@85
|
635 if (string == 0)
|
cannam@85
|
636 string = id3_ucs4_empty;
|
cannam@85
|
637
|
cannam@85
|
638 new = id3_ucs4_duplicate(string);
|
cannam@85
|
639 if (new == 0)
|
cannam@85
|
640 return -1;
|
cannam@85
|
641
|
cannam@85
|
642 strings = realloc(field->stringlist.strings,
|
cannam@85
|
643 (field->stringlist.nstrings + 1) * sizeof(*strings));
|
cannam@85
|
644 if (strings == 0) {
|
cannam@85
|
645 free(new);
|
cannam@85
|
646 return -1;
|
cannam@85
|
647 }
|
cannam@85
|
648
|
cannam@85
|
649 field->stringlist.strings = strings;
|
cannam@85
|
650 field->stringlist.strings[field->stringlist.nstrings++] = new;
|
cannam@85
|
651
|
cannam@85
|
652 return 0;
|
cannam@85
|
653 }
|
cannam@85
|
654
|
cannam@85
|
655 /*
|
cannam@85
|
656 * NAME: field->setlanguage()
|
cannam@85
|
657 * DESCRIPTION: set the value of a language field
|
cannam@85
|
658 */
|
cannam@85
|
659 int id3_field_setlanguage(union id3_field *field, char const *language)
|
cannam@85
|
660 {
|
cannam@85
|
661 assert(field);
|
cannam@85
|
662
|
cannam@85
|
663 if (field->type != ID3_FIELD_TYPE_LANGUAGE)
|
cannam@85
|
664 return -1;
|
cannam@85
|
665
|
cannam@85
|
666 id3_field_finish(field);
|
cannam@85
|
667
|
cannam@85
|
668 if (language) {
|
cannam@85
|
669 if (strlen(language) != 3)
|
cannam@85
|
670 return -1;
|
cannam@85
|
671
|
cannam@85
|
672 strcpy(field->immediate.value, language);
|
cannam@85
|
673 }
|
cannam@85
|
674
|
cannam@85
|
675 return 0;
|
cannam@85
|
676 }
|
cannam@85
|
677
|
cannam@85
|
678 /*
|
cannam@85
|
679 * NAME: field->setframeid()
|
cannam@85
|
680 * DESCRIPTION: set the value of a frameid field
|
cannam@85
|
681 */
|
cannam@85
|
682 int id3_field_setframeid(union id3_field *field, char const *id)
|
cannam@85
|
683 {
|
cannam@85
|
684 assert(field);
|
cannam@85
|
685
|
cannam@85
|
686 if (field->type != ID3_FIELD_TYPE_FRAMEID ||
|
cannam@85
|
687 !id3_frame_validid(id))
|
cannam@85
|
688 return -1;
|
cannam@85
|
689
|
cannam@85
|
690 id3_field_finish(field);
|
cannam@85
|
691
|
cannam@85
|
692 field->immediate.value[0] = id[0];
|
cannam@85
|
693 field->immediate.value[1] = id[1];
|
cannam@85
|
694 field->immediate.value[2] = id[2];
|
cannam@85
|
695 field->immediate.value[3] = id[3];
|
cannam@85
|
696 field->immediate.value[4] = 0;
|
cannam@85
|
697
|
cannam@85
|
698 return 0;
|
cannam@85
|
699 }
|
cannam@85
|
700
|
cannam@85
|
701 /*
|
cannam@85
|
702 * NAME: field->setbinarydata()
|
cannam@85
|
703 * DESCRIPTION: set the value of a binarydata field
|
cannam@85
|
704 */
|
cannam@85
|
705 int id3_field_setbinarydata(union id3_field *field,
|
cannam@85
|
706 id3_byte_t const *data, id3_length_t length)
|
cannam@85
|
707 {
|
cannam@85
|
708 id3_byte_t *mem;
|
cannam@85
|
709
|
cannam@85
|
710 assert(field);
|
cannam@85
|
711
|
cannam@85
|
712 if (field->type != ID3_FIELD_TYPE_BINARYDATA)
|
cannam@85
|
713 return -1;
|
cannam@85
|
714
|
cannam@85
|
715 id3_field_finish(field);
|
cannam@85
|
716
|
cannam@85
|
717 if (length == 0)
|
cannam@85
|
718 mem = 0;
|
cannam@85
|
719 else {
|
cannam@85
|
720 mem = malloc(length);
|
cannam@85
|
721 if (mem == 0)
|
cannam@85
|
722 return -1;
|
cannam@85
|
723
|
cannam@85
|
724 assert(data);
|
cannam@85
|
725
|
cannam@85
|
726 memcpy(mem, data, length);
|
cannam@85
|
727 }
|
cannam@85
|
728
|
cannam@85
|
729 field->binary.data = mem;
|
cannam@85
|
730 field->binary.length = length;
|
cannam@85
|
731
|
cannam@85
|
732 return 0;
|
cannam@85
|
733 }
|
cannam@85
|
734
|
cannam@85
|
735 /*
|
cannam@85
|
736 * NAME: field->getint()
|
cannam@85
|
737 * DESCRIPTION: return the value of an integer field
|
cannam@85
|
738 */
|
cannam@85
|
739 signed long id3_field_getint(union id3_field const *field)
|
cannam@85
|
740 {
|
cannam@85
|
741 assert(field);
|
cannam@85
|
742
|
cannam@85
|
743 if (field->type != ID3_FIELD_TYPE_INT8 &&
|
cannam@85
|
744 field->type != ID3_FIELD_TYPE_INT16 &&
|
cannam@85
|
745 field->type != ID3_FIELD_TYPE_INT24 &&
|
cannam@85
|
746 field->type != ID3_FIELD_TYPE_INT32)
|
cannam@85
|
747 return -1;
|
cannam@85
|
748
|
cannam@85
|
749 return field->number.value;
|
cannam@85
|
750 }
|
cannam@85
|
751
|
cannam@85
|
752 /*
|
cannam@85
|
753 * NAME: field->gettextencoding()
|
cannam@85
|
754 * DESCRIPTION: return the value of a text encoding field
|
cannam@85
|
755 */
|
cannam@85
|
756 enum id3_field_textencoding
|
cannam@85
|
757 id3_field_gettextencoding(union id3_field const *field)
|
cannam@85
|
758 {
|
cannam@85
|
759 assert(field);
|
cannam@85
|
760
|
cannam@85
|
761 if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
|
cannam@85
|
762 return -1;
|
cannam@85
|
763
|
cannam@85
|
764 return field->number.value;
|
cannam@85
|
765 }
|
cannam@85
|
766
|
cannam@85
|
767 /*
|
cannam@85
|
768 * NAME: field->getlatin1()
|
cannam@85
|
769 * DESCRIPTION: return the value of a latin1 field
|
cannam@85
|
770 */
|
cannam@85
|
771 id3_latin1_t const *id3_field_getlatin1(union id3_field const *field)
|
cannam@85
|
772 {
|
cannam@85
|
773 assert(field);
|
cannam@85
|
774
|
cannam@85
|
775 if (field->type != ID3_FIELD_TYPE_LATIN1)
|
cannam@85
|
776 return 0;
|
cannam@85
|
777
|
cannam@85
|
778 return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
|
cannam@85
|
779 }
|
cannam@85
|
780
|
cannam@85
|
781 /*
|
cannam@85
|
782 * NAME: field->getfulllatin1()
|
cannam@85
|
783 * DESCRIPTION: return the value of a full latin1 field
|
cannam@85
|
784 */
|
cannam@85
|
785 id3_latin1_t const *id3_field_getfulllatin1(union id3_field const *field)
|
cannam@85
|
786 {
|
cannam@85
|
787 assert(field);
|
cannam@85
|
788
|
cannam@85
|
789 if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
|
cannam@85
|
790 return 0;
|
cannam@85
|
791
|
cannam@85
|
792 return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
|
cannam@85
|
793 }
|
cannam@85
|
794
|
cannam@85
|
795 /*
|
cannam@85
|
796 * NAME: field->getstring()
|
cannam@85
|
797 * DESCRIPTION: return the value of a string field
|
cannam@85
|
798 */
|
cannam@85
|
799 id3_ucs4_t const *id3_field_getstring(union id3_field const *field)
|
cannam@85
|
800 {
|
cannam@85
|
801 assert(field);
|
cannam@85
|
802
|
cannam@85
|
803 if (field->type != ID3_FIELD_TYPE_STRING)
|
cannam@85
|
804 return 0;
|
cannam@85
|
805
|
cannam@85
|
806 return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
|
cannam@85
|
807 }
|
cannam@85
|
808
|
cannam@85
|
809 /*
|
cannam@85
|
810 * NAME: field->getfullstring()
|
cannam@85
|
811 * DESCRIPTION: return the value of a fullstring field
|
cannam@85
|
812 */
|
cannam@85
|
813 id3_ucs4_t const *id3_field_getfullstring(union id3_field const *field)
|
cannam@85
|
814 {
|
cannam@85
|
815 assert(field);
|
cannam@85
|
816
|
cannam@85
|
817 if (field->type != ID3_FIELD_TYPE_STRINGFULL)
|
cannam@85
|
818 return 0;
|
cannam@85
|
819
|
cannam@85
|
820 return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
|
cannam@85
|
821 }
|
cannam@85
|
822
|
cannam@85
|
823 /*
|
cannam@85
|
824 * NAME: field->getnstrings()
|
cannam@85
|
825 * DESCRIPTION: return the number of strings in a stringlist field
|
cannam@85
|
826 */
|
cannam@85
|
827 unsigned int id3_field_getnstrings(union id3_field const *field)
|
cannam@85
|
828 {
|
cannam@85
|
829 assert(field);
|
cannam@85
|
830
|
cannam@85
|
831 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
|
cannam@85
|
832 return 0;
|
cannam@85
|
833
|
cannam@85
|
834 return field->stringlist.nstrings;
|
cannam@85
|
835 }
|
cannam@85
|
836
|
cannam@85
|
837 /*
|
cannam@85
|
838 * NAME: field->getstrings()
|
cannam@85
|
839 * DESCRIPTION: return one value of a stringlist field
|
cannam@85
|
840 */
|
cannam@85
|
841 id3_ucs4_t const *id3_field_getstrings(union id3_field const *field,
|
cannam@85
|
842 unsigned int index)
|
cannam@85
|
843 {
|
cannam@85
|
844 id3_ucs4_t const *string;
|
cannam@85
|
845
|
cannam@85
|
846 assert(field);
|
cannam@85
|
847
|
cannam@85
|
848 if (field->type != ID3_FIELD_TYPE_STRINGLIST ||
|
cannam@85
|
849 index >= field->stringlist.nstrings)
|
cannam@85
|
850 return 0;
|
cannam@85
|
851
|
cannam@85
|
852 string = field->stringlist.strings[index];
|
cannam@85
|
853
|
cannam@85
|
854 return string ? string : id3_ucs4_empty;
|
cannam@85
|
855 }
|
cannam@85
|
856
|
cannam@85
|
857 /*
|
cannam@85
|
858 * NAME: field->getframeid()
|
cannam@85
|
859 * DESCRIPTION: return the value of a frameid field
|
cannam@85
|
860 */
|
cannam@85
|
861 char const *id3_field_getframeid(union id3_field const *field)
|
cannam@85
|
862 {
|
cannam@85
|
863 assert(field);
|
cannam@85
|
864
|
cannam@85
|
865 if (field->type != ID3_FIELD_TYPE_FRAMEID)
|
cannam@85
|
866 return 0;
|
cannam@85
|
867
|
cannam@85
|
868 return field->immediate.value;
|
cannam@85
|
869 }
|
cannam@85
|
870
|
cannam@85
|
871 /*
|
cannam@85
|
872 * NAME: field->getbinarydata()
|
cannam@85
|
873 * DESCRIPTION: return the value of a binarydata field
|
cannam@85
|
874 */
|
cannam@85
|
875 id3_byte_t const *id3_field_getbinarydata(union id3_field const *field,
|
cannam@85
|
876 id3_length_t *length)
|
cannam@85
|
877 {
|
cannam@85
|
878 static id3_byte_t const empty;
|
cannam@85
|
879
|
cannam@85
|
880 assert(field && length);
|
cannam@85
|
881
|
cannam@85
|
882 if (field->type != ID3_FIELD_TYPE_BINARYDATA)
|
cannam@85
|
883 return 0;
|
cannam@85
|
884
|
cannam@85
|
885 assert(field->binary.length == 0 || field->binary.data);
|
cannam@85
|
886
|
cannam@85
|
887 *length = field->binary.length;
|
cannam@85
|
888
|
cannam@85
|
889 return field->binary.data ? field->binary.data : ∅
|
cannam@85
|
890 }
|