aboutsummaryrefslogtreecommitdiff
path: root/src/common/Utilities
diff options
context:
space:
mode:
authorTreeston <treeston.mmoc@gmail.com>2020-08-28 00:11:16 +0200
committerShauren <shauren.trinity@gmail.com>2022-02-04 00:27:14 +0100
commit9f97fdd31a3b9a06b6acfa1101d105e43687e824 (patch)
tree027f81c18e7733fa3554cf1dd704a0900d254725 /src/common/Utilities
parent6e45c371c4098942e0085a71577a07b17725ee93 (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.cpp93
-rw-r--r--src/common/Utilities/Util.h34
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);