Casual observation from a random reader that's sometimes hit by testresults acting up:
On Thu, 9 Feb 2023, Dimitrij Mijoski via Gcc-patches wrote: > libstdc++-v3/ChangeLog: > > * testsuite/22_locale/codecvt/codecvt_unicode.cc: Rename > functions. > * testsuite/22_locale/codecvt/codecvt_unicode.h: Make more > generic so it accepts char8_t. > * testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc: Rename > functions. > * testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc: New test. (Second line indents to the "*", not the text after it. TL;DR: See other entries.) But above that, please never *modify* existing tests (unless they're bad and wrong), add new ones instead. TL;DR: Bisecting when reghunting gets messy. brgds, H-P > --- > .../22_locale/codecvt/codecvt_unicode.cc | 16 +- > .../22_locale/codecvt/codecvt_unicode.h | 807 +++++++++--------- > .../codecvt/codecvt_unicode_char8_t.cc | 53 ++ > .../codecvt/codecvt_unicode_wchar_t.cc | 6 +- > 4 files changed, 484 insertions(+), 398 deletions(-) > create mode 100644 > libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc > > diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc > b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc > index df1a2b4cc..eafb53a8c 100644 > --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc > +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.cc > @@ -27,38 +27,38 @@ void > test_utf8_utf32_codecvts () > { > using codecvt_c32 = codecvt<char32_t, char, mbstate_t>; > - auto loc_c = locale::classic (); > + auto &loc_c = locale::classic (); > VERIFY (has_facet<codecvt_c32> (loc_c)); > > auto &cvt = use_facet<codecvt_c32> (loc_c); > - test_utf8_utf32_codecvts (cvt); > + test_utf8_utf32_cvt (cvt); > > codecvt_utf8<char32_t> cvt2; > - test_utf8_utf32_codecvts (cvt2); > + test_utf8_utf32_cvt (cvt2); > } > > void > test_utf8_utf16_codecvts () > { > using codecvt_c16 = codecvt<char16_t, char, mbstate_t>; > - auto loc_c = locale::classic (); > + auto &loc_c = locale::classic (); > VERIFY (has_facet<codecvt_c16> (loc_c)); > > auto &cvt = use_facet<codecvt_c16> (loc_c); > - test_utf8_utf16_cvts (cvt); > + test_utf8_utf16_cvt (cvt); > > codecvt_utf8_utf16<char16_t> cvt2; > - test_utf8_utf16_cvts (cvt2); > + test_utf8_utf16_cvt (cvt2); > > codecvt_utf8_utf16<char32_t> cvt3; > - test_utf8_utf16_cvts (cvt3); > + test_utf8_utf16_cvt (cvt3); > } > > void > test_utf8_ucs2_codecvts () > { > codecvt_utf8<char16_t> cvt; > - test_utf8_ucs2_cvts (cvt); > + test_utf8_ucs2_cvt (cvt); > } > > int > diff --git a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h > b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h > index fbdc7a35b..690c07215 100644 > --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h > +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode.h > @@ -42,33 +42,33 @@ auto constexpr array_size (const T (&)[N]) -> size_t > return N; > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf32_in_ok (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf32_in_ok (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char in[] = "b?\uAAAA\U0010AAAA"; > - const char32_t exp_literal[] = U"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - std::copy (begin (exp_literal), end (exp_literal), begin (exp)); > - > - static_assert (array_size (in) == 11, ""); > - static_assert (array_size (exp_literal) == 5, ""); > - static_assert (array_size (exp) == 5, ""); > - VERIFY (char_traits<char>::length (in) == 10); > - VERIFY (char_traits<char32_t>::length (exp_literal) == 4); > - VERIFY (char_traits<CharT>::length (exp) == 4); > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char32_t expected[] = U"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 5, ""); > + > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 4); > > test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {3, 2}, {6, 3}, {10, 4}}; > for (auto t : offsets) > { > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -76,19 +76,19 @@ utf8_to_utf32_in_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<CharT>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > > for (auto t : offsets) > { > - CharT out[array_size (exp)] = {}; > + InternT out[array_size (exp)] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res > @@ -96,29 +96,29 @@ utf8_to_utf32_in_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<CharT>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf32_in_partial (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf32_in_partial (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char in[] = "b?\uAAAA\U0010AAAA"; > - const char32_t exp_literal[] = U"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - std::copy (begin (exp_literal), end (exp_literal), begin (exp)); > - > - static_assert (array_size (in) == 11, ""); > - static_assert (array_size (exp_literal) == 5, ""); > - static_assert (array_size (exp) == 5, ""); > - VERIFY (char_traits<char>::length (in) == 10); > - VERIFY (char_traits<char32_t>::length (exp_literal) == 4); > - VERIFY (char_traits<CharT>::length (exp) == 4); > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char32_t expected[] = U"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 5, ""); > + > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 4); > > test_offsets_partial offsets[] = { > {1, 0, 0, 0}, // no space for first CP > @@ -144,14 +144,14 @@ utf8_to_utf32_in_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > > for (auto t : offsets) > { > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -159,37 +159,38 @@ utf8_to_utf32_in_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.partial); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<CharT>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf32_in_error (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf32_in_error (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char valid_in[] = "b?\uAAAA\U0010AAAA"; > - const char32_t exp_literal[] = U"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - std::copy (begin (exp_literal), end (exp_literal), begin (exp)); > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char32_t expected[] = U"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 5, ""); > > - static_assert (array_size (valid_in) == 11, ""); > - static_assert (array_size (exp_literal) == 5, ""); > - static_assert (array_size (exp) == 5, ""); > - VERIFY (char_traits<char>::length (valid_in) == 10); > - VERIFY (char_traits<char32_t>::length (exp_literal) == 4); > - VERIFY (char_traits<CharT>::length (exp) == 4); > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 4); > > - test_offsets_error<char> offsets[] = { > + test_offsets_error<unsigned char> offsets[] = { > > // replace leading byte with invalid byte > - {1, 4, 0, 0, '\xFF', 0}, > - {3, 4, 1, 1, '\xFF', 1}, > - {6, 4, 3, 2, '\xFF', 3}, > - {10, 4, 6, 3, '\xFF', 6}, > + {1, 4, 0, 0, 0xFF, 0}, > + {3, 4, 1, 1, 0xFF, 1}, > + {6, 4, 3, 2, 0xFF, 3}, > + {10, 4, 6, 3, 0xFF, 6}, > > // replace first trailing byte with ASCII byte > {3, 4, 1, 1, 'z', 2}, > @@ -197,21 +198,21 @@ utf8_to_utf32_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > {10, 4, 6, 3, 'z', 7}, > > // replace first trailing byte with invalid byte > - {3, 4, 1, 1, '\xFF', 2}, > - {6, 4, 3, 2, '\xFF', 4}, > - {10, 4, 6, 3, '\xFF', 7}, > + {3, 4, 1, 1, 0xFF, 2}, > + {6, 4, 3, 2, 0xFF, 4}, > + {10, 4, 6, 3, 0xFF, 7}, > > // replace second trailing byte with ASCII byte > {6, 4, 3, 2, 'z', 5}, > {10, 4, 6, 3, 'z', 8}, > > // replace second trailing byte with invalid byte > - {6, 4, 3, 2, '\xFF', 5}, > - {10, 4, 6, 3, '\xFF', 8}, > + {6, 4, 3, 2, 0xFF, 5}, > + {10, 4, 6, 3, 0xFF, 8}, > > // replace third trailing byte > {10, 4, 6, 3, 'z', 9}, > - {10, 4, 6, 3, '\xFF', 9}, > + {10, 4, 6, 3, 0xFF, 9}, > > // replace first trailing byte with ASCII byte, also incomplete at end > {5, 4, 3, 2, 'z', 4}, > @@ -219,30 +220,29 @@ utf8_to_utf32_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > {9, 4, 6, 3, 'z', 7}, > > // replace first trailing byte with invalid byte, also incomplete at end > - {5, 4, 3, 2, '\xFF', 4}, > - {8, 4, 6, 3, '\xFF', 7}, > - {9, 4, 6, 3, '\xFF', 7}, > + {5, 4, 3, 2, 0xFF, 4}, > + {8, 4, 6, 3, 0xFF, 7}, > + {9, 4, 6, 3, 0xFF, 7}, > > // replace second trailing byte with ASCII byte, also incomplete at end > {9, 4, 6, 3, 'z', 8}, > > // replace second trailing byte with invalid byte, also incomplete at end > - {9, 4, 6, 3, '\xFF', 8}, > + {9, 4, 6, 3, 0xFF, 8}, > }; > for (auto t : offsets) > { > - char in[array_size (valid_in)] = {}; > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > - char_traits<char>::copy (in, valid_in, array_size (valid_in)); > + auto old_char = in[t.replace_pos]; > in[t.replace_pos] = t.replace_char; > > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -250,48 +250,51 @@ utf8_to_utf32_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.error); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<CharT>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > + > + in[t.replace_pos] = old_char; > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf32_in (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf32_in (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf8_to_utf32_in_ok (cvt); > utf8_to_utf32_in_partial (cvt); > utf8_to_utf32_in_error (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf32_to_utf8_out_ok (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf32_to_utf8_out_ok (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char32_t in_literal[] = U"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - CharT in[array_size (in_literal)] = {}; > - copy (begin (in_literal), end (in_literal), begin (in)); > - > - static_assert (array_size (in_literal) == 5, ""); > - static_assert (array_size (in) == 5, ""); > - static_assert (array_size (exp) == 11, ""); > - VERIFY (char_traits<char32_t>::length (in_literal) == 4); > - VERIFY (char_traits<CharT>::length (in) == 4); > - VERIFY (char_traits<char>::length (exp) == 10); > + const char32_t input[] = U"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 5, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 4); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > > const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {4, > 10}}; > for (auto t : offsets) > { > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -299,29 +302,29 @@ utf32_to_utf8_out_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<char>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf32_to_utf8_out_partial (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf32_to_utf8_out_partial (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char32_t in_literal[] = U"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - CharT in[array_size (in_literal)] = {}; > - copy (begin (in_literal), end (in_literal), begin (in)); > - > - static_assert (array_size (in_literal) == 5, ""); > - static_assert (array_size (in) == 5, ""); > - static_assert (array_size (exp) == 11, ""); > - VERIFY (char_traits<char32_t>::length (in_literal) == 4); > - VERIFY (char_traits<CharT>::length (in) == 4); > - VERIFY (char_traits<char>::length (exp) == 10); > + const char32_t input[] = U"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 5, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 4); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > > const test_offsets_partial offsets[] = { > {1, 0, 0, 0}, // no space for first CP > @@ -340,14 +343,14 @@ utf32_to_utf8_out_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > }; > for (auto t : offsets) > { > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -355,44 +358,49 @@ utf32_to_utf8_out_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.partial); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<char>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf32_to_utf8_out_error (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf32_to_utf8_out_error (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > - const char32_t valid_in[] = U"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - > - static_assert (array_size (valid_in) == 5, ""); > - static_assert (array_size (exp) == 11, ""); > - VERIFY (char_traits<char32_t>::length (valid_in) == 4); > - VERIFY (char_traits<char>::length (exp) == 10); > - > - test_offsets_error<CharT> offsets[] = {{4, 10, 0, 0, 0x00110000, 0}, > - {4, 10, 1, 1, 0x00110000, 1}, > - {4, 10, 2, 3, 0x00110000, 2}, > - {4, 10, 3, 6, 0x00110000, 3}}; > + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > + const char32_t input[] = U"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 5, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 4); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > + > + test_offsets_error<InternT> offsets[] = {{4, 10, 0, 0, 0x00110000, 0}, > + {4, 10, 1, 1, 0x00110000, 1}, > + {4, 10, 2, 3, 0x00110000, 2}, > + {4, 10, 3, 6, 0x00110000, 3}}; > > for (auto t : offsets) > { > - CharT in[array_size (valid_in)] = {}; > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > - copy (begin (valid_in), end (valid_in), begin (in)); > + auto old_char = in[t.replace_pos]; > in[t.replace_pos] = t.replace_char; > > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -400,56 +408,59 @@ utf32_to_utf8_out_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.error); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<char>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > + > + in[t.replace_pos] = old_char; > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf32_to_utf8_out (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf32_to_utf8_out (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf32_to_utf8_out_ok (cvt); > utf32_to_utf8_out_partial (cvt); > utf32_to_utf8_out_error (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -test_utf8_utf32_codecvts (const std::codecvt<CharT, char, mbstate_t> &cvt) > +test_utf8_utf32_cvt (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf8_to_utf32_in (cvt); > utf32_to_utf8_out (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf16_in_ok (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf16_in_ok (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char in[] = "b?\uAAAA\U0010AAAA"; > - const char16_t exp_literal[] = u"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - copy (begin (exp_literal), end (exp_literal), begin (exp)); > - > - static_assert (array_size (in) == 11, ""); > - static_assert (array_size (exp_literal) == 6, ""); > - static_assert (array_size (exp) == 6, ""); > - VERIFY (char_traits<char>::length (in) == 10); > - VERIFY (char_traits<char16_t>::length (exp_literal) == 5); > - VERIFY (char_traits<CharT>::length (exp) == 5); > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char16_t expected[] = u"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 6, ""); > + > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 5); > > test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {3, 2}, {6, 3}, {10, 5}}; > for (auto t : offsets) > { > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -457,19 +468,19 @@ utf8_to_utf16_in_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<CharT>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > > for (auto t : offsets) > { > - CharT out[array_size (exp)] = {}; > + InternT out[array_size (exp)] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res > @@ -477,29 +488,29 @@ utf8_to_utf16_in_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<CharT>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf16_in_partial (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf16_in_partial (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char in[] = "b?\uAAAA\U0010AAAA"; > - const char16_t exp_literal[] = u"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - copy (begin (exp_literal), end (exp_literal), begin (exp)); > - > - static_assert (array_size (in) == 11, ""); > - static_assert (array_size (exp_literal) == 6, ""); > - static_assert (array_size (exp) == 6, ""); > - VERIFY (char_traits<char>::length (in) == 10); > - VERIFY (char_traits<char16_t>::length (exp_literal) == 5); > - VERIFY (char_traits<CharT>::length (exp) == 5); > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char16_t expected[] = u"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 6, ""); > + > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 5); > > test_offsets_partial offsets[] = { > {1, 0, 0, 0}, // no space for first CP > @@ -530,14 +541,14 @@ utf8_to_utf16_in_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > > for (auto t : offsets) > { > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -545,36 +556,38 @@ utf8_to_utf16_in_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.partial); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<CharT>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf16_in_error (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf16_in_error (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > - const char valid_in[] = "b?\uAAAA\U0010AAAA"; > - const char16_t exp_literal[] = u"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - copy (begin (exp_literal), end (exp_literal), begin (exp)); > + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char16_t expected[] = u"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 6, ""); > > - static_assert (array_size (valid_in) == 11, ""); > - static_assert (array_size (exp_literal) == 6, ""); > - static_assert (array_size (exp) == 6, ""); > - VERIFY (char_traits<char>::length (valid_in) == 10); > - VERIFY (char_traits<char16_t>::length (exp_literal) == 5); > - VERIFY (char_traits<CharT>::length (exp) == 5); > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 5); > > - test_offsets_error<char> offsets[] = { > + test_offsets_error<unsigned char> offsets[] = { > > // replace leading byte with invalid byte > - {1, 5, 0, 0, '\xFF', 0}, > - {3, 5, 1, 1, '\xFF', 1}, > - {6, 5, 3, 2, '\xFF', 3}, > - {10, 5, 6, 3, '\xFF', 6}, > + {1, 5, 0, 0, 0xFF, 0}, > + {3, 5, 1, 1, 0xFF, 1}, > + {6, 5, 3, 2, 0xFF, 3}, > + {10, 5, 6, 3, 0xFF, 6}, > > // replace first trailing byte with ASCII byte > {3, 5, 1, 1, 'z', 2}, > @@ -582,21 +595,21 @@ utf8_to_utf16_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > {10, 5, 6, 3, 'z', 7}, > > // replace first trailing byte with invalid byte > - {3, 5, 1, 1, '\xFF', 2}, > - {6, 5, 3, 2, '\xFF', 4}, > - {10, 5, 6, 3, '\xFF', 7}, > + {3, 5, 1, 1, 0xFF, 2}, > + {6, 5, 3, 2, 0xFF, 4}, > + {10, 5, 6, 3, 0xFF, 7}, > > // replace second trailing byte with ASCII byte > {6, 5, 3, 2, 'z', 5}, > {10, 5, 6, 3, 'z', 8}, > > // replace second trailing byte with invalid byte > - {6, 5, 3, 2, '\xFF', 5}, > - {10, 5, 6, 3, '\xFF', 8}, > + {6, 5, 3, 2, 0xFF, 5}, > + {10, 5, 6, 3, 0xFF, 8}, > > // replace third trailing byte > {10, 5, 6, 3, 'z', 9}, > - {10, 5, 6, 3, '\xFF', 9}, > + {10, 5, 6, 3, 0xFF, 9}, > > // replace first trailing byte with ASCII byte, also incomplete at end > {5, 5, 3, 2, 'z', 4}, > @@ -604,30 +617,29 @@ utf8_to_utf16_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > {9, 5, 6, 3, 'z', 7}, > > // replace first trailing byte with invalid byte, also incomplete at end > - {5, 5, 3, 2, '\xFF', 4}, > - {8, 5, 6, 3, '\xFF', 7}, > - {9, 5, 6, 3, '\xFF', 7}, > + {5, 5, 3, 2, 0xFF, 4}, > + {8, 5, 6, 3, 0xFF, 7}, > + {9, 5, 6, 3, 0xFF, 7}, > > // replace second trailing byte with ASCII byte, also incomplete at end > {9, 5, 6, 3, 'z', 8}, > > // replace second trailing byte with invalid byte, also incomplete at end > - {9, 5, 6, 3, '\xFF', 8}, > + {9, 5, 6, 3, 0xFF, 8}, > }; > for (auto t : offsets) > { > - char in[array_size (valid_in)] = {}; > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > - char_traits<char>::copy (in, valid_in, array_size (valid_in)); > + auto old_char = in[t.replace_pos]; > in[t.replace_pos] = t.replace_char; > > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -635,48 +647,51 @@ utf8_to_utf16_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.error); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<CharT>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > + > + in[t.replace_pos] = old_char; > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_utf16_in (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_utf16_in (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf8_to_utf16_in_ok (cvt); > utf8_to_utf16_in_partial (cvt); > utf8_to_utf16_in_error (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf16_to_utf8_out_ok (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf16_to_utf8_out_ok (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char16_t in_literal[] = u"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - CharT in[array_size (in_literal)]; > - copy (begin (in_literal), end (in_literal), begin (in)); > - > - static_assert (array_size (in_literal) == 6, ""); > - static_assert (array_size (exp) == 11, ""); > - static_assert (array_size (in) == 6, ""); > - VERIFY (char_traits<char16_t>::length (in_literal) == 5); > - VERIFY (char_traits<char>::length (exp) == 10); > - VERIFY (char_traits<CharT>::length (in) == 5); > + const char16_t input[] = u"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 6, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 5); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > > const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}, {5, > 10}}; > for (auto t : offsets) > { > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -684,29 +699,29 @@ utf16_to_utf8_out_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<char>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf16_to_utf8_out_partial (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf16_to_utf8_out_partial (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > - const char16_t in_literal[] = u"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - CharT in[array_size (in_literal)]; > - copy (begin (in_literal), end (in_literal), begin (in)); > - > - static_assert (array_size (in_literal) == 6, ""); > - static_assert (array_size (exp) == 11, ""); > - static_assert (array_size (in) == 6, ""); > - VERIFY (char_traits<char16_t>::length (in_literal) == 5); > - VERIFY (char_traits<char>::length (exp) == 10); > - VERIFY (char_traits<CharT>::length (in) == 5); > + const char16_t input[] = u"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 6, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 5); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > > const test_offsets_partial offsets[] = { > {1, 0, 0, 0}, // no space for first CP > @@ -732,14 +747,14 @@ utf16_to_utf8_out_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > }; > for (auto t : offsets) > { > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -747,26 +762,32 @@ utf16_to_utf8_out_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.partial); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<char>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf16_to_utf8_out_error (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf16_to_utf8_out_error (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > - const char16_t valid_in[] = u"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - > - static_assert (array_size (valid_in) == 6, ""); > - static_assert (array_size (exp) == 11, ""); > - VERIFY (char_traits<char16_t>::length (valid_in) == 5); > - VERIFY (char_traits<char>::length (exp) == 10); > - > - test_offsets_error<CharT> offsets[] = { > + // UTF-8 string of 1-byte CP, 2-byte CP, 3-byte CP and 4-byte CP > + const char16_t input[] = u"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 6, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 5); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > + > + test_offsets_error<InternT> offsets[] = { > {5, 10, 0, 0, 0xD800, 0}, > {5, 10, 0, 0, 0xDBFF, 0}, > {5, 10, 0, 0, 0xDC00, 0}, > @@ -796,18 +817,17 @@ utf16_to_utf8_out_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > > for (auto t : offsets) > { > - CharT in[array_size (valid_in)] = {}; > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > - copy (begin (valid_in), end (valid_in), begin (in)); > + auto old_char = in[t.replace_pos]; > in[t.replace_pos] = t.replace_char; > > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -815,56 +835,59 @@ utf16_to_utf8_out_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.error); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<char>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > + > + in[t.replace_pos] = old_char; > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf16_to_utf8_out (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf16_to_utf8_out (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf16_to_utf8_out_ok (cvt); > utf16_to_utf8_out_partial (cvt); > utf16_to_utf8_out_error (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -test_utf8_utf16_cvts (const std::codecvt<CharT, char, mbstate_t> &cvt) > +test_utf8_utf16_cvt (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf8_to_utf16_in (cvt); > utf16_to_utf8_out (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_ucs2_in_ok (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_ucs2_in_ok (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP > - const char in[] = "b?\uAAAA"; > - const char16_t exp_literal[] = u"b?\uAAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - copy (begin (exp_literal), end (exp_literal), begin (exp)); > - > - static_assert (array_size (in) == 7, ""); > - static_assert (array_size (exp_literal) == 4, ""); > - static_assert (array_size (exp) == 4, ""); > - VERIFY (char_traits<char>::length (in) == 6); > - VERIFY (char_traits<char16_t>::length (exp_literal) == 3); > - VERIFY (char_traits<CharT>::length (exp) == 3); > + const unsigned char input[] = "b?\uAAAA"; > + const char16_t expected[] = u"b?\uAAAA"; > + static_assert (array_size (input) == 7, ""); > + static_assert (array_size (expected) == 4, ""); > + > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 6); > + VERIFY (char_traits<InternT>::length (exp) == 3); > > test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {3, 2}, {6, 3}}; > for (auto t : offsets) > { > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -872,19 +895,19 @@ utf8_to_ucs2_in_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<CharT>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > > for (auto t : offsets) > { > - CharT out[array_size (exp)] = {}; > + InternT out[array_size (exp)] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res > @@ -892,29 +915,29 @@ utf8_to_ucs2_in_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<CharT>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_ucs2_in_partial (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_ucs2_in_partial (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP > - const char in[] = "b?\uAAAA"; > - const char16_t exp_literal[] = u"b?\uAAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - copy (begin (exp_literal), end (exp_literal), begin (exp)); > - > - static_assert (array_size (in) == 7, ""); > - static_assert (array_size (exp_literal) == 4, ""); > - static_assert (array_size (exp) == 4, ""); > - VERIFY (char_traits<char>::length (in) == 6); > - VERIFY (char_traits<char16_t>::length (exp_literal) == 3); > - VERIFY (char_traits<CharT>::length (exp) == 3); > + const unsigned char input[] = "b?\uAAAA"; > + const char16_t expected[] = u"b?\uAAAA"; > + static_assert (array_size (input) == 7, ""); > + static_assert (array_size (expected) == 4, ""); > + > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 6); > + VERIFY (char_traits<InternT>::length (exp) == 3); > > test_offsets_partial offsets[] = { > {1, 0, 0, 0}, // no space for first CP > @@ -932,14 +955,14 @@ utf8_to_ucs2_in_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > > for (auto t : offsets) > { > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -947,36 +970,37 @@ utf8_to_ucs2_in_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.partial); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<CharT>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_ucs2_in_error (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_ucs2_in_error (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > - const char valid_in[] = "b?\uAAAA\U0010AAAA"; > - const char16_t exp_literal[] = u"b?\uAAAA\U0010AAAA"; > - CharT exp[array_size (exp_literal)] = {}; > - copy (begin (exp_literal), end (exp_literal), begin (exp)); > + const unsigned char input[] = "b?\uAAAA\U0010AAAA"; > + const char16_t expected[] = u"b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 11, ""); > + static_assert (array_size (expected) == 6, ""); > > - static_assert (array_size (valid_in) == 11, ""); > - static_assert (array_size (exp_literal) == 6, ""); > - static_assert (array_size (exp) == 6, ""); > - VERIFY (char_traits<char>::length (valid_in) == 10); > - VERIFY (char_traits<char16_t>::length (exp_literal) == 5); > - VERIFY (char_traits<CharT>::length (exp) == 5); > + ExternT in[array_size (input)]; > + InternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<ExternT>::length (in) == 10); > + VERIFY (char_traits<InternT>::length (exp) == 5); > > - test_offsets_error<char> offsets[] = { > + test_offsets_error<unsigned char> offsets[] = { > > // replace leading byte with invalid byte > - {1, 5, 0, 0, '\xFF', 0}, > - {3, 5, 1, 1, '\xFF', 1}, > - {6, 5, 3, 2, '\xFF', 3}, > - {10, 5, 6, 3, '\xFF', 6}, > + {1, 5, 0, 0, 0xFF, 0}, > + {3, 5, 1, 1, 0xFF, 1}, > + {6, 5, 3, 2, 0xFF, 3}, > + {10, 5, 6, 3, 0xFF, 6}, > > // replace first trailing byte with ASCII byte > {3, 5, 1, 1, 'z', 2}, > @@ -984,21 +1008,21 @@ utf8_to_ucs2_in_error (const std::codecvt<CharT, char, > mbstate_t> &cvt) > {10, 5, 6, 3, 'z', 7}, > > // replace first trailing byte with invalid byte > - {3, 5, 1, 1, '\xFF', 2}, > - {6, 5, 3, 2, '\xFF', 4}, > - {10, 5, 6, 3, '\xFF', 7}, > + {3, 5, 1, 1, 0xFF, 2}, > + {6, 5, 3, 2, 0xFF, 4}, > + {10, 5, 6, 3, 0xFF, 7}, > > // replace second trailing byte with ASCII byte > {6, 5, 3, 2, 'z', 5}, > {10, 5, 6, 3, 'z', 8}, > > // replace second trailing byte with invalid byte > - {6, 5, 3, 2, '\xFF', 5}, > - {10, 5, 6, 3, '\xFF', 8}, > + {6, 5, 3, 2, 0xFF, 5}, > + {10, 5, 6, 3, 0xFF, 8}, > > // replace third trailing byte > {10, 5, 6, 3, 'z', 9}, > - {10, 5, 6, 3, '\xFF', 9}, > + {10, 5, 6, 3, 0xFF, 9}, > > // When we see a leading byte of 4-byte CP, we should return error, no > // matter if it is incomplete at the end or has errors in the trailing > @@ -1020,36 +1044,35 @@ utf8_to_ucs2_in_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > {5, 5, 3, 2, 'z', 4}, > > // replace first trailing byte with invalid byte, also incomplete at end > - {5, 5, 3, 2, '\xFF', 4}, > + {5, 5, 3, 2, 0xFF, 4}, > > // replace first trailing byte with ASCII byte, also incomplete at end > {8, 5, 6, 3, 'z', 7}, > {9, 5, 6, 3, 'z', 7}, > > // replace first trailing byte with invalid byte, also incomplete at end > - {8, 5, 6, 3, '\xFF', 7}, > - {9, 5, 6, 3, '\xFF', 7}, > + {8, 5, 6, 3, 0xFF, 7}, > + {9, 5, 6, 3, 0xFF, 7}, > > // replace second trailing byte with ASCII byte, also incomplete at end > {9, 5, 6, 3, 'z', 8}, > > // replace second trailing byte with invalid byte, also incomplete at end > - {9, 5, 6, 3, '\xFF', 8}, > + {9, 5, 6, 3, 0xFF, 8}, > }; > for (auto t : offsets) > { > - char in[array_size (valid_in)] = {}; > - CharT out[array_size (exp) - 1] = {}; > + InternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > - char_traits<char>::copy (in, valid_in, array_size (valid_in)); > + auto old_char = in[t.replace_pos]; > in[t.replace_pos] = t.replace_char; > > auto state = mbstate_t{}; > - auto in_next = (const char *) nullptr; > - auto out_next = (CharT *) nullptr; > + auto in_next = (const ExternT *) nullptr; > + auto out_next = (InternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.in (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -1057,48 +1080,51 @@ utf8_to_ucs2_in_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.error); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<CharT>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<InternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > + > + in[t.replace_pos] = old_char; > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -utf8_to_ucs2_in (const std::codecvt<CharT, char, mbstate_t> &cvt) > +utf8_to_ucs2_in (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf8_to_ucs2_in_ok (cvt); > utf8_to_ucs2_in_partial (cvt); > utf8_to_ucs2_in_error (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -ucs2_to_utf8_out_ok (const std::codecvt<CharT, char, mbstate_t> &cvt) > +ucs2_to_utf8_out_ok (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP > - const char16_t in_literal[] = u"b?\uAAAA"; > - const char exp[] = "b?\uAAAA"; > - CharT in[array_size (in_literal)] = {}; > - copy (begin (in_literal), end (in_literal), begin (in)); > - > - static_assert (array_size (in_literal) == 4, ""); > - static_assert (array_size (exp) == 7, ""); > - static_assert (array_size (in) == 4, ""); > - VERIFY (char_traits<char16_t>::length (in_literal) == 3); > - VERIFY (char_traits<char>::length (exp) == 6); > - VERIFY (char_traits<CharT>::length (in) == 3); > + const char16_t input[] = u"b?\uAAAA"; > + const unsigned char expected[] = "b?\uAAAA"; > + static_assert (array_size (input) == 4, ""); > + static_assert (array_size (expected) == 7, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 3); > + VERIFY (char_traits<ExternT>::length (exp) == 6); > > const test_offsets_ok offsets[] = {{0, 0}, {1, 1}, {2, 3}, {3, 6}}; > for (auto t : offsets) > { > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -1106,29 +1132,29 @@ ucs2_to_utf8_out_ok (const std::codecvt<CharT, char, > mbstate_t> &cvt) > VERIFY (res == cvt.ok); > VERIFY (in_next == in + t.in_size); > VERIFY (out_next == out + t.out_size); > - VERIFY (char_traits<char>::compare (out, exp, t.out_size) == 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.out_size) == 0); > if (t.out_size < array_size (out)) > VERIFY (out[t.out_size] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -ucs2_to_utf8_out_partial (const std::codecvt<CharT, char, mbstate_t> &cvt) > +ucs2_to_utf8_out_partial (const std::codecvt<InternT, ExternT, mbstate_t> > &cvt) > { > using namespace std; > // UTF-8 string of 1-byte CP, 2-byte CP and 3-byte CP > - const char16_t in_literal[] = u"b?\uAAAA"; > - const char exp[] = "b?\uAAAA"; > - CharT in[array_size (in_literal)] = {}; > - copy (begin (in_literal), end (in_literal), begin (in)); > - > - static_assert (array_size (in_literal) == 4, ""); > - static_assert (array_size (exp) == 7, ""); > - static_assert (array_size (in) == 4, ""); > - VERIFY (char_traits<char16_t>::length (in_literal) == 3); > - VERIFY (char_traits<char>::length (exp) == 6); > - VERIFY (char_traits<CharT>::length (in) == 3); > + const char16_t input[] = u"b?\uAAAA"; > + const unsigned char expected[] = "b?\uAAAA"; > + static_assert (array_size (input) == 4, ""); > + static_assert (array_size (expected) == 7, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 3); > + VERIFY (char_traits<ExternT>::length (exp) == 6); > > const test_offsets_partial offsets[] = { > {1, 0, 0, 0}, // no space for first CP > @@ -1142,14 +1168,14 @@ ucs2_to_utf8_out_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > }; > for (auto t : offsets) > { > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -1157,26 +1183,31 @@ ucs2_to_utf8_out_partial (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.partial); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<char>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -ucs2_to_utf8_out_error (const std::codecvt<CharT, char, mbstate_t> &cvt) > +ucs2_to_utf8_out_error (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > using namespace std; > - const char16_t valid_in[] = u"b?\uAAAA\U0010AAAA"; > - const char exp[] = "b?\uAAAA\U0010AAAA"; > - > - static_assert (array_size (valid_in) == 6, ""); > - static_assert (array_size (exp) == 11, ""); > - VERIFY (char_traits<char16_t>::length (valid_in) == 5); > - VERIFY (char_traits<char>::length (exp) == 10); > - > - test_offsets_error<CharT> offsets[] = { > + const char16_t input[] = u"b?\uAAAA\U0010AAAA"; > + const unsigned char expected[] = "b?\uAAAA\U0010AAAA"; > + static_assert (array_size (input) == 6, ""); > + static_assert (array_size (expected) == 11, ""); > + > + InternT in[array_size (input)]; > + ExternT exp[array_size (expected)]; > + copy (begin (input), end (input), begin (in)); > + copy (begin (expected), end (expected), begin (exp)); > + VERIFY (char_traits<InternT>::length (in) == 5); > + VERIFY (char_traits<ExternT>::length (exp) == 10); > + > + test_offsets_error<InternT> offsets[] = { > {5, 10, 0, 0, 0xD800, 0}, > {5, 10, 0, 0, 0xDBFF, 0}, > {5, 10, 0, 0, 0xDC00, 0}, > @@ -1219,18 +1250,17 @@ ucs2_to_utf8_out_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > > for (auto t : offsets) > { > - CharT in[array_size (valid_in)] = {}; > - char out[array_size (exp) - 1] = {}; > + ExternT out[array_size (exp) - 1] = {}; > VERIFY (t.in_size <= array_size (in)); > VERIFY (t.out_size <= array_size (out)); > VERIFY (t.expected_in_next <= t.in_size); > VERIFY (t.expected_out_next <= t.out_size); > - copy (begin (valid_in), end (valid_in), begin (in)); > + auto old_char = in[t.replace_pos]; > in[t.replace_pos] = t.replace_char; > > auto state = mbstate_t{}; > - auto in_next = (const CharT *) nullptr; > - auto out_next = (char *) nullptr; > + auto in_next = (const InternT *) nullptr; > + auto out_next = (ExternT *) nullptr; > auto res = codecvt_base::result (); > > res = cvt.out (state, in, in + t.in_size, in_next, out, out + > t.out_size, > @@ -1238,24 +1268,27 @@ ucs2_to_utf8_out_error (const std::codecvt<CharT, > char, mbstate_t> &cvt) > VERIFY (res == cvt.error); > VERIFY (in_next == in + t.expected_in_next); > VERIFY (out_next == out + t.expected_out_next); > - VERIFY (char_traits<char>::compare (out, exp, t.expected_out_next) == > 0); > + VERIFY (char_traits<ExternT>::compare (out, exp, t.expected_out_next) > + == 0); > if (t.expected_out_next < array_size (out)) > VERIFY (out[t.expected_out_next] == 0); > + > + in[t.replace_pos] = old_char; > } > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -ucs2_to_utf8_out (const std::codecvt<CharT, char, mbstate_t> &cvt) > +ucs2_to_utf8_out (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > ucs2_to_utf8_out_ok (cvt); > ucs2_to_utf8_out_partial (cvt); > ucs2_to_utf8_out_error (cvt); > } > > -template <class CharT> > +template <class InternT, class ExternT> > void > -test_utf8_ucs2_cvts (const std::codecvt<CharT, char, mbstate_t> &cvt) > +test_utf8_ucs2_cvt (const std::codecvt<InternT, ExternT, mbstate_t> &cvt) > { > utf8_to_ucs2_in (cvt); > ucs2_to_utf8_out (cvt); > diff --git > a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc > b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc > new file mode 100644 > index 000000000..8ab5ba79f > --- /dev/null > +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_char8_t.cc > @@ -0,0 +1,53 @@ > +// Copyright (C) 2020-2023 Free Software Foundation, Inc. > +// > +// This file is part of the GNU ISO C++ Library. This library is free > +// software; you can redistribute it and/or modify it under the > +// terms of the GNU General Public License as published by the > +// Free Software Foundation; either version 3, or (at your option) > +// any later version. > + > +// This library is distributed in the hope that it will be useful, > +// but WITHOUT ANY WARRANTY; without even the implied warranty of > +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the > +// GNU General Public License for more details. > + > +// You should have received a copy of the GNU General Public License along > +// with this library; see the file COPYING3. If not see > +// <http://www.gnu.org/licenses/>. > + > +// { dg-do run { target c++11 } } > +// { dg-require-cstdint "" } > +// { dg-options "-fchar8_t" } > + > +#include "codecvt_unicode.h" > + > +using namespace std; > + > +void > +test_utf8_utf32_codecvts () > +{ > + using codecvt_c32_c8 = codecvt<char32_t, char8_t, mbstate_t>; > + auto &loc_c = locale::classic (); > + VERIFY (has_facet<codecvt_c32_c8> (loc_c)); > + > + auto &cvt = use_facet<codecvt_c32_c8> (loc_c); > + test_utf8_utf32_cvt (cvt); > +} > + > +void > +test_utf8_utf16_codecvts () > +{ > + using codecvt_c16_c8 = codecvt<char16_t, char8_t, mbstate_t>; > + auto &loc_c = locale::classic (); > + VERIFY (has_facet<codecvt_c16_c8> (loc_c)); > + > + auto &cvt = use_facet<codecvt_c16_c8> (loc_c); > + test_utf8_utf16_cvt (cvt); > +} > + > +int > +main () > +{ > + test_utf8_utf32_codecvts (); > + test_utf8_utf16_codecvts (); > +} > diff --git > a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc > b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc > index 4fd1bfec6..6e9152b50 100644 > --- a/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc > +++ b/libstdc++-v3/testsuite/22_locale/codecvt/codecvt_unicode_wchar_t.cc > @@ -28,7 +28,7 @@ test_utf8_utf32_codecvts () > { > #if __SIZEOF_WCHAR_T__ == 4 > codecvt_utf8<wchar_t> cvt; > - test_utf8_utf32_codecvts (cvt); > + test_utf8_utf32_cvt (cvt); > #endif > } > > @@ -37,7 +37,7 @@ test_utf8_utf16_codecvts () > { > #if __SIZEOF_WCHAR_T__ >= 2 > codecvt_utf8_utf16<wchar_t> cvt; > - test_utf8_utf16_cvts (cvt); > + test_utf8_utf16_cvt (cvt); > #endif > } > > @@ -46,7 +46,7 @@ test_utf8_ucs2_codecvts () > { > #if __SIZEOF_WCHAR_T__ == 2 > codecvt_utf8<wchar_t> cvt; > - test_utf8_ucs2_cvts (cvt); > + test_utf8_ucs2_cvt (cvt); > #endif > } > > -- > 2.34.1 >