support for printing iterable objects and tuples with %s

This commit is contained in:
q66 2017-02-20 19:36:38 +01:00
parent 3aa5db5b1c
commit 3f983afae5

View file

@ -679,6 +679,30 @@ private:
write_str(writer, escape, val); write_str(writer, escape, val);
return; return;
} }
/* tuples */
if constexpr(detail::is_tuple_like<T>) {
if (spec() != 's') {
throw format_error{"ranges need the '%s' spec"};
}
writer.put('<');
write_tuple_val<0, std::tuple_size<T>::value>(
writer, !(flags() & FMT_FLAG_DASH), ", ", val
);
writer.put('>');
return;
}
/* ranges */
if constexpr(detail::iterable_test<T>) {
if (spec() != 's') {
throw format_error{"tuples need the '%s' spec"};
}
writer.put('{');
write_range_val(
writer, !(flags() & FMT_FLAG_DASH), false, "%s", ", ", val
);
writer.put('}');
return;
}
/* bools, check if printing as string, otherwise convert to int */ /* bools, check if printing as string, otherwise convert to int */
if constexpr(std::is_same_v<T, bool>) { if constexpr(std::is_same_v<T, bool>) {
if (spec() == 's') { if (spec() == 's') {
@ -745,26 +769,28 @@ private:
template<typename R, typename T> template<typename R, typename T>
inline void write_range_item( inline void write_range_item(
R &writer, bool expandval, string_range fmt, T const &item R &writer, bool escape, bool expandval, string_range fmt, T const &item
) const { ) const {
if constexpr(detail::is_tuple_like<T>) { if constexpr(detail::is_tuple_like<T>) {
if (expandval) { if (expandval) {
std::apply([&writer, esc = p_nested_escape, &fmt]( std::apply([&writer, escape, &fmt](
auto const &...args auto const &...args
) mutable { ) mutable {
format_spec sp{fmt, esc}; format_spec sp{fmt, escape};
sp.write_fmt(writer, args...); sp.write_fmt(writer, args...);
}, item); }, item);
return; return;
} }
} }
format_spec sp{fmt, p_nested_escape}; format_spec sp{fmt, escape};
sp.write_fmt(writer, item); sp.write_fmt(writer, item);
} }
template<typename R, typename T> template<typename R, typename T>
void write_range_val( void write_range_val(
R &writer, bool expandval, string_range sep, T const &val R &writer, bool escape, bool expandval, string_range ifmt,
string_range sep,
T const &val
) const { ) const {
if constexpr(detail::iterable_test<T>) { if constexpr(detail::iterable_test<T>) {
auto range = ostd::iter(val); auto range = ostd::iter(val);
@ -772,7 +798,7 @@ private:
return; return;
} }
for (;;) { for (;;) {
write_range_item(writer, expandval, rest(), range.front()); write_range_item(writer, escape, expandval, ifmt, range.front());
range.pop_front(); range.pop_front();
if (range.empty()) { if (range.empty()) {
break; break;
@ -784,6 +810,18 @@ private:
} }
} }
template<size_t I, size_t N, typename R, typename T>
void write_tuple_val(
R &writer, bool escape, string_range sep, T const &tup
) const {
format_spec sp{"%s", escape};
sp.write_fmt(writer, std::get<I>(tup));
if constexpr(I < (N - 1)) {
range_put_all(writer, sep);
write_tuple_val<I + 1, N>(writer, escape, sep, tup);
}
}
/* range writer */ /* range writer */
template<typename R, typename T, typename ...A> template<typename R, typename T, typename ...A>
void write_range( void write_range(
@ -797,7 +835,7 @@ private:
write_range(writer, idx - 1, expandval, sep, args...); write_range(writer, idx - 1, expandval, sep, args...);
} }
} else { } else {
write_range_val(writer, expandval, sep, val); write_range_val(writer, nested_escape(), expandval, rest(), sep, val);
} }
} }