From 2cdf2bedfa6e3ac19ee688b1fa4bafa707405095 Mon Sep 17 00:00:00 2001 From: frosch Date: Mon, 7 Apr 2025 18:22:47 +0200 Subject: [PATCH] Codechange: Add a std::string overload for StrMakeValidInPlace() and a moving std::string&& overload for StrMakeValid(). (#13962) --- src/fios.cpp | 2 +- src/network/network_command.cpp | 2 +- src/saveload/oldloader.cpp | 4 ++-- src/saveload/saveload.cpp | 2 +- src/script/api/script_object.hpp | 2 +- src/settings.cpp | 4 ++-- src/string.cpp | 18 ++++++++++++++++++ src/string_func.h | 13 ++++++++++++- 8 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/fios.cpp b/src/fios.cpp index 25cb67509b..760ca1e066 100644 --- a/src/fios.cpp +++ b/src/fios.cpp @@ -396,7 +396,7 @@ static std::string GetFileTitle(const std::string &file, Subdirectory subdir) size_t read = fread(title, 1, lengthof(title), *f); assert(read <= lengthof(title)); - return StrMakeValid({title, read}); + return StrMakeValid(std::string_view{title, read}); } /** diff --git a/src/network/network_command.cpp b/src/network/network_command.cpp index b1662534ff..e4f65308f4 100644 --- a/src/network/network_command.cpp +++ b/src/network/network_command.cpp @@ -441,7 +441,7 @@ template static inline void SanitizeSingleStringHelper([[maybe_unused]] CommandFlags cmd_flags, T &data) { if constexpr (std::is_same_v) { - data = StrMakeValid(data, (!_network_server && cmd_flags.Test(CommandFlag::StrCtrl)) ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK); + StrMakeValidInPlace(data, (!_network_server && cmd_flags.Test(CommandFlag::StrCtrl)) ? SVS_ALLOW_CONTROL_CODE | SVS_REPLACE_WITH_QUESTION_MARK : SVS_REPLACE_WITH_QUESTION_MARK); } } diff --git a/src/saveload/oldloader.cpp b/src/saveload/oldloader.cpp index 0152fdbf53..01c1d600a3 100644 --- a/src/saveload/oldloader.cpp +++ b/src/saveload/oldloader.cpp @@ -219,11 +219,11 @@ static std::tuple DetermineOldSavegameTypeAndName(Fil } if (VerifyOldNameChecksum(buffer, TTO_HEADER_SIZE) && fseek(f, pos + TTO_HEADER_SIZE, SEEK_SET) == 0) { - return { SGT_TTO, "(TTO)" + StrMakeValid({buffer, TTO_HEADER_SIZE - HEADER_CHECKSUM_SIZE}) }; + return { SGT_TTO, "(TTO)" + StrMakeValid(std::string_view{buffer, TTO_HEADER_SIZE - HEADER_CHECKSUM_SIZE}) }; } if (VerifyOldNameChecksum(buffer, TTD_HEADER_SIZE) && fseek(f, pos + TTD_HEADER_SIZE, SEEK_SET) == 0) { - return { SGT_TTD, "(TTD)" + StrMakeValid({buffer, TTD_HEADER_SIZE - HEADER_CHECKSUM_SIZE}) }; + return { SGT_TTD, "(TTD)" + StrMakeValid(std::string_view{buffer, TTD_HEADER_SIZE - HEADER_CHECKSUM_SIZE}) }; } return { SGT_INVALID, "(broken) Unknown" }; diff --git a/src/saveload/saveload.cpp b/src/saveload/saveload.cpp index c585851644..a50c077b31 100644 --- a/src/saveload/saveload.cpp +++ b/src/saveload/saveload.cpp @@ -1028,7 +1028,7 @@ static void SlStdString(void *ptr, VarType conv) if ((conv & SLF_ALLOW_NEWLINE) != 0) { settings = settings | SVS_ALLOW_NEWLINE; } - *str = StrMakeValid(*str, settings); + StrMakeValidInPlace(*str, settings); } case SLA_PTRS: break; diff --git a/src/script/api/script_object.hpp b/src/script/api/script_object.hpp index f6436822e7..8c3067c448 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. */ - data = ::StrMakeValid(data, SVS_NONE); + ::StrMakeValidInPlace(data, SVS_NONE); } } diff --git a/src/settings.cpp b/src/settings.cpp index cb75b27f1c..7b99d786f8 100644 --- a/src/settings.cpp +++ b/src/settings.cpp @@ -597,8 +597,8 @@ void StringSettingDesc::MakeValueValid(std::string &str) const /* In case a maximum length is imposed by the setting, the length * includes the '\0' termination for network transfer purposes. * Also ensure the string is valid after chopping of some bytes. */ - std::string stdstr(str, 0, this->max_length - 1); - str.assign(StrMakeValid(stdstr, SVS_NONE)); + str.erase(this->max_length - 1, std::string::npos); + StrMakeValidInPlace(str, SVS_NONE); } /** diff --git a/src/string.cpp b/src/string.cpp index 2413d37ae3..203a5d6ba7 100644 --- a/src/string.cpp +++ b/src/string.cpp @@ -201,6 +201,24 @@ void StrMakeValidInPlace(char *str, StringValidationSettings settings) *dst = '\0'; } +/** + * Scans the string for invalid characters and replaces them with a + * question mark '?' (if not ignored). + * @param str The string to validate. + * @param settings The settings for the string validation. + * @note The string must be properly NUL terminated. + */ +void StrMakeValidInPlace(std::string &str, StringValidationSettings settings) +{ + if (str.empty()) return; + + char *buf = str.data(); + char *last = buf + str.size() - 1; + char *dst = buf; + StrMakeValid(dst, buf, last, settings); + str.erase(dst - buf, std::string::npos); +} + /** * Copies the valid (UTF-8) characters from \c str to the returned string. * Depending on the \c settings invalid characters can be replaced with a diff --git a/src/string_func.h b/src/string_func.h index 9fd207289c..231a69527c 100644 --- a/src/string_func.h +++ b/src/string_func.h @@ -21,8 +21,19 @@ void strecpy(std::span dst, std::string_view src); std::string FormatArrayAsHex(std::span data); -[[nodiscard]] std::string StrMakeValid(std::string_view str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); void StrMakeValidInPlace(char *str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); +void StrMakeValidInPlace(std::string &str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK); + +[[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) +{ + return StrMakeValid(std::string_view(str), settings); +} +[[nodiscard]] inline std::string StrMakeValid(std::string &&str, StringValidationSettings settings = SVS_REPLACE_WITH_QUESTION_MARK) +{ + StrMakeValidInPlace(str, settings); + return std::move(str); +} bool strtolower(std::string &str, std::string::size_type offs = 0);