@@ -1959,6 +1959,152 @@ ImVec2 ImTriangleClosestPoint(const ImVec2& a, const ImVec2& b, const ImVec2& c,
1959
1959
// [SECTION] MISC HELPERS/UTILITIES (String, Format, Hash functions)
1960
1960
//-----------------------------------------------------------------------------
1961
1961
1962
+ #if defined IMGUI_ENABLE_AVX2_IMSTRLEN
1963
+ size_t ImStrlen(const char* str)
1964
+ {
1965
+ const size_t SIMD_LENGTH = 32;
1966
+ const size_t SIMD_LENGTH_MASK = SIMD_LENGTH - 1;
1967
+
1968
+ const unsigned char* begin = (unsigned char*)str;
1969
+ const unsigned char* ptr = begin;
1970
+
1971
+ // first page
1972
+ {
1973
+ const size_t PAGE_LENGTH = 4096;
1974
+ const size_t PAGE_LENGTH_MASK = PAGE_LENGTH - 1;
1975
+
1976
+ const unsigned char* page_end = (const unsigned char*)_andn_u64(PAGE_LENGTH_MASK, (uintptr_t)ptr + PAGE_LENGTH_MASK);
1977
+ const unsigned char* align_page_end = (const unsigned char*)(page_end - SIMD_LENGTH);
1978
+
1979
+ // if ptr is far the end of page
1980
+ if (ptr <= align_page_end)
1981
+ {
1982
+ __m256i target = _mm256_setzero_si256();
1983
+
1984
+ // if ptr not aligned, align ptr to SIMD_LENGTH
1985
+ if ((uintptr_t)ptr & SIMD_LENGTH_MASK)
1986
+ {
1987
+ __m256i chunk = _mm256_lddqu_si256((const __m256i*)ptr);
1988
+ int mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(chunk, target));
1989
+
1990
+ if (mask)
1991
+ return (uintptr_t)(ptr - begin + _tzcnt_u32(mask));
1992
+
1993
+ ptr = (const unsigned char*)_andn_u64(SIMD_LENGTH_MASK, (uintptr_t)ptr + SIMD_LENGTH_MASK);
1994
+ }
1995
+
1996
+ // main loop of first page
1997
+ for (; ptr <= align_page_end; ptr += SIMD_LENGTH)
1998
+ {
1999
+ __m256i chunk = _mm256_load_si256((const __m256i*)ptr);
2000
+ int mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(chunk, target));
2001
+
2002
+ if (mask)
2003
+ return (uintptr_t)(ptr - begin + _tzcnt_u32(mask));
2004
+
2005
+ _mm_prefetch((const char*)ptr + 1024, _MM_HINT_T0);
2006
+ }
2007
+ }
2008
+
2009
+ // if ptr is near the end of page
2010
+ for (; ptr < page_end; ptr++)
2011
+ {
2012
+ if (!(*ptr))
2013
+ return (uintptr_t)(ptr - begin);
2014
+ }
2015
+ }
2016
+
2017
+ __m256i target = _mm256_setzero_si256();
2018
+
2019
+ // main loop
2020
+ for (; ; ptr += SIMD_LENGTH)
2021
+ {
2022
+ __m256i chunk = _mm256_load_si256((const __m256i*)ptr);
2023
+ int mask = _mm256_movemask_epi8(_mm256_cmpeq_epi8(chunk, target));
2024
+
2025
+ if (mask)
2026
+ return (uintptr_t)(ptr - begin + _tzcnt_u32(mask));
2027
+
2028
+ _mm_prefetch((const char*)ptr + 1024, _MM_HINT_T0);
2029
+ }
2030
+ }
2031
+ #elif defined IMGUI_ENABLE_SSE_IMSTRLEN
2032
+ size_t ImStrlen(const char* str)
2033
+ {
2034
+ const size_t SIMD_LENGTH = 16;
2035
+ const size_t SIMD_LENGTH_MASK = SIMD_LENGTH - 1;
2036
+
2037
+ const unsigned char* begin = (unsigned char*)str;
2038
+ const unsigned char* ptr = begin;
2039
+ const unsigned char ch = '\0';
2040
+
2041
+ // first page
2042
+ {
2043
+ const size_t PAGE_LENGTH = 4096;
2044
+ const size_t PAGE_LENGTH_MASK = PAGE_LENGTH - 1;
2045
+
2046
+ const unsigned char* page_end = (const unsigned char*)(((uintptr_t)ptr + PAGE_LENGTH_MASK) & ~PAGE_LENGTH_MASK);
2047
+ const unsigned char* align_page_end = (const unsigned char*)(page_end - SIMD_LENGTH);
2048
+
2049
+ // if ptr is far the end of page
2050
+ if (ptr <= align_page_end)
2051
+ {
2052
+ __m128i target = _mm_set1_epi8(ch);
2053
+
2054
+ // if ptr not aligned, align ptr to SIMD_LENGTH
2055
+ if ((uintptr_t)ptr & SIMD_LENGTH_MASK)
2056
+ {
2057
+ __m128i chunk = _mm_lddqu_si128((const __m128i*)ptr);
2058
+ int mask = _mm_movemask_epi8(_mm_cmpeq_epi8(chunk, target));
2059
+
2060
+ if (mask)
2061
+ return (uintptr_t)(ptr + _tzcnt_u32(mask) - begin);
2062
+
2063
+ ptr = (const unsigned char*)(((uintptr_t)ptr + SIMD_LENGTH_MASK) & ~SIMD_LENGTH_MASK);
2064
+ }
2065
+
2066
+ // main loop of first page
2067
+ for (; ptr <= align_page_end; ptr += SIMD_LENGTH)
2068
+ {
2069
+ __m128i chunk = _mm_load_si128((const __m128i*)ptr);
2070
+ int mask = _mm_movemask_epi8(_mm_cmpeq_epi8(chunk, target));
2071
+
2072
+ if (mask)
2073
+ return (uintptr_t)(ptr + _tzcnt_u32(mask) - begin);
2074
+
2075
+ _mm_prefetch((const char*)ptr + 1024, _MM_HINT_T0);
2076
+ }
2077
+ }
2078
+
2079
+ // if ptr is near the end of page
2080
+ for (; ptr < page_end; ptr++)
2081
+ {
2082
+ if (*ptr == ch)
2083
+ return (uintptr_t)(ptr - begin);
2084
+ }
2085
+ }
2086
+
2087
+ __m128i target = _mm_set1_epi8(ch);
2088
+
2089
+ // main loop
2090
+ for (; ; ptr += SIMD_LENGTH)
2091
+ {
2092
+ __m128i chunk = _mm_load_si128((const __m128i*)ptr);
2093
+ int mask = _mm_movemask_epi8(_mm_cmpeq_epi8(chunk, target));
2094
+
2095
+ if (mask)
2096
+ return (uintptr_t)(ptr + _tzcnt_u32(mask) - begin);
2097
+
2098
+ _mm_prefetch((const char*)ptr + 1024, _MM_HINT_T0);
2099
+ }
2100
+ }
2101
+ #else
2102
+ size_t ImStrlen(const char* str)
2103
+ {
2104
+ return strlen(str);
2105
+ }
2106
+ #endif
2107
+
1962
2108
#if defined IMGUI_ENABLE_AVX2_IMMEMCHR
1963
2109
const void* ImMemchr(const void* buf, int val, size_t count)
1964
2110
{
@@ -2086,15 +2232,15 @@ void ImStrncpy(char* dst, const char* src, size_t count)
2086
2232
2087
2233
char* ImStrdup(const char* str)
2088
2234
{
2089
- size_t len = strlen (str);
2235
+ size_t len = ImStrlen (str);
2090
2236
void* buf = IM_ALLOC(len + 1);
2091
2237
return (char*)memcpy(buf, (const void*)str, len + 1);
2092
2238
}
2093
2239
2094
2240
char* ImStrdupcpy(char* dst, size_t* p_dst_size, const char* src)
2095
2241
{
2096
- size_t dst_buf_size = p_dst_size ? *p_dst_size : strlen (dst) + 1;
2097
- size_t src_size = strlen (src) + 1;
2242
+ size_t dst_buf_size = p_dst_size ? *p_dst_size : ImStrlen (dst) + 1;
2243
+ size_t src_size = ImStrlen (src) + 1;
2098
2244
if (dst_buf_size < src_size)
2099
2245
{
2100
2246
IM_FREE(dst);
@@ -2128,7 +2274,7 @@ const char* ImStreolRange(const char* str, const char* str_end)
2128
2274
2129
2275
const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find beginning-of-line
2130
2276
{
2131
- IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + strlen (buf_begin));
2277
+ IM_ASSERT_PARANOID(buf_mid_line >= buf_begin && buf_mid_line <= buf_begin + ImStrlen (buf_begin));
2132
2278
while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
2133
2279
buf_mid_line--;
2134
2280
return buf_mid_line;
@@ -2137,7 +2283,7 @@ const char* ImStrbol(const char* buf_mid_line, const char* buf_begin) // find be
2137
2283
const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end)
2138
2284
{
2139
2285
if (!needle_end)
2140
- needle_end = needle + strlen (needle);
2286
+ needle_end = needle + ImStrlen (needle);
2141
2287
2142
2288
const char un0 = (char)ImToUpper(*needle);
2143
2289
while ((!haystack_end && *haystack) || (haystack_end && haystack < haystack_end))
@@ -2258,7 +2404,7 @@ void ImFormatStringToTempBufferV(const char** out_buf, const char** out_buf_end,
2258
2404
if (buf == NULL)
2259
2405
buf = "(null)";
2260
2406
*out_buf = buf;
2261
- if (out_buf_end) { *out_buf_end = buf + strlen (buf); }
2407
+ if (out_buf_end) { *out_buf_end = buf + ImStrlen (buf); }
2262
2408
}
2263
2409
else if (fmt[0] == '%' && fmt[1] == '.' && fmt[2] == '*' && fmt[3] == 's' && fmt[4] == 0)
2264
2410
{
@@ -2667,7 +2813,7 @@ const char* ImTextFindPreviousUtf8Codepoint(const char* in_text_start, const cha
2667
2813
int ImTextCountLines(const char* in_text, const char* in_text_end)
2668
2814
{
2669
2815
if (in_text_end == NULL)
2670
- in_text_end = in_text + strlen (in_text); // FIXME-OPT: Not optimal approach, discourage use for now.
2816
+ in_text_end = in_text + ImStrlen (in_text); // FIXME-OPT: Not optimal approach, discourage use for now.
2671
2817
int count = 0;
2672
2818
while (in_text < in_text_end)
2673
2819
{
@@ -2952,7 +3098,7 @@ void ImGuiTextFilter::ImGuiTextRange::split(char separator, ImVector<ImGuiTextRa
2952
3098
void ImGuiTextFilter::Build()
2953
3099
{
2954
3100
Filters.resize(0);
2955
- ImGuiTextRange input_range(InputBuf, InputBuf + strlen (InputBuf));
3101
+ ImGuiTextRange input_range(InputBuf, InputBuf + ImStrlen (InputBuf));
2956
3102
input_range.split(',', &Filters);
2957
3103
2958
3104
CountGrep = 0;
@@ -3020,7 +3166,7 @@ char ImGuiTextBuffer::EmptyString[1] = { 0 };
3020
3166
3021
3167
void ImGuiTextBuffer::append(const char* str, const char* str_end)
3022
3168
{
3023
- int len = str_end ? (int)(str_end - str) : (int)strlen (str);
3169
+ int len = str_end ? (int)(str_end - str) : (int)ImStrlen (str);
3024
3170
3025
3171
// Add zero-terminator the first time
3026
3172
const int write_off = (Buf.Size != 0) ? Buf.Size : 1;
@@ -3703,7 +3849,7 @@ void ImGui::RenderText(ImVec2 pos, const char* text, const char* text_end, bool
3703
3849
else
3704
3850
{
3705
3851
if (!text_end)
3706
- text_end = text + strlen (text); // FIXME-OPT
3852
+ text_end = text + ImStrlen (text); // FIXME-OPT
3707
3853
text_display_end = text_end;
3708
3854
}
3709
3855
@@ -3721,7 +3867,7 @@ void ImGui::RenderTextWrapped(ImVec2 pos, const char* text, const char* text_end
3721
3867
ImGuiWindow* window = g.CurrentWindow;
3722
3868
3723
3869
if (!text_end)
3724
- text_end = text + strlen (text); // FIXME-OPT
3870
+ text_end = text + ImStrlen (text); // FIXME-OPT
3725
3871
3726
3872
if (text != text_end)
3727
3873
{
@@ -4394,7 +4540,7 @@ ImGuiWindow::ImGuiWindow(ImGuiContext* ctx, const char* name) : DrawListInst(NUL
4394
4540
memset(this, 0, sizeof(*this));
4395
4541
Ctx = ctx;
4396
4542
Name = ImStrdup(name);
4397
- NameBufLen = (int)strlen (name) + 1;
4543
+ NameBufLen = (int)ImStrlen (name) + 1;
4398
4544
ID = ImHashStr(name);
4399
4545
IDStack.push_back(ID);
4400
4546
MoveId = GetID("#MOVE");
@@ -8925,7 +9071,7 @@ const char* ImGui::GetKeyChordName(ImGuiKeyChord key_chord)
8925
9071
(key != ImGuiKey_None || key_chord == ImGuiKey_None) ? GetKeyName(key) : "");
8926
9072
size_t len;
8927
9073
if (key == ImGuiKey_None && key_chord != 0)
8928
- if ((len = strlen (g.TempKeychordName)) != 0) // Remove trailing '+'
9074
+ if ((len = ImStrlen (g.TempKeychordName)) != 0) // Remove trailing '+'
8929
9075
g.TempKeychordName[len - 1] = 0;
8930
9076
return g.TempKeychordName;
8931
9077
}
@@ -14215,7 +14361,7 @@ bool ImGui::SetDragDropPayload(const char* type, const void* data, size_t data_s
14215
14361
cond = ImGuiCond_Always;
14216
14362
14217
14363
IM_ASSERT(type != NULL);
14218
- IM_ASSERT(strlen (type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
14364
+ IM_ASSERT(ImStrlen (type) < IM_ARRAYSIZE(payload.DataType) && "Payload type can be at most 32 characters long");
14219
14365
IM_ASSERT((data != NULL && data_size > 0) || (data == NULL && data_size == 0));
14220
14366
IM_ASSERT(cond == ImGuiCond_Always || cond == ImGuiCond_Once);
14221
14367
IM_ASSERT(payload.SourceId != 0); // Not called between BeginDragDropSource() and EndDragDropSource()
@@ -14459,7 +14605,7 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
14459
14605
}
14460
14606
14461
14607
if (prefix)
14462
- LogRenderedText(ref_pos, prefix, prefix + strlen (prefix)); // Calculate end ourself to ensure "##" are included here.
14608
+ LogRenderedText(ref_pos, prefix, prefix + ImStrlen (prefix)); // Calculate end ourself to ensure "##" are included here.
14463
14609
14464
14610
// Re-adjust padding if we have popped out of our starting depth
14465
14611
if (g.LogDepthRef > window->DC.TreeDepth)
@@ -14492,7 +14638,7 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
14492
14638
}
14493
14639
14494
14640
if (suffix)
14495
- LogRenderedText(ref_pos, suffix, suffix + strlen (suffix));
14641
+ LogRenderedText(ref_pos, suffix, suffix + ImStrlen (suffix));
14496
14642
}
14497
14643
14498
14644
// Start logging/capturing text output
@@ -14758,7 +14904,7 @@ void ImGui::LoadIniSettingsFromMemory(const char* ini_data, size_t ini_size)
14758
14904
// For user convenience, we allow passing a non zero-terminated string (hence the ini_size parameter).
14759
14905
// For our convenience and to make the code simpler, we'll also write zero-terminators within the buffer. So let's create a writable copy..
14760
14906
if (ini_size == 0)
14761
- ini_size = strlen (ini_data);
14907
+ ini_size = ImStrlen (ini_data);
14762
14908
g.SettingsIniData.Buf.resize((int)ini_size + 1);
14763
14909
char* const buf = g.SettingsIniData.Buf.Data;
14764
14910
char* const buf_end = buf + ini_size;
@@ -14859,7 +15005,7 @@ ImGuiWindowSettings* ImGui::CreateNewWindowSettings(const char* name)
14859
15005
if (const char* p = strstr(name, "###"))
14860
15006
name = p;
14861
15007
}
14862
- const size_t name_len = strlen (name);
15008
+ const size_t name_len = ImStrlen (name);
14863
15009
14864
15010
// Allocate chunk
14865
15011
const size_t chunk_size = sizeof(ImGuiWindowSettings) + name_len + 1;
@@ -15151,7 +15297,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext*, const char* t
15151
15297
if (!main_clipboard)
15152
15298
PasteboardCreate(kPasteboardClipboard, &main_clipboard);
15153
15299
PasteboardClear(main_clipboard);
15154
- CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, strlen (text));
15300
+ CFDataRef cf_data = CFDataCreate(kCFAllocatorDefault, (const UInt8*)text, ImStrlen (text));
15155
15301
if (cf_data)
15156
15302
{
15157
15303
PasteboardPutItemFlavor(main_clipboard, (PasteboardItemID)1, CFSTR("public.utf8-plain-text"), cf_data, 0);
@@ -15205,7 +15351,7 @@ static void Platform_SetClipboardTextFn_DefaultImpl(ImGuiContext* ctx, const cha
15205
15351
{
15206
15352
ImGuiContext& g = *ctx;
15207
15353
g.ClipboardHandlerData.clear();
15208
- const char* text_end = text + strlen (text);
15354
+ const char* text_end = text + ImStrlen (text);
15209
15355
g.ClipboardHandlerData.resize((int)(text_end - text) + 1);
15210
15356
memcpy(&g.ClipboardHandlerData[0], text, (size_t)(text_end - text));
15211
15357
g.ClipboardHandlerData[(int)(text_end - text)] = 0;
@@ -16975,7 +17121,7 @@ void ImGui::DebugHookIdInfo(ImGuiID id, ImGuiDataType data_type, const void* dat
16975
17121
ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%d", (int)(intptr_t)data_id);
16976
17122
break;
16977
17123
case ImGuiDataType_String:
16978
- ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)strlen ((const char*)data_id), (const char*)data_id);
17124
+ ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "%.*s", data_id_end ? (int)((const char*)data_id_end - (const char*)data_id) : (int)ImStrlen ((const char*)data_id), (const char*)data_id);
16979
17125
break;
16980
17126
case ImGuiDataType_Pointer:
16981
17127
ImFormatString(info->Desc, IM_ARRAYSIZE(info->Desc), "(void*)0x%p", data_id);
0 commit comments