summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBruno Haible <bruno@clisp.org>2007-01-21 21:34:27 +0000
committerBruno Haible <bruno@clisp.org>2007-01-21 21:34:27 +0000
commit6984bc2a8dbe533274ee1869ba3c9e919040cf85 (patch)
tree805571638f1403088a010f7696c3aac582c37eb8
parent09588236cbfd1a2fb863f9f4f6db8158e8bcf062 (diff)
downloadgnulib-6984bc2a8dbe533274ee1869ba3c9e919040cf85.tar.gz
Change specification of mem_cd_iconveh.
-rw-r--r--lib/striconveh.c123
-rw-r--r--lib/striconveh.h11
-rw-r--r--tests/test-striconveh.c12
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,