42 constexpr It
parse(It it, It end)
44 if (it == end || *it ==
'}')
54 if (
next != end && (*
next ==
'<' || *
next ==
'>' || *
next ==
'^') && *it !=
'<' && *it !=
'>'
61 else if (*it ==
'<' || *it ==
'>' || *it ==
'^')
71 while (it != end && *it >=
'0' && *it <=
'9')
74 w = w * 10 +
static_cast<unsigned>(*it -
'0');
83 while (it != end && *it !=
'}')
93 if (
width <= inner.size())
98 const std::size_t pad =
width - inner.size();
102 return inner + std::string(pad,
fill);
105 std::size_t left = pad / 2;
106 std::size_t right = pad - left;
107 return std::string(left,
fill) + inner + std::string(right,
fill);
111 return std::string(pad,
fill) + inner;
121 for (
auto&& elem : seq)
127 std::format_to(std::back_inserter(core),
"{}", elem);
138 template <
class... T>
139 struct formatter<
std::variant<T...>>
141 constexpr auto parse(format_parse_context& ctx)
143 auto pos = ctx.begin();
144 while (pos != ctx.end() && *pos !=
'}')
153 auto format(
const std::variant<T...>& v, std::format_context& ctx)
const
156 [&ctx,
this](
const auto& value)
158 return std::vformat_to(ctx.out(),
m_format_string, std::make_format_args(value));
168 struct formatter<
std::byte>
170 constexpr auto parse(format_parse_context& ctx)
172 return m_underlying_formatter.parse(ctx);
175 auto format(std::byte b, std::format_context& ctx)
const
177 return std::format_to(ctx.out(),
"{:#04x}", std::to_integer<unsigned>(b));
183 std::formatter<unsigned> m_underlying_formatter;
189 template <
typename R>
190 concept RangeOfRanges = std::ranges::range<R> && std::ranges::range<std::ranges::range_value_t<R>>;
192 template <
typename T>
193 concept Format =
requires(
const T& t) { std::format(t, 1); };
195 template <
typename T>
201 for (
const char c : str)
203 if ((c & 0xC0) != 0x80)
211 constexpr size_t max_width(
const std::ranges::input_range
auto& data)
214 for (
const auto& value : data)
216 if constexpr (std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>, std::string>
217 || std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>, std::string_view>
218 || std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>,
const char*>
219 || std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>,
char*>)
231 template <RangeOfRanges Columns>
234 std::vector<size_t> widths;
235 widths.reserve(std::ranges::size(columns));
236 for (
const auto& col : columns)
243 template <
typename OutputIt, std::ranges::input_range W
idths, std::ranges::input_range Values>
244 requires(std::same_as<std::ranges::range_value_t<Widths>,
size_t>)
246 to_row(OutputIt out,
const Widths& widths,
const Values& values, std::string_view separator =
"|")
249 if (std::ranges::size(values) == 0)
253 auto value_it = values.begin();
254 auto width_it = widths.begin();
255 for (
size_t i = 0; i < std::ranges::size(values); ++i)
257 const std::string fmt = std::format(
"{}{{:>{}}}", separator, *width_it);
258 const auto& value = *value_it;
259 std::vformat_to(out, fmt, std::make_format_args(value));
263 std::format_to(out,
"{}", separator);
266 template <
typename OutputIt>
270 if (std::ranges::size(widths) == 0)
274 const size_t count = std::ranges::size(widths) + 1 + std::reduce(widths.begin(), widths.end());
275 std::format_to(out,
"{}", std::string(count, separator[0]));
278#if defined(__clang__)
279# pragma clang diagnostic push
280# pragma clang diagnostic ignored "-Wsign-conversion"
283# pragma GCC diagnostic push
284# pragma GCC diagnostic ignored "-Wsign-conversion"
286 template <std::ranges::input_range Headers, RangeOfRanges Columns,
typename OutputIt>
287 requires(std::convertible_to<std::ranges::range_value_t<Headers>, std::string>)
290 const size_t column_count = std::ranges::size(columns);
292 if (column_count == 0)
298 if (column_count > 0)
300 for (
auto it = columns.begin() + 1; it != columns.end(); ++it)
309 for (
size_t i = 0; i < std::ranges::size(headers); ++i)
311 widths[i] = std::max(widths[i], std::ranges::size(headers[i]));
313 to_row(out, widths, headers);
314 std::format_to(out,
"{}",
'\n');
316 std::format_to(out,
"{}",
'\n');
319 for (
size_t i = 0; i < std::ranges::size(columns[0]); ++i)
321 const auto row_range = std::views::transform(
323 [i](
const auto& column)
328 to_row(out, widths, row_range);
329 std::format_to(out,
"{}",
'\n');
335# pragma GCC diagnostic pop
337#if defined(__clang__)
338# 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 InputIt next(InputIt it, Distance n)
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)
constexpr size_t size_of_utf8(const std::string_view str)
Extensions to the C++ standard library.