annotate src/libid3tag-0.15.1b/field.c @ 23:619f715526df sv_v2.1

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