inline String<STRU16> _U8STOU16S_ (const String<STRU8> &src) {
Buffer<STRU16> ret (src.length () + 1) ;
INDEX iw = 0 ;
FLAG state = 0 ;
for (const STRU8 &i : src) {
if (state == 0 && (i & STRU8 (0XF0)) == STRU8 (0XE0)) {
ret[iw] = i & STRU8 (0X0F) ;
state = 2 ;
} else if (state == 0 && (i & STRU8 (0XE0)) == STRU8 (0XC0)) {
ret[iw] = i & STRU8 (0X1F) ;
state = 1 ;
} else if (state != 0 && (i & STRU8 (0XC0)) == STRU8 (0X80)) {
ret[iw] = (ret[iw] << 6) | (i & STRU8 (0X3F)) ;
if (--state == 0)
iw++ ;
} else if (state == 0 && (i & STRU8 (0X80)) == STRU8 (0X00)) {
ret[iw++] = i ;
} else {
return String<STRU16> () ;
}
}
ret[iw] = 0 ;
return ret.to () ;
}
inline String<STRU8> _U16STOU8S_ (const String<STRU16> &src) {
Buffer<STRU8> ret (src.length () * 3) ;
INDEX iw = 0 ;
for (const STRU16 &i : src) {
if (i <= STRU16 (0X007F)) {
ret[iw++] = STRU8 (i) ;
} else if (i <= STRU16 (0X07FF)) {
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0XDF)) | STRU8 (0XC0) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
} else {
ret[iw++] = (STRU8 (i >> 12) & STRU8 (0XEF)) | STRU8 (0XE0) ;
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
}
}
ret[iw] = 0 ;
return ret.to () ;
}
inline String<STRU32> _U8STOU32S_ (const String<STRU8> &src) {
Buffer<STRU32> ret (src.length ()) ;
INDEX iw = 0 ;
FLAG state = 0 ;
for (const STRU8 &i : src) {
if (state == 0 && (i & STRU8 (0XFE)) == STRU8 (0XFC)) {
ret[iw] = i & STRU8 (0X01) ;
state = 5 ;
} else if (state == 0 && (i & STRU8 (0XFC)) == STRU8 (0XF8)) {
ret[iw] = i & STRU8 (0X03) ;
state = 4 ;
} else if (state == 0 && (i & STRU8 (0XF8)) == STRU8 (0XF0)) {
ret[iw] = i & STRU8 (0X07) ;
state = 3 ;
} else if (state == 0 && (i & STRU8 (0XF0)) == STRU8 (0XE0)) {
ret[iw] = i & STRU8 (0X0F) ;
state = 2 ;
} else if (state == 0 && (i & STRU8 (0XE0)) == STRU8 (0XC0)) {
ret[iw] = i & STRU8 (0X1F) ;
state = 1 ;
} else if (state != 0 && (i & STRU8 (0XC0)) == STRU8 (0X80)) {
ret[iw] = (ret[iw] << 6) | (i & STRU8 (0X3F)) ;
if (--state == 0)
iw++ ;
} else if (state == 0 && (i & STRU8 (0X80)) == STRU8 (0X00)) {
ret[iw++] = i ;
} else {
return String<STRU32> () ;
}
}
ret[iw] = 0 ;
return ret.to () ;
}
inline String<STRU8> _U32STOU8S_ (const String<STRU32> &src) {
Buffer<STRU8> ret (src.length () * 6) ;
INDEX iw = 0 ;
for (const STRU32 &i : src) {
if (i <= STRU32 (0X0000007F)) {
ret[iw++] = STRU8 (i) ;
} else if (i <= STRU32 (0X000007FF)) {
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0X1F)) | STRU8 (0XC0) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
} else if (i <= STRU32 (0X0000FFFF)) {
ret[iw++] = (STRU8 (i >> 12) & STRU8 (0XEF)) | STRU8 (0XE0) ;
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
} else if (i <= STRU32 (0X001FFFFF)) {
ret[iw++] = (STRU8 (i >> 18) & STRU8 (0XF7)) | STRU8 (0XF0) ;
ret[iw++] = (STRU8 (i >> 12) & STRU8 (0X3F)) ;
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
} else if (i <= STRU32 (0X03FFFFFF)) {
ret[iw++] = (STRU8 (i >> 24) & STRU8 (0XFB)) | STRU8 (0XF8) ;
ret[iw++] = (STRU8 (i >> 18) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i >> 12) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
} else if (i <= STRU32 (0X7FFFFFFF)) {
ret[iw++] = (STRU8 (i >> 30) & STRU8 (0XFD)) | STRU8 (0XFC) ;
ret[iw++] = (STRU8 (i >> 24) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i >> 18) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i >> 12) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i >> 6) & STRU8 (0X3F)) | STRU8 (0X80) ;
ret[iw++] = (STRU8 (i) & STRU8 (0X3F)) | STRU8 (0X80) ;
} else {
return String<STRU8> () ;
}
}
ret[iw] = 0 ;
return ret.to () ;
}
如题
解决方案
15
先转 UTF32, 再正常转 UTF8, UTF8 最好还是只支持到 U+10FFFF, 不然有些字符在 UTF16 下无法表示…
c1 = read_UTF16();
if(c1 >= 0xD800 && c1 <= 0xDFFF)
{ /* Surrogate Area */
if(c1 >= 0xDC00)
return invalid .......
c2 = read_UTF16();
if(0 == c2)
return wouldblock.... or invalid ....
if(c2 < 0xDC00 || c2 > 0xDFFF)
return invalid .......
ucs4_ch = (c2 & 0x03FF) + (((c1 & 0x03FF) + 0x40) << 10);
}
25
// UTF-8 编码字符理论上可以最多到 6个字节长,但目前全世界的所 // 有文字和符号种类加起来也只要编到 4个字节长就够了。 // UTF-8 是以 8位(即 1个字节)为单元对原始码进行编码(注意一 // 点:这里所讲的原始码都是指Unicode码),并规定:多字节码(2个字 // 节以上才称为多字节)以转换后第1个字节起头的连续“1”的数目(这 // 些连续“1”称为标记位),表示转换成几个字节:“110”连续两个 // “1”,表示转换结果为2个字节,“1110”表示3个字节,而“11110” // 则表示4个字节……跟随在标记位之后的“0”,其作用是分隔标记位和 // 字符码位。第2~第4个字节的起头两个位固定设置为“10”,也作为标 // 记,剩下的6个位才做为字符码位使用。 // 这样,2字节UTF-8码剩下11个字符码位,可用以转换0080~07FF的 // 原始字符码,3字节剩下16个字符码位,可用以转换0800~FFFF的原始字 // 符码,由此类推。编码方式的模板如下: // // 原始码(16进制) UTF-8编码(二进制) // -- // 0000 - 007F 0xxxxxxx // 0080 - 07FF 110xxxxx 10xxxxxx // 0800 - FFFF 1110xxxx 10xxxxxx 10xxxxxx // …… // -- // // 模板中的“x”表示字符码。 // Ascii码<007F,编为1个 // 字节的UTF-8码。汉字的 Unicode编码范围为0800-FFFF,所以被编为 // 3个字节的UTF-8码。 // 例如“汉”字的Unicode编码是6C49,6C49在0800-FFFF之间,所以 // 要用3个字节的模板:1110wwww 10xxxxyy 10yyzzzz。 // 6 C 4 9 // 0110 1100 0100 1001 // wwww xxxx yyyy zzzz // wwww xxxxyy yyzzzz // 1110wwww 10xxxxyy 10yyzzzz。 // 11100110 10110001 10001001 // E 6 B 1 8 9 //“汉”字的UTF-8编码是E6 B1 89