UTF-8转换为宽字符mbtowc

typedef struct
{
  intcmask; //前缀码掩码
  intcval;  //前缀码
  intshift; //移动位数
  longlmask; //Unicode值掩码
  longlval;  //Unicode下限值
} Tab;
 
static Tab  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 解析的字节长度
*/
int mbtowc(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;
}

你可能感兴趣的:(开发语言,c语言)