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. */
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;
}
}
else
{
- if (result != tmpbuf)
+ if (result != initial_result)
{
int saved_errno = errno;
free (result);
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;
}
}
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);
if (res1 == (size_t)(-1)
&& !(errno == E2BIG || errno == EINVAL || errno == EILSEQ))
{
- if (result != tmpbuf)
+ if (result != initial_result)
{
int saved_errno = errno;
free (result);
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;
if (res == (size_t)(-1))
{
/* Failure converting the ASCII replacement. */
- if (result != tmpbuf)
+ if (result != initial_result)
{
int saved_errno = errno;
free (result);
}
else
{
- if (result != tmpbuf)
+ if (result != initial_result)
{
int saved_errno = errno;
free (result);
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;
}
}
in1size = 0;
else if (errno1 == EILSEQ)
{
- if (result != tmpbuf)
+ if (result != initial_result)
free (result);
errno = errno1;
return -1;
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
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);
(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,
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,
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,
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),
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,
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,
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,