[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: new module: iconvstring
From: |
Simon Josefsson |
Subject: |
Re: new module: iconvstring |
Date: |
Tue, 25 Apr 2006 11:14:56 +0200 |
User-agent: |
Gnus/5.110005 (No Gnus v0.5) Emacs/22.0.50 (gnu/linux) |
Bruno Haible <address@hidden> writes:
> Hi,
>
> This module 'iconvstring' is in use in GNU gettext in 4 places. It is an
> easy-to-use iconv() wrapper, like the 'iconvme' module. The difference is
> that 'iconvstring' uses an iconv_t descriptor, rather than two encoding names,
> and is therefore suitable for converting a whole lot of strings, without
> needing
> to re-open a conversion descriptor for each string.
>
> Nothing against Simon's 'iconvme' module - it is very nice. It is just that
> sometimes you need one, sometimes the other.
Did you see iconv_alloc in iconvme? There is some overlap here.
Perhaps iconvme could simply be re-written to use iconvstring, to
avoid slightly duplicated code. Your module seem more general, but I
still find the iconvme API easier to understand and use for
non-experts.
> Bruno
>
> ================================= modules/iconvstring
> ===============================
> Description:
> Character set conversion of strings made easy and fast, uses iconv.
>
> Files:
> lib/iconvstring.h
> lib/iconvstring.c
> m4/iconvstring.m4
>
> Depends-on:
> iconv
> xalloc
>
> configure.ac:
> gl_ICONVSTRING
>
> Makefile.am:
> lib_SOURCES += iconvstring.h iconvstring.c
> lib_LIBADD += $(LTLIBICONV)
>
> Include:
> "iconvstring.h"
>
> License:
> GPL
>
> Maintainer:
> Bruno Haible
>
> ================================= lib/iconvstring.h
> ===============================
> /* Charset conversion.
> Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
> Written by Bruno Haible <address@hidden>, 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 <stddef.h>
> #if HAVE_ICONV
> #include <iconv.h>
> #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 */
> ================================= lib/iconvstring.c
> ===============================
> /* Charset conversion.
> Copyright (C) 2001-2003, 2006 Free Software Foundation, Inc.
> Written by Bruno Haible <address@hidden>, 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 <errno.h>
> #include <stdlib.h>
>
> #if HAVE_ICONV
> # include <iconv.h>
> #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
> ================================= m4/iconvstring.m4
> ===============================
> # iconvstring.m4 serial 1
> dnl Copyright (C) 2006 Free Software Foundation, Inc.
> dnl This file is free software; the Free Software Foundation
> dnl gives unlimited permission to copy and/or distribute it,
> dnl with or without modifications, as long as this notice is preserved.
>
> AC_DEFUN([gl_ICONVSTRING],
> [
> gl_PREREQ_ICONVSTRING
> ])
>
> # Prerequisites of lib/iconvstring.h and lib/iconvstring.c.
> AC_DEFUN([gl_PREREQ_ICONVSTRING],
> [
> AC_REQUIRE([AM_ICONV])
> ])