changeset 7914:9862bb358a30

Change specification of mem_cd_iconveh.
author Bruno Haible <bruno@clisp.org>
date Sun, 21 Jan 2007 21:34:27 +0000
parents 36d66034ca77
children 957b6eccce2c
files lib/striconveh.c lib/striconveh.h tests/test-striconveh.c
diffstat 3 files changed, 77 insertions(+), 71 deletions(-) [+]
line wrap: on
line diff
--- a/lib/striconveh.c
+++ b/lib/striconveh.c
@@ -137,9 +137,23 @@
   union { unsigned int align; char buf[tmpbufsize]; } tmp;
 # define tmpbuf tmp.buf
 
-  char *result = tmpbuf;
-  size_t allocated = sizeof (tmpbuf);
-  size_t length = 0;
+  char *initial_result;
+  char *result;
+  size_t allocated;
+  size_t length;
+
+  if (*lengthp >= sizeof (tmpbuf))
+    {
+      initial_result = *resultp;
+      allocated = *lengthp;
+    }
+  else
+    {
+      initial_result = tmpbuf;
+      allocated = sizeof (tmpbuf);
+    }
+  result = initial_result;
+  length = 0;
 
   /* First, try a direct conversion, and see whether a conversion error
      occurs at all.  */
@@ -194,19 +208,19 @@
 			allocated = 2 * allocated;
 			if (length + 1 + extra_alloc > allocated)
 			  abort ();
-			if (result == tmpbuf)
+			if (result == initial_result)
 			  memory = (char *) malloc (allocated);
 			else
 			  memory = (char *) realloc (result, allocated);
 			if (memory == NULL)
 			  {
-			    if (result != tmpbuf)
+			    if (result != initial_result)
 			      free (result);
 			    errno = ENOMEM;
 			    return -1;
 			  }
-			if (result == tmpbuf)
-			  memcpy (memory, tmpbuf, length);
+			if (result == initial_result)
+			  memcpy (memory, initial_result, length);
 			result = memory;
 			grow = false;
 		      }
@@ -227,7 +241,7 @@
 	      }
 	    else
 	      {
-		if (result != tmpbuf)
+		if (result != initial_result)
 		  {
 		    int saved_errno = errno;
 		    free (result);
@@ -243,19 +257,19 @@
 	    char *memory;
 
 	    allocated = 2 * allocated;
-	    if (result == tmpbuf)
+	    if (result == initial_result)
 	      memory = (char *) malloc (allocated);
 	    else
 	      memory = (char *) realloc (result, allocated);
 	    if (memory == NULL)
 	      {
-		if (result != tmpbuf)
+		if (result != initial_result)
 		  free (result);
 		errno = ENOMEM;
 		return -1;
 	      }
-	    if (result == tmpbuf)
-	      memcpy (memory, tmpbuf, length);
+	    if (result == initial_result)
+	      memcpy (memory, initial_result, length);
 	    result = memory;
 	  }
       }
@@ -280,24 +294,24 @@
 	      char *memory;
 
 	      allocated = 2 * allocated;
-	      if (result == tmpbuf)
+	      if (result == initial_result)
 		memory = (char *) malloc (allocated);
 	      else
 		memory = (char *) realloc (result, allocated);
 	      if (memory == NULL)
 		{
-		  if (result != tmpbuf)
+		  if (result != initial_result)
 		    free (result);
 		  errno = ENOMEM;
 		  return -1;
 		}
