/*
* ngx_utf8_decode() decodes two and more bytes UTF sequences only
* the return values:
* 0x80 - 0x10ffff valid character
* 0x110000 - 0xfffffffd invalid sequence
* 0xfffffffe incomplete sequence
* 0xffffffff error
*/
/*
* 0 ~ 0x7f 0xxx|xxxx
* 0x80 ~ 0x7ff 110x|xxxx 10xx|xxxx
* 0x800 ~ 0xffff 1110|xxxx 10xx|xxxx 10xx|xxxx
* 0x10000 ~ 0x10ffff 1111|0xxx 10xx|xxxx 10xx|xxxx 10xx|xxxx
*
*该程序首先根据多字节数据的首字节获取表示的实际Unicode码值的区间,该多字节的长度
*然后依次提取实际存储的Unicode码值,并存放在u中
*len 表示除去一个字节之外,理论上还有多少字节
*valid 表示该多字节所对应的Unicode编码必须大于的Unicode编码值
*u表示utf-8编码对应的多字节Unicode码值
* u > 0xf0 则对应 0x10000 ~ 0x10ffff Unicode编码区间 因为只有该区间的utf-8编码的首字节11110xxxx大于0xf0
* u > 0xe0 则对应 0x800 ~ 0xffff Unicode编码区间 因为只有该区间的utf-8编码的首字节小于11110xxxx,但大于 1110xxxx,且1110xxxx大于0xe0
* u > 0xc0 则对应 0x80 ~ 0x7ff Unicode编码区间,同样的理由,110xxxxx 大于0xc0 ,假如所有的xxxxx位全为0,则必然退化成单字节表示
*/
uint32_t
ngx_utf8_decode(u_char **p, size_t n)
{
size_t len;
uint32_t u, i, valid;
u = **p;
if (u > 0xf0) {
u &= 0x07;
valid = 0xffff;
len = 3;
} else if (u > 0xe0) {
u &= 0x0f;
valid = 0x7ff;
len = 2;
} else if (u > 0xc0) {
u &= 0x1f;
valid = 0x7f;
len = 1;
} else {
(*p)++;
return 0xffffffff;
}
if (n - 1 < len) {
return 0xfffffffe;
}
(*p)++;
while (len) {
i = *(*p)++;
if (i < 0x80) {
return 0xffffffff;
}
u = (u << 6) | (i & 0x3f);
len--;
}
if (u > valid) {
return u;
}
return 0xffffffff;
}