Created
March 4, 2011 09:44
-
-
Save ynkdir/854406 to your computer and use it in GitHub Desktop.
str_iconv.c
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* 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