changeset 30975:a2f4140594dd

Add a 'resultbuf' argument.
author Bruno Haible <bruno@clisp.org>
date Sat, 07 Mar 2009 14:22:32 +0100
parents 22b37e8d6622
children 9f34a28986da
files lib/memxfrm.c lib/memxfrm.h
diffstat 2 files changed, 29 insertions(+), 12 deletions(-) [+]
line wrap: on
line diff
--- a/lib/memxfrm.c	Sat Mar 07 13:38:02 2009 +0100
+++ b/lib/memxfrm.c	Sat Mar 07 14:22:32 2009 +0100
@@ -25,7 +25,7 @@
 #include <string.h>
 
 char *
-memxfrm (char *s, size_t n, size_t *lengthp)
+memxfrm (char *s, size_t n, char *resultbuf, size_t *lengthp)
 {
   /* Result accumulator.  */
   char *result;
@@ -35,10 +35,18 @@
   char orig_sentinel;
 
   /* Initial memory allocation.  */
-  allocated = (n > 0 ? n : 1);
-  result = (char *) malloc (allocated);
-  if (result == NULL)
-    goto out_of_memory_2;
+  if (resultbuf != NULL && *lengthp > 0)
+    {
+      result = resultbuf;
+      allocated = *lengthp;
+    }
+  else
+    {
+      allocated = (n > 0 ? n : 1);
+      result = (char *) malloc (allocated);
+      if (result == NULL)
+	goto out_of_memory_2;
+    }
   length = 0;
 
   /* Add sentinel.byte.  */
@@ -72,7 +80,12 @@
 		char *new_result;
 
 		allocated = 2 * allocated;
-		new_result = (char *) realloc (result, allocated);
+		if (allocated < 64)
+		  allocated = 64;
+		if (result == resultbuf)
+		  new_result = (char *) malloc (allocated);
+		else
+		  new_result = (char *) realloc (result, allocated);
 		if (new_result == NULL)
 		  goto out_of_memory_1;
 		result = new_result;
@@ -93,7 +106,7 @@
   }
 
   /* Shrink the allocated memory if possible.  */
-  if ((length > 0 ? length : 1) < allocated)
+  if (result != resultbuf && (length > 0 ? length : 1) < allocated)
     {
       char *memory = (char *) realloc (result, length > 0 ? length : 1);
       if (memory != NULL)
@@ -107,14 +120,16 @@
  fail:
   {
     int saved_errno = errno;
-    free (result);
+    if (result != resultbuf)
+      free (result);
     s[n] = orig_sentinel;
     errno = saved_errno;
     return NULL;
   }
 
  out_of_memory_1:
-  free (result);
+  if (result != resultbuf)
+    free (result);
   s[n] = orig_sentinel;
  out_of_memory_2:
   errno = ENOMEM;
--- a/lib/memxfrm.h	Sat Mar 07 13:38:02 2009 +0100
+++ b/lib/memxfrm.h	Sat Mar 07 14:22:32 2009 +0100
@@ -33,10 +33,12 @@
    restored before this function returns.
    The result of this function depends on the LC_COLLATE category of the
    current locale.
-   If successful, return the freshly allocated transformed string and set
-   *LENGTHP to its length,
+   If successful: If resultbuf is not NULL and the result fits into *lengthp
+   bytes, it is put in resultbuf, and resultbuf is returned.  Otherwise, a
+   freshly allocated string is returned.  In both cases, *lengthp is set to the
+   length of the returned string.
    Upon failure, return NULL, with errno set.  */
-extern char * memxfrm (char *s, size_t n, size_t *lengthp);
+extern char * memxfrm (char *s, size_t n, char *resultbuf, size_t *lengthp);
 
 
 #ifdef __cplusplus