Warning: This file is not a C or C++ file. It does not have highlighting.
1 | // -*- C++ -*- |
---|---|
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H |
11 | #define _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H |
12 | |
13 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
14 | # pragma GCC system_header |
15 | #endif |
16 | |
17 | #include <__algorithm/ranges_copy.h> |
18 | #include <__chrono/statically_widen.h> |
19 | #include <__concepts/same_as.h> |
20 | #include <__config> |
21 | #include <__format/concepts.h> |
22 | #include <__format/formatter.h> |
23 | #include <__format/range_formatter.h> |
24 | #include <__iterator/back_insert_iterator.h> |
25 | #include <__ranges/concepts.h> |
26 | #include <__ranges/data.h> |
27 | #include <__ranges/from_range.h> |
28 | #include <__ranges/size.h> |
29 | #include <__type_traits/conditional.h> |
30 | #include <__type_traits/remove_cvref.h> |
31 | #include <__utility/pair.h> |
32 | #include <string_view> |
33 | |
34 | _LIBCPP_BEGIN_NAMESPACE_STD |
35 | |
36 | #if _LIBCPP_STD_VER >= 23 |
37 | |
38 | template <class _Rp, class _CharT> |
39 | concept __const_formattable_range = |
40 | ranges::input_range<const _Rp> && formattable<ranges::range_reference_t<const _Rp>, _CharT>; |
41 | |
42 | template <class _Rp, class _CharT> |
43 | using __fmt_maybe_const _LIBCPP_NODEBUG = conditional_t<__const_formattable_range<_Rp, _CharT>, const _Rp, _Rp>; |
44 | |
45 | _LIBCPP_DIAGNOSTIC_PUSH |
46 | _LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wshadow") |
47 | _LIBCPP_GCC_DIAGNOSTIC_IGNORED("-Wshadow") |
48 | // This shadows map, set, and string. |
49 | enum class range_format { disabled, map, set, sequence, string, debug_string }; |
50 | _LIBCPP_DIAGNOSTIC_POP |
51 | |
52 | // There is no definition of this struct, it's purely intended to be used to |
53 | // generate diagnostics. |
54 | template <class _Rp> |
55 | struct __instantiated_the_primary_template_of_format_kind; |
56 | |
57 | template <class _Rp> |
58 | constexpr range_format format_kind = [] { |
59 | // [format.range.fmtkind]/1 |
60 | // A program that instantiates the primary template of format_kind is ill-formed. |
61 | static_assert(sizeof(_Rp) != sizeof(_Rp), "create a template specialization of format_kind for your type"); |
62 | return range_format::disabled; |
63 | }(); |
64 | |
65 | template <ranges::input_range _Rp> |
66 | requires same_as<_Rp, remove_cvref_t<_Rp>> |
67 | inline constexpr range_format format_kind<_Rp> = [] { |
68 | // [format.range.fmtkind]/2 |
69 | |
70 | // 2.1 If same_as<remove_cvref_t<ranges::range_reference_t<R>>, R> is true, |
71 | // Otherwise format_kind<R> is range_format::disabled. |
72 | if constexpr (same_as<remove_cvref_t<ranges::range_reference_t<_Rp>>, _Rp>) |
73 | return range_format::disabled; |
74 | // 2.2 Otherwise, if the qualified-id R::key_type is valid and denotes a type: |
75 | else if constexpr (requires { typename _Rp::key_type; }) { |
76 | // 2.2.1 If the qualified-id R::mapped_type is valid and denotes a type ... |
77 | if constexpr (requires { typename _Rp::mapped_type; } && |
78 | // 2.2.1 ... If either U is a specialization of pair or U is a specialization |
79 | // of tuple and tuple_size_v<U> == 2 |
80 | __fmt_pair_like<remove_cvref_t<ranges::range_reference_t<_Rp>>>) |
81 | return range_format::map; |
82 | else |
83 | // 2.2.2 Otherwise format_kind<R> is range_format::set. |
84 | return range_format::set; |
85 | } else |
86 | // 2.3 Otherwise, format_kind<R> is range_format::sequence. |
87 | return range_format::sequence; |
88 | }(); |
89 | |
90 | template <range_format _Kp, ranges::input_range _Rp, class _CharT> |
91 | struct __range_default_formatter; |
92 | |
93 | // Required specializations |
94 | |
95 | template <ranges::input_range _Rp, class _CharT> |
96 | struct __range_default_formatter<range_format::sequence, _Rp, _CharT> { |
97 | private: |
98 | using __maybe_const_r _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; |
99 | range_formatter<remove_cvref_t<ranges::range_reference_t<__maybe_const_r>>, _CharT> __underlying_; |
100 | |
101 | public: |
102 | _LIBCPP_HIDE_FROM_ABI constexpr void set_separator(basic_string_view<_CharT> __separator) noexcept { |
103 | __underlying_.set_separator(__separator); |
104 | } |
105 | _LIBCPP_HIDE_FROM_ABI constexpr void |
106 | set_brackets(basic_string_view<_CharT> __opening_bracket, basic_string_view<_CharT> __closing_bracket) noexcept { |
107 | __underlying_.set_brackets(__opening_bracket, __closing_bracket); |
108 | } |
109 | |
110 | template <class _ParseContext> |
111 | _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { |
112 | return __underlying_.parse(__ctx); |
113 | } |
114 | |
115 | template <class _FormatContext> |
116 | _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator |
117 | format(__maybe_const_r& __range, _FormatContext& __ctx) const { |
118 | return __underlying_.format(__range, __ctx); |
119 | } |
120 | }; |
121 | |
122 | template <ranges::input_range _Rp, class _CharT> |
123 | struct __range_default_formatter<range_format::map, _Rp, _CharT> { |
124 | private: |
125 | using __maybe_const_map _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; |
126 | using __element_type _LIBCPP_NODEBUG = remove_cvref_t<ranges::range_reference_t<__maybe_const_map>>; |
127 | range_formatter<__element_type, _CharT> __underlying_; |
128 | |
129 | public: |
130 | _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() |
131 | requires(__fmt_pair_like<__element_type>) |
132 | { |
133 | __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); |
134 | __underlying_.underlying().set_brackets({}, {}); |
135 | __underlying_.underlying().set_separator(_LIBCPP_STATICALLY_WIDEN(_CharT, ": ")); |
136 | } |
137 | |
138 | template <class _ParseContext> |
139 | _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { |
140 | return __underlying_.parse(__ctx); |
141 | } |
142 | |
143 | template <class _FormatContext> |
144 | _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator |
145 | format(__maybe_const_map& __range, _FormatContext& __ctx) const { |
146 | return __underlying_.format(__range, __ctx); |
147 | } |
148 | }; |
149 | |
150 | template <ranges::input_range _Rp, class _CharT> |
151 | struct __range_default_formatter<range_format::set, _Rp, _CharT> { |
152 | private: |
153 | using __maybe_const_set _LIBCPP_NODEBUG = __fmt_maybe_const<_Rp, _CharT>; |
154 | using __element_type _LIBCPP_NODEBUG = remove_cvref_t<ranges::range_reference_t<__maybe_const_set>>; |
155 | range_formatter<__element_type, _CharT> __underlying_; |
156 | |
157 | public: |
158 | _LIBCPP_HIDE_FROM_ABI constexpr __range_default_formatter() { |
159 | __underlying_.set_brackets(_LIBCPP_STATICALLY_WIDEN(_CharT, "{"), _LIBCPP_STATICALLY_WIDEN(_CharT, "}")); |
160 | } |
161 | |
162 | template <class _ParseContext> |
163 | _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { |
164 | return __underlying_.parse(__ctx); |
165 | } |
166 | |
167 | template <class _FormatContext> |
168 | _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator |
169 | format(__maybe_const_set& __range, _FormatContext& __ctx) const { |
170 | return __underlying_.format(__range, __ctx); |
171 | } |
172 | }; |
173 | |
174 | template <range_format _Kp, ranges::input_range _Rp, class _CharT> |
175 | requires(_Kp == range_format::string || _Kp == range_format::debug_string) |
176 | struct __range_default_formatter<_Kp, _Rp, _CharT> { |
177 | private: |
178 | // This deviates from the Standard, there the exposition only type is |
179 | // formatter<basic_string<charT>, charT> underlying_; |
180 | // Using a string_view allows the format function to avoid a copy of the |
181 | // input range when it is a contigious range. |
182 | formatter<basic_string_view<_CharT>, _CharT> __underlying_; |
183 | |
184 | public: |
185 | template <class _ParseContext> |
186 | _LIBCPP_HIDE_FROM_ABI constexpr typename _ParseContext::iterator parse(_ParseContext& __ctx) { |
187 | typename _ParseContext::iterator __i = __underlying_.parse(__ctx); |
188 | if constexpr (_Kp == range_format::debug_string) |
189 | __underlying_.set_debug_format(); |
190 | return __i; |
191 | } |
192 | |
193 | template <class _FormatContext> |
194 | _LIBCPP_HIDE_FROM_ABI typename _FormatContext::iterator |
195 | format(conditional_t<ranges::input_range<const _Rp>, const _Rp&, _Rp&> __range, _FormatContext& __ctx) const { |
196 | // When the range is contiguous use a basic_string_view instead to avoid a |
197 | // copy of the underlying data. The basic_string_view formatter |
198 | // specialization is the "basic" string formatter in libc++. |
199 | if constexpr (ranges::contiguous_range<_Rp> && std::ranges::sized_range<_Rp>) |
200 | return __underlying_.format(basic_string_view<_CharT>{ranges::data(__range), ranges::size(__range)}, __ctx); |
201 | else |
202 | return __underlying_.format(basic_string<_CharT>{from_range, __range}, __ctx); |
203 | } |
204 | }; |
205 | |
206 | template <ranges::input_range _Rp, class _CharT> |
207 | requires(format_kind<_Rp> != range_format::disabled && formattable<ranges::range_reference_t<_Rp>, _CharT>) |
208 | struct formatter<_Rp, _CharT> : __range_default_formatter<format_kind<_Rp>, _Rp, _CharT> {}; |
209 | |
210 | #endif // _LIBCPP_STD_VER >= 23 |
211 | |
212 | _LIBCPP_END_NAMESPACE_STD |
213 | |
214 | #endif // _LIBCPP___FORMAT_RANGE_DEFAULT_FORMATTER_H |
215 |
Warning: This file is not a C or C++ file. It does not have highlighting.