From 5b5e96599e90a94c5d8f40e570c56faec8af9dc1 Mon Sep 17 00:00:00 2001 From: Luo Jinghua Date: Fri, 8 Jan 2010 15:04:40 +0800 Subject: uniconv: be compatible with system's iconv --- uniconv.c | 57 +++++++++++++++++++++++++++++++++------------------------ 1 file changed, 33 insertions(+), 24 deletions(-) diff --git a/uniconv.c b/uniconv.c index 22a70ee..7e9fe1e 100644 --- a/uniconv.c +++ b/uniconv.c @@ -94,8 +94,6 @@ uniconv_conv(uniconv_t *uc, size_t *outleft) { int ret; - uc_char_t local_ucs4[UNICONV_MAX_LOCAL]; - uc_char_t *ucs4, *inucs4; size_t ucs4len; const char *saved_inbuf; const char *saved_outbuf; @@ -112,38 +110,49 @@ uniconv_conv(uniconv_t *uc, /* converting/pushing input data */ if (inbuf) { - if (*inleft < UNICONV_MAX_LOCAL) - ucs4 = local_ucs4; - else - ucs4 = malloc(sizeof(uc_char_t) * (*inleft)); - if (!ucs4) - return UNICONV_EINVAL; + uc_char_t ucs4; + uc_char_t *ucsbuf; - inucs4 = ucs4; - ucs4len = *inleft; saved_inbuf = *inbuf; saved_outbuf = *outbuf; - ret = uc->from->decode(uc->from, inbuf, *inleft, &inucs4, ucs4len); - *inleft -= *inbuf - saved_inbuf; - if (ret) - goto error_decode; - - ucs4len = inucs4 - ucs4; - inucs4 = ucs4; - ret = uc->to->encode(uc->to, (const ucs4_t **)&inucs4, ucs4len, - outbuf, *outleft); + while (*inleft) { + size_t i = 0; + const char *abuf; + const char *aoutbuf; + + /* decode a char at a time */ + for (i = 1; i <= *inleft; i++) { + ucsbuf = &ucs4; + abuf = *inbuf; + ret = uc->from->decode(uc->from, &abuf, i, &ucsbuf, 1); + if (ret < 0 && ret == UNICONV_EINVAL) + continue; + break; + } + if (ret == UNICONV_E2BIG) + ret = UNICONV_EILSEQ; + if (ret < 0) + return ret; + + ucs4len = ucsbuf - &ucs4; + ucsbuf = &ucs4; + aoutbuf = *outbuf; + ret = uc->to->encode(uc->to, (const ucs4_t **)&ucsbuf, ucs4len, + outbuf, *outleft); + *outleft -= *outbuf - aoutbuf; + if (ret < 0) + break; + *inleft -= i; + (*inbuf) += i; + } } else { - ucs4 = NULL; /* converting pending data in buffer */ saved_inbuf = NULL; saved_outbuf = *outbuf; ret = uc->to->encode(uc->to, NULL, 0, outbuf, *outleft); + *outleft -= *outbuf - saved_outbuf; } - *outleft -= *outbuf - saved_outbuf; - error_decode: - if (ucs4 && ucs4 != local_ucs4) - free (ucs4); return ret; } -- cgit v1.2.3