Avoid copies when working with EnrichedString

This commit is contained in:
sfan5 2024-08-27 13:51:02 +02:00
parent fa4529b4f1
commit 19a58745c9
6 changed files with 53 additions and 54 deletions

@ -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<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* clip) void CGUITTFont::draw(const core::stringw& text, const core::rect<s32>& position, video::SColor color, bool hcenter, bool vcenter, const core::rect<s32>* 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<s32>& position, bool hcenter, bool vcenter, const core::rect<s32>* clip) void CGUITTFont::draw(const EnrichedString &text, const core::rect<s32>& position, bool hcenter, bool vcenter, const core::rect<s32>* clip)
{ {
const std::vector<video::SColor> &colors = text.getColors(); const auto &colors = text.getColors();
if (!Driver) if (!Driver)
return; return;

@ -61,7 +61,7 @@ namespace gui
static irr::gui::IGUIStaticText *add( static irr::gui::IGUIStaticText *add(
irr::gui::IGUIEnvironment *guienv, irr::gui::IGUIEnvironment *guienv,
const wchar_t *text, std::wstring_view text,
const core::rect< s32 > &rectangle, const core::rect< s32 > &rectangle,
bool border = false, bool border = false,
bool wordWrap = true, 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())); setStaticText(static_text, EnrichedString(text, static_text->getOverrideColor()));
} }

