Author: iratqq
Date: Sun Dec 14 11:50:02 2008
New Revision: 5669

Modified:
   trunk/uim/iconv.c

Log:
* uim/iconv.c (uim_iconv_code_conv):
  - Replace alloca with uim_malloc/uim_realloc.
  - Treate E2BIG.

  Inspired by following code,
   - http://www.hi-matic.org/distfiles/citrus/NetBSD/iconv_sample.c


Modified: trunk/uim/iconv.c
==============================================================================
--- trunk/uim/iconv.c   (original)
+++ trunk/uim/iconv.c   Sun Dec 14 11:50:02 2008
@@ -248,45 +248,76 @@
 }

 static char *
-uim_iconv_code_conv(void *obj, const char *str)
+uim_iconv_code_conv(void *obj, const char *instr)
 {
-  iconv_t ic;
-  size_t len, bufsize;
-  char *outbuf, *realbuf, *copied;
-  const char *inbuf, *src;
+  iconv_t cd = (iconv_t)obj;
+  size_t ins;
+  const char *in;
+  size_t outbufsiz, outs;
+  char   *outbuf, *out;
+  size_t ret = 0;
+  size_t idx = 0;

   if (UIM_CATCH_ERROR_BEGIN())
     return NULL;

-  do {
-    if (!str) {
-      copied = NULL;
-      break;
+  ins = strlen(instr);
+  in = instr;
+
+  outbufsiz = BUFSIZ;
+  out = outbuf = uim_malloc(outbufsiz);
+
+  while (ins > 0) {
+    out = outbuf + idx;
+    outs = outbufsiz;
+
+    ret = iconv(cd, (ICONV_CONST char **)&in, &ins, &out, &outs);
+    idx += outbufsiz - outs;
+
+    if (ret == (size_t)-1) {
+      switch (errno) {
+      case EINVAL:
+       /*
+        * XXX: assume input string is stateless charset
+        */
+       goto err;
+      case E2BIG:
+       outbufsiz *= 2;
+       out = uim_realloc(outbuf, outbufsiz);
+       outbuf = out;
+       break;
+      default:
+       goto err;
+      }
+    } else {
+      /* XXX: irreversible characters */
     }
+  }
+  do {
+    out = outbuf + idx;
+    outs = outbufsiz;
+
+    ret = iconv(cd, NULL, NULL, &out, &outs);
+    idx += outbufsiz - outs;

-    ic = (iconv_t)obj;
-    if (ic) {
-      len = strlen(str);
-      bufsize = (len + sizeof("")) * MBCHAR_LEN_MAX;
-      realbuf = alloca(bufsize);
-      bufsize--;
-
-      inbuf = str;
-      outbuf = realbuf;
-      iconv(ic, (ICONV_CONST char **)&inbuf, &len, &outbuf, &bufsize);
-      iconv(ic, NULL, NULL, &outbuf, &bufsize);
-      *outbuf = '\0';
-      src = realbuf;
+    if (ret == (size_t)-1) {
+      outbufsiz *= 2;
+      out = uim_realloc(outbuf, outbufsiz);
+      outbuf = out;
     } else {
-      src = str;
+      /* XXX: irreversible characters */
     }
+  } while (ret == (size_t)-1);
+
+  *out = '\0';
+  UIM_CATCH_ERROR_END();

-    copied = uim_strdup(src);
-  } while (/* CONSTCOND */ 0);
+  return outbuf;

+ err:
   UIM_CATCH_ERROR_END();

-  return copied;
+  return uim_strdup("");
 }

 static void

Reply via email to