diff --git a/include/fmt/base.h b/include/fmt/base.h index aef46612..1f00f5ec 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -420,20 +420,17 @@ struct is_std_string_like().find_first_of( typename T::value_type(), 0))>> : std::true_type {}; -FMT_CONSTEXPR inline auto is_utf8_enabled() -> bool { - FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char section[] = "\u00A7"; +// Returns true iff the literal encoding is UTF-8. +constexpr auto is_utf8_enabled() -> bool { // Avoid an MSVC sign extension bug: https://github.com/fmtlib/fmt/pull/2297. using uchar = unsigned char; - constexpr bool utf8 = sizeof(section) == 3 && uchar(section[0]) == 0xC2 && - uchar(section[1]) == 0xA7; - static_assert(utf8 || !FMT_MSC_VERSION, - "Unicode support requires compiling with /utf-8"); - return utf8; + return sizeof("\u00A7") == 3 && uchar("\u00A7"[0]) == 0xC2 && + uchar("\u00A7"[1]) == 0xA7; } +constexpr auto use_utf8() -> bool { return FMT_UNICODE || is_utf8_enabled(); } -FMT_CONSTEXPR inline auto is_utf8() -> bool { - return FMT_UNICODE || is_utf8_enabled(); -} +static_assert(!(FMT_UNICODE && FMT_MSC_VERSION && !is_utf8_enabled()), + "Unicode support requires compiling with /utf-8"); template FMT_CONSTEXPR auto length(const Char* s) -> size_t { size_t len = 0; @@ -3027,7 +3024,7 @@ FMT_API void vprintln(FILE* f, string_view fmt, format_args args); template FMT_INLINE void print(format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - if (!detail::is_utf8()) return detail::vprint_mojibake(stdout, fmt, vargs); + if (!detail::use_utf8()) return detail::vprint_mojibake(stdout, fmt, vargs); return detail::is_locking() ? vprint(fmt, vargs) : vprint_locked(stdout, fmt, vargs); } @@ -3045,7 +3042,7 @@ FMT_INLINE void print(format_string fmt, T&&... args) { template FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - if (!detail::is_utf8()) return detail::vprint_mojibake(f, fmt, vargs); + if (!detail::use_utf8()) return detail::vprint_mojibake(f, fmt, vargs); return detail::is_locking() ? vprint(f, fmt, vargs) : vprint_locked(f, fmt, vargs); } @@ -3057,8 +3054,8 @@ FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { template FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - return detail::is_utf8() ? vprintln(f, fmt, vargs) - : detail::vprint_mojibake(f, fmt, vargs, true); + return detail::use_utf8() ? vprintln(f, fmt, vargs) + : detail::vprint_mojibake(f, fmt, vargs, true); } /** diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index 88dd911e..d61b0832 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -397,7 +397,7 @@ void write_codecvt(codecvt_result& out, string_view in_buf, template auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) -> OutputIt { - if (detail::is_utf8() && loc != get_classic_locale()) { + if (detail::use_utf8() && loc != get_classic_locale()) { // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and // gcc-4. #if FMT_MSC_VERSION != 0 || \ diff --git a/include/fmt/format.h b/include/fmt/format.h index 6876967f..da3b7f13 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1800,7 +1800,7 @@ auto find_escape(const Char* begin, const Char* end) inline auto find_escape(const char* begin, const char* end) -> find_escape_result { - if (!is_utf8()) return find_escape(begin, end); + if (!use_utf8()) return find_escape(begin, end); auto result = find_escape_result{end, nullptr, 0}; for_each_codepoint(string_view(begin, to_unsigned(end - begin)), [&](uint32_t cp, string_view sv) { diff --git a/include/fmt/ostream.h b/include/fmt/ostream.h index 7ab24580..1547184d 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -183,7 +183,7 @@ void vprint(std::basic_ostream& os, FMT_EXPORT template void print(std::ostream& os, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - if (detail::is_utf8()) + if (detail::use_utf8()) vprint(os, fmt, vargs); else detail::vprint_directly(os, fmt, vargs); diff --git a/test/ranges-test.cc b/test/ranges-test.cc index b2c0b67a..6df1ee76 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -530,7 +530,7 @@ TEST(ranges_test, escape) { EXPECT_EQ(fmt::format("{}", vec{"\x7f"}), "[\"\\x7f\"]"); EXPECT_EQ(fmt::format("{}", vec{"n\xcc\x83"}), "[\"n\xcc\x83\"]"); - if (fmt::detail::is_utf8()) { + if (fmt::detail::use_utf8()) { EXPECT_EQ(fmt::format("{}", vec{"\xcd\xb8"}), "[\"\\u0378\"]"); // Unassigned Unicode code points. EXPECT_EQ(fmt::format("{}", vec{"\xf0\xaa\x9b\x9e"}), "[\"\\U0002a6de\"]"); diff --git a/test/unicode-test.cc b/test/unicode-test.cc index e9ea5e5e..07b7eb35 100644 --- a/test/unicode-test.cc +++ b/test/unicode-test.cc @@ -15,7 +15,7 @@ using testing::Contains; -TEST(unicode_test, is_utf8) { EXPECT_TRUE(fmt::detail::is_utf8()); } +TEST(unicode_test, use_utf8) { EXPECT_TRUE(fmt::detail::use_utf8()); } TEST(unicode_test, legacy_locale) { auto loc = get_locale("be_BY.CP1251", "Belarusian_Belarus.1251");