@ -29,7 +29,7 @@ EnrichedString::EnrichedString()
clear(); clear();
} }
EnrichedString::EnrichedString(const std::wstring &string, EnrichedString::EnrichedString(std::wstring_view string,
const std::vector<SColor> &colors) const std::vector<SColor> &colors)
{ {
clear(); clear();
@ -37,18 +37,12 @@ EnrichedString::EnrichedString(const std::wstring &string,
m_colors = colors; m_colors = colors;
} }
EnrichedString::EnrichedString(const std::wstring &s, const SColor &color) EnrichedString::EnrichedString(std::wstring_view s, const SColor &color)
{ {
clear(); clear();
addAtEnd(translate_string(s), color); 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() void EnrichedString::clear()
{ {
m_string.clear(); m_string.clear();
@ -59,19 +53,20 @@ void EnrichedString::clear()
m_background = irr::video::SColor(0, 0, 0, 0); m_background = irr::video::SColor(0, 0, 0, 0);
} }
EnrichedString &EnrichedString::operator=(const wchar_t *str) EnrichedString &EnrichedString::operator=(std::wstring_view str)
{ {
clear(); clear();
addAtEnd(translate_string(std::wstring(str)), m_default_color); addAtEnd(translate_string(str), m_default_color);
return *this; 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); SColor color(initial_color);
bool use_default = (m_default_length == m_string.size() && bool use_default = (m_default_length == m_string.size() &&
color == m_default_color); color == m_default_color);
m_string.reserve(m_string.size() + s.size());
m_colors.reserve(m_colors.size() + s.size()); m_colors.reserve(m_colors.size() + s.size());
size_t i = 0; size_t i = 0;
@ -142,7 +137,7 @@ void EnrichedString::addCharNoColor(wchar_t c)
if (m_colors.empty()) { if (m_colors.empty()) {
m_colors.emplace_back(m_default_color); m_colors.emplace_back(m_default_color);
} else { } 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; return str;
} }
const wchar_t *EnrichedString::c_str() const
{
return m_string.c_str();
}
const std::vector<SColor> &EnrichedString::getColors() const const std::vector<SColor> &EnrichedString::getColors() const
{ {
return m_colors; return m_colors;

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once #pragma once
#include <string> #include <string>
#include <string_view>
#include <vector> #include <vector>
#include <SColor.h> #include <SColor.h>
@ -28,17 +29,15 @@ using namespace irr;
class EnrichedString { class EnrichedString {
public: public:
EnrichedString(); EnrichedString();
EnrichedString(const std::wstring &s, EnrichedString(std::wstring_view s,
const video::SColor &color = video::SColor(255, 255, 255, 255)); const video::SColor &color = video::SColor(255, 255, 255, 255));
EnrichedString(const wchar_t *str, EnrichedString(std::wstring_view string,
const video::SColor &color = video::SColor(255, 255, 255, 255));
EnrichedString(const std::wstring &string,
const std::vector<video::SColor> &colors); const std::vector<video::SColor> &colors);
EnrichedString &operator=(const wchar_t *str); EnrichedString &operator=(std::wstring_view s);
void clear(); 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. // Adds the character source[i] at the end.
// An EnrichedString should always be able to be copied // An EnrichedString should always be able to be copied
@ -51,9 +50,18 @@ public:
EnrichedString getNextLine(size_t *pos) const; EnrichedString getNextLine(size_t *pos) const;
EnrichedString substr(size_t pos = 0, size_t len = std::string::npos) const; EnrichedString substr(size_t pos = 0, size_t len = std::string::npos) const;
EnrichedString operator+(const EnrichedString &other) const; EnrichedString operator+(const EnrichedString &other) const;
void operator+=(const EnrichedString &other); 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<video::SColor> &getColors() const; const std::vector<video::SColor> &getColors() const;
const std::wstring &getString() const; const std::wstring &getString() const;
@ -106,6 +114,5 @@ private:
video::SColor m_default_color; video::SColor m_default_color;
video::SColor m_background; video::SColor m_background;
// This variable defines the length of the default-colored text. // 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; size_t m_default_length = 0;
}; };

@ -670,23 +670,26 @@ std::string wrap_rows(std::string_view from, unsigned row_len, bool has_color_co
* before filling it again. * 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); 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) const std::wstring &textdomain, size_t &i, std::wstring &res)
{ {
std::wostringstream output;
std::vector<std::wstring> args; std::vector<std::wstring> args;
int arg_number = 1; int arg_number = 1;
// Re-assemble the template.
std::wstring output;
output.reserve(s.length());
while (i < s.length()) { while (i < s.length()) {
// Not an escape sequence: just add the character. // Not an escape sequence: just add the character.
if (s[i] != '\x1b') { if (s[i] != '\x1b') {
output.put(s[i]); output += s[i];
// The character is a literal '@'; add it twice // The character is a literal '@'; add it twice
// so that it is not mistaken for an argument. // so that it is not mistaken for an argument.
if (s[i] == L'@') if (s[i] == L'@')
output.put(L'@'); output += L'@';
++i; ++i;
continue; continue;
} }
@ -733,12 +736,12 @@ static void translate_string(const std::wstring &s, Translations *translations,
args.push_back(arg); args.push_back(arg);
continue; continue;
} }
output.put(L'@'); output += L'@';
output << arg_number; output += std::to_wstring(arg_number);
++arg_number; ++arg_number;
std::wstring arg; std::wstring arg;
translate_all(s, i, translations, arg); translate_all(s, i, translations, arg);
args.push_back(arg); args.push_back(std::move(arg));
} else { } else {
// This is an escape sequence *inside* the template string to translate itself. // This is an escape sequence *inside* the template string to translate itself.
// This should not happen, show an error message. // 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. // Translate the template.
if (translations != nullptr) const std::wstring &toutput = translations ?
toutput = translations->getTranslation( translations->getTranslation(textdomain, output) : output;
textdomain, output.str());
else
toutput = output.str();
// Put back the arguments in the translated template. // Put back the arguments in the translated template.
std::wostringstream result;
size_t j = 0; size_t j = 0;
res.clear();
res.reserve(toutput.length());
while (j < toutput.length()) { while (j < toutput.length()) {
// Normal character, add it to output and continue. // Normal character, add it to output and continue.
if (toutput[j] != L'@' || j == toutput.length() - 1) { if (toutput[j] != L'@' || j == toutput.length() - 1) {
result.put(toutput[j]); res += toutput[j];
++j; ++j;
continue; continue;
} }
@ -769,7 +769,7 @@ static void translate_string(const std::wstring &s, Translations *translations,
++j; ++j;
// Literal escape for '@'. // Literal escape for '@'.
if (toutput[j] == L'@') { if (toutput[j] == L'@') {
result.put(L'@'); res += L'@';
++j; ++j;
continue; continue;
} }
@ -778,16 +778,15 @@ static void translate_string(const std::wstring &s, Translations *translations,
int arg_index = toutput[j] - L'1'; int arg_index = toutput[j] - L'1';
++j; ++j;
if (0 <= arg_index && (size_t)arg_index < args.size()) { if (0 <= arg_index && (size_t)arg_index < args.size()) {
result << args[arg_index]; res += args[arg_index];
} else { } else {
// This is not allowed: show an error message // This is not allowed: show an error message
errorstream << "Ignoring out-of-bounds argument escape sequence in translation" << std::endl; 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) Translations *translations, std::wstring &res)
{ {
res.clear(); res.clear();
@ -849,7 +848,7 @@ static void translate_all(const std::wstring &s, size_t &i,
} }
// Translate string server side // 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; size_t i = 0;
std::wstring res; std::wstring res;
@ -858,7 +857,7 @@ std::wstring translate_string(const std::wstring &s, Translations *translations)
} }
// Translate string client side // Translate string client side
std::wstring translate_string(const std::wstring &s) std::wstring translate_string(std::wstring_view s)
{ {
#ifdef SERVER #ifdef SERVER
return translate_string(s, nullptr); return translate_string(s, nullptr);

@ -631,11 +631,11 @@ std::vector<std::basic_string<T> > split(const std::basic_string<T> &s, T delim)
return tokens; 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)); return unescape_enriched(translate_string(s));
} }