2 {
3 DWORD charsCount= 0 ;
4 DWORD result ;
5 LPDWORD pResult=&result ;
6 LPVOID tmpBuffer=NULL ;
7 LPBYTE tmpData=(LPBYTE)utf8Bytes ;
8 if(IsUTF8Data(tmpData))
9 {
10 utf8Bytes=tmpData+ 3 ;
11 bytesLength-= 3 ;
12 }
13 *unicodeBytes=malloc(bytesLength* 2) ; //分配最大可能需要的内存
14 //EAX:需要计算的数据
15 //EBX:操作状态
16 //ECX:最大源地址
17 //EDX:计算结果
18 //ESI:源
19 //EDI:目标
20 __asm
21 {
22 // push eax ; //对使用到的寄存器进行保存
23 // push ebx ; //对使用到的寄存器进行保存
24 // push ecx ;
25 // push edx ;
26 // push esi ;
27 // push edi ;
28 pushad ;
29 MOV eax, 0 ;
30 mov esi,utf8Bytes ; //设置源地址
31 mov edi,DWORD PTR[unicodeBytes] ; //设置目标地址
32 mov edi,DWORD PTR[EDI] ;
33 mov ecx,bytesLength ;
34 add ecx,esi ; //计算源数据最高地址
35 MOV EBX,pResult
36 XOR EAX,EAX ;
37 XOR EDX,EDX ;
38 LoopStart: ;
39 mov EAX,DWORD PTR[ESI] ; //读取数据
40
41 test al,0x80 ;
42 jz L1 ;
43 test al,0x40 ;
44 JZ LoopEnd ; //错误数据
45 TEST AL,0x20 ;
46 JZ L2 ;
47 JNZ L3 ;
48
49 NOT EBX ; //遇到无效字符(不支持四字节字符)
50 JMP LoopEnd ;
51 L3: ;
52 AND EAX,0x003F3F0F ;
53 ADD DL,AL ;
54 SHL EDX, 6 ;
55 SHR EAX, 8 ;
56 ADD DL,AL ;
57 SHL EDX, 6 ;
58 // SHR EAX, 8 ;
59 ADD DL,AH ;
60 ADD ESI, 3 ;
61 JMP END ;
62 L2: ;
63 AND EAX,0x00003F1F ;
64 ADD DL,AL ;
65 SHL EDX, 6 ;
66 // SHR EAX, 8 ;
67 ADD DL,AH ;
68 ADD ESI, 2 ;
69 JMP END ;
70 L1: ;
71 MOV DL,AL ;
72 ADD ESI, 1 ;
73 // SHL EDX, 8 ;
74 END: ;
75 MOV WORD PTR [EDI],DX ;
76 XOR EDX,EDX ;
77 ADD EDI, 2 ;
78
79 CMP ESI,ECX ;
80 JNGE LoopStart ; //如果ESI小于ECX 继续循环
81
82 MOV WORD PTR [EDI], 0 ;
83 MOV DWORD PTR[EBX],EDI ;
84 LoopEnd: ;
85 //错误的数据
86 popad
87 // pop edi ; //恢复使用到的寄存器
88 // pop esi ;
89 // pop edx ;
90 // pop ecx ;
91 // pop ebx ;
92 // pop eax ;
93 }
94 if(result!=- 1)
95 {
96 charsCount=result-(DWORD)*unicodeBytes ;
97 tmpBuffer=malloc(charsCount+ 4) ;
98 memset(tmpBuffer, 0,charsCount+ 4) ;
99 memcpy(tmpBuffer,*unicodeBytes,charsCount) ;
100 free(*unicodeBytes) ;
101 *unicodeBytes=tmpBuffer ;
102 }
103 return charsCount ;
104 }
UTF-8编码转换Utf-16
以上代码不转换4字节Utf-8编码字符,因为4字节Utf-8编码字符无法在UTF-16保存,最大0X1FFFF而Utf-16最大0xFFFF;utf-32可以保存
Utf-16编码和Unicode是一一对应的,Unicode程序中使用的也就是utf-16;
所以很多时候需要进行转换,utf-8保存英文字符占用空间小于utf-16,但是对于中文大于utf-16占用的空间
首先一次性取4个字节(对于32位机器取一个字节的消耗和4个字节一样),然后判断第一个字节(因为使用了寄存器,那么第一个字节就在最低位,低位低字节,高位高字节),
8 7 6 5 4
0 x x x x 单字节
1 1 0 x x 双字节
1 1 1 0 x 三字节
1 1 1 1 0四字节
1 0 x x x多字节的话处第一个字节外其余字节以这个开头
低位低字节,高位高字节。Unicode有两种表示一种高位在前,另外1种高位在后
11011111,10001111
那么结果是11001111,00001111//部分编码选择这种方式
那么结果是00001111,11001111//目前大多数是这样的
其实就是高低字节顺序的问题
更多信息请参见Utf-8编码的标准文档
上边代码对四字节处理基本忽略掉了,因为出现4字节Utf-16无法保存,所以处理也是白处理