From fbfd90255731954fb80483f4ba7188d3611fafec Mon Sep 17 00:00:00 2001 From: crupest Date: Sun, 31 Mar 2019 17:14:47 +0800 Subject: ... --- include/cru/common/format.hpp | 104 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 include/cru/common/format.hpp (limited to 'include/cru/common/format.hpp') 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 +#include + +namespace cru::util { +namespace details { +template +struct TypeTag {}; + +constexpr std::wstring_view PlaceHolder(TypeTag) { + return std::wstring_view(L"{}"); +} + +constexpr std::string_view PlaceHolder(TypeTag) { + return std::string_view("{}"); +} + +template +void FormatInternal(TString& string) { + const auto find_result = string.find(PlaceHolder(TypeTag{})); + if (find_result != TString::npos) + throw std::invalid_argument("There is more placeholders than args."); +} + +template +void FormatInternal(TString& string, const T& arg, const TRest&... args) { + const auto find_result = string.find(PlaceHolder(TypeTag{})); + if (find_result == TString::npos) + throw std::invalid_argument("There is less placeholders than args."); + + string.replace(find_result, 2, FormatToString(arg, TypeTag{})); + FormatInternal(string, args...); +} +} // namespace details + +template +std::wstring Format(const std::wstring_view& format, const T&... args) { + std::wstring result(format); + details::FormatInternal(result, args...); + return result; +} + +template +std::string Format(const std::string_view& format, const T&... args) { + std::string result(format); + details::FormatInternal(result, args...); + return result; +} + +#define CRU_FORMAT_NUMBER(type) \ + inline std::string FormatToString(const type number, \ + details::TypeTag) { \ + return std::to_string(number); \ + } \ + inline std::wstring FormatToString(const type number, \ + details::TypeTag) { \ + 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) { + return string; +} + +inline std::string_view FormatToString(const std::string& string, + details::TypeTag) { + return string; +} + +inline std::wstring_view FormatToString(const std::wstring_view& string, + details::TypeTag) { + return string; +} + +inline std::string_view FormatToString(const std::string_view& string, + details::TypeTag) { + return string; +} + +inline std::wstring_view FormatToString(const wchar_t* string, + details::TypeTag) { + return std::wstring_view(string); +} + +inline std::string_view FormatToString(const char* string, + details::TypeTag) { + return std::string(string); +} +} // namespace cru::util -- cgit v1.2.3