-	      if (result == tmpbuf)
-		memcpy (memory, tmpbuf, length);
+	      if (result == initial_result)
+		memcpy (memory, initial_result, length);
 	      result = memory;
 	    }
 	  else
 	    {
-	      if (result != tmpbuf)
+	      if (result != initial_result)
 		{
 		  int saved_errno = errno;
 		  free (result);
@@ -429,7 +443,7 @@
 	if (res1 == (size_t)(-1)
 	    && !(errno == E2BIG || errno == EINVAL || errno == EILSEQ))
 	  {
-	    if (result != tmpbuf)
+	    if (result != initial_result)
 	      {
 		int saved_errno = errno;
 		free (result);
@@ -569,19 +583,19 @@
 			    allocated = 2 * allocated;
 			    if (length + 1 + extra_alloc > allocated)
 			      abort ();
-			    if (result == tmpbuf)
+			    if (result == initial_result)
 			      memory = (char *) malloc (allocated);
 			    else
 			      memory = (char *) realloc (result, allocated);
 			    if (memory == NULL)
 			      {
-				if (result != tmpbuf)
+				if (result != initial_result)
 				  free (result);
 				errno = ENOMEM;
 				return -1;
 			      }
-			    if (result == tmpbuf)
-			      memcpy (memory, tmpbuf, length);
+			    if (result == initial_result)
+			      memcpy (memory, initial_result, length);
 			    result = memory;
 			    grow = false;
 
@@ -607,7 +621,7 @@
 			if (res == (size_t)(-1))
 			  {
 			    /* Failure converting the ASCII replacement.  */
-			    if (result != tmpbuf)
+			    if (result != initial_result)
 			      {
 				int saved_errno = errno;
 				free (result);
@@ -618,7 +632,7 @@
 		      }
 		    else
 		      {
-			if (result != tmpbuf)
+			if (result != initial_result)
 			  {
 			    int saved_errno = errno;
 			    free (result);
@@ -635,19 +649,19 @@
 		    char *memory;
 
 		    allocated = 2 * allocated;
-		    if (result == tmpbuf)
+		    if (result == initial_result)
 		      memory = (char *) malloc (allocated);
 		    else
 		      memory = (char *) realloc (result, allocated);
 		    if (memory == NULL)
 		      {
-			if (result != tmpbuf)
+			if (result != initial_result)
 			  free (result);
 			errno = ENOMEM;
 			return -1;
 		      }
-		    if (result == tmpbuf)
-		      memcpy (memory, tmpbuf, length);
+		    if (result == initial_result)
+		      memcpy (memory, initial_result, length);
 		    result = memory;
 		  }
 	      }
@@ -664,7 +678,7 @@
 	      in1size = 0;
 	    else if (errno1 == EILSEQ)
 	      {
-		if (result != tmpbuf)
+		if (result != initial_result)
 		  free (result);
 		errno = errno1;
 		return -1;
@@ -676,42 +690,33 @@
 
  done:
   /* Now the final memory allocation.  */
-  if (resultp != NULL)
+  if (result == tmpbuf)
     {
-      if (result == tmpbuf)
-	{
-	  char *memory;
+      char *memory;
 
-	  memory = (char *) malloc (length + extra_alloc);
-	  if (memory != NULL)
-	    {
-	      memcpy (memory, tmpbuf, length);
-	      result = memory;
-	    }
-	  else
-	    {
-	      errno = ENOMEM;
-	      return -1;
-	    }
+      memory = (char *) malloc (length + extra_alloc);
+      if (memory != NULL)
+	{
+	  memcpy (memory, tmpbuf, length);
+	  result = memory;
 	}
-      else if (length + extra_alloc < allocated)
+      else
 	{
-	  /* Shrink the allocated memory if possible.  */
-	  char *memory;
+	  errno = ENOMEM;
+	  return -1;
+        }
+    }
+  else if (result != *resultp && length + extra_alloc < allocated)
+    {
+      /* Shrink the allocated memory if possible.  */
+      char *memory;
 
-	  memory = (char *) realloc (result, length + extra_alloc);
-	  if (memory != NULL)
-	    result = memory;
-	}
-      *resultp = result;
+      memory = (char *) realloc (result, length + extra_alloc);
+      if (memory != NULL)
+	result = memory;
     }
-  else
-    {
-      if (result != tmpbuf)
-	free (result);
-    }
-  if (lengthp != NULL)
-    *lengthp = length;
+  *resultp = result;
+  *lengthp = length;
   return 0;
 # undef tmpbuf
 # undef tmpbufsize
@@ -737,7 +742,7 @@
      function is usable for UTF-7, we have to exclude the NUL byte from the
      conversion and add it by hand afterwards.  */
   char *result = NULL;
-  size_t length;
+  size_t length = 0;
   int retval = mem_cd_iconveh_internal (src, strlen (src),
 					cd, cd1, cd2, handler, 1,
 					&result, &length);
--- a/lib/striconveh.h
+++ b/lib/striconveh.h
@@ -47,12 +47,13 @@
    (iconv_t)(-1) if FROM_CODESET is UTF-8).
    CD2 is the conversion descriptor from UTF-8 to TO_CODESET (or (iconv_t)(-1)
    if TO_CODESET is UTF-8).
-   *RESULTP should initially contain NULL or a malloced memory block.
-   May change the size of the allocated memory block in *RESULTP, storing
-   its new address in *RESULTP and its new length in *LENGTHP.
+   *RESULTP and *LENGTH should initially be a scratch buffer and its size,
+   or *RESULTP can initially be NULL.
+   May erase the contents of the memory at *RESULTP.
    Return value: 0 if successful, otherwise -1 and errno set.
-   If successful, the resulting string is stored in *RESULTP and its length
-   in *LENGTHP.  */
+   If successful: The resulting string is stored in *RESULTP and its length
+   in *LENGTHP.  *RESULTP is set to a freshly allocated memory block, or is
+   unchanged if no dynamic memory allocation was necessary.  */
 extern int
        mem_cd_iconveh (const char *src, size_t srclen,
 		       iconv_t cd, iconv_t cd1, iconv_t cd2,
--- a/tests/test-striconveh.c
+++ b/tests/test-striconveh.c
@@ -67,7 +67,7 @@
       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
       char *result = NULL;
-      size_t length;
+      size_t length = 0;
       int retval = mem_cd_iconveh (input, strlen (input),
 				   cd_88592_to_88591,
 				   cd_88592_to_utf8, cd_utf8_to_88591,
@@ -85,7 +85,7 @@
       enum iconv_ilseq_handler handler = handlers[h];
       static const char input[] = "Rafa\263 Maszkowski"; /* Rafał Maszkowski */
       char *result = NULL;
-      size_t length;
+      size_t length = 0;
       int retval = mem_cd_iconveh (input, strlen (input),
 				   cd_88592_to_88591,
 				   cd_88592_to_utf8, cd_utf8_to_88591,
@@ -125,7 +125,7 @@
       static const char input[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
       static const char expected[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
       char *result = NULL;
-      size_t length;
+      size_t length = 0;
       int retval = mem_cd_iconveh (input, strlen (input),
 				   cd_88591_to_utf8,
 				   cd_88591_to_utf8, (iconv_t)(-1),
@@ -144,7 +144,7 @@
       static const char input[] = "\303\204rger mit b\303\266sen B\303\274bchen ohne Augenma\303\237";
       static const char expected[] = "\304rger mit b\366sen B\374bchen ohne Augenma\337";
       char *result = NULL;
-      size_t length;
+      size_t length = 0;
       int retval = mem_cd_iconveh (input, strlen (input),
 				   cd_utf8_to_88591,
 				   (iconv_t)(-1), cd_utf8_to_88591,
@@ -162,7 +162,7 @@
       enum iconv_ilseq_handler handler = handlers[h];
       static const char input[] = "Rafa\305\202 Maszkowski"; /* Rafał Maszkowski */
       char *result = NULL;
-      size_t length;
+      size_t length = 0;
       int retval = mem_cd_iconveh (input, strlen (input),
 				   cd_utf8_to_88591,
 				   (iconv_t)(-1), cd_utf8_to_88591,
@@ -201,7 +201,7 @@
       enum iconv_ilseq_handler handler = handlers[h];
       static const char input[] = "\342";
       char *result = NULL;
-      size_t length;
+      size_t length = 0;
       int retval = mem_cd_iconveh (input, strlen (input),
 				   cd_utf8_to_88591,
 				   (iconv_t)(-1), cd_utf8_to_88591,