Change specification of mem_cd_iconveh.
authorBruno Haible <bruno@clisp.org>
Sun, 21 Jan 2007 21:34:27 +0000 (21:34 +0000)
committerBruno Haible <bruno@clisp.org>
Sun, 21 Jan 2007 21:34:27 +0000 (21:34 +0000)
lib/striconveh.c
lib/striconveh.h
tests/test-striconveh.c

index 9e916e6..07e8e2a 100644 (file)
@@ -137,9 +137,23 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
   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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                        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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
              }
            else
              {
-               if (result != tmpbuf)
+               if (result != initial_result)
                  {
                    int saved_errno = errno;
                    free (result);
@@ -243,19 +257,19 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
            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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
              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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
        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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                            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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                        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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                      }
                    else
                      {
-                       if (result != tmpbuf)
+                       if (result != initial_result)
                          {
                            int saved_errno = errno;
                            free (result);
@@ -635,19 +649,19 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
                    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 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
              in1size = 0;
            else if (errno1 == EILSEQ)
              {
-               if (result != tmpbuf)
+               if (result != initial_result)
                  free (result);
                errno = errno1;
                return -1;
@@ -676,42 +690,33 @@ mem_cd_iconveh_internal (const char *src, size_t srclen,
 
  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;
-           }
-       }
-      else if (length + extra_alloc < allocated)
+      memory = (char *) malloc (length + extra_alloc);
+      if (memory != NULL)
        {
-         /* Shrink the allocated memory if possible.  */
-         char *memory;
-
-         memory = (char *) realloc (result, length + extra_alloc);
-         if (memory != NULL)
-           result = memory;
+         memcpy (memory, tmpbuf, length);
+         result = memory;
        }
-      *resultp = result;
+      else
+       {
+         errno = ENOMEM;
+         return -1;
+        }
     }
-  else
+  else if (result != *resultp && length + extra_alloc < allocated)
     {
-      if (result != tmpbuf)
-       free (result);
+      /* Shrink the allocated memory if possible.  */
+      char *memory;
+
+      memory = (char *) realloc (result, length + extra_alloc);
+      if (memory != NULL)
+       result = memory;
     }
-  if (lengthp != NULL)
-    *lengthp = length;
+  *resultp = result;
+  *lengthp = length;
   return 0;
 # undef tmpbuf
 # undef tmpbufsize
@@ -737,7 +742,7 @@ str_cd_iconveh (const char *src,
      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);
index b528e51..2ea7d54 100644 (file)
@@ -47,12 +47,13 @@ enum iconv_ilseq_handler
    (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,
index bc005ca..1243fcd 100644 (file)
@@ -67,7 +67,7 @@ main ()
       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 @@ main ()
       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 @@ main ()
       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 @@ main ()
       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 @@ main ()
       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 @@ main ()
       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,