annotate src/libid3tag-0.15.1b/field.c @ 83:ae30d91d2ffe

Replace these with versions built using an older toolset (so as to avoid ABI compatibilities when linking on Ubuntu 14.04 for packaging purposes)
author Chris Cannam
date Fri, 07 Feb 2020 11:51:13 +0000
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 }