\brief Convert the codepoint to utf8 \param input the input \return the utf8 string
| 82 | /// \param input the input |
| 83 | /// \return the utf8 string |
| 84 | std::string Tokenizer::cpt_to_utf8(const std::string& input) { |
| 85 | static const std::string pattern = "▁"; |
| 86 | static const size_t pattern_size = pattern.size(); |
| 87 | static auto inv_map = this->make_inverse_byte_map(); |
| 88 | std::string output = ""; |
| 89 | output.reserve(input.size()); |
| 90 | size_t i = 0; |
| 91 | if (!this->is_doubled_encoded) { // simply do pattern substitution of "▁" to " ", temporary solution |
| 92 | std::string output = ""; |
| 93 | for (size_t i = 0; i < input.size(); i++) { |
| 94 | if (i <= input.size() - pattern_size && input.substr(i, pattern_size) == pattern) { |
| 95 | output += " "; |
| 96 | i += pattern_size - 1; // -1 because the loop will increment i by 1 |
| 97 | } |
| 98 | else { |
| 99 | output += input[i]; |
| 100 | } |
| 101 | } |
| 102 | return output; |
| 103 | } |
| 104 | while (i < input.size()) { |
| 105 | unsigned char c = input[i]; |
| 106 | uint32_t cp; |
| 107 | size_t width; |
| 108 | |
| 109 | // --- Decode a UTF-8 codepoint --- |
| 110 | if (c < 0x80) { |
| 111 | cp = c; |
| 112 | width = 1; |
| 113 | } |
| 114 | else if ((c & 0xE0) == 0xC0) { |
| 115 | if (i + 1 >= input.size()) throw std::runtime_error("Truncated UTF-8, ll = 2"); |
| 116 | cp = (uint32_t)(c & 0x1F) << 6; |
| 117 | cp |= (uint32_t)(input[i+1] & 0x3F); |
| 118 | width = 2; |
| 119 | } |
| 120 | else if ((c & 0xF0) == 0xE0) { |
| 121 | if (i + 2 >= input.size()) throw std::runtime_error("Truncated UTF-8, ll = 3"); |
| 122 | cp = (uint32_t)(c & 0x0F) << 12; |
| 123 | cp |= (uint32_t)(input[i+1] & 0x3F) << 6; |
| 124 | cp |= (uint32_t)(input[i+2] & 0x3F); |
| 125 | width = 3; |
| 126 | } |
| 127 | else if ((c & 0xF8) == 0xF0) { |
| 128 | if (i + 3 >= input.size()) throw std::runtime_error("Truncated UTF-8, ll = 4"); |
| 129 | cp = (uint32_t)(c & 0x07) << 18; |
| 130 | cp |= (uint32_t)(input[i+1] & 0x3F) << 12; |
| 131 | cp |= (uint32_t)(input[i+2] & 0x3F) << 6; |
| 132 | cp |= (uint32_t)(input[i+3] & 0x3F); |
| 133 | width = 4; |
| 134 | } |
| 135 | else { |
| 136 | std::cout << std::hex <<"cp: " << cp << std::endl; |
| 137 | throw std::runtime_error("Invalid UTF-8 byte"); |
| 138 | } |
| 139 | |
| 140 | // --- Look up the original byte --- |
| 141 | auto it = inv_map.find(cp); |
no test coverage detected