📄 field.c
字号:
/*
* libid3tag - ID3 tag manipulation library
* Copyright (C) 2000-2004 Underbit Technologies, Inc.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
* $Id: field.c,v 1.1 2004/05/17 19:25:37 lcanis Exp $
*/
#pragma warning( disable : 4146 )
# ifdef HAVE_CONFIG_H
# include "config.h"
# endif
# include "global.h"
# include <stdlib.h>
# include <string.h>
# ifdef HAVE_ASSERT_H
# include <assert.h>
# endif
# include "id3tag.h"
# include "field.h"
# include "frame.h"
# include "render.h"
# include "ucs4.h"
# include "latin1.h"
# include "parse.h"
/*
* NAME: field->init()
* DESCRIPTION: initialize a field to a default value for the given type
*/
void id3_field_init(union id3_field *field, enum id3_field_type type)
{
assert(field);
switch (field->type = type) {
case ID3_FIELD_TYPE_TEXTENCODING:
case ID3_FIELD_TYPE_INT8:
case ID3_FIELD_TYPE_INT16:
case ID3_FIELD_TYPE_INT24:
case ID3_FIELD_TYPE_INT32:
field->number.value = 0;
break;
case ID3_FIELD_TYPE_LATIN1:
case ID3_FIELD_TYPE_LATIN1FULL:
field->latin1.ptr = 0;
break;
case ID3_FIELD_TYPE_LATIN1LIST:
field->latin1list.nstrings = 0;
field->latin1list.strings = 0;
case ID3_FIELD_TYPE_STRING:
case ID3_FIELD_TYPE_STRINGFULL:
field->string.ptr = 0;
break;
case ID3_FIELD_TYPE_STRINGLIST:
field->stringlist.nstrings = 0;
field->stringlist.strings = 0;
break;
case ID3_FIELD_TYPE_LANGUAGE:
strcpy(field->immediate.value, "XXX");
break;
case ID3_FIELD_TYPE_FRAMEID:
strcpy(field->immediate.value, "XXXX");
break;
case ID3_FIELD_TYPE_DATE:
memset(field->immediate.value, 0, sizeof(field->immediate.value));
break;
case ID3_FIELD_TYPE_INT32PLUS:
case ID3_FIELD_TYPE_BINARYDATA:
field->binary.data = 0;
field->binary.length = 0;
break;
}
}
/*
* NAME: field->finish()
* DESCRIPTION: reset a field, deallocating memory if necessary
*/
void id3_field_finish(union id3_field *field)
{
unsigned int i;
assert(field);
switch (field->type) {
case ID3_FIELD_TYPE_TEXTENCODING:
case ID3_FIELD_TYPE_INT8:
case ID3_FIELD_TYPE_INT16:
case ID3_FIELD_TYPE_INT24:
case ID3_FIELD_TYPE_INT32:
case ID3_FIELD_TYPE_LANGUAGE:
case ID3_FIELD_TYPE_FRAMEID:
case ID3_FIELD_TYPE_DATE:
break;
case ID3_FIELD_TYPE_LATIN1:
case ID3_FIELD_TYPE_LATIN1FULL:
if (field->latin1.ptr)
free(field->latin1.ptr);
break;
case ID3_FIELD_TYPE_LATIN1LIST:
for (i = 0; i < field->latin1list.nstrings; ++i)
free(field->latin1list.strings[i]);
if (field->latin1list.strings)
free(field->latin1list.strings);
break;
case ID3_FIELD_TYPE_STRING:
case ID3_FIELD_TYPE_STRINGFULL:
if (field->string.ptr)
free(field->string.ptr);
break;
case ID3_FIELD_TYPE_STRINGLIST:
for (i = 0; i < field->stringlist.nstrings; ++i)
free(field->stringlist.strings[i]);
if (field->stringlist.strings)
free(field->stringlist.strings);
break;
case ID3_FIELD_TYPE_INT32PLUS:
case ID3_FIELD_TYPE_BINARYDATA:
if (field->binary.data)
free(field->binary.data);
break;
}
id3_field_init(field, field->type);
}
/*
* NAME: field->type()
* DESCRIPTION: return the value type of a field
*/
enum id3_field_type id3_field_type(union id3_field const *field)
{
assert(field);
return field->type;
}
/*
* NAME: field->parse()
* DESCRIPTION: parse a field value
*/
int id3_field_parse(union id3_field *field, id3_byte_t const **ptr,
id3_length_t length, enum id3_field_textencoding *encoding)
{
assert(field);
id3_field_finish(field);
switch (field->type) {
case ID3_FIELD_TYPE_INT32:
if (length < 4)
goto fail;
field->number.value = id3_parse_uint(ptr, 4);
break;
case ID3_FIELD_TYPE_INT24:
if (length < 3)
goto fail;
field->number.value = id3_parse_uint(ptr, 3);
break;
case ID3_FIELD_TYPE_INT16:
if (length < 2)
goto fail;
field->number.value = id3_parse_uint(ptr, 2);
break;
case ID3_FIELD_TYPE_INT8:
case ID3_FIELD_TYPE_TEXTENCODING:
if (length < 1)
goto fail;
field->number.value = id3_parse_uint(ptr, 1);
if (field->type == ID3_FIELD_TYPE_TEXTENCODING)
*encoding = field->number.value;
break;
case ID3_FIELD_TYPE_LANGUAGE:
if (length < 3)
goto fail;
id3_parse_immediate(ptr, 3, field->immediate.value);
break;
case ID3_FIELD_TYPE_FRAMEID:
if (length < 4)
goto fail;
id3_parse_immediate(ptr, 4, field->immediate.value);
break;
case ID3_FIELD_TYPE_DATE:
if (length < 8)
goto fail;
id3_parse_immediate(ptr, 8, field->immediate.value);
break;
case ID3_FIELD_TYPE_LATIN1:
case ID3_FIELD_TYPE_LATIN1FULL:
{
id3_latin1_t *latin1;
latin1 = id3_parse_latin1(ptr, length,
field->type == ID3_FIELD_TYPE_LATIN1FULL);
if (latin1 == 0)
goto fail;
field->latin1.ptr = latin1;
}
break;
case ID3_FIELD_TYPE_LATIN1LIST:
{
id3_byte_t const *end;
id3_latin1_t *latin1, **strings;
end = *ptr + length;
while (end - *ptr > 0) {
latin1 = id3_parse_latin1(ptr, end - *ptr, 0);
if (latin1 == 0)
goto fail;
strings = realloc(field->latin1list.strings,
(field->latin1list.nstrings + 1) * sizeof(*strings));
if (strings == 0) {
free(latin1);
goto fail;
}
field->latin1list.strings = strings;
field->latin1list.strings[field->latin1list.nstrings++] = latin1;
}
}
break;
case ID3_FIELD_TYPE_STRING:
case ID3_FIELD_TYPE_STRINGFULL:
{
id3_ucs4_t *ucs4;
ucs4 = id3_parse_string(ptr, length, *encoding,
field->type == ID3_FIELD_TYPE_STRINGFULL);
if (ucs4 == 0)
goto fail;
field->string.ptr = ucs4;
}
break;
case ID3_FIELD_TYPE_STRINGLIST:
{
id3_byte_t const *end;
id3_ucs4_t *ucs4, **strings;
end = *ptr + length;
while (end - *ptr > 0) {
ucs4 = id3_parse_string(ptr, end - *ptr, *encoding, 0);
if (ucs4 == 0)
goto fail;
strings = realloc(field->stringlist.strings,
(field->stringlist.nstrings + 1) * sizeof(*strings));
if (strings == 0) {
free(ucs4);
goto fail;
}
field->stringlist.strings = strings;
field->stringlist.strings[field->stringlist.nstrings++] = ucs4;
}
}
break;
case ID3_FIELD_TYPE_INT32PLUS:
case ID3_FIELD_TYPE_BINARYDATA:
{
id3_byte_t *data;
data = id3_parse_binary(ptr, length);
if (data == 0)
goto fail;
field->binary.data = data;
field->binary.length = length;
}
break;
}
return 0;
fail:
return -1;
}
/*
* NAME: field->render()
* DESCRIPTION: render a field value
*/
id3_length_t id3_field_render(union id3_field const *field, id3_byte_t **ptr,
enum id3_field_textencoding *encoding,
int terminate)
{
id3_length_t size;
unsigned int i;
assert(field && encoding);
switch (field->type) {
case ID3_FIELD_TYPE_INT32:
return id3_render_int(ptr, field->number.value, 4);
case ID3_FIELD_TYPE_INT24:
return id3_render_int(ptr, field->number.value, 3);
case ID3_FIELD_TYPE_INT16:
return id3_render_int(ptr, field->number.value, 2);
case ID3_FIELD_TYPE_TEXTENCODING:
*encoding = field->number.value;
case ID3_FIELD_TYPE_INT8:
return id3_render_int(ptr, field->number.value, 1);
case ID3_FIELD_TYPE_LATIN1:
case ID3_FIELD_TYPE_LATIN1FULL:
return id3_render_latin1(ptr, field->latin1.ptr, terminate);
case ID3_FIELD_TYPE_LATIN1LIST:
size = 0;
for (i = 0; i < field->latin1list.nstrings; ++i) {
size += id3_render_latin1(ptr, field->latin1list.strings[i],
(i < field->latin1list.nstrings - 1) ||
terminate);
}
return size;
case ID3_FIELD_TYPE_STRING:
case ID3_FIELD_TYPE_STRINGFULL:
return id3_render_string(ptr, field->string.ptr, *encoding, terminate);
case ID3_FIELD_TYPE_STRINGLIST:
size = 0;
for (i = 0; i < field->stringlist.nstrings; ++i) {
size += id3_render_string(ptr, field->stringlist.strings[i], *encoding,
(i < field->stringlist.nstrings - 1) ||
terminate);
}
return size;
case ID3_FIELD_TYPE_LANGUAGE:
return id3_render_immediate(ptr, field->immediate.value, 3);
case ID3_FIELD_TYPE_FRAMEID:
return id3_render_immediate(ptr, field->immediate.value, 4);
case ID3_FIELD_TYPE_DATE:
return id3_render_immediate(ptr, field->immediate.value, 8);
case ID3_FIELD_TYPE_INT32PLUS:
case ID3_FIELD_TYPE_BINARYDATA:
return id3_render_binary(ptr, field->binary.data, field->binary.length);
}
return 0;
}
/*
* NAME: field->setint()
* DESCRIPTION: set the value of an int field
*/
int id3_field_setint(union id3_field *field, signed long number)
{
assert(field);
switch (field->type) {
case ID3_FIELD_TYPE_INT8:
if (number > 0x7f || number < -0x80)
return -1;
break;
case ID3_FIELD_TYPE_INT16:
if (number > 0x7fff || number < -0x8000)
return -1;
break;
case ID3_FIELD_TYPE_INT24:
if (number > 0x7fffffL || number < -0x800000L)
return -1;
break;
case ID3_FIELD_TYPE_INT32:
if (number > 0x7fffffffL || number < -0x80000000L)
return -1;
break;
default:
return -1;
}
id3_field_finish(field);
field->number.value = number;
return 0;
}
/*
* NAME: field->settextencoding()
* DESCRIPTION: set the value of a textencoding field
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -