summaryrefslogtreecommitdiff
path: root/iconv/iconv_charmap.c
diff options
context:
space:
mode:
Diffstat (limited to 'iconv/iconv_charmap.c')
-rw-r--r--iconv/iconv_charmap.c132
1 files changed, 53 insertions, 79 deletions
diff --git a/iconv/iconv_charmap.c b/iconv/iconv_charmap.c
index 7bbd8e9fef..b6a17ebc16 100644
--- a/iconv/iconv_charmap.c
+++ b/iconv/iconv_charmap.c
@@ -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);