annotate src/libid3tag-0.15.1b/field.c @ 169:223a55898ab9 tip default

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