diff --git a/src/console.cpp b/src/console.cpp index d09f6fc109..675b8bbcb5 100644 --- a/src/console.cpp +++ b/src/console.cpp @@ -103,7 +103,7 @@ void IConsolePrint(TextColour colour_code, const std::string &string) /* Create a copy of the string, strip it of colours and invalid * characters and (when applicable) assign it to the console buffer */ - std::string str = StrMakeValid(string, SVS_NONE); + std::string str = StrMakeValid(string, {}); if (_network_dedicated) { NetworkAdminConsole("console", str); diff --git a/src/network/core/packet.h b/src/network/core/packet.h index 2105bf24a9..d1ffa33c80 100644 --- a/src/network/core/packet.h +++ b/src/network/core/packet.h @@ -87,7 +87,7 @@ public: uint64_t Recv_uint64(); std::vector Recv_buffer(); size_t Recv_bytes(std::span span); - std::string Recv_string(size_t length, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); + std::string Recv_string(size_t length, StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark); size_t RemainingBytesToTransfer() const; diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index e4f65308f4..092ac1811f 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -441,7 +441,11 @@ template static inline void SanitizeSingleStringHelper([[maybe_unused]] CommandFlags cmd_flags, T &data) { if constexpr (std::is_same_v) { - StrMakeValidInPlace(data, (!_network_server && cmd_flags.Test(CommandFlag::StrCtrl)) ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK); + if (!_network_server && cmd_flags.Test(CommandFlag::StrCtrl)) { + StrMakeValidInPlace(data, {StringValidationSetting::AllowControlCode, StringValidationSetting::ReplaceWithQuestionMark}); + } else { + StrMakeValidInPlace(data, {StringValidationSetting::ReplaceWithQuestionMark}); + } } } diff --git a/src/network/network_content.cpp b/src/network/network_content.cpp index ac0f70d683..4a347c6424 100644 --- a/src/network/network_content.cpp +++ b/src/network/network_content.cpp @@ -68,7 +68,7 @@ bool ClientNetworkContentSocketHandler::Receive_SERVER_INFO(Packet &p) ci->name = p.Recv_string(NETWORK_CONTENT_NAME_LENGTH); ci->version = p.Recv_string(NETWORK_CONTENT_VERSION_LENGTH); ci->url = p.Recv_string(NETWORK_CONTENT_URL_LENGTH); - ci->description = p.Recv_string(NETWORK_CONTENT_DESC_LENGTH, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE); + ci->description = p.Recv_string(NETWORK_CONTENT_DESC_LENGTH, {StringValidationSetting::ReplaceWithQuestionMark, StringValidationSetting::AllowNewline}); ci->unique_id = p.Recv_uint32(); p.Recv_bytes(ci->md5sum); diff --git a/src/newgrf_gui.cpp b/src/newgrf_gui.cpp index c838687d7b..9a36c269d2 100644 --- a/src/newgrf_gui.cpp +++ b/src/newgrf_gui.cpp @@ -1398,8 +1398,8 @@ private: /** Sort grfs by name. */ static bool NameSorter(const GRFConfig * const &a, const GRFConfig * const &b) { - std::string name_a = StrMakeValid(a->GetName(), SVS_NONE); // Make a copy without control codes. - std::string name_b = StrMakeValid(b->GetName(), SVS_NONE); // Make a copy without control codes. + std::string name_a = StrMakeValid(a->GetName(), {}); // Make a copy without control codes. + std::string name_b = StrMakeValid(b->GetName(), {}); // Make a copy without control codes. int i = StrNaturalCompare(name_a, name_b, true); // Sort by name (natural sorting). if (i != 0) return i < 0; diff --git a/src/news_gui.cpp b/src/news_gui.cpp index 51e51f748f..ab247fb7ae 100644 --- a/src/news_gui.cpp +++ b/src/news_gui.cpp @@ -1190,7 +1190,7 @@ void ShowLastNewsMessage() static void DrawNewsString(uint left, uint right, int y, TextColour colour, const NewsItem &ni) { /* Get the string, replaces newlines with spaces and remove control codes from the string. */ - std::string message = StrMakeValid(ni.GetStatusText(), SVS_REPLACE_TAB_CR_NL_WITH_SPACE); + std::string message = StrMakeValid(ni.GetStatusText(), StringValidationSetting::ReplaceTabCrNlWithSpace); /* Truncate and show string; postfixed by '...' if necessary */ DrawString(left, right, y, message, colour); diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index a50c077b31..6b0d349f6b 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1020,13 +1020,13 @@ static void SlStdString(void *ptr, VarType conv) SlReadString(*str, len); - StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK; + StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark; if ((conv & SLF_ALLOW_CONTROL) != 0) { - settings = settings | SVS_ALLOW_CONTROL_CODE; + settings.Set(StringValidationSetting::AllowControlCode); if (IsSavegameVersionBefore(SLV_ENCODED_STRING_FORMAT)) FixSCCEncoded(*str, IsSavegameVersionBefore(SLV_169)); } if ((conv & SLF_ALLOW_NEWLINE) != 0) { - settings = settings | SVS_ALLOW_NEWLINE; + settings.Set(StringValidationSetting::AllowNewline); } StrMakeValidInPlace(*str, settings); } diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index 8c3067c448..9a8cf7b226 100644 --- a/src/script/api/script_object.hpp +++ b/src/script/api/script_object.hpp @@ -353,7 +353,7 @@ namespace ScriptObjectInternal { if constexpr (std::is_same_v) { /* The string must be valid, i.e. not contain special codes. Since some * can be made with GSText, make sure the control codes are removed. */ - ::StrMakeValidInPlace(data, SVS_NONE); + ::StrMakeValidInPlace(data, {}); } } diff --git a/src/script/api/script_text.cpp b/src/script/api/script_text.cpp index acfbd20861..5cc784a427 100644 --- a/src/script/api/script_text.cpp +++ b/src/script/api/script_text.cpp @@ -204,7 +204,7 @@ void ScriptText::ParamCheck::Encode(std::back_insert_iterator &outp void operator()(std::string value) { Utf8Encode(this->output, SCC_ENCODED_STRING); - StrMakeValidInPlace(value, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE | SVS_REPLACE_TAB_CR_NL_WITH_SPACE); + StrMakeValidInPlace(value, {StringValidationSetting::ReplaceWithQuestionMark, StringValidationSetting::AllowNewline, StringValidationSetting::ReplaceTabCrNlWithSpace}); fmt::format_to(this->output, "{}", value); } diff --git a/src/settings.cpp b/src/settings.cpp index 7b99d786f8..9cd14a2da7 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -598,7 +598,7 @@ void StringSettingDesc::MakeValueValid(std::string &str) const * includes the '\0' termination for network transfer purposes. * Also ensure the string is valid after chopping of some bytes. */ str.erase(this->max_length - 1, std::string::npos); - StrMakeValidInPlace(str, SVS_NONE); + StrMakeValidInPlace(str, {}); } /** diff --git a/src/statusbar_gui.cpp b/src/statusbar_gui.cpp index 61aae847af..7944176499 100644 --- a/src/statusbar_gui.cpp +++ b/src/statusbar_gui.cpp @@ -39,7 +39,7 @@ static bool DrawScrollingStatusText(const NewsItem &ni, int scroll_pos, int left, int right, int top, int bottom) { /* Replace newlines and the likes with spaces. */ - std::string message = StrMakeValid(ni.GetStatusText(), SVS_REPLACE_TAB_CR_NL_WITH_SPACE); + std::string message = StrMakeValid(ni.GetStatusText(), StringValidationSetting::ReplaceTabCrNlWithSpace); DrawPixelInfo tmp_dpi; if (!FillDrawPixelInfo(&tmp_dpi, left, top, right - left, bottom)) return true; diff --git a/src/string.cpp b/src/string.cpp index 203a5d6ba7..966a3b6af7 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -159,25 +159,25 @@ static void StrMakeValid(T &dst, const char *str, const char *last, StringValida continue; } - if ((IsPrintable(c) && (c < SCC_SPRITE_START || c > SCC_SPRITE_END)) || ((settings & SVS_ALLOW_CONTROL_CODE) != 0 && IsSccEncodedCode(c))) { + if ((IsPrintable(c) && (c < SCC_SPRITE_START || c > SCC_SPRITE_END)) || (settings.Test(StringValidationSetting::AllowControlCode) && IsSccEncodedCode(c))) { /* Copy the character back. Even if dst is current the same as str * (i.e. no characters have been changed) this is quicker than * moving the pointers ahead by len */ do { *dst++ = *str++; } while (--len != 0); - } else if ((settings & SVS_ALLOW_NEWLINE) != 0 && c == '\n') { + } else if (settings.Test(StringValidationSetting::AllowNewline) && c == '\n') { *dst++ = *str++; } else { - if ((settings & SVS_ALLOW_NEWLINE) != 0 && c == '\r' && str[1] == '\n') { + if (settings.Test(StringValidationSetting::AllowNewline) && c == '\r' && str[1] == '\n') { str += len; continue; } str += len; - if ((settings & SVS_REPLACE_TAB_CR_NL_WITH_SPACE) != 0 && (c == '\r' || c == '\n' || c == '\t')) { + if (settings.Test(StringValidationSetting::ReplaceTabCrNlWithSpace) && (c == '\r' || c == '\n' || c == '\t')) { /* Replace the tab, carriage return or newline with a space. */ *dst++ = ' '; - } else if ((settings & SVS_REPLACE_WITH_QUESTION_MARK) != 0) { + } else if (settings.Test(StringValidationSetting::ReplaceWithQuestionMark)) { /* Replace the undesirable character with a question mark */ *dst++ = '?'; } diff --git a/src/string_func.h b/src/string_func.h index 231a69527c..4e44b3bb7a 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -21,15 +21,15 @@ void strecpy(std::span dst, std::string_view src); std::string FormatArrayAsHex(std::span data); -void StrMakeValidInPlace(char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); -void StrMakeValidInPlace(std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); +void StrMakeValidInPlace(char *str, StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark); +void StrMakeValidInPlace(std::string &str, StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark); -[[nodiscard]] std::string StrMakeValid(std::string_view str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); -[[nodiscard]] inline std::string StrMakeValid(const char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) +[[nodiscard]] std::string StrMakeValid(std::string_view str, StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark); +[[nodiscard]] inline std::string StrMakeValid(const char *str, StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark) { return StrMakeValid(std::string_view(str), settings); } -[[nodiscard]] inline std::string StrMakeValid(std::string &&str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) +[[nodiscard]] inline std::string StrMakeValid(std::string &&str, StringValidationSettings settings = StringValidationSetting::ReplaceWithQuestionMark) { StrMakeValidInPlace(str, settings); return std::move(str); diff --git a/src/string_type.h b/src/string_type.h index 3222e29d46..345a7dcb4e 100644 --- a/src/string_type.h +++ b/src/string_type.h @@ -41,19 +41,19 @@ static const char32_t CHAR_TD_RLO = 0x202E; ///< Force the following characters static const char32_t CHAR_TD_PDF = 0x202C; ///< Restore the text-direction state to before the last LRE, RLE, LRO or RLO. /** Settings for the string validation. */ -enum StringValidationSettings : uint8_t { - SVS_NONE = 0, ///< Allow nothing and replace nothing. - SVS_REPLACE_WITH_QUESTION_MARK = 1 << 0, ///< Replace the unknown/bad bits with question marks. - SVS_ALLOW_NEWLINE = 1 << 1, ///< Allow newlines; replaces '\r\n' with '\n' during processing. - SVS_ALLOW_CONTROL_CODE = 1 << 2, ///< Allow the special control codes. +enum class StringValidationSetting : uint8_t { + ReplaceWithQuestionMark, ///< Replace the unknown/bad bits with question marks. + AllowNewline, ///< Allow newlines; replaces '\r\n' with '\n' during processing. + AllowControlCode, ///< Allow the special control codes. /** * Replace tabs ('\t'), carriage returns ('\r') and newlines ('\n') with spaces. - * When #SVS_ALLOW_NEWLINE is set, a '\n' or '\r\n' combination are not replaced with a space. A lone '\r' is replaced with a space. - * When #SVS_REPLACE_WITH_QUESTION_MARK is set, this replacement runs first. + * When #StringValidationSetting::AllowNewline is set, a '\n' or '\r\n' combination are not replaced with a space. A lone '\r' is replaced with a space. + * When #StringValidationSetting::ReplaceWithQuestionMark is set, this replacement runs first. */ - SVS_REPLACE_TAB_CR_NL_WITH_SPACE = 1 << 3, + ReplaceTabCrNlWithSpace, }; -DECLARE_ENUM_AS_BIT_SET(StringValidationSettings) + +using StringValidationSettings = EnumBitSet; /** Type for a list of strings. */ diff --git a/src/textfile_gui.cpp b/src/textfile_gui.cpp index 3d8bdbcf1a..82e06a02b2 100644 --- a/src/textfile_gui.cpp +++ b/src/textfile_gui.cpp @@ -803,7 +803,7 @@ static std::vector Xunzip(std::span input) */ void TextfileWindow::LoadText(std::string_view buf) { - std::string text = StrMakeValid(buf, SVS_REPLACE_WITH_QUESTION_MARK | SVS_ALLOW_NEWLINE | SVS_REPLACE_TAB_CR_NL_WITH_SPACE); + std::string text = StrMakeValid(buf, {StringValidationSetting::ReplaceWithQuestionMark, StringValidationSetting::AllowNewline, StringValidationSetting::ReplaceTabCrNlWithSpace}); this->lines.clear(); /* Split the string on newlines. */