aboutsummaryrefslogtreecommitdiff
path: root/include/cru/common
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2020-04-18 00:22:41 +0800
committercrupest <crupest@outlook.com>2020-04-18 00:22:41 +0800
commit76f62be24b7e612b1f6880f9d7b0ddc07a8d38eb (patch)
tree1a7cac8773f1634ca32014eac6690433f55c0345 /include/cru/common
parentf81940e3ea386a6dfdda2ff4a42d8cede35f2c8a (diff)
downloadcru-76f62be24b7e612b1f6880f9d7b0ddc07a8d38eb.tar.gz
cru-76f62be24b7e612b1f6880f9d7b0ddc07a8d38eb.tar.bz2
cru-76f62be24b7e612b1f6880f9d7b0ddc07a8d38eb.zip
...
Diffstat (limited to 'include/cru/common')
-rw-r--r--include/cru/common/format.hpp99
-rw-r--r--include/cru/common/logger.hpp47
2 files changed, 76 insertions, 70 deletions
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 <typename T>
+template <typename TChar>
struct FormatTrait {};
template <>
-struct FormatTrait<std::string_view> {
- static constexpr std::string_view placeholder = "{}";
- using ResultType = std::string;
+struct FormatTrait<char> {
+ using StringType = std::string;
+ using ViewType = std::string_view;
using StreamType = std::stringstream;
+ static constexpr ViewType placeholder = "{}";
};
template <>
-struct FormatTrait<std::wstring_view> {
- static constexpr std::wstring_view placeholder = L"{}";
- using ResultType = std::wstring;
+struct FormatTrait<wchar_t> {
+ using StringType = std::wstring;
+ using ViewType = std::wstring_view;
using StreamType = std::wstringstream;
+ static constexpr ViewType placeholder = L"{}";
+};
+} // namespace details
+
+template <typename TFormatTrait, typename T>
+struct Formatter {
+ static typename TFormatTrait::StringType Format(const T& value) {
+ typename TFormatTrait::StreamType stream;
+ stream << value;
+ return stream.str();
+ }
};
-template <typename TStringView>
-void FormatInternal(typename FormatTrait<TStringView>::StreamType& stream,
- const TStringView& string) {
- const auto find_result = string.find(FormatTrait<TStringView>::placeholder);
- if (find_result != TStringView::npos)
+namespace details {
+template <typename TString>
+void FormatInternal(TString& string) {
+ using Trait = FormatTrait<TString::value_type>;
+ 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 <typename TStringView, typename T, typename... TRest>
-void FormatInternal(typename FormatTrait<TStringView>::StreamType& stream,
- const TStringView& string, const T& arg,
- const TRest&... args) {
- const auto find_result = string.find(FormatTrait<TStringView>::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 <typename TString, typename T, typename... TRest>
+void FormatInternal(TString& string, const T& arg, const TRest&... args) {
+ using Trait = FormatTrait<TString::value_type>;
+ 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 <typename TStringView, typename... T>
-auto FormatTemplate(const TStringView& format, const T&... args) ->
- typename FormatTrait<TStringView>::ResultType {
- typename FormatTrait<TStringView>::StreamType stream;
- FormatInternal(stream, format, args...);
- return stream.str();
+ string.replace(find_result, 2, Formatter<Trait, T>::Format(arg));
+ FormatInternal<TString>(string, args...);
}
} // namespace details
template <typename... T>
-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 <typename... T>
-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 <typename T, typename... TArgs>
+auto Format(T format, const TArgs&... args)
+ -> std::enable_if_t<std::is_same_v<T, std::wstring_view>, std::wstring> {
+ return Format(std::wstring{format}, args...);
+}
+
+template <typename T, typename... TArgs>
+auto Format(T format, const TArgs&... args)
+ -> std::enable_if_t<std::is_same_v<T, std::string_view>, 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 <typename... TArgs>
- void Debug(const std::string_view& format, TArgs&&... args) {
-#ifdef CRU_DEBUG
- Log(LogLevel::Debug, util::Format(format, std::forward<TArgs>(args)...));
-#endif
- }
-
- template <typename... TArgs>
- void Info(const std::string_view& format, TArgs&&... args) {
- Log(LogLevel::Info, util::Format(format, std::forward<TArgs>(args)...));
- }
-
- template <typename... TArgs>
- void Warn(const std::string_view& format, TArgs&&... args) {
- Log(LogLevel::Warn, util::Format(format, std::forward<TArgs>(args)...));
- }
-
- template <typename... TArgs>
- void Error(const std::string_view& format, TArgs&&... args) {
- Log(LogLevel::Error, util::Format(format, std::forward<TArgs>(args)...));
- }
-
public:
std::list<std::unique_ptr<ILogSource>> sources_;
};
template <typename... TArgs>
-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<TArgs>(args)...));
+ Logger::GetInstance()->Log(LogLevel::Debug,
+ util::Format(std::forward<TArgs>(args)...));
#endif
}
template <typename... TArgs>
-void Info(const std::string_view& format, TArgs&&... args) {
- Logger::GetInstance()->Log(
- LogLevel::Info, util::Format(format, std::forward<TArgs>(args)...));
+void Info(TArgs&&... args) {
+ Logger::GetInstance()->Log(LogLevel::Info,
+ util::Format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
-void Warn(const std::string_view& format, TArgs&&... args) {
- Logger::GetInstance()->Log(
- LogLevel::Warn, util::Format(format, std::forward<TArgs>(args)...));
+void Warn(TArgs&&... args) {
+ Logger::GetInstance()->Log(LogLevel::Warn,
+ util::Format(std::forward<TArgs>(args)...));
}
template <typename... TArgs>
-void Error(const std::string_view& format, TArgs&&... args) {
- Logger::GetInstance()->Log(
- LogLevel::Error, util::Format(format, std::forward<TArgs>(args)...));
+void Error(TArgs&&... args) {
+ Logger::GetInstance()->Log(LogLevel::Error,
+ util::Format(std::forward<TArgs>(args)...));
}
} // namespace cru::log