From 5ac9dd04e4bfbe19e2ec241078171881a4424b77 Mon Sep 17 00:00:00 2001 From: Chris Miles Date: Sun, 22 Jun 2025 13:52:13 -0500 Subject: [PATCH] [Code] Cleanup Strings Header (#4950) * [Code] Cleanup Strings Header * Include optimize --- common/database.cpp | 14 ++ common/process/process.cpp | 1 + common/repositories/rule_values_repository.h | 61 +++++- common/shareddb.cpp | 54 ++++- common/strings.cpp | 20 ++ common/strings.h | 196 +------------------ tests/string_util_test.h | 16 -- zone/bot_database.cpp | 62 +++++- zone/position.cpp | 1 + 9 files changed, 204 insertions(+), 221 deletions(-) diff --git a/common/database.cpp b/common/database.cpp index c79ae0117..099b796ad 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -708,6 +708,20 @@ const std::string Database::GetNPCNameByID(uint32 npc_id) return e.id ? e.name : std::string(); } +template +inline auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result) +{ + for (; first != last; ++first) { + if (*first == '_') { + *result = ' '; + } + else if (isalpha(*first) || *first == '`') { + *result = *first; + } + } + return result; +} + const std::string Database::GetCleanNPCNameByID(uint32 npc_id) { const auto& e = NpcTypesRepository::FindOne(*this, npc_id); diff --git a/common/process/process.cpp b/common/process/process.cpp index badb0fe11..56bbeff2b 100644 --- a/common/process/process.cpp +++ b/common/process/process.cpp @@ -1,6 +1,7 @@ #include #include #include "process.h" +#include std::string Process::execute(const std::string &cmd) { diff --git a/common/repositories/rule_values_repository.h b/common/repositories/rule_values_repository.h index 072175d5f..d7eb1530e 100644 --- a/common/repositories/rule_values_repository.h +++ b/common/repositories/rule_values_repository.h @@ -43,6 +43,47 @@ public: * method and encapsulate filters there */ + template + static std::vector join_tuple( + const std::string &glue, + const std::pair &encapsulation, + const std::vector> &src + ) + { + if (src.empty()) { + return {}; + } + + std::vector output; + + for (const std::tuple &src_iter: src) { + + output.emplace_back( + + fmt::format( + "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", + encapsulation.first, + std::get<0>(src_iter), + encapsulation.second, + glue, + encapsulation.first, + std::get<1>(src_iter), + encapsulation.second, + glue, + encapsulation.first, + std::get<2>(src_iter), + encapsulation.second, + glue, + encapsulation.first, + std::get<3>(src_iter), + encapsulation.second + ) + ); + } + + return output; + } + // Custom extended repository methods here static std::vector GetRuleNames(Database &db, int rule_set_id) { @@ -87,12 +128,28 @@ public: return v; } + template + static std::string + ImplodePair(const std::string &glue, const std::pair &encapsulation, const std::vector &src) + { + if (src.empty()) { + return {}; + } + std::ostringstream oss; + for (const T &src_iter: src) { + oss << encapsulation.first << src_iter << encapsulation.second << glue; + } + std::string output(oss.str()); + output.resize(output.size() - glue.size()); + return output; + } + static bool DeleteOrphanedRules(Database& db, std::vector& v) { const auto query = fmt::format( "DELETE FROM {} WHERE rule_name IN ({})", TableName(), - Strings::ImplodePair(",", std::pair('\'', '\''), v) + ImplodePair(",", std::pair('\'', '\''), v) ); return db.QueryDatabase(query).Success(); @@ -103,7 +160,7 @@ public: const auto query = fmt::format( "REPLACE INTO {} (`ruleset_id`, `rule_name`, `rule_value`, `notes`) VALUES {}", TableName(), - Strings::ImplodePair( + ImplodePair( ",", std::pair('(', ')'), join_tuple(",", std::pair('\'', '\''), v) diff --git a/common/shareddb.cpp b/common/shareddb.cpp index 8fe9d61bf..d143dfbfd 100644 --- a/common/shareddb.cpp +++ b/common/shareddb.cpp @@ -1544,12 +1544,60 @@ bool SharedDatabase::GetCommandSettings(std::map +inline std::vector join_pair( + const std::string &glue, + const std::pair &encapsulation, + const std::vector> &src +) +{ + if (src.empty()) { + return {}; + } + + std::vector output; + + for (const std::pair &src_iter: src) { + output.emplace_back( + + fmt::format( + "{}{}{}{}{}{}{}", + encapsulation.first, + src_iter.first, + encapsulation.second, + glue, + encapsulation.first, + src_iter.second, + encapsulation.second + ) + ); + } + + return output; +} + +template +inline std::string +ImplodePair(const std::string &glue, const std::pair &encapsulation, const std::vector &src) +{ + if (src.empty()) { + return {}; + } + std::ostringstream oss; + for (const T &src_iter: src) { + oss << encapsulation.first << src_iter << encapsulation.second << glue; + } + std::string output(oss.str()); + output.resize(output.size() - glue.size()); + return output; +} + bool SharedDatabase::UpdateInjectedCommandSettings(const std::vector> &injected) { if (injected.size()) { const std::string query = fmt::format( "REPLACE INTO `command_settings`(`command`, `access`) VALUES {}", - Strings::ImplodePair( + ImplodePair( ",", std::pair('(', ')'), join_pair(",", std::pair('\'', '\''), injected) @@ -1576,7 +1624,7 @@ bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector('\'', '\''), orphaned) + ImplodePair(",", std::pair('\'', '\''), orphaned) ); auto results = QueryDatabase(query); @@ -1586,7 +1634,7 @@ bool SharedDatabase::UpdateOrphanedCommandSettings(const std::vector('\'', '\''), orphaned) + ImplodePair(",", std::pair('\'', '\''), orphaned) ); auto results_two = QueryDatabase(query); diff --git a/common/strings.cpp b/common/strings.cpp index 58261388f..52990aa85 100644 --- a/common/strings.cpp +++ b/common/strings.cpp @@ -34,6 +34,7 @@ */ #include "strings.h" +#include #include #include #include @@ -41,6 +42,7 @@ #include #include #include +#include #include #include @@ -49,6 +51,12 @@ #include "strings_legacy.cpp" // legacy c functions #include "strings_misc.cpp" // anything non "Strings" scoped +#ifdef _WINDOWS +#include +#include +#include +#endif + std::string Strings::Random(size_t length) { static auto &chrs = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -701,6 +709,18 @@ std::string &Strings::Trim(std::string &str, const std::string &chars) return LTrim(RTrim(str, chars), chars); } +const std::string NUM_TO_ENGLISH_X[] = { + "", "One ", "Two ", "Three ", "Four ", + "Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ", + "Twelve ", "Thirteen ", "Fourteen ", "Fifteen ", + "Sixteen ", "Seventeen ", "Eighteen ", "Nineteen " +}; + +const std::string NUM_TO_ENGLISH_Y[] = { + "", "", "Twenty ", "Thirty ", "Forty ", + "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " +}; + // Function to convert single digit or two digit number into words std::string Strings::ConvertToDigit(int n, const std::string& suffix) { diff --git a/common/strings.h b/common/strings.h index 5338949b5..8ae8fee25 100644 --- a/common/strings.h +++ b/common/strings.h @@ -36,53 +36,19 @@ #define _STRINGUTIL_H_ #include -#include -#include +#include #include +#include #include #include -#include #include -#include -#include - -#ifndef _WIN32 -// this doesn't appear to affect linux-based systems..need feedback for _WIN64 - -#endif - -#ifdef _WINDOWS +#ifdef _WIN32 #include -#include -#include #endif #include "types.h" -namespace detail { - // template magic to check if std::from_chars floating point functions exist - template - struct has_from_chars_float : std::false_type { }; - - // basically it "uses" this template if they do exist because reasons - template - struct has_from_chars_float < T, - std::void_t(), std::declval(), - std::declval()))>> : std::true_type { }; -}; // namespace detail - -namespace EQ { -// lame -- older GCC's didn't define this, clang's libc++ however does, even though they lack FP support -#if defined(__GNUC__) && (__GNUC__ < 11) && !defined(__clang__) - enum class chars_format { - scientific = 1, fixed = 2, hex = 4, general = fixed | scientific - }; -#else - using chars_format = std::chars_format; -#endif -}; // namespace EQ - class Strings { public: static bool Contains(std::vector container, const std::string& element); @@ -133,61 +99,6 @@ public: static bool BeginsWith(const std::string& subject, const std::string& search); static bool EndsWith(const std::string& subject, const std::string& search); static std::string ZoneTime(const uint8 hours, const uint8 minutes); - - template - static std::string - ImplodePair(const std::string &glue, const std::pair &encapsulation, const std::vector &src) - { - if (src.empty()) { - return {}; - } - std::ostringstream oss; - for (const T &src_iter: src) { - oss << encapsulation.first << src_iter << encapsulation.second << glue; - } - std::string output(oss.str()); - output.resize(output.size() - glue.size()); - return output; - } - - // basic string_view overloads that just use std stuff since they work! - template - std::enable_if_t && detail::has_from_chars_float::value, std::from_chars_result> - static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general) - { - return std::from_chars(str.data(), str.data() + str.size(), value, fmt); - } - - template - std::enable_if_t, std::from_chars_result> - static from_chars(std::string_view str, T& value, int base = 10) - { - return std::from_chars(str.data(), str.data() + str.size(), value, base); - } - - // fallback versions of floating point in case they're not implemented - // TODO: add error handling ... - // This does have to allocate since from_chars doesn't need a null terminated string and neither does string_view - template - std::enable_if_t && !detail::has_from_chars_float::value && std::is_same_v, std::from_chars_result> - static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general) - { - std::from_chars_result res{}; - std::string tmp_str(str.data(), str.size()); - value = strtof(tmp_str.data(), nullptr); - return res; - } - - template - std::enable_if_t && !detail::has_from_chars_float::value && std::is_same_v, std::from_chars_result> - static from_chars(std::string_view str, T& value, EQ::chars_format fmt = EQ::chars_format::general) - { - std::from_chars_result res{}; - std::string tmp_str(str.data(), str.size()); - value = strtod(tmp_str.data(), nullptr); - return res; - } - static std::string Slugify(const std::string &input, const std::string &separator = "-"); static bool IsValidJson(const std::string& json); }; @@ -199,93 +110,6 @@ const std::string vStringFormat(const char *format, va_list args); // Used for grid nodes, as NPC names remove numerals. // But general purpose -const std::string NUM_TO_ENGLISH_X[] = { - "", "One ", "Two ", "Three ", "Four ", - "Five ", "Six ", "Seven ", "Eight ", "Nine ", "Ten ", "Eleven ", - "Twelve ", "Thirteen ", "Fourteen ", "Fifteen ", - "Sixteen ", "Seventeen ", "Eighteen ", "Nineteen " -}; - -const std::string NUM_TO_ENGLISH_Y[] = { - "", "", "Twenty ", "Thirty ", "Forty ", - "Fifty ", "Sixty ", "Seventy ", "Eighty ", "Ninety " -}; - -// _WIN32 builds require that #include be included in whatever code file the invocation is made from (no header files) -template -std::vector join_pair( - const std::string &glue, - const std::pair &encapsulation, - const std::vector> &src -) -{ - if (src.empty()) { - return {}; - } - - std::vector output; - - for (const std::pair &src_iter: src) { - output.emplace_back( - - fmt::format( - "{}{}{}{}{}{}{}", - encapsulation.first, - src_iter.first, - encapsulation.second, - glue, - encapsulation.first, - src_iter.second, - encapsulation.second - ) - ); - } - - return output; -} - -// _WIN32 builds require that #include be included in whatever code file the invocation is made from (no header files) -template -std::vector join_tuple( - const std::string &glue, - const std::pair &encapsulation, - const std::vector> &src -) -{ - if (src.empty()) { - return {}; - } - - std::vector output; - - for (const std::tuple &src_iter: src) { - - output.emplace_back( - - fmt::format( - "{}{}{}{}{}{}{}{}{}{}{}{}{}{}{}", - encapsulation.first, - std::get<0>(src_iter), - encapsulation.second, - glue, - encapsulation.first, - std::get<1>(src_iter), - encapsulation.second, - glue, - encapsulation.first, - std::get<2>(src_iter), - encapsulation.second, - glue, - encapsulation.first, - std::get<3>(src_iter), - encapsulation.second - ) - ); - } - - return output; -} - // misc functions std::string SanitizeWorldServerName(std::string server_long_name); std::vector GetBadWords(); @@ -310,18 +134,4 @@ std::string FormatName(const std::string &char_name); bool IsAllowedWorldServerCharacterList(char c); void SanitizeWorldServerName(char *name); -template -auto CleanMobName(InputIterator first, InputIterator last, OutputIterator result) -{ - for (; first != last; ++first) { - if (*first == '_') { - *result = ' '; - } - else if (isalpha(*first) || *first == '`') { - *result = *first; - } - } - return result; -} - #endif diff --git a/tests/string_util_test.h b/tests/string_util_test.h index af88a5a03..37bd539f7 100644 --- a/tests/string_util_test.h +++ b/tests/string_util_test.h @@ -30,7 +30,6 @@ public: TEST_ADD(StringUtilTest::EscapeStringTest); TEST_ADD(StringUtilTest::SearchDeliminatedStringTest); TEST_ADD(StringUtilTest::SplitStringTest); - TEST_ADD(StringUtilTest::FromCharsTest); TEST_ADD(StringUtilTest::TestIsFloat); TEST_ADD(StringUtilTest::TestIsNumber); } @@ -108,21 +107,6 @@ public: TEST_ASSERT(v[2] == "789"); } - void FromCharsTest() { - char int_chars[] = "123"; - int int_value = 0; - - char float_chars[] = "3.14"; - float float_value = 0.0f; - - Strings::from_chars(int_chars, int_value); - TEST_ASSERT(int_value == 123); - - Strings::from_chars(float_chars, float_value); - TEST_ASSERT(float_value == 3.14f); - - } - void TestIsFloat() { TEST_ASSERT_EQUALS(Strings::IsFloat("0.23424523"), true); TEST_ASSERT_EQUALS(Strings::IsFloat("12312312313.23424523"), true); diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 4c78284e6..10d681913 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -74,13 +74,61 @@ bool BotDatabase::LoadBotCommandSettings(std::map +inline std::vector join_pair( + const std::string &glue, + const std::pair &encapsulation, + const std::vector> &src +) +{ + if (src.empty()) { + return {}; + } + + std::vector output; + + for (const std::pair &src_iter: src) { + output.emplace_back( + + fmt::format( + "{}{}{}{}{}{}{}", + encapsulation.first, + src_iter.first, + encapsulation.second, + glue, + encapsulation.first, + src_iter.second, + encapsulation.second + ) + ); + } + + return output; +} + +template +inline std::string +ImplodePair(const std::string &glue, const std::pair &encapsulation, const std::vector &src) +{ + if (src.empty()) { + return {}; + } + std::ostringstream oss; + for (const T &src_iter: src) { + oss << encapsulation.first << src_iter << encapsulation.second << glue; + } + std::string output(oss.str()); + output.resize(output.size() - glue.size()); + return output; +} + bool BotDatabase::UpdateInjectedBotCommandSettings(const std::vector> &injected) { if (injected.size()) { query = fmt::format( "REPLACE INTO `bot_command_settings`(`bot_command`, `access`) VALUES {}", - Strings::ImplodePair( + ImplodePair( ",", std::pair('(', ')'), join_pair(",", std::pair('\'', '\''), injected) @@ -107,7 +155,7 @@ bool BotDatabase::UpdateOrphanedBotCommandSettings(const std::vector('\'', '\''), orphaned) + ImplodePair(",", std::pair('\'', '\''), orphaned) ); if (!database.QueryDatabase(query).Success()) { @@ -248,7 +296,7 @@ bool BotDatabase::LoadBotsList(const uint32 owner_id, std::listGetCleanName(), Stance::GetName(Stance::Passive), Stance::Passive); return true; @@ -2278,7 +2326,7 @@ bool BotDatabase::SaveBotSettings(Mob* m) if (!m->IsOfClientBot()) { return false; } - + uint32 bot_id = (m->IsBot() ? m->CastToBot()->GetBotID() : 0); uint32 character_id = (m->IsClient() ? m->CastToClient()->CharacterID() : 0); uint8 stance_id = (m->IsBot() ? m->CastToBot()->GetBotStance() : 0); @@ -2289,10 +2337,10 @@ bool BotDatabase::SaveBotSettings(Mob* m) } std::string query = ""; - + if (m->IsClient()) { query = fmt::format("`character_id` = {} AND `stance` = {}", character_id, stance_id); - } + } else { query = fmt::format("`bot_id` = {} AND `stance` = {}", bot_id, stance_id); } diff --git a/zone/position.cpp b/zone/position.cpp index 52062120e..39cb5b6d4 100644 --- a/zone/position.cpp +++ b/zone/position.cpp @@ -6,6 +6,7 @@ #include "../common/data_verification.h" #include #include "../common/types.h" +#include constexpr float position_eps = 0.0001f;