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)
217 std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>, std::string>
218 || std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>, std::string_view>
219 || std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>,
const char*>
220 || std::is_same_v<std::remove_cvref_t<std::decay_t<
decltype(value)>>,
char*>
233 template <RangeOfRanges Columns>
236 std::vector<size_t> widths;
237 widths.reserve(std::ranges::size(columns));
238 for (
const auto& col : columns)
245 template <
typename OutputIt, std::ranges::input_range W
idths, std::ranges::input_range Values>
246 requires(std::same_as<std::ranges::range_value_t<Widths>,
size_t>)
248 to_row(OutputIt out,
const Widths& widths,
const Values& values, std::string_view separator =
"|")
251 if (std::ranges::size(values) == 0)
255 auto value_it = values.begin();
256 auto width_it = widths.begin();
257 for (
size_t i = 0; i < std::ranges::size(values); ++i)
259 const std::string fmt = std::format(
"{}{{:>{}}}", separator, *width_it);
260 const auto& value = *value_it;
261 std::vformat_to(out, fmt, std::make_format_args(value));
265 std::format_to(out,
"{}", separator);
268 template <
typename OutputIt>
272 if (std::ranges::size(widths) == 0)
276 const size_t count = std::ranges::size(widths) + 1 + std::reduce(widths.begin(), widths.end());
277 std::format_to(out,
"{}", std::string(count, separator[0]));
280#if defined(__clang__)
281# pragma clang diagnostic push
282# pragma clang diagnostic ignored "-Wsign-conversion"
285# pragma GCC diagnostic push
286# pragma GCC diagnostic ignored "-Wsign-conversion"
288 template <std::ranges::input_range Headers, RangeOfRanges Columns,
typename OutputIt>
289 requires(std::convertible_to<std::ranges::range_value_t<Headers>, std::string>)
292 const size_t column_count = std::ranges::size(columns);
294 if (column_count == 0)
300 if (column_count > 0)
302 for (
auto it = columns.begin() + 1; it != columns.end(); ++it)
311 for (
size_t i = 0; i < std::ranges::size(headers); ++i)
313 widths[i] = std::max(widths[i], std::ranges::size(headers[i]));
315 to_row(out, widths, headers);
316 std::format_to(out,
"{}",
'\n');
318 std::format_to(out,
"{}",
'\n');
321 for (
size_t i = 0; i < std::ranges::size(columns[0]); ++i)
323 const auto row_range = std::views::transform(
325 [i](
const auto& column)
330 to_row(out, widths, row_range);
331 std::format_to(out,
"{}",
'\n');
337# pragma GCC diagnostic pop
339#if defined(__clang__)
340# 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.