/*
* 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;
}