@@ -511,48 +511,95 @@ struct range_format_kind
511511template <typename R, typename Char>
512512struct 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