32 struct formatter<
std::variant<T...>>
34 constexpr auto parse(format_parse_context& ctx)
36 auto pos = ctx.begin();
37 while (pos != ctx.end() && *pos !=
'}')
46 auto format(
const std::variant<T...>& v, std::format_context& ctx)
const
49 [&ctx,
this](
const auto& value)
51 return std::vformat_to(ctx.out(),
m_format_string, std::make_format_args(value));
64 concept RangeOfRanges = std::ranges::range<R> && std::ranges::range<std::ranges::range_value_t<R>>;
67 concept Format =
requires(
const T& t) { std::format(t, 1); };
72 constexpr size_t max_width(
const std::ranges::input_range
auto& data)
75 for (
const auto& value : data)
82 template <RangeOfRanges Columns>
85 std::vector<size_t> widths;
86 widths.reserve(std::ranges::size(columns));
87 for (
const auto& col : columns)
94 template <
typename OutputIt, std::ranges::input_range W
idths, std::ranges::input_range Values>
95 requires(std::same_as<std::ranges::range_value_t<Widths>,
size_t>)
97 to_row(OutputIt out,
const Widths& widths,
const Values& values, std::string_view separator =
"|")
100 if (std::ranges::size(values) == 0)
104 auto value_it = values.begin();
105 auto width_it = widths.begin();
106 for (
size_t i = 0; i < std::ranges::size(values); ++i)
108 const std::string fmt = std::format(
"{}{{:>{}}}", separator, *width_it);
109 const auto& value = *value_it;
110 std::vformat_to(out, fmt, std::make_format_args(value));
114 std::format_to(out,
"{}", separator);
117 template <
typename OutputIt>
121 if (std::ranges::size(widths) == 0)
125 const size_t count = std::ranges::size(widths) + 1 + std::reduce(widths.begin(), widths.end());
126 std::format_to(out,
"{}", std::string(count, separator[0]));
129#if defined(__clang__)
130# pragma clang diagnostic push
131# pragma clang diagnostic ignored "-Wsign-conversion"
134# pragma GCC diagnostic push
135# pragma GCC diagnostic ignored "-Wsign-conversion"
137 template <std::ranges::input_range Headers, RangeOfRanges Columns,
typename OutputIt>
138 requires(std::convertible_to<std::ranges::range_value_t<Headers>, std::string>)
141 const size_t column_count = std::ranges::size(columns);
143 if (column_count == 0)
149 if (column_count > 0)
151 for (
auto it = columns.begin() + 1; it != columns.end(); ++it)
160 for (
size_t i = 0; i < std::ranges::size(headers); ++i)
162 widths[i] = std::max(widths[i], std::ranges::size(headers[i]));
164 to_row(out, widths, headers);
165 std::format_to(out,
"{}",
'\n');
167 std::format_to(out,
"{}",
'\n');
170 for (
size_t i = 0; i < std::ranges::size(columns[0]); ++i)
172 const auto row_range = std::views::transform(
174 [i](
const auto& column)
179 to_row(out, widths, row_range);
180 std::format_to(out,
"{}",
'\n');
186# pragma GCC diagnostic pop
188#if defined(__clang__)
189# pragma clang diagnostic pop
#define SPARROW_ASSERT_TRUE(expr__)
constexpr void horizontal_separator(OutputIt out, const std::vector< size_t > &widths, std::string_view separator="-")
constexpr void to_row(OutputIt out, const Widths &widths, const Values &values, std::string_view separator="|")
constexpr void to_table_with_columns(OutputIt out, const Headers &headers, const Columns &columns)
constexpr size_t max_width(const std::ranges::input_range auto &data)
constexpr std::vector< size_t > columns_widths(const Columns &columns)