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 | |
parent | 6e45c371c4098942e0085a71577a07b17725ee93 (diff) |
Core/Common: Tokenizer -> Trinity::Tokenize (PR: #25327)
(cherry picked from commit 534a2388b7c662c8796aabb1ec8cb424879799b6)
Diffstat (limited to 'src/common')
-rw-r--r-- | src/common/Logging/AppenderConsole.cpp | 45 | ||||
-rw-r--r-- | src/common/Logging/AppenderConsole.h | 14 | ||||
-rw-r--r-- | src/common/Logging/AppenderFile.cpp | 27 | ||||
-rw-r--r-- | src/common/Logging/AppenderFile.h | 6 | ||||
-rw-r--r-- | src/common/Logging/Log.cpp | 63 | ||||
-rw-r--r-- | src/common/Logging/Log.h | 11 | ||||
-rw-r--r-- | src/common/Logging/LogCommon.h | 15 | ||||
-rw-r--r-- | src/common/Logging/enuminfo_AppenderConsole.cpp | 103 | ||||
-rw-r--r-- | src/common/Logging/enuminfo_LogCommon.cpp | 124 | ||||
-rw-r--r-- | src/common/Metric/Metric.cpp | 2 | ||||
-rw-r--r-- | src/common/Utilities/Util.cpp | 93 | ||||
-rw-r--r-- | src/common/Utilities/Util.h | 34 |
12 files changed, 380 insertions, 157 deletions
diff --git a/src/common/Logging/AppenderConsole.cpp b/src/common/Logging/AppenderConsole.cpp index 86e7634f1b9..af2117c6d0c 100644 --- a/src/common/Logging/AppenderConsole.cpp +++ b/src/common/Logging/AppenderConsole.cpp @@ -17,6 +17,9 @@ #include "AppenderConsole.h" #include "LogMessage.h" +#include "SmartEnum.h" +#include "StringFormat.h" +#include "StringConvert.h" #include "Util.h" #include <sstream> @@ -24,17 +27,17 @@ #include <Windows.h> #endif -AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) +AppenderConsole::AppenderConsole(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args) : Appender(id, name, level, flags), _colored(false) { for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) - _colors[i] = ColorTypes(MaxColors); + _colors[i] = ColorTypes(NUM_COLOR_TYPES); - if (!extraArgs.empty()) - InitColors(extraArgs[0]); + if (3 < args.size()) + InitColors(name, args[3]); } -void AppenderConsole::InitColors(std::string const& str) +void AppenderConsole::InitColors(std::string const& name, std::string_view str) { if (str.empty()) { @@ -42,23 +45,23 @@ void AppenderConsole::InitColors(std::string const& str) return; } - int color[NUM_ENABLED_LOG_LEVELS]; - - std::istringstream ss(str); - - for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) + std::vector<std::string_view> colorStrs = Trinity::Tokenize(str, ' ', false); + if (colorStrs.size() != NUM_ENABLED_LOG_LEVELS) { - ss >> color[i]; - - if (!ss) - return; - - if (color[i] < 0 || color[i] >= MaxColors) - return; + throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid color data '%s' for console appender %s (expected %u entries, got %zu)", + std::string(str).c_str(), name.c_str(), NUM_ENABLED_LOG_LEVELS, colorStrs.size())); } for (uint8 i = 0; i < NUM_ENABLED_LOG_LEVELS; ++i) - _colors[i] = ColorTypes(color[i]); + { + if (Optional<uint8> color = Trinity::StringTo<uint8>(colorStrs[i]); color && EnumUtils::IsValid<ColorTypes>(*color)) + _colors[i] = static_cast<ColorTypes>(*color); + else + { + throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid color '%s' for log level %s on console appender %s", + std::string(colorStrs[i]).c_str(), EnumUtils::ToTitle(static_cast<LogLevel>(i)), name.c_str())); + } + } _colored = true; } @@ -66,7 +69,7 @@ void AppenderConsole::InitColors(std::string const& str) void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color) { #if TRINITY_PLATFORM == TRINITY_PLATFORM_WINDOWS - static WORD WinColorFG[MaxColors] = + static WORD WinColorFG[NUM_COLOR_TYPES] = { 0, // BLACK FOREGROUND_RED, // RED @@ -127,7 +130,7 @@ void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color) BG_WHITE }; - static uint8 UnixColorFG[MaxColors] = + static uint8 UnixColorFG[NUM_COLOR_TYPES] = { FG_BLACK, // BLACK FG_RED, // RED @@ -146,7 +149,7 @@ void AppenderConsole::SetColor(bool stdout_stream, ColorTypes color) FG_WHITE // LWHITE }; - fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < MaxColors ? ";1" : "")); + fprintf((stdout_stream? stdout : stderr), "\x1b[%d%sm", UnixColorFG[color], (color >= YELLOW && color < NUM_COLOR_TYPES ? ";1" : "")); #endif } diff --git a/src/common/Logging/AppenderConsole.h b/src/common/Logging/AppenderConsole.h index 72c2bf98e10..6c6be4b6c59 100644 --- a/src/common/Logging/AppenderConsole.h +++ b/src/common/Logging/AppenderConsole.h @@ -20,6 +20,7 @@ #include "Appender.h" +// EnumUtils: DESCRIBE THIS enum ColorTypes { BLACK, @@ -36,19 +37,18 @@ enum ColorTypes LBLUE, LMAGENTA, LCYAN, - WHITE + WHITE, + NUM_COLOR_TYPES // SKIP }; -const uint8 MaxColors = uint8(WHITE) + 1; - class TC_COMMON_API AppenderConsole : public Appender { public: - typedef std::integral_constant<AppenderType, APPENDER_CONSOLE>::type TypeIndex; + static constexpr AppenderType type = APPENDER_CONSOLE; - AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs); - void InitColors(const std::string& init_str); - AppenderType getType() const override { return TypeIndex::value; } + AppenderConsole(uint8 _id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args); + void InitColors(std::string const& name, std::string_view init_str); + AppenderType getType() const override { return type; } private: void SetColor(bool stdout_stream, ColorTypes color); diff --git a/src/common/Logging/AppenderFile.cpp b/src/common/Logging/AppenderFile.cpp index 3cfd6b950a6..bb38cade4e4 100644 --- a/src/common/Logging/AppenderFile.cpp +++ b/src/common/Logging/AppenderFile.cpp @@ -18,23 +18,25 @@ #include "AppenderFile.h" #include "Log.h" #include "LogMessage.h" +#include "StringConvert.h" +#include "Util.h" #include <algorithm> -AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs) : +AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args) : Appender(id, name, level, flags), logfile(nullptr), _logDir(sLog->GetLogsDir()), _maxFileSize(0), _fileSize(0) { - if (extraArgs.empty()) - throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s\n", name.c_str())); + if (args.size() < 4) + throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Missing file name for appender %s", name.c_str())); - _fileName = extraArgs[0]; + _fileName.assign(args[3]); - char const* mode = "a"; - if (extraArgs.size() > 1) - mode = extraArgs[1]; + std::string mode = "a"; + if (4 < args.size()) + mode.assign(args[4]); if (flags & APPENDER_FLAGS_USE_TIMESTAMP) { @@ -45,14 +47,19 @@ AppenderFile::AppenderFile(uint8 id, std::string const& name, LogLevel level, Ap _fileName += sLog->GetLogsTimestamp(); } - if (extraArgs.size() > 2) - _maxFileSize = atoi(extraArgs[2]); + if (5 < args.size()) + { + if (Optional<uint32> size = Trinity::StringTo<uint32>(args[5])) + _maxFileSize = *size; + else + throw InvalidAppenderArgsException(Trinity::StringFormat("Log::CreateAppenderFromConfig: Invalid size '%s' for appender %s", std::string(args[5]).c_str(), name.c_str())); + } _dynamicName = std::string::npos != _fileName.find("%s"); _backup = (flags & APPENDER_FLAGS_MAKE_FILE_BACKUP) != 0; if (!_dynamicName) - logfile = OpenFile(_fileName, mode, !strcmp(mode, "w") && _backup); + logfile = OpenFile(_fileName, mode, (mode == "w") && _backup); } AppenderFile::~AppenderFile() diff --git a/src/common/Logging/AppenderFile.h b/src/common/Logging/AppenderFile.h index a320e90eb2b..c360e81a2ae 100644 --- a/src/common/Logging/AppenderFile.h +++ b/src/common/Logging/AppenderFile.h @@ -24,12 +24,12 @@ class TC_COMMON_API AppenderFile : public Appender { public: - typedef std::integral_constant<AppenderType, APPENDER_FILE>::type TypeIndex; + static constexpr AppenderType type = APPENDER_FILE; - AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*> extraArgs); + AppenderFile(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& args); ~AppenderFile(); FILE* OpenFile(std::string const& name, std::string const& mode, bool backup); - AppenderType getType() const override { return TypeIndex::value; } + AppenderType getType() const override { return type; } private: void CloseFile(); diff --git a/src/common/Logging/Log.cpp b/src/common/Logging/Log.cpp index 6c364105a7b..fba5ac84aaf 100644 --- a/src/common/Logging/Log.cpp +++ b/src/common/Logging/Log.cpp @@ -25,6 +25,7 @@ #include "LogMessage.h" #include "LogOperation.h" #include "Strand.h" +#include "StringConvert.h" #include "Util.h" #include <chrono> #include <sstream> @@ -47,7 +48,7 @@ uint8 Log::NextAppenderId() return AppenderId++; } -Appender* Log::GetAppenderByName(std::string const& name) +Appender* Log::GetAppenderByName(std::string_view name) { auto it = appenders.begin(); while (it != appenders.end() && it->second && it->second->getName() != name) @@ -65,10 +66,9 @@ void Log::CreateAppenderFromConfigLine(std::string const& appenderName, std::str // if type = File. optional1 = file and option2 = mode // if type = Console. optional1 = Color - Tokenizer tokens(options, ','); - auto iter = tokens.begin(); + std::vector<std::string_view> tokens = Trinity::Tokenize(options, ',', true); - size_t size = tokens.size(); + size_t const size = tokens.size(); std::string name = appenderName.substr(9); if (size < 2) @@ -78,33 +78,41 @@ void Log::CreateAppenderFromConfigLine(std::string const& appenderName, std::str } AppenderFlags flags = APPENDER_FLAGS_NONE; - AppenderType type = AppenderType(atoi(*iter++)); - LogLevel level = LogLevel(atoi(*iter++)); + AppenderType type = AppenderType(Trinity::StringTo<uint8>(tokens[0]).value_or(APPENDER_INVALID)); + LogLevel level = LogLevel(Trinity::StringTo<uint8>(tokens[1]).value_or(LOG_LEVEL_INVALID)); - if (level > LOG_LEVEL_FATAL) + auto factoryFunction = appenderFactory.find(type); + if (factoryFunction == appenderFactory.end()) { - fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level %d for appender %s\n", level, name.c_str()); + fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type '%s' for appender %s\n", std::string(tokens[0]).c_str(), name.c_str()); return; } - if (size > 2) - flags = AppenderFlags(atoi(*iter++)); - - auto factoryFunction = appenderFactory.find(type); - if (factoryFunction == appenderFactory.end()) + if (level > NUM_ENABLED_LOG_LEVELS) { - fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown type %d for appender %s\n", type, name.c_str()); + fprintf(stderr, "Log::CreateAppenderFromConfig: Wrong Log Level '%s' for appender %s\n", std::string(tokens[1]).c_str(), name.c_str()); return; } + if (size > 2) + { + if (Optional<uint8> flagsVal = Trinity::StringTo<uint8>(tokens[2])) + flags = AppenderFlags(*flagsVal); + else + { + fprintf(stderr, "Log::CreateAppenderFromConfig: Unknown flags '%s' for appender %s\n", std::string(tokens[2]).c_str(), name.c_str()); + return; + } + } + try { - Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, std::vector<char const*>(iter, tokens.end())); + Appender* appender = factoryFunction->second(NextAppenderId(), name, level, flags, tokens); appenders[appender->getId()].reset(appender); } catch (InvalidAppenderArgsException const& iaae) { - fprintf(stderr, "%s", iaae.what()); + fprintf(stderr, "%s\n", iaae.what()); } } @@ -119,7 +127,6 @@ void Log::CreateLoggerFromConfigLine(std::string const& loggerName, std::string return; LogLevel level = LOG_LEVEL_DISABLED; - uint8 type = uint8(-1); std::string name = loggerName.substr(7); @@ -129,8 +136,7 @@ void Log::CreateLoggerFromConfigLine(std::string const& loggerName, std::string return; } - Tokenizer tokens(options, ','); - Tokenizer::const_iterator iter = tokens.begin(); + std::vector<std::string_view> tokens = Trinity::Tokenize(options, ',', true); if (tokens.size() != 2) { @@ -145,10 +151,10 @@ void Log::CreateLoggerFromConfigLine(std::string const& loggerName, std::string return; } - level = LogLevel(atoi(*iter++)); - if (level > LOG_LEVEL_FATAL) + level = LogLevel(Trinity::StringTo<uint8>(tokens[0]).value_or(LOG_LEVEL_INVALID)); + if (level > NUM_ENABLED_LOG_LEVELS) { - fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level %u for logger %s\n", type, name.c_str()); + fprintf(stderr, "Log::CreateLoggerFromConfig: Wrong Log Level '%s' for logger %s\n", std::string(tokens[0]).c_str(), name.c_str()); return; } @@ -158,20 +164,15 @@ void Log::CreateLoggerFromConfigLine(std::string const& loggerName, std::string logger = std::make_unique<Logger>(name, level); //fprintf(stdout, "Log::CreateLoggerFromConfig: Created Logger %s, Level %u\n", name.c_str(), level); - std::istringstream ss(*iter); - std::string str; - - ss >> str; - while (ss) + for (std::string_view appenderName : Trinity::Tokenize(tokens[1], ' ', false)) { - if (Appender* appender = GetAppenderByName(str)) + if (Appender* appender = GetAppenderByName(appenderName)) { logger->addAppender(appender->getId(), appender); //fprintf(stdout, "Log::CreateLoggerFromConfig: Added Appender %s to Logger %s\n", appender->getName().c_str(), name.c_str()); } else - fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist", str.c_str(), name.c_str()); - ss >> str; + fprintf(stderr, "Error while configuring Appender %s in Logger %s. Appender does not exist\n", std::string(appenderName).c_str(), name.c_str()); } } @@ -201,7 +202,7 @@ void Log::ReadLoggersFromConfig() Close(); // Clean any Logger or Appender created - AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, std::vector<char const*>()); + AppenderConsole* appender = new AppenderConsole(NextAppenderId(), "Console", LOG_LEVEL_DEBUG, APPENDER_FLAGS_NONE, {}); appenders[appender->getId()].reset(appender); Logger* rootLogger = new Logger(LOGGER_ROOT, LOG_LEVEL_ERROR); diff --git a/src/common/Logging/Log.h b/src/common/Logging/Log.h index a496687ab57..5ec20040187 100644 --- a/src/common/Logging/Log.h +++ b/src/common/Logging/Log.h @@ -40,12 +40,12 @@ namespace Trinity #define LOGGER_ROOT "root" -typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs); +typedef Appender*(*AppenderCreatorFn)(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& extraArgs); template <class AppenderImpl> -Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<char const*>&& extraArgs) +Appender* CreateAppender(uint8 id, std::string const& name, LogLevel level, AppenderFlags flags, std::vector<std::string_view> const& extraArgs) { - return new AppenderImpl(id, name, level, flags, std::forward<std::vector<char const*>>(extraArgs)); + return new AppenderImpl(id, name, level, flags, extraArgs); } class TC_COMMON_API Log @@ -90,8 +90,7 @@ class TC_COMMON_API Log template<class AppenderImpl> void RegisterAppender() { - using Index = typename AppenderImpl::TypeIndex; - RegisterAppender(Index::value, &CreateAppender<AppenderImpl>); + RegisterAppender(AppenderImpl::type, &CreateAppender<AppenderImpl>); } std::string const& GetLogsDir() const { return m_logsDir; } @@ -105,7 +104,7 @@ class TC_COMMON_API Log void write(std::unique_ptr<LogMessage>&& msg) const; Logger const* GetLoggerByType(std::string const& type) const; - Appender* GetAppenderByName(std::string const& name); + Appender* GetAppenderByName(std::string_view name); uint8 NextAppenderId(); void CreateAppenderFromConfig(std::string const& name); void CreateLoggerFromConfig(std::string const& name); diff --git a/src/common/Logging/LogCommon.h b/src/common/Logging/LogCommon.h index 04df9fb31d5..35844e0e0f7 100644 --- a/src/common/Logging/LogCommon.h +++ b/src/common/Logging/LogCommon.h @@ -18,7 +18,10 @@ #ifndef LogCommon_h__ #define LogCommon_h__ -enum LogLevel +#include "Define.h" + +// EnumUtils: DESCRIBE THIS +enum LogLevel : uint8 { LOG_LEVEL_DISABLED = 0, LOG_LEVEL_TRACE = 1, @@ -28,18 +31,22 @@ enum LogLevel LOG_LEVEL_ERROR = 5, LOG_LEVEL_FATAL = 6, - NUM_ENABLED_LOG_LEVELS = 6 + NUM_ENABLED_LOG_LEVELS = LOG_LEVEL_FATAL, // SKIP + LOG_LEVEL_INVALID = 0xFF // SKIP }; +// EnumUtils: DESCRIBE THIS enum AppenderType : uint8 { APPENDER_NONE, APPENDER_CONSOLE, APPENDER_FILE, - APPENDER_DB + APPENDER_DB, + + APPENDER_INVALID = 0xFF // SKIP }; -enum AppenderFlags +enum AppenderFlags : uint8 { APPENDER_FLAGS_NONE = 0x00, APPENDER_FLAGS_PREFIX_TIMESTAMP = 0x01, diff --git a/src/common/Logging/enuminfo_AppenderConsole.cpp b/src/common/Logging/enuminfo_AppenderConsole.cpp new file mode 100644 index 00000000000..1b5562b1f84 --- /dev/null +++ b/src/common/Logging/enuminfo_AppenderConsole.cpp @@ -0,0 +1,103 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "AppenderConsole.h" +#include "Define.h" +#include "SmartEnum.h" +#include <stdexcept> + +namespace Trinity::Impl::EnumUtilsImpl +{ + +/********************************************************************\ +|* data for enum 'ColorTypes' in 'AppenderConsole.h' auto-generated *| +\********************************************************************/ +template <> +TC_API_EXPORT EnumText EnumUtils<ColorTypes>::ToString(ColorTypes value) +{ + switch (value) + { + case BLACK: return { "BLACK", "BLACK", "" }; + case RED: return { "RED", "RED", "" }; + case GREEN: return { "GREEN", "GREEN", "" }; + case BROWN: return { "BROWN", "BROWN", "" }; + case BLUE: return { "BLUE", "BLUE", "" }; + case MAGENTA: return { "MAGENTA", "MAGENTA", "" }; + case CYAN: return { "CYAN", "CYAN", "" }; + case GREY: return { "GREY", "GREY", "" }; + case YELLOW: return { "YELLOW", "YELLOW", "" }; + case LRED: return { "LRED", "LRED", "" }; + case LGREEN: return { "LGREEN", "LGREEN", "" }; + case LBLUE: return { "LBLUE", "LBLUE", "" }; + case LMAGENTA: return { "LMAGENTA", "LMAGENTA", "" }; + case LCYAN: return { "LCYAN", "LCYAN", "" }; + case WHITE: return { "WHITE", "WHITE", "" }; + default: throw std::out_of_range("value"); + } +} + +template <> +TC_API_EXPORT size_t EnumUtils<ColorTypes>::Count() { return 15; } + +template <> +TC_API_EXPORT ColorTypes EnumUtils<ColorTypes>::FromIndex(size_t index) +{ + switch (index) + { + case 0: return BLACK; + case 1: return RED; + case 2: return GREEN; + case 3: return BROWN; + case 4: return BLUE; + case 5: return MAGENTA; + case 6: return CYAN; + case 7: return GREY; + case 8: return YELLOW; + case 9: return LRED; + case 10: return LGREEN; + case 11: return LBLUE; + case 12: return LMAGENTA; + case 13: return LCYAN; + case 14: return WHITE; + default: throw std::out_of_range("index"); + } +} + +template <> +TC_API_EXPORT size_t EnumUtils<ColorTypes>::ToIndex(ColorTypes value) +{ + switch (value) + { + case BLACK: return 0; + case RED: return 1; + case GREEN: return 2; + case BROWN: return 3; + case BLUE: return 4; + case MAGENTA: return 5; + case CYAN: return 6; + case GREY: return 7; + case YELLOW: return 8; + case LRED: return 9; + case LGREEN: return 10; + case LBLUE: return 11; + case LMAGENTA: return 12; + case LCYAN: return 13; + case WHITE: return 14; + default: throw std::out_of_range("value"); + } +} +} diff --git a/src/common/Logging/enuminfo_LogCommon.cpp b/src/common/Logging/enuminfo_LogCommon.cpp new file mode 100644 index 00000000000..de7d35e118e --- /dev/null +++ b/src/common/Logging/enuminfo_LogCommon.cpp @@ -0,0 +1,124 @@ +/* + * This file is part of the TrinityCore Project. See AUTHORS file for Copyright information + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + * + * You should have received a copy of the GNU General Public License along + * with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include "LogCommon.h" +#include "Define.h" +#include "SmartEnum.h" +#include <stdexcept> + +namespace Trinity::Impl::EnumUtilsImpl +{ + +/************************************************************\ +|* data for enum 'LogLevel' in 'LogCommon.h' auto-generated *| +\************************************************************/ +template <> +TC_API_EXPORT EnumText EnumUtils<LogLevel>::ToString(LogLevel value) +{ + switch (value) + { + case LOG_LEVEL_DISABLED: return { "LOG_LEVEL_DISABLED", "LOG_LEVEL_DISABLED", "" }; + case LOG_LEVEL_TRACE: return { "LOG_LEVEL_TRACE", "LOG_LEVEL_TRACE", "" }; + case LOG_LEVEL_DEBUG: return { "LOG_LEVEL_DEBUG", "LOG_LEVEL_DEBUG", "" }; + case LOG_LEVEL_INFO: return { "LOG_LEVEL_INFO", "LOG_LEVEL_INFO", "" }; + case LOG_LEVEL_WARN: return { "LOG_LEVEL_WARN", "LOG_LEVEL_WARN", "" }; + case LOG_LEVEL_ERROR: return { "LOG_LEVEL_ERROR", "LOG_LEVEL_ERROR", "" }; + case LOG_LEVEL_FATAL: return { "LOG_LEVEL_FATAL", "LOG_LEVEL_FATAL", "" }; + default: throw std::out_of_range("value"); + } +} + +template <> +TC_API_EXPORT size_t EnumUtils<LogLevel>::Count() { return 7; } + +template <> +TC_API_EXPORT LogLevel EnumUtils<LogLevel>::FromIndex(size_t index) +{ + switch (index) + { + case 0: return LOG_LEVEL_DISABLED; + case 1: return LOG_LEVEL_TRACE; + case 2: return LOG_LEVEL_DEBUG; + case 3: return LOG_LEVEL_INFO; + case 4: return LOG_LEVEL_WARN; + case 5: return LOG_LEVEL_ERROR; + case 6: return LOG_LEVEL_FATAL; + default: throw std::out_of_range("index"); + } +} + +template <> +TC_API_EXPORT size_t EnumUtils<LogLevel>::ToIndex(LogLevel value) +{ + switch (value) + { + case LOG_LEVEL_DISABLED: return 0; + case LOG_LEVEL_TRACE: return 1; + case LOG_LEVEL_DEBUG: return 2; + case LOG_LEVEL_INFO: return 3; + case LOG_LEVEL_WARN: return 4; + case LOG_LEVEL_ERROR: return 5; + case LOG_LEVEL_FATAL: return 6; + default: throw std::out_of_range("value"); + } +} + +/****************************************************************\ +|* data for enum 'AppenderType' in 'LogCommon.h' auto-generated *| +\****************************************************************/ +template <> +TC_API_EXPORT EnumText EnumUtils<AppenderType>::ToString(AppenderType value) +{ + switch (value) + { + case APPENDER_NONE: return { "APPENDER_NONE", "APPENDER_NONE", "" }; + case APPENDER_CONSOLE: return { "APPENDER_CONSOLE", "APPENDER_CONSOLE", "" }; + case APPENDER_FILE: return { "APPENDER_FILE", "APPENDER_FILE", "" }; + case APPENDER_DB: return { "APPENDER_DB", "APPENDER_DB", "" }; + default: throw std::out_of_range("value"); + } +} + +template <> +TC_API_EXPORT size_t EnumUtils<AppenderType>::Count() { return 4; } + +template <> +TC_API_EXPORT AppenderType EnumUtils<AppenderType>::FromIndex(size_t index) +{ + switch (index) + { + case 0: return APPENDER_NONE; + case 1: return APPENDER_CONSOLE; + case 2: return APPENDER_FILE; + case 3: return APPENDER_DB; + default: throw std::out_of_range("index"); + } +} + +template <> +TC_API_EXPORT size_t EnumUtils<AppenderType>::ToIndex(AppenderType value) +{ + switch (value) + { + case APPENDER_NONE: return 0; + case APPENDER_CONSOLE: return 1; + case APPENDER_FILE: return 2; + case APPENDER_DB: return 3; + default: throw std::out_of_range("value"); + } +} +} diff --git a/src/common/Metric/Metric.cpp b/src/common/Metric/Metric.cpp index b5762dbd8e2..97d68568a3f 100644 --- a/src/common/Metric/Metric.cpp +++ b/src/common/Metric/Metric.cpp @@ -89,7 +89,7 @@ void Metric::LoadFromConfigs() return; } - Tokenizer tokens(connectionInfo, ';'); + std::vector<std::string_view> tokens = Trinity::Tokenize(connectionInfo, ';', true); if (tokens.size() != 3) { TC_LOG_ERROR("metric", "'Metric.ConnectionInfo' specified with wrong format in configuration file."); 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); |