47void 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;
103void 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);
162enum id3_field_type id3_field_type(
union id3_field const *field)
173int 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;
337id3_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);
408int 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;
448int 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;
464int 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;
485int 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);
510int 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);
523int 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;
544int 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);
569int 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);
585int 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;
626int 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;
659int 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);
682int 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;
705int 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;
739signed 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;
756enum id3_field_textencoding
757id3_field_gettextencoding(
union id3_field const *field)
761 if (field->type != ID3_FIELD_TYPE_TEXTENCODING)
764 return field->number.value;
771id3_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 *)
"";
785id3_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 *)
"";
799id3_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;
813id3_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;
827unsigned int id3_field_getnstrings(
union id3_field const *field)
831 if (field->type != ID3_FIELD_TYPE_STRINGLIST)
834 return field->stringlist.nstrings;
841id3_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;
861char const *id3_field_getframeid(
union id3_field const *field)
865 if (field->type != ID3_FIELD_TYPE_FRAMEID)
868 return field->immediate.value;
875id3_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 : ∅