UTF8 문자열을 UTF16 (리틀 엔디안)으로 변환하는 함수를 작성하고 싶습니다. 문제는 iconv
함수가 출력 문자열을 저장하는 데 필요한 바이트 수를 미리 알 수없는 것입니다.iconv를 사용한 간단한 UTF8-> UTF16 문자열 변환
static int utf8_to_utf16le(char *utf8, char **utf16, int *utf16_len)
{
iconv_t cd;
char *inbuf, *outbuf;
size_t inbytesleft, outbytesleft, nchars, utf16_buf_len;
cd = iconv_open("UTF16LE", "UTF8");
if (cd == (iconv_t)-1) {
printf("!%s: iconv_open failed: %d\n", __func__, errno);
return -1;
}
inbytesleft = strlen(utf8);
if (inbytesleft == 0) {
printf("!%s: empty string\n", __func__);
iconv_close(cd);
return -1;
}
inbuf = utf8;
utf16_buf_len = 2 * inbytesleft; // sufficient in many cases, i.e. if the input string is ASCII
*utf16 = malloc(utf16_buf_len);
if (!*utf16) {
printf("!%s: malloc failed\n", __func__);
iconv_close(cd);
return -1;
}
outbytesleft = utf16_buf_len;
outbuf = *utf16;
nchars = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
while (nchars == (size_t)-1 && errno == E2BIG) {
char *ptr;
size_t increase = 10; // increase length a bit
size_t len;
utf16_buf_len += increase;
outbytesleft += increase;
ptr = realloc(*utf16, utf16_buf_len);
if (!ptr) {
printf("!%s: realloc failed\n", __func__);
free(*utf16);
iconv_close(cd);
return -1;
}
len = outbuf - *utf16;
*utf16 = ptr;
outbuf = *utf16 + len;
nchars = iconv(cd, &inbuf, &inbytesleft, &outbuf, &outbytesleft);
}
if (nchars == (size_t)-1) {
printf("!%s: iconv failed: %d\n", __func__, errno);
free(*utf16);
iconv_close(cd);
return -1;
}
iconv_close(cd);
*utf16_len = utf16_buf_len - outbytesleft;
return 0;
}
이 그것을 할 수있는 가장 좋은 방법 정말 :
내 솔루션 realloc
필요한 경우와 그 버퍼의 크기를 증가 2*strlen(utf8)
을 할당하여 시작한 다음 루프에서 iconv
을 실행하는 것입니다? 반복 된 realloc
s는 낭비 적이지만 utf8에 어떤 문자 시퀀스가 있을지 모르고 utf16에서 어떤 결과가 나올지 모르는 상태에서 2*strlen(utf8)
보다 초기 버퍼 크기를 더 잘 예측할 수 있는지 알 수 없습니다.
좋은 점은'strlen'이지만, 제 경우에는 출력 문자열에 널 종료 입력 문자열과 종료되지 않은 버퍼 + 길이를 원했습니다. 나는 분명히하지 않았다. – craig65535