diff --git a/src/3rdparty/fmt/std.h b/src/3rdparty/fmt/std.h --- a/src/3rdparty/fmt/std.h +++ b/src/3rdparty/fmt/std.h @@ -8,6 +8,8 @@ #ifndef FMT_STD_H_ #define FMT_STD_H_ +#include +#include #include #include #include @@ -15,7 +17,9 @@ #include #include #include +#include +#include "format.h" #include "ostream.h" #if FMT_HAS_INCLUDE() @@ -34,6 +38,10 @@ # endif #endif +#if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE() +# include +#endif + // GCC 4 does not support FMT_HAS_INCLUDE. #if FMT_HAS_INCLUDE() || defined(__GLIBCXX__) # include @@ -44,67 +52,155 @@ # endif #endif -#ifdef __cpp_lib_filesystem +// Check if typeid is available. +#ifndef FMT_USE_TYPEID +// __RTTI is for EDG compilers. In MSVC typeid is available without RTTI. +# if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || FMT_MSC_VERSION || \ + defined(__INTEL_RTTI__) || defined(__RTTI) +# define FMT_USE_TYPEID 1 +# else +# define FMT_USE_TYPEID 0 +# endif +#endif + +// For older Xcode versions, __cpp_lib_xxx flags are inaccurately defined. +#ifndef FMT_CPP_LIB_FILESYSTEM +# ifdef __cpp_lib_filesystem +# define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem +# else +# define FMT_CPP_LIB_FILESYSTEM 0 +# endif +#endif + +#ifndef FMT_CPP_LIB_VARIANT +# ifdef __cpp_lib_variant +# define FMT_CPP_LIB_VARIANT __cpp_lib_variant +# else +# define FMT_CPP_LIB_VARIANT 0 +# endif +#endif + +#if FMT_CPP_LIB_FILESYSTEM FMT_BEGIN_NAMESPACE namespace detail { -template -void write_escaped_path(basic_memory_buffer& quoted, - const std::filesystem::path& p) { - write_escaped_string(std::back_inserter(quoted), p.string()); +template +auto get_path_string(const std::filesystem::path& p, + const std::basic_string& native) { + if constexpr (std::is_same_v && std::is_same_v) + return to_utf8(native, to_utf8_error_policy::replace); + else + return p.string(); } -# ifdef _WIN32 -template <> -inline void write_escaped_path(memory_buffer& quoted, - const std::filesystem::path& p) { - auto buf = basic_memory_buffer(); - write_escaped_string(std::back_inserter(buf), p.native()); - // Convert UTF-16 to UTF-8. - if (!unicode_to_utf8::convert(quoted, {buf.data(), buf.size()})) - FMT_THROW(std::runtime_error("invalid utf16")); -} -# endif -template <> -inline void write_escaped_path( - basic_memory_buffer& quoted, - const std::filesystem::path& p) { - write_escaped_string( - std::back_inserter(quoted), p.native()); + +template +void write_escaped_path(basic_memory_buffer& quoted, + const std::filesystem::path& p, + const std::basic_string& native) { + if constexpr (std::is_same_v && + std::is_same_v) { + auto buf = basic_memory_buffer(); + write_escaped_string(std::back_inserter(buf), native); + bool valid = to_utf8::convert(quoted, {buf.data(), buf.size()}); + FMT_ASSERT(valid, "invalid utf16"); + } else if constexpr (std::is_same_v) { + write_escaped_string( + std::back_inserter(quoted), native); + } else { + write_escaped_string(std::back_inserter(quoted), p.string()); + } } } // namespace detail -FMT_MODULE_EXPORT -template -struct formatter - : formatter> { +FMT_EXPORT +template struct formatter { + private: + format_specs specs_; + detail::arg_ref width_ref_; + bool debug_ = false; + char path_type_ = 0; + + public: + FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; } + template FMT_CONSTEXPR auto parse(ParseContext& ctx) { - auto out = formatter>::parse(ctx); - this->set_debug_format(false); - return out; + auto it = ctx.begin(), end = ctx.end(); + if (it == end) return it; + + it = detail::parse_align(it, end, specs_); + if (it == end) return it; + + it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx); + if (it != end && *it == '?') { + debug_ = true; + ++it; + } + if (it != end && (*it == 'g')) path_type_ = *it++; + return it; } + template - auto format(const std::filesystem::path& p, FormatContext& ctx) const -> - typename FormatContext::iterator { + auto format(const std::filesystem::path& p, FormatContext& ctx) const { + auto specs = specs_; +# ifdef _WIN32 + auto path_string = !path_type_ ? p.native() : p.generic_wstring(); +# else + auto path_string = !path_type_ ? p.native() : p.generic_string(); +# endif + + detail::handle_dynamic_spec(specs.width, width_ref_, + ctx); + if (!debug_) { + auto s = detail::get_path_string(p, path_string); + return detail::write(ctx.out(), basic_string_view(s), specs); + } auto quoted = basic_memory_buffer(); - detail::write_escaped_path(quoted, p); - return formatter>::format( - basic_string_view(quoted.data(), quoted.size()), ctx); + detail::write_escaped_path(quoted, p, path_string); + return detail::write(ctx.out(), + basic_string_view(quoted.data(), quoted.size()), + specs); } }; FMT_END_NAMESPACE -#endif +#endif // FMT_CPP_LIB_FILESYSTEM FMT_BEGIN_NAMESPACE -FMT_MODULE_EXPORT +FMT_EXPORT +template +struct formatter, Char> : nested_formatter { + private: + // Functor because C++11 doesn't support generic lambdas. + struct writer { + const std::bitset& bs; + + template + FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt { + for (auto pos = N; pos > 0; --pos) { + out = detail::write(out, bs[pos - 1] ? Char('1') : Char('0')); + } + + return out; + } + }; + + public: + template + auto format(const std::bitset& bs, FormatContext& ctx) const + -> decltype(ctx.out()) { + return write_padded(ctx, writer{bs}); + } +}; + +FMT_EXPORT template struct formatter : basic_ostream_formatter {}; FMT_END_NAMESPACE #ifdef __cpp_lib_optional FMT_BEGIN_NAMESPACE -FMT_MODULE_EXPORT +FMT_EXPORT template struct formatter, Char, std::enable_if_t::value>> { @@ -132,7 +228,7 @@ struct formatter, Char, } template - auto format(std::optional const& opt, FormatContext& ctx) const + auto format(const std::optional& opt, FormatContext& ctx) const -> decltype(ctx.out()) { if (!opt) return detail::write(ctx.out(), none); @@ -146,24 +242,33 @@ struct formatter, Char, FMT_END_NAMESPACE #endif // __cpp_lib_optional -#ifdef __cpp_lib_variant +#ifdef __cpp_lib_source_location FMT_BEGIN_NAMESPACE -FMT_MODULE_EXPORT -template struct formatter { - template - FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { +FMT_EXPORT +template <> struct formatter { + template FMT_CONSTEXPR auto parse(ParseContext& ctx) { return ctx.begin(); } template - auto format(const std::monostate&, FormatContext& ctx) const + auto format(const std::source_location& loc, FormatContext& ctx) const -> decltype(ctx.out()) { auto out = ctx.out(); - out = detail::write(out, "monostate"); + out = detail::write(out, loc.file_name()); + out = detail::write(out, ':'); + out = detail::write(out, loc.line()); + out = detail::write(out, ':'); + out = detail::write(out, loc.column()); + out = detail::write(out, ": "); + out = detail::write(out, loc.function_name()); return out; } }; +FMT_END_NAMESPACE +#endif +#if FMT_CPP_LIB_VARIANT +FMT_BEGIN_NAMESPACE namespace detail { template @@ -197,6 +302,7 @@ auto write_variant_alternative(OutputIt } } // namespace detail + template struct is_variant_like { static constexpr const bool value = detail::is_variant_like_::value; }; @@ -206,7 +312,21 @@ template struct detail::is_variant_formattable_::value; }; -FMT_MODULE_EXPORT +FMT_EXPORT +template struct formatter { + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const std::monostate&, FormatContext& ctx) const + -> decltype(ctx.out()) { + return detail::write(ctx.out(), "monostate"); + } +}; + +FMT_EXPORT template struct formatter< Variant, Char, @@ -223,13 +343,14 @@ struct formatter< auto out = ctx.out(); out = detail::write(out, "variant("); - try { + FMT_TRY { std::visit( [&](const auto& v) { out = detail::write_variant_alternative(out, v); }, value); - } catch (const std::bad_variant_access&) { + } + FMT_CATCH(const std::bad_variant_access&) { detail::write(out, "valueless by exception"); } *out++ = ')'; @@ -237,10 +358,10 @@ struct formatter< } }; FMT_END_NAMESPACE -#endif // __cpp_lib_variant +#endif // FMT_CPP_LIB_VARIANT FMT_BEGIN_NAMESPACE -FMT_MODULE_EXPORT +FMT_EXPORT template struct formatter { template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { @@ -258,10 +379,10 @@ template struct formatte } }; -FMT_MODULE_EXPORT +FMT_EXPORT template struct formatter< - T, Char, + T, Char, // DEPRECATED! Mixing code unit types. typename std::enable_if::value>::type> { private: bool with_typename_ = false; @@ -274,7 +395,7 @@ struct formatter< if (it == end || *it == '}') return it; if (*it == 't') { ++it; - with_typename_ = true; + with_typename_ = FMT_USE_TYPEID != 0; } return it; } @@ -287,11 +408,12 @@ struct formatter< if (!with_typename_) return detail::write_bytes(out, string_view(ex.what()), spec); +#if FMT_USE_TYPEID const std::type_info& ti = typeid(ex); -#ifdef FMT_HAS_ABI_CXA_DEMANGLE +# ifdef FMT_HAS_ABI_CXA_DEMANGLE int status = 0; std::size_t size = 0; - std::unique_ptr demangled_name_ptr( + std::unique_ptr demangled_name_ptr( abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free); string_view demangled_name_view; @@ -327,23 +449,89 @@ struct formatter< demangled_name_view = string_view(ti.name()); } out = detail::write_bytes(out, demangled_name_view, spec); -#elif FMT_MSC_VERSION +# elif FMT_MSC_VERSION string_view demangled_name_view(ti.name()); if (demangled_name_view.starts_with("class ")) demangled_name_view.remove_prefix(6); else if (demangled_name_view.starts_with("struct ")) demangled_name_view.remove_prefix(7); out = detail::write_bytes(out, demangled_name_view, spec); -#else +# else out = detail::write_bytes(out, string_view(ti.name()), spec); +# endif + *out++ = ':'; + *out++ = ' '; + return detail::write_bytes(out, string_view(ex.what()), spec); #endif - out = detail::write(out, Char(':')); - out = detail::write(out, Char(' ')); - out = detail::write_bytes(out, string_view(ex.what()), spec); - - return out; } }; -FMT_END_NAMESPACE + +namespace detail { + +template +struct has_flip : std::false_type {}; + +template +struct has_flip().flip())>> + : std::true_type {}; + +template struct is_bit_reference_like { + static constexpr const bool value = + std::is_convertible::value && + std::is_nothrow_assignable::value && has_flip::value; +}; + +#ifdef _LIBCPP_VERSION + +// Workaround for libc++ incompatibility with C++ standard. +// According to the Standard, `bitset::operator[] const` returns bool. +template +struct is_bit_reference_like> { + static constexpr const bool value = true; +}; + +#endif + +} // namespace detail +// We can't use std::vector::reference and +// std::bitset::reference because the compiler can't deduce Allocator and N +// in partial specialization. +FMT_EXPORT +template +struct formatter::value>> + : formatter { + template + FMT_CONSTEXPR auto format(const BitRef& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v, ctx); + } +}; + +FMT_EXPORT +template +struct formatter, Char, + enable_if_t::value>> + : formatter { + template + auto format(const std::atomic& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.load(), ctx); + } +}; + +#ifdef __cpp_lib_atomic_flag_test +FMT_EXPORT +template +struct formatter : formatter { + template + auto format(const std::atomic_flag& v, FormatContext& ctx) const + -> decltype(ctx.out()) { + return formatter::format(v.test(), ctx); + } +}; +#endif // __cpp_lib_atomic_flag_test + +FMT_END_NAMESPACE #endif // FMT_STD_H_