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)
{
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)
{
const std::vector<video::SColor> &colors = text.getColors();
const auto &colors = text.getColors();
if (!Driver)
return;

@ -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()));
}

@ -29,7 +29,7 @@ EnrichedString::EnrichedString()
clear();
}
EnrichedString::EnrichedString(const std::wstring &string,
EnrichedString::EnrichedString(std::wstring_view string,
const std::vector<SColor> &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<SColor> &EnrichedString::getColors() const
{
return m_colors;

@ -20,6 +20,7 @@ with this program; if not, write to the Free Software Foundation, Inc.,
#pragma once
#include <string>
#include <string_view>
#include <vector>
#include <SColor.h>
@ -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<video::SColor> &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<video::SColor> &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;
};

@ -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<std::wstring> 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);

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