1 // { dg-do run { target c++20 } }
5 #include <testsuite_hooks.h>
7 namespace uc
= std::__unicode
;
8 using namespace std::string_view_literals
;
13 const std::u8string_view s8
= u8
"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡";
15 VERIFY( std::ranges::distance(v
) == s8
.size() );
16 VERIFY( std::ranges::equal(v
, s8
) );
22 const std::u8string_view s8
= u8
"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡";
23 const std::u16string_view s16
= u
"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡";
24 uc::_Utf16_view
v(s8
);
25 VERIFY( std::ranges::distance(v
) == s16
.size() );
26 VERIFY( std::ranges::equal(v
, s16
) );
32 const auto s8
= u8
"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡"sv
;
33 const auto s32
= U
"£🇬🇧 €🇪🇺 æбçδé ♠♥♦♣ 🤡"sv
;
34 uc::_Utf32_view
v(s8
);
35 VERIFY( std::ranges::distance(v
) == s32
.size() );
36 VERIFY( std::ranges::equal(v
, s32
) );
42 uc::_Utf32_view
v("\xa3 10.99 \xee \xdd"sv
);
43 VERIFY( std::ranges::equal(v
, U
"\uFFFD 10.99 \uFFFD \uFFFD"sv
) );
45 uc::_Utf16_view
v2(" \xf8\x80\x80\x80 "sv
);
46 VERIFY( std::ranges::distance(v2
) == 6 );
47 VERIFY( std::ranges::equal(v2
, U
" \uFFFD\uFFFD\uFFFD\uFFFD "sv
) );
49 // Examples of U+FFFD substitution from Unicode standard.
50 uc::_Utf8_view
v3("\xc0\xaf\xe0\x80\xbf\xf0\x81\x82\x41"sv
); // Table 3-8
51 VERIFY( std::ranges::equal(v3
, u8
"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv
) );
52 uc::_Utf8_view
v4("\xed\xa0\x80\xed\xbf\xbf\xed\xaf\x41"sv
); // Table 3-9
53 VERIFY( std::ranges::equal(v4
, u8
"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv
) );
54 uc::_Utf8_view
v5("\xf4\x91\x92\x93\xff\x41\x80\xbf\x42"sv
); // Table 3-10
55 VERIFY( std::ranges::equal(v5
, u8
"\uFFFD\uFFFD\uFFFD\uFFFD\uFFFD\x41\uFFFD\uFFFD\x42"sv
) );
56 uc::_Utf8_view
v6("\xe1\x80\xe2\xf0\x91\x92\xf1\xbf\x41"sv
); // Table 3-11
57 VERIFY( std::ranges::equal(v6
, u8
"\uFFFD\uFFFD\uFFFD\uFFFD\x41"sv
) );
61 test_illformed_utf16()
63 std::u16string_view s
= u
"\N{CLOWN FACE}";
64 std::u16string_view r
= u
"\uFFFD";
65 VERIFY( std::ranges::equal(uc::_Utf16_view(s
.substr(0, 1)), r
) );
66 VERIFY( std::ranges::equal(uc::_Utf16_view(s
.substr(1, 1)), r
) );
67 std::array s2
{ s
[0], s
[0] };
68 VERIFY( std::ranges::equal(uc::_Utf16_view(s2
), u
"\uFFFD\uFFFD"sv
) );
69 std::array s3
{ s
[0], s
[0], s
[1] };
70 VERIFY( std::ranges::equal(uc::_Utf16_view(s3
), u
"\uFFFD\N{CLOWN FACE}"sv
) );
71 std::array s4
{ s
[1], s
[0] };
72 VERIFY( std::ranges::equal(uc::_Utf16_view(s4
), u
"\uFFFD\uFFFD"sv
) );
73 std::array s5
{ s
[1], s
[0], s
[1] };
74 VERIFY( std::ranges::equal(uc::_Utf16_view(s5
), u
"\uFFFD\N{CLOWN FACE}"sv
) );
78 test_illformed_utf32()
80 std::u32string_view s
= U
"\x110000";
81 VERIFY( std::ranges::equal(uc::_Utf32_view(s
), U
"\uFFFD"sv
) );
83 VERIFY( std::ranges::equal(uc::_Utf32_view(s
), U
"\uFFFD"sv
) );
85 VERIFY( std::ranges::equal(uc::_Utf32_view(s
), U
"\uFFFD"sv
) );
91 const auto s8
= u8
"1234"sv
;
92 uc::_Utf32_view
v(s8
);
93 auto iter
= v
.begin();
94 std::advance(iter
, 4);
95 VERIFY( iter
== v
.end() );
96 // Incrementing past the end has well-defined behaviour.
98 VERIFY( iter
== v
.end() );
99 VERIFY( *iter
== U
'4' ); // Still dereferenceable.
101 VERIFY( iter
== v
.end() );
102 VERIFY( *iter
== U
'4' );
104 VERIFY( iter
== v
.end() );
105 VERIFY( *iter
== U
'4' );
107 std::string_view empty
;
108 uc::_Utf32_view
v2(empty
);
109 auto iter2
= v2
.begin();
110 VERIFY( iter2
== v2
.end() );
111 VERIFY( *iter2
== U
'\0' );
113 VERIFY( iter2
== v2
.end() );
114 VERIFY( *iter2
== U
'\0' );
121 test_utf8_to_utf16();
122 test_utf8_to_utf32();
123 test_illformed_utf8();
124 test_illformed_utf16();
125 test_illformed_utf32();
130 VERIFY( run_tests() );
131 static_assert( run_tests() );