讲解


代码
//编码用函数 返回value按照utf8编码后的字节数 根据valle的大小反推需要的字节数uint32_t getByteNumOfEncodeUtf8(int value) { ASSERT(value > 0, "Can`t encode negative value!"); // 单个ascii字符需要1字节 if (value <= 0x7f) { return 1; } //此范围内数值编码为utf8需要2字节 if (value <= 0x7ff) { return 2; } //此范围内数值编码为utf8需要3字节 if (value <= 0xffff) { return 3; } //此范围内数值编码为utf8需要4字节 if (value <= 0x10ffff) { return 4; } return 0; //超过范围返回0}//编码用函数 把value编码为utf8后写入缓冲区buf,返回写入的字节数uint8_t encodeUtf8(uint8_t* buf, int value) { ASSERT(value > 0, "Can`t encode negative value!");//按照大端字节序写入缓冲区 if (value <= 0x7f) { // 单个ascii字符需要1字节 // 0x7f => 0b01111111 *buf = value & 0x7f; // 往buf内存地址处写值 return 1; } else if (value <= 0x7ff) { //此范围内数值编码为utf8需要2字节 // 0x7ff => 0b11111111111 2字节编码范围 // 110xxxxx 10xxxxxx 11位有效 utf-8 2字节编码规则 // 例如:value 是 0b10100_011001 // 0b11111_000000 & 0b10100_011001 => 0b10100_000000 // 0b10100_000000 >> 6 => 0b10100 value中的高5位 // 写入buf内存 => 0b110_10100 此时buf内存中起始就是高字节部分 // buf内存地址再加一个字节,向内存地址高地址处移动一个字节 // 与操作过滤 或操作合并 //先写入高字节 *buf = 0xc0/*0b110_00000*/ | ((value & 0x7c0/*0b11111_000000*/) >> 6); buf++; // 0b111111 & 0b10100_011001 => 0b10100_011001 // 再写入低字节 *buf = 0x80/*0b10_000000*/ | (value & 0x3f/*0b111111*/); return 2; } else if (value <= 0xffff) { //此范围内数值编码为utf8需要3字节 // 先写入高字节 *buf = 0xe0 | ((value & 0xf000) >> 12); buf++; //再写入中间字节 *buf = 0x80 | ((value & 0xfc0) >> 6); buf++; //最后写入低字节 *buf = 0x80 | (value & 0x3f); return 3; } else if (value <= 0x10ffff) { //此范围内数值编码为utf8需要4字节 *buf = 0xf0 | ((value & 0x1c0000) >> 18); buf++; *buf = 0x80 | ((value & 0x3f000) >> 12); buf++; *buf = 0x80 | ((value & 0xfc0) >> 6); buf++; *buf = 0x80 | (value & 0x3f); return 4; } NOT_REACHED(); return 0;}//解码用函数 返回解码utf8的字节数uint32_t getByteNumOfDecodeUtf8(uint8_t byte) { //byte应该是utf8的最高1字节,如果指向了utf8编码后面的低字节部分则返回0 if ((byte & 0xc0/*0b11000000*/) == 0x80/*0b10000000*/) { // 10不因该是utf-8高位,应该是低位 return 0; } if ((byte & 0xf8/*0b11111_000 有效位清0*/) == 0xf0/*0b11110_000 utf-8 4字节高字节清0后各位的特征*/) { return 4; } if ((byte & 0xf0/*0b1111_0000 有效位清0*/) == 0xe0/*0b1110_0000 utf-8 3字节高字节清0后各位的特征*/) { return 3; } if ((byte & 0xe0/*0b111_00000 有效位清0*/) == 0xc0/*0b110_00000 utf-8 2字节高字节清0后各位的特征*/) { return 2; } return 1; //ascii码} //解码用函数 解码以bytePtr为起始地址的UTF-8序列 其最大长度为length 若不是UTF-8序列就返回-1int decodeUtf8(const uint8_t* bytePtr, uint32_t length) { //若是1字节的ascii: 0xxxxxxx if (*bytePtr <= 0x7f) { return *bytePtr; } int value; uint32_t remainingBytes; //先读取高1字节 //根据高字节的高n位判断相应字节数的utf8编码 if ((*bytePtr & 0xe0) == 0xc0) { //若是2字节的utf8 value = *bytePtr & 0x1f/*0b000_11111*/; // 过滤出高字节有效位 remainingBytes = 1; } else if ((*bytePtr & 0xf0) == 0xe0) { //若是3字节的utf8 value = *bytePtr & 0x0f; remainingBytes = 2; } else if ((*bytePtr & 0xf8) == 0xf0) { //若是4字节的utf8 value = *bytePtr & 0x07; remainingBytes = 3; } else { //非法编码 return -1; } //如果utf8被斩断了就不再读过去了 if (remainingBytes > length - 1) { return -1; } //再读取低字节中的数据 while (remainingBytes > 0) { bytePtr++; remainingBytes--; //高2位必须是10 if ((*bytePtr & 0xc0) != 0x80) { return -1; } //从次高字节往低字节,不断累加各字节的低6位 value = value << 6 | (*bytePtr & 0x3f); } return value;}