#pragma once #include "pre.hpp" #include "base.hpp" namespace cru::util { namespace details { template struct TypeTag {}; constexpr StringView PlaceHolder(TypeTag) { return StringView(L"{}"); } constexpr MultiByteStringView PlaceHolder(TypeTag) { return MultiByteStringView("{}"); } 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 String Format(const StringView& format, const T&... args) { String result(format); details::FormatInternal(result, args...); return result; } template MultiByteString Format(const MultiByteStringView& format, const T&... args) { MultiByteString result(format); details::FormatInternal(result, args...); return result; } #define CRU_FORMAT_NUMBER(type) \ inline String FormatToString(const type number, details::TypeTag) { \ return std::to_wstring(number); \ } \ inline MultiByteString FormatToString(const type number, \ details::TypeTag) { \ return std::to_string(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 StringView FormatToString(const String& string, details::TypeTag) { return string; } inline MultiByteString FormatToString(const MultiByteString& string, details::TypeTag) { return string; } inline StringView FormatToString(const StringView& string, details::TypeTag) { return string; } inline MultiByteStringView FormatToString(const MultiByteStringView& string, details::TypeTag) { return string; } inline StringView FormatToString(const wchar_t* string, details::TypeTag) { return StringView(string); } inline MultiByteStringView FormatToString(const char* string, details::TypeTag) { return MultiByteString(string); } } // namespace cru::util