两个字符的utf-16怎么转utf-8

C++语言 码拜 9年前 (2016-04-06) 1008次浏览
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

CodeBye 版权所有丨如未注明 , 均为原创丨本网站采用BY-NC-SA协议进行授权 , 转载请注明两个字符的utf-16怎么转utf-8
喜欢 (0)
[1034331897@qq.com]
分享 (0)