MCPcopy Create free account
hub / github.com/KebsCS/KBotExt / ImTextCharFromUtf8

Function ImTextCharFromUtf8

KBotExt/imgui/imgui.cpp:2086–2141  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

2084//-----------------------------------------------------------------------------
2085
2086IM_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.
2091int 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
2143int ImTextStrFromUtf8(ImWchar* buf, int buf_size, const char* in_text, const char* in_text_end, const char** in_text_remaining)

Callers 10

ImTextStrFromUtf8Function · 0.85
ImTextCountCharsFromUtf8Function · 0.85
DebugTextEncodingMethod · 0.85
AddTextMethod · 0.85
CalcWordWrapPositionAMethod · 0.85
CalcTextSizeAMethod · 0.85
RenderTextMethod · 0.85
InputTextExMethod · 0.85

Calls 1

ImMinFunction · 0.85

Tested by

no test coverage detected