aboutsummaryrefslogtreecommitdiff
path: root/include/cru/common/format.hpp
diff options
context:
space:
mode:
authorcrupest <crupest@outlook.com>2019-03-31 17:14:47 +0800
committercrupest <crupest@outlook.com>2019-03-31 17:14:47 +0800
commitfbfd90255731954fb80483f4ba7188d3611fafec (patch)
tree8e3283c911d7aec76130d6a1dc7f5d8a85512b59 /include/cru/common/format.hpp
parent877f65e2e2c40eecc7cfeb194dc9d391af60711b (diff)
downloadcru-fbfd90255731954fb80483f4ba7188d3611fafec.tar.gz
cru-fbfd90255731954fb80483f4ba7188d3611fafec.tar.bz2
cru-fbfd90255731954fb80483f4ba7188d3611fafec.zip
...
Diffstat (limited to 'include/cru/common/format.hpp')
-rw-r--r--include/cru/common/format.hpp104
1 files changed, 104 insertions, 0 deletions
diff --git a/include/cru/common/format.hpp b/include/cru/common/format.hpp
new file mode 100644
index 00000000..1fb6863a
--- /dev/null
+++ b/include/cru/common/format.hpp
@@ -0,0 +1,104 @@
+#pragma once
+#include "pre_config.hpp"
+
+#include <string>
+#include <string_view>
+
+namespace cru::util {
+namespace details {
+template <typename T>
+struct TypeTag {};
+
+constexpr std::wstring_view PlaceHolder(TypeTag<std::wstring>) {
+ return std::wstring_view(L"{}");
+}
+
+constexpr std::string_view PlaceHolder(TypeTag<std::string>) {
+ return std::string_view("{}");
+}
+
+template <typename TString>
+void FormatInternal(TString& string) {
+ const auto find_result = string.find(PlaceHolder(TypeTag<TString>{}));
+ if (find_result != TString::npos)
+ throw std::invalid_argument("There is more placeholders than args.");
+}
+
+template <typename TString, typename T, typename... TRest>
+void FormatInternal(TString& string, const T& arg, const TRest&... args) {
+ const auto find_result = string.find(PlaceHolder(TypeTag<TString>{}));
+ if (find_result == TString::npos)
+ throw std::invalid_argument("There is less placeholders than args.");
+
+ string.replace(find_result, 2, FormatToString(arg, TypeTag<TString>{}));
+ FormatInternal<TString>(string, args...);
+}
+} // namespace details
+
+template <typename... T>
+std::wstring Format(const std::wstring_view& format, const T&... args) {
+ std::wstring result(format);
+ details::FormatInternal<std::wstring>(result, args...);
+ return result;
+}
+
+template <typename... T>
+std::string Format(const std::string_view& format, const T&... args) {
+ std::string result(format);
+ details::FormatInternal<std::string>(result, args...);
+ return result;
+}
+
+#define CRU_FORMAT_NUMBER(type) \
+ inline std::string FormatToString(const type number, \
+ details::TypeTag<std::string>) { \
+ return std::to_string(number); \
+ } \
+ inline std::wstring FormatToString(const type number, \
+ details::TypeTag<std::wstring>) { \
+ return std::to_wstring(number); \
+ }
+
+CRU_FORMAT_NUMBER(int)
+CRU_FORMAT_NUMBER(short)
+CRU_FORMAT_NUMBER(long)
+CRU_FORMAT_NUMBER(long long)
+CRU_FORMAT_NUMBER(unsigned int)
+CRU_FORMAT_NUMBER(unsigned short)
+CRU_FORMAT_NUMBER(unsigned long)
+CRU_FORMAT_NUMBER(unsigned long long)
+CRU_FORMAT_NUMBER(float)
+CRU_FORMAT_NUMBER(double)
+
+#undef CRU_FORMAT_NUMBER
+
+inline std::wstring_view FormatToString(const std::wstring& string,
+ details::TypeTag<std::wstring>) {
+ return string;
+}
+
+inline std::string_view FormatToString(const std::string& string,
+ details::TypeTag<std::string>) {
+ return string;
+}
+
+inline std::wstring_view FormatToString(const std::wstring_view& string,
+ details::TypeTag<String>) {
+ return string;
+}
+
+inline std::string_view FormatToString(const std::string_view& string,
+ details::TypeTag<std::string>) {
+ return string;
+}
+
+inline std::wstring_view FormatToString(const wchar_t* string,
+ details::TypeTag<String>) {
+ return std::wstring_view(string);
+}
+
+inline std::string_view FormatToString(const char* string,
+ details::TypeTag<std::string>) {
+ return std::string(string);
+}
+} // namespace cru::util