diff --git a/libcxx/include/__format/unicode.h b/libcxx/include/__format/unicode.h --- a/libcxx/include/__format/unicode.h +++ b/libcxx/include/__format/unicode.h @@ -87,17 +87,15 @@ } // https://www.unicode.org/glossary/#surrogate_code_point -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_surrogate(char32_t __value) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_surrogate(char32_t __value) { return __value >= 0xd800 && __value <= 0xdfff; } // https://www.unicode.org/glossary/#code_point -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_code_point(char32_t __value) { - return __value <= 0x10ffff; -} +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_code_point(char32_t __value) { return __value <= 0x10ffff; } // https://www.unicode.org/glossary/#unicode_scalar_value -[[nodiscard]] _LIBCPP_HIDE_FROM_ABI inline constexpr bool __is_scalar_value(char32_t __value) { +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool __is_scalar_value(char32_t __value) { return __unicode::__is_code_point(__value) && !__unicode::__is_surrogate(__value); } diff --git a/libcxx/test/std/time/time.hms/time.hms.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.hms/time.hms.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.hms/time.hms.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.hms/time.hms.nonmembers/ostream.pass.cpp @@ -13,9 +13,6 @@ // TODO FMT Evaluate gcc-12 status // UNSUPPORTED: gcc-12 -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // XFAIL: availability-fp_to_chars-missing // REQUIRES: locale.fr_FR.UTF-8 diff --git a/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.day/time.cal.day.nonmembers/ostream.pass.cpp @@ -10,8 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED msvc, target={{.+}}-windows-gnu // TODO FMT Evaluate gcc-12 status // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.md/time.cal.md.nonmembers/ostream.pass.cpp @@ -10,9 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.mdlast/ostream.pass.cpp @@ -12,9 +12,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.month/time.cal.month.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.month/time.cal.month.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.month/time.cal.month.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.month/time.cal.month.nonmembers/ostream.pass.cpp @@ -12,9 +12,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.mwd/time.cal.mwd.nonmembers/ostream.pass.cpp @@ -12,9 +12,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.mwdlast/time.cal.mwdlast.nonmembers/ostream.pass.cpp @@ -12,9 +12,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.year/time.cal.year.nonmembers/ostream.pass.cpp @@ -10,9 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ym/time.cal.ym.nonmembers/ostream.pass.cpp @@ -12,9 +12,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymd/time.cal.ymd.nonmembers/ostream.pass.cpp @@ -10,9 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymdlast/time.cal.ymdlast.nonmembers/ostream.pass.cpp @@ -12,9 +12,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwd/time.cal.ymwd.nonmembers/ostream.pass.cpp @@ -10,9 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp --- a/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp +++ b/libcxx/test/std/time/time.cal/time.cal.ymwdlast/time.cal.ymwdlast.nonmembers/ostream.pass.cpp @@ -10,9 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.clock/time.clock.file/ostream.pass.cpp b/libcxx/test/std/time/time.clock/time.clock.file/ostream.pass.cpp --- a/libcxx/test/std/time/time.clock/time.clock.file/ostream.pass.cpp +++ b/libcxx/test/std/time/time.clock/time.clock.file/ostream.pass.cpp @@ -10,8 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED msvc, target={{.+}}-windows-gnu // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.clock/time.clock.local/ostream.pass.cpp b/libcxx/test/std/time/time.clock/time.clock.local/ostream.pass.cpp --- a/libcxx/test/std/time/time.clock/time.clock.local/ostream.pass.cpp +++ b/libcxx/test/std/time/time.clock/time.clock.local/ostream.pass.cpp @@ -10,8 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED msvc, target={{.+}}-windows-gnu // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.clock/time.clock.system/ostream.pass.cpp b/libcxx/test/std/time/time.clock/time.clock.system/ostream.pass.cpp --- a/libcxx/test/std/time/time.clock/time.clock.system/ostream.pass.cpp +++ b/libcxx/test/std/time/time.clock/time.clock.system/ostream.pass.cpp @@ -10,8 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED msvc, target={{.+}}-windows-gnu // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.duration/time.duration.nonmember/ostream.pass.cpp b/libcxx/test/std/time/time.duration/time.duration.nonmember/ostream.pass.cpp --- a/libcxx/test/std/time/time.duration/time.duration.nonmember/ostream.pass.cpp +++ b/libcxx/test/std/time/time.duration/time.duration.nonmember/ostream.pass.cpp @@ -10,8 +10,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu // TODO FMT Evaluate gcc-12 status // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.hh_mm_ss.pass.cpp b/libcxx/test/std/time/time.syn/formatter.hh_mm_ss.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.hh_mm_ss.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.hh_mm_ss.pass.cpp @@ -12,9 +12,6 @@ // TODO FMT Evaluate gcc-12 status // UNSUPPORTED: gcc-12 -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // XFAIL: LIBCXX-FREEBSD-FIXME // XFAIL: availability-fp_to_chars-missing diff --git a/libcxx/test/std/time/time.syn/formatter.day.pass.cpp b/libcxx/test/std/time/time.syn/formatter.day.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.day.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.day.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp b/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.duration.pass.cpp @@ -11,8 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu // TODO FMT Evaluate gcc-12 status // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp b/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.file_time.pass.cpp @@ -14,8 +14,6 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp b/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.local_time.pass.cpp @@ -14,8 +14,6 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp b/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.month_day.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp b/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.sys_time.pass.cpp @@ -14,8 +14,6 @@ // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.weekday.pass.cpp b/libcxx/test/std/time/time.syn/formatter.weekday.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.weekday.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.weekday.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp b/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.weekday_index.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp b/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.weekday_last.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.year.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.year.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.year.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT Fix this test using GCC, it currently crashes. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp b/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp --- a/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp +++ b/libcxx/test/std/time/time.syn/formatter.year_month_day.pass.cpp @@ -11,9 +11,6 @@ // UNSUPPORTED: no-localization // UNSUPPORTED: libcpp-has-no-incomplete-format -// TODO FMT Investigate Windows issues. -// UNSUPPORTED: msvc, target={{.+}}-windows-gnu - // TODO FMT It seems GCC uses too much memory in the CI and fails. // UNSUPPORTED: gcc-12 diff --git a/libcxx/test/std/utilities/format/format.functions/unicode.pass.cpp b/libcxx/test/std/utilities/format/format.functions/unicode.pass.cpp --- a/libcxx/test/std/utilities/format/format.functions/unicode.pass.cpp +++ b/libcxx/test/std/utilities/format/format.functions/unicode.pass.cpp @@ -11,9 +11,6 @@ // This version runs the test when the platform has Unicode support. // UNSUPPORTED: libcpp-has-no-unicode -// TODO FMT Investigate Windows issues. -// UNSUPPORTED msvc, target={{.+}}-windows-gnu - // TODO FMT This test should not require std::to_chars(floating-point) // XFAIL: availability-fp_to_chars-missing diff --git a/libcxx/test/support/concat_macros.h b/libcxx/test/support/concat_macros.h --- a/libcxx/test/support/concat_macros.h +++ b/libcxx/test/support/concat_macros.h @@ -19,12 +19,118 @@ # include #endif +#ifdef TEST_HAS_NO_WIDE_CHARACTERS +# include +#endif #if TEST_STD_VER > 17 # ifndef TEST_HAS_NO_LOCALIZATION + +template +concept test_streamable = requires(std::basic_stringstream& stream, T value) { stream << value; }; + +template +concept test_char_streamable = test_streamable; + +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + template -concept test_char_streamable = requires(T&& value) { std::stringstream{} << std::forward(value); }; -# endif +concept test_wide_char_streamable = test_streamable; + +[[nodiscard]] constexpr bool test_is_high_surrogate(char32_t value) { return value >= 0xd800 && value <= 0xdbff; } + +[[nodiscard]] constexpr bool test_is_low_surrogate(char32_t value) { return value >= 0xdc00 && value <= 0xdfff; } + +[[nodiscard]] constexpr bool test_is_surrogate(char32_t value) { return value >= 0xd800 && value <= 0xdfff; } + +[[nodiscard]] _LIBCPP_HIDE_FROM_ABI constexpr bool test_is_code_point(char32_t value) { return value <= 0x10ffff; } + +[[nodiscard]] constexpr bool test_is_scalar_value(char32_t value) { + return test_is_code_point(value) && !test_is_surrogate(value); +} + +inline constexpr char32_t test_replacement_character = U'\ufffd'; + +template +OutIt test_transcode() = delete; + +template + requires std::output_iterator +void test_encode(OutIt& out_it, char16_t value) { + if (value < 0x80) + *out_it++ = value; + else if (value < 0x800) { + *out_it++ = 0b1100'0000 | (value >> 6); + *out_it++ = 0b1000'0000 | (value & 0b0011'1111); + } else { + *out_it++ = 0b1110'0000 | (value >> 12); + *out_it++ = 0b1000'0000 | ((value) >> 6 & 0b0011'1111); + *out_it++ = 0b1000'0000 | (value & 0b0011'1111); + } +} + +template + requires std::output_iterator +void test_encode(OutIt& out_it, char32_t value) { + if ((value & 0xffff0000) == 0) + test_encode(out_it, static_cast(value)); + else { + *out_it++ = 0b1110'0000 | (value >> 18); + *out_it++ = 0b1000'0000 | ((value) >> 12 & 0b0011'1111); + *out_it++ = 0b1000'0000 | ((value) >> 6 & 0b0011'1111); + *out_it++ = 0b1000'0000 | (value & 0b0011'1111); + } +} + +template + requires(std::output_iterator && std::same_as, wchar_t> && + sizeof(wchar_t) == 2) +OutIt test_transcode(InIt first, InIt last, OutIt out_it) { + while (first != last) { + char32_t value = *first++; + + if (test_is_low_surrogate(value)) [[unlikely]] { + test_encode(out_it, static_cast(test_replacement_character)); + continue; + } + + if (!test_is_high_surrogate(value)) { + test_encode(out_it, static_cast(value)); + continue; + } + + if (first == last || !test_is_low_surrogate(static_cast(*first))) [[unlikely]] { + test_encode(out_it, static_cast(test_replacement_character)); + continue; + } + + value -= 0xd800; + value <<= 10; + value += static_cast(*first++) - 0xdc00; + value += 0x10000; + + if (test_is_code_point(value)) [[likely]] + test_encode(out_it, value); + else + test_encode(out_it, static_cast(test_replacement_character)); + } +} + +template + requires(std::output_iterator && std::same_as, wchar_t> && + sizeof(wchar_t) == 4) +OutIt test_transcode(InIt first, InIt last, OutIt out_it) { + while (first != last) { + char32_t value = *first++; + if (test_is_code_point(value)) [[likely]] + test_encode(out_it, value); + else + test_encode(out_it, static_cast(test_replacement_character)); + } + return out_it; +} +# endif // TEST_HAS_NO_WIDE_CHARACTERS +# endif // TEST_HAS_NO_LOCALIZATION // If possible concatenates message for the assertion function, else returns a // default message. Not being able to stream is not considered and error. For @@ -40,9 +146,21 @@ if constexpr ((test_char_streamable && ...)) { std::stringstream sstr; ((sstr << std::forward(args)), ...); + // asm("int3"); return sstr.str(); } else -# endif +# ifndef TEST_HAS_NO_WIDE_CHARACTERS + if constexpr ((test_wide_char_streamable && ...)) { + std::wstringstream wsstr; + ((wsstr << std::forward(args)), ...); + std::wstring wstr = wsstr.str(); // TODO FMT Use view + + std::string str; + test_transcode(wstr.begin(), wstr.end(), std::back_inserter(str)); + return str; + } else +# endif // TEST_HAS_NO_WIDE_CHARACTERS +# endif // TEST_HAS_NO_LOCALIZATION return "Message discarded since it can't be streamed to std::cerr.\n"; } @@ -50,5 +168,4 @@ # define TEST_WRITE_CONCATENATED(...) [&] { ::test_eprintf("%s", ::test_concat_message(__VA_ARGS__).c_str()); } #endif // TEST_STD_VER > 17 - #endif // TEST_SUPPORT_CONCAT_MACROS_H