From: Bruno Haible Date: Wed, 29 Mar 2006 11:25:13 +0000 (+0000) Subject: Charset conversion module. X-Git-Tag: v0.15~273 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=50a128218db86eab04185e4416d48ec8141f32e8;p=thirdparty%2Fgettext.git Charset conversion module. --- diff --git a/gettext-tools/lib/iconvstring.c b/gettext-tools/lib/iconvstring.c new file mode 100644 index 000000000..cd0d9af63 --- /dev/null +++ b/gettext-tools/lib/iconvstring.c @@ -0,0 +1,158 @@ +/* Charset conversion. + Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + 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. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +/* Specification. */ +#include "iconvstring.h" + +#include +#include + +#if HAVE_ICONV +# include +#endif + +#include "xalloc.h" + + +#if HAVE_ICONV + +/* Converts an entire string from one encoding to another, using iconv. + Return value: 0 if successful, otherwise -1 and errno set. */ +int +iconv_string (iconv_t cd, const char *start, const char *end, + char **resultp, size_t *lengthp) +{ +#define tmpbufsize 4096 + size_t length; + char *result; + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun) + /* Set to the initial state. */ + iconv (cd, NULL, NULL, NULL, NULL); +# endif + + /* Determine the length we need. */ + { + size_t count = 0; + char tmpbuf[tmpbufsize]; + const char *inptr = start; + size_t insize = end - start; + + while (insize > 0) + { + char *outptr = tmpbuf; + size_t outsize = tmpbufsize; + size_t res = iconv (cd, + (ICONV_CONST char **) &inptr, &insize, + &outptr, &outsize); + + if (res == (size_t)(-1)) + { + if (errno == E2BIG) + ; + else if (errno == EINVAL) + break; + else + return -1; + } +# if !defined _LIBICONV_VERSION && (defined sgi || defined __sgi) + /* Irix iconv() inserts a NUL byte if it cannot convert. */ + else if (res > 0) + return -1; +# endif + count += outptr - tmpbuf; + } + /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun) + { + char *outptr = tmpbuf; + size_t outsize = tmpbufsize; + size_t res = iconv (cd, NULL, NULL, &outptr, &outsize); + + if (res == (size_t)(-1)) + return -1; + count += outptr - tmpbuf; + } +# endif + length = count; + } + + *lengthp = length; + *resultp = result = xrealloc (*resultp, length); + if (length == 0) + return 0; + + /* Avoid glibc-2.1 bug and Solaris 2.7-2.9 bug. */ +# if defined _LIBICONV_VERSION \ + || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun) + /* Return to the initial state. */ + iconv (cd, NULL, NULL, NULL, NULL); +# endif + + /* Do the conversion for real. */ + { + const char *inptr = start; + size_t insize = end - start; + char *outptr = result; + size_t outsize = length; + + while (insize > 0) + { + size_t res = iconv (cd, + (ICONV_CONST char **) &inptr, &insize, + &outptr, &outsize); + + if (res == (size_t)(-1)) + { + if (errno == EINVAL) + break; + else + return -1; + } +# if !defined _LIBICONV_VERSION && (defined sgi || defined __sgi) + /* Irix iconv() inserts a NUL byte if it cannot convert. */ + else if (res > 0) + return -1; +# endif + } + /* Avoid glibc-2.1 bug and Solaris 2.7 bug. */ +# if defined _LIBICONV_VERSION \ + || !((__GLIBC__ - 0 == 2 && __GLIBC_MINOR__ - 0 <= 1) || defined __sun) + { + size_t res = iconv (cd, NULL, NULL, &outptr, &outsize); + + if (res == (size_t)(-1)) + return -1; + } +# endif + if (outsize != 0) + abort (); + } + + return 0; +#undef tmpbufsize +} + +#endif diff --git a/gettext-tools/lib/iconvstring.h b/gettext-tools/lib/iconvstring.h new file mode 100644 index 000000000..4ab5f969c --- /dev/null +++ b/gettext-tools/lib/iconvstring.h @@ -0,0 +1,51 @@ +/* Charset conversion. + Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc. + Written by Bruno Haible , 2001. + + 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. + + 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ + +#ifndef _ICONVSTRING_H +#define _ICONVSTRING_H + +#include +#if HAVE_ICONV +#include +#endif + + +#ifdef __cplusplus +extern "C" { +#endif + + +#if HAVE_ICONV + +/* Convert an entire string from one encoding to another, using iconv. + *RESULTP should initially contain NULL or malloced memory block. + Return value: 0 if successful, otherwise -1 and errno set. + If successful, the resulting string is stored in *RESULTP and its length + in *LENGTHP. */ +extern int iconv_string (iconv_t cd, const char *start, const char *end, + char **resultp, size_t *lengthp); + +#endif + + +#ifdef __cplusplus +} +#endif + + +#endif /* _ICONVSTRING_H */