annotate src/libid3tag-0.15.1b/compat.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 /* C code produced by gperf version 3.0.1 */
Chris@0 2 /* Command-line: gperf -tCcTonD -K id -N id3_compat_lookup -s -3 -k '*' compat.gperf */
Chris@0 3
Chris@0 4 #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \
Chris@0 5 && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \
Chris@0 6 && (')' == 41) && ('*' == 42) && ('+' == 43) && (',' == 44) \
Chris@0 7 && ('-' == 45) && ('.' == 46) && ('/' == 47) && ('0' == 48) \
Chris@0 8 && ('1' == 49) && ('2' == 50) && ('3' == 51) && ('4' == 52) \
Chris@0 9 && ('5' == 53) && ('6' == 54) && ('7' == 55) && ('8' == 56) \
Chris@0 10 && ('9' == 57) && (':' == 58) && (';' == 59) && ('<' == 60) \
Chris@0 11 && ('=' == 61) && ('>' == 62) && ('?' == 63) && ('A' == 65) \
Chris@0 12 && ('B' == 66) && ('C' == 67) && ('D' == 68) && ('E' == 69) \
Chris@0 13 && ('F' == 70) && ('G' == 71) && ('H' == 72) && ('I' == 73) \
Chris@0 14 && ('J' == 74) && ('K' == 75) && ('L' == 76) && ('M' == 77) \
Chris@0 15 && ('N' == 78) && ('O' == 79) && ('P' == 80) && ('Q' == 81) \
Chris@0 16 && ('R' == 82) && ('S' == 83) && ('T' == 84) && ('U' == 85) \
Chris@0 17 && ('V' == 86) && ('W' == 87) && ('X' == 88) && ('Y' == 89) \
Chris@0 18 && ('Z' == 90) && ('[' == 91) && ('\\' == 92) && (']' == 93) \
Chris@0 19 && ('^' == 94) && ('_' == 95) && ('a' == 97) && ('b' == 98) \
Chris@0 20 && ('c' == 99) && ('d' == 100) && ('e' == 101) && ('f' == 102) \
Chris@0 21 && ('g' == 103) && ('h' == 104) && ('i' == 105) && ('j' == 106) \
Chris@0 22 && ('k' == 107) && ('l' == 108) && ('m' == 109) && ('n' == 110) \
Chris@0 23 && ('o' == 111) && ('p' == 112) && ('q' == 113) && ('r' == 114) \
Chris@0 24 && ('s' == 115) && ('t' == 116) && ('u' == 117) && ('v' == 118) \
Chris@0 25 && ('w' == 119) && ('x' == 120) && ('y' == 121) && ('z' == 122) \
Chris@0 26 && ('{' == 123) && ('|' == 124) && ('}' == 125) && ('~' == 126))
Chris@0 27 /* The character set is not based on ISO-646. */
Chris@0 28 error "gperf generated tables don't work with this execution character set. Please report a bug to <bug-gnu-gperf@gnu.org>."
Chris@0 29 #endif
Chris@0 30
Chris@0 31 #line 1 "compat.gperf"
Chris@0 32
Chris@0 33 /*
Chris@0 34 * libid3tag - ID3 tag manipulation library
Chris@0 35 * Copyright (C) 2000-2004 Underbit Technologies, Inc.
Chris@0 36 *
Chris@0 37 * This program is free software; you can redistribute it and/or modify
Chris@0 38 * it under the terms of the GNU General Public License as published by
Chris@0 39 * the Free Software Foundation; either version 2 of the License, or
Chris@0 40 * (at your option) any later version.
Chris@0 41 *
Chris@0 42 * This program is distributed in the hope that it will be useful,
Chris@0 43 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Chris@0 44 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
Chris@0 45 * GNU General Public License for more details.
Chris@0 46 *
Chris@0 47 * You should have received a copy of the GNU General Public License
Chris@0 48 * along with this program; if not, write to the Free Software
Chris@0 49 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Chris@0 50 *
Chris@0 51 * Id: compat.gperf,v 1.11 2004/01/23 09:41:32 rob Exp
Chris@0 52 */
Chris@0 53
Chris@0 54 # ifdef HAVE_CONFIG_H
Chris@0 55 # include "config.h"
Chris@0 56 # endif
Chris@0 57
Chris@0 58 # include "global.h"
Chris@0 59
Chris@0 60 # include <stdlib.h>
Chris@0 61 # include <string.h>
Chris@0 62
Chris@0 63 # ifdef HAVE_ASSERT_H
Chris@0 64 # include <assert.h>
Chris@0 65 # endif
Chris@0 66
Chris@0 67 # include "id3tag.h"
Chris@0 68 # include "compat.h"
Chris@0 69 # include "frame.h"
Chris@0 70 # include "field.h"
Chris@0 71 # include "parse.h"
Chris@0 72 # include "ucs4.h"
Chris@0 73
Chris@0 74 # define EQ(id) #id, 0
Chris@0 75 # define OBSOLETE 0, 0
Chris@0 76 # define TX(id) #id, translate_##id
Chris@0 77
Chris@0 78 static id3_compat_func_t translate_TCON;
Chris@0 79
Chris@0 80 #define TOTAL_KEYWORDS 73
Chris@0 81 #define MIN_WORD_LENGTH 3
Chris@0 82 #define MAX_WORD_LENGTH 4
Chris@0 83 #define MIN_HASH_VALUE 6
Chris@0 84 #define MAX_HASH_VALUE 127
Chris@0 85 /* maximum key range = 122, duplicates = 0 */
Chris@0 86
Chris@0 87 #ifdef __GNUC__
Chris@0 88 __inline
Chris@0 89 #else
Chris@0 90 #ifdef __cplusplus
Chris@0 91 inline
Chris@0 92 #endif
Chris@0 93 #endif
Chris@0 94 static unsigned int
Chris@0 95 hash (str, len)
Chris@0 96 register const char *str;
Chris@0 97 register unsigned int len;
Chris@0 98 {
Chris@0 99 static const unsigned char asso_values[] =
Chris@0 100 {
Chris@0 101 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 102 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 103 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 104 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 105 128, 128, 128, 128, 128, 128, 128, 128, 128, 64,
Chris@0 106 58, 20, 15, 128, 128, 128, 128, 128, 128, 128,
Chris@0 107 128, 128, 128, 128, 128, 10, 18, 3, 6, 1,
Chris@0 108 47, 0, 128, 42, 62, 30, 31, 0, 19, 52,
Chris@0 109 10, 24, 8, 30, 5, 3, 30, 8, 25, 47,
Chris@0 110 3, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 111 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 112 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 113 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 114 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 115 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 116 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 117 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 118 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 119 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 120 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 121 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 122 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 123 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 124 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 125 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
Chris@0 126 128, 128, 128, 128, 128, 128, 128
Chris@0 127 };
Chris@0 128 register int hval = 0;
Chris@0 129
Chris@0 130 switch (len)
Chris@0 131 {
Chris@0 132 default:
Chris@0 133 hval += asso_values[(unsigned char)str[3]];
Chris@0 134 /*FALLTHROUGH*/
Chris@0 135 case 3:
Chris@0 136 hval += asso_values[(unsigned char)str[2]];
Chris@0 137 /*FALLTHROUGH*/
Chris@0 138 case 2:
Chris@0 139 hval += asso_values[(unsigned char)str[1]+1];
Chris@0 140 /*FALLTHROUGH*/
Chris@0 141 case 1:
Chris@0 142 hval += asso_values[(unsigned char)str[0]];
Chris@0 143 break;
Chris@0 144 }
Chris@0 145 return hval;
Chris@0 146 }
Chris@0 147
Chris@0 148 #ifdef __GNUC__
Chris@0 149 __inline
Chris@0 150 #endif
Chris@0 151 const struct id3_compat *
Chris@0 152 id3_compat_lookup (str, len)
Chris@0 153 register const char *str;
Chris@0 154 register unsigned int len;
Chris@0 155 {
Chris@0 156 static const struct id3_compat wordlist[] =
Chris@0 157 {
Chris@0 158 #line 97 "compat.gperf"
Chris@0 159 {"TLE", EQ(TLEN) /* Length */},
Chris@0 160 #line 68 "compat.gperf"
Chris@0 161 {"ETC", EQ(ETCO) /* Event timing codes */},
Chris@0 162 #line 126 "compat.gperf"
Chris@0 163 {"ULT", EQ(USLT) /* Unsynchronised lyric/text transcription */},
Chris@0 164 #line 123 "compat.gperf"
Chris@0 165 {"TYE", OBSOLETE /* Year [obsolete] */},
Chris@0 166 #line 92 "compat.gperf"
Chris@0 167 {"TFT", EQ(TFLT) /* File type */},
Chris@0 168 #line 84 "compat.gperf"
Chris@0 169 {"TCM", EQ(TCOM) /* Composer */},
Chris@0 170 #line 66 "compat.gperf"
Chris@0 171 {"EQU", OBSOLETE /* Equalization [obsolete] */},
Chris@0 172 #line 63 "compat.gperf"
Chris@0 173 {"COM", EQ(COMM) /* Comments */},
Chris@0 174 #line 130 "compat.gperf"
Chris@0 175 {"WCM", EQ(WCOM) /* Commercial information */},
Chris@0 176 #line 96 "compat.gperf"
Chris@0 177 {"TLA", EQ(TLAN) /* Language(s) */},
Chris@0 178 #line 88 "compat.gperf"
Chris@0 179 {"TDA", OBSOLETE /* Date [obsolete] */},
Chris@0 180 #line 124 "compat.gperf"
Chris@0 181 {"TYER", OBSOLETE /* Year [obsolete] */},
Chris@0 182 #line 83 "compat.gperf"
Chris@0 183 {"TBP", EQ(TBPM) /* BPM (beats per minute) */},
Chris@0 184 #line 87 "compat.gperf"
Chris@0 185 {"TCR", EQ(TCOP) /* Copyright message */},
Chris@0 186 #line 104 "compat.gperf"
Chris@0 187 {"TOT", EQ(TOAL) /* Original album/movie/show title */},
Chris@0 188 #line 89 "compat.gperf"
Chris@0 189 {"TDAT", OBSOLETE /* Date [obsolete] */},
Chris@0 190 #line 67 "compat.gperf"
Chris@0 191 {"EQUA", OBSOLETE /* Equalization [obsolete] */},
Chris@0 192 #line 102 "compat.gperf"
Chris@0 193 {"TOR", EQ(TDOR) /* Original release year [obsolete] */},
Chris@0 194 #line 131 "compat.gperf"
Chris@0 195 {"WCP", EQ(WCOP) /* Copyright/legal information */},
Chris@0 196 #line 99 "compat.gperf"
Chris@0 197 {"TOA", EQ(TOPE) /* Original artist(s)/performer(s) */},
Chris@0 198 #line 78 "compat.gperf"
Chris@0 199 {"RVA", OBSOLETE /* Relative volume adjustment [obsolete] */},
Chris@0 200 #line 120 "compat.gperf"
Chris@0 201 {"TT3", EQ(TIT3) /* Subtitle/description refinement */},
Chris@0 202 #line 98 "compat.gperf"
Chris@0 203 {"TMT", EQ(TMED) /* Media type */},
Chris@0 204 #line 76 "compat.gperf"
Chris@0 205 {"POP", EQ(POPM) /* Popularimeter */},
Chris@0 206 #line 74 "compat.gperf"
Chris@0 207 {"MLL", EQ(MLLT) /* MPEG location lookup table */},
Chris@0 208 #line 79 "compat.gperf"
Chris@0 209 {"RVAD", OBSOLETE /* Relative volume adjustment [obsolete] */},
Chris@0 210 #line 65 "compat.gperf"
Chris@0 211 {"CRM", OBSOLETE /* Encrypted meta frame [obsolete] */},
Chris@0 212 #line 128 "compat.gperf"
Chris@0 213 {"WAR", EQ(WOAR) /* Official artist/performer webpage */},
Chris@0 214 #line 80 "compat.gperf"
Chris@0 215 {"SLT", EQ(SYLT) /* Synchronised lyric/text */},
Chris@0 216 #line 81 "compat.gperf"
Chris@0 217 {"STC", EQ(SYTC) /* Synchronised tempo codes */},
Chris@0 218 #line 95 "compat.gperf"
Chris@0 219 {"TKE", EQ(TKEY) /* Initial key */},
Chris@0 220 #line 111 "compat.gperf"
Chris@0 221 {"TRC", EQ(TSRC) /* ISRC (international standard recording code) */},
Chris@0 222 #line 109 "compat.gperf"
Chris@0 223 {"TPA", EQ(TPOS) /* Part of a set */},
Chris@0 224 #line 117 "compat.gperf"
Chris@0 225 {"TSS", EQ(TSSE) /* Software/hardware and settings used for encoding */},
Chris@0 226 #line 112 "compat.gperf"
Chris@0 227 {"TRD", OBSOLETE /* Recording dates [obsolete] */},
Chris@0 228 #line 64 "compat.gperf"
Chris@0 229 {"CRA", EQ(AENC) /* Audio encryption */},
Chris@0 230 #line 108 "compat.gperf"
Chris@0 231 {"TP4", EQ(TPE4) /* Interpreted, remixed, or otherwise modified by */},
Chris@0 232 #line 125 "compat.gperf"
Chris@0 233 {"UFI", EQ(UFID) /* Unique file identifier */},
Chris@0 234 #line 101 "compat.gperf"
Chris@0 235 {"TOL", EQ(TOLY) /* Original lyricist(s)/text writer(s) */},
Chris@0 236 #line 110 "compat.gperf"
Chris@0 237 {"TPB", EQ(TPUB) /* Publisher */},
Chris@0 238 #line 73 "compat.gperf"
Chris@0 239 {"MCI", EQ(MCDI) /* Music CD identifier */},
Chris@0 240 #line 107 "compat.gperf"
Chris@0 241 {"TP3", EQ(TPE3) /* Conductor/performer refinement */},
Chris@0 242 #line 132 "compat.gperf"
Chris@0 243 {"WPB", EQ(WPUB) /* Publishers official webpage */},
Chris@0 244 #line 113 "compat.gperf"
Chris@0 245 {"TRDA", OBSOLETE /* Recording dates [obsolete] */},
Chris@0 246 #line 115 "compat.gperf"
Chris@0 247 {"TSI", OBSOLETE /* Size [obsolete] */},
Chris@0 248 #line 90 "compat.gperf"
Chris@0 249 {"TDY", EQ(TDLY) /* Playlist delay */},
Chris@0 250 #line 82 "compat.gperf"
Chris@0 251 {"TAL", EQ(TALB) /* Album/movie/show title */},
Chris@0 252 #line 116 "compat.gperf"
Chris@0 253 {"TSIZ", OBSOLETE /* Size [obsolete] */},
Chris@0 254 #line 129 "compat.gperf"
Chris@0 255 {"WAS", EQ(WOAS) /* Official audio source webpage */},
Chris@0 256 #line 121 "compat.gperf"
Chris@0 257 {"TXT", EQ(TEXT) /* Lyricist/text writer */},
Chris@0 258 #line 62 "compat.gperf"
Chris@0 259 {"CNT", EQ(PCNT) /* Play counter */},
Chris@0 260 #line 100 "compat.gperf"
Chris@0 261 {"TOF", EQ(TOFN) /* Original filename */},
Chris@0 262 #line 85 "compat.gperf"
Chris@0 263 {"TCO", TX(TCON) /* Content type */},
Chris@0 264 #line 114 "compat.gperf"
Chris@0 265 {"TRK", EQ(TRCK) /* Track number/position in set */},
Chris@0 266 #line 119 "compat.gperf"
Chris@0 267 {"TT2", EQ(TIT2) /* Title/songname/content description */},
Chris@0 268 #line 93 "compat.gperf"
Chris@0 269 {"TIM", OBSOLETE /* Time [obsolete] */},
Chris@0 270 #line 94 "compat.gperf"
Chris@0 271 {"TIME", OBSOLETE /* Time [obsolete] */},
Chris@0 272 #line 103 "compat.gperf"
Chris@0 273 {"TORY", EQ(TDOR) /* Original release year [obsolete] */},
Chris@0 274 #line 91 "compat.gperf"
Chris@0 275 {"TEN", EQ(TENC) /* Encoded by */},
Chris@0 276 #line 118 "compat.gperf"
Chris@0 277 {"TT1", EQ(TIT1) /* Content group description */},
Chris@0 278 #line 127 "compat.gperf"
Chris@0 279 {"WAF", EQ(WOAF) /* Official audio file webpage */},
Chris@0 280 #line 75 "compat.gperf"
Chris@0 281 {"PIC", EQ(APIC) /* Attached picture */},
Chris@0 282 #line 122 "compat.gperf"
Chris@0 283 {"TXX", EQ(TXXX) /* User defined text information frame */},
Chris@0 284 #line 133 "compat.gperf"
Chris@0 285 {"WXX", EQ(WXXX) /* User defined URL link frame */},
Chris@0 286 #line 86 "compat.gperf"
Chris@0 287 {"TCON", TX(TCON) /* Content type */},
Chris@0 288 #line 77 "compat.gperf"
Chris@0 289 {"REV", EQ(RVRB) /* Reverb */},
Chris@0 290 #line 106 "compat.gperf"
Chris@0 291 {"TP2", EQ(TPE2) /* Band/orchestra/accompaniment */},
Chris@0 292 #line 105 "compat.gperf"
Chris@0 293 {"TP1", EQ(TPE1) /* Lead performer(s)/soloist(s) */},
Chris@0 294 #line 61 "compat.gperf"
Chris@0 295 {"BUF", EQ(RBUF) /* Recommended buffer size */},
Chris@0 296 #line 70 "compat.gperf"
Chris@0 297 {"IPL", EQ(TIPL) /* Involved people list */},
Chris@0 298 #line 69 "compat.gperf"
Chris@0 299 {"GEO", EQ(GEOB) /* General encapsulated object */},
Chris@0 300 #line 72 "compat.gperf"
Chris@0 301 {"LNK", EQ(LINK) /* Linked information */},
Chris@0 302 #line 71 "compat.gperf"
Chris@0 303 {"IPLS", EQ(TIPL) /* Involved people list */}
Chris@0 304 };
Chris@0 305
Chris@0 306 static const short lookup[] =
Chris@0 307 {
Chris@0 308 -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7,
Chris@0 309 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, -1,
Chris@0 310 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34,
Chris@0 311 -1, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
Chris@0 312 48, 49, -1, -1, 50, -1, 51, 52, -1, 53, 54, 55, 56, -1,
Chris@0 313 57, 58, 59, 60, -1, 61, -1, 62, -1, -1, 63, -1, 64, -1,
Chris@0 314 -1, 65, -1, 66, -1, -1, -1, -1, -1, 67, -1, 68, -1, 69,
Chris@0 315 -1, 70, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
Chris@0 316 -1, 71, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
Chris@0 317 -1, 72
Chris@0 318 };
Chris@0 319
Chris@0 320 if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH)
Chris@0 321 {
Chris@0 322 register int key = hash (str, len);
Chris@0 323
Chris@0 324 if (key <= MAX_HASH_VALUE && key >= 0)
Chris@0 325 {
Chris@0 326 register int index = lookup[key];
Chris@0 327
Chris@0 328 if (index >= 0)
Chris@0 329 {
Chris@0 330 register const char *s = wordlist[index].id;
Chris@0 331
Chris@0 332 if (*str == *s && !strncmp (str + 1, s + 1, len - 1) && s[len] == '\0')
Chris@0 333 return &wordlist[index];
Chris@0 334 }
Chris@0 335 }
Chris@0 336 }
Chris@0 337 return 0;
Chris@0 338 }
Chris@0 339 #line 134 "compat.gperf"
Chris@0 340
Chris@0 341
Chris@0 342 static
Chris@0 343 int translate_TCON(struct id3_frame *frame, char const *oldid,
Chris@0 344 id3_byte_t const *data, id3_length_t length)
Chris@0 345 {
Chris@0 346 id3_byte_t const *end;
Chris@0 347 enum id3_field_textencoding encoding;
Chris@0 348 id3_ucs4_t *string = 0, *ptr, *endptr;
Chris@0 349 int result = 0;
Chris@0 350
Chris@0 351 /* translate old TCON syntax into multiple strings */
Chris@0 352
Chris@0 353 assert(frame->nfields == 2);
Chris@0 354
Chris@0 355 encoding = ID3_FIELD_TEXTENCODING_ISO_8859_1;
Chris@0 356
Chris@0 357 end = data + length;
Chris@0 358
Chris@0 359 if (id3_field_parse(&frame->fields[0], &data, end - data, &encoding) == -1)
Chris@0 360 goto fail;
Chris@0 361
Chris@0 362 string = id3_parse_string(&data, end - data, encoding, 0);
Chris@0 363 if (string == 0)
Chris@0 364 goto fail;
Chris@0 365
Chris@0 366 ptr = string;
Chris@0 367 while (*ptr == '(') {
Chris@0 368 if (*++ptr == '(')
Chris@0 369 break;
Chris@0 370
Chris@0 371 endptr = ptr;
Chris@0 372 while (*endptr && *endptr != ')')
Chris@0 373 ++endptr;
Chris@0 374
Chris@0 375 if (*endptr)
Chris@0 376 *endptr++ = 0;
Chris@0 377
Chris@0 378 if (id3_field_addstring(&frame->fields[1], ptr) == -1)
Chris@0 379 goto fail;
Chris@0 380
Chris@0 381 ptr = endptr;
Chris@0 382 }
Chris@0 383
Chris@0 384 if (*ptr && id3_field_addstring(&frame->fields[1], ptr) == -1)
Chris@0 385 goto fail;
Chris@0 386
Chris@0 387 if (0) {
Chris@0 388 fail:
Chris@0 389 result = -1;
Chris@0 390 }
Chris@0 391
Chris@0 392 if (string)
Chris@0 393 free(string);
Chris@0 394
Chris@0 395 return result;
Chris@0 396 }
Chris@0 397
Chris@0 398 /*
Chris@0 399 * NAME: compat->fixup()
Chris@0 400 * DESCRIPTION: finish compatibility translations
Chris@0 401 */
Chris@0 402 int id3_compat_fixup(struct id3_tag *tag)
Chris@0 403 {
Chris@0 404 struct id3_frame *frame;
Chris@0 405 unsigned int index;
Chris@0 406 id3_ucs4_t timestamp[17] = { 0 };
Chris@0 407 int result = 0;
Chris@0 408
Chris@0 409 /* create a TDRC frame from obsolete TYER/TDAT/TIME frames */
Chris@0 410
Chris@0 411 /*
Chris@0 412 * TYE/TYER: YYYY
Chris@0 413 * TDA/TDAT: DDMM
Chris@0 414 * TIM/TIME: HHMM
Chris@0 415 *
Chris@0 416 * TDRC: yyyy-MM-ddTHH:mm
Chris@0 417 */
Chris@0 418
Chris@0 419 index = 0;
Chris@0 420 while ((frame = id3_tag_findframe(tag, ID3_FRAME_OBSOLETE, index++))) {
Chris@0 421 char const *id;
Chris@0 422 id3_byte_t const *data, *end;
Chris@0 423 id3_length_t length;
Chris@0 424 enum id3_field_textencoding encoding;
Chris@0 425 id3_ucs4_t *string;
Chris@0 426
Chris@0 427 id = id3_field_getframeid(&frame->fields[0]);
Chris@0 428 assert(id);
Chris@0 429
Chris@0 430 if (strcmp(id, "TYER") != 0 && strcmp(id, "YTYE") != 0 &&
Chris@0 431 strcmp(id, "TDAT") != 0 && strcmp(id, "YTDA") != 0 &&
Chris@0 432 strcmp(id, "TIME") != 0 && strcmp(id, "YTIM") != 0)
Chris@0 433 continue;
Chris@0 434
Chris@0 435 data = id3_field_getbinarydata(&frame->fields[1], &length);
Chris@0 436 assert(data);
Chris@0 437
Chris@0 438 if (length < 1)
Chris@0 439 continue;
Chris@0 440
Chris@0 441 end = data + length;
Chris@0 442
Chris@0 443 encoding = id3_parse_uint(&data, 1);
Chris@0 444 string = id3_parse_string(&data, end - data, encoding, 0);
Chris@0 445
Chris@0 446 if (id3_ucs4_length(string) < 4) {
Chris@0 447 free(string);
Chris@0 448 continue;
Chris@0 449 }
Chris@0 450
Chris@0 451 if (strcmp(id, "TYER") == 0 ||
Chris@0 452 strcmp(id, "YTYE") == 0) {
Chris@0 453 timestamp[0] = string[0];
Chris@0 454 timestamp[1] = string[1];
Chris@0 455 timestamp[2] = string[2];
Chris@0 456 timestamp[3] = string[3];
Chris@0 457 }
Chris@0 458 else if (strcmp(id, "TDAT") == 0 ||
Chris@0 459 strcmp(id, "YTDA") == 0) {
Chris@0 460 timestamp[4] = '-';
Chris@0 461 timestamp[5] = string[2];
Chris@0 462 timestamp[6] = string[3];
Chris@0 463 timestamp[7] = '-';
Chris@0 464 timestamp[8] = string[0];
Chris@0 465 timestamp[9] = string[1];
Chris@0 466 }
Chris@0 467 else { /* TIME or YTIM */
Chris@0 468 timestamp[10] = 'T';
Chris@0 469 timestamp[11] = string[0];
Chris@0 470 timestamp[12] = string[1];
Chris@0 471 timestamp[13] = ':';
Chris@0 472 timestamp[14] = string[2];
Chris@0 473 timestamp[15] = string[3];
Chris@0 474 }
Chris@0 475
Chris@0 476 free(string);
Chris@0 477 }
Chris@0 478
Chris@0 479 if (timestamp[0]) {
Chris@0 480 id3_ucs4_t *strings;
Chris@0 481
Chris@0 482 frame = id3_frame_new("TDRC");
Chris@0 483 if (frame == 0)
Chris@0 484 goto fail;
Chris@0 485
Chris@0 486 strings = timestamp;
Chris@0 487
Chris@0 488 if (id3_field_settextencoding(&frame->fields[0],
Chris@0 489 ID3_FIELD_TEXTENCODING_ISO_8859_1) == -1 ||
Chris@0 490 id3_field_setstrings(&frame->fields[1], 1, &strings) == -1 ||
Chris@0 491 id3_tag_attachframe(tag, frame) == -1) {
Chris@0 492 id3_frame_delete(frame);
Chris@0 493 goto fail;
Chris@0 494 }
Chris@0 495 }
Chris@0 496
Chris@0 497 if (0) {
Chris@0 498 fail:
Chris@0 499 result = -1;
Chris@0 500 }
Chris@0 501
Chris@0 502 return result;
Chris@0 503 }