From 76f62be24b7e612b1f6880f9d7b0ddc07a8d38eb Mon Sep 17 00:00:00 2001 From: crupest Date: Sat, 18 Apr 2020 00:22:41 +0800 Subject: ... --- include/cru/common/format.hpp | 99 ++++++++++++++++++++++++++++--------------- include/cru/common/logger.hpp | 47 ++++++-------------- 2 files changed, 76 insertions(+), 70 deletions(-) (limited to 'include/cru/common') diff --git a/include/cru/common/format.hpp b/include/cru/common/format.hpp index 4405c8c5..4276880e 100644 --- a/include/cru/common/format.hpp +++ b/include/cru/common/format.hpp @@ -7,62 +7,91 @@ namespace cru::util { namespace details { -template +template struct FormatTrait {}; template <> -struct FormatTrait { - static constexpr std::string_view placeholder = "{}"; - using ResultType = std::string; +struct FormatTrait { + using StringType = std::string; + using ViewType = std::string_view; using StreamType = std::stringstream; + static constexpr ViewType placeholder = "{}"; }; template <> -struct FormatTrait { - static constexpr std::wstring_view placeholder = L"{}"; - using ResultType = std::wstring; +struct FormatTrait { + using StringType = std::wstring; + using ViewType = std::wstring_view; using StreamType = std::wstringstream; + static constexpr ViewType placeholder = L"{}"; +}; +} // namespace details + +template +struct Formatter { + static typename TFormatTrait::StringType Format(const T& value) { + typename TFormatTrait::StreamType stream; + stream << value; + return stream.str(); + } }; -template -void FormatInternal(typename FormatTrait::StreamType& stream, - const TStringView& string) { - const auto find_result = string.find(FormatTrait::placeholder); - if (find_result != TStringView::npos) +namespace details { +template +void FormatInternal(TString& string) { + using Trait = FormatTrait; + constexpr const auto& placeholder = Trait::placeholder; + + const auto find_result = string.find(placeholder); + if (find_result != TString::npos) throw std::invalid_argument("There is more placeholders than args."); - stream << string; } -template -void FormatInternal(typename FormatTrait::StreamType& stream, - const TStringView& string, const T& arg, - const TRest&... args) { - const auto find_result = string.find(FormatTrait::placeholder); - if (find_result == TStringView::npos) - throw std::invalid_argument("There is less placeholders than args."); - - stream << string.substr(0, find_result); - stream << arg; +template +void FormatInternal(TString& string, const T& arg, const TRest&... args) { + using Trait = FormatTrait; + constexpr const auto& placeholder = Trait::placeholder; - FormatInternal(stream, string.substr(find_result + 2), args...); -} + const auto find_result = string.find(placeholder); + if (find_result == TString::npos) + throw std::invalid_argument("There is less placeholders than args."); -template -auto FormatTemplate(const TStringView& format, const T&... args) -> - typename FormatTrait::ResultType { - typename FormatTrait::StreamType stream; - FormatInternal(stream, format, args...); - return stream.str(); + string.replace(find_result, 2, Formatter::Format(arg)); + FormatInternal(string, args...); } } // namespace details template -std::wstring Format(const std::wstring_view& format, const T&... args) { - return details::FormatTemplate(format, args...); +std::wstring Format(std::wstring format, const T&... args) { + details::FormatInternal(format, args...); + return format; } template -std::string Format(const std::string_view& format, const T&... args) { - return details::FormatTemplate(format, args...); +std::string Format(std::string format, const T&... args) { + details::FormatInternal(format, args...); + return format; +} + +// Why is two overloads below exist? +// Because people should be able to pass string_view instance as format. +// However, the two overloads above do not accept string_view as format due to +// conversion from string_view to string is explicit. +// +// Why not just overload but SFINAE? +// Because I want to make two overloads below worse than the two ones above. +// Otherwise it will be ambiguous when pass const char* as format. +// + +template +auto Format(T format, const TArgs&... args) + -> std::enable_if_t, std::wstring> { + return Format(std::wstring{format}, args...); +} + +template +auto Format(T format, const TArgs&... args) + -> std::enable_if_t, std::string> { + return Format(std::string{format}, args...); } } // namespace cru::util diff --git a/include/cru/common/logger.hpp b/include/cru/common/logger.hpp index b947ba99..38ddb6eb 100644 --- a/include/cru/common/logger.hpp +++ b/include/cru/common/logger.hpp @@ -60,56 +60,33 @@ class Logger : public Object { public: void Log(LogLevel level, const std::string_view& s); - template - void Debug(const std::string_view& format, TArgs&&... args) { -#ifdef CRU_DEBUG - Log(LogLevel::Debug, util::Format(format, std::forward(args)...)); -#endif - } - - template - void Info(const std::string_view& format, TArgs&&... args) { - Log(LogLevel::Info, util::Format(format, std::forward(args)...)); - } - - template - void Warn(const std::string_view& format, TArgs&&... args) { - Log(LogLevel::Warn, util::Format(format, std::forward(args)...)); - } - - template - void Error(const std::string_view& format, TArgs&&... args) { - Log(LogLevel::Error, util::Format(format, std::forward(args)...)); - } - public: std::list> sources_; }; template -void Debug([[maybe_unused]] const std::string_view& format, - [[maybe_unused]] TArgs&&... args) { +void Debug([[maybe_unused]] TArgs&&... args) { #ifdef CRU_DEBUG - Logger::GetInstance()->Log( - LogLevel::Debug, util::Format(format, std::forward(args)...)); + Logger::GetInstance()->Log(LogLevel::Debug, + util::Format(std::forward(args)...)); #endif } template -void Info(const std::string_view& format, TArgs&&... args) { - Logger::GetInstance()->Log( - LogLevel::Info, util::Format(format, std::forward(args)...)); +void Info(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Info, + util::Format(std::forward(args)...)); } template -void Warn(const std::string_view& format, TArgs&&... args) { - Logger::GetInstance()->Log( - LogLevel::Warn, util::Format(format, std::forward(args)...)); +void Warn(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Warn, + util::Format(std::forward(args)...)); } template -void Error(const std::string_view& format, TArgs&&... args) { - Logger::GetInstance()->Log( - LogLevel::Error, util::Format(format, std::forward(args)...)); +void Error(TArgs&&... args) { + Logger::GetInstance()->Log(LogLevel::Error, + util::Format(std::forward(args)...)); } } // namespace cru::log -- cgit v1.2.3