summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--cxxformat.hpp62
-rw-r--r--main.cpp9
2 files changed, 46 insertions, 25 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)...);
}
diff --git a/main.cpp b/main.cpp
index bea2436..62c55de 100644
--- a/main.cpp
+++ b/main.cpp
@@ -40,11 +40,12 @@ struct format::AutoConversion<std::array<T, N>> : format::SimpleAutoConversion<'
template<size_t N, typename T>
struct format::AutoConversion<T[N], std::enable_if_t<!std::is_same_v<format::detail::remove_cvref_t<T>, char>>> : format::SimpleAutoConversion<'s', const T(&)[N]> {};
-int main(int argc, char *argv[])
+int main(int, char *[])
{
- const std::array<int, 5> array[] = {std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}};
- std::cout << format::format_s<format::str{"Hello %s: %d %03.5f %V"}>("World", 7, 3.5, &array) << std::endl;
- std::cout << format::format("%v%v%v%v%v", 'H', 'e', 'l', 'l', 'o') << std::endl;
+ constexpr std::array<int, 5> array[] = {std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}, std::array{1, 2, 3, 4, 5}};
+
+ std::cout << format::format<"Hello %s: %d %03.5f %V">("World", 7, 3.5, array) << std::endl;
+ std::cout << format::format<"%v%v%v%v%v">('H', 'e', 'l', 'l', 'o') << std::endl;
std::cout << format::format("%V", &array) << std::endl;
std::cout << format::format("%s", std::array{1, 2, 3, 4, 5}) << std::endl;
std::cout << format::format("Hello %v: %-7v %v", "World", 3.5, 5) << std::endl;