• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //===----------------------------------------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 #ifndef TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FORMATTER_FORMAT_FUNCTIONS_TESTS_H
9 #define TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FORMATTER_FORMAT_FUNCTIONS_TESTS_H
10 
11 #include <algorithm>
12 #include <array>
13 #include <charconv>
14 #include <concepts>
15 #include <deque>
16 #include <format>
17 #include <list>
18 #include <ranges>
19 #include <span>
20 #include <tuple>
21 #include <vector>
22 
23 #include "format.functions.common.h"
24 #include "make_string.h"
25 #include "platform_support.h" // locale name macros
26 #include "test_iterators.h"
27 #include "test_macros.h"
28 
29 //
30 // Char
31 //
32 
33 template <class CharT, class TestFunction, class ExceptionTest>
test_char_default(TestFunction check,ExceptionTest check_exception,auto && input)34 void test_char_default(TestFunction check, ExceptionTest check_exception, auto&& input) {
35   // Note when no range-underlying-spec is present the char is escaped,
36   check(SV("['H', 'e', 'l', 'l', 'o']"), SV("{}"), input);
37 
38   // when one is present there is no escaping,
39   check(SV("[H, e, l, l, o]"), SV("{::}"), input);
40   // unless forced by the type specifier.
41   check(SV("['H', 'e', 'l', 'l', 'o']"), SV("{::?}"), input);
42 
43   // ***** underlying has no format-spec
44 
45   // *** align-fill & width ***
46   check(SV("['H', 'e', 'l', 'l', 'o']     "), SV("{:30}"), input);
47   check(SV("['H', 'e', 'l', 'l', 'o']*****"), SV("{:*<30}"), input);
48   check(SV("__['H', 'e', 'l', 'l', 'o']___"), SV("{:_^30}"), input);
49   check(SV("#####['H', 'e', 'l', 'l', 'o']"), SV("{:#>30}"), input);
50 
51   check(SV("['H', 'e', 'l', 'l', 'o']     "), SV("{:{}}"), input, 30);
52   check(SV("['H', 'e', 'l', 'l', 'o']*****"), SV("{:*<{}}"), input, 30);
53   check(SV("__['H', 'e', 'l', 'l', 'o']___"), SV("{:_^{}}"), input, 30);
54   check(SV("#####['H', 'e', 'l', 'l', 'o']"), SV("{:#>{}}"), input, 30);
55 
56   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
57   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
58   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
59 
60   // *** sign ***
61   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
62   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
63   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
64 
65   // *** alternate form ***
66   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
67 
68   // *** zero-padding ***
69   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
70 
71   // *** precision ***
72   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
73 
74   // *** locale-specific form ***
75   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
76 
77   // *** n
78   check(SV("__'H', 'e', 'l', 'l', 'o'___"), SV("{:_^28n}"), input);
79 
80   // *** type ***
81   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
82   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
83     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
84 
85   // ***** Only underlying has a format-spec
86   check(SV("[H   , e   , l   , l   , o   ]"), SV("{::4}"), input);
87   check(SV("[H***, e***, l***, l***, o***]"), SV("{::*<4}"), input);
88   check(SV("[_H__, _e__, _l__, _l__, _o__]"), SV("{::_^4}"), input);
89   check(SV("[:::H, :::e, :::l, :::l, :::o]"), SV("{:::>4}"), input);
90 
91   check(SV("[H   , e   , l   , l   , o   ]"), SV("{::{}}"), input, 4);
92   check(SV("[H***, e***, l***, l***, o***]"), SV("{::*<{}}"), input, 4);
93   check(SV("[_H__, _e__, _l__, _l__, _o__]"), SV("{::_^{}}"), input, 4);
94   check(SV("[:::H, :::e, :::l, :::l, :::o]"), SV("{:::>{}}"), input, 4);
95 
96   check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
97   check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
98 
99   // *** sign ***
100   check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
101   check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
102   check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
103 
104   check(SV("[72, 101, 108, 108, 111]"), SV("{::-d}"), input);
105   check(SV("[+72, +101, +108, +108, +111]"), SV("{::+d}"), input);
106   check(SV("[ 72,  101,  108,  108,  111]"), SV("{:: d}"), input);
107 
108   // *** alternate form ***
109   check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
110 
111   check(SV("[0x48, 0x65, 0x6c, 0x6c, 0x6f]"), SV("{::#x}"), input);
112 
113   // *** zero-padding ***
114   check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
115 
116   check(SV("[00110, 00145, 00154, 00154, 00157]"), SV("{::05o}"), input);
117 
118   // *** precision ***
119   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
120 
121   // *** locale-specific form ***
122   check(SV("[H, e, l, l, o]"), SV("{::L}"), input);
123 
124   // *** type ***
125   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
126     check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
127 
128   // ***** Both have a format-spec
129   check(SV("^^[:H, :e, :l, :l, :o]^^^"), SV("{:^^25::>2}"), input);
130   check(SV("^^[:H, :e, :l, :l, :o]^^^"), SV("{:^^{}::>2}"), input, 25);
131   check(SV("^^[:H, :e, :l, :l, :o]^^^"), SV("{:^^{}::>{}}"), input, 25, 2);
132 
133   check_exception("Argument index out of bounds", SV("{:^^{}::>2}"), input);
134   check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 25);
135 }
136 
137 template <class CharT, class TestFunction, class ExceptionTest>
test_char_string(TestFunction check,ExceptionTest check_exception,auto && input)138 void test_char_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
139   check(SV("Hello"), SV("{:s}"), input);
140 
141   // ***** underlying has no format-spec
142 
143   // *** align-fill & width ***
144   check(SV("Hello   "), SV("{:8s}"), input);
145   check(SV("Hello***"), SV("{:*<8s}"), input);
146   check(SV("_Hello__"), SV("{:_^8s}"), input);
147   check(SV("###Hello"), SV("{:#>8s}"), input);
148 
149   check(SV("Hello   "), SV("{:{}s}"), input, 8);
150   check(SV("Hello***"), SV("{:*<{}s}"), input, 8);
151   check(SV("_Hello__"), SV("{:_^{}s}"), input, 8);
152   check(SV("###Hello"), SV("{:#>{}s}"), input, 8);
153 
154   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<s}"), input);
155   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<s}"), input);
156   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<s}"), input);
157 
158   // *** sign ***
159   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-s}"), input);
160   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+s}"), input);
161   check_exception("The format-spec should consume the input or end with a '}'", SV("{: s}"), input);
162 
163   // *** alternate form ***
164   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#s}"), input);
165 
166   // *** zero-padding ***
167   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0s}"), input);
168 
169   // *** precision ***
170   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.s}"), input);
171 
172   // *** locale-specific form ***
173   check_exception("The format-spec should consume the input or end with a '}'", SV("{:Ls}"), input);
174 
175   // *** n
176   check_exception("The n option and type s can't be used together", SV("{:ns}"), input);
177 
178   // *** type ***
179   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
180 
181   // ***** Only underlying has a format-spec
182   check_exception("Type s and an underlying format specification can't be used together", SV("{:s:}"), input);
183   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX?"))
184     check_exception("The format-spec type has a type not supported for a char argument", fmt, input);
185 
186   // ***** Both have a format-spec
187   check_exception("Type s and an underlying format specification can't be used together", SV("{:5s:5}"), input);
188 }
189 
190 template <class CharT, class TestFunction, class ExceptionTest>
test_char_escaped_string(TestFunction check,ExceptionTest check_exception,auto && input)191 void test_char_escaped_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
192   check(SV(R"("\"Hello'")"), SV("{:?s}"), input);
193 
194   // ***** underlying has no format-spec
195 
196   // *** align-fill & width ***
197   check(SV(R"("\"Hello'"   )"), SV("{:13?s}"), input);
198   check(SV(R"("\"Hello'"***)"), SV("{:*<13?s}"), input);
199   check(SV(R"(_"\"Hello'"__)"), SV("{:_^13?s}"), input);
200   check(SV(R"(###"\"Hello'")"), SV("{:#>13?s}"), input);
201 
202   check(SV(R"("\"Hello'"   )"), SV("{:{}?s}"), input, 13);
203   check(SV(R"("\"Hello'"***)"), SV("{:*<{}?s}"), input, 13);
204   check(SV(R"(_"\"Hello'"__)"), SV("{:_^{}?s}"), input, 13);
205   check(SV(R"(###"\"Hello'")"), SV("{:#>{}?s}"), input, 13);
206 
207   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<?s}"), input);
208   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<?s}"), input);
209   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<?s}"), input);
210 
211   // *** sign ***
212   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-?s}"), input);
213   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+?s}"), input);
214   check_exception("The format-spec should consume the input or end with a '}'", SV("{: ?s}"), input);
215 
216   // *** alternate form ***
217   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#?s}"), input);
218 
219   // *** zero-padding ***
220   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0?s}"), input);
221 
222   // *** precision ***
223   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.?s}"), input);
224 
225   // *** locale-specific form ***
226   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L?s}"), input);
227 
228   // *** n
229   check_exception("The n option and type ?s can't be used together", SV("{:n?s}"), input);
230 
231   // *** type ***
232   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
233 
234   // ***** Only underlying has a format-spec
235   check_exception("Type ?s and an underlying format specification can't be used together", SV("{:?s:}"), input);
236 
237   // ***** Both have a format-spec
238   check_exception("Type ?s and an underlying format specification can't be used together", SV("{:5?s:5}"), input);
239 }
240 
241 template <class CharT, class TestFunction, class ExceptionTest>
test_char(TestFunction check,ExceptionTest check_exception)242 void test_char(TestFunction check, ExceptionTest check_exception) {
243   test_char_default<CharT>(
244       check, check_exception, std::array{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')});
245 
246   // This tests two different implementations in libc++. A basic_string_view
247   // formatter if the range is contiguous, a basic_string otherwise.
248   test_char_escaped_string<CharT>(
249       check,
250       check_exception,
251       std::array{CharT('"'), CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o'), CharT('\'')});
252   test_char_escaped_string<CharT>(
253       check,
254       check_exception,
255       std::list{CharT('"'), CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o'), CharT('\'')});
256 
257   // This tests two different implementations in libc++. A basic_string_view
258   // formatter if the range is contiguous, a basic_string otherwise.
259   test_char_string<CharT>(
260       check, check_exception, std::array{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')});
261   test_char_string<CharT>(
262       check, check_exception, std::list{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')});
263 }
264 
265 //
266 // char -> wchar_t
267 //
268 
269 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
270 template <class TestFunction, class ExceptionTest>
271 void test_char_to_wchar(TestFunction check, ExceptionTest check_exception) {
272   test_char_default<wchar_t>(check, check_exception, std::array{'H', 'e', 'l', 'l', 'o'});
273 
274   // The types s and ?s may only be used when using range_formatter<T, charT>
275   // where the types T and charT are the same. This means this can't be used for
276   // range_formatter<wchar_t, char> even when formatter<wchar_t, char> has a
277   // debug-enabled specialization.
278 
279   using CharT = wchar_t;
280   check_exception("The range-format-spec type s requires formatting a character type",
281                   SV("{:s}"),
282                   std::array{'H', 'e', 'l', 'l', 'o'});
283   check_exception("The range-format-spec type ?s requires formatting a character type",
284                   SV("{:?s}"),
285                   std::array{'H', 'e', 'l', 'l', 'o'});
286 }
287 #endif
288 
289 //
290 // Bool
291 //
292 
293 template <class CharT, class TestFunction, class ExceptionTest>
test_bool(TestFunction check,ExceptionTest check_exception)294 void test_bool(TestFunction check, ExceptionTest check_exception) {
295   std::array input{true, true, false};
296 
297   check(SV("[true, true, false]"), SV("{}"), input);
298 
299   // ***** underlying has no format-spec
300 
301   // *** align-fill & width ***
302   check(SV("[true, true, false]     "), SV("{:24}"), input);
303   check(SV("[true, true, false]*****"), SV("{:*<24}"), input);
304   check(SV("__[true, true, false]___"), SV("{:_^24}"), input);
305   check(SV("#####[true, true, false]"), SV("{:#>24}"), input);
306 
307   check(SV("[true, true, false]     "), SV("{:{}}"), input, 24);
308   check(SV("[true, true, false]*****"), SV("{:*<{}}"), input, 24);
309   check(SV("__[true, true, false]___"), SV("{:_^{}}"), input, 24);
310   check(SV("#####[true, true, false]"), SV("{:#>{}}"), input, 24);
311 
312   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
313   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
314   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
315 
316   // *** sign ***
317   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
318   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
319   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
320 
321   // *** alternate form ***
322   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
323 
324   // *** zero-padding ***
325   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
326 
327   // *** precision ***
328   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
329 
330   // *** locale-specific form ***
331   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
332 
333   // *** n
334   check(SV("__true, true, false___"), SV("{:_^22n}"), input);
335 
336   // *** type ***
337   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
338   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
339   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
340   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
341     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
342 
343   // ***** Only underlying has a format-spec
344   check(SV("[true   , true   , false  ]"), SV("{::7}"), input);
345   check(SV("[true***, true***, false**]"), SV("{::*<7}"), input);
346   check(SV("[_true__, _true__, _false_]"), SV("{::_^7}"), input);
347   check(SV("[:::true, :::true, ::false]"), SV("{:::>7}"), input);
348 
349   check(SV("[true   , true   , false  ]"), SV("{::{}}"), input, 7);
350   check(SV("[true***, true***, false**]"), SV("{::*<{}}"), input, 7);
351   check(SV("[_true__, _true__, _false_]"), SV("{::_^{}}"), input, 7);
352   check(SV("[:::true, :::true, ::false]"), SV("{:::>{}}"), input, 7);
353 
354   check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
355   check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
356 
357   // *** sign ***
358   check_exception("A sign field isn't allowed in this format-spec", SV("{::-}"), input);
359   check_exception("A sign field isn't allowed in this format-spec", SV("{::+}"), input);
360   check_exception("A sign field isn't allowed in this format-spec", SV("{:: }"), input);
361 
362   check(SV("[1, 1, 0]"), SV("{::-d}"), input);
363   check(SV("[+1, +1, +0]"), SV("{::+d}"), input);
364   check(SV("[ 1,  1,  0]"), SV("{:: d}"), input);
365 
366   // *** alternate form ***
367   check_exception("An alternate form field isn't allowed in this format-spec", SV("{::#}"), input);
368 
369   check(SV("[0x1, 0x1, 0x0]"), SV("{::#x}"), input);
370 
371   // *** zero-padding ***
372   check_exception("A zero-padding field isn't allowed in this format-spec", SV("{::05}"), input);
373 
374   check(SV("[00001, 00001, 00000]"), SV("{::05o}"), input);
375 
376   // *** precision ***
377   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
378 
379   // *** locale-specific form ***
380   check(SV("[true, true, false]"), SV("{::L}"), input);
381 
382   // *** type ***
383   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBdosxX"))
384     check_exception("The format-spec type has a type not supported for a bool argument", fmt, input);
385 
386   // ***** Both have a format-spec
387   check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^32::>7}"), input);
388   check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^{}::>7}"), input, 32);
389   check(SV("^^[:::true, :::true, ::false]^^^"), SV("{:^^{}::>{}}"), input, 32, 7);
390 
391   check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
392   check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 32);
393 }
394 
395 //
396 // Integral
397 //
398 
399 template <class CharT, class TestFunction, class ExceptionTest>
test_int(TestFunction check,ExceptionTest check_exception,auto && input)400 void test_int(TestFunction check, ExceptionTest check_exception, auto&& input) {
401   check(SV("[1, 2, 42, -42]"), SV("{}"), input);
402 
403   // ***** underlying has no format-spec
404 
405   // *** align-fill & width ***
406   check(SV("[1, 2, 42, -42]     "), SV("{:20}"), input);
407   check(SV("[1, 2, 42, -42]*****"), SV("{:*<20}"), input);
408   check(SV("__[1, 2, 42, -42]___"), SV("{:_^20}"), input);
409   check(SV("#####[1, 2, 42, -42]"), SV("{:#>20}"), input);
410 
411   check(SV("[1, 2, 42, -42]     "), SV("{:{}}"), input, 20);
412   check(SV("[1, 2, 42, -42]*****"), SV("{:*<{}}"), input, 20);
413   check(SV("__[1, 2, 42, -42]___"), SV("{:_^{}}"), input, 20);
414   check(SV("#####[1, 2, 42, -42]"), SV("{:#>{}}"), input, 20);
415 
416   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
417   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
418   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
419 
420   // *** sign ***
421   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
422   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
423   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
424 
425   // *** alternate form ***
426   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
427 
428   // *** zero-padding ***
429   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
430 
431   // *** precision ***
432   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
433 
434   // *** locale-specific form ***
435   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
436 
437   // *** n
438   check(SV("__1, 2, 42, -42___"), SV("{:_^18n}"), input);
439 
440   // *** type ***
441   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
442   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
443   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
444   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
445     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
446 
447   // ***** Only underlying has a format-spec
448   check(SV("[    1,     2,    42,   -42]"), SV("{::5}"), input);
449   check(SV("[1****, 2****, 42***, -42**]"), SV("{::*<5}"), input);
450   check(SV("[__1__, __2__, _42__, _-42_]"), SV("{::_^5}"), input);
451   check(SV("[::::1, ::::2, :::42, ::-42]"), SV("{:::>5}"), input);
452 
453   check(SV("[    1,     2,    42,   -42]"), SV("{::{}}"), input, 5);
454   check(SV("[1****, 2****, 42***, -42**]"), SV("{::*<{}}"), input, 5);
455   check(SV("[__1__, __2__, _42__, _-42_]"), SV("{::_^{}}"), input, 5);
456   check(SV("[::::1, ::::2, :::42, ::-42]"), SV("{:::>{}}"), input, 5);
457 
458   check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
459   check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
460 
461   // *** sign ***
462   check(SV("[1, 2, 42, -42]"), SV("{::-}"), input);
463   check(SV("[+1, +2, +42, -42]"), SV("{::+}"), input);
464   check(SV("[ 1,  2,  42, -42]"), SV("{:: }"), input);
465 
466   // *** alternate form ***
467   check(SV("[0x1, 0x2, 0x2a, -0x2a]"), SV("{::#x}"), input);
468 
469   // *** zero-padding ***
470   check(SV("[00001, 00002, 00042, -0042]"), SV("{::05}"), input);
471   check(SV("[00001, 00002, 0002a, -002a]"), SV("{::05x}"), input);
472   check(SV("[0x001, 0x002, 0x02a, -0x2a]"), SV("{::#05x}"), input);
473 
474   // *** precision ***
475   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
476 
477   // *** locale-specific form ***
478   check(SV("[1, 2, 42, -42]"), SV("{::L}"), input); // does nothing in this test, but is accepted.
479 
480   // *** type ***
481   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("bBcdoxX"))
482     check_exception("The format-spec type has a type not supported for an integer argument", fmt, input);
483 
484   // ***** Both have a format-spec
485   check(SV("^^[::::1, ::::2, :::42, ::-42]^^^"), SV("{:^^33::>5}"), input);
486   check(SV("^^[::::1, ::::2, :::42, ::-42]^^^"), SV("{:^^{}::>5}"), input, 33);
487   check(SV("^^[::::1, ::::2, :::42, ::-42]^^^"), SV("{:^^{}::>{}}"), input, 33, 5);
488 
489   check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
490   check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 33);
491 }
492 
493 template <class CharT, class TestFunction, class ExceptionTest>
test_int(TestFunction check,ExceptionTest check_exception)494 void test_int(TestFunction check, ExceptionTest check_exception) {
495   test_int<CharT>(check, check_exception, std::array{1, 2, 42, -42});
496   test_int<CharT>(check, check_exception, std::list{1, 2, 42, -42});
497   test_int<CharT>(check, check_exception, std::vector{1, 2, 42, -42});
498   std::array input{1, 2, 42, -42};
499   test_int<CharT>(check, check_exception, std::span{input});
500 }
501 
502 //
503 // Floating point
504 //
505 
506 template <class CharT, class TestFunction, class ExceptionTest>
test_floating_point(TestFunction check,ExceptionTest check_exception,auto && input)507 void test_floating_point(TestFunction check, ExceptionTest check_exception, auto&& input) {
508   check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{}"), input);
509 
510   // ***** underlying has no format-spec
511 
512   // *** align-fill & width ***
513   check(SV("[-42.5, 0, 1.25, 42.5]     "), SV("{:27}"), input);
514   check(SV("[-42.5, 0, 1.25, 42.5]*****"), SV("{:*<27}"), input);
515   check(SV("__[-42.5, 0, 1.25, 42.5]___"), SV("{:_^27}"), input);
516   check(SV("#####[-42.5, 0, 1.25, 42.5]"), SV("{:#>27}"), input);
517 
518   check(SV("[-42.5, 0, 1.25, 42.5]     "), SV("{:{}}"), input, 27);
519   check(SV("[-42.5, 0, 1.25, 42.5]*****"), SV("{:*<{}}"), input, 27);
520   check(SV("__[-42.5, 0, 1.25, 42.5]___"), SV("{:_^{}}"), input, 27);
521   check(SV("#####[-42.5, 0, 1.25, 42.5]"), SV("{:#>{}}"), input, 27);
522 
523   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
524   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
525   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
526 
527   // *** sign ***
528   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
529   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
530   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
531 
532   // *** alternate form ***
533   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
534 
535   // *** zero-padding ***
536   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
537 
538   // *** precision ***
539   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
540 
541   // *** locale-specific form ***
542   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
543 
544   // *** n
545   check(SV("__-42.5, 0, 1.25, 42.5___"), SV("{:_^25n}"), input);
546 
547   // *** type ***
548   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
549   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
550   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
551   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
552     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
553 
554   // ***** Only underlying has a format-spec
555   check(SV("[-42.5,     0,  1.25,  42.5]"), SV("{::5}"), input);
556   check(SV("[-42.5, 0****, 1.25*, 42.5*]"), SV("{::*<5}"), input);
557   check(SV("[-42.5, __0__, 1.25_, 42.5_]"), SV("{::_^5}"), input);
558   check(SV("[-42.5, ::::0, :1.25, :42.5]"), SV("{:::>5}"), input);
559 
560   check(SV("[-42.5,     0,  1.25,  42.5]"), SV("{::{}}"), input, 5);
561   check(SV("[-42.5, 0****, 1.25*, 42.5*]"), SV("{::*<{}}"), input, 5);
562   check(SV("[-42.5, __0__, 1.25_, 42.5_]"), SV("{::_^{}}"), input, 5);
563   check(SV("[-42.5, ::::0, :1.25, :42.5]"), SV("{:::>{}}"), input, 5);
564 
565   check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
566   check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
567 
568   // *** sign ***
569   check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::-}"), input);
570   check(SV("[-42.5, +0, +1.25, +42.5]"), SV("{::+}"), input);
571   check(SV("[-42.5,  0,  1.25,  42.5]"), SV("{:: }"), input);
572 
573   // *** alternate form ***
574   check(SV("[-42.5, 0., 1.25, 42.5]"), SV("{::#}"), input);
575 
576   // *** zero-padding ***
577   check(SV("[-42.5, 00000, 01.25, 042.5]"), SV("{::05}"), input);
578   check(SV("[-42.5, 0000., 01.25, 042.5]"), SV("{::#05}"), input);
579 
580   // *** precision ***
581   check(SV("[-42, 0, 1.2, 42]"), SV("{::.2}"), input);
582   check(SV("[-42.500, 0.000, 1.250, 42.500]"), SV("{::.3f}"), input);
583 
584   check(SV("[-42, 0, 1.2, 42]"), SV("{::.{}}"), input, 2);
585   check(SV("[-42.500, 0.000, 1.250, 42.500]"), SV("{::.{}f}"), input, 3);
586 
587   check_exception("The format-spec precision field doesn't contain a value or arg-id", SV("{::.}"), input);
588 
589   // *** locale-specific form ***
590   check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::L}"), input); // does not require locales present
591 #ifndef TEST_HAS_NO_LOCALIZATION
592 // TODO FMT Enable with locale testing active
593 #  if 0
594   std::locale::global(std::locale(LOCALE_fr_FR_UTF_8));
595   check(SV("[-42,5, 0, 1,25, 42,5]"), SV("{::L}"), input);
596 
597   std::locale::global(std::locale(LOCALE_en_US_UTF_8));
598   check(SV("[-42.5, 0, 1.25, 42.5]"), SV("{::L}"), input);
599 
600   std::locale::global(std::locale::classic());
601 #  endif
602 #endif // TEST_HAS_NO_LOCALIZATION
603 
604   // *** type ***
605   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("aAeEfFgG"))
606     check_exception("The format-spec type has a type not supported for a floating-point argument", fmt, input);
607 
608   // ***** Both have a format-spec
609   check(SV("^^[-42.5, ::::0, :1.25, :42.5]^^^"), SV("{:^^33::>5}"), input);
610   check(SV("^^[-42.5, ::::0, :1.25, :42.5]^^^"), SV("{:^^{}::>5}"), input, 33);
611   check(SV("^^[-42.5, ::::0, :1.25, :42.5]^^^"), SV("{:^^{}::>{}}"), input, 33, 5);
612 
613   check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^33::>5.2}"), input);
614   check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^{}::>5.2}"), input, 33);
615   check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^{}::>{}.2}"), input, 33, 5);
616   check(SV("^^[::-42, ::::0, ::1.2, :::42]^^^"), SV("{:^^{}::>{}.{}}"), input, 33, 5, 2);
617 
618   check_exception("Argument index out of bounds", SV("{:^^{}::>5.2}"), input);
619   check_exception("Argument index out of bounds", SV("{:^^{}::>{}.2}"), input, 33);
620   check_exception("Argument index out of bounds", SV("{:^^{}::>{}.{}}"), input, 33, 5);
621 }
622 
623 template <class CharT, class TestFunction, class ExceptionTest>
test_floating_point(TestFunction check,ExceptionTest check_exception)624 void test_floating_point(TestFunction check, ExceptionTest check_exception) {
625   test_floating_point<CharT>(check, check_exception, std::array{-42.5f, 0.0f, 1.25f, 42.5f});
626   test_floating_point<CharT>(check, check_exception, std::vector{-42.5, 0.0, 1.25, 42.5});
627 
628   std::array input{-42.5l, 0.0l, 1.25l, 42.5l};
629   test_floating_point<CharT>(check, check_exception, std::span{input});
630 }
631 
632 //
633 // Pointer
634 //
635 
636 template <class CharT, class TestFunction, class ExceptionTest>
test_pointer(TestFunction check,ExceptionTest check_exception,auto && input)637 void test_pointer(TestFunction check, ExceptionTest check_exception, auto&& input) {
638   check(SV("[0x0]"), SV("{}"), input);
639 
640   // ***** underlying has no format-spec
641 
642   // *** align-fill & width ***
643   check(SV("[0x0]     "), SV("{:10}"), input);
644   check(SV("[0x0]*****"), SV("{:*<10}"), input);
645   check(SV("__[0x0]___"), SV("{:_^10}"), input);
646   check(SV("#####[0x0]"), SV("{:#>10}"), input);
647 
648   check(SV("[0x0]     "), SV("{:{}}"), input, 10);
649   check(SV("[0x0]*****"), SV("{:*<{}}"), input, 10);
650   check(SV("__[0x0]___"), SV("{:_^{}}"), input, 10);
651   check(SV("#####[0x0]"), SV("{:#>{}}"), input, 10);
652 
653   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
654   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
655   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
656 
657   // *** sign ***
658   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
659 
660   // *** alternate form ***
661   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
662 
663   // *** zero-padding ***
664   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
665 
666   // *** precision ***
667   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
668 
669   // *** locale-specific form ***
670   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
671 
672   // *** n
673   check(SV("_0x0_"), SV("{:_^5n}"), input);
674 
675   // *** type ***
676   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
677   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
678   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
679   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
680     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
681 
682   // ***** Only underlying has a format-spec
683   check(SV("[  0x0]"), SV("{::5}"), input);
684   check(SV("[0x0**]"), SV("{::*<5}"), input);
685   check(SV("[_0x0_]"), SV("{::_^5}"), input);
686   check(SV("[::0x0]"), SV("{:::>5}"), input);
687 
688   check(SV("[  0x0]"), SV("{::{}}"), input, 5);
689   check(SV("[0x0**]"), SV("{::*<{}}"), input, 5);
690   check(SV("[_0x0_]"), SV("{::_^{}}"), input, 5);
691   check(SV("[::0x0]"), SV("{:::>{}}"), input, 5);
692 
693   check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
694   check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
695 
696   // *** sign ***
697   check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
698 
699   // *** alternate form ***
700   check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
701 
702   // *** zero-padding ***
703   check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
704 
705   // *** precision ***
706   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
707 
708   // *** locale-specific form ***
709   check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
710 
711   // *** type ***
712   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("p"))
713     check_exception("The format-spec type has a type not supported for a pointer argument", fmt, input);
714 
715   // ***** Both have a format-spec
716   check(SV("^^[::0x0]^^^"), SV("{:^^12::>5}"), input);
717   check(SV("^^[::0x0]^^^"), SV("{:^^{}::>5}"), input, 12);
718   check(SV("^^[::0x0]^^^"), SV("{:^^{}::>{}}"), input, 12, 5);
719 
720   check(SV("^^[::0x0]^^^"), SV("{:^^12::>5}"), input);
721   check(SV("^^[::0x0]^^^"), SV("{:^^{}::>5}"), input, 12);
722   check(SV("^^[::0x0]^^^"), SV("{:^^{}::>{}}"), input, 12, 5);
723 
724   check_exception("Argument index out of bounds", SV("{:^^{}::>5}"), input);
725   check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 12);
726 }
727 
728 template <class CharT, class TestFunction, class ExceptionTest>
test_pointer(TestFunction check,ExceptionTest check_exception)729 void test_pointer(TestFunction check, ExceptionTest check_exception) {
730   test_pointer<CharT>(check, check_exception, std::array{nullptr});
731   test_pointer<CharT>(check, check_exception, std::array{static_cast<const void*>(0)});
732   test_pointer<CharT>(check, check_exception, std::array{static_cast<void*>(0)});
733 }
734 
735 //
736 // String
737 //
738 
739 template <class CharT, class TestFunction, class ExceptionTest>
test_string(TestFunction check,ExceptionTest check_exception,auto && input)740 void test_string(TestFunction check, ExceptionTest check_exception, auto&& input) {
741   check(SV(R"(["Hello", "world"])"), SV("{}"), input);
742 
743   // ***** underlying has no format-spec
744 
745   // *** align-fill & width ***
746   check(SV(R"(["Hello", "world"]     )"), SV("{:23}"), input);
747   check(SV(R"(["Hello", "world"]*****)"), SV("{:*<23}"), input);
748   check(SV(R"(__["Hello", "world"]___)"), SV("{:_^23}"), input);
749   check(SV(R"(#####["Hello", "world"])"), SV("{:#>23}"), input);
750 
751   check(SV(R"(["Hello", "world"]     )"), SV("{:{}}"), input, 23);
752   check(SV(R"(["Hello", "world"]*****)"), SV("{:*<{}}"), input, 23);
753   check(SV(R"(__["Hello", "world"]___)"), SV("{:_^{}}"), input, 23);
754   check(SV(R"(#####["Hello", "world"])"), SV("{:#>{}}"), input, 23);
755 
756   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
757   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
758   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
759 
760   // *** sign ***
761   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
762 
763   // *** alternate form ***
764   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
765 
766   // *** zero-padding ***
767   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
768 
769   // *** precision ***
770   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
771 
772   // *** locale-specific form ***
773   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
774 
775   // *** n
776   check(SV(R"(_"Hello", "world"_)"), SV("{:_^18n}"), input);
777 
778   // *** type ***
779   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
780   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
781   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
782   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
783     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
784 
785   // ***** Only underlying has a format-spec
786   check(SV(R"([Hello   , world   ])"), SV("{::8}"), input);
787   check(SV(R"([Hello***, world***])"), SV("{::*<8}"), input);
788   check(SV(R"([_Hello__, _world__])"), SV("{::_^8}"), input);
789   check(SV(R"([:::Hello, :::world])"), SV("{:::>8}"), input);
790 
791   check(SV(R"([Hello   , world   ])"), SV("{::{}}"), input, 8);
792   check(SV(R"([Hello***, world***])"), SV("{::*<{}}"), input, 8);
793   check(SV(R"([_Hello__, _world__])"), SV("{::_^{}}"), input, 8);
794   check(SV(R"([:::Hello, :::world])"), SV("{:::>{}}"), input, 8);
795 
796   check_exception("The format-spec fill field contains an invalid character", SV("{::}<}"), input);
797   check_exception("The format-spec fill field contains an invalid character", SV("{::{<}"), input);
798 
799   // *** sign ***
800   check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
801 
802   // *** alternate form ***
803   check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
804 
805   // *** zero-padding ***
806   check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
807 
808   // *** precision ***
809   check(SV(R"([Hel, wor])"), SV("{::.3}"), input);
810 
811   check(SV(R"([Hel, wor])"), SV("{::.{}}"), input, 3);
812 
813   check_exception("The format-spec precision field doesn't contain a value or arg-id", SV("{::.}"), input);
814 
815   // *** locale-specific form ***
816   check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
817 
818   // *** type ***
819   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("s?"))
820     check_exception("The format-spec type has a type not supported for a string argument", fmt, input);
821 
822   // ***** Both have a format-spec
823   check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^25::>8}"), input);
824   check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>8}"), input, 25);
825   check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
826 
827   check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^25::>8}"), input);
828   check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>8}"), input, 25);
829   check(SV(R"(^^[:::Hello, :::world]^^^)"), SV("{:^^{}::>{}}"), input, 25, 8);
830 
831   check_exception("Argument index out of bounds", SV("{:^^{}::>8}"), input);
832   check_exception("Argument index out of bounds", SV("{:^^{}::>{}}"), input, 25);
833 }
834 
835 template <class CharT, class TestFunction, class ExceptionTest>
test_string(TestFunction check,ExceptionTest check_exception)836 void test_string(TestFunction check, ExceptionTest check_exception) {
837   test_string<CharT>(check, check_exception, std::array{CSTR("Hello"), CSTR("world")});
838   test_string<CharT>(check, check_exception, std::array{STR("Hello"), STR("world")});
839   test_string<CharT>(check, check_exception, std::array{SV("Hello"), SV("world")});
840 }
841 
842 //
843 // Handle
844 //
845 
846 template <class CharT, class TestFunction, class ExceptionTest>
test_status(TestFunction check,ExceptionTest check_exception)847 void test_status(TestFunction check, ExceptionTest check_exception) {
848   std::array input{status::foo, status::bar, status::foobar};
849 
850   check(SV("[0xaaaa, 0x5555, 0xaa55]"), SV("{}"), input);
851 
852   // ***** underlying has no format-spec
853 
854   // *** align-fill & width ***
855   check(SV("[0xaaaa, 0x5555, 0xaa55]     "), SV("{:29}"), input);
856   check(SV("[0xaaaa, 0x5555, 0xaa55]*****"), SV("{:*<29}"), input);
857   check(SV("__[0xaaaa, 0x5555, 0xaa55]___"), SV("{:_^29}"), input);
858   check(SV("#####[0xaaaa, 0x5555, 0xaa55]"), SV("{:#>29}"), input);
859 
860   check(SV("[0xaaaa, 0x5555, 0xaa55]     "), SV("{:{}}"), input, 29);
861   check(SV("[0xaaaa, 0x5555, 0xaa55]*****"), SV("{:*<{}}"), input, 29);
862   check(SV("__[0xaaaa, 0x5555, 0xaa55]___"), SV("{:_^{}}"), input, 29);
863   check(SV("#####[0xaaaa, 0x5555, 0xaa55]"), SV("{:#>{}}"), input, 29);
864 
865   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
866   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
867   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
868 
869   // *** sign ***
870   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
871   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
872   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
873 
874   // *** alternate form ***
875   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
876 
877   // *** zero-padding ***
878   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
879 
880   // *** precision ***
881   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
882 
883   // *** locale-specific form ***
884   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
885 
886   // *** n
887   check(SV("__0xaaaa, 0x5555, 0xaa55___"), SV("{:_^27n}"), input);
888 
889   // *** type ***
890   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
891   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
892   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
893   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
894     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
895 
896   // ***** Only underlying has a format-spec
897   check_exception("The format-spec type has a type not supported for a status argument", SV("{::*<7}"), input);
898   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("sxX"))
899     check_exception("The format-spec type has a type not supported for a status argument", fmt, input);
900 
901   check(SV("[0xaaaa, 0x5555, 0xaa55]"), SV("{::x}"), input);
902   check(SV("[0XAAAA, 0X5555, 0XAA55]"), SV("{::X}"), input);
903   check(SV("[foo, bar, foobar]"), SV("{::s}"), input);
904 
905   // ***** Both have a format-spec
906   check(SV("^^[0XAAAA, 0X5555, 0XAA55]^^^"), SV("{:^^29:X}"), input);
907   check(SV("^^[0XAAAA, 0X5555, 0XAA55]^^^"), SV("{:^^{}:X}"), input, 29);
908 
909   check_exception("Argument index out of bounds", SV("{:^^{}:X}"), input);
910 }
911 
912 //
913 // Pair
914 //
915 
916 template <class CharT, class TestFunction, class ExceptionTest>
test_pair_tuple(TestFunction check,ExceptionTest check_exception,auto && input)917 void test_pair_tuple(TestFunction check, ExceptionTest check_exception, auto&& input) {
918   // [format.range.formatter]/3
919   //   For range_formatter<T, charT>, the format-spec in a
920   //   range-underlying-spec, if any, is interpreted by formatter<T, charT>.
921   //
922   //   template<class ParseContext>
923   //   constexpr typename ParseContext::iterator
924   //    parse(ParseContext& ctx);
925   // [format.tuple]/7
926   //   ... if e.set_debug_format() is a valid expression, calls
927   //   e.set_debug_format().
928   // So when there is no range-underlying-spec, there is no need to call parse
929   // thus the char element is not escaped.
930   // TODO FMT P2733 addresses this issue.
931   check(SV("[(1, 'a'), (42, '*')]"), SV("{}"), input);
932 
933   // ***** underlying has no format-spec
934 
935   // *** align-fill & width ***
936   check(SV("[(1, 'a'), (42, '*')]     "), SV("{:26}"), input);
937   check(SV("[(1, 'a'), (42, '*')]*****"), SV("{:*<26}"), input);
938   check(SV("__[(1, 'a'), (42, '*')]___"), SV("{:_^26}"), input);
939   check(SV("#####[(1, 'a'), (42, '*')]"), SV("{:#>26}"), input);
940 
941   check(SV("[(1, 'a'), (42, '*')]     "), SV("{:{}}"), input, 26);
942   check(SV("[(1, 'a'), (42, '*')]*****"), SV("{:*<{}}"), input, 26);
943   check(SV("__[(1, 'a'), (42, '*')]___"), SV("{:_^{}}"), input, 26);
944   check(SV("#####[(1, 'a'), (42, '*')]"), SV("{:#>{}}"), input, 26);
945 
946   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
947   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
948   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
949 
950   // *** sign ***
951   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
952   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
953   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
954 
955   // *** alternate form ***
956   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
957 
958   // *** zero-padding ***
959   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
960 
961   // *** precision ***
962   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
963 
964   // *** locale-specific form ***
965   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
966 
967   // *** n
968   check(SV("__(1, 'a'), (42, '*')___"), SV("{:_^24n}"), input);
969   check(SV("__(1, 'a'), (42, '*')___"), SV("{:_^24nm}"), input); // m should have no effect
970 
971   // *** type ***
972   check(SV("__{(1, 'a'), (42, '*')}___"), SV("{:_^26m}"), input);
973   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
974   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
975   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
976     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
977 
978   // ***** Only underlying has a format-spec
979   check(SV("[(1, 'a')   , (42, '*')  ]"), SV("{::11}"), input);
980   check(SV("[(1, 'a')***, (42, '*')**]"), SV("{::*<11}"), input);
981   check(SV("[_(1, 'a')__, _(42, '*')_]"), SV("{::_^11}"), input);
982   check(SV("[###(1, 'a'), ##(42, '*')]"), SV("{::#>11}"), input);
983 
984   check(SV("[(1, 'a')   , (42, '*')  ]"), SV("{::{}}"), input, 11);
985   check(SV("[(1, 'a')***, (42, '*')**]"), SV("{::*<{}}"), input, 11);
986   check(SV("[_(1, 'a')__, _(42, '*')_]"), SV("{::_^{}}"), input, 11);
987   check(SV("[###(1, 'a'), ##(42, '*')]"), SV("{::#>{}}"), input, 11);
988 
989   check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
990   check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
991   check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
992 
993   // *** sign ***
994   check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
995   check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
996   check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
997 
998   // *** alternate form ***
999   check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
1000 
1001   // *** zero-padding ***
1002   check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
1003 
1004   // *** precision ***
1005   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
1006 
1007   // *** locale-specific form ***
1008   check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
1009 
1010   // *** type ***
1011   check(SV("[1: 'a', 42: '*']"), SV("{::m}"), input);
1012   check(SV("[1, 'a', 42, '*']"), SV("{::n}"), input);
1013   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
1014     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1015 
1016   // ***** Both have a format-spec
1017   check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^31:#>11}"), input);
1018   check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^31:#>11}"), input);
1019   check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^{}:#>11}"), input, 31);
1020   check(SV("^^[###(1, 'a'), ##(42, '*')]^^^"), SV("{:^^{}:#>{}}"), input, 31, 11);
1021 
1022   check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
1023   check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 31);
1024 
1025   check(SV("1: 'a', 42: '*'"), SV("{:n:m}"), input);
1026   check(SV("1, 'a', 42, '*'"), SV("{:n:n}"), input);
1027   check(SV("{1: 'a', 42: '*'}"), SV("{:m:m}"), input);
1028   check(SV("{1, 'a', 42, '*'}"), SV("{:m:n}"), input);
1029 }
1030 
1031 template <class CharT, class TestFunction, class ExceptionTest>
test_pair_tuple(TestFunction check,ExceptionTest check_exception)1032 void test_pair_tuple(TestFunction check, ExceptionTest check_exception) {
1033   test_pair_tuple<CharT>(
1034       check, check_exception, std::array{std::make_pair(1, CharT('a')), std::make_pair(42, CharT('*'))});
1035   test_pair_tuple<CharT>(
1036       check, check_exception, std::array{std::make_tuple(1, CharT('a')), std::make_tuple(42, CharT('*'))});
1037 }
1038 
1039 //
1040 // Tuple 1
1041 //
1042 
1043 template <class CharT, class TestFunction, class ExceptionTest>
test_tuple_int(TestFunction check,ExceptionTest check_exception)1044 void test_tuple_int(TestFunction check, ExceptionTest check_exception) {
1045   std::array input{std::make_tuple(42), std::make_tuple(99)};
1046 
1047   check(SV("[(42), (99)]"), SV("{}"), input);
1048 
1049   // ***** underlying has no format-spec
1050 
1051   // *** align-fill & width ***
1052   check(SV("[(42), (99)]     "), SV("{:17}"), input);
1053   check(SV("[(42), (99)]*****"), SV("{:*<17}"), input);
1054   check(SV("__[(42), (99)]___"), SV("{:_^17}"), input);
1055   check(SV("#####[(42), (99)]"), SV("{:#>17}"), input);
1056 
1057   check(SV("[(42), (99)]     "), SV("{:{}}"), input, 17);
1058   check(SV("[(42), (99)]*****"), SV("{:*<{}}"), input, 17);
1059   check(SV("__[(42), (99)]___"), SV("{:_^{}}"), input, 17);
1060   check(SV("#####[(42), (99)]"), SV("{:#>{}}"), input, 17);
1061 
1062   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
1063   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
1064   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
1065 
1066   // *** sign ***
1067   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
1068   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
1069   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
1070 
1071   // *** alternate form ***
1072   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
1073 
1074   // *** zero-padding ***
1075   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
1076 
1077   // *** precision ***
1078   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
1079 
1080   // *** locale-specific form ***
1081   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
1082 
1083   // *** n
1084   check(SV("__(42), (99)___"), SV("{:_^15n}"), input);
1085 
1086   // *** type ***
1087   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
1088   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
1089   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
1090   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
1091     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1092 
1093   // ***** Only underlying has a format-spec
1094   check(SV("[(42)   , (99)   ]"), SV("{::7}"), input);
1095   check(SV("[(42)***, (99)***]"), SV("{::*<7}"), input);
1096   check(SV("[_(42)__, _(99)__]"), SV("{::_^7}"), input);
1097   check(SV("[###(42), ###(99)]"), SV("{::#>7}"), input);
1098 
1099   check(SV("[(42)   , (99)   ]"), SV("{::{}}"), input, 7);
1100   check(SV("[(42)***, (99)***]"), SV("{::*<{}}"), input, 7);
1101   check(SV("[_(42)__, _(99)__]"), SV("{::_^{}}"), input, 7);
1102   check(SV("[###(42), ###(99)]"), SV("{::#>{}}"), input, 7);
1103 
1104   check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
1105   check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
1106   check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
1107 
1108   // *** sign ***
1109   check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
1110   check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
1111   check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
1112 
1113   // *** alternate form ***
1114   check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
1115 
1116   // *** zero-padding ***
1117   check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
1118 
1119   // *** precision ***
1120   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
1121 
1122   // *** locale-specific form ***
1123   check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
1124 
1125   // *** type ***
1126   check(SV("[42, 99]"), SV("{::n}"), input);
1127   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>(""))
1128     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1129 
1130   // ***** Both have a format-spec
1131   check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^23:#>7}"), input);
1132   check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^23:#>7}"), input);
1133   check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^{}:#>7}"), input, 23);
1134   check(SV("^^[###(42), ###(99)]^^^"), SV("{:^^{}:#>{}}"), input, 23, 7);
1135 
1136   check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
1137   check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 23);
1138 }
1139 
1140 //
1141 // Tuple 3
1142 //
1143 
1144 template <class CharT, class TestFunction, class ExceptionTest>
test_tuple_int_int_int(TestFunction check,ExceptionTest check_exception)1145 void test_tuple_int_int_int(TestFunction check, ExceptionTest check_exception) {
1146   std::array input{std::make_tuple(42, 99, 0), std::make_tuple(1, 10, 100)};
1147 
1148   check(SV("[(42, 99, 0), (1, 10, 100)]"), SV("{}"), input);
1149 
1150   // ***** underlying has no format-spec
1151 
1152   // *** align-fill & width ***
1153   check(SV("[(42, 99, 0), (1, 10, 100)]     "), SV("{:32}"), input);
1154   check(SV("[(42, 99, 0), (1, 10, 100)]*****"), SV("{:*<32}"), input);
1155   check(SV("__[(42, 99, 0), (1, 10, 100)]___"), SV("{:_^32}"), input);
1156   check(SV("#####[(42, 99, 0), (1, 10, 100)]"), SV("{:#>32}"), input);
1157 
1158   check(SV("[(42, 99, 0), (1, 10, 100)]     "), SV("{:{}}"), input, 32);
1159   check(SV("[(42, 99, 0), (1, 10, 100)]*****"), SV("{:*<{}}"), input, 32);
1160   check(SV("__[(42, 99, 0), (1, 10, 100)]___"), SV("{:_^{}}"), input, 32);
1161   check(SV("#####[(42, 99, 0), (1, 10, 100)]"), SV("{:#>{}}"), input, 32);
1162 
1163   check_exception("The format-spec range-fill field contains an invalid character", SV("{:}<}"), input);
1164   check_exception("The format-spec range-fill field contains an invalid character", SV("{:{<}"), input);
1165   check_exception("The format-spec range-fill field contains an invalid character", SV("{::<}"), input);
1166 
1167   // *** sign ***
1168   check_exception("The format-spec should consume the input or end with a '}'", SV("{:-}"), input);
1169   check_exception("The format-spec should consume the input or end with a '}'", SV("{:+}"), input);
1170   check_exception("The format-spec should consume the input or end with a '}'", SV("{: }"), input);
1171 
1172   // *** alternate form ***
1173   check_exception("The format-spec should consume the input or end with a '}'", SV("{:#}"), input);
1174 
1175   // *** zero-padding ***
1176   check_exception("A format-spec width field shouldn't have a leading zero", SV("{:0}"), input);
1177 
1178   // *** precision ***
1179   check_exception("The format-spec should consume the input or end with a '}'", SV("{:.}"), input);
1180 
1181   // *** locale-specific form ***
1182   check_exception("The format-spec should consume the input or end with a '}'", SV("{:L}"), input);
1183 
1184   // *** n
1185   check(SV("__(42, 99, 0), (1, 10, 100)___"), SV("{:_^30n}"), input);
1186 
1187   // *** type ***
1188   check_exception("The range-format-spec type m requires two elements for a pair or tuple", SV("{:m}"), input);
1189   check_exception("The range-format-spec type s requires formatting a character type", SV("{:s}"), input);
1190   check_exception("The range-format-spec type ?s requires formatting a character type", SV("{:?s}"), input);
1191   for (std::basic_string_view<CharT> fmt : fmt_invalid_types<CharT>("s"))
1192     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1193 
1194   // ***** Only underlying has a format-spec
1195   check(SV("[(42, 99, 0)   , (1, 10, 100)  ]"), SV("{::14}"), input);
1196   check(SV("[(42, 99, 0)***, (1, 10, 100)**]"), SV("{::*<14}"), input);
1197   check(SV("[_(42, 99, 0)__, _(1, 10, 100)_]"), SV("{::_^14}"), input);
1198   check(SV("[###(42, 99, 0), ##(1, 10, 100)]"), SV("{::#>14}"), input);
1199 
1200   check(SV("[(42, 99, 0)   , (1, 10, 100)  ]"), SV("{::{}}"), input, 14);
1201   check(SV("[(42, 99, 0)***, (1, 10, 100)**]"), SV("{::*<{}}"), input, 14);
1202   check(SV("[_(42, 99, 0)__, _(1, 10, 100)_]"), SV("{::_^{}}"), input, 14);
1203   check(SV("[###(42, 99, 0), ##(1, 10, 100)]"), SV("{::#>{}}"), input, 14);
1204 
1205   check_exception("The format-spec range-fill field contains an invalid character", SV("{:::<}"), input);
1206   check_exception("The format-spec range-fill field contains an invalid character", SV("{::}<}"), input);
1207   check_exception("The format-spec range-fill field contains an invalid character", SV("{::{<}"), input);
1208 
1209   // *** sign ***
1210   check_exception("The format-spec should consume the input or end with a '}'", SV("{::-}"), input);
1211   check_exception("The format-spec should consume the input or end with a '}'", SV("{::+}"), input);
1212   check_exception("The format-spec should consume the input or end with a '}'", SV("{:: }"), input);
1213 
1214   // *** alternate form ***
1215   check_exception("The format-spec should consume the input or end with a '}'", SV("{::#}"), input);
1216 
1217   // *** zero-padding ***
1218   check_exception("A format-spec width field shouldn't have a leading zero", SV("{::05}"), input);
1219 
1220   // *** precision ***
1221   check_exception("The format-spec should consume the input or end with a '}'", SV("{::.}"), input);
1222 
1223   // *** locale-specific form ***
1224   check_exception("The format-spec should consume the input or end with a '}'", SV("{::L}"), input);
1225 
1226   // *** type ***
1227   check(SV("[42, 99, 0, 1, 10, 100]"), SV("{::n}"), input);
1228   for (std::basic_string_view<CharT> fmt : fmt_invalid_nested_types<CharT>("s"))
1229     check_exception("The format-spec should consume the input or end with a '}'", fmt, input);
1230 
1231   // ***** Both have a format-spec
1232   check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^37:#>14}"), input);
1233   check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^37:#>14}"), input);
1234   check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^{}:#>14}"), input, 37);
1235   check(SV("^^[###(42, 99, 0), ##(1, 10, 100)]^^^"), SV("{:^^{}:#>{}}"), input, 37, 14);
1236 
1237   check_exception("Argument index out of bounds", SV("{:^^{}:#>5}"), input);
1238   check_exception("Argument index out of bounds", SV("{:^^{}:#>{}}"), input, 37);
1239 }
1240 
1241 //
1242 // Ranges
1243 //
1244 
1245 template <class CharT, class TestFunction, class ExceptionTest>
test_with_ranges(TestFunction check,ExceptionTest check_exception,auto && iter)1246 void test_with_ranges(TestFunction check, ExceptionTest check_exception, auto&& iter) {
1247   std::ranges::subrange range{std::move(iter), std::default_sentinel};
1248   test_int<CharT>(check, check_exception, std::move(range));
1249 }
1250 
1251 template <class CharT, class TestFunction, class ExceptionTest>
test_with_ranges(TestFunction check,ExceptionTest check_exception)1252 void test_with_ranges(TestFunction check, ExceptionTest check_exception) {
1253   std::array input{1, 2, 42, -42};
1254   test_with_ranges<CharT>(
1255       check, check_exception, std::counted_iterator{cpp20_input_iterator<int*>(input.data()), input.size()});
1256   test_with_ranges<CharT>(
1257       check, check_exception, std::counted_iterator{forward_iterator<int*>(input.data()), input.size()});
1258   test_with_ranges<CharT>(
1259       check, check_exception, std::counted_iterator{bidirectional_iterator<int*>(input.data()), input.size()});
1260   test_with_ranges<CharT>(
1261       check, check_exception, std::counted_iterator{random_access_iterator<int*>(input.data()), input.size()});
1262   test_with_ranges<CharT>(
1263       check, check_exception, std::counted_iterator{contiguous_iterator<int*>(input.data()), input.size()});
1264 }
1265 
1266 //
1267 // Adaptor
1268 //
1269 
1270 template <class CharT>
1271 class non_contiguous {
1272   // A deque iterator is random access, but not contiguous.
1273   using adaptee = std::deque<CharT>;
1274 
1275 public:
1276   using iterator = typename adaptee::iterator;
1277   using pointer  = typename adaptee::pointer;
1278 
begin()1279   iterator begin() { return data_.begin(); }
end()1280   iterator end() { return data_.end(); }
1281 
non_contiguous(adaptee && data)1282   explicit non_contiguous(adaptee&& data) : data_(std::move(data)) {}
1283 
1284 private:
1285   adaptee data_;
1286 };
1287 
1288 template <class CharT>
1289 class contiguous {
1290   // A vector iterator is contiguous.
1291   using adaptee = std::vector<CharT>;
1292 
1293 public:
1294   using iterator = typename adaptee::iterator;
1295   using pointer  = typename adaptee::pointer;
1296 
begin()1297   iterator begin() { return data_.begin(); }
end()1298   iterator end() { return data_.end(); }
1299 
contiguous(adaptee && data)1300   explicit contiguous(adaptee&& data) : data_(std::move(data)) {}
1301 
1302 private:
1303   adaptee data_;
1304 };
1305 
1306 // This tests two different implementations in libc++. A basic_string_view
1307 // formatter if the range is contiguous, a basic_string otherwise.
1308 template <class CharT, class TestFunction, class ExceptionTest>
test_adaptor(TestFunction check,ExceptionTest check_exception)1309 void test_adaptor(TestFunction check, ExceptionTest check_exception) {
1310   static_assert(std::format_kind<non_contiguous<CharT>> == std::range_format::sequence);
1311   static_assert(std::ranges::sized_range<non_contiguous<CharT>>);
1312   static_assert(!std::ranges::contiguous_range<non_contiguous<CharT>>);
1313   test_char_string<CharT>(
1314       check,
1315       check_exception,
1316       non_contiguous<CharT>{std::deque{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')}});
1317 
1318   static_assert(std::format_kind<contiguous<CharT>> == std::range_format::sequence);
1319   static_assert(std::ranges::sized_range<contiguous<CharT>>);
1320   static_assert(std::ranges::contiguous_range<contiguous<CharT>>);
1321   test_char_string<CharT>(check,
1322                           check_exception,
1323                           contiguous<CharT>{std::vector{CharT('H'), CharT('e'), CharT('l'), CharT('l'), CharT('o')}});
1324 }
1325 
1326 //
1327 // Driver
1328 //
1329 
1330 template <class CharT, class TestFunction, class ExceptionTest>
format_tests(TestFunction check,ExceptionTest check_exception)1331 void format_tests(TestFunction check, ExceptionTest check_exception) {
1332   test_char<CharT>(check, check_exception);
1333 #ifndef _LIBCPP_HAS_NO_WIDE_CHARACTERS
1334   if (std::same_as<CharT, wchar_t>) // avoid testing twice
1335     test_char_to_wchar(check, check_exception);
1336 #endif
1337   test_bool<CharT>(check, check_exception);
1338   test_int<CharT>(check, check_exception);
1339   test_floating_point<CharT>(check, check_exception);
1340   test_pointer<CharT>(check, check_exception);
1341   test_string<CharT>(check, check_exception);
1342 
1343   test_status<CharT>(check, check_exception); // Has its own handler with its own parser
1344 
1345   test_pair_tuple<CharT>(check, check_exception);
1346   test_tuple_int<CharT>(check, check_exception);
1347   test_tuple_int_int_int<CharT>(check, check_exception);
1348 
1349   test_with_ranges<CharT>(check, check_exception);
1350 
1351   test_adaptor<CharT>(check, check_exception);
1352 }
1353 
1354 #endif // TEST_STD_UTILITIES_FORMAT_FORMAT_RANGE_FORMAT_RANGE_FORMATTER_FORMAT_FUNCTIONS_TESTS_H
1355