summaryrefslogtreecommitdiffstats
path: root/cxxformat.hpp
diff options
context:
space:
mode:
authorMarkus Mittendrein <git@maxmitti.tk>2019-12-05 14:58:37 +0100
committerMarkus Mittendrein <git@maxmitti.tk>2019-12-05 14:58:37 +0100
commit1fd208995b70f943edc324e7f89ca57a402fa85a (patch)
tree1d3a9c98b478a61146399ffcd56a35d8a6d13730 /cxxformat.hpp
parente483d06fe31a2569c58aed429fe6d69f4e7f208c (diff)
downloadcxxformat-1fd208995b70f943edc324e7f89ca57a402fa85a.tar.gz
cxxformat-1fd208995b70f943edc324e7f89ca57a402fa85a.zip
Improve syntax and name of compile time variant
Diffstat (limited to 'cxxformat.hpp')
-rw-r--r--cxxformat.hpp62
1 files changed, 41 insertions, 21 deletions
diff --git a/cxxformat.hpp b/cxxformat.hpp
index 6a86e4c..1dd919e 100644
--- a/cxxformat.hpp
+++ b/cxxformat.hpp
@@ -411,34 +411,51 @@ private:
template<size_t... indices>
constexpr str<N + 1> appendCharHelper(const char c, std::index_sequence<indices...>) const
{
- return str<N + 1>{s[indices]..., c, '\0'};
+ return str<N + 1>{s[indices]..., c};
}
template<size_t... indices>
static constexpr str<N + 1> prependCharHelper(const char c, const str<N> &s, std::index_sequence<indices...>)
{
- return str<N + 1>{c, s.s[indices]..., '\0'};
+ return str<N + 1>{c, s.s[indices]...};
}
template<auto other, size_t... ownIndices, size_t... othersIndices>
constexpr str<N + sizeof...(othersIndices)> appendStrHelper(std::index_sequence<ownIndices...>, std::index_sequence<othersIndices...>) const
{
- return str<N + sizeof...(othersIndices)>{s[ownIndices]..., other.s[othersIndices]..., '\0'};
+ return str<N + sizeof...(othersIndices)>{s[ownIndices]..., other.s[othersIndices]...};
}
+
public:
+ template<size_t... indices>
+ constexpr str(const char (&s)[N + 1], std::index_sequence<indices...>) : s{s[indices]...}
+ {
+
+ }
+
+ constexpr str(const char (&s)[N + 1]) : str{s, std::make_index_sequence<N + 1>()}
+ {
+
+ }
+
+ template<typename... Chars>
+ constexpr str(Chars... chars) : s{chars..., '\0'}
+ {
+ static_assert(N == sizeof...(chars), "O.o");
+ }
template<size_t index>
- constexpr char get(str_index<index>) const
+ constexpr char get() const
{
static_assert(index < N, "str::get: index out of range");
return s[index];
}
template<size_t offset, size_t... indices>
- constexpr str<sizeof...(indices)> extract(std::index_sequence<indices...>, str_index<offset> = str_index<0>{}) const
+ constexpr str<sizeof...(indices)> extract(std::index_sequence<indices...>) const
{
static_assert(((indices + offset < N) && ...), "str::extract: index out of range");
- return str<sizeof...(indices)>{s[indices + offset]..., '\0'};
+ return str<sizeof...(indices)>{s[indices + offset]...};
}
constexpr str<N + 1> operator+(const char c) const
@@ -465,28 +482,31 @@ constexpr str<N + 1> operator+(const char c, const str<N> &other)
template<size_t N>
str(const char(&)[N]) -> str<N - 1>;
+template<typename... Chars>
+str(Chars... chars) -> str<sizeof...(Chars)>;
+
namespace detail
{
template<size_t i, size_t N>
constexpr char get(const str<N>& s)
{
- return s.get(str_index<i>{});
+ return s.template get<i>();
}
template<size_t N, size_t offset, size_t... indices>
constexpr str<sizeof...(indices)> extractStr(const str<N> &source, std::index_sequence<indices...>)
{
- return str<sizeof...(indices)>{get<indices + offset>(source)..., '\0'};
+ return str<sizeof...(indices)>{get<indices + offset>(source)...};
}
template<size_t start, size_t end = std::string::npos, bool endIsIndex = false, size_t N>
constexpr str<end == std::string::npos ? N - start : (endIsIndex ? end + 1 - start : end)> substr(const str<N> &s)
{
- static_assert(!endIsIndex || end < N, "End index / substr-length is out of range");
- if constexpr (end == std::string::npos) return substr<start, N - 1, true>(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<start, N - 1, true>(s);
else if constexpr (!endIsIndex) return substr<start, start + end - 1, true>(s);
- else if constexpr (endIsIndex && end + 1 - start == 0) return str{""};
- else return s.extract(std::make_index_sequence<end - start + 1>(), str_index<start>{});
+ else return s.template extract<start>(std::make_index_sequence<end - start + 1>());
}
template<typename T, auto s, size_t i = 0, bool allowSign = true, T parsedPart = 0>
@@ -532,7 +552,7 @@ namespace detail
return str<1>{'0' + N};
}
else return toStr<T, N / 10>() + char(N % 10 + '0');
- };
+ }
template<auto fmt, size_t i, size_t argumentIndex>
std::string format_s()
@@ -608,15 +628,15 @@ namespace detail
constexpr char conversion = checkReplaceAutoConversion<get<iAfterPrecision>(fmt), argumentIndex>(std::forward<Arg>(arg));
- if constexpr (conversion == 'c') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 0>().s, convert<char, false>(std::forward<Arg>(arg), "character", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
- else if constexpr (conversion == 'd' || conversion == 'i') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 'j'>().s, convert<std::intmax_t, false>(std::forward<Arg>(arg), "signed integer", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
- else if constexpr (conversion == 'u' || conversion == 'o' || conversion == 'x' || conversion == 'X') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 'j'>().s, convert<std::uintmax_t, false>(std::forward<Arg>(arg), "unsigned integer", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(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<fmt, conversion, i, iAfterPrecision, 0>().s, convert<double, false>(std::forward<Arg>(arg), "double", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
- else if constexpr (conversion == 'p') return substr<0, i - 1, true>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 0>().s, convert<const void *, false>(std::forward<Arg>(arg), "pointer", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
+ if constexpr (conversion == 'c') return substr<0, i>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 0>().s, convert<char, false>(std::forward<Arg>(arg), "character", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
+ else if constexpr (conversion == 'd' || conversion == 'i') return substr<0, i>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 'j'>().s, convert<std::intmax_t, false>(std::forward<Arg>(arg), "signed integer", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
+ else if constexpr (conversion == 'u' || conversion == 'o' || conversion == 'x' || conversion == 'X') return substr<0, i>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 'j'>().s, convert<std::uintmax_t, false>(std::forward<Arg>(arg), "unsigned integer", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(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<fmt, conversion, i, iAfterPrecision, 0>().s, convert<double, false>(std::forward<Arg>(arg), "double", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
+ else if constexpr (conversion == 'p') return substr<0, i>(fmt).s + strprintf(makeDirective<fmt, conversion, i, iAfterPrecision, 0>().s, convert<const void *, false>(std::forward<Arg>(arg), "pointer", argumentIndex)) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
else if constexpr (conversion == 's')
{
const auto& string = convert<string_or_string_view<remove_cvref_t<Arg>>, false>(std::forward<Arg>(arg), "string", argumentIndex);
- return substr<0, i - 1, true>(fmt).s + strprintf((str{"%."}.s + std::to_string(determineStringPrecision<havePrecision, fmt, iAfterFieldWidth, iAfterPrecision>(string)) + 's').c_str(), string.data()) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
+ return substr<0, i>(fmt).s + strprintf((str{"%."}.s + std::to_string(determineStringPrecision<havePrecision, fmt, iAfterFieldWidth, iAfterPrecision>(string)) + 's').c_str(), string.data()) + format_s<substr<iAfterPrecision + 1>(fmt), 0, argumentIndex + 1>(std::forward<Args>(args)...);
}
else
{
@@ -628,8 +648,8 @@ namespace detail
}
}
-template<auto fmt, typename... Args>
-std::string format_s(Args &&...args)
+template<str fmt, typename... Args>
+std::string format(Args &&...args)
{
return detail::format_s<fmt, 0, 1>(std::forward<Args>(args)...);
}