#pragma once // ReSharper disable once CppUnusedIncludeDirective #include "pre.hpp" #include "base.hpp" namespace cru { namespace details { constexpr StringView PlaceHolder(type_tag) { return StringView(L"{}"); } constexpr MultiByteStringView PlaceHolder(type_tag) { return MultiByteStringView("{}"); } template void FormatInternal(TString& string) { const auto find_result = string.find(PlaceHolder(type_tag{})); 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(type_tag{})); if (find_result == TString::npos) throw std::invalid_argument("There is less placeholders than args."); string.replace(find_result, 2, FormatToString(arg, type_tag{})); FormatInternal(string, args...); } } 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, type_tag) \ { \ return std::to_wstring(number); \ } \ inline MultiByteString FormatToString(const type number, type_tag) \ { \ 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, type_tag) { return string; } inline MultiByteString FormatToString(const MultiByteString& string, type_tag) { return string; } inline StringView FormatToString(const StringView& string, type_tag) { return string; } inline MultiByteStringView FormatToString(const MultiByteStringView& string, type_tag) { return string; } inline StringView FormatToString(const wchar_t* string, type_tag) { return StringView(string); } inline MultiByteStringView FormatToString(const char* string, type_tag) { return MultiByteString(string); } }