xref: /llvm-project/libcxx/include/__format/range_default_formatter.h (revision f69585235ec85d54e0f3fc41b2d5700430907f99)
1d184958bSMark de Wever // -*- C++ -*-
2d184958bSMark de Wever //===----------------------------------------------------------------------===//
3d184958bSMark de Wever //
4d184958bSMark de Wever // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5d184958bSMark de Wever // See https://llvm.org/LICENSE.txt for license information.
6d184958bSMark de Wever // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7d184958bSMark de Wever //
8d184958bSMark de Wever //===----------------------------------------------------------------------===//
9d184958bSMark de Wever 
10d184958bSMark de Wever #ifndef _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H
11d184958bSMark de Wever #define _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H
12d184958bSMark de Wever 
13d184958bSMark de Wever #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
14d184958bSMark de Wever #  pragma GCC system_header
15d184958bSMark de Wever #endif
16d184958bSMark de Wever 
17ed8ea2bbSMark de Wever #include <__algorithm/ranges_copy.h>
18af5fc4b4SMark de Wever #include <__chrono/statically_widen.h>
19d184958bSMark de Wever #include <__concepts/same_as.h>
20d184958bSMark de Wever #include <__config>
21d184958bSMark de Wever #include <__format/concepts.h>
22d184958bSMark de Wever #include <__format/formatter.h>
2322e8525dSMark de Wever #include <__format/range_formatter.h>
24ed8ea2bbSMark de Wever #include <__iterator/back_insert_iterator.h>
25d184958bSMark de Wever #include <__ranges/concepts.h>
26ed8ea2bbSMark de Wever #include <__ranges/data.h>
277b580d8bSMark de Wever #include <__ranges/from_range.h>
28ed8ea2bbSMark de Wever #include <__ranges/size.h>
29285e1e2aSMark de Wever #include <__type_traits/conditional.h>
30d184958bSMark de Wever #include <__type_traits/remove_cvref.h>
31d184958bSMark de Wever #include <__utility/pair.h>
3222e8525dSMark de Wever #include <string_view>
33d184958bSMark de Wever 
34d184958bSMark de Wever _LIBCPP_BEGIN_NAMESPACE_STD
35d184958bSMark de Wever 
364f15267dSNikolas Klauser #if _LIBCPP_STD_VER >= 23
37d184958bSMark de Wever 
38d184958bSMark de Wever template <class _Rp, class _CharT>
39d184958bSMark de Wever concept __const_formattable_range =
40d184958bSMark de Wever     ranges::input_range<const _Rp> && formattable<ranges::range_reference_t<const _Rp>, _CharT>;
41d184958bSMark de Wever 
42d184958bSMark de Wever template <class _Rp, class _CharT>
43*f6958523SNikolas Klauser using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>;
44d184958bSMark de Wever 
45d184958bSMark de Wever _LIBCPP_DIAGNOSTIC_PUSH
46d184958bSMark de Wever _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow")
47d184958bSMark de Wever _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow")
48d184958bSMark de Wever // This shadows map, set, and string.
49d184958bSMark de Wever enum class range_format { disabled, map, set, sequence, string, debug_string };
50d184958bSMark de Wever _LIBCPP_DIAGNOSTIC_POP
51d184958bSMark de Wever 
52d184958bSMark de Wever // There is no definition of this struct, it's purely intended to be used to
53d184958bSMark de Wever // generate diagnostics.
54d184958bSMark de Wever template <class _Rp>
55d184958bSMark de Wever struct _LIBCPP_TEMPLATE_VIS __instantiated_the_primary_template_of_format_kind;
56d184958bSMark de Wever 
57d184958bSMark de Wever template <class _Rp>
58d184958bSMark de Wever constexpr range_format format_kind = [] {
59d184958bSMark de Wever   // [format.range.fmtkind]/1
60d184958bSMark de Wever   // A program that instantiates the primary template of format_kind is ill-formed.
61d184958bSMark de Wever   static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type");
62d184958bSMark de Wever   return range_format::disabled;
63d184958bSMark de Wever }();
64d184958bSMark de Wever 
65d184958bSMark de Wever template <ranges::input_range _Rp>
66d184958bSMark de Wever   requires same_as<_Rp, remove_cvref_t<_Rp>>
67d184958bSMark de Wever inline constexpr range_format format_kind<_Rp> = [] {
68d184958bSMark de Wever   // [format.range.fmtkind]/2
69d184958bSMark de Wever 
70d184958bSMark de Wever   // 2.1 If same_as<remove_cvref_t<ranges::range_reference_t<R>>, R> is true,
71d184958bSMark de Wever   // Otherwise format_kind<R> is range_format::disabled.
72d184958bSMark de Wever   if constexpr (same_as<remove_cvref_t<ranges::range_reference_t<_Rp>>, _Rp>)
73d184958bSMark de Wever     return range_format::disabled;
74d184958bSMark de Wever   // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type:
75d184958bSMark de Wever   else if constexpr (requires { typename _Rp::key_type; }) {
76d184958bSMark de Wever     // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ...
77d184958bSMark de Wever     if constexpr (requires { typename _Rp::mapped_type; } &&
78d184958bSMark de Wever                   // 2.2.1 ... If either U is a specialization of pair or U is a specialization
79d184958bSMark de Wever                   // of tuple and tuple_size_v<U> == 2
80d184958bSMark de Wever                   __fmt_pair_like<remove_cvref_t<ranges::range_reference_t<_Rp>>>)
81d184958bSMark de Wever       return range_format::map;
82d184958bSMark de Wever     else
83d184958bSMark de Wever       // 2.2.2 Otherwise format_kind<R> is range_format::set.
84d184958bSMark de Wever       return range_format::set;
85d184958bSMark de Wever   } else
86d184958bSMark de Wever     // 2.3 Otherwise, format_kind<R> is range_format::sequence.
87d184958bSMark de Wever     return range_format::sequence;
88d184958bSMark de Wever }();
89d184958bSMark de Wever 
90d184958bSMark de Wever template <range_format _Kp, ranges::input_range _Rp, class _CharT>
913d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter;
92d184958bSMark de Wever 
93d184958bSMark de Wever // Required specializations
94d184958bSMark de Wever 
95d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT>
963d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::sequence, _Rp, _CharT> {
9722e8525dSMark de Wever private:
98*f6958523SNikolas Klauser   using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>;
9922e8525dSMark de Wever   range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>, _CharT> __underlying_;
10022e8525dSMark de Wever 
10122e8525dSMark de Wever public:
102f68a536aSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept {
10322e8525dSMark de Wever     __underlying_.set_separator(__separator);
10422e8525dSMark de Wever   }
10522e8525dSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr void
106f68a536aSMark de Wever   set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept {
10722e8525dSMark de Wever     __underlying_.set_brackets(__opening_bracket, __closing_bracket);
10822e8525dSMark de Wever   }
10922e8525dSMark de Wever 
11022e8525dSMark de Wever   template <class _ParseContext>
11122e8525dSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
11222e8525dSMark de Wever     return __underlying_.parse(__ctx);
11322e8525dSMark de Wever   }
11422e8525dSMark de Wever 
1151e24b4d3SNikolas Klauser   template <class _FormatContext>
1161e24b4d3SNikolas Klauser   _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
1171e24b4d3SNikolas Klauser   format(__maybe_const_r& __range, _FormatContext& __ctx) const {
11822e8525dSMark de Wever     return __underlying_.format(__range, __ctx);
11922e8525dSMark de Wever   }
120d184958bSMark de Wever };
121d184958bSMark de Wever 
122d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT>
1233d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::map, _Rp, _CharT> {
124af5fc4b4SMark de Wever private:
125*f6958523SNikolas Klauser   using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>;
126*f6958523SNikolas Klauser   using __element_type _LIBCPP_NODEBUG    = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>;
127af5fc4b4SMark de Wever   range_formatter<__element_type, _CharT> __underlying_;
128af5fc4b4SMark de Wever 
129af5fc4b4SMark de Wever public:
130af5fc4b4SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter()
131af5fc4b4SMark de Wever     requires(__fmt_pair_like<__element_type>)
132af5fc4b4SMark de Wever   {
133af5fc4b4SMark de Wever     __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}"));
134af5fc4b4SMark de Wever     __underlying_.underlying().set_brackets({}, {});
135af5fc4b4SMark de Wever     __underlying_.underlying().set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": "));
136af5fc4b4SMark de Wever   }
137af5fc4b4SMark de Wever 
138af5fc4b4SMark de Wever   template <class _ParseContext>
139af5fc4b4SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
140af5fc4b4SMark de Wever     return __underlying_.parse(__ctx);
141af5fc4b4SMark de Wever   }
142af5fc4b4SMark de Wever 
143af5fc4b4SMark de Wever   template <class _FormatContext>
144af5fc4b4SMark de Wever   _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
145af5fc4b4SMark de Wever   format(__maybe_const_map& __range, _FormatContext& __ctx) const {
146af5fc4b4SMark de Wever     return __underlying_.format(__range, __ctx);
147af5fc4b4SMark de Wever   }
148d184958bSMark de Wever };
149d184958bSMark de Wever 
150d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT>
1513d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<range_format::set, _Rp, _CharT> {
152857cbb92SMark de Wever private:
153*f6958523SNikolas Klauser   using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>;
154*f6958523SNikolas Klauser   using __element_type _LIBCPP_NODEBUG    = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>;
155857cbb92SMark de Wever   range_formatter<__element_type, _CharT> __underlying_;
156857cbb92SMark de Wever 
157857cbb92SMark de Wever public:
158857cbb92SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() {
159857cbb92SMark de Wever     __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}"));
160857cbb92SMark de Wever   }
161857cbb92SMark de Wever 
162857cbb92SMark de Wever   template <class _ParseContext>
163857cbb92SMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
164857cbb92SMark de Wever     return __underlying_.parse(__ctx);
165857cbb92SMark de Wever   }
166857cbb92SMark de Wever 
167857cbb92SMark de Wever   template <class _FormatContext>
168857cbb92SMark de Wever   _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
169857cbb92SMark de Wever   format(__maybe_const_set& __range, _FormatContext& __ctx) const {
170857cbb92SMark de Wever     return __underlying_.format(__range, __ctx);
171857cbb92SMark de Wever   }
172d184958bSMark de Wever };
173d184958bSMark de Wever 
174d184958bSMark de Wever template <range_format _Kp, ranges::input_range _Rp, class _CharT>
175d184958bSMark de Wever   requires(_Kp == range_format::string || _Kp == range_format::debug_string)
1763d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS __range_default_formatter<_Kp, _Rp, _CharT> {
177ed8ea2bbSMark de Wever private:
178ed8ea2bbSMark de Wever   // This deviates from the Standard, there the exposition only type is
179ed8ea2bbSMark de Wever   //   formatter<basic_string<charT>, charT> underlying_;
180ed8ea2bbSMark de Wever   // Using a string_view allows the format function to avoid a copy of the
181ed8ea2bbSMark de Wever   // input range when it is a contigious range.
182ed8ea2bbSMark de Wever   formatter<basic_string_view<_CharT>, _CharT> __underlying_;
183ed8ea2bbSMark de Wever 
184ed8ea2bbSMark de Wever public:
185ed8ea2bbSMark de Wever   template <class _ParseContext>
186ed8ea2bbSMark de Wever   _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) {
187ed8ea2bbSMark de Wever     typename _ParseContext::iterator __i = __underlying_.parse(__ctx);
188ed8ea2bbSMark de Wever     if constexpr (_Kp == range_format::debug_string)
189ed8ea2bbSMark de Wever       __underlying_.set_debug_format();
190ed8ea2bbSMark de Wever     return __i;
191ed8ea2bbSMark de Wever   }
192ed8ea2bbSMark de Wever 
193ed8ea2bbSMark de Wever   template <class _FormatContext>
194ed8ea2bbSMark de Wever   _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator
195ed8ea2bbSMark de Wever   format(conditional_t<ranges::input_range<const _Rp>, const _Rp&, _Rp&> __range, _FormatContext& __ctx) const {
196ed8ea2bbSMark de Wever     // When the range is contiguous use a basic_string_view instead to avoid a
197ed8ea2bbSMark de Wever     // copy of the underlying data. The basic_string_view formatter
198ed8ea2bbSMark de Wever     // specialization is the "basic" string formatter in libc++.
199ed8ea2bbSMark de Wever     if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>)
200ed8ea2bbSMark de Wever       return __underlying_.format(basic_string_view<_CharT>{ranges::data(__range), ranges::size(__range)}, __ctx);
2017b580d8bSMark de Wever     else
2027b580d8bSMark de Wever       return __underlying_.format(basic_string<_CharT>{from_range, __range}, __ctx);
203ed8ea2bbSMark de Wever   }
204d184958bSMark de Wever };
205d184958bSMark de Wever 
206d184958bSMark de Wever template <ranges::input_range _Rp, class _CharT>
207d184958bSMark de Wever   requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>)
2083d334df5SLouis Dionne struct _LIBCPP_TEMPLATE_VIS formatter<_Rp, _CharT> : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {};
209d184958bSMark de Wever 
2104f15267dSNikolas Klauser #endif // _LIBCPP_STD_VER >= 23
211d184958bSMark de Wever 
212d184958bSMark de Wever _LIBCPP_END_NAMESPACE_STD
213d184958bSMark de Wever 
214d184958bSMark de Wever #endif // _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H
215