Clean up wchar_t conversion code in iconv program.

This commit is contained in:
Roland McGrath 2014-10-30 12:56:51 -07:00
parent d4e157aaae
commit 65b00b6c51
2 changed files with 61 additions and 79 deletions

View File

@ -1,3 +1,11 @@
2014-10-30 Roland McGrath <roland@hack.frob.com>
* iconv/iconv_charmap.c (add_bytes): Make IN argument pointer to const.
(convert_charseq): New function, broken out of ...
(use_from_charmap): ... here. Call it.
(use_to_charmap): Use convert_charseq and free instead of duplicating
its code with a variable-length stack struct.
2014-10-30 Joseph Myers <joseph@codesourcery.com>
* include/fcntl.h (__libc_creat): Remove declaration.

View File

@ -232,8 +232,10 @@ charmap_conversion (const char *from_code, struct charmap_t *from_charmap,
}
/* Add the IN->OUT mapping to TBL. OUT is potentially stored in the table.
IN is used only here, so it need not be kept live afterwards. */
static void
add_bytes (struct convtable *tbl, struct charseq *in, struct charseq *out)
add_bytes (struct convtable *tbl, const struct charseq *in, struct charseq *out)
{
int n = 0;
unsigned int byte;
@ -266,6 +268,45 @@ add_bytes (struct convtable *tbl, struct charseq *in, struct charseq *out)
}
}
/* Try to convert SEQ from WCHAR_T format using CD.
Returns a malloc'd struct or NULL. */
static struct charseq *
convert_charseq (iconv_t cd, const struct charseq *seq)
{
struct charseq *result = NULL;
if (seq->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { seq->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
result = xmalloc (sizeof (struct charseq) + outlen);
result->name = seq->name;
result->ucs4 = seq->ucs4;
result->nbytes = outlen;
memcpy (result->bytes, outbuf, outlen);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
return result;
}
static struct convtable *
use_from_charmap (struct charmap_t *from_charmap, const char *to_code)
@ -290,41 +331,10 @@ use_from_charmap (struct charmap_t *from_charmap, const char *to_code)
while (iterate_table (&from_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *in = (struct charseq *) data;
if (in->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { in->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
struct charseq *newp;
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
newp = (struct charseq *) xmalloc (sizeof (struct charseq)
+ outlen);
newp->name = in->name;
newp->ucs4 = in->ucs4;
newp->nbytes = outlen;
memcpy (newp->bytes, outbuf, outlen);
add_bytes (rettbl, in, newp);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
struct charseq *in = data;
struct charseq *newp = convert_charseq (cd, in);
if (newp != NULL)
add_bytes (rettbl, in, newp);
}
iconv_close (cd);
@ -360,49 +370,13 @@ use_to_charmap (const char *from_code, struct charmap_t *to_charmap)
while (iterate_table (&to_charmap->char_table, &ptr, &key, &keylen, &data)
>= 0)
{
struct charseq *out = (struct charseq *) data;
if (out->ucs4 != UNINITIALIZED_CHAR_VALUE)
{
/* There is a chance. Try the iconv module. */
wchar_t inbuf[1] = { out->ucs4 };
unsigned char outbuf[64];
char *inptr = (char *) inbuf;
size_t inlen = sizeof (inbuf);
char *outptr = (char *) outbuf;
size_t outlen = sizeof (outbuf);
(void) iconv (cd, &inptr, &inlen, &outptr, &outlen);
if (outptr != (char *) outbuf)
{
/* We got some output. Good, use it. */
union
{
struct charseq seq;
struct
{
const char *name;
uint32_t ucs4;
int nbytes;
unsigned char bytes[outlen];
} mem;
} new;
outlen = sizeof (outbuf) - outlen;
assert ((char *) outbuf + outlen == outptr);
new.mem.name = out->name;
new.mem.ucs4 = out->ucs4;
new.mem.nbytes = outlen;
memcpy (new.mem.bytes, outbuf, outlen);
add_bytes (rettbl, &new.seq, out);
}
/* Clear any possible state left behind. */
(void) iconv (cd, NULL, NULL, NULL, NULL);
}
struct charseq *out = data;
struct charseq *newp = convert_charseq (cd, out);
if (newp != NULL)
{
add_bytes (rettbl, newp, out);
free (newp);
}
}
iconv_close (cd);