1 /* Conversion from UTF-16 to legacy encodings.
2 Copyright (C) 2002, 2006-2010 Free Software Foundation, Inc.
4 This program is free software: you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as published
6 by the Free Software Foundation; either version 3 of the License, or
7 (at your option) any later version.
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
14 You should have received a copy of the GNU Lesser General Public License
15 along with this program. If not, see <http://www.gnu.org/licenses/>. */
17 /* Written by Bruno Haible <bruno@clisp.org>. */
28 #include "striconveha.h"
31 #define SIZEOF(array) (sizeof (array) / sizeof (array[0]))
33 /* Name of UTF-16 encoding with machine dependent endianness and alignment. */
34 #if defined _LIBICONV_VERSION || (__GLIBC__ > 2) || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2)
35 # ifdef WORDS_BIGENDIAN
36 # define UTF16_NAME "UTF-16BE"
38 # define UTF16_NAME "UTF-16LE"
43 #if !defined UTF16_NAME
45 /* A variant of u16_to_u8 that treats an incomplete sequence of units at the
46 end as a harmless no-op, rather than reporting it as an EILSEQ error. */
48 #define FUNC u16_to_u8_lenient
49 #define SRC_UNIT uint16_t
50 #define DST_UNIT uint8_t
53 FUNC (const SRC_UNIT *s, size_t n, DST_UNIT *resultbuf, size_t *lengthp)
55 const SRC_UNIT *s_end = s + n;
56 /* Output string accumulator. */
61 if (resultbuf != NULL)
73 result is either == resultbuf or == NULL or malloc-allocated.
74 If length > 0, then result != NULL. */
81 /* Fetch a Unicode character from the input string. */
82 count = u16_mbtoucr (&uc, s, s_end - s);
86 /* Incomplete sequence of units. */
88 if (!(result == resultbuf || result == NULL))
95 /* Store it in the output string. */
96 count = u8_uctomb (result + length, uc, allocated - length);
99 if (!(result == resultbuf || result == NULL))
108 allocated = (allocated > 0 ? 2 * allocated : 12);
109 if (length + 6 > allocated)
110 allocated = length + 6;
111 if (result == resultbuf || result == NULL)
112 memory = (DST_UNIT *) malloc (allocated * sizeof (DST_UNIT));
115 (DST_UNIT *) realloc (result, allocated * sizeof (DST_UNIT));
119 if (!(result == resultbuf || result == NULL))
124 if (result == resultbuf && length > 0)
125 memcpy ((char *) memory, (char *) result,
126 length * sizeof (DST_UNIT));
128 count = u8_uctomb (result + length, uc, allocated - length);
139 /* Return a non-NULL value. NULL means error. */
140 result = (DST_UNIT *) malloc (1);
148 else if (result != resultbuf && length < allocated)
150 /* Shrink the allocated memory if possible. */
153 memory = (DST_UNIT *) realloc (result, length * sizeof (DST_UNIT));
169 #define FUNC u16_conv_to_encoding
170 #define UNIT uint16_t
171 #define U_TO_U8 u16_to_u8_lenient
172 #define U_MBLEN u16_mblen
173 #if defined UTF16_NAME
174 # define UTF_NAME UTF16_NAME
175 # define HAVE_UTF_NAME 1
177 #include "u-conv-to-enc.h"