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