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// UNSUPPORTED: c++03, c++11, c++14, c++17, c++20
9// UNSUPPORTED: GCC-ALWAYS_INLINE-FIXME
10
11// This version runs the test when the platform has Unicode support.
12// UNSUPPORTED: libcpp-has-no-unicode
13
14// TODO FMT This test should not require std::to_chars(floating-point)
15// XFAIL: availability-fp_to_chars-missing
16
17// <format>
18
19// This test the debug string type for the formatter specializations for char
20// and string types. This tests Unicode strings.
21
22#include <format>
23
24#include <cassert>
25#include <concepts>
26#include <iterator>
27#include <list>
28#include <vector>
29
30#include "test_macros.h"
31#include "make_string.h"
32#include "test_format_string.h"
33#include "assert_macros.h"
34#include "concat_macros.h"
35
36#ifndef TEST_HAS_NO_LOCALIZATION
37# include <iostream>
38#endif
39
40#define SV(S) MAKE_STRING_VIEW(CharT, S)
41
42auto test_format = []<class CharT, class... Args>(
43 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
44 {
45 std::basic_string<CharT> out = std::format(fmt, std::forward<Args>(args)...);
46 TEST_REQUIRE(out == expected,
47 TEST_WRITE_CONCATENATED(
48 "\nFormat string ", fmt.get(), "\nExpected output ", expected, "\nActual output ", out, '\n'));
49 }
50#ifndef TEST_HAS_NO_LOCALIZATION
51 {
52 std::basic_string<CharT> out = std::format(std::locale(), fmt, std::forward<Args>(args)...);
53 assert(out == expected);
54 }
55#endif // TEST_HAS_NO_LOCALIZATION
56};
57
58auto test_format_to =
59 []<class CharT, class... Args>(
60 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
61 {
62 std::basic_string<CharT> out(expected.size(), CharT(' '));
63 auto it = std::format_to(out.begin(), fmt, std::forward<Args>(args)...);
64 assert(it == out.end());
65 assert(out == expected);
66 }
67#ifndef TEST_HAS_NO_LOCALIZATION
68 {
69 std::basic_string<CharT> out(expected.size(), CharT(' '));
70 auto it = std::format_to(out.begin(), std::locale(), fmt, std::forward<Args>(args)...);
71 assert(it == out.end());
72 assert(out == expected);
73 }
74#endif // TEST_HAS_NO_LOCALIZATION
75 {
76 std::list<CharT> out;
77 std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...);
78 assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
79 }
80 {
81 std::vector<CharT> out;
82 std::format_to(std::back_inserter(out), fmt, std::forward<Args>(args)...);
83 assert(std::equal(out.begin(), out.end(), expected.begin(), expected.end()));
84 }
85 {
86 assert(expected.size() < 4096 && "Update the size of the buffer.");
87 CharT out[4096];
88 CharT* it = std::format_to(out, fmt, std::forward<Args>(args)...);
89 assert(std::distance(out, it) == int(expected.size()));
90 // Convert to std::string since output contains '\0' for boolean tests.
91 assert(std::basic_string<CharT>(out, it) == expected);
92 }
93 };
94
95auto test_formatted_size =
96 []<class CharT, class... Args>(
97 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
98 {
99 std::size_t size = std::formatted_size(fmt, std::forward<Args>(args)...);
100 assert(size == expected.size());
101 }
102#ifndef TEST_HAS_NO_LOCALIZATION
103 {
104 std::size_t size = std::formatted_size(std::locale(), fmt, std::forward<Args>(args)...);
105 assert(size == expected.size());
106 }
107#endif // TEST_HAS_NO_LOCALIZATION
108 };
109
110auto test_format_to_n =
111 []<class CharT, class... Args>(
112 std::basic_string_view<CharT> expected, test_format_string<CharT, Args...> fmt, Args&&... args) {
113 {
114 std::size_t n = expected.size();
115 std::basic_string<CharT> out(n, CharT(' '));
116 std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
117 assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
118 assert(result.out == out.end());
119 assert(out == expected);
120 }
121#ifndef TEST_HAS_NO_LOCALIZATION
122 {
123 std::size_t n = expected.size();
124 std::basic_string<CharT> out(n, CharT(' '));
125 std::format_to_n_result result =
126 std::format_to_n(out.begin(), n, std::locale(), fmt, std::forward<Args>(args)...);
127 assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
128 assert(result.out == out.end());
129 assert(out == expected);
130 }
131#endif // TEST_HAS_NO_LOCALIZATION
132 {
133 std::ptrdiff_t n = 0;
134 std::basic_string<CharT> out;
135 std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
136 assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
137 assert(result.out == out.end());
138 assert(out.empty());
139 }
140 {
141 std::ptrdiff_t n = expected.size() / 2;
142 std::basic_string<CharT> out(n, CharT(' '));
143 std::format_to_n_result result = std::format_to_n(out.begin(), n, fmt, std::forward<Args>(args)...);
144 assert(result.size == static_cast<std::ptrdiff_t>(expected.size()));
145 assert(result.out == out.end());
146 assert(out == expected.substr(0, n));
147 }
148 };
149
150template <class CharT>
151void test_char() {
152 // *** P2286 examples ***
153 test_format(SV("['\\'', '\"']"), SV("[{:?}, {:?}]"), CharT('\''), CharT('"'));
154
155 // *** Special cases ***
156 test_format(SV("'\\t'"), SV("{:?}"), CharT('\t'));
157 test_format(SV("'\\n'"), SV("{:?}"), CharT('\n'));
158 test_format(SV("'\\r'"), SV("{:?}"), CharT('\r'));
159 test_format(SV("'\\\\'"), SV("{:?}"), CharT('\\'));
160
161 test_format(SV("'\\\''"), SV("{:?}"), CharT('\''));
162 test_format(SV("'\"'"), SV("{:?}"), CharT('"')); // only special for string
163
164 test_format(SV("' '"), SV("{:?}"), CharT(' '));
165
166 // *** Printable ***
167 test_format(SV("'a'"), SV("{:?}"), CharT('a'));
168 test_format(SV("'b'"), SV("{:?}"), CharT('b'));
169 test_format(SV("'c'"), SV("{:?}"), CharT('c'));
170
171 // *** Non-printable ***
172
173 // Control
174 test_format(SV("'\\u{0}'"), SV("{:?}"), CharT('\0'));
175 test_format(SV("'\\u{1f}'"), SV("{:?}"), CharT('\x1f'));
176
177 // Ill-formed
178 if constexpr (sizeof(CharT) == 1)
179 test_format(SV("'\\x{80}'"), SV("{:?}"), CharT('\x80'));
180
181#ifndef TEST_HAS_NO_WIDE_CHARACTERS
182 if constexpr (sizeof(CharT) > 1) {
183 using V = std::basic_string_view<CharT>;
184
185 // Unicode fitting in a 16-bit wchar_t
186
187 // *** Non-printable ***
188
189 // Space_Separator
190 test_format(V{L"'\\u{a0}'"}, L"{:?}", L'\xa0'); // NO-BREAK SPACE
191 test_format(V{L"'\\u{3000}'"}, L"{:?}", L'\x3000'); // IDEOGRAPHIC SPACE
192
193 // Line_Separator
194 test_format(V{L"'\\u{2028}'"}, L"{:?}", L'\x2028'); // LINE SEPARATOR
195
196 // Paragraph_Separator
197 test_format(V{L"'\\u{2029}'"}, L"{:?}", L'\x2029'); // PARAGRAPH SEPARATOR
198
199 // Format
200 test_format(V{L"'\\u{ad}'"}, L"{:?}", L'\xad'); // SOFT HYPHEN
201 test_format(V{L"'\\u{600}'"}, L"{:?}", L'\x600'); // ARABIC NUMBER SIGN
202 test_format(V{L"'\\u{feff}'"}, L"{:?}", L'\xfeff'); // ZERO WIDTH NO-BREAK SPACE
203
204 // Incomplete surrogate pair in UTF-16
205 test_format(V{L"'\\x{d800}'"}, L"{:?}", L'\xd800'); // <surrogate-D800>
206 test_format(V{L"'\\x{dfff}'"}, L"{:?}", L'\xdfff'); // <surrogate-DFFF>
207
208 // Private_Use
209 test_format(V{L"'\\u{e000}'"}, L"{:?}", L'\xe000'); // <private-use-E000>
210 test_format(V{L"'\\u{f8ff}'"}, L"{:?}", L'\xf8ff'); // <private-use-F8FF>
211
212 // Unassigned
213 test_format(V{L"'\\u{378}'"}, L"{:?}", L'\x378'); // <reserved-0378>
214 test_format(V{L"'\\u{1774}'"}, L"{:?}", L'\x1774'); // <reserved-1774>
215 test_format(V{L"'\\u{ffff}'"}, L"{:?}", L'\xffff'); // <noncharacter-FFFF>
216
217 // Grapheme Extended
218 test_format(V{L"'\\u{300}'"}, L"{:?}", L'\x300'); // COMBINING GRAVE ACCENT
219 test_format(V{L"'\\u{fe20}'"}, L"{:?}", L'\xfe20'); // VARIATION SELECTOR-1
220 }
221# ifndef TEST_SHORT_WCHAR
222 if constexpr (sizeof(CharT) > 2) {
223 static_assert(sizeof(CharT) == 4, "add support for unexpected size");
224 // Unicode fitting in a 32-bit wchar_t
225
226 constexpr wchar_t x = 0x1ffff;
227 constexpr std::uint32_t y = 0x1ffff;
228 static_assert(x == y);
229
230 using V = std::basic_string_view<CharT>;
231
232 // *** Non-printable ***
233 // Format
234 test_format(V{L"'\\u{110bd}'"}, L"{:?}", L'\x110bd'); // KAITHI NUMBER SIGN
235 test_format(V{L"'\\u{e007f}'"}, L"{:?}", L'\xe007f'); // CANCEL TAG
236
237 // Private_Use
238 test_format(V{L"'\\u{f0000}'"}, L"{:?}", L'\xf0000'); // <private-use-F0000>
239 test_format(V{L"'\\u{ffffd}'"}, L"{:?}", L'\xffffd'); // <private-use-FFFFD>
240
241 test_format(V{L"'\\u{100000}'"}, L"{:?}", L'\x100000'); // <private-use-100000>
242 test_format(V{L"'\\u{10fffd}'"}, L"{:?}", L'\x10fffd'); // <private-use-10FFFD>
243
244 // Unassigned
245 test_format(V{L"'\\u{1000c}'"}, L"{:?}", L'\x1000c'); // <reserved-1000c>
246 test_format(V{L"'\\u{fffff}'"}, L"{:?}", L'\xfffff'); // <noncharacter-FFFFF>
247 test_format(V{L"'\\u{10fffe}'"}, L"{:?}", L'\x10fffe'); // <noncharacter-10FFFE>
248
249 // Grapheme Extended
250 test_format(V{L"'\\u{101fd}'"}, L"{:?}", L'\x101fd'); // COMBINING OLD PERMIC LETTER AN
251 test_format(V{L"'\\u{e0100}'"}, L"{:?}", L'\xe0100'); // VARIATION SELECTOR-17
252
253 // Ill-formed
254 test_format(V{L"'\\x{110000}'"}, L"{:?}", L'\x110000');
255 test_format(V{L"'\\x{ffffffff}'"}, L"{:?}", L'\xffffffff');
256 }
257# endif // TEST_SHORT_WCHAR
258#endif // TEST_HAS_NO_WIDE_CHARACTERS
259}
260
261template <class CharT>
262void test_string() {
263 // *** P2286 examples ***
264 test_format(SV("[h\tllo]"), SV("[{}]"), SV("h\tllo"));
265 test_format(SV(R"(["h\tllo"])"), SV("[{:?}]"), SV("h\tllo"));
266 test_format(SV(R"(["Спасибо, Виктор ♥!"])"), SV("[{:?}]"), SV("Спасибо, Виктор ♥!"));
267
268 test_format(SV(R"(["\u{0} \n \t \u{2} \u{1b}"])"), SV("[{:?}]"), SV("\0 \n \t \x02 \x1b"));
269
270 if constexpr (sizeof(CharT) == 1) {
271 // Ill-formend UTF-8
272 test_format(SV(R"(["\x{c3}"])"), SV("[{:?}]"), "\xc3");
273 test_format(SV(R"(["\x{c3}("])"), SV("[{:?}]"), "\xc3\x28");
274
275 /* U+0000..U+0007F 1 code unit range, encoded in 2 code units. */
276 test_format(SV(R"(["\x{c0}\x{80}"])"), SV("[{:?}]"), "\xc0\x80"); // U+0000
277 test_format(SV(R"(["\x{c1}\x{bf}"])"), SV("[{:?}]"), "\xc1\xbf"); // U+007F
278 test_format(SV(R"(["\u{80}"])"), SV("[{:?}]"), "\xc2\x80"); // U+0080 first valid (General_Category=Control)
279
280 /* U+0000..U+07FFF 1 and 2 code unit range, encoded in 3 code units. */
281 test_format(SV(R"(["\x{e0}\x{80}\x{80}"])"), SV("[{:?}]"), "\xe0\x80\x80"); // U+0000
282 test_format(SV(R"(["\x{e0}\x{81}\x{bf}"])"), SV("[{:?}]"), "\xe0\x81\xbf"); // U+007F
283 test_format(SV(R"(["\x{e0}\x{82}\x{80}"])"), SV("[{:?}]"), "\xe0\x82\x80"); // U+0080
284 test_format(SV(R"(["\x{e0}\x{9f}\x{bf}"])"), SV("[{:?}]"), "\xe0\x9f\xbf"); // U+07FF
285 test_format(SV("[\"\u0800\"]"), SV("[{:?}]"), "\xe0\xa0\x80"); // U+0800 first valid
286
287#if 0
288 // This code point is in the Hangul Jamo Extended-B block and at the time of writing
289 // it's unassigned. When it comes defined, this branch might become true.
290 test_format(SV("[\"\ud7ff\"]"), SV("[{:?}]"), "\xed\x9f\xbf"); // U+D7FF last valid
291#else
292 /* U+D800..D+DFFFF surrogate range */
293 test_format(SV(R"(["\u{d7ff}"])"), SV("[{:?}]"), "\xed\x9f\xbf"); // U+D7FF last valid
294#endif
295 test_format(SV(R"(["\x{ed}\x{a0}\x{80}"])"), SV("[{:?}]"), "\xed\xa0\x80"); // U+D800
296 test_format(SV(R"(["\x{ed}\x{af}\x{bf}"])"), SV("[{:?}]"), "\xed\xaf\xbf"); // U+DBFF
297 test_format(SV(R"(["\x{ed}\x{bf}\x{80}"])"), SV("[{:?}]"), "\xed\xbf\x80"); // U+DC00
298 test_format(SV(R"(["\x{ed}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xed\xbf\xbf"); // U+DFFF
299 test_format(SV(R"(["\u{e000}"])"), SV("[{:?}]"), "\xee\x80\x80"); // U+E000 first valid
300 // (in the Private Use Area block)
301
302 /* U+0000..U+FFFF 1, 2, and 3 code unit range */
303 test_format(SV(R"(["\x{f0}\x{80}\x{80}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\x80\x80"); // U+0000
304 test_format(SV(R"(["\x{f0}\x{80}\x{81}\x{bf}"])"), SV("[{:?}]"), "\xf0\x80\x81\xbf"); // U+007F
305 test_format(SV(R"(["\x{f0}\x{80}\x{82}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\x82\x80"); // U+0080
306 test_format(SV(R"(["\x{f0}\x{80}\x{9f}\x{bf}"])"), SV("[{:?}]"), "\xf0\x80\x9f\xbf"); // U+07FF
307 test_format(SV(R"(["\x{f0}\x{80}\x{a0}\x{80}"])"), SV("[{:?}]"), "\xf0\x80\xa0\x80"); // U+0800
308 test_format(SV(R"(["\x{f0}\x{8f}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xf0\x8f\xbf\xbf"); // U+FFFF
309 test_format(SV("[\"\U00010000\"]"), SV("[{:?}]"), "\xf0\x90\x80\x80"); // U+10000 first valid
310
311 /* U+10FFFF..U+1FFFFF invalid range */
312 test_format(SV(R"(["\u{10ffff}"])"), SV("[{:?}]"), "\xf4\x8f\xbf\xbf"); // U+10FFFF last valid
313 // (in Supplementary Private Use Area-B)
314 test_format(SV(R"(["\x{f4}\x{90}\x{80}\x{80}"])"), SV("[{:?}]"), "\xf4\x90\x80\x80"); // U+110000
315 test_format(SV(R"(["\x{f4}\x{bf}\x{bf}\x{bf}"])"), SV("[{:?}]"), "\xf4\xbf\xbf\xbf"); // U+11FFFF
316 } else {
317 // Valid UTF-16 and UTF-32
318 test_format(SV("[\"\u00c3\"]"), SV("[{:?}]"), L"\xc3"); // LATIN CAPITAL LETTER A WITH TILDE
319 test_format(SV("[\"\u00c3(\"]"), SV("[{:?}]"), L"\xc3\x28");
320 }
321
322 test_format(SV(R"(["🤷🏻\u{200d}♂\u{fe0f}"])"), SV("[{:?}]"), SV("🤷🏻‍♂️"));
323
324 // *** Special cases ***
325 test_format(SV(R"("\t\n\r\\'\" ")"), SV("{:?}"), SV("\t\n\r\\'\" "));
326
327 // *** Printable ***
328 test_format(SV(R"("abcdefg")"), SV("{:?}"), SV("abcdefg"));
329
330 // *** Non-printable ***
331
332 // Control
333 test_format(SV(R"("\u{0}\u{1f}")"), SV("{:?}"), SV("\0\x1f"));
334
335 // Ill-formed
336 if constexpr (sizeof(CharT) == 1)
337 test_format(SV(R"("\x{80}")"), SV("{:?}"), SV("\x80"));
338
339#ifndef TEST_HAS_NO_WIDE_CHARACTERS
340 if constexpr (sizeof(CharT) > 1) {
341 using V = std::basic_string_view<CharT>;
342
343 // Unicode fitting in a 16-bit wchar_t
344
345 // *** Non-printable ***
346
347 // Space_Separator
348 test_format(V{LR"("\u{a0}\u{3000}")"}, L"{:?}", L"\xa0\x3000");
349
350 // Line_Separator
351 test_format(V{LR"("\u{2028}")"}, L"{:?}", L"\x2028"); // LINE SEPARATOR
352
353 // Paragraph_Separator
354 test_format(V{LR"("\u{2029}")"}, L"{:?}", L"\x2029"); // PARAGRAPH SEPARATOR
355
356 // Format
357 test_format(V{LR"("\u{ad}\u{600}\u{feff}")"}, L"{:?}", L"\xad\x600\xfeff");
358
359 // Incomplete surrogate pair in UTF-16
360 test_format(V{LR"("\x{d800}")"}, L"{:?}", L"\xd800");
361
362 // Private_Use
363 test_format(V{LR"("\u{e000}\u{f8ff}")"}, L"{:?}", L"\xe000\xf8ff");
364
365 // Unassigned
366 test_format(V{LR"("\u{378}\u{1774}\u{ffff}")"}, L"{:?}", L"\x378\x1774\xffff");
367
368 // Grapheme Extended
369 test_format(V{LR"("\u{300}\u{fe20}")"}, L"{:?}", L"\x300\xfe20");
370 }
371# ifndef TEST_SHORT_WCHAR
372 if constexpr (sizeof(CharT) > 2) {
373 static_assert(sizeof(CharT) == 4, "add support for unexpected size");
374 // Unicode fitting in a 32-bit wchar_t
375
376 constexpr wchar_t x = 0x1ffff;
377 constexpr std::uint32_t y = 0x1ffff;
378 static_assert(x == y);
379
380 using V = std::basic_string_view<CharT>;
381
382 // *** Non-printable ***
383 // Format
384 test_format(V{LR"("\u{110bd}\u{e007f}")"}, L"{:?}", L"\x110bd\xe007f");
385
386 // Private_Use
387 test_format(V{LR"("\u{f0000}\u{ffffd}\u{100000}\u{10fffd}")"}, L"{:?}", L"\xf0000\xffffd\x100000\x10fffd");
388
389 // Unassigned
390 test_format(V{LR"("\u{1000c}\u{fffff}\u{10fffe}")"}, L"{:?}", L"\x1000c\xfffff\x10fffe");
391
392 // Grapheme Extended
393 test_format(V{LR"("\u{101fd}\u{e0100}")"}, L"{:?}", L"\x101fd\xe0100");
394
395 // Ill-formed
396 test_format(V{LR"("\x{110000}\x{ffffffff}")"}, L"{:?}", L"\x110000\xffffffff");
397 }
398# endif // TEST_SHORT_WCHAR
399#endif // TEST_HAS_NO_WIDE_CHARACTERS
400}
401
402template <class CharT, class TestFunction>
403void test_format_functions(TestFunction check) {
404 // *** align-fill & width ***
405 check(SV(R"(***"hellö")"), SV("{:*>10?}"), SV("hellö")); // ö is LATIN SMALL LETTER O WITH DIAERESIS
406 check(SV(R"(*"hellö"**)"), SV("{:*^10?}"), SV("hellö"));
407 check(SV(R"("hellö"***)"), SV("{:*<10?}"), SV("hellö"));
408
409 check(SV(R"("hello\u{308}")"), SV("{:*>10?}"), SV("hello\u0308"));
410 check(SV(R"(***"hello\u{308}")"), SV("{:*>17?}"), SV("hello\u0308"));
411 check(SV(R"(*"hello\u{308}"**)"), SV("{:*^17?}"), SV("hello\u0308"));
412 check(SV(R"("hello\u{308}"***)"), SV("{:*<17?}"), SV("hello\u0308"));
413
414 check(SV(R"("hello 🤷🏻\u{200d}♂\u{fe0f}")"), SV("{:*>10?}"), SV("hello 🤷🏻‍♂️"));
415 check(SV(R"(***"hello 🤷🏻\u{200d}♂\u{fe0f}")"), SV("{:*>30?}"), SV("hello 🤷🏻‍♂️"));
416 check(SV(R"(*"hello 🤷🏻\u{200d}♂\u{fe0f}"**)"), SV("{:*^30?}"), SV("hello 🤷🏻‍♂️"));
417 check(SV(R"("hello 🤷🏻\u{200d}♂\u{fe0f}"***)"), SV("{:*<30?}"), SV("hello 🤷🏻‍♂️"));
418
419 // *** width ***
420 check(SV(R"("hellö" )"), SV("{:10?}"), SV("hellö"));
421 check(SV(R"("hello\u{308}" )"), SV("{:17?}"), SV("hello\u0308"));
422 check(SV(R"("hello 🤷🏻\u{200d}♂\u{fe0f}" )"), SV("{:30?}"), SV("hello 🤷🏻‍♂️"));
423
424 // *** precision ***
425 check(SV(R"("hell)"), SV("{:.5?}"), SV("hellö"));
426 check(SV(R"("hellö)"), SV("{:.6?}"), SV("hellö"));
427 check(SV(R"("hellö")"), SV("{:.7?}"), SV("hellö"));
428
429 check(SV(R"("hello )"), SV("{:.7?}"), SV("hello 🤷🏻‍♂️"));
430 check(SV(R"("hello )"), SV("{:.8?}"), SV("hello 🤷🏻‍♂️")); // shrug is two columns
431 check(SV(R"("hello 🤷🏻)"), SV("{:.9?}"), SV("hello 🤷🏻‍♂️"));
432 check(SV(R"("hello 🤷🏻\)"), SV("{:.10?}"), SV("hello 🤷🏻‍♂️"));
433 check(SV(R"("hello 🤷🏻\u{200d})"), SV("{:.17?}"), SV("hello 🤷🏻‍♂️"));
434 check(SV(R"("hello 🤷🏻\u{200d}♂)"), SV("{:.18?}"), SV("hello 🤷🏻‍♂️"));
435 check(SV(R"("hello 🤷🏻\u{200d}♂\)"), SV("{:.19?}"), SV("hello 🤷🏻‍♂️"));
436 check(SV(R"("hello 🤷🏻\u{200d}♂\u{fe0f}")"), SV("{:.28?}"), SV("hello 🤷🏻‍♂️"));
437
438 // *** width & precision ***
439 check(SV(R"("hell#########################)"), SV("{:#<30.5?}"), SV("hellö"));
440 check(SV(R"("hellö########################)"), SV("{:#<30.6?}"), SV("hellö"));
441 check(SV(R"("hellö"#######################)"), SV("{:#<30.7?}"), SV("hellö"));
442
443 check(SV(R"("hello #######################)"), SV("{:#<30.7?}"), SV("hello 🤷🏻‍♂️"));
444 check(SV(R"("hello #######################)"), SV("{:#<30.8?}"), SV("hello 🤷🏻‍♂️"));
445 check(SV(R"("hello 🤷🏻#####################)"), SV("{:#<30.9?}"), SV("hello 🤷🏻‍♂️"));
446 check(SV(R"("hello 🤷🏻\####################)"), SV("{:#<30.10?}"), SV("hello 🤷🏻‍♂️"));
447 check(SV(R"("hello 🤷🏻\u{200d}#############)"), SV("{:#<30.17?}"), SV("hello 🤷🏻‍♂️"));
448 check(SV(R"("hello 🤷🏻\u{200d}♂############)"), SV("{:#<30.18?}"), SV("hello 🤷🏻‍♂️"));
449 check(SV(R"("hello 🤷🏻\u{200d}♂\###########)"), SV("{:#<30.19?}"), SV("hello 🤷🏻‍♂️"));
450 check(SV(R"("hello 🤷🏻\u{200d}♂\u{fe0f}"###)"), SV("{:#<30.28?}"), SV("hello 🤷🏻‍♂️"));
451}
452
453template <class CharT>
454void test() {
455 test_char<CharT>();
456 test_string<CharT>();
457
458 test_format_functions<CharT>(test_format);
459 test_format_functions<CharT>(test_format_to);
460 test_format_functions<CharT>(test_formatted_size);
461 test_format_functions<CharT>(test_format_to_n);
462}
463
464static void test_ill_formed_utf8() {
465 using namespace std::literals;
466
467 // Too few code units
468 test_format(R"("\x{df}")"sv, "{:?}", "\xdf");
469 test_format(R"("\x{ef}")"sv, "{:?}", "\xef");
470 test_format(R"("\x{ef}\x{bf}")"sv, "{:?}", "\xef\xbf");
471 test_format(R"("\x{f7}")"sv, "{:?}", "\xf7");
472 test_format(R"("\x{f7}\x{bf}")"sv, "{:?}", "\xf7\xbf");
473 test_format(R"("\x{f7}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf");
474
475 // Invalid continuation byte
476 test_format(R"("\x{df}a")"sv,
477 "{:?}",
478 "\xdf"
479 "a");
480 test_format(R"("\x{ef}a")"sv,
481 "{:?}",
482 "\xef"
483 "a");
484 test_format(R"("\x{ef}\x{bf}a")"sv,
485 "{:?}",
486 "\xef\xbf"
487 "a");
488 test_format(R"("\x{f7}a")"sv,
489 "{:?}",
490 "\xf7"
491 "a");
492 test_format(R"("\x{f7}\x{bf}a")"sv,
493 "{:?}",
494 "\xf7\xbf"
495 "a");
496 test_format(R"("\x{f7}\x{bf}\x{bf}a")"sv,
497 "{:?}",
498 "\xf7\xbf\xbf"
499 "a");
500
501 test_format(R"("a\x{f1}\x{80}\x{80}\x{e1}\x{80}\x{c2}b")"sv,
502 "{:?}",
503 "a"
504 "\xf1\x80\x80\xe1\x80\xc2"
505 "b");
506
507 // Code unit out of range
508 test_format(R"("\u{10ffff}")"sv, "{:?}", "\xf4\x8f\xbf\xbf"); // last valid code point
509 test_format(R"("\x{f4}\x{90}\x{80}\x{80}")"sv, "{:?}", "\xf4\x90\x80\x80"); // first invalid code point
510 test_format(R"("\x{f5}\x{b1}\x{b2}\x{b3}")"sv, "{:?}", "\xf5\xb1\xb2\xb3");
511 test_format(R"("\x{f7}\x{bf}\x{bf}\x{bf}")"sv, "{:?}", "\xf7\xbf\xbf\xbf"); // largest encoded code point
512}
513
514#ifndef TEST_HAS_NO_WIDE_CHARACTERS
515# ifdef TEST_SHORT_WCHAR
516static void test_ill_formed_utf16() {
517 using namespace std::literals;
518
519 // Too few code units
520 test_format(LR"("\x{d800}")"sv, L"{:?}", L"\xd800");
521 test_format(LR"("\x{dbff}")"sv, L"{:?}", L"\xdbff");
522
523 // Start with low surrogate pair
524 test_format(LR"("\x{dc00}a")"sv,
525 L"{:?}",
526 L"\xdc00"
527 "a");
528 test_format(LR"("\x{dfff}a")"sv,
529 L"{:?}",
530 L"\xdfff"
531 "a");
532
533 // Only high surrogate pair
534 test_format(LR"("\x{d800}a")"sv,
535 L"{:?}",
536 L"\xd800"
537 "a");
538 test_format(LR"("\x{dbff}a")"sv,
539 L"{:?}",
540 L"\xdbff"
541 "a");
542}
543# else // TEST_SHORT_WCHAR
544static void test_ill_formed_utf32() {
545 using namespace std::literals;
546
547 test_format(LR"("\u{10ffff}")"sv, L"{:?}", L"\x10ffff"); // last valid code point
548 test_format(LR"("\x{110000}")"sv, L"{:?}", L"\x110000"); // first invalid code point
549 test_format(LR"("\x{ffffffff}")"sv, L"{:?}", L"\xffffffff"); // largest encoded code point
550}
551
552# endif // TEST_SHORT_WCHAR
553#endif // TEST_HAS_NO_WIDE_CHARACTERS
554
555int main(int, char**) {
556 test<char>();
557#ifndef TEST_HAS_NO_WIDE_CHARACTERS
558 test<wchar_t>();
559#endif
560
561 test_ill_formed_utf8();
562#ifndef TEST_HAS_NO_WIDE_CHARACTERS
563# ifdef TEST_SHORT_WCHAR
564 test_ill_formed_utf16();
565# else // TEST_SHORT_WCHAR
566 test_ill_formed_utf32();
567# endif // TEST_SHORT_WCHAR
568#endif // TEST_HAS_NO_WIDE_CHARACTERS
569
570 return 0;
571}
572

source code of libcxx/test/std/utilities/format/format.functions/escaped_output.unicode.pass.cpp