From 19a58745c9db8b984d72f6634a1307e2f2d39c00 Mon Sep 17 00:00:00 2001 From: sfan5 Date: Tue, 27 Aug 2024 13:51:02 +0200 Subject: [PATCH] Avoid copies when working with EnrichedString --- src/irrlicht_changes/CGUITTFont.cpp | 7 +++-- src/irrlicht_changes/static_text.h | 4 +-- src/util/enriched_string.cpp | 24 +++++----------- src/util/enriched_string.h | 23 +++++++++------ src/util/string.cpp | 43 ++++++++++++++--------------- src/util/string.h | 6 ++-- 6 files changed, 53 insertions(+), 54 deletions(-) diff --git a/src/irrlicht_changes/CGUITTFont.cpp b/src/irrlicht_changes/CGUITTFont.cpp index 40d2bb405..4f5f52b4e 100644 --- a/src/irrlicht_changes/CGUITTFont.cpp +++ b/src/irrlicht_changes/CGUITTFont.cpp @@ -513,12 +513,15 @@ void CGUITTFont::setFontHinting(const bool enable, const bool enable_auto_hintin void CGUITTFont::draw(const core::stringw& text, const core::rect& position, video::SColor color, bool hcenter, bool vcenter, const core::rect* clip) { - draw(EnrichedString(std::wstring(text.c_str()), color), position, hcenter, vcenter, clip); + // Allow colors to work for strings that have passed through irrlicht by catching + // them here and converting them to enriched just before drawing. + EnrichedString s(text.c_str(), color); + draw(s, position, hcenter, vcenter, clip); } void CGUITTFont::draw(const EnrichedString &text, const core::rect& position, bool hcenter, bool vcenter, const core::rect* clip) { - const std::vector &colors = text.getColors(); + const auto &colors = text.getColors(); if (!Driver) return; diff --git a/src/irrlicht_changes/static_text.h b/src/irrlicht_changes/static_text.h index 636760f6c..15a976c74 100644 --- a/src/irrlicht_changes/static_text.h +++ b/src/irrlicht_changes/static_text.h @@ -61,7 +61,7 @@ namespace gui static irr::gui::IGUIStaticText *add( irr::gui::IGUIEnvironment *guienv, - const wchar_t *text, + std::wstring_view text, const core::rect< s32 > &rectangle, bool border = false, bool wordWrap = true, @@ -204,7 +204,7 @@ inline void setStaticText(irr::gui::IGUIStaticText *static_text, const EnrichedS } } -inline void setStaticText(irr::gui::IGUIStaticText *static_text, const wchar_t *text) +inline void setStaticText(irr::gui::IGUIStaticText *static_text, std::wstring_view text) { setStaticText(static_text, EnrichedString(text, static_text->getOverrideColor())); } diff --git a/src/util/enriched_string.cpp b/src/util/enriched_string.cpp index 04c5ef806..09baeac29 100644 --- a/src/util/enriched_string.cpp +++ b/src/util/enriched_string.cpp @@ -29,7 +29,7 @@ EnrichedString::EnrichedString() clear(); } -EnrichedString::EnrichedString(const std::wstring &string, +EnrichedString::EnrichedString(std::wstring_view string, const std::vector &colors) { clear(); @@ -37,18 +37,12 @@ EnrichedString::EnrichedString(const std::wstring &string, m_colors = colors; } -EnrichedString::EnrichedString(const std::wstring &s, const SColor &color) +EnrichedString::EnrichedString(std::wstring_view s, const SColor &color) { clear(); addAtEnd(translate_string(s), color); } -EnrichedString::EnrichedString(const wchar_t *str, const SColor &color) -{ - clear(); - addAtEnd(translate_string(std::wstring(str)), color); -} - void EnrichedString::clear() { m_string.clear(); @@ -59,19 +53,20 @@ void EnrichedString::clear() m_background = irr::video::SColor(0, 0, 0, 0); } -EnrichedString &EnrichedString::operator=(const wchar_t *str) +EnrichedString &EnrichedString::operator=(std::wstring_view str) { clear(); - addAtEnd(translate_string(std::wstring(str)), m_default_color); + addAtEnd(translate_string(str), m_default_color); return *this; } -void EnrichedString::addAtEnd(const std::wstring &s, SColor initial_color) +void EnrichedString::addAtEnd(std::wstring_view s, SColor initial_color) { SColor color(initial_color); bool use_default = (m_default_length == m_string.size() && color == m_default_color); + m_string.reserve(m_string.size() + s.size()); m_colors.reserve(m_colors.size() + s.size()); size_t i = 0; @@ -142,7 +137,7 @@ void EnrichedString::addCharNoColor(wchar_t c) if (m_colors.empty()) { m_colors.emplace_back(m_default_color); } else { - m_colors.push_back(m_colors[m_colors.size() - 1]); + m_colors.push_back(m_colors.back()); } } @@ -203,11 +198,6 @@ EnrichedString EnrichedString::substr(size_t pos, size_t len) const return str; } -const wchar_t *EnrichedString::c_str() const -{ - return m_string.c_str(); -} - const std::vector &EnrichedString::getColors() const { return m_colors; diff --git a/src/util/enriched_string.h b/src/util/enriched_string.h index 3d19eaed5..18fd967bc 100644 --- a/src/util/enriched_string.h +++ b/src/util/enriched_string.h @@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc., #pragma once #include +#include #include #include @@ -28,17 +29,15 @@ using namespace irr; class EnrichedString { public: EnrichedString(); - EnrichedString(const std::wstring &s, + EnrichedString(std::wstring_view s, const video::SColor &color = video::SColor(255, 255, 255, 255)); - EnrichedString(const wchar_t *str, - const video::SColor &color = video::SColor(255, 255, 255, 255)); - EnrichedString(const std::wstring &string, + EnrichedString(std::wstring_view string, const std::vector &colors); - EnrichedString &operator=(const wchar_t *str); + EnrichedString &operator=(std::wstring_view s); void clear(); - void addAtEnd(const std::wstring &s, video::SColor color); + void addAtEnd(std::wstring_view s, video::SColor color); // Adds the character source[i] at the end. // An EnrichedString should always be able to be copied @@ -51,9 +50,18 @@ public: EnrichedString getNextLine(size_t *pos) const; EnrichedString substr(size_t pos = 0, size_t len = std::string::npos) const; + EnrichedString operator+(const EnrichedString &other) const; void operator+=(const EnrichedString &other); - const wchar_t *c_str() const; + void operator+=(std::wstring_view other) + { + *this += EnrichedString(other); + } + + const wchar_t *c_str() const + { + return getString().c_str(); + } const std::vector &getColors() const; const std::wstring &getString() const; @@ -106,6 +114,5 @@ private: video::SColor m_default_color; video::SColor m_background; // This variable defines the length of the default-colored text. - // Change this to a std::vector if an "end coloring" tag is wanted. size_t m_default_length = 0; }; diff --git a/src/util/string.cpp b/src/util/string.cpp index 73d1d6907..74a360266 100644 --- a/src/util/string.cpp +++ b/src/util/string.cpp @@ -670,23 +670,26 @@ std::string wrap_rows(std::string_view from, unsigned row_len, bool has_color_co * before filling it again. */ -static void translate_all(const std::wstring &s, size_t &i, +static void translate_all(std::wstring_view s, size_t &i, Translations *translations, std::wstring &res); -static void translate_string(const std::wstring &s, Translations *translations, +static void translate_string(std::wstring_view s, Translations *translations, const std::wstring &textdomain, size_t &i, std::wstring &res) { - std::wostringstream output; std::vector args; int arg_number = 1; + + // Re-assemble the template. + std::wstring output; + output.reserve(s.length()); while (i < s.length()) { // Not an escape sequence: just add the character. if (s[i] != '\x1b') { - output.put(s[i]); + output += s[i]; // The character is a literal '@'; add it twice // so that it is not mistaken for an argument. if (s[i] == L'@') - output.put(L'@'); + output += L'@'; ++i; continue; } @@ -733,12 +736,12 @@ static void translate_string(const std::wstring &s, Translations *translations, args.push_back(arg); continue; } - output.put(L'@'); - output << arg_number; + output += L'@'; + output += std::to_wstring(arg_number); ++arg_number; std::wstring arg; translate_all(s, i, translations, arg); - args.push_back(arg); + args.push_back(std::move(arg)); } else { // This is an escape sequence *inside* the template string to translate itself. // This should not happen, show an error message. @@ -747,21 +750,18 @@ static void translate_string(const std::wstring &s, Translations *translations, } } - std::wstring toutput; // Translate the template. - if (translations != nullptr) - toutput = translations->getTranslation( - textdomain, output.str()); - else - toutput = output.str(); + const std::wstring &toutput = translations ? + translations->getTranslation(textdomain, output) : output; // Put back the arguments in the translated template. - std::wostringstream result; size_t j = 0; + res.clear(); + res.reserve(toutput.length()); while (j < toutput.length()) { // Normal character, add it to output and continue. if (toutput[j] != L'@' || j == toutput.length() - 1) { - result.put(toutput[j]); + res += toutput[j]; ++j; continue; } @@ -769,7 +769,7 @@ static void translate_string(const std::wstring &s, Translations *translations, ++j; // Literal escape for '@'. if (toutput[j] == L'@') { - result.put(L'@'); + res += L'@'; ++j; continue; } @@ -778,16 +778,15 @@ static void translate_string(const std::wstring &s, Translations *translations, int arg_index = toutput[j] - L'1'; ++j; if (0 <= arg_index && (size_t)arg_index < args.size()) { - result << args[arg_index]; + res += args[arg_index]; } else { // This is not allowed: show an error message errorstream << "Ignoring out-of-bounds argument escape sequence in translation" << std::endl; } } - res = result.str(); } -static void translate_all(const std::wstring &s, size_t &i, +static void translate_all(std::wstring_view s, size_t &i, Translations *translations, std::wstring &res) { res.clear(); @@ -849,7 +848,7 @@ static void translate_all(const std::wstring &s, size_t &i, } // Translate string server side -std::wstring translate_string(const std::wstring &s, Translations *translations) +std::wstring translate_string(std::wstring_view s, Translations *translations) { size_t i = 0; std::wstring res; @@ -858,7 +857,7 @@ std::wstring translate_string(const std::wstring &s, Translations *translations) } // Translate string client side -std::wstring translate_string(const std::wstring &s) +std::wstring translate_string(std::wstring_view s) { #ifdef SERVER return translate_string(s, nullptr); diff --git a/src/util/string.h b/src/util/string.h index ad3d09818..aae1167b6 100644 --- a/src/util/string.h +++ b/src/util/string.h @@ -631,11 +631,11 @@ std::vector > split(const std::basic_string &s, T delim) return tokens; } -std::wstring translate_string(const std::wstring &s, Translations *translations); +std::wstring translate_string(std::wstring_view s, Translations *translations); -std::wstring translate_string(const std::wstring &s); +std::wstring translate_string(std::wstring_view s); -inline std::wstring unescape_translate(const std::wstring &s) { +inline std::wstring unescape_translate(std::wstring_view s) { return unescape_enriched(translate_string(s)); }