comparison src/libid3tag/field.c @ 2503:10692383c103 trunk

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