diff --git a/include/fmt/base.h b/include/fmt/base.h index c2f46873..51649328 100644 --- a/include/fmt/base.h +++ b/include/fmt/base.h @@ -429,21 +429,20 @@ struct is_std_string_like().find_first_of( : std::is_convertible().data()), const typename T::value_type*> {}; -// Returns true iff the literal encoding is UTF-8. -constexpr auto is_utf8_enabled() -> bool { return "\u00A7"[1] == '\xA7'; } -// It is a macro for better debug codegen without if constexpr. -#define FMT_USE_UTF8 (!FMT_MSC_VERSION || fmt::detail::is_utf8_enabled()) - -template constexpr const char* narrow(const T*) { return nullptr; } -constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; } +// Check if the literal encoding is UTF-8. +enum { is_utf8_enabled = "\u00A7"[1] == '\xA7' }; +enum { use_utf8 = !FMT_MSC_VERSION || is_utf8_enabled }; #ifndef FMT_UNICODE # define FMT_UNICODE 1 #endif -static_assert(!FMT_UNICODE || FMT_USE_UTF8, +static_assert(!FMT_UNICODE || use_utf8, "Unicode support requires compiling with /utf-8"); +template constexpr const char* narrow(const T*) { return nullptr; } +constexpr FMT_ALWAYS_INLINE const char* narrow(const char* s) { return s; } + template FMT_CONSTEXPR auto compare(const Char* s1, const Char* s2, std::size_t n) -> int { @@ -2931,7 +2930,8 @@ FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args); template FMT_INLINE void print(format_string fmt, T&&... args) { vargs va = {{args...}}; - if (!FMT_USE_UTF8) return detail::vprint_mojibake(stdout, fmt.str, va, false); + if (!detail::use_utf8) + return detail::vprint_mojibake(stdout, fmt.str, va, false); return detail::is_locking() ? vprint_buffered(stdout, fmt.str, va) : vprint(fmt.str, va); } @@ -2947,7 +2947,7 @@ FMT_INLINE void print(format_string fmt, T&&... args) { template FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { vargs va = {{args...}}; - if (!FMT_USE_UTF8) return detail::vprint_mojibake(f, fmt.str, va, false); + if (!detail::use_utf8) return detail::vprint_mojibake(f, fmt.str, va, false); return detail::is_locking() ? vprint_buffered(f, fmt.str, va) : vprint(f, fmt.str, va); } @@ -2957,8 +2957,8 @@ FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { template FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) { vargs va = {{args...}}; - return FMT_USE_UTF8 ? vprintln(f, fmt.str, va) - : detail::vprint_mojibake(f, fmt.str, va, true); + return detail::use_utf8 ? vprintln(f, fmt.str, va) + : detail::vprint_mojibake(f, fmt.str, va, true); } /// Formats `args` according to specifications in `fmt` and writes the output diff --git a/include/fmt/chrono.h b/include/fmt/chrono.h index b59c4db7..a1e67583 100644 --- a/include/fmt/chrono.h +++ b/include/fmt/chrono.h @@ -353,7 +353,7 @@ void write_codecvt(codecvt_result& out, string_view in, template auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) -> OutputIt { - if (FMT_USE_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 || \ @@ -648,7 +648,7 @@ FMT_CONSTEXPR inline auto get_units() -> const char* { if (std::is_same::value) return "ps"; if (std::is_same::value) return "ns"; if (std::is_same::value) - return FMT_USE_UTF8 ? "µs" : "us"; + return detail::use_utf8 ? "µs" : "us"; if (std::is_same::value) return "ms"; if (std::is_same::value) return "cs"; if (std::is_same::value) return "ds"; diff --git a/include/fmt/format.h b/include/fmt/format.h index 5a54187e..3d019501 100644 --- a/include/fmt/format.h +++ b/include/fmt/format.h @@ -1862,7 +1862,7 @@ auto find_escape(const Char* begin, const Char* end) inline auto find_escape(const char* begin, const char* end) -> find_escape_result { - if (!FMT_USE_UTF8) return find_escape(begin, end); + if (!detail::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 18a8b88c..114b8c29 100644 --- a/include/fmt/ostream.h +++ b/include/fmt/ostream.h @@ -142,7 +142,7 @@ inline void vprint(std::ostream& os, string_view fmt, format_args args) { FMT_EXPORT template void print(std::ostream& os, format_string fmt, T&&... args) { fmt::vargs vargs = {{args...}}; - if (FMT_USE_UTF8) return vprint(os, fmt.str, vargs); + if (detail::use_utf8) return vprint(os, fmt.str, vargs); auto buffer = memory_buffer(); detail::vformat_to(buffer, fmt.str, vargs); detail::write_buffer(os, buffer); diff --git a/include/fmt/xchar.h b/include/fmt/xchar.h index 6644b6ad..a43530f1 100644 --- a/include/fmt/xchar.h +++ b/include/fmt/xchar.h @@ -118,7 +118,7 @@ template <> struct is_char : std::true_type {}; #ifdef __cpp_char8_t template <> -struct is_char : bool_constant {}; +struct is_char : bool_constant {}; #endif template diff --git a/test/ranges-test.cc b/test/ranges-test.cc index f859e241..a3b659db 100644 --- a/test/ranges-test.cc +++ b/test/ranges-test.cc @@ -560,7 +560,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_USE_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 f2c04e95..2b59cff9 100644 --- a/test/unicode-test.cc +++ b/test/unicode-test.cc @@ -15,7 +15,7 @@ using testing::Contains; -TEST(unicode_test, use_utf8) { EXPECT_TRUE(FMT_USE_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");