Chris@0: /* Chris@0: * libid3tag - ID3 tag manipulation library Chris@0: * Copyright (C) 2000-2004 Underbit Technologies, Inc. Chris@0: * Chris@0: * This program is free software; you can redistribute it and/or modify Chris@0: * it under the terms of the GNU General Public License as published by Chris@0: * the Free Software Foundation; either version 2 of the License, or Chris@0: * (at your option) any later version. Chris@0: * Chris@0: * This program is distributed in the hope that it will be useful, Chris@0: * but WITHOUT ANY WARRANTY; without even the implied warranty of Chris@0: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the Chris@0: * GNU General Public License for more details. Chris@0: * Chris@0: * You should have received a copy of the GNU General Public License Chris@0: * along with this program; if not, write to the Free Software Chris@0: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Chris@0: * Chris@0: * $Id: ucs4.c,v 1.13 2004/01/23 09:41:32 rob Exp $ Chris@0: */ Chris@0: Chris@0: # ifdef HAVE_CONFIG_H Chris@0: # include "config.h" Chris@0: # endif Chris@0: Chris@0: # include "global.h" Chris@0: Chris@0: # include Chris@0: Chris@0: # include "id3tag.h" Chris@0: # include "ucs4.h" Chris@0: # include "latin1.h" Chris@0: # include "utf16.h" Chris@0: # include "utf8.h" Chris@0: Chris@0: id3_ucs4_t const id3_ucs4_empty[] = { 0 }; Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->length() Chris@0: * DESCRIPTION: return the number of ucs4 chars represented by a ucs4 string Chris@0: */ Chris@0: id3_length_t id3_ucs4_length(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: id3_ucs4_t const *ptr = ucs4; Chris@0: Chris@0: while (*ptr) Chris@0: ++ptr; Chris@0: Chris@0: return ptr - ucs4; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->size() Chris@0: * DESCRIPTION: return the encoding size of a ucs4 string Chris@0: */ Chris@0: id3_length_t id3_ucs4_size(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: return id3_ucs4_length(ucs4) + 1; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->latin1size() Chris@0: * DESCRIPTION: return the encoding size of a latin1-encoded ucs4 string Chris@0: */ Chris@0: id3_length_t id3_ucs4_latin1size(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: return id3_ucs4_size(ucs4); Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->utf16size() Chris@0: * DESCRIPTION: return the encoding size of a utf16-encoded ucs4 string Chris@0: */ Chris@0: id3_length_t id3_ucs4_utf16size(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: id3_length_t size = 0; Chris@0: Chris@0: while (*ucs4) { Chris@0: ++size; Chris@0: if (*ucs4 >= 0x00010000L && Chris@0: *ucs4 <= 0x0010ffffL) Chris@0: ++size; Chris@0: Chris@0: ++ucs4; Chris@0: } Chris@0: Chris@0: return size + 1; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->utf8size() Chris@0: * DESCRIPTION: return the encoding size of a utf8-encoded ucs4 string Chris@0: */ Chris@0: id3_length_t id3_ucs4_utf8size(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: id3_length_t size = 0; Chris@0: Chris@0: while (*ucs4) { Chris@0: if (*ucs4 <= 0x0000007fL) Chris@0: size += 1; Chris@0: else if (*ucs4 <= 0x000007ffL) Chris@0: size += 2; Chris@0: else if (*ucs4 <= 0x0000ffffL) Chris@0: size += 3; Chris@0: else if (*ucs4 <= 0x001fffffL) Chris@0: size += 4; Chris@0: else if (*ucs4 <= 0x03ffffffL) Chris@0: size += 5; Chris@0: else if (*ucs4 <= 0x7fffffffL) Chris@0: size += 6; Chris@0: else Chris@0: size += 2; /* based on U+00B7 replacement char */ Chris@0: Chris@0: ++ucs4; Chris@0: } Chris@0: Chris@0: return size + 1; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->latin1duplicate() Chris@0: * DESCRIPTION: duplicate and encode a ucs4 string into latin1 Chris@0: */ Chris@0: id3_latin1_t *id3_ucs4_latin1duplicate(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: id3_latin1_t *latin1; Chris@0: Chris@0: latin1 = malloc(id3_ucs4_latin1size(ucs4) * sizeof(*latin1)); Chris@0: if (latin1) Chris@0: id3_latin1_encode(latin1, ucs4); Chris@0: Chris@0: return release(latin1); Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->utf16duplicate() Chris@0: * DESCRIPTION: duplicate and encode a ucs4 string into utf16 Chris@0: */ Chris@0: id3_utf16_t *id3_ucs4_utf16duplicate(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: id3_utf16_t *utf16; Chris@0: Chris@0: utf16 = malloc(id3_ucs4_utf16size(ucs4) * sizeof(*utf16)); Chris@0: if (utf16) Chris@0: id3_utf16_encode(utf16, ucs4); Chris@0: Chris@0: return release(utf16); Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->utf8duplicate() Chris@0: * DESCRIPTION: duplicate and encode a ucs4 string into utf8 Chris@0: */ Chris@0: id3_utf8_t *id3_ucs4_utf8duplicate(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: id3_utf8_t *utf8; Chris@0: Chris@0: utf8 = malloc(id3_ucs4_utf8size(ucs4) * sizeof(*utf8)); Chris@0: if (utf8) Chris@0: id3_utf8_encode(utf8, ucs4); Chris@0: Chris@0: return release(utf8); Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->copy() Chris@0: * DESCRIPTION: copy a ucs4 string Chris@0: */ Chris@0: void id3_ucs4_copy(id3_ucs4_t *dest, id3_ucs4_t const *src) Chris@0: { Chris@0: while ((*dest++ = *src++)) Chris@0: ; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->duplicate() Chris@0: * DESCRIPTION: duplicate a ucs4 string Chris@0: */ Chris@0: id3_ucs4_t *id3_ucs4_duplicate(id3_ucs4_t const *src) Chris@0: { Chris@0: id3_ucs4_t *ucs4; Chris@0: Chris@0: ucs4 = malloc(id3_ucs4_size(src) * sizeof(*ucs4)); Chris@0: if (ucs4) Chris@0: id3_ucs4_copy(ucs4, src); Chris@0: Chris@0: return ucs4; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->putnumber() Chris@0: * DESCRIPTION: write a ucs4 string containing a (positive) decimal number Chris@0: */ Chris@0: void id3_ucs4_putnumber(id3_ucs4_t *ucs4, unsigned long number) Chris@0: { Chris@0: int digits[10], *digit; Chris@0: Chris@0: digit = digits; Chris@0: Chris@0: do { Chris@0: *digit++ = number % 10; Chris@0: number /= 10; Chris@0: } Chris@0: while (number); Chris@0: Chris@0: while (digit != digits) Chris@0: *ucs4++ = '0' + *--digit; Chris@0: Chris@0: *ucs4 = 0; Chris@0: } Chris@0: Chris@0: /* Chris@0: * NAME: ucs4->getnumber() Chris@0: * DESCRIPTION: read a ucs4 string containing a (positive) decimal number Chris@0: */ Chris@0: unsigned long id3_ucs4_getnumber(id3_ucs4_t const *ucs4) Chris@0: { Chris@0: unsigned long number = 0; Chris@0: Chris@0: while (*ucs4 >= '0' && *ucs4 <= '9') Chris@0: number = 10 * number + (*ucs4++ - '0'); Chris@0: Chris@0: return number; Chris@0: }