libsodium: Needed for Dnscrypto-proxy Release 1.3.0
[tomato.git] / release / src / router / libid3tag / field.c
blobf2ecc0fd485d0ec018d7c48d11fc9d5aa54b42c6
1 /*
2 * libid3tag - ID3 tag manipulation library
3 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 * $Id: field.c,v 1.16 2004/01/23 09:41:32 rob Exp $
22 # ifdef HAVE_CONFIG_H
23 # include "config.h"
24 # endif
26 # include "global.h"
28 # include <stdlib.h>
29 # include <string.h>
31 # ifdef HAVE_ASSERT_H
32 # include <assert.h>
33 # endif
35 # include "id3tag.h"
36 # include "field.h"
37 # include "frame.h"
38 # include "render.h"
39 # include "ucs4.h"
40 # include "latin1.h"
41 # include "parse.h"
44 * NAME: field->init()
45 * DESCRIPTION: initialize a field to a default value for the given type
47 void id3_field_init(union id3_field *field, enum id3_field_type type)
49 assert(field);
51 switch (field->type = type) {
52 case ID3_FIELD_TYPE_TEXTENCODING:
53 case ID3_FIELD_TYPE_INT8:
54 case ID3_FIELD_TYPE_INT16:
55 case ID3_FIELD_TYPE_INT24:
56 case ID3_FIELD_TYPE_INT32:
57 field->number.value = 0;
58 break;
60 case ID3_FIELD_TYPE_LATIN1:
61 case ID3_FIELD_TYPE_LATIN1FULL:
62 field->latin1.ptr = 0;
63 break;
65 case ID3_FIELD_TYPE_LATIN1LIST:
66 field->latin1list.nstrings = 0;
67 field->latin1list.strings = 0;
69 case ID3_FIELD_TYPE_STRING:
70 case ID3_FIELD_TYPE_STRINGFULL:
71 field->string.ptr = 0;
72 break;
74 case ID3_FIELD_TYPE_STRINGLIST:
75 field->stringlist.nstrings = 0;
76 field->stringlist.strings = 0;
77 break;
79 case ID3_FIELD_TYPE_LANGUAGE:
80 strcpy(field->immediate.value, "XXX");
81 break;
83 case ID3_FIELD_TYPE_FRAMEID:
84 strcpy(field->immediate.value, "XXXX");
85 break;
87 case ID3_FIELD_TYPE_DATE:
88 memset(field->immediate.value, 0, sizeof(field->immediate.value));
89 break;
91 case ID3_FIELD_TYPE_INT32PLUS:
92 case ID3_FIELD_TYPE_BINARYDATA:
93 field->binary.data = 0;
94 field->binary.length = 0;
95 break;
100 * NAME: field->finish()
101 * DESCRIPTION: reset a field, deallocating memory if necessary
103 void id3_field_finish(union id3_field *field)
105 unsigned int i;
107 assert(field);
109 switch (field->type) {
110 case ID3_FIELD_TYPE_TEXTENCODING:
111 case ID3_FIELD_TYPE_INT8:
112 case ID3_FIELD_TYPE_INT16:
113 case ID3_FIELD_TYPE_INT24:
114 case ID3_FIELD_TYPE_INT32:
115 case ID3_FIELD_TYPE_LANGUAGE:
116 case ID3_FIELD_TYPE_FRAMEID:
117 case ID3_FIELD_TYPE_DATE:
118 break;
120 case ID3_FIELD_TYPE_LATIN1:
121 case ID3_FIELD_TYPE_LATIN1FULL:
122 if (field->latin1.ptr)
123 free(field->latin1.ptr);
124 break;
126 case ID3_FIELD_TYPE_LATIN1LIST:
127 for (i = 0; i < field->latin1list.nstrings; ++i)
128 free(field->latin1list.strings[i]);
130 if (field->latin1list.strings)
131 free(field->latin1list.strings);
132 break;
134 case ID3_FIELD_TYPE_STRING:
135 case ID3_FIELD_TYPE_STRINGFULL:
136 if (field->string.ptr)
137 free(field->string.ptr);
138 break;
140 case ID3_FIELD_TYPE_STRINGLIST:
141 for (i = 0; i < field->stringlist.nstrings; ++i)
142 free(field->stringlist.strings[i]);
144 if (field->stringlist.strings)
145 free(field->stringlist.strings);
146 break;
148 case ID3_FIELD_TYPE_INT32PLUS:
149 case ID3_FIELD_TYPE_BINARYDATA:
150 if (field->binary.data)
151 free(field->binary.data);
152 break;
155 id3_field_init(field, field->type);
159 * NAME: field->type()
160 * DESCRIPTION: return the value type of a field
162 enum id3_field_type id3_field_type(union id3_field const *field)
164 assert(field);
166 return field->type;
170 * NAME: field->parse()
171 * DESCRIPTION: parse a field value
173 int id3_field_parse(union id3_field *field, id3_byte_t const **ptr,
174 id3_length_t length, enum id3_field_textencoding *encoding)
176 assert(field);
178 id3_field_finish(field);
180 switch (field->type) {
181 case ID3_FIELD_TYPE_INT32:
182 if (length < 4)
183 goto fail;
185 field->number.value = id3_parse_uint(ptr, 4);
186 break;
188 case ID3_FIELD_TYPE_INT24:
189 if (length < 3)
190 goto fail;
192 field->number.value = id3_parse_uint(ptr, 3);
193 break;
195 case ID3_FIELD_TYPE_INT16:
196 if (length < 2)
197 goto fail;
199 field->number.value = id3_parse_uint(ptr, 2);
200 break;
202 case ID3_FIELD_TYPE_INT8:
203 case ID3_FIELD_TYPE_TEXTENCODING:
204 if (length < 1)
205 goto fail;
207 field->number.value = id3_parse_uint(ptr, 1);
209 if (field->type == ID3_FIELD_TYPE_TEXTENCODING)
210 *encoding = field->number.value;
211 break;
213 case ID3_FIELD_TYPE_LANGUAGE:
214 if (length < 3)
215 goto fail;
217 id3_parse_immediate(ptr, 3, field->immediate.value);
218 break;
220 case ID3_FIELD_TYPE_FRAMEID:
221 if (length < 4)
222 goto fail;
224 id3_parse_immediate(ptr, 4, field->immediate.value);
225 break;
227 case ID3_FIELD_TYPE_DATE:
228 if (length < 8)
229 goto fail;
231 id3_parse_immediate(ptr, 8, field->immediate.value);
232 break;
234 case ID3_FIELD_TYPE_LATIN1:
235 case ID3_FIELD_TYPE_LATIN1FULL:
237 id3_latin1_t *latin1;
239 latin1 = id3_parse_latin1(ptr, length,
240 field->type == ID3_FIELD_TYPE_LATIN1FULL);
241 if (latin1 == 0)
242 goto fail;
244 field->latin1.ptr = latin1;
246 break;
248 case ID3_FIELD_TYPE_LATIN1LIST:
250 id3_byte_t const *end;
251 id3_latin1_t *latin1, **strings;
253 end = *ptr + length;
255 while (end - *ptr > 0) {
256 latin1 = id3_parse_latin1(ptr, end - *ptr, 0);
257 if (latin1 == 0)
258 goto fail;
260 strings = realloc(field->latin1list.strings,
261 (field->latin1list.nstrings + 1) * sizeof(*strings));
262 if (strings == 0) {
263 free(latin1);
264 goto fail;
267 field->latin1list.strings = strings;
268 field->latin1list.strings[field->latin1list.nstrings++] = latin1;
271 break;
273 case ID3_FIELD_TYPE_STRING:
274 case ID3_FIELD_TYPE_STRINGFULL:
276 id3_ucs4_t *ucs4;
278 ucs4 = id3_parse_string(ptr, length, *encoding,
279 field->type == ID3_FIELD_TYPE_STRINGFULL);
280 if (ucs4 == 0)
281 goto fail;
283 field->string.ptr = ucs4;
285 break;
287 case ID3_FIELD_TYPE_STRINGLIST:
289 id3_byte_t const *end;
290 id3_ucs4_t *ucs4, **strings;
292 end = *ptr + length;
294 while (end - *ptr > 0) {
295 ucs4 = id3_parse_string(ptr, end - *ptr, *encoding, 0);
296 if (ucs4 == 0)
297 goto fail;
299 strings = realloc(field->stringlist.strings,
300 (field->stringlist.nstrings + 1) * sizeof(*strings));
301 if (strings == 0) {
302 free(ucs4);
303 goto fail;
306 field->stringlist.strings = strings;
307 field->stringlist.strings[field->stringlist.nstrings++] = ucs4;
310 break;
312 case ID3_FIELD_TYPE_INT32PLUS:
313 case ID3_FIELD_TYPE_BINARYDATA:
315 id3_byte_t *data;
317 data = id3_parse_binary(ptr, length);
318 if (data == 0)
319 goto fail;
321 field->binary.data = data;
322 field->binary.length = length;
324 break;
327 return 0;
329 fail:
330 return -1;
334 * NAME: field->render()
335 * DESCRIPTION: render a field value
337 id3_length_t id3_field_render(union id3_field const *field, id3_byte_t **ptr,
338 enum id3_field_textencoding *encoding,
339 int terminate)
341 id3_length_t size;
342 unsigned int i;
344 assert(field && encoding);
346 switch (field->type) {
347 case ID3_FIELD_TYPE_INT32:
348 return id3_render_int(ptr, field->number.value, 4);
350 case ID3_FIELD_TYPE_INT24:
351 return id3_render_int(ptr, field->number.value, 3);
353 case ID3_FIELD_TYPE_INT16:
354 return id3_render_int(ptr, field->number.value, 2);
356 case ID3_FIELD_TYPE_TEXTENCODING:
357 *encoding = field->number.value;
358 case ID3_FIELD_TYPE_INT8:
359 return id3_render_int(ptr, field->number.value, 1);
361 case ID3_FIELD_TYPE_LATIN1:
362 case ID3_FIELD_TYPE_LATIN1FULL:
363 return id3_render_latin1(ptr, field->latin1.ptr, terminate);
365 case ID3_FIELD_TYPE_LATIN1LIST:
366 size = 0;
367 for (i = 0; i < field->latin1list.nstrings; ++i) {
368 size += id3_render_latin1(ptr, field->latin1list.strings[i],
369 (i < field->latin1list.nstrings - 1) ||
370 terminate);
372 return size;
374 case ID3_FIELD_TYPE_STRING:
375 case ID3_FIELD_TYPE_STRINGFULL:
376 return id3_render_string(ptr, field->string.ptr, *encoding, terminate);
378 case ID3_FIELD_TYPE_STRINGLIST:
379 size = 0;
380 for (i = 0; i < field->stringlist.nstrings; ++i) {
381 size += id3_render_string(ptr, field->stringlist.strings[i], *encoding,
382 (i < field->stringlist.nstrings - 1) ||
383 terminate);
385 return size;
387 case ID3_FIELD_TYPE_LANGUAGE:
388 return id3_render_immediate(ptr, field->immediate.value, 3);
390 case ID3_FIELD_TYPE_FRAMEID:
391 return id3_render_immediate(ptr, field->immediate.value, 4);
393 case ID3_FIELD_TYPE_DATE:
394 return id3_render_immediate(ptr, field->immediate.value, 8);
396 case ID3_FIELD_TYPE_INT32PLUS:
397 case ID3_FIELD_TYPE_BINARYDATA:
398 return id3_render_binary(ptr, field->binary.data, field->binary.length);
401 return 0;
405 * NAME: field->setint()
406 * DESCRIPTION: set the value of an int field
408 int id3_field_setint(union id3_field *field, signed long number)
410 assert(field);
412 switch (field->type) {
413 case ID3_FIELD_TYPE_INT8:
414 if (number > 0x7f || number < -0x80)
415 return -1;
416 break;
418 case ID3_FIELD_TYPE_INT16:
419 if (number > 0x7fff || number < -0x8000)
420 return -1;
421 break;
423 case ID3_FIELD_TYPE_INT24:
424 if (number > 0x7fffffL || number < -0x800000L)
425 return -1;
426 break;
428 case ID3_FIELD_TYPE_INT32:
429 if (number > 0x7fffffffL || number < -0x80000000L)
430 return -1;
431 break;
433 default:
434 return -1;
437 id3_field_finish(field);
439 field->number.value = number;
441 return 0;
445 * NAME: field->settextencoding()
446 * DESCRIPTION: set the value of a textencoding field
448 int id3_field_settextencoding(union id3_field *field,
449 enum id3_field_textencoding encoding)
451 assert(field);
453 if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
454 return -1;
456 id3_field_finish(field);
458 field->number.value = encoding;
460 return 0;
463 static
464 int set_latin1(union id3_field *field, id3_latin1_t const *latin1)
466 id3_latin1_t *data;
468 if (latin1 == 0 || *latin1 == 0)
469 data = 0;
470 else {
471 data = id3_latin1_duplicate(latin1);
472 if (data == 0)
473 return -1;
476 field->latin1.ptr = data;
478 return 0;
482 * NAME: field->setlatin1()
483 * DESCRIPTION: set the value of a latin1 field
485 int id3_field_setlatin1(union id3_field *field, id3_latin1_t const *latin1)
487 assert(field);
489 if (field->type != ID3_FIELD_TYPE_LATIN1)
490 return -1;
492 id3_field_finish(field);
494 if (latin1) {
495 id3_latin1_t const *ptr;
497 for (ptr = latin1; *ptr; ++ptr) {
498 if (*ptr == '\n')
499 return -1;
503 return set_latin1(field, latin1);
507 * NAME: field->setfulllatin1()
508 * DESCRIPTION: set the value of a full latin1 field
510 int id3_field_setfulllatin1(union id3_field *field, id3_latin1_t const *latin1)
512 assert(field);
514 if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
515 return -1;
517 id3_field_finish(field);
519 return set_latin1(field, latin1);
522 static
523 int set_string(union id3_field *field, id3_ucs4_t const *string)
525 id3_ucs4_t *data;
527 if (string == 0 || *string == 0)
528 data = 0;
529 else {
530 data = id3_ucs4_duplicate(string);
531 if (data == 0)
532 return -1;
535 field->string.ptr = data;
537 return 0;
541 * NAME: field->setstring()
542 * DESCRIPTION: set the value of a string field
544 int id3_field_setstring(union id3_field *field, id3_ucs4_t const *string)
546 assert(field);
548 if (field->type != ID3_FIELD_TYPE_STRING)
549 return -1;
551 id3_field_finish(field);
553 if (string) {
554 id3_ucs4_t const *ptr;
556 for (ptr = string; *ptr; ++ptr) {
557 if (*ptr == '\n')
558 return -1;
562 return set_string(field, string);
566 * NAME: field->setfullstring()
567 * DESCRIPTION: set the value of a full string field
569 int id3_field_setfullstring(union id3_field *field, id3_ucs4_t const *string)
571 assert(field);
573 if (field->type != ID3_FIELD_TYPE_STRINGFULL)
574 return -1;
576 id3_field_finish(field);
578 return set_string(field, string);
582 * NAME: field->setstrings()
583 * DESCRIPTION: set the value of a stringlist field
585 int id3_field_setstrings(union id3_field *field,
586 unsigned int length, id3_ucs4_t **ptrs)
588 id3_ucs4_t **strings;
589 unsigned int i;
591 assert(field);
593 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
594 return -1;
596 id3_field_finish(field);
598 if (length == 0)
599 return 0;
601 strings = malloc(length * sizeof(*strings));
602 if (strings == 0)
603 return -1;
605 for (i = 0; i < length; ++i) {
606 strings[i] = id3_ucs4_duplicate(ptrs[i]);
607 if (strings[i] == 0) {
608 while (i--)
609 free(strings[i]);
611 free(strings);
612 return -1;
616 field->stringlist.strings = strings;
617 field->stringlist.nstrings = length;
619 return 0;
623 * NAME: field->addstring()
624 * DESCRIPTION: add a string to a stringlist field
626 int id3_field_addstring(union id3_field *field, id3_ucs4_t const *string)
628 id3_ucs4_t *new, **strings;
630 assert(field);
632 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
633 return -1;
635 if (string == 0)
636 string = id3_ucs4_empty;
638 new = id3_ucs4_duplicate(string);
639 if (new == 0)
640 return -1;
642 strings = realloc(field->stringlist.strings,
643 (field->stringlist.nstrings + 1) * sizeof(*strings));
644 if (strings == 0) {
645 free(new);
646 return -1;
649 field->stringlist.strings = strings;
650 field->stringlist.strings[field->stringlist.nstrings++] = new;
652 return 0;
656 * NAME: field->setlanguage()
657 * DESCRIPTION: set the value of a language field
659 int id3_field_setlanguage(union id3_field *field, char const *language)
661 assert(field);
663 if (field->type != ID3_FIELD_TYPE_LANGUAGE)
664 return -1;
666 id3_field_finish(field);
668 if (language) {
669 if (strlen(language) != 3)
670 return -1;
672 strcpy(field->immediate.value, language);
675 return 0;
679 * NAME: field->setframeid()
680 * DESCRIPTION: set the value of a frameid field
682 int id3_field_setframeid(union id3_field *field, char const *id)
684 assert(field);
686 if (field->type != ID3_FIELD_TYPE_FRAMEID ||
687 !id3_frame_validid(id))
688 return -1;
690 id3_field_finish(field);
692 field->immediate.value[0] = id[0];
693 field->immediate.value[1] = id[1];
694 field->immediate.value[2] = id[2];
695 field->immediate.value[3] = id[3];
696 field->immediate.value[4] = 0;
698 return 0;
702 * NAME: field->setbinarydata()
703 * DESCRIPTION: set the value of a binarydata field
705 int id3_field_setbinarydata(union id3_field *field,
706 id3_byte_t const *data, id3_length_t length)
708 id3_byte_t *mem;
710 assert(field);
712 if (field->type != ID3_FIELD_TYPE_BINARYDATA)
713 return -1;
715 id3_field_finish(field);
717 if (length == 0)
718 mem = 0;
719 else {
720 mem = malloc(length);
721 if (mem == 0)
722 return -1;
724 assert(data);
726 memcpy(mem, data, length);
729 field->binary.data = mem;
730 field->binary.length = length;
732 return 0;
736 * NAME: field->getint()
737 * DESCRIPTION: return the value of an integer field
739 signed long id3_field_getint(union id3_field const *field)
741 assert(field);
743 if (field->type != ID3_FIELD_TYPE_INT8 &&
744 field->type != ID3_FIELD_TYPE_INT16 &&
745 field->type != ID3_FIELD_TYPE_INT24 &&
746 field->type != ID3_FIELD_TYPE_INT32)
747 return -1;
749 return field->number.value;
753 * NAME: field->gettextencoding()
754 * DESCRIPTION: return the value of a text encoding field
756 enum id3_field_textencoding
757 id3_field_gettextencoding(union id3_field const *field)
759 assert(field);
761 if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
762 return -1;
764 return field->number.value;
768 * NAME: field->getlatin1()
769 * DESCRIPTION: return the value of a latin1 field
771 id3_latin1_t const *id3_field_getlatin1(union id3_field const *field)
773 assert(field);
775 if (field->type != ID3_FIELD_TYPE_LATIN1)
776 return 0;
778 return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
782 * NAME: field->getfulllatin1()
783 * DESCRIPTION: return the value of a full latin1 field
785 id3_latin1_t const *id3_field_getfulllatin1(union id3_field const *field)
787 assert(field);
789 if (field->type != ID3_FIELD_TYPE_LATIN1FULL)
790 return 0;
792 return field->latin1.ptr ? field->latin1.ptr : (id3_latin1_t const *) "";
796 * NAME: field->getstring()
797 * DESCRIPTION: return the value of a string field
799 id3_ucs4_t const *id3_field_getstring(union id3_field const *field)
801 assert(field);
803 if (field->type != ID3_FIELD_TYPE_STRING)
804 return 0;
806 return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
810 * NAME: field->getfullstring()
811 * DESCRIPTION: return the value of a fullstring field
813 id3_ucs4_t const *id3_field_getfullstring(union id3_field const *field)
815 assert(field);
817 if (field->type != ID3_FIELD_TYPE_STRINGFULL)
818 return 0;
820 return field->string.ptr ? field->string.ptr : id3_ucs4_empty;
824 * NAME: field->getnstrings()
825 * DESCRIPTION: return the number of strings in a stringlist field
827 unsigned int id3_field_getnstrings(union id3_field const *field)
829 assert(field);
831 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
832 return 0;
834 return field->stringlist.nstrings;
838 * NAME: field->getstrings()
839 * DESCRIPTION: return one value of a stringlist field
841 id3_ucs4_t const *id3_field_getstrings(union id3_field const *field,
842 unsigned int index)
844 id3_ucs4_t const *string;
846 assert(field);
848 if (field->type != ID3_FIELD_TYPE_STRINGLIST ||
849 index >= field->stringlist.nstrings)
850 return 0;
852 string = field->stringlist.strings[index];
854 return string ? string : id3_ucs4_empty;
858 * NAME: field->getframeid()
859 * DESCRIPTION: return the value of a frameid field
861 char const *id3_field_getframeid(union id3_field const *field)
863 assert(field);
865 if (field->type != ID3_FIELD_TYPE_FRAMEID)
866 return 0;
868 return field->immediate.value;
872 * NAME: field->getbinarydata()
873 * DESCRIPTION: return the value of a binarydata field
875 id3_byte_t const *id3_field_getbinarydata(union id3_field const *field,
876 id3_length_t *length)
878 static id3_byte_t const empty;
880 assert(field && length);
882 if (field->type != ID3_FIELD_TYPE_BINARYDATA)
883 return 0;
885 assert(field->binary.length == 0 || field->binary.data);
887 *length = field->binary.length;
889 return field->binary.data ? field->binary.data : &empty;