From 5d20c9325ba0e9c732e041ccbab3b0929c30f22a Mon Sep 17 00:00:00 2001 From: Jim Porter Date: Mon, 22 Jul 2024 18:43:21 -0700 Subject: [PATCH] Add support for `char8_t` --- CHANGES.md | 1 + doc/about/changes.md | 1 + include/mettle/output/string.hpp | 8 ++++++++ include/mettle/output/to_printable.hpp | 6 ++++++ include/mettle/output/traits.hpp | 3 +++ test/output/test_string_output.cpp | 12 ++++++++++-- test/output/test_to_printable.cpp | 26 ++++++++++++++++++++++++++ 7 files changed, 55 insertions(+), 2 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index a8fe374..48c285b 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -9,6 +9,7 @@ matchers which need access to non-const objects (e.g. to call a non-const member function) - New matchers `in_interval` and `exception_what` +- Add support for `char8_t` ### Bug fixes - Test failures across multiple runs are now correctly grouped in the summary diff --git a/doc/about/changes.md b/doc/about/changes.md index cdb3df3..c2f295b 100644 --- a/doc/about/changes.md +++ b/doc/about/changes.md @@ -11,6 +11,7 @@ in progress matchers which need access to non-const objects (e.g. to call a non-const member function) - New matchers `in_interval` and `exception_what` +- Add support for `char8_t` ### Bug fixes - Test failures across multiple runs are now correctly grouped in the summary diff --git a/include/mettle/output/string.hpp b/include/mettle/output/string.hpp index 8ce3e73..aedf909 100644 --- a/include/mettle/output/string.hpp +++ b/include/mettle/output/string.hpp @@ -50,6 +50,14 @@ namespace mettle { return s; } +#if __cpp_char8_t + inline std::string_view + convert_string(const std::u8string_view &s) { + return std::string_view(reinterpret_cast(s.begin()), + reinterpret_cast(s.end())); + } +#endif + // Ignore warnings about deprecated . #if defined(_MSC_VER) && !defined(__clang__) # pragma warning(push) diff --git a/include/mettle/output/to_printable.hpp b/include/mettle/output/to_printable.hpp index a91cdb1..bdac668 100644 --- a/include/mettle/output/to_printable.hpp +++ b/include/mettle/output/to_printable.hpp @@ -49,6 +49,12 @@ namespace mettle { return represent_string(std::wstring(1, c), '\''); } +#if __cpp_char8_t + inline std::string to_printable(char8_t c) { + return represent_string(std::u8string(1, c), '\''); + } +#endif + inline std::string to_printable(char16_t c) { return represent_string(std::u16string(1, c), '\''); } diff --git a/include/mettle/output/traits.hpp b/include/mettle/output/traits.hpp index 439e961..dd2f106 100644 --- a/include/mettle/output/traits.hpp +++ b/include/mettle/output/traits.hpp @@ -14,6 +14,9 @@ namespace mettle { template<> struct is_any_char : std::true_type {}; template<> struct is_any_char : std::true_type {}; +#if __cpp_char8_t + template<> struct is_any_char : std::true_type {}; +#endif template<> struct is_any_char : std::true_type {}; template<> struct is_any_char : std::true_type {}; diff --git a/test/output/test_string_output.cpp b/test/output/test_string_output.cpp index a532897..ac1b59d 100644 --- a/test/output/test_string_output.cpp +++ b/test/output/test_string_output.cpp @@ -44,7 +44,11 @@ suite<> test_string_output("string output", [](auto &_) { }); subsuite< - char, wchar_t, char16_t, char32_t + char, +#if __cpp_char8_t + char8_t, +#endif + wchar_t, char16_t, char32_t >(_, "convert_string()", type_only, [](auto &_) { using C = fixture_type_t; auto T = &make_string; @@ -69,7 +73,11 @@ suite<> test_string_output("string output", [](auto &_) { }); subsuite< - char, wchar_t, char16_t, char32_t + char, +#if __cpp_char8_t + char8_t, +#endif + wchar_t, char16_t, char32_t >(_, "represent_string()", type_only, [](auto &_) { using C = fixture_type_t; auto T = &make_string; diff --git a/test/output/test_to_printable.cpp b/test/output/test_to_printable.cpp index eec57f7..06fe999 100644 --- a/test/output/test_to_printable.cpp +++ b/test/output/test_to_printable.cpp @@ -291,6 +291,32 @@ suite<> test_to_printable("to_printable()", [](auto &_) { expect(ns, stringified("nullptr")); }); +#if __cpp_char8_t + _.test("char8_t", []() { + expect(u8'x', stringified("'x'")); + expect(u8'\n', stringified("'\\n'")); + expect(u8'\0', stringified("'\\0'")); + expect(u8'\x1f', stringified("'\\x1f'")); + + expect(u8"text", stringified("\"text\"")); + expect(u8"text\nmore", stringified("\"text\\nmore\"")); + expect(std::u8string(u8"text"), stringified("\"text\"")); + expect(std::u8string_view(u8"text"), stringified("\"text\"")); + expect(std::u8string{u8'a', u8'\0', u8'b'}, stringified("\"a\\0b\"")); + + char8_t s[] = u8"text"; + expect(s, stringified("\"text\"")); + expect(static_cast(s), stringified("\"text\"")); + + const char8_t cs[] = u8"text"; + expect(cs, stringified("\"text\"")); + expect(static_cast(cs), stringified("\"text\"")); + + char8_t *ns = nullptr; + expect(ns, stringified("nullptr")); + }); +#endif + _.test("char16_t", []() { expect(u'x', stringified("'x'")); expect(u'\n', stringified("'\\n'"));