/* Character set conversion with error handling.
- Copyright (C) 2001-2007 Free Software Foundation, Inc.
+ Copyright (C) 2001-2008 Free Software Foundation, Inc.
Written by Bruno Haible and Simon Josefsson.
- This program is free software; you can redistribute it and/or modify
+ 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, or (at your option)
- any later version.
+ the Free Software Foundation; either version 3 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
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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+ along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
&outptr, &outsize);
if (!(res == (size_t)(-1) && errno == EINVAL))
break;
- /* We expect that no input bytes have been consumed so far. */
- if (inptr != inptr_before)
- abort ();
+ /* iconv can eat up a shift sequence but give EINVAL while attempting
+ to convert the first character. E.g. libiconv does this. */
+ if (inptr > inptr_before)
+ {
+ res = 0;
+ break;
+ }
}
if (res == 0)
# endif
/* iconv_carefully_1 is like iconv_carefully, except that it stops after
- converting one character. */
+ converting one character or one shift sequence. */
static size_t
iconv_carefully_1 (iconv_t cd,
const char **inbuf, size_t *inbytesleft,
char **outbuf, size_t *outbytesleft,
bool *incremented)
{
- const char *inptr = *inbuf;
- const char *inptr_end = inptr + *inbytesleft;
+ const char *inptr_before = *inbuf;
+ const char *inptr = inptr_before;
+ const char *inptr_end = inptr_before + *inbytesleft;
char *outptr = *outbuf;
size_t outsize = *outbytesleft;
- const char *inptr_before = inptr;
size_t res = (size_t)(-1);
size_t insize;
- for (insize = 1; inptr + insize <= inptr_end; insize++)
+ for (insize = 1; inptr_before + insize <= inptr_end; insize++)
{
+ inptr = inptr_before;
res = iconv (cd,
(ICONV_CONST char **) &inptr, &insize,
&outptr, &outsize);
if (!(res == (size_t)(-1) && errno == EINVAL))
break;
- /* We expect that no input bytes have been consumed so far. */
- if (inptr != inptr_before)
- abort ();
+ /* iconv can eat up a shift sequence but give EINVAL while attempting
+ to convert the first character. E.g. libiconv does this. */
+ if (inptr > inptr_before)
+ {
+ res = 0;
+ break;
+ }
}
*inbuf = inptr;
/* Now the final memory allocation. */
if (result == tmpbuf)
{
+ size_t memsize = length + extra_alloc;
char *memory;
- memory = (char *) malloc (length + extra_alloc);
+ memory = (char *) malloc (memsize > 0 ? memsize : 1);
if (memory != NULL)
{
memcpy (memory, tmpbuf, length);
else if (result != *resultp && length + extra_alloc < allocated)
{
/* Shrink the allocated memory if possible. */
+ size_t memsize = length + extra_alloc;
char *memory;
- memory = (char *) realloc (result, length + extra_alloc);
+ memory = (char *) realloc (result, memsize > 0 ? memsize : 1);
if (memory != NULL)
result = memory;
}
}
}
- if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
+ if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || _LIBICONV_VERSION >= 0x0105
+ || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0
+# endif
+ )
cd2 = (iconv_t)(-1);
else
{
}
}
- if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0))
+ if (STRCASEEQ (to_codeset, "UTF-8", 'U','T','F','-','8',0,0,0,0)
+# if (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 2) || __GLIBC__ > 2 || _LIBICONV_VERSION >= 0x0105
+ || c_strcasecmp (to_codeset, "UTF-8//TRANSLIT") == 0
+# endif
+ )
cd2 = (iconv_t)(-1);
else
{