需求
有一个 xml
文件,是 utf16-be
格式的,直接使用 firefox
打开不对,所以考虑先转码为 utf8
然后再打开。
解决
int Utf16leToUtf8(uint8_t* dest, int dest_size, int* dest_len, uint16_t* src, int src_len)
{
uint8_t* dest_start = dest;
uint8_t* dest_end = dest + dest_size;
//uint16_t* src_end = (uint16_t*)((uint8_t*)src + src_len);
uint16_t* src_end = src + src_len;
while (src < src_end)
{
if (*src < UTF16_2 && dest + 1 < dest_end) {
//0000 - 007F : 0xxxxxxx
*dest++ = (uint8_t)*src;
} else if(*src >= UTF16_2 && *src < UTF16_3
&& dest + 2 < dest_end) {
//0080 - 07FF : 110xxxxx 10xxxxxx
*dest++ = ((*src >> 6) & 0x1F) | 0xC0;
*dest++ = (*src & 0x3F) | 0x80;
} else if(*src >= UTF16_3 && *src < UTF16_4
&& dest + 3 < dest_end) {
//0800 - FFFF : 1110xxxx 10xxxxxx 10xxxxxx
*dest++ = ((*src >> 12) & 0x0F) | 0xE0;
*dest++ = ((*src >> 6) & 0x3F) | 0x80;
*dest++ = (*src & 0x3F) | 0x80;
} else if(*src >= UTF16_4 && *src < UTF16_4_SECOND
&& dest + 4 < dest_end) {
// 代理项对部分(4字节表示)
//0001 0000 - 001F FFFF : 1111 0xxx 10xxxxxx 10xxxxxx 10xxxxxx
// 从代理项对到UNICODE代码点转换
// 1、从高代理项减去0xD800,获取有效10bit
// 2、从低代理项减去0xDC00,获取有效10bit
// 3、加上0x10000,获取UNICODE代码点值
uint16_t high_sur = *src++;
uint16_t low_sur = *src;
uint32_t code_point = high_sur - UTF16_4;
code_point <<= 10;
code_point |= low_sur - UTF16_4_SECOND;
code_point += UTF16_4_PLUS;
*dest++ = (code_point >> 18) | 0xF0;
*dest++ = ((code_point >> 12) & 0x3F) | 0x80;
*dest++ = ((code_point >> 06) & 0x3F) | 0x80;
*dest++ = (code_point & 0x3F) | 0x80;
} else {
break;
}
src++;
}
*dest = 0;
*dest_len = dest - dest_start;
if (src < src_end) {
return -1;
}
return 0;
}
int Utf16beToUtf8(uint8_t* dest, int dest_size, int* dest_len, uint16_t* src, int src_len)
{
uint16_t le[src_len];
union {
uint16_t s;
uint8_t buf[sizeof(uint16_t)];
} data;
for (int i = 0; i < src_len; i++) {
/*
uint8_t * d = (uint8_t *)(src + i);
uint8_t tmp = *d;
*d = *(d + 1);
*(d + 1) = tmp;
*/
data.s = *(src + i);
uint8_t tmp = data.buf[0];
data.buf[0] = data.buf[1];
data.buf[1] = tmp;
*(le + i) = data.s;
}
return Utf16leToUtf8(dest, dest_size, dest_len, le, src_len);
}