bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

new module: iconvstring


From: Bruno Haible
Subject: new module: iconvstring
Date: Mon, 24 Apr 2006 22:41:32 +0200
User-agent: KMail/1.5

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.

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])
])





reply via email to

[Prev in Thread] Current Thread [Next in Thread]