| 174 | } |
| 175 | |
| 176 | void String::append_utf32(const Span<char32_t> &p_cstr) { |
| 177 | if (p_cstr.is_empty()) { |
| 178 | return; |
| 179 | } |
| 180 | |
| 181 | const int prev_length = length(); |
| 182 | resize_uninitialized(prev_length + p_cstr.size() + 1); |
| 183 | const char32_t *src = p_cstr.ptr(); |
| 184 | const char32_t *end = p_cstr.ptr() + p_cstr.size(); |
| 185 | char32_t *dst = ptrw() + prev_length; |
| 186 | |
| 187 | // Copy the string, and check for UTF-32 problems. |
| 188 | for (; src < end; ++src, ++dst) { |
| 189 | const char32_t chr = *src; |
| 190 | if (unlikely(chr == U'\0')) { |
| 191 | // NUL in string is allowed by the unicode standard, but unsupported in our implementation right now. |
| 192 | print_unicode_error("Unexpected NUL character", true); |
| 193 | *dst = _replacement_char; |
| 194 | } else if (unlikely((chr & 0xfffff800) == 0xd800)) { |
| 195 | print_unicode_error(vformat("Unpaired surrogate (%x)", (uint32_t)chr), true); |
| 196 | *dst = _replacement_char; |
| 197 | } else if (unlikely(chr > 0x10ffff)) { |
| 198 | print_unicode_error(vformat("Invalid unicode codepoint (%x)", (uint32_t)chr), true); |
| 199 | *dst = _replacement_char; |
| 200 | } else { |
| 201 | *dst = chr; |
| 202 | } |
| 203 | } |
| 204 | *dst = 0; |
| 205 | } |
| 206 | |
| 207 | void String::copy_from_unchecked(const char32_t *p_char, const int p_length) { |
| 208 | resize_uninitialized(p_length + 1); // + 1 for \0 |
no test coverage detected