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 $
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
)
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;
60 case ID3_FIELD_TYPE_LATIN1
:
61 case ID3_FIELD_TYPE_LATIN1FULL
:
62 field
->latin1
.ptr
= 0;
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;
74 case ID3_FIELD_TYPE_STRINGLIST
:
75 field
->stringlist
.nstrings
= 0;
76 field
->stringlist
.strings
= 0;
79 case ID3_FIELD_TYPE_LANGUAGE
:
80 strcpy(field
->immediate
.value
, "XXX");
83 case ID3_FIELD_TYPE_FRAMEID
:
84 strcpy(field
->immediate
.value
, "XXXX");
87 case ID3_FIELD_TYPE_DATE
:
88 memset(field
->immediate
.value
, 0, sizeof(field
->immediate
.value
));
91 case ID3_FIELD_TYPE_INT32PLUS
:
92 case ID3_FIELD_TYPE_BINARYDATA
:
93 field
->binary
.data
= 0;
94 field
->binary
.length
= 0;
100 * NAME: field->finish()
101 * DESCRIPTION: reset a field, deallocating memory if necessary
103 void id3_field_finish(union id3_field
*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
:
120 case ID3_FIELD_TYPE_LATIN1
:
121 case ID3_FIELD_TYPE_LATIN1FULL
:
122 if (field
->latin1
.ptr
)
123 free(field
->latin1
.ptr
);
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
);
134 case ID3_FIELD_TYPE_STRING
:
135 case ID3_FIELD_TYPE_STRINGFULL
:
136 if (field
->string
.ptr
)
137 free(field
->string
.ptr
);
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
);
148 case ID3_FIELD_TYPE_INT32PLUS
:
149 case ID3_FIELD_TYPE_BINARYDATA
:
150 if (field
->binary
.data
)
151 free(field
->binary
.data
);
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
)
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
)
178 id3_field_finish(field
);
180 switch (field
->type
) {
181 case ID3_FIELD_TYPE_INT32
:
185 field
->number
.value
= id3_parse_uint(ptr
, 4);
188 case ID3_FIELD_TYPE_INT24
:
192 field
->number
.value
= id3_parse_uint(ptr
, 3);
195 case ID3_FIELD_TYPE_INT16
:
199 field
->number
.value
= id3_parse_uint(ptr
, 2);
202 case ID3_FIELD_TYPE_INT8
:
203 case ID3_FIELD_TYPE_TEXTENCODING
:
207 field
->number
.value
= id3_parse_uint(ptr
, 1);
209 if (field
->type
== ID3_FIELD_TYPE_TEXTENCODING
)
210 *encoding
= field
->number
.value
;
213 case ID3_FIELD_TYPE_LANGUAGE
:
217 id3_parse_immediate(ptr
, 3, field
->immediate
.value
);
220 case ID3_FIELD_TYPE_FRAMEID
:
224 id3_parse_immediate(ptr
, 4, field
->immediate
.value
);
227 case ID3_FIELD_TYPE_DATE
:
231 id3_parse_immediate(ptr
, 8, field
->immediate
.value
);
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
);
244 field
->latin1
.ptr
= latin1
;
248 case ID3_FIELD_TYPE_LATIN1LIST
:
250 id3_byte_t
const *end
;
251 id3_latin1_t
*latin1
, **strings
;
255 while (end
- *ptr
> 0) {
256 latin1
= id3_parse_latin1(ptr
, end
- *ptr
, 0);
260 strings
= realloc(field
->latin1list
.strings
,
261 (field
->latin1list
.nstrings
+ 1) * sizeof(*strings
));
267 field
->latin1list
.strings
= strings
;
268 field
->latin1list
.strings
[field
->latin1list
.nstrings
++] = latin1
;
273 case ID3_FIELD_TYPE_STRING
:
274 case ID3_FIELD_TYPE_STRINGFULL
:
278 ucs4
= id3_parse_string(ptr
, length
, *encoding
,
279 field
->type
== ID3_FIELD_TYPE_STRINGFULL
);
283 field
->string
.ptr
= ucs4
;
287 case ID3_FIELD_TYPE_STRINGLIST
:
289 id3_byte_t
const *end
;
290 id3_ucs4_t
*ucs4
, **strings
;
294 while (end
- *ptr
> 0) {
295 ucs4
= id3_parse_string(ptr
, end
- *ptr
, *encoding
, 0);
299 strings
= realloc(field
->stringlist
.strings
,
300 (field
->stringlist
.nstrings
+ 1) * sizeof(*strings
));
306 field
->stringlist
.strings
= strings
;
307 field
->stringlist
.strings
[field
->stringlist
.nstrings
++] = ucs4
;
312 case ID3_FIELD_TYPE_INT32PLUS
:
313 case ID3_FIELD_TYPE_BINARYDATA
:
317 data
= id3_parse_binary(ptr
, length
);
321 field
->binary
.data
= data
;
322 field
->binary
.length
= length
;
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
,
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
:
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) ||
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
:
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) ||
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
);
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
)
412 switch (field
->type
) {
413 case ID3_FIELD_TYPE_INT8
:
414 if (number
> 0x7f || number
< -0x80)
418 case ID3_FIELD_TYPE_INT16
:
419 if (number
> 0x7fff || number
< -0x8000)
423 case ID3_FIELD_TYPE_INT24
:
424 if (number
> 0x7fffffL
|| number
< -0x800000L
)
428 case ID3_FIELD_TYPE_INT32
:
429 if (number
> 0x7fffffffL
|| number
< -0x80000000L
)
437 id3_field_finish(field
);
439 field
->number
.value
= number
;
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
)
453 if (field
->type
!= ID3_FIELD_TYPE_TEXTENCODING
)
456 id3_field_finish(field
);
458 field
->number
.value
= encoding
;
464 int set_latin1(union id3_field
*field
, id3_latin1_t
const *latin1
)
468 if (latin1
== 0 || *latin1
== 0)
471 data
= id3_latin1_duplicate(latin1
);
476 field
->latin1
.ptr
= data
;
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
)
489 if (field
->type
!= ID3_FIELD_TYPE_LATIN1
)
492 id3_field_finish(field
);
495 id3_latin1_t
const *ptr
;
497 for (ptr
= latin1
; *ptr
; ++ptr
) {
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
)
514 if (field
->type
!= ID3_FIELD_TYPE_LATIN1FULL
)
517 id3_field_finish(field
);
519 return set_latin1(field
, latin1
);
523 int set_string(union id3_field
*field
, id3_ucs4_t
const *string
)
527 if (string
== 0 || *string
== 0)
530 data
= id3_ucs4_duplicate(string
);
535 field
->string
.ptr
= data
;
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
)
548 if (field
->type
!= ID3_FIELD_TYPE_STRING
)
551 id3_field_finish(field
);
554 id3_ucs4_t
const *ptr
;
556 for (ptr
= string
; *ptr
; ++ptr
) {
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
)
573 if (field
->type
!= ID3_FIELD_TYPE_STRINGFULL
)
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
;
593 if (field
->type
!= ID3_FIELD_TYPE_STRINGLIST
)
596 id3_field_finish(field
);
601 strings
= malloc(length
* sizeof(*strings
));
605 for (i
= 0; i
< length
; ++i
) {
606 strings
[i
] = id3_ucs4_duplicate(ptrs
[i
]);
607 if (strings
[i
] == 0) {
616 field
->stringlist
.strings
= strings
;
617 field
->stringlist
.nstrings
= length
;
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
;
632 if (field
->type
!= ID3_FIELD_TYPE_STRINGLIST
)
636 string
= id3_ucs4_empty
;
638 new = id3_ucs4_duplicate(string
);
642 strings
= realloc(field
->stringlist
.strings
,
643 (field
->stringlist
.nstrings
+ 1) * sizeof(*strings
));
649 field
->stringlist
.strings
= strings
;
650 field
->stringlist
.strings
[field
->stringlist
.nstrings
++] = new;
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
)
663 if (field
->type
!= ID3_FIELD_TYPE_LANGUAGE
)
666 id3_field_finish(field
);
669 if (strlen(language
) != 3)
672 strcpy(field
->immediate
.value
, language
);
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
)
686 if (field
->type
!= ID3_FIELD_TYPE_FRAMEID
||
687 !id3_frame_validid(id
))
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;
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
)
712 if (field
->type
!= ID3_FIELD_TYPE_BINARYDATA
)
715 id3_field_finish(field
);
720 mem
= malloc(length
);
726 memcpy(mem
, data
, length
);
729 field
->binary
.data
= mem
;
730 field
->binary
.length
= length
;
736 * NAME: field->getint()
737 * DESCRIPTION: return the value of an integer field
739 signed long id3_field_getint(union id3_field
const *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
)
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
)
761 if (field
->type
!= ID3_FIELD_TYPE_TEXTENCODING
)
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
)
775 if (field
->type
!= ID3_FIELD_TYPE_LATIN1
)
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
)
789 if (field
->type
!= ID3_FIELD_TYPE_LATIN1FULL
)
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
)
803 if (field
->type
!= ID3_FIELD_TYPE_STRING
)
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
)
817 if (field
->type
!= ID3_FIELD_TYPE_STRINGFULL
)
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
)
831 if (field
->type
!= ID3_FIELD_TYPE_STRINGLIST
)
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
,
844 id3_ucs4_t
const *string
;
848 if (field
->type
!= ID3_FIELD_TYPE_STRINGLIST
||
849 index
>= field
->stringlist
.nstrings
)
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
)
865 if (field
->type
!= ID3_FIELD_TYPE_FRAMEID
)
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
)
885 assert(field
->binary
.length
== 0 || field
->binary
.data
);
887 *length
= field
->binary
.length
;
889 return field
->binary
.data
? field
->binary
.data
: &empty
;