讲解

697585《自制编程语言基于C语言》_郑钢_20210819224630.jpg
697585《自制编程语言基于C语言》_郑钢_20210819225034.jpg
697585《自制编程语言基于C语言》_郑钢_20210819225214.jpg

代码

  1. //编码用函数 返回value按照utf8编码后的字节数 根据valle的大小反推需要的字节数
  2. uint32_t getByteNumOfEncodeUtf8(int value) {
  3. ASSERT(value > 0, "Can`t encode negative value!");
  4. // 单个ascii字符需要1字节
  5. if (value <= 0x7f) {
  6. return 1;
  7. }
  8. //此范围内数值编码为utf8需要2字节
  9. if (value <= 0x7ff) {
  10. return 2;
  11. }
  12. //此范围内数值编码为utf8需要3字节
  13. if (value <= 0xffff) {
  14. return 3;
  15. }
  16. //此范围内数值编码为utf8需要4字节
  17. if (value <= 0x10ffff) {
  18. return 4;
  19. }
  20. return 0; //超过范围返回0
  21. }
  22. //编码用函数 把value编码为utf8后写入缓冲区buf,返回写入的字节数
  23. uint8_t encodeUtf8(uint8_t* buf, int value) {
  24. ASSERT(value > 0, "Can`t encode negative value!");
  25. //按照大端字节序写入缓冲区
  26. if (value <= 0x7f) { // 单个ascii字符需要1字节
  27. // 0x7f => 0b01111111
  28. *buf = value & 0x7f; // 往buf内存地址处写值
  29. return 1;
  30. } else if (value <= 0x7ff) { //此范围内数值编码为utf8需要2字节
  31. // 0x7ff => 0b11111111111 2字节编码范围
  32. // 110xxxxx 10xxxxxx 11位有效 utf-8 2字节编码规则
  33. // 例如:value 是 0b10100_011001
  34. // 0b11111_000000 & 0b10100_011001 => 0b10100_000000
  35. // 0b10100_000000 >> 6 => 0b10100 value中的高5位
  36. // 写入buf内存 => 0b110_10100 此时buf内存中起始就是高字节部分
  37. // buf内存地址再加一个字节,向内存地址高地址处移动一个字节
  38. // 与操作过滤 或操作合并
  39. //先写入高字节
  40. *buf = 0xc0/*0b110_00000*/ | ((value & 0x7c0/*0b11111_000000*/) >> 6);
  41. buf++;
  42. // 0b111111 & 0b10100_011001 => 0b10100_011001
  43. // 再写入低字节
  44. *buf = 0x80/*0b10_000000*/ | (value & 0x3f/*0b111111*/);
  45. return 2;
  46. } else if (value <= 0xffff) { //此范围内数值编码为utf8需要3字节
  47. // 先写入高字节
  48. *buf = 0xe0 | ((value & 0xf000) >> 12);
  49. buf++;
  50. //再写入中间字节
  51. *buf = 0x80 | ((value & 0xfc0) >> 6);
  52. buf++;
  53. //最后写入低字节
  54. *buf = 0x80 | (value & 0x3f);
  55. return 3;
  56. } else if (value <= 0x10ffff) { //此范围内数值编码为utf8需要4字节
  57. *buf = 0xf0 | ((value & 0x1c0000) >> 18);
  58. buf++;
  59. *buf = 0x80 | ((value & 0x3f000) >> 12);
  60. buf++;
  61. *buf = 0x80 | ((value & 0xfc0) >> 6);
  62. buf++;
  63. *buf = 0x80 | (value & 0x3f);
  64. return 4;
  65. }
  66. NOT_REACHED();
  67. return 0;
  68. }
  69. //解码用函数 返回解码utf8的字节数
  70. uint32_t getByteNumOfDecodeUtf8(uint8_t byte) {
  71. //byte应该是utf8的最高1字节,如果指向了utf8编码后面的低字节部分则返回0
  72. if ((byte & 0xc0/*0b11000000*/) == 0x80/*0b10000000*/) {
  73. // 10不因该是utf-8高位,应该是低位
  74. return 0;
  75. }
  76. if ((byte & 0xf8/*0b11111_000 有效位清0*/) == 0xf0/*0b11110_000 utf-8 4字节高字节清0后各位的特征*/) {
  77. return 4;
  78. }
  79. if ((byte & 0xf0/*0b1111_0000 有效位清0*/) == 0xe0/*0b1110_0000 utf-8 3字节高字节清0后各位的特征*/) {
  80. return 3;
  81. }
  82. if ((byte & 0xe0/*0b111_00000 有效位清0*/) == 0xc0/*0b110_00000 utf-8 2字节高字节清0后各位的特征*/) {
  83. return 2;
  84. }
  85. return 1; //ascii码
  86. }
  87. //解码用函数 解码以bytePtr为起始地址的UTF-8序列 其最大长度为length 若不是UTF-8序列就返回-1
  88. int decodeUtf8(const uint8_t* bytePtr, uint32_t length) {
  89. //若是1字节的ascii: 0xxxxxxx
  90. if (*bytePtr <= 0x7f) {
  91. return *bytePtr;
  92. }
  93. int value;
  94. uint32_t remainingBytes;
  95. //先读取高1字节
  96. //根据高字节的高n位判断相应字节数的utf8编码
  97. if ((*bytePtr & 0xe0) == 0xc0) {
  98. //若是2字节的utf8
  99. value = *bytePtr & 0x1f/*0b000_11111*/; // 过滤出高字节有效位
  100. remainingBytes = 1;
  101. } else if ((*bytePtr & 0xf0) == 0xe0) {
  102. //若是3字节的utf8
  103. value = *bytePtr & 0x0f;
  104. remainingBytes = 2;
  105. } else if ((*bytePtr & 0xf8) == 0xf0) {
  106. //若是4字节的utf8
  107. value = *bytePtr & 0x07;
  108. remainingBytes = 3;
  109. } else { //非法编码
  110. return -1;
  111. }
  112. //如果utf8被斩断了就不再读过去了
  113. if (remainingBytes > length - 1) {
  114. return -1;
  115. }
  116. //再读取低字节中的数据
  117. while (remainingBytes > 0) {
  118. bytePtr++;
  119. remainingBytes--;
  120. //高2位必须是10
  121. if ((*bytePtr & 0xc0) != 0x80) {
  122. return -1;
  123. }
  124. //从次高字节往低字节,不断累加各字节的低6位
  125. value = value << 6 | (*bytePtr & 0x3f);
  126. }
  127. return value;
  128. }