| 2084 | //----------------------------------------------------------------------------- |
| 2085 | |
| 2086 | IM_MSVC_RUNTIME_CHECKS_OFF |
| 2087 | |
| 2088 | // Convert UTF-8 to 32-bit character, process single character input. |
| 2089 | // A nearly-branchless UTF-8 decoder, based on work of Christopher Wellons (https://github.com/skeeto/branchless-utf8). |
| 2090 | // We handle UTF-8 decoding error by skipping forward. |
| 2091 | int ImTextCharFromUtf8(unsigned int* out_char, const char* in_text, const char* in_text_end) |
| 2092 | { |
| 2093 | static const char lengths[32] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0 }; |
| 2094 | static const int masks[] = { 0x00, 0x7f, 0x1f, 0x0f, 0x07 }; |
| 2095 | static const uint32_t mins[] = { 0x400000, 0, 0x80, 0x800, 0x10000 }; |
| 2096 | static const int shiftc[] = { 0, 18, 12, 6, 0 }; |
| 2097 | static const int shifte[] = { 0, 6, 4, 2, 0 }; |
| 2098 | int len = lengths[*(const unsigned char*)in_text >> 3]; |
| 2099 | int wanted = len + (len ? 0 : 1); |
| 2100 | |
| 2101 | if (in_text_end == NULL) |
| 2102 | in_text_end = in_text + wanted; // Max length, nulls will be taken into account. |
| 2103 | |
| 2104 | // Copy at most 'len' bytes, stop copying at 0 or past in_text_end. Branch predictor does a good job here, |
| 2105 | // so it is fast even with excessive branching. |
| 2106 | unsigned char s[4]; |
| 2107 | s[0] = in_text + 0 < in_text_end ? in_text[0] : 0; |
| 2108 | s[1] = in_text + 1 < in_text_end ? in_text[1] : 0; |
| 2109 | s[2] = in_text + 2 < in_text_end ? in_text[2] : 0; |
| 2110 | s[3] = in_text + 3 < in_text_end ? in_text[3] : 0; |
| 2111 | |
| 2112 | // Assume a four-byte character and load four bytes. Unused bits are shifted out. |
| 2113 | *out_char = (uint32_t)(s[0] & masks[len]) << 18; |
| 2114 | *out_char |= (uint32_t)(s[1] & 0x3f) << 12; |
| 2115 | *out_char |= (uint32_t)(s[2] & 0x3f) << 6; |
| 2116 | *out_char |= (uint32_t)(s[3] & 0x3f) << 0; |
| 2117 | *out_char >>= shiftc[len]; |
| 2118 | |
| 2119 | // Accumulate the various error conditions. |
| 2120 | int e = 0; |
| 2121 | e = (*out_char < mins[len]) << 6; // non-canonical encoding |
| 2122 | e |= ((*out_char >> 11) == 0x1b) << 7; // surrogate half? |
| 2123 | e |= (*out_char > IM_UNICODE_CODEPOINT_MAX) << 8; // out of range? |
| 2124 | e |= (s[1] & 0xc0) >> 2; |
| 2125 | e |= (s[2] & 0xc0) >> 4; |
| 2126 | e |= (s[3]) >> 6; |
| 2127 | e ^= 0x2a; // top two bits of each tail byte correct? |
| 2128 | e >>= shifte[len]; |
| 2129 | |
| 2130 | if (e) |
| 2131 | { |
| 2132 | // No bytes are consumed when *in_text == 0 || in_text == in_text_end. |
| 2133 | // One byte is consumed in case of invalid first byte of in_text. |
| 2134 | // All available bytes (at most `len` bytes) are consumed on incomplete/invalid second to last bytes. |
| 2135 | // Invalid or incomplete input may consume less bytes than wanted, therefore every byte has to be inspected in s. |
| 2136 | wanted = ImMin(wanted, !!s[0] + !!s[1] + !!s[2] + !!s[3]); |
| 2137 | *out_char = IM_UNICODE_CODEPOINT_INVALID; |
| 2138 | } |
| 2139 | |
| 2140 | return wanted; |
| 2141 | } |
| 2142 | |
| 2143 | int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining) |
no test coverage detected