From: Bruno Haible Date: Sat, 7 Mar 2009 13:22:32 +0000 (+0100) Subject: Add a 'resultbuf' argument. X-Git-Tag: v0.1~6202 X-Git-Url: http://erislabs.org.uk/gitweb/?a=commitdiff_plain;h=e84790be54801e0b39d7a21d50cd9444207337eb;p=gnulib.git Add a 'resultbuf' argument. --- diff --git a/lib/memxfrm.c b/lib/memxfrm.c index 9b29c52d9..dc6eda1fa 100644 --- a/lib/memxfrm.c +++ b/lib/memxfrm.c @@ -25,7 +25,7 @@ #include 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 @@ memxfrm (char *s, size_t n, size_t *lengthp) 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 @@ memxfrm (char *s, size_t n, size_t *lengthp) 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 @@ memxfrm (char *s, size_t n, size_t *lengthp) } /* 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 @@ memxfrm (char *s, size_t n, size_t *lengthp) 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; diff --git a/lib/memxfrm.h b/lib/memxfrm.h index 635463318..d78900a70 100644 --- a/lib/memxfrm.h +++ b/lib/memxfrm.h @@ -33,10 +33,12 @@ extern "C" { 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