Mercurial > hg > octave-nkf > gnulib-hg
changeset 5652:7c8ed35c4bd7
2005-02-22 Simon Josefsson <jas@extundo.com>
* iconvme.h, iconvme.c: New files, from libc.
author | Simon Josefsson <simon@josefsson.org> |
---|---|
date | Wed, 23 Feb 2005 23:30:10 +0000 |
parents | feed259a0290 |
children | 3b925de1333c |
files | lib/ChangeLog lib/iconvme.c lib/iconvme.h lib/size_max.h |
diffstat | 4 files changed, 221 insertions(+), 0 deletions(-) [+] |
line wrap: on
line diff
--- a/lib/ChangeLog +++ b/lib/ChangeLog @@ -1,3 +1,7 @@ +2005-02-22 Simon Josefsson <jas@extundo.com> + + * iconvme.h, iconvme.c: New files, from libc. + 2005-02-20 Neil Conway <neilc@samurai.com> * xgethostname.c (xgethostname): Check for ENOMEM, which is
new file mode 100644 --- /dev/null +++ b/lib/iconvme.c @@ -0,0 +1,165 @@ +/* Recode strings between character sets, using iconv. + Copyright (C) 2002, 2003, 2004, 2005 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public License as + published by the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifdef HAVE_CONFIG_H +# include <config.h> +#endif + +/* Get prototype. */ +#include "iconvme.h" + +/* Get malloc. */ +#include <stdlib.h> + +/* Get strcmp. */ +#include <string.h> + +/* Get errno. */ +#include <errno.h> + +#ifdef _LIBC +# define HAVE_ICONV 1 +#else +/* Get strdup. */ +# include "strdup.h" +#endif + +#if HAVE_ICONV +/* Get iconv etc. */ +# include <iconv.h> +/* Get MB_LEN_MAX. */ +# include <limits.h> +#endif + +/* Convert a zero-terminated string STR from the FROM_CODSET code set + to the TO_CODESET code set. The returned string is allocated using + malloc, and must be dellocated by the caller using free. On + failure, NULL is returned and errno holds the error reason. Note + that if TO_CODESET uses \0 for anything but to terminate the + string, the caller of this function may have difficulties finding + out the length of the output string. */ +char * +iconv_string (const char *str, const char *from_codeset, + const char *to_codeset) +{ + char *dest = NULL; +#if HAVE_ICONV + iconv_t cd; + char *outp; + char *p = (char *) str; + size_t inbytes_remaining = strlen (p); + /* Guess the maximum length the output string can have. */ + size_t outbuf_size = (inbytes_remaining + 1) * MB_LEN_MAX; + size_t outbytes_remaining = outbuf_size - 1; /* -1 for NUL */ + size_t err; + int have_error = 0; + + if (1 < MB_LEN_MAX && SIZE_MAX / MB_LEN_MAX <= inbytes_remaining) + { + errno = ENOMEM; + return NULL; + } +#endif + + if (strcmp (to_codeset, from_codeset) == 0) + return strdup (str); + +#if HAVE_ICONV + cd = iconv_open (to_codeset, from_codeset); + if (cd == (iconv_t) -1) + return NULL; + + outp = dest = (char *) malloc (outbuf_size); + if (dest == NULL) + goto out; + +again: + err = iconv (cd, &p, &inbytes_remaining, &outp, &outbytes_remaining); + + if (err == (size_t) - 1) + { + switch (errno) + { + case EINVAL: + /* Incomplete text, do not report an error */ + break; + + case E2BIG: + { + size_t used = outp - dest; + size_t newsize = outbuf_size * 2; + char *newdest; + + if (newsize <= outbuf_size) + { + errno = ENOMEM; + have_error = 1; + goto out; + } + newdest = (char *) realloc (dest, newsize); + if (newdest == NULL) + { + have_error = 1; + goto out; + } + dest = newdest; + outbuf_size = newsize; + + outp = dest + used; + outbytes_remaining = outbuf_size - used - 1; /* -1 for NUL */ + + goto again; + } + break; + + case EILSEQ: + have_error = 1; + break; + + default: + have_error = 1; + break; + } + } + + *outp = '\0'; + +out: + { + int save_errno = errno; + + if (iconv_close (cd) < 0 && !have_error) + { + /* If we didn't have a real error before, make sure we restore + the iconv_close error below. */ + save_errno = errno; + have_error = 1; + } + + if (have_error && dest) + { + free (dest); + dest = NULL; + errno = save_errno; + } + } +#else + errno = ENOSYS; +#endif + + return dest; +}
new file mode 100644 --- /dev/null +++ b/lib/iconvme.h @@ -0,0 +1,25 @@ +/* Recode strings between character sets, using iconv. + Copyright (C) 2004 Free Software Foundation, Inc. + Written by Simon Josefsson. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU Lesser General Public License as published by + the Free Software Foundation; either version 2.1, 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 Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public License along + with this program; if not, write to the Free Software Foundation, + Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef ICONVME_H +# define ICONVME_H + +extern char *iconv_string (const char *string, const char *from_code, + const char *to_code); + +#endif /* ICONVME_H */
new file mode 100644 --- /dev/null +++ b/lib/size_max.h @@ -0,0 +1,27 @@ +/* size_max.h -- declare SIZE_MAX through system headers + Copyright (C) 2005 Free Software Foundation, Inc. + Written by Simon Josefsson. + + 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ + +#ifndef GNULIB_SIZE_MAX_H +#define GNULIB_SIZE_MAX_H + +# include <limits.h> +# if HAVE_STDINT_H +# include <stdint.h> +# endif + +#endif /* GNULIB_SIZE_MAX_H */