diff --git a/include/fmt/core.h b/include/fmt/core.h index 25647037..4734aba2 100644 --- a/include/fmt/core.h +++ b/include/fmt/core.h @@ -315,6 +315,12 @@ FMT_CONSTEXPR typename std::make_unsigned::type to_unsigned(Int value) { FMT_ASSERT(value >= 0, "negative value"); return static_cast::type>(value); } + +#ifdef __cpp_char8_t +using char8_type = char8_t; +#else +enum char8_type : unsigned char {}; +#endif } // namespace internal template @@ -415,15 +421,15 @@ using string_view = basic_string_view; using wstring_view = basic_string_view; #ifndef __cpp_char8_t -// A UTF-8 code unit type. -enum char8_t : unsigned char {}; +// char8_t is deprecated; use char instead. +using char8_t FMT_DEPRECATED_ALIAS = internal::char8_type; #endif /** Specifies if ``T`` is a character type. Can be specialized by users. */ template struct is_char : std::false_type {}; template <> struct is_char : std::true_type {}; template <> struct is_char : std::true_type {}; -template <> struct is_char : std::true_type {}; +template <> struct is_char : std::true_type {}; template <> struct is_char : std::true_type {}; template <> struct is_char : std::true_type {}; diff --git a/include/fmt/format.h b/include/fmt/format.h index 07d4f5f8..ee7f0f93 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -482,7 +482,7 @@ inline size_t count_code_points(basic_string_view s) { return num_code_points; } -inline size_t count_code_points(basic_string_view s) { +inline size_t count_code_points(basic_string_view s) { return count_code_points(basic_string_view( reinterpret_cast(s.data()), s.size())); } @@ -494,8 +494,8 @@ inline size_t code_point_index(basic_string_view s, size_t n) { } // Calculates the index of the nth code point in a UTF-8 string. -inline size_t code_point_index(basic_string_view s, size_t n) { - const char8_t* data = s.data(); +inline size_t code_point_index(basic_string_view s, size_t n) { + const char8_type* data = s.data(); size_t num_code_points = 0; for (size_t i = 0, size = s.size(); i != size; ++i) { if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) { @@ -505,13 +505,13 @@ inline size_t code_point_index(basic_string_view s, size_t n) { return s.size(); } -inline char8_t to_char8_t(char c) { return static_cast(c); } +inline char8_type to_char8_t(char c) { return static_cast(c); } template using needs_conversion = bool_constant< std::is_same::value_type, char>::value && - std::is_same::value>; + std::is_same::value>; template ::value)> @@ -555,20 +555,22 @@ class buffer_range : public internal::output_range< : internal::output_range(std::back_inserter(buf)) {} }; -class FMT_DEPRECATED u8string_view : public basic_string_view { +class FMT_DEPRECATED u8string_view + : public basic_string_view { public: u8string_view(const char* s) - : basic_string_view(reinterpret_cast(s)) {} + : basic_string_view( + reinterpret_cast(s)) {} u8string_view(const char* s, size_t count) FMT_NOEXCEPT - : basic_string_view(reinterpret_cast(s), count) { - } + : basic_string_view( + reinterpret_cast(s), count) {} }; #if FMT_USE_USER_DEFINED_LITERALS inline namespace literals { -FMT_DEPRECATED inline basic_string_view operator"" _u(const char* s, - std::size_t n) { - return {reinterpret_cast(s), n}; +FMT_DEPRECATED inline basic_string_view operator"" _u( + const char* s, std::size_t n) { + return {reinterpret_cast(s), n}; } } // namespace literals #endif diff --git a/test/format-impl-test.cc b/test/format-impl-test.cc index 34814967..21e91014 100644 --- a/test/format-impl-test.cc +++ b/test/format-impl-test.cc @@ -10,12 +10,11 @@ #include "test-assert.h" // Include format.cc instead of format.h to test implementation. -#include "../src/format.cc" -#include "fmt/printf.h" - #include #include +#include "../src/format.cc" +#include "fmt/printf.h" #include "gmock.h" #include "gtest-extra.h" #include "util.h" @@ -430,8 +429,10 @@ TEST(FormatTest, CountCodePoints) { #ifndef __cpp_char8_t using fmt::char8_t; #endif - EXPECT_EQ(4, fmt::internal::count_code_points( - fmt::basic_string_view(reinterpret_cast("ёжик")))); + EXPECT_EQ( + 4, fmt::internal::count_code_points( + fmt::basic_string_view( + reinterpret_cast("ёжик")))); } // Tests fmt::internal::count_digits for integer type Int. diff --git a/test/format-test.cc b/test/format-test.cc index 92ad5369..af72acaf 100644 --- a/test/format-test.cc +++ b/test/format-test.cc @@ -2504,25 +2504,6 @@ TEST(FormatTest, FmtStringInTemplate) { #endif // FMT_USE_CONSTEXPR -// C++20 feature test, since r346892 Clang considers char8_t a fundamental -// type in this mode. If this is the case __cpp_char8_t will be defined. -#ifndef __cpp_char8_t -// Locally provide type char8_t defined in format.h -using fmt::char8_t; -#endif - -// Convert 'char8_t' character sequences to 'char' sequences -// Otherwise GTest will insist on inserting 'char8_t' NTBS into a 'char' stream, -// but basic_ostream::operator<< overloads taking 'char8_t' arguments -// are defined as deleted by P1423. -// Handling individual 'char8_t's is done inline. -std::string from_u8str(const std::basic_string& str) { - return std::string(str.begin(), str.end()); -} -std::string from_u8str(const fmt::basic_string_view& str) { - return std::string(str.begin(), str.end()); -} - TEST(FormatTest, EmphasisNonHeaderOnly) { // Ensure this compiles even if FMT_HEADER_ONLY is not defined. EXPECT_EQ(fmt::format(fmt::emphasis::bold, "bold error"), @@ -2561,10 +2542,18 @@ TEST(FormatTest, FormatCustomChar) { EXPECT_EQ(result[0], mychar('x')); } +// Convert a char8_t string to std::string. Otherwise GTest will insist on +// inserting `char8_t` NTBS into a `char` stream which is disabled by P1423. +template std::string from_u8str(const S& str) { + return std::string(str.begin(), str.end()); +} + TEST(FormatTest, FormatUTF8Precision) { - using str_type = std::basic_string; - str_type format(reinterpret_cast(u8"{:.4}")); - str_type str(reinterpret_cast(u8"caf\u00e9s")); // cafés + using str_type = std::basic_string; + str_type format( + reinterpret_cast(u8"{:.4}")); + str_type str(reinterpret_cast( + u8"caf\u00e9s")); // cafés auto result = fmt::format(format, str); EXPECT_EQ(fmt::internal::count_code_points(result), 4); EXPECT_EQ(result.size(), 5);