1 /* -*- buffer-read-only: t -*- vi: set ro: */
2 /* DO NOT EDIT! GENERATED AUTOMATICALLY! */
4 Copyright (C) 2001-2007, 2010-2011 Free Software Foundation, Inc.
5 Written by Bruno Haible and Simon Josefsson.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software Foundation,
19 Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
32 /* Get MB_LEN_MAX, CHAR_BIT. */
36 #include "c-strcase.h"
39 # define SIZE_MAX ((size_t) -1)
46 mem_cd_iconv (const char *src, size_t srclen, iconv_t cd,
47 char **resultp, size_t *lengthp)
49 # define tmpbufsize 4096
53 /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */
54 # if defined _LIBICONV_VERSION \
55 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
57 /* Set to the initial state. */
58 iconv (cd, NULL, NULL, NULL, NULL);
61 /* Determine the length we need. */
64 /* The alignment is needed when converting e.g. to glibc's WCHAR_T or
65 libiconv's UCS-4-INTERNAL encoding. */
66 union { unsigned int align; char buf[tmpbufsize]; } tmp;
67 # define tmpbuf tmp.buf
68 const char *inptr = src;
69 size_t insize = srclen;
73 char *outptr = tmpbuf;
74 size_t outsize = tmpbufsize;
75 size_t res = iconv (cd,
76 (ICONV_CONST char **) &inptr, &insize,
79 if (res == (size_t)(-1))
83 else if (errno == EINVAL)
88 # if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)
89 /* Irix iconv() inserts a NUL byte if it cannot convert.
90 NetBSD iconv() inserts a question mark if it cannot convert.
91 Only GNU libiconv and GNU libc are known to prefer to fail rather
92 than doing a lossy conversion. */
99 count += outptr - tmpbuf;
101 /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */
102 # if defined _LIBICONV_VERSION \
103 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
106 char *outptr = tmpbuf;
107 size_t outsize = tmpbufsize;
108 size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);
110 if (res == (size_t)(-1))
112 count += outptr - tmpbuf;
124 if (*resultp != NULL && *lengthp >= length)
128 result = (char *) malloc (length);
136 /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */
137 # if defined _LIBICONV_VERSION \
138 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
140 /* Return to the initial state. */
141 iconv (cd, NULL, NULL, NULL, NULL);
144 /* Do the conversion for real. */
146 const char *inptr = src;
147 size_t insize = srclen;
148 char *outptr = result;
149 size_t outsize = length;
153 size_t res = iconv (cd,
154 (ICONV_CONST char **) &inptr, &insize,
157 if (res == (size_t)(-1))
164 # if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)
165 /* Irix iconv() inserts a NUL byte if it cannot convert.
166 NetBSD iconv() inserts a question mark if it cannot convert.
167 Only GNU libiconv and GNU libc are known to prefer to fail rather
168 than doing a lossy conversion. */
176 /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */
177 # if defined _LIBICONV_VERSION \
178 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
181 size_t res = iconv (cd, NULL, NULL, &outptr, &outsize);
183 if (res == (size_t)(-1))
198 if (result != *resultp)
200 int saved_errno = errno;
210 str_cd_iconv (const char *src, iconv_t cd)
212 /* For most encodings, a trailing NUL byte in the input will be converted
213 to a trailing NUL byte in the output. But not for UTF-7. So that this
214 function is usable for UTF-7, we have to exclude the NUL byte from the
215 conversion and add it by hand afterwards. */
216 # if !defined _LIBICONV_VERSION && !(defined __GLIBC__ && !defined __UCLIBC__)
217 /* Irix iconv() inserts a NUL byte if it cannot convert.
218 NetBSD iconv() inserts a question mark if it cannot convert.
219 Only GNU libiconv and GNU libc are known to prefer to fail rather
220 than doing a lossy conversion. For other iconv() implementations,
221 we have to look at the number of irreversible conversions returned;
222 but this information is lost when iconv() returns for an E2BIG reason.
223 Therefore we cannot use the second, faster algorithm. */
227 int retval = mem_cd_iconv (src, strlen (src), cd, &result, &length);
237 /* Add the terminating NUL byte. */
239 (result != NULL ? realloc (result, length + 1) : malloc (length + 1));
240 if (final_result == NULL)
246 final_result[length] = '\0';
251 /* This algorithm is likely faster than the one above. But it may produce
252 iconv() returns for an E2BIG reason, when the output size guess is too
253 small. Therefore it can only be used when we don't need the number of
254 irreversible conversions performed. */
258 const char *inptr = src;
259 size_t inbytes_remaining = strlen (src);
261 /* Make a guess for the worst-case output size, in order to avoid a
262 realloc. It's OK if the guess is wrong as long as it is not zero and
263 doesn't lead to an integer overflow. */
264 result_size = inbytes_remaining;
266 size_t approx_sqrt_SIZE_MAX = SIZE_MAX >> (sizeof (size_t) * CHAR_BIT / 2);
267 if (result_size <= approx_sqrt_SIZE_MAX / MB_LEN_MAX)
268 result_size *= MB_LEN_MAX;
270 result_size += 1; /* for the terminating NUL */
272 result = (char *) malloc (result_size);
279 /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */
280 # if defined _LIBICONV_VERSION \
281 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
283 /* Set to the initial state. */
284 iconv (cd, NULL, NULL, NULL, NULL);
287 /* Do the conversion. */
289 char *outptr = result;
290 size_t outbytes_remaining = result_size - 1;
294 /* Here inptr + inbytes_remaining = src + strlen (src),
295 outptr + outbytes_remaining = result + result_size - 1. */
296 size_t res = iconv (cd,
297 (ICONV_CONST char **) &inptr, &inbytes_remaining,
298 &outptr, &outbytes_remaining);
300 if (res == (size_t)(-1))
304 else if (errno == E2BIG)
306 size_t used = outptr - result;
307 size_t newsize = result_size * 2;
310 if (!(newsize > result_size))
315 newresult = (char *) realloc (result, newsize);
316 if (newresult == NULL)
322 result_size = newsize;
323 outptr = result + used;
324 outbytes_remaining = result_size - 1 - used;
332 /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */
333 # if defined _LIBICONV_VERSION \
334 || !(((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
338 /* Here outptr + outbytes_remaining = result + result_size - 1. */
339 size_t res = iconv (cd, NULL, NULL, &outptr, &outbytes_remaining);
341 if (res == (size_t)(-1))
345 size_t used = outptr - result;
346 size_t newsize = result_size * 2;
349 if (!(newsize > result_size))
354 newresult = (char *) realloc (result, newsize);
355 if (newresult == NULL)
361 result_size = newsize;
362 outptr = result + used;
363 outbytes_remaining = result_size - 1 - used;
373 /* Add the terminating NUL byte. */
376 length = outptr - result;
379 /* Give away unused memory. */
380 if (length < result_size)
382 char *smaller_result = (char *) realloc (result, length);
384 if (smaller_result != NULL)
385 result = smaller_result;
392 int saved_errno = errno;
404 str_iconv (const char *src, const char *from_codeset, const char *to_codeset)
406 if (*src == '\0' || c_strcasecmp (from_codeset, to_codeset) == 0)
408 char *result = strdup (src);
420 /* Avoid glibc-2.1 bug with EUC-KR. */
421 # if ((__GLIBC__ == 2 && __GLIBC_MINOR__ <= 1) && !defined __UCLIBC__) \
422 && !defined _LIBICONV_VERSION
423 if (c_strcasecmp (from_codeset, "EUC-KR") == 0
424 || c_strcasecmp (to_codeset, "EUC-KR") == 0)
430 cd = iconv_open (to_codeset, from_codeset);
431 if (cd == (iconv_t) -1)
434 result = str_cd_iconv (src, cd);
438 /* Close cd, but preserve the errno from str_cd_iconv. */
439 int saved_errno = errno;
445 if (iconv_close (cd) < 0)
447 /* Return NULL, but free the allocated memory, and while doing
448 that, preserve the errno from iconv_close. */
449 int saved_errno = errno;
457 /* This is a different error code than if iconv_open existed but didn't
458 support from_codeset and to_codeset, so that the caller can emit
459 an error message such as
460 "iconv() is not supported. Installing GNU libiconv and
461 then reinstalling this package would fix this." */