带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(9)

简介: 带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(9)

带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(8) https://developer.aliyun.com/article/1240879?groupCode=tech_library


10.5.2程序算法


用文字不太好描述算法结构,我们就直接来欣赏一下UTF-8鼻祖写的这段解析代码,这是Ken Thompson(B语言、C语言的作者、Unix之父)和 Rob Pike 用一个晚上写出来的编解码算法,代码非常简短精炼,为了方便阅读我加了注释解读。


typedefstruct

{

 intcmask; //前缀码掩码

 intcval;  //前缀码

 intshift; //移动位数

 longlmask; //Unicode值掩码

 longlval;  //Unicode下限值

} Tab;

 

staticTab  tab[] =

{

 0x80, 0x00, 0*6, 0x7F,       0,         /* 1 byte sequence */

 0xE0, 0xC0, 1*6, 0x7FF,      0x80,      /* 2 byte sequence */

 0xF0, 0xE0, 2*6, 0xFFFF,     0x800,     /* 3 byte sequence */

 0xF8, 0xF0, 3*6, 0x1FFFFF,   0x10000,   /* 4 byte sequence */

 0xFC, 0xF8, 4*6, 0x3FFFFFF,  0x200000,  /* 5 byte sequence */

 0xFE, 0xFC, 5*6, 0x7FFFFFFF, 0x4000000, /* 6 byte sequence */

 0, /* end of table */

};

 

/**

* 把一个多字节序列转换为一个宽字符

*

* @param p 存放计算后的unicode值

* @param s 需要解析的UTF-8字节序列

* @param n 字节长度

* @return 解析的字节长度

*/

intmbtowc(wchar_t*p, char*s, size_tn)

{

 longl;  intc0, c, nc;  Tab *t;

 if(s == 0) return0;

 nc = 0;

 //异常校验(可不用关注)

 if(n <= nc) return-1;

 //c0 此处备份一下首字节,后续需要用到前缀码

 c0 = *s & 0xff;

 //l 保存 Unicode 结果

 l = c0;

 /* 遍历tab,从单字节结构->2字节结构->..依次检查找到对应tab */

 for(t=tab; t->cmask; t++) {

   //字节数+1,字节数和tab结构是对应的,也就是当nc=1时 tab结构是单字节,nc=2是tab是两字节

   nc++;

   /* 判断前缀码跟当前的tab是否一致, 如果一致计算最终unicode值并返回*/

   if((c0 & t->cmask) == t->cval) {

     //通过 & Unicode有效值掩码,移除高位前缀码,得到最终unicode值

     l &= t->lmask;

     //异常校验

     if(l < t->lval) return-1;

     //保存结果并反回

     *p = l;

     returnnc;

   }

   //异常校验

   if(n <= nc) return-1;

   //读取下个字节;如果上面判断前缀码不一致,说明需要再读取下个字节

   s++;

   //计算有效位的值,目的是去除UTF-8 编码从第二个字节开始的高两位10

   // 例如 s=10101111、0x80=10000000 计算结果是00101111,这样就去除了高位前缀10

   c = (*s ^ 0x80) & 0xFF;

   //异常校验

   if(c & 0xC0) return-1;

   //重新计算unicode值,根据UTF-8规则c只有低 6 位有效,所以通过移位把c填入到l的低6位

   l = (l<<6) | c;

 }

 //返回异常

 return-1;

}



带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(10) https://developer.aliyun.com/article/1240875?groupCode=tech_library

相关文章
|
6月前
|
存储 JavaScript Java
[字符编码] 理论篇:常见字符集与编码方式
[字符编码] 理论篇:常见字符集与编码方式
170 0
|
存储
带你读《全景揭秘字符编码》之二:二、什么是字符编码?
带你读《全景揭秘字符编码》之二:二、什么是字符编码?
248 1
|
自然语言处理
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(6)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(6)
161 0
|
Unix Linux Windows
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(7)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(7)
156 0
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(4)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(4)
181 0
|
自然语言处理
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(2)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(2)
149 0
|
存储
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(5)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(5)
150 0
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(3)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(3)
196 0
|
存储
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(8)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(8)
176 0
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(10)
带你读《全景揭秘字符编码》之十:常见字符编码4:UNICODE(10)