changeset 10406:5991da96e696

Make striconveh work better with stateful encodings.
author Bruno Haible <bruno@clisp.org>
date Sun, 07 Sep 2008 23:18:24 +0200
parents b1a4eae36771
children 2575b6d4b6b5
files ChangeLog lib/striconveh.c
diffstat 2 files changed, 26 insertions(+), 11 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2008-09-07  Bruno Haible  <bruno@clisp.org>
+
+	Make striconveh work better with stateful encodings.
+	* lib/striconveh.c (iconv_carefully, iconv_carefully_1): Don't assume
+	that iconv does not increment the inptr when returning -1/EINVAL.
+
 2008-09-07  Bruno Haible  <bruno@clisp.org>
 
 	* build-aux/config.rpath: Update according to libtool-2.2.6.
--- a/lib/striconveh.c
+++ b/lib/striconveh.c
@@ -79,9 +79,13 @@
 		       &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)
@@ -117,31 +121,36 @@
 # 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;