diff options
author | Treeston <treeston.mmoc@gmail.com> | 2020-08-28 00:11:16 +0200 |
---|---|---|
committer | Shauren <shauren.trinity@gmail.com> | 2022-02-04 00:27:14 +0100 |
commit | 9f97fdd31a3b9a06b6acfa1101d105e43687e824 (patch) | |
tree | 027f81c18e7733fa3554cf1dd704a0900d254725 /src/common/Utilities | |
parent | 6e45c371c4098942e0085a71577a07b17725ee93 (diff) |
Core/Common: Tokenizer -> Trinity::Tokenize (PR: #25327)
(cherry picked from commit 534a2388b7c662c8796aabb1ec8cb424879799b6)
Diffstat (limited to 'src/common/Utilities')
-rw-r--r-- | src/common/Utilities/Util.cpp | 93 | ||||
-rw-r--r-- | src/common/Utilities/Util.h | 34 |
2 files changed, 53 insertions, 74 deletions
diff --git a/src/common/Utilities/Util.cpp b/src/common/Utilities/Util.cpp index f3f76569d11..317f8c754f8 100644 --- a/src/common/Utilities/Util.cpp +++ b/src/common/Utilities/Util.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "Containers.h" #include "IpAddress.h" +#include "StringConvert.h" #include "StringFormat.h" #include <utf8.h> #include <algorithm> @@ -35,39 +36,22 @@ #include <arpa/inet.h> #endif -Tokenizer::Tokenizer(std::string_view src, const char sep, uint32 vectorReserve /*= 0*/, bool keepEmptyStrings /*= true*/) +std::vector<std::string_view> Trinity::Tokenize(std::string_view str, char sep, bool keepEmpty) { - m_str = new char[src.length() + 1]; - memcpy(m_str, src.data(), src.length() + 1); + std::vector<std::string_view> tokens; - if (vectorReserve) - m_storage.reserve(vectorReserve); - - char* posold = m_str; - char* posnew = m_str; - - for (;;) + size_t start = 0; + for (size_t end = str.find(sep); end != std::string_view::npos; end = str.find(sep, start)) { - if (*posnew == sep) - { - if (keepEmptyStrings || posold != posnew) - m_storage.push_back(posold); - - posold = posnew + 1; - *posnew = '\0'; - } - else if (*posnew == '\0') - { - // Hack like, but the old code accepted these kind of broken strings, - // so changing it would break other things - if (posold != posnew) - m_storage.push_back(posold); + if (keepEmpty || (start < end)) + tokens.push_back(str.substr(start, end - start)); + start = end+1; + } - break; - } + if (keepEmpty || (start < str.length())) + tokens.push_back(str.substr(start)); - ++posnew; - } + return tokens; } #if (defined(WIN32) || defined(_WIN32) || defined(__WIN32__)) @@ -210,32 +194,43 @@ std::string secsToTimeString(uint64 timeInSecs, TimeFormat timeFormat, bool hour return ss.str(); } -int64 MoneyStringToMoney(std::string const& moneyString) +Optional<int64> MoneyStringToMoney(std::string const& moneyString) { int64 money = 0; - if (!(std::count(moneyString.begin(), moneyString.end(), 'g') == 1 || - std::count(moneyString.begin(), moneyString.end(), 's') == 1 || - std::count(moneyString.begin(), moneyString.end(), 'c') == 1)) - return 0; // Bad format + bool hadG = false; + bool hadS = false; + bool hadC = false; - Tokenizer tokens(moneyString, ' '); - for (char const* token : tokens) + for (std::string_view token : Trinity::Tokenize(moneyString, ' ', false)) { - std::string tokenString(token); - size_t gCount = std::count(tokenString.begin(), tokenString.end(), 'g'); - size_t sCount = std::count(tokenString.begin(), tokenString.end(), 's'); - size_t cCount = std::count(tokenString.begin(), tokenString.end(), 'c'); - if (gCount + sCount + cCount != 1) - return 0; - - uint64 amount = strtoull(token, nullptr, 10); - if (gCount == 1) - money += amount * 100 * 100; - else if (sCount == 1) - money += amount * 100; - else if (cCount == 1) - money += amount; + uint32 unit; + switch (token[token.length() - 1]) + { + case 'g': + if (hadG) return std::nullopt; + hadG = true; + unit = 100 * 100; + break; + case 's': + if (hadS) return std::nullopt; + hadS = true; + unit = 100; + break; + case 'c': + if (hadC) return std::nullopt; + hadC = true; + unit = 1; + break; + default: + return std::nullopt; + } + + Optional<uint64> amount = Trinity::StringTo<uint32>(token.substr(0, token.length() - 1)); + if (amount) + money += (unit * *amount); + else + return std::nullopt; } return money; diff --git a/src/common/Utilities/Util.h b/src/common/Utilities/Util.h index 28d0285d74d..8708405882e 100644 --- a/src/common/Utilities/Util.h +++ b/src/common/Utilities/Util.h @@ -37,35 +37,19 @@ enum class TimeFormat : uint8 Numeric // 1:2:3:4 }; -class TC_COMMON_API Tokenizer +namespace Trinity { -public: - typedef std::vector<char const*> StorageType; - - typedef StorageType::size_type size_type; - - typedef StorageType::const_iterator const_iterator; - typedef StorageType::reference reference; - typedef StorageType::const_reference const_reference; - -public: - Tokenizer(std::string_view src, char const sep, uint32 vectorReserve = 0, bool keepEmptyStrings = true); - ~Tokenizer() { delete[] m_str; } + TC_COMMON_API std::vector<std::string_view> Tokenize(std::string_view str, char sep, bool keepEmpty); - const_iterator begin() const { return m_storage.begin(); } - const_iterator end() const { return m_storage.end(); } + /* this would return string_view into temporary otherwise */ + std::vector<std::string_view> Tokenize(std::string&&, char, bool) = delete; + std::vector<std::string_view> Tokenize(std::string const&&, char, bool) = delete; - size_type size() const { return m_storage.size(); } - - reference operator [] (size_type i) { return m_storage[i]; } - const_reference operator [] (size_type i) const { return m_storage[i]; } - -private: - char* m_str; - StorageType m_storage; -}; + /* the delete overload means we need to make this explicit */ + inline std::vector<std::string_view> Tokenize(char const* str, char sep, bool keepEmpty) { return Tokenize(std::string_view(str ? str : ""), sep, keepEmpty); } +} -TC_COMMON_API int64 MoneyStringToMoney(std::string const& moneyString); +TC_COMMON_API Optional<int64> MoneyStringToMoney(std::string const& moneyString); TC_COMMON_API struct tm* localtime_r(time_t const* time, struct tm *result); TC_COMMON_API time_t LocalTimeToUTCTime(time_t time); |