TextUnformatted: Using memchr(), fixed not properly testing for text_end bound + comments.

Internals: Added ImStreolRange() + used in LogRenderedText() + comments.
This commit is contained in:
omar 2018-10-11 11:48:40 +02:00
parent d02b11dfbd
commit cf0afb48ac
4 changed files with 29 additions and 32 deletions

View File

@ -56,6 +56,8 @@ Other Changes:
- BeginChild(): Fixed BeginChild(const char*, ...) variation erroneously not applying the ID stack - BeginChild(): Fixed BeginChild(const char*, ...) variation erroneously not applying the ID stack
to the provided string to uniquely identify the child window. This was undoing an intentional change to the provided string to uniquely identify the child window. This was undoing an intentional change
introduced in 1.50 and broken in 1.60. (#1698, #894, #713). introduced in 1.50 and broken in 1.60. (#1698, #894, #713).
- TextUnformatted(): Fixed a case where large-text path would read bytes past the text_end marker depending
on the position of new lines in the buffer (it wasn't affecting the output but still not the right thing to do!)
- BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f. - BeginMenu(): Fixed menu popup horizontal offset being off the item in the menu bar when WindowPadding=0.0f.
- ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different. - ArrowButton(): Fixed arrow shape being horizontally misaligned by (FramePadding.y-FramePadding.x) if they are different.
- Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143) - Drag and Drop: Added GetDragDropPayload() to peek directly into the payload (if any) from anywhere. (#143)

View File

@ -1203,10 +1203,8 @@ char* ImStrdup(const char *str)
const char* ImStrchrRange(const char* str, const char* str_end, char c) const char* ImStrchrRange(const char* str, const char* str_end, char c)
{ {
for ( ; str < str_end; str++) const char* p = (const char*)memchr(str, (int)c, str_end - str);
if (*str == c) return p;
return str;
return NULL;
} }
int ImStrlenW(const ImWchar* str) int ImStrlenW(const ImWchar* str)
@ -1216,6 +1214,13 @@ int ImStrlenW(const ImWchar* str)
return n; return n;
} }
// Find end-of-line. Return pointer will point to either first \n, either str_end.
const char* ImStreolRange(const char* str, const char* str_end)
{
const char* p = (const char*)memchr(str, '\n', str_end - str);
return p ? p : str_end;
}
const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line const ImWchar* ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin) // find beginning-of-line
{ {
while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n') while (buf_mid_line > buf_begin && buf_mid_line[-1] != '\n')
@ -8343,29 +8348,17 @@ void ImGui::LogRenderedText(const ImVec2* ref_pos, const char* text, const char*
for (;;) for (;;)
{ {
// Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry. // Split the string. Each new line (after a '\n') is followed by spacing corresponding to the current depth of our log entry.
const char* line_end = text_remaining; const char* line_start = text_remaining;
while (line_end < text_end) const char* line_end = ImStreolRange(line_start, text_end);
if (*line_end == '\n') const bool is_first_line = (line_start == text);
break; const bool is_last_line = (line_end == text_end);
else if (!is_last_line || (line_start != line_end))
line_end++;
if (line_end >= text_end)
line_end = NULL;
const bool is_first_line = (text == text_remaining);
bool is_last_line = false;
if (line_end == NULL)
{ {
is_last_line = true; const int char_count = (int)(line_end - line_start);
line_end = text_end;
}
if (line_end != NULL && !(is_last_line && (line_end - text_remaining)==0))
{
const int char_count = (int)(line_end - text_remaining);
if (log_new_line || !is_first_line) if (log_new_line || !is_first_line)
LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, text_remaining); LogText(IM_NEWLINE "%*s%.*s", tree_depth*4, "", char_count, line_start);
else else
LogText(" %.*s", char_count, text_remaining); LogText(" %.*s", char_count, line_start);
} }
if (is_last_line) if (is_last_line)

View File

@ -141,7 +141,8 @@ IMGUI_API void ImStrncpy(char* dst, const char* src, size_t count);
IMGUI_API char* ImStrdup(const char* str); IMGUI_API char* ImStrdup(const char* str);
IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c); IMGUI_API const char* ImStrchrRange(const char* str_begin, const char* str_end, char c);
IMGUI_API int ImStrlenW(const ImWchar* str); IMGUI_API int ImStrlenW(const ImWchar* str);
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line IMGUI_API const char* ImStreolRange(const char* str, const char* str_end); // End end-of-line
IMGUI_API const ImWchar*ImStrbolW(const ImWchar* buf_mid_line, const ImWchar* buf_begin); // Find beginning-of-line
IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end); IMGUI_API const char* ImStristr(const char* haystack, const char* haystack_end, const char* needle, const char* needle_end);
IMGUI_API void ImStrTrimBlanks(char* str); IMGUI_API void ImStrTrimBlanks(char* str);
IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3); IMGUI_API int ImFormatString(char* buf, size_t buf_size, const char* fmt, ...) IM_FMTARGS(3);

View File

@ -133,8 +133,9 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
{ {
// Long text! // Long text!
// Perform manual coarse clipping to optimize for long multi-line text // Perform manual coarse clipping to optimize for long multi-line text
// From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled. // - From this point we will only compute the width of lines that are visible. Optimization only available when word-wrapping is disabled.
// We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line. // - We also don't vertically center the text within the line full height, which is unlikely to matter because we are likely the biggest and only item on the line.
// - We use memchr(), pay attention that well optimized versions of those str/mem functions are much faster than a casually written loop.
const char* line = text; const char* line = text;
const float line_height = GetTextLineHeight(); const float line_height = GetTextLineHeight();
const ImRect clip_rect = window->ClipRect; const ImRect clip_rect = window->ClipRect;
@ -153,7 +154,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
int lines_skipped = 0; int lines_skipped = 0;
while (line < text_end && lines_skipped < lines_skippable) while (line < text_end && lines_skipped < lines_skippable)
{ {
const char* line_end = strchr(line, '\n'); const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end) if (!line_end)
line_end = text_end; line_end = text_end;
line = line_end + 1; line = line_end + 1;
@ -169,15 +170,15 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height)); ImRect line_rect(pos, pos + ImVec2(FLT_MAX, line_height));
while (line < text_end) while (line < text_end)
{ {
const char* line_end = strchr(line, '\n');
if (IsClippedEx(line_rect, 0, false)) if (IsClippedEx(line_rect, 0, false))
break; break;
const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end)
line_end = text_end;
const ImVec2 line_size = CalcTextSize(line, line_end, false); const ImVec2 line_size = CalcTextSize(line, line_end, false);
text_size.x = ImMax(text_size.x, line_size.x); text_size.x = ImMax(text_size.x, line_size.x);
RenderText(pos, line, line_end, false); RenderText(pos, line, line_end, false);
if (!line_end)
line_end = text_end;
line = line_end + 1; line = line_end + 1;
line_rect.Min.y += line_height; line_rect.Min.y += line_height;
line_rect.Max.y += line_height; line_rect.Max.y += line_height;
@ -188,7 +189,7 @@ void ImGui::TextUnformatted(const char* text, const char* text_end)
int lines_skipped = 0; int lines_skipped = 0;
while (line < text_end) while (line < text_end)
{ {
const char* line_end = strchr(line, '\n'); const char* line_end = (const char*)memchr(line, '\n', text_end - line);
if (!line_end) if (!line_end)
line_end = text_end; line_end = text_end;
line = line_end + 1; line = line_end + 1;