| 123 | } |
| 124 | |
| 125 | void ConvertUtf16ToModifiedUtf8(char* utf8_out, size_t byte_count, |
| 126 | const uint16_t* utf16_in, size_t char_count) { |
| 127 | if (LIKELY(byte_count == char_count)) { |
| 128 | // Common case where all characters are ASCII. |
| 129 | const uint16_t *utf16_end = utf16_in + char_count; |
| 130 | for (const uint16_t *p = utf16_in; p < utf16_end;) { |
| 131 | *utf8_out++ = dchecked_integral_cast<char>(*p++); |
| 132 | } |
| 133 | return; |
| 134 | } |
| 135 | |
| 136 | // String contains non-ASCII characters. |
| 137 | while (char_count--) { |
| 138 | const uint16_t ch = *utf16_in++; |
| 139 | if (ch > 0 && ch <= 0x7f) { |
| 140 | *utf8_out++ = ch; |
| 141 | } else { |
| 142 | // Char_count == 0 here implies we've encountered an unpaired |
| 143 | // surrogate and we have no choice but to encode it as 3-byte UTF |
| 144 | // sequence. Note that unpaired surrogates can occur as a part of |
| 145 | // "normal" operation. |
| 146 | if ((ch >= 0xd800 && ch <= 0xdbff) && (char_count > 0)) { |
| 147 | const uint16_t ch2 = *utf16_in; |
| 148 | |
| 149 | // Check if the other half of the pair is within the expected |
| 150 | // range. If it isn't, we will have to emit both "halves" as |
| 151 | // separate 3 byte sequences. |
| 152 | if (ch2 >= 0xdc00 && ch2 <= 0xdfff) { |
| 153 | utf16_in++; |
| 154 | char_count--; |
| 155 | const uint32_t code_point = (ch << 10) + ch2 - 0x035fdc00; |
| 156 | *utf8_out++ = (code_point >> 18) | 0xf0; |
| 157 | *utf8_out++ = ((code_point >> 12) & 0x3f) | 0x80; |
| 158 | *utf8_out++ = ((code_point >> 6) & 0x3f) | 0x80; |
| 159 | *utf8_out++ = (code_point & 0x3f) | 0x80; |
| 160 | continue; |
| 161 | } |
| 162 | } |
| 163 | |
| 164 | if (ch > 0x07ff) { |
| 165 | // Three byte encoding. |
| 166 | *utf8_out++ = (ch >> 12) | 0xe0; |
| 167 | *utf8_out++ = ((ch >> 6) & 0x3f) | 0x80; |
| 168 | *utf8_out++ = (ch & 0x3f) | 0x80; |
| 169 | } else /*(ch > 0x7f || ch == 0)*/ { |
| 170 | // Two byte encoding. |
| 171 | *utf8_out++ = (ch >> 6) | 0xc0; |
| 172 | *utf8_out++ = (ch & 0x3f) | 0x80; |
| 173 | } |
| 174 | } |
| 175 | } |
| 176 | } |
| 177 | |
| 178 | int32_t ComputeUtf16HashFromModifiedUtf8(const char* utf8, size_t utf16_length) { |
| 179 | uint32_t hash = 0; |
nothing calls this directly
no outgoing calls
no test coverage detected