From 1fd208995b70f943edc324e7f89ca57a402fa85a Mon Sep 17 00:00:00 2001 From: Markus Mittendrein Date: Thu, 5 Dec 2019 14:58:37 +0100 Subject: Improve syntax and name of compile time variant --- cxxformat.hpp | 62 +++++++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 41 insertions(+), 21 deletions(-) (limited to 'cxxformat.hpp') diff --git a/cxxformat.hpp b/cxxformat.hpp index 6a86e4c..1dd919e 100644 --- a/cxxformat.hpp +++ b/cxxformat.hpp @@ -411,34 +411,51 @@ private: template constexpr str appendCharHelper(const char c, std::index_sequence) const { - return str{s[indices]..., c, '\0'}; + return str{s[indices]..., c}; } template static constexpr str prependCharHelper(const char c, const str &s, std::index_sequence) { - return str{c, s.s[indices]..., '\0'}; + return str{c, s.s[indices]...}; } template constexpr str appendStrHelper(std::index_sequence, std::index_sequence) const { - return str{s[ownIndices]..., other.s[othersIndices]..., '\0'}; + return str{s[ownIndices]..., other.s[othersIndices]...}; } + public: + template + constexpr str(const char (&s)[N + 1], std::index_sequence) : s{s[indices]...} + { + + } + + constexpr str(const char (&s)[N + 1]) : str{s, std::make_index_sequence()} + { + + } + + template + constexpr str(Chars... chars) : s{chars..., '\0'} + { + static_assert(N == sizeof...(chars), "O.o"); + } template - constexpr char get(str_index) const + constexpr char get() const { static_assert(index < N, "str::get: index out of range"); return s[index]; } template - constexpr str extract(std::index_sequence, str_index = str_index<0>{}) const + constexpr str extract(std::index_sequence) const { static_assert(((indices + offset < N) && ...), "str::extract: index out of range"); - return str{s[indices + offset]..., '\0'}; + return str{s[indices + offset]...}; } constexpr str operator+(const char c) const @@ -465,28 +482,31 @@ constexpr str operator+(const char c, const str &other) template str(const char(&)[N]) -> str; +template +str(Chars... chars) -> str; + namespace detail { template constexpr char get(const str& s) { - return s.get(str_index{}); + return s.template get(); } template constexpr str extractStr(const str &source, std::index_sequence) { - return str{get(source)..., '\0'}; + return str{get(source)...}; } template constexpr str substr(const str &s) { - static_assert(!endIsIndex || end < N, "End index / substr-length is out of range"); - if constexpr (end == std::string::npos) return substr(s); + static_assert(!endIsIndex || end < N, "substr: end index / substr-length is out of range"); + if constexpr (!endIsIndex && end == 0) return str<0>{}; + else if constexpr (end == std::string::npos) return substr(s); else if constexpr (!endIsIndex) return substr(s); - else if constexpr (endIsIndex && end + 1 - start == 0) return str{""}; - else return s.extract(std::make_index_sequence(), str_index{}); + else return s.template extract(std::make_index_sequence()); } template @@ -532,7 +552,7 @@ namespace detail return str<1>{'0' + N}; } else return toStr() + char(N % 10 + '0'); - }; + } template std::string format_s() @@ -608,15 +628,15 @@ namespace detail constexpr char conversion = checkReplaceAutoConversion(fmt), argumentIndex>(std::forward(arg)); - if constexpr (conversion == 'c') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "character", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'd' || conversion == 'i') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "signed integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'u' || conversion == 'o' || conversion == 'x' || conversion == 'X') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "unsigned integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'e' || conversion == 'E' || conversion == 'f' || conversion == 'F' || conversion == 'g' || conversion == 'G' || conversion == 'a' || conversion == 'A') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "double", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); - else if constexpr (conversion == 'p') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "pointer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + if constexpr (conversion == 'c') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "character", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'd' || conversion == 'i') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "signed integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'u' || conversion == 'o' || conversion == 'x' || conversion == 'X') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "unsigned integer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'e' || conversion == 'E' || conversion == 'f' || conversion == 'F' || conversion == 'g' || conversion == 'G' || conversion == 'a' || conversion == 'A') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "double", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + else if constexpr (conversion == 'p') return substr<0, i>(fmt).s + strprintf(makeDirective().s, convert(std::forward(arg), "pointer", argumentIndex)) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); else if constexpr (conversion == 's') { const auto& string = convert>, false>(std::forward(arg), "string", argumentIndex); - return substr<0, i - 1, true>(fmt).s + strprintf((str{"%."}.s + std::to_string(determineStringPrecision(string)) + 's').c_str(), string.data()) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); + return substr<0, i>(fmt).s + strprintf((str{"%."}.s + std::to_string(determineStringPrecision(string)) + 's').c_str(), string.data()) + format_s(fmt), 0, argumentIndex + 1>(std::forward(args)...); } else { @@ -628,8 +648,8 @@ namespace detail } } -template -std::string format_s(Args &&...args) +template +std::string format(Args &&...args) { return detail::format_s(std::forward(args)...); } -- cgit v1.2.3-54-g00ecf