Skip to content

Commit 77bfd84

Browse files
committed
Split range and map formatters
1 parent 3af8ac7 commit 77bfd84

1 file changed

Lines changed: 66 additions & 19 deletions

File tree

include/fmt/ranges.h

Lines changed: 66 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -511,48 +511,95 @@ struct range_format_kind
511511
template <typename R, typename Char>
512512
struct formatter<
513513
R, Char,
514-
enable_if_t<conjunction<bool_constant<range_format_kind<R, Char>::value !=
515-
range_format::disabled>
514+
enable_if_t<conjunction<
515+
bool_constant<range_format_kind<R, Char>::value !=
516+
range_format::disabled &&
517+
range_format_kind<R, Char>::value != range_format::map>
516518
// Workaround a bug in MSVC 2015 and earlier.
517519
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
518-
,
519-
detail::is_formattable_delayed<R, Char>
520+
,
521+
detail::is_formattable_delayed<R, Char>
520522
#endif
521-
>::value>> {
523+
>::value>> {
522524
private:
523525
using range_type = detail::maybe_const_range<R>;
524526
range_formatter<detail::uncvref_type<range_type>, Char> range_formatter_;
525527

526-
FMT_CONSTEXPR void init(detail::range_format_constant<range_format::set>) {
528+
public:
529+
FMT_CONSTEXPR formatter() {
530+
if (range_format_kind<R, Char>::value != range_format::set) return;
527531
range_formatter_.set_brackets(detail::string_literal<Char, '{'>{},
528532
detail::string_literal<Char, '}'>{});
529533
}
530534

531-
FMT_CONSTEXPR void init(detail::range_format_constant<range_format::map>) {
532-
range_formatter_.set_brackets(detail::string_literal<Char, '{'>{},
533-
detail::string_literal<Char, '}'>{});
534-
range_formatter_.underlying().set_brackets({}, {});
535-
range_formatter_.underlying().set_separator(
536-
detail::string_literal<Char, ':', ' '>{});
535+
template <typename ParseContext>
536+
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
537+
return range_formatter_.parse(ctx);
537538
}
538539

539-
FMT_CONSTEXPR void init(
540-
detail::range_format_constant<range_format::sequence>) {}
540+
template <typename FormatContext>
541+
auto format(range_type& range, FormatContext& ctx) const
542+
-> decltype(ctx.out()) {
543+
return range_formatter_.format(range, ctx);
544+
}
545+
};
546+
547+
template <typename R, typename Char>
548+
struct formatter<
549+
R, Char,
550+
enable_if_t<range_format_kind<R, Char>::value == range_format::map>> {
551+
private:
552+
using map_type = detail::maybe_const_range<R>;
553+
detail::range_formatter_type<Char, detail::uncvref_type<map_type>>
554+
underlying_;
555+
bool no_delimiters_ = false;
541556

542557
public:
543558
FMT_CONSTEXPR formatter() {
544-
init(detail::range_format_constant<range_format_kind<R, Char>::value>());
559+
underlying_.set_brackets({}, {});
560+
underlying_.set_separator(detail::string_literal<Char, ':', ' '>{});
545561
}
546562

547563
template <typename ParseContext>
548564
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
549-
return range_formatter_.parse(ctx);
565+
auto it = ctx.begin();
566+
auto end = ctx.end();
567+
detail::maybe_set_debug_format(underlying_, true);
568+
if (it == end) return underlying_.parse(ctx);
569+
570+
if (detail::to_ascii(*it) == 'n') {
571+
no_delimiters_ = true;
572+
++it;
573+
}
574+
if (it != end && *it != '}') {
575+
if (*it != ':') report_error("invalid format specifier");
576+
detail::maybe_set_debug_format(underlying_, false);
577+
++it;
578+
}
579+
ctx.advance_to(it);
580+
return underlying_.parse(ctx);
550581
}
551582

552583
template <typename FormatContext>
553-
auto format(range_type& range, FormatContext& ctx) const
554-
-> decltype(ctx.out()) {
555-
return range_formatter_.format(range, ctx);
584+
auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) {
585+
auto mapper = detail::range_mapper<buffered_context<Char>>();
586+
auto out = ctx.out();
587+
auto it = detail::range_begin(map);
588+
auto end = detail::range_end(map);
589+
590+
basic_string_view<Char> open = detail::string_literal<Char, '{'>{};
591+
if (!no_delimiters_) out = detail::copy<Char>(open, out);
592+
int i = 0;
593+
basic_string_view<Char> sep = detail::string_literal<Char, ',', ' '>{};
594+
for (; it != end; ++it) {
595+
if (i > 0) out = detail::copy<Char>(sep, out);
596+
ctx.advance_to(out);
597+
out = underlying_.format(mapper.map(*it), ctx);
598+
++i;
599+
}
600+
basic_string_view<Char> close = detail::string_literal<Char, '}'>{};
601+
if (!no_delimiters_) out = detail::copy<Char>(close, out);
602+
return out;
556603
}
557604
};
558605

0 commit comments

Comments
 (0)