Skip to content

Instantly share code, notes, and snippets.

@ynkdir
Created March 4, 2011 09:44
Show Gist options
  • Save ynkdir/854406 to your computer and use it in GitHub Desktop.
Save ynkdir/854406 to your computer and use it in GitHub Desktop.
str_iconv.c
/* str_iconv() function */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <iconv.h>
static char *
str_iconv(const char *fromcode, const char *tocode, const char *str, size_t len)
{
iconv_t cd = (iconv_t)(-1);
char buf[8192];
char *outbuf = NULL;
size_t outlen;
char *newbuf;
const char *from;
size_t fromlen;
char *to;
size_t tolen;
size_t r;
cd = iconv_open(tocode, fromcode);
if (cd == (iconv_t)(-1))
return NULL;
from = str;
if (len == (size_t)(-1))
fromlen = strlen(str);
else
fromlen = len;
outlen = 1;
outbuf = calloc(outlen, sizeof(char));
if (outbuf == NULL)
goto onerror;
while (fromlen > 0) {
to = buf;
tolen = sizeof(buf);
r = iconv(cd, (void *)&from, &fromlen, &to, &tolen);
if (r == (size_t)(-1)) {
if (errno == E2BIG) {
/* There is not sufficient room at *outbuf. */
/* Verbose check. */
if (to == buf)
goto onerror;
} else if (errno == EILSEQ) {
/* An invalid multibyte sequence has been encountered in
* the input. */
goto onerror;
} else if (errno == EINVAL) {
/* An incomplete multibyte sequence has been encountered
* in the input. */
/* Read more bytes from input if possible. */
goto onerror;
} else {
/* Unknown error. Probarly never happen. */
goto onerror;
}
}
newbuf = realloc(outbuf, outlen + (to - buf));
if (newbuf == NULL)
goto onerror;
outbuf = newbuf;
memmove(outbuf + outlen - 1, buf, to - buf);
outlen = outlen + (to - buf);
outbuf[outlen - 1] = '\0';
}
/* flush */
to = buf;
tolen = sizeof(buf);
r = iconv(cd, NULL, NULL, &to, &tolen);
if (r == (size_t)(-1))
goto onerror;
if (to - buf > 0) {
newbuf = realloc(outbuf, outlen + (to - buf));
if (newbuf == NULL)
goto onerror;
outbuf = newbuf;
memmove(outbuf + outlen - 1, buf, to - buf);
outlen = outlen + (to - buf);
outbuf[outlen - 1] = '\0';
}
iconv_close(cd);
return outbuf;
onerror:
if (outbuf != NULL)
free(outbuf);
if (cd != (iconv_t)(-1))
iconv_close(cd);
return NULL;
}
int
main(int argc, char **argv)
{
char *buf;
char *p;
buf = str_iconv("utf-8", "cp932", "あいうえお", -1);
printf("cp932: ");
for (p = buf; *p != '\0'; ++p) {
printf("%02x ", (unsigned char)*p);
}
printf("\n");
free(buf);
buf = str_iconv("utf-8", "euc-jp", "あいうえお", -1);
printf("euc-jp: ");
for (p = buf; *p != '\0'; ++p) {
printf("%02x ", (unsigned char)*p);
}
printf("\n");
free(buf);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment