From 6984bc2a8dbe533274ee1869ba3c9e919040cf85 Mon Sep 17 00:00:00 2001 From: Bruno Haible Date: Sun, 21 Jan 2007 21:34:27 +0000 Subject: [PATCH] Change specification of mem_cd_iconveh. --- lib/striconveh.c | 123 +++++++++++++++++++++------------------- lib/striconveh.h | 11 ++-- tests/test-striconveh.c | 12 ++-- 3 files changed, 76 insertions(+), 70 deletions(-) diff --git a/lib/striconveh.c b/lib/striconveh.c index 9e916e656c..07e8e2a3ec 100644 --- a/lib/striconveh.c +++ b/lib/striconveh.c @@ -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); diff --git a/lib/striconveh.h b/lib/striconveh.h index b528e5152f..2ea7d540f0 100644 --- a/lib/striconveh.h +++ b/lib/striconveh.h @@ -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, diff --git a/tests/test-striconveh.c b/tests/test-striconveh.c index bc005ca150..1243fcdfe4 100644 --- a/tests/test-striconveh.c +++ b/tests/test-striconveh.c @@ -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, -- 2.30.2