From 9d728fe0ed3a583078c5d17b6b80f51823d590a3 Mon Sep 17 00:00:00 2001 From: Allan CORNET Date: Sun, 28 Aug 2022 19:24:47 +0200 Subject: [PATCH] fix #715 update {fmt} to 9.1.0 --- CHANGELOG.md | 6 + modules/stream_manager/src/fmt/ChangeLog.rst | 128 ++++++++- .../src/fmt/include/fmt/chrono.h | 45 ++-- .../src/fmt/include/fmt/color.h | 2 +- .../src/fmt/include/fmt/compile.h | 26 +- .../stream_manager/src/fmt/include/fmt/core.h | 79 ++++-- .../src/fmt/include/fmt/format-inl.h | 52 ++-- .../src/fmt/include/fmt/format.h | 105 +++++--- .../src/fmt/include/fmt/ostream.h | 104 ++++--- .../src/fmt/include/fmt/ranges.h | 255 ++++++++++++------ .../stream_manager/src/fmt/include/fmt/std.h | 5 - .../src/fmt/include/fmt/xchar.h | 13 +- 12 files changed, 557 insertions(+), 263 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 25de9bb84f..b7287eb038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). +## 0.6.9 (UNRELEASED) + +### Changed + +- [#715](http://github.com/Nelson-numerical-software/nelson/issues/715): update `{fmt}` to 9.1.0. + ## 0.6.8 (2022-08-27) ### Added diff --git a/modules/stream_manager/src/fmt/ChangeLog.rst b/modules/stream_manager/src/fmt/ChangeLog.rst index 966d039f81..4ebc5c7330 100644 --- a/modules/stream_manager/src/fmt/ChangeLog.rst +++ b/modules/stream_manager/src/fmt/ChangeLog.rst @@ -1,3 +1,129 @@ +9.1.0 - 2022-08-27 +------------------ + +* ``fmt::formatted_size`` now works at compile time + (`#3026 `_). For example + (`godbolt `__): + + .. code:: c++ + + #include + + int main() { + using namespace fmt::literals; + constexpr size_t n = fmt::formatted_size("{}"_cf, 42); + fmt::print("{}\n", n); // prints 2 + } + + Thanks `@marksantaniello (Mark Santaniello) + `_. + +* Fixed handling of invalid UTF-8 + (`#3038 `_, + `#3044 `_, + `#3056 `_). + Thanks `@phprus (Vladislav Shchapov) `_ and + `@skeeto (Christopher Wellons) `_. + +* Improved Unicode support in ``ostream`` overloads of ``print`` + (`#2994 `_, + `#3001 `_, + `#3025 `_). + Thanks `@dimztimz (Dimitrij Mijoski) `_. + +* Fixed handling of the sign specifier in localized formatting on systems with + 32-bit ``wchar_t`` (`#3041 `_). + +* Added support for wide streams to ``fmt::streamed`` + (`#2994 `_). + Thanks `@phprus (Vladislav Shchapov) `_. + +* Added the ``n`` specifier that disables the output of delimiters when + formatting ranges (`#2981 `_, + `#2983 `_). + For example (`godbolt `__): + + .. code:: c++ + + #include + #include + + int main() { + auto v = std::vector{1, 2, 3}; + fmt::print("{:n}\n", v); // prints 1, 2, 3 + } + + Thanks `@BRevzin (Barry Revzin) `_. + +* Worked around problematic ``std::string_view`` constructors introduced in + C++23 (`#3030 `_, + `#3050 `_). + Thanks `@strega-nil-ms (nicole mazzuca) `_. + +* Improve handling (exclusion) of recursive ranges + (`#2968 `_, + `#2974 `_). + Thanks `@Dani-Hub (Daniel Krügler) `_. + +* Improved error reporting in format string compilation + (`#3055 `_). + +* Improved the implementation of + `Dragonbox `_, the algorithm used for + the default floating-point formatting + (`#2984 `_). + Thanks `@jk-jeon (Junekey Jeon) `_. + +* Fixed issues with floating-point formatting on exotic platforms. + +* Improved the implementation of chrono formatting + (`#3010 `_). + Thanks `@phprus (Vladislav Shchapov) `_. + +* Improved documentation + (`#2966 `_, + `#3009 `_, + `#3020 `_, + `#3037 `_). + Thanks `@mwinterb `_, + `@jcelerier (Jean-Michaël Celerier) `_ + and `@remiburtin (Rémi Burtin) `_. + +* Improved build configuration + (`#2991 `_, + `#2995 `_, + `#3004 `_, + `#3007 `_, + `#3040 `_). + Thanks `@dimztimz (Dimitrij Mijoski) `_ and + `@hwhsu1231 (Haowei Hsu) `_. + +* Fixed various warnings and compilation issues + (`#2969 `_, + `#2971 `_, + `#2975 `_, + `#2982 `_, + `#2985 `_, + `#2988 `_, + `#3000 `_, + `#3006 `_, + `#3014 `_, + `#3015 `_, + `#3021 `_, + `#3023 `_, + `#3024 `_, + `#3029 `_, + `#3043 `_, + `#3052 `_, + `#3053 `_, + `#3054 `_). + Thanks `@h-friederich (Hannes Friederich) `_, + `@dimztimz (Dimitrij Mijoski) `_, + `@olupton (Olli Lupton) `_, + `@bernhardmgruber (Bernhard Manfred Gruber) + `_, + `@phprus (Vladislav Shchapov) `_. + 9.0.0 - 2022-07-04 ------------------ @@ -19,7 +145,7 @@ return result; } - constexpr auto answer = compile_time_itoa(0.42); + constexpr auto answer = compile_time_dtoa(0.42); works with the default settings. diff --git a/modules/stream_manager/src/fmt/include/fmt/chrono.h b/modules/stream_manager/src/fmt/include/fmt/chrono.h index 7602b3c02e..e8b355d523 100644 --- a/modules/stream_manager/src/fmt/include/fmt/chrono.h +++ b/modules/stream_manager/src/fmt/include/fmt/chrono.h @@ -203,7 +203,7 @@ To safe_duration_cast(std::chrono::duration from, } const auto min1 = (std::numeric_limits::min)() / Factor::num; - if (count < min1) { + if (!std::is_unsigned::value && count < min1) { ec = 1; return {}; } @@ -1396,7 +1396,8 @@ inline bool isfinite(T) { // Converts value to Int and checks that it's in the range [0, upper). template ::value)> inline Int to_nonnegative_int(T value, Int upper) { - FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper), + FMT_ASSERT(std::is_unsigned::value || + (value >= 0 && to_unsigned(value) <= to_unsigned(upper)), "invalid value"); (void)upper; return static_cast(value); @@ -1776,7 +1777,7 @@ struct chrono_formatter { format_to(std::back_inserter(buf), runtime("{:.{}f}"), std::fmod(val * static_cast(Period::num) / static_cast(Period::den), - 60), + static_cast(60)), num_fractional_digits); if (negative) *out++ = '-'; if (buf.size() < 2 || buf[1] == '.') *out++ = '0'; @@ -2001,13 +2002,9 @@ template struct formatter, Char> : formatter { FMT_CONSTEXPR formatter() { - this->do_parse(default_specs, - default_specs + sizeof(default_specs) / sizeof(Char)); - } - - template - FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { - return this->do_parse(ctx.begin(), ctx.end(), true); + basic_string_view default_specs = + detail::string_literal{}; + this->do_parse(default_specs.begin(), default_specs.end()); } template @@ -2015,15 +2012,8 @@ struct formatter, FormatContext& ctx) const -> decltype(ctx.out()) { return formatter::format(localtime(val), ctx); } - - static constexpr const Char default_specs[] = {'%', 'F', ' ', '%', 'T'}; }; -template -constexpr const Char - formatter, - Char>::default_specs[]; - template struct formatter { private: enum class spec { @@ -2035,13 +2025,18 @@ template struct formatter { basic_string_view specs; protected: - template - FMT_CONSTEXPR auto do_parse(It begin, It end, bool with_default = false) - -> It { + template FMT_CONSTEXPR auto do_parse(It begin, It end) -> It { if (begin != end && *begin == ':') ++begin; end = detail::parse_chrono_format(begin, end, detail::tm_format_checker()); - if (!with_default || end != begin) - specs = {begin, detail::to_unsigned(end - begin)}; + // Replace default spec only if the new spec is not empty. + if (end != begin) specs = {begin, detail::to_unsigned(end - begin)}; + return end; + } + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + auto end = this->do_parse(ctx.begin(), ctx.end()); // basic_string_view<>::compare isn't constexpr before C++17. if (specs.size() == 2 && specs[0] == Char('%')) { if (specs[1] == Char('F')) @@ -2052,12 +2047,6 @@ template struct formatter { return end; } - public: - template - FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { - return this->do_parse(ctx.begin(), ctx.end()); - } - template auto format(const std::tm& tm, FormatContext& ctx) const -> decltype(ctx.out()) { diff --git a/modules/stream_manager/src/fmt/include/fmt/color.h b/modules/stream_manager/src/fmt/include/fmt/color.h index e6212d249e..4c163277ef 100644 --- a/modules/stream_manager/src/fmt/include/fmt/color.h +++ b/modules/stream_manager/src/fmt/include/fmt/color.h @@ -634,7 +634,7 @@ struct formatter, Char> : formatter { **Example**:: - fmt::print("Elapsed time: {s:.2f} seconds", + fmt::print("Elapsed time: {0:.2f} seconds", fmt::styled(1.23, fmt::fg(fmt::color::green) | fmt::bg(fmt::color::blue))); \endrst diff --git a/modules/stream_manager/src/fmt/include/fmt/compile.h b/modules/stream_manager/src/fmt/include/fmt/compile.h index c09dd6f2a1..933668c41c 100644 --- a/modules/stream_manager/src/fmt/include/fmt/compile.h +++ b/modules/stream_manager/src/fmt/include/fmt/compile.h @@ -14,8 +14,8 @@ FMT_BEGIN_NAMESPACE namespace detail { template -inline counting_iterator copy_str(InputIt begin, InputIt end, - counting_iterator it) { +FMT_CONSTEXPR inline counting_iterator copy_str(InputIt begin, InputIt end, + counting_iterator it) { return it + (end - begin); } @@ -341,7 +341,7 @@ constexpr parse_specs_result parse_specs(basic_string_view str, next_arg_id); auto f = formatter(); auto end = f.parse(ctx); - return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1, + return {f, pos + fmt::detail::to_unsigned(end - str.data()), next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; } @@ -397,13 +397,20 @@ constexpr auto parse_replacement_field_then_tail(S format_str) { return parse_tail( field::type, ARG_INDEX>(), format_str); - } else if constexpr (c == ':') { + } else if constexpr (c != ':') { + FMT_THROW(format_error("expected ':'")); + } else { constexpr auto result = parse_specs::type>( str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); - return parse_tail( - spec_field::type, ARG_INDEX>{ - result.fmt}, - format_str); + if constexpr (result.end >= str.size() || str[result.end] != '}') { + FMT_THROW(format_error("expected '}'")); + return 0; + } else { + return parse_tail( + spec_field::type, ARG_INDEX>{ + result.fmt}, + format_str); + } } } @@ -568,7 +575,8 @@ format_to_n_result format_to_n(OutputIt out, size_t n, template ::value)> -size_t formatted_size(const S& format_str, const Args&... args) { +FMT_CONSTEXPR20 size_t formatted_size(const S& format_str, + const Args&... args) { return fmt::format_to(detail::counting_iterator(), format_str, args...) .count(); } diff --git a/modules/stream_manager/src/fmt/include/fmt/core.h b/modules/stream_manager/src/fmt/include/fmt/core.h index 0e7843b85f..f6a37af9e3 100644 --- a/modules/stream_manager/src/fmt/include/fmt/core.h +++ b/modules/stream_manager/src/fmt/include/fmt/core.h @@ -17,7 +17,7 @@ #include // The fmt library version in the form major * 10000 + minor * 100 + patch. -#define FMT_VERSION 90000 +#define FMT_VERSION 90100 #if defined(__clang__) && !defined(__ibmxl__) # define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__) @@ -200,6 +200,9 @@ # endif #endif +// An inline std::forward replacement. +#define FMT_FORWARD(...) static_cast(__VA_ARGS__) + #ifdef _MSC_VER # define FMT_UNCHECKED_ITERATOR(It) \ using _Unchecked_type = It // Mark iterator as checked. @@ -273,7 +276,8 @@ #ifndef FMT_USE_NONTYPE_TEMPLATE_ARGS # if defined(__cpp_nontype_template_args) && \ ((FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L) || \ - __cpp_nontype_template_args >= 201911L) + __cpp_nontype_template_args >= 201911L) && \ + !defined(__NVCOMPILER) # define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 # else # define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 @@ -402,7 +406,7 @@ template auto convert_for_visit(T) -> monostate { return {}; } template FMT_CONSTEXPR auto to_unsigned(Int value) -> typename std::make_unsigned::type { - FMT_ASSERT(value >= 0, "negative value"); + FMT_ASSERT(std::is_unsigned::value || value >= 0, "negative value"); return static_cast::type>(value); } @@ -707,8 +711,8 @@ class basic_format_parse_context : private ErrorHandler { next_arg_id_ = -1; do_check_arg_id(id); } - FMT_CONSTEXPR void check_arg_id(basic_string_view) {} + FMT_CONSTEXPR void check_dynamic_spec(int arg_id); FMT_CONSTEXPR void on_error(const char* message) { ErrorHandler::on_error(message); @@ -735,7 +739,8 @@ class compile_parse_context ErrorHandler eh = {}, int next_arg_id = 0) : base(format_str, eh, next_arg_id), num_args_(num_args), types_(types) {} - constexpr int num_args() const { return num_args_; } + constexpr auto num_args() const -> int { return num_args_; } + constexpr auto arg_type(int id) const -> type { return types_[id]; } FMT_CONSTEXPR auto next_arg_id() -> int { int id = base::next_arg_id(); @@ -748,6 +753,11 @@ class compile_parse_context if (id >= num_args_) this->on_error("argument not found"); } using base::check_arg_id; + + FMT_CONSTEXPR void check_dynamic_spec(int arg_id) { + if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id])) + this->on_error("width/precision is not integer"); + } }; FMT_END_DETAIL_NAMESPACE @@ -763,6 +773,15 @@ basic_format_parse_context::do_check_arg_id(int id) { } } +template +FMT_CONSTEXPR void +basic_format_parse_context::check_dynamic_spec(int arg_id) { + if (detail::is_constant_evaluated()) { + using context = detail::compile_parse_context; + static_cast(this)->check_dynamic_spec(arg_id); + } +} + template class basic_format_arg; template class basic_format_args; template class dynamic_format_arg_store; @@ -917,11 +936,11 @@ template class buffer { /** Appends data to the end of the buffer. */ template void append(const U* begin, const U* end); - template FMT_CONSTEXPR auto operator[](I index) -> T& { + template FMT_CONSTEXPR auto operator[](Idx index) -> T& { return ptr_[index]; } - template - FMT_CONSTEXPR auto operator[](I index) const -> const T& { + template + FMT_CONSTEXPR auto operator[](Idx index) const -> const T& { return ptr_[index]; } }; @@ -1649,6 +1668,11 @@ auto copy_str(InputIt begin, InputIt end, appender out) -> appender { return out; } +template +FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt { + return detail::copy_str(rng.begin(), rng.end(), out); +} + #if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 // A workaround for gcc 4.8 to make void_t work in a SFINAE context. template struct void_t_impl { using type = void; }; @@ -1708,7 +1732,7 @@ constexpr auto encode_types() -> unsigned long long { template FMT_CONSTEXPR FMT_INLINE auto make_value(T&& val) -> value { - const auto& arg = arg_mapper().map(std::forward(val)); + const auto& arg = arg_mapper().map(FMT_FORWARD(val)); constexpr bool formattable_char = !std::is_same::value; @@ -1875,7 +1899,7 @@ class format_arg_store data_{detail::make_arg< is_packed, Context, detail::mapped_type_constant, Context>::value>( - std::forward(args))...} { + FMT_FORWARD(args))...} { detail::init_named_args(data_.named_args(), 0, 0, args...); } }; @@ -1891,7 +1915,7 @@ class format_arg_store template constexpr auto make_format_args(Args&&... args) -> format_arg_store...> { - return {std::forward(args)...}; + return {FMT_FORWARD(args)...}; } /** @@ -2240,11 +2264,14 @@ class dynamic_specs_handler FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type { context_.check_arg_id(arg_id); + context_.check_dynamic_spec(arg_id); return arg_ref_type(arg_id); } FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type { - return arg_ref_type(context_.next_arg_id()); + int arg_id = context_.next_arg_id(); + context_.check_dynamic_spec(arg_id); + return arg_ref_type(arg_id); } FMT_CONSTEXPR auto make_arg_ref(basic_string_view arg_id) @@ -2270,12 +2297,15 @@ constexpr auto to_ascii(Char c) -> underlying_t { return c; } +FMT_CONSTEXPR inline auto code_point_length_impl(char c) -> int { + return "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4" + [static_cast(c) >> 3]; +} + template FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int { if (const_check(sizeof(Char) != 1)) return 1; - auto lengths = - "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"; - int len = lengths[static_cast(*begin) >> 3]; + int len = code_point_length_impl(static_cast(*begin)); // Compute the pointer to the next character early so that the next // iteration can start working on the next character. Neither Clang @@ -2803,7 +2833,8 @@ FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs& specs, template FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type, ErrorHandler&& eh = {}) -> bool { - if (type == presentation_type::none || type == presentation_type::string) + if (type == presentation_type::none || type == presentation_type::string || + type == presentation_type::debug) return true; if (type != presentation_type::pointer) eh.on_error("invalid type specifier"); return false; @@ -2921,7 +2952,10 @@ class format_string_checker { basic_string_view format_str, ErrorHandler eh) : context_(format_str, num_args, types_, eh), parse_funcs_{&parse_format_specs...}, - types_{type_constant::value...} {} + types_{ + mapped_type_constant>::value...} { + } FMT_CONSTEXPR void on_text(const Char*, const Char*) {} @@ -3065,6 +3099,15 @@ struct formatter::value, + enable_if_t<(U == detail::type::string_type || + U == detail::type::cstring_type || + U == detail::type::char_type), + int> = 0> + FMT_CONSTEXPR void set_debug_format() { + specs_.type = presentation_type::debug; + } + template FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const -> decltype(ctx.out()); @@ -3127,7 +3170,7 @@ template class basic_format_string { #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 // Workaround broken conversion on older gcc. template using format_string = string_view; -inline auto runtime(string_view s) -> basic_string_view { return s; } +inline auto runtime(string_view s) -> string_view { return s; } #else template using format_string = basic_format_string...>; diff --git a/modules/stream_manager/src/fmt/include/fmt/format-inl.h b/modules/stream_manager/src/fmt/include/fmt/format-inl.h index f44df01c5d..22b1ec8df0 100644 --- a/modules/stream_manager/src/fmt/include/fmt/format-inl.h +++ b/modules/stream_manager/src/fmt/include/fmt/format-inl.h @@ -1337,7 +1337,7 @@ template decimal_fp to_decimal(T x) noexcept { if (r < deltai) { // Exclude the right endpoint if necessary. - if (r == 0 && z_mul.is_integer && !include_right_endpoint) { + if (r == 0 && (z_mul.is_integer & !include_right_endpoint)) { --ret_value.significand; r = float_info::big_divisor; goto small_divisor_case_label; @@ -1346,26 +1346,11 @@ template decimal_fp to_decimal(T x) noexcept { goto small_divisor_case_label; } else { // r == deltai; compare fractional parts. - const carrier_uint two_fl = two_fc - 1; - - if (!include_left_endpoint || - exponent < float_info::case_fc_pm_half_lower_threshold || - exponent > float_info::divisibility_check_by_5_threshold) { - // If the left endpoint is not included, the condition for - // success is z^(f) < delta^(f) (odd parity). - // Otherwise, the inequalities on exponent ensure that - // x is not an integer, so if z^(f) >= delta^(f) (even parity), we in fact - // have strict inequality. - if (!cache_accessor::compute_mul_parity(two_fl, cache, beta).parity) { - goto small_divisor_case_label; - } - } else { - const typename cache_accessor::compute_mul_parity_result x_mul = - cache_accessor::compute_mul_parity(two_fl, cache, beta); - if (!x_mul.parity && !x_mul.is_integer) { - goto small_divisor_case_label; - } - } + const typename cache_accessor::compute_mul_parity_result x_mul = + cache_accessor::compute_mul_parity(two_fc - 1, cache, beta); + + if (!(x_mul.parity | (x_mul.is_integer & include_left_endpoint))) + goto small_divisor_case_label; } ret_value.exponent = minus_k + float_info::kappa + 1; @@ -1404,7 +1389,7 @@ template decimal_fp to_decimal(T x) noexcept { // or equivalently, when y is an integer. if (y_mul.parity != approx_y_parity) --ret_value.significand; - else if (y_mul.is_integer && ret_value.significand % 2 != 0) + else if (y_mul.is_integer & (ret_value.significand % 2 != 0)) --ret_value.significand; return ret_value; } @@ -1488,17 +1473,13 @@ FMT_FUNC std::string vformat(string_view fmt, format_args args) { return to_string(buffer); } -#ifdef _WIN32 namespace detail { +#ifdef _WIN32 using dword = conditional_t; extern "C" __declspec(dllimport) int __stdcall WriteConsoleW( // void*, const void*, dword, dword*, void*); -} // namespace detail -#endif -namespace detail { -FMT_FUNC void print(std::FILE* f, string_view text) { -#ifdef _WIN32 +FMT_FUNC bool write_console(std::FILE* f, string_view text) { auto fd = _fileno(f); if (_isatty(fd)) { detail::utf8_to_utf16 u16(string_view(text.data(), text.size())); @@ -1506,11 +1487,20 @@ FMT_FUNC void print(std::FILE* f, string_view text) { if (detail::WriteConsoleW(reinterpret_cast(_get_osfhandle(fd)), u16.c_str(), static_cast(u16.size()), &written, nullptr)) { - return; + return true; } - // Fallback to fwrite on failure. It can happen if the output has been - // redirected to NUL. } + // We return false if the file descriptor was not TTY, or it was but + // SetConsoleW failed which can happen if the output has been redirected to + // NUL. In both cases when we return false, we should attempt to do regular + // write via fwrite or std::ostream::write. + return false; +} +#endif + +FMT_FUNC void print(std::FILE* f, string_view text) { +#ifdef _WIN32 + if (write_console(f, text)) return; #endif detail::fwrite_fully(text.data(), 1, text.size(), f); } diff --git a/modules/stream_manager/src/fmt/include/fmt/format.h b/modules/stream_manager/src/fmt/include/fmt/format.h index 04adee5bff..9ac7c5df75 100644 --- a/modules/stream_manager/src/fmt/include/fmt/format.h +++ b/modules/stream_manager/src/fmt/include/fmt/format.h @@ -249,6 +249,18 @@ FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) { #endif } +template struct string_literal { + static constexpr CharT value[sizeof...(C)] = {C...}; + constexpr operator basic_string_view() const { + return {value, sizeof...(C)}; + } +}; + +#if FMT_CPLUSPLUS < 201703L +template +constexpr CharT string_literal::value[sizeof...(C)]; +#endif + template class formatbuf : public Streambuf { private: using char_type = typename Streambuf::char_type; @@ -287,7 +299,8 @@ FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { if (is_constant_evaluated()) return std::bit_cast(from); #endif auto to = To(); - std::memcpy(&to, &from, sizeof(to)); + // The cast suppresses a bogus -Wclass-memaccess on GCC. + std::memcpy(static_cast(&to), &from, sizeof(to)); return to; } @@ -366,10 +379,12 @@ class uint128_fallback { } FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { if (shift == 64) return {0, hi_}; + if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64); return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; } FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback { if (shift == 64) return {lo_, 0}; + if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64); return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; } FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& { @@ -389,11 +404,11 @@ class uint128_fallback { hi_ += (lo_ < n ? 1 : 0); return *this; } -#if FMT_HAS_BUILTIN(__builtin_addcll) +#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__) unsigned long long carry; lo_ = __builtin_addcll(lo_, n, 0, &carry); hi_ += carry; -#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) +#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__) unsigned long long result; auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result); lo_ = result; @@ -592,19 +607,23 @@ FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e) constexpr const int shiftc[] = {0, 18, 12, 6, 0}; constexpr const int shifte[] = {0, 6, 4, 2, 0}; - int len = code_point_length(s); - const char* next = s + len; + int len = code_point_length_impl(*s); + // Compute the pointer to the next character early so that the next + // iteration can start working on the next character. Neither Clang + // nor GCC figure out this reordering on their own. + const char* next = s + len + !len; + + using uchar = unsigned char; // Assume a four-byte character and load four bytes. Unused bits are // shifted out. - *c = uint32_t(s[0] & masks[len]) << 18; - *c |= uint32_t(s[1] & 0x3f) << 12; - *c |= uint32_t(s[2] & 0x3f) << 6; - *c |= uint32_t(s[3] & 0x3f) << 0; + *c = uint32_t(uchar(s[0]) & masks[len]) << 18; + *c |= uint32_t(uchar(s[1]) & 0x3f) << 12; + *c |= uint32_t(uchar(s[2]) & 0x3f) << 6; + *c |= uint32_t(uchar(s[3]) & 0x3f) << 0; *c >>= shiftc[len]; // Accumulate the various error conditions. - using uchar = unsigned char; *e = (*c < mins[len]) << 6; // non-canonical encoding *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? *e |= (*c > 0x10FFFF) << 8; // out of range? @@ -628,8 +647,8 @@ FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { auto error = 0; auto end = utf8_decode(buf_ptr, &cp, &error); bool result = f(error ? invalid_code_point : cp, - string_view(ptr, to_unsigned(end - buf_ptr))); - return result ? end : nullptr; + string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr))); + return result ? (error ? buf_ptr + 1 : end) : nullptr; }; auto p = s.data(); const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. @@ -919,8 +938,11 @@ struct is_contiguous> : std::true_type { }; namespace detail { +#ifdef _WIN32 +FMT_API bool write_console(std::FILE* f, string_view text); +#endif FMT_API void print(std::FILE*, string_view); -} +} // namespace detail /** A formatting error such as invalid format string. */ FMT_CLASS_API @@ -1213,7 +1235,7 @@ FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) template >::value)> -inline auto format_decimal(Iterator out, UInt value, int size) +FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size) -> format_decimal_result { // Buffer is large enough to hold all digits (digits10 + 1). Char buffer[digits10() + 1]; @@ -1274,8 +1296,6 @@ template <> struct float_info { static const int small_divisor = 10; static const int min_k = -31; static const int max_k = 46; - static const int divisibility_check_by_5_threshold = 39; - static const int case_fc_pm_half_lower_threshold = -1; static const int shorter_interval_tie_lower_threshold = -35; static const int shorter_interval_tie_upper_threshold = -35; }; @@ -1288,8 +1308,6 @@ template <> struct float_info { static const int small_divisor = 100; static const int min_k = -292; static const int max_k = 326; - static const int divisibility_check_by_5_threshold = 86; - static const int case_fc_pm_half_lower_threshold = -2; static const int shorter_interval_tie_lower_threshold = -77; static const int shorter_interval_tie_upper_threshold = -77; }; @@ -1543,7 +1561,10 @@ FMT_CONSTEXPR inline fp get_cached_power(int min_exponent, const int dec_exp_step = 8; index = (index - first_dec_exp - 1) / dec_exp_step + 1; pow10_exponent = first_dec_exp + index * dec_exp_step; - return {data::pow10_significands[index], data::pow10_exponents[index]}; + // Using *(x + index) instead of x[index] avoids an issue with some compilers + // using the EDG frontend (e.g. nvhpc/22.3 in C++17 mode). + return {*(data::pow10_significands + index), + *(data::pow10_exponents + index)}; } #ifndef _MSC_VER @@ -1724,18 +1745,18 @@ inline auto find_escape(const char* begin, const char* end) return result; } -#define FMT_STRING_IMPL(s, base, explicit) \ - [] { \ - /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ - /* Use a macro-like name to avoid shadowing warnings. */ \ - struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \ - using char_type = fmt::remove_cvref_t; \ - FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ - operator fmt::basic_string_view() const { \ - return fmt::detail_exported::compile_string_to_view(s); \ - } \ - }; \ - return FMT_COMPILE_STRING(); \ +#define FMT_STRING_IMPL(s, base, explicit) \ + [] { \ + /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ + /* Use a macro-like name to avoid shadowing warnings. */ \ + struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \ + using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t; \ + FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ + operator fmt::basic_string_view() const { \ + return fmt::detail_exported::compile_string_to_view(s); \ + } \ + }; \ + return FMT_COMPILE_STRING(); \ }() /** @@ -1981,7 +2002,10 @@ auto write_int_localized(OutputIt out, UInt value, unsigned prefix, grouping.count_separators(num_digits)); return write_padded( out, specs, size, size, [&](reserve_iterator it) { - if (prefix != 0) *it++ = static_cast(prefix); + if (prefix != 0) { + char sign = static_cast(prefix); + *it++ = static_cast(sign); + } return grouping.apply(it, string_view(digits, to_unsigned(num_digits))); }); } @@ -2123,29 +2147,30 @@ class counting_iterator { FMT_UNCHECKED_ITERATOR(counting_iterator); struct value_type { - template void operator=(const T&) {} + template FMT_CONSTEXPR void operator=(const T&) {} }; - counting_iterator() : count_(0) {} + FMT_CONSTEXPR counting_iterator() : count_(0) {} - size_t count() const { return count_; } + FMT_CONSTEXPR size_t count() const { return count_; } - counting_iterator& operator++() { + FMT_CONSTEXPR counting_iterator& operator++() { ++count_; return *this; } - counting_iterator operator++(int) { + FMT_CONSTEXPR counting_iterator operator++(int) { auto it = *this; ++*this; return it; } - friend counting_iterator operator+(counting_iterator it, difference_type n) { + FMT_CONSTEXPR friend counting_iterator operator+(counting_iterator it, + difference_type n) { it.count_ += static_cast(n); return it; } - value_type operator*() const { return {}; } + FMT_CONSTEXPR value_type operator*() const { return {}; } }; template @@ -2991,7 +3016,7 @@ FMT_CONSTEXPR20 inline void format_dragon(basic_fp value, upper = &upper_store; } } - bool even = (value.f & 1) == 0; + int even = static_cast((value.f & 1) == 0); if (!upper) upper = &lower; if ((flags & dragon::fixup) != 0) { if (add_compare(numerator, *upper, denominator) + even <= 0) { diff --git a/modules/stream_manager/src/fmt/include/fmt/ostream.h b/modules/stream_manager/src/fmt/include/fmt/ostream.h index 394d947c56..c3cdd4a61b 100644 --- a/modules/stream_manager/src/fmt/include/fmt/ostream.h +++ b/modules/stream_manager/src/fmt/include/fmt/ostream.h @@ -10,6 +10,12 @@ #include #include +#if defined(_WIN32) && defined(__GLIBCXX__) +# include +# include +#elif defined(_WIN32) && defined(_LIBCPP_VERSION) +# include <__std_stream> +#endif #include "format.h" @@ -51,43 +57,50 @@ struct is_streamable< (std::is_convertible::value && !std::is_enum::value)>> : std::false_type {}; -template FILE* get_file(std::basic_filebuf&) { - return nullptr; -} - -struct dummy_filebuf { - FILE* _Myfile; -}; -template struct ms_filebuf { - using type = dummy_filebuf; -}; -template struct ms_filebuf { - using type = T; -}; -using filebuf_type = ms_filebuf::type; - -FILE* get_file(filebuf_type& buf); - // Generate a unique explicit instantion in every translation unit using a tag // type in an anonymous namespace. namespace { -struct filebuf_access_tag {}; +struct file_access_tag {}; } // namespace -template -class filebuf_access { - friend FILE* get_file(filebuf_type& buf) { return buf.*file; } +template +class file_access { + friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; } }; -template class filebuf_access; - -inline bool write(std::filebuf& buf, fmt::string_view data) { - FILE* f = get_file(buf); - if (!f) return false; - print(f, data); - return true; + +#if FMT_MSC_VERSION +template class file_access; +auto get_file(std::filebuf&) -> FILE*; +#elif defined(_WIN32) && defined(_LIBCPP_VERSION) +template class file_access, + &std::__stdoutbuf::__file_>; +auto get_file(std::__stdoutbuf&) -> FILE*; +#endif + +inline bool write_ostream_unicode(std::ostream& os, fmt::string_view data) { +#if FMT_MSC_VERSION + if (auto* buf = dynamic_cast(os.rdbuf())) + if (FILE* f = get_file(*buf)) return write_console(f, data); +#elif defined(_WIN32) && defined(__GLIBCXX__) + auto* rdbuf = os.rdbuf(); + FILE* c_file; + if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) + c_file = fbuf->file(); + else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf*>(rdbuf)) + c_file = fbuf->file(); + else + return false; + if (c_file) return write_console(c_file, data); +#elif defined(_WIN32) && defined(_LIBCPP_VERSION) + if (auto* buf = dynamic_cast*>(os.rdbuf())) + if (FILE* f = get_file(*buf)) return write_console(f, data); +#else + ignore_unused(os, data); +#endif + return false; } -inline bool write(std::wfilebuf&, fmt::basic_string_view) { +inline bool write_ostream_unicode(std::wostream&, + fmt::basic_string_view) { return false; } @@ -95,10 +108,6 @@ inline bool write(std::wfilebuf&, fmt::basic_string_view) { // It is a separate function rather than a part of vprint to simplify testing. template void write_buffer(std::basic_ostream& os, buffer& buf) { - if (const_check(FMT_MSC_VERSION)) { - auto filebuf = dynamic_cast*>(os.rdbuf()); - if (filebuf && write(*filebuf, {buf.data(), buf.size()})) return; - } const Char* buf_data = buf.data(); using unsigned_streamsize = std::make_unsigned::type; unsigned_streamsize size = buf.size(); @@ -130,6 +139,8 @@ template struct streamed_view { const T& value; }; // Formats an object of type T that has an overloaded ostream operator<<. template struct basic_ostream_formatter : formatter, Char> { + void set_debug_format() = delete; + template auto format(const T& value, basic_format_context& ctx) const -> OutputIt { @@ -142,12 +153,13 @@ struct basic_ostream_formatter : formatter, Char> { using ostream_formatter = basic_ostream_formatter; -template -struct formatter> : ostream_formatter { +template +struct formatter, Char> + : basic_ostream_formatter { template auto format(detail::streamed_view view, - basic_format_context& ctx) const -> OutputIt { - return ostream_formatter::format(view.value, ctx); + basic_format_context& ctx) const -> OutputIt { + return basic_ostream_formatter::format(view.value, ctx); } }; @@ -175,6 +187,13 @@ struct fallback_formatter::value>> using basic_ostream_formatter::format; }; +inline void vprint_directly(std::ostream& os, string_view format_str, + format_args args) { + auto buffer = memory_buffer(); + detail::vformat_to(buffer, format_str, args); + detail::write_buffer(os, buffer); +} + } // namespace detail FMT_MODULE_EXPORT template @@ -183,6 +202,7 @@ void vprint(std::basic_ostream& os, basic_format_args>> args) { auto buffer = basic_memory_buffer(); detail::vformat_to(buffer, format_str, args); + if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return; detail::write_buffer(os, buffer); } @@ -197,7 +217,11 @@ void vprint(std::basic_ostream& os, */ FMT_MODULE_EXPORT template void print(std::ostream& os, format_string fmt, T&&... args) { - vprint(os, fmt, fmt::make_format_args(args...)); + const auto& vargs = fmt::make_format_args(args...); + if (detail::is_utf8()) + vprint(os, fmt, vargs); + else + detail::vprint_directly(os, fmt, vargs); } FMT_MODULE_EXPORT diff --git a/modules/stream_manager/src/fmt/include/fmt/ranges.h b/modules/stream_manager/src/fmt/include/fmt/ranges.h index 10429fc8ed..dea7d60dd6 100644 --- a/modules/stream_manager/src/fmt/include/fmt/ranges.h +++ b/modules/stream_manager/src/fmt/include/fmt/ranges.h @@ -270,8 +270,8 @@ template using uncvref_type = remove_cvref_t>; template -using uncvref_first_type = remove_cvref_t< - decltype(std::declval>().first)>; +using uncvref_first_type = + remove_cvref_t>().first)>; template using uncvref_second_type = remove_cvref_t< @@ -326,18 +326,37 @@ struct formatter::value && fmt::is_tuple_formattable::value>> { private: + basic_string_view separator_ = detail::string_literal{}; + basic_string_view opening_bracket_ = + detail::string_literal{}; + basic_string_view closing_bracket_ = + detail::string_literal{}; + // C++11 generic lambda for format(). template struct format_each { template void operator()(const T& v) { - if (i > 0) out = detail::write_delimiter(out); + if (i > 0) out = detail::copy_str(separator, out); out = detail::write_range_entry(out, v); ++i; } int i; typename FormatContext::iterator& out; + basic_string_view separator; }; public: + FMT_CONSTEXPR formatter() {} + + FMT_CONSTEXPR void set_separator(basic_string_view sep) { + separator_ = sep; + } + + FMT_CONSTEXPR void set_brackets(basic_string_view open, + basic_string_view close) { + opening_bracket_ = open; + closing_bracket_ = close; + } + template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { return ctx.begin(); @@ -347,9 +366,9 @@ struct formatter decltype(ctx.out()) { auto out = ctx.out(); - *out++ = '('; - detail::for_each(values, format_each{0, out}); - *out++ = ')'; + out = detail::copy_str(opening_bracket_, out); + detail::for_each(values, format_each{0, out, separator_}); + out = detail::copy_str(closing_bracket_, out); return out; } }; @@ -357,9 +376,8 @@ struct formatter struct is_range { static constexpr const bool value = detail::is_range_::value && !detail::is_std_string_like::value && - !detail::is_map::value && !std::is_convertible>::value && - !std::is_constructible, T>::value; + !std::is_convertible>::value; }; namespace detail { @@ -390,40 +408,88 @@ using range_formatter_type = conditional_t< template using maybe_const_range = conditional_t::value, const R, R>; -} // namespace detail +// Workaround a bug in MSVC 2015 and earlier. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910 template -struct formatter< - R, Char, - enable_if_t< - conjunction -// Workaround a bug in MSVC 2017 and earlier. -#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920 - , - disjunction< - is_formattable>, - Char>, - detail::has_fallback_formatter< - detail::uncvref_type>, Char> - > +struct is_formattable_delayed + : disjunction< + is_formattable>, Char>, + has_fallback_formatter>, Char>> {}; #endif - >::value - >> { - using range_type = detail::maybe_const_range; - using formatter_type = - detail::range_formatter_type>; - formatter_type underlying_; +} // namespace detail + +template +struct range_formatter; + +template +struct range_formatter< + T, Char, + enable_if_t>, + disjunction, + detail::has_fallback_formatter>>::value>> { + private: + detail::range_formatter_type underlying_; bool custom_specs_ = false; + basic_string_view separator_ = detail::string_literal{}; + basic_string_view opening_bracket_ = + detail::string_literal{}; + basic_string_view closing_bracket_ = + detail::string_literal{}; + + template + FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, int) + -> decltype(u.set_debug_format()) { + u.set_debug_format(); + } + + template + FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {} + + FMT_CONSTEXPR void maybe_set_debug_format() { + maybe_set_debug_format(underlying_, 0); + } + + public: + FMT_CONSTEXPR range_formatter() {} + + FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type& { + return underlying_; + } + + FMT_CONSTEXPR void set_separator(basic_string_view sep) { + separator_ = sep; + } + + FMT_CONSTEXPR void set_brackets(basic_string_view open, + basic_string_view close) { + opening_bracket_ = open; + closing_bracket_ = close; + } template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { auto it = ctx.begin(); auto end = ctx.end(); - if (it == end || *it == '}') return it; + if (it == end || *it == '}') { + maybe_set_debug_format(); + return it; + } + + if (*it == 'n') { + set_brackets({}, {}); + ++it; + } + + if (*it == '}') { + maybe_set_debug_format(); + return it; + } if (*it != ':') - FMT_THROW(format_error("no top-level range formatters supported")); + FMT_THROW(format_error("no other top-level range formatters supported")); custom_specs_ = true; ++it; @@ -431,76 +497,101 @@ struct formatter< return underlying_.parse(ctx); } - template - auto format(range_type& range, FormatContext& ctx) const - -> decltype(ctx.out()) { - Char prefix = detail::is_set::value ? '{' : '['; - Char postfix = detail::is_set::value ? '}' : ']'; + template + auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) { detail::range_mapper> mapper; auto out = ctx.out(); - *out++ = prefix; + out = detail::copy_str(opening_bracket_, out); int i = 0; auto it = detail::range_begin(range); auto end = detail::range_end(range); for (; it != end; ++it) { - if (i > 0) out = detail::write_delimiter(out); - if (custom_specs_) { - ctx.advance_to(out); - out = underlying_.format(mapper.map(*it), ctx); - } else { - out = detail::write_range_entry(out, *it); - } + if (i > 0) out = detail::copy_str(separator_, out); + ; + ctx.advance_to(out); + out = underlying_.format(mapper.map(*it), ctx); ++i; } - *out++ = postfix; + out = detail::copy_str(closing_bracket_, out); return out; } }; -template -struct formatter< - T, Char, - enable_if_t -// Workaround a bug in MSVC 2017 and earlier. -#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920 - , - disjunction< - is_formattable, Char>, - detail::has_fallback_formatter, Char> - >, - disjunction< - is_formattable, Char>, - detail::has_fallback_formatter, Char> - > -#endif - >::value - >> { +enum class range_format { disabled, map, set, sequence, string, debug_string }; + +namespace detail { +template struct range_format_kind_ { + static constexpr auto value = std::is_same, T>::value + ? range_format::disabled + : is_map::value ? range_format::map + : is_set::value ? range_format::set + : range_format::sequence; +}; + +template +struct range_default_formatter; + +template +using range_format_constant = std::integral_constant; + +template +struct range_default_formatter< + K, R, Char, + enable_if_t<(K == range_format::sequence || K == range_format::map || + K == range_format::set)>> { + using range_type = detail::maybe_const_range; + range_formatter, Char> underlying_; + + FMT_CONSTEXPR range_default_formatter() { init(range_format_constant()); } + + FMT_CONSTEXPR void init(range_format_constant) { + underlying_.set_brackets(detail::string_literal{}, + detail::string_literal{}); + } + + FMT_CONSTEXPR void init(range_format_constant) { + underlying_.set_brackets(detail::string_literal{}, + detail::string_literal{}); + underlying_.underlying().set_brackets({}, {}); + underlying_.underlying().set_separator( + detail::string_literal{}); + } + + FMT_CONSTEXPR void init(range_format_constant) {} + template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { - return ctx.begin(); + return underlying_.parse(ctx); } - template < - typename FormatContext, typename U, - FMT_ENABLE_IF( - std::is_same::value, - const T, T>>::value)> - auto format(U& map, FormatContext& ctx) const -> decltype(ctx.out()) { - auto out = ctx.out(); - *out++ = '{'; - int i = 0; - for (const auto& item : map) { - if (i > 0) out = detail::write_delimiter(out); - out = detail::write_range_entry(out, item.first); - *out++ = ':'; - *out++ = ' '; - out = detail::write_range_entry(out, item.second); - ++i; - } - *out++ = '}'; - return out; + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + return underlying_.format(range, ctx); } }; +} // namespace detail + +template +struct range_format_kind + : conditional_t< + is_range::value, detail::range_format_kind_, + std::integral_constant> {}; + +template +struct formatter< + R, Char, + enable_if_t::value != + range_format::disabled> +// Workaround a bug in MSVC 2015 and earlier. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910 + , + detail::is_formattable_delayed +#endif + >::value>> + : detail::range_default_formatter::value, R, + Char> { +}; template struct tuple_join_view : detail::view { const std::tuple& tuple; diff --git a/modules/stream_manager/src/fmt/include/fmt/std.h b/modules/stream_manager/src/fmt/include/fmt/std.h index 227f484112..41d2b2838b 100644 --- a/modules/stream_manager/src/fmt/include/fmt/std.h +++ b/modules/stream_manager/src/fmt/include/fmt/std.h @@ -57,10 +57,6 @@ inline void write_escaped_path( } // namespace detail -#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1920 -// For MSVC 2017 and earlier using the partial specialization -// would cause an ambiguity error, therefore we provide it only -// conditionally. template struct formatter : formatter> { @@ -73,7 +69,6 @@ struct formatter basic_string_view(quoted.data(), quoted.size()), ctx); } }; -#endif FMT_END_NAMESPACE #endif diff --git a/modules/stream_manager/src/fmt/include/fmt/xchar.h b/modules/stream_manager/src/fmt/include/fmt/xchar.h index 2865b76efc..3b5bc15ca0 100644 --- a/modules/stream_manager/src/fmt/include/fmt/xchar.h +++ b/modules/stream_manager/src/fmt/include/fmt/xchar.h @@ -9,7 +9,6 @@ #define FMT_XCHAR_H_ #include -#include #include "format.h" @@ -30,9 +29,11 @@ using wmemory_buffer = basic_memory_buffer; #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 // Workaround broken conversion on older gcc. template using wformat_string = wstring_view; +inline auto runtime(wstring_view s) -> wstring_view { return s; } #else template using wformat_string = basic_format_string...>; +inline auto runtime(wstring_view s) -> basic_runtime { return {{s}}; } #endif template <> struct is_char : std::true_type {}; @@ -82,20 +83,16 @@ auto vformat(basic_string_view format_str, return to_string(buffer); } -#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 409 -template -using wformat_string = basic_format_string...>; -#endif - template auto format(wformat_string fmt, T&&... args) -> std::wstring { - return vformat(fmt, fmt::make_wformat_args(args...)); + return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...)); } // Pass char_t as a default template parameter instead of using // std::basic_string> to reduce the symbol size. template , - FMT_ENABLE_IF(!std::is_same::value)> + FMT_ENABLE_IF(!std::is_same::value && + !std::is_same::value)> auto format(const S& format_str, Args&&... args) -> std::basic_string { return vformat(detail::to_string_view(format_str), fmt::make_format_args>(args...));