diff options
| author | Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> | 2024-12-06 20:09:31 +0200 |
|---|---|---|
| committer | Dirk-Jan C. Binnema <djcb@djcbsoftware.nl> | 2024-12-06 20:09:31 +0200 |
| commit | 030daeed5269be173cec2768124cfbc8059704ba (patch) | |
| tree | c96053cfd02c88042708f55bf30624bd349d9e76 /thirdparty/fmt/std.h | |
| parent | 6166b435d2bfa4e8c12bcf78a44d7bdc7baa90cb (diff) | |
thirdparty/fmt: bump to 11.0.2
Diffstat (limited to 'thirdparty/fmt/std.h')
| -rw-r--r-- | thirdparty/fmt/std.h | 394 |
1 files changed, 278 insertions, 116 deletions
diff --git a/thirdparty/fmt/std.h b/thirdparty/fmt/std.h index 7cff115..fb43940 100644 --- a/thirdparty/fmt/std.h +++ b/thirdparty/fmt/std.h @@ -8,38 +8,46 @@ #ifndef FMT_STD_H_ #define FMT_STD_H_ -#include <atomic> -#include <bitset> -#include <cstdlib> -#include <exception> -#include <memory> -#include <thread> -#include <type_traits> -#include <typeinfo> -#include <utility> -#include <vector> - #include "format.h" #include "ostream.h" -#if FMT_HAS_INCLUDE(<version>) -# include <version> -#endif -// Checking FMT_CPLUSPLUS for warning suppression in MSVC. -#if FMT_CPLUSPLUS >= 201703L -# if FMT_HAS_INCLUDE(<filesystem>) -# include <filesystem> +#ifndef FMT_MODULE +# include <atomic> +# include <bitset> +# include <complex> +# include <cstdlib> +# include <exception> +# include <memory> +# include <thread> +# include <type_traits> +# include <typeinfo> +# include <utility> +# include <vector> + +// Check FMT_CPLUSPLUS to suppress a bogus warning in MSVC. +# if FMT_CPLUSPLUS >= 201703L +# if FMT_HAS_INCLUDE(<filesystem>) +# include <filesystem> +# endif +# if FMT_HAS_INCLUDE(<variant>) +# include <variant> +# endif +# if FMT_HAS_INCLUDE(<optional>) +# include <optional> +# endif # endif -# if FMT_HAS_INCLUDE(<variant>) -# include <variant> +// Use > instead of >= in the version check because <source_location> may be +// available after C++17 but before C++20 is marked as implemented. +# if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<source_location>) +# include <source_location> # endif -# if FMT_HAS_INCLUDE(<optional>) -# include <optional> +# if FMT_CPLUSPLUS > 202002L && FMT_HAS_INCLUDE(<expected>) +# include <expected> # endif -#endif +#endif // FMT_MODULE -#if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<source_location>) -# include <source_location> +#if FMT_HAS_INCLUDE(<version>) +# include <version> #endif // GCC 4 does not support FMT_HAS_INCLUDE. @@ -52,17 +60,6 @@ # endif #endif -// 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 @@ -117,7 +114,7 @@ void write_escaped_path(basic_memory_buffer<Char>& quoted, FMT_EXPORT template <typename Char> struct formatter<std::filesystem::path, Char> { private: - format_specs<Char> specs_; + format_specs specs_; detail::arg_ref<Char> width_ref_; bool debug_ = false; char path_type_ = 0; @@ -137,18 +134,16 @@ template <typename Char> struct formatter<std::filesystem::path, Char> { debug_ = true; ++it; } - if (it != end && (*it == 'g')) path_type_ = *it++; + if (it != end && (*it == 'g')) path_type_ = detail::to_ascii(*it++); return it; } template <typename FormatContext> 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 + auto path_string = + !path_type_ ? p.native() + : p.generic_string<std::filesystem::path::value_type>(); detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_, ctx); @@ -163,6 +158,22 @@ template <typename Char> struct formatter<std::filesystem::path, Char> { specs); } }; + +class path : public std::filesystem::path { + public: + auto display_string() const -> std::string { + const std::filesystem::path& base = *this; + return fmt::format(FMT_STRING("{}"), base); + } + auto system_string() const -> std::string { return string(); } + + auto generic_display_string() const -> std::string { + const std::filesystem::path& base = *this; + return fmt::format(FMT_STRING("{:g}"), base); + } + auto generic_system_string() const -> std::string { return generic_string(); } +}; + FMT_END_NAMESPACE #endif // FMT_CPP_LIB_FILESYSTEM @@ -242,6 +253,56 @@ struct formatter<std::optional<T>, Char, FMT_END_NAMESPACE #endif // __cpp_lib_optional +#if defined(__cpp_lib_expected) || FMT_CPP_LIB_VARIANT + +FMT_BEGIN_NAMESPACE +namespace detail { + +template <typename Char, typename OutputIt, typename T> +auto write_escaped_alternative(OutputIt out, const T& v) -> OutputIt { + if constexpr (has_to_string_view<T>::value) + return write_escaped_string<Char>(out, detail::to_string_view(v)); + if constexpr (std::is_same_v<T, Char>) return write_escaped_char(out, v); + return write<Char>(out, v); +} + +} // namespace detail + +FMT_END_NAMESPACE +#endif + +#ifdef __cpp_lib_expected +FMT_BEGIN_NAMESPACE + +FMT_EXPORT +template <typename T, typename E, typename Char> +struct formatter<std::expected<T, E>, Char, + std::enable_if_t<is_formattable<T, Char>::value && + is_formattable<E, Char>::value>> { + template <typename ParseContext> + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template <typename FormatContext> + auto format(const std::expected<T, E>& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + + if (value.has_value()) { + out = detail::write<Char>(out, "expected("); + out = detail::write_escaped_alternative<Char>(out, *value); + } else { + out = detail::write<Char>(out, "unexpected("); + out = detail::write_escaped_alternative<Char>(out, value.error()); + } + *out++ = ')'; + return out; + } +}; +FMT_END_NAMESPACE +#endif // __cpp_lib_expected + #ifdef __cpp_lib_source_location FMT_BEGIN_NAMESPACE FMT_EXPORT @@ -291,16 +352,6 @@ template <typename T, typename C> class is_variant_formattable_ { decltype(check(variant_index_sequence<T>{}))::value; }; -template <typename Char, typename OutputIt, typename T> -auto write_variant_alternative(OutputIt out, const T& v) -> OutputIt { - if constexpr (is_string<T>::value) - return write_escaped_string<Char>(out, detail::to_string_view(v)); - else if constexpr (std::is_same_v<T, Char>) - return write_escaped_char(out, v); - else - return write<Char>(out, v); -} - } // namespace detail template <typename T> struct is_variant_like { @@ -346,7 +397,7 @@ struct formatter< FMT_TRY { std::visit( [&](const auto& v) { - out = detail::write_variant_alternative<Char>(out, v); + out = detail::write_escaped_alternative<Char>(out, v); }, value); } @@ -372,13 +423,102 @@ template <typename Char> struct formatter<std::error_code, Char> { FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const -> decltype(ctx.out()) { auto out = ctx.out(); - out = detail::write_bytes(out, ec.category().name(), format_specs<Char>()); + out = detail::write_bytes<Char>(out, ec.category().name(), format_specs()); out = detail::write<Char>(out, Char(':')); out = detail::write<Char>(out, ec.value()); return out; } }; +#if FMT_USE_RTTI +namespace detail { + +template <typename Char, typename OutputIt> +auto write_demangled_name(OutputIt out, const std::type_info& ti) -> OutputIt { +# ifdef FMT_HAS_ABI_CXA_DEMANGLE + int status = 0; + std::size_t size = 0; + std::unique_ptr<char, void (*)(void*)> demangled_name_ptr( + abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free); + + string_view demangled_name_view; + if (demangled_name_ptr) { + demangled_name_view = demangled_name_ptr.get(); + + // Normalization of stdlib inline namespace names. + // libc++ inline namespaces. + // std::__1::* -> std::* + // std::__1::__fs::* -> std::* + // libstdc++ inline namespaces. + // std::__cxx11::* -> std::* + // std::filesystem::__cxx11::* -> std::filesystem::* + if (demangled_name_view.starts_with("std::")) { + char* begin = demangled_name_ptr.get(); + char* to = begin + 5; // std:: + for (char *from = to, *end = begin + demangled_name_view.size(); + from < end;) { + // This is safe, because demangled_name is NUL-terminated. + if (from[0] == '_' && from[1] == '_') { + char* next = from + 1; + while (next < end && *next != ':') next++; + if (next[0] == ':' && next[1] == ':') { + from = next + 2; + continue; + } + } + *to++ = *from++; + } + demangled_name_view = {begin, detail::to_unsigned(to - begin)}; + } + } else { + demangled_name_view = string_view(ti.name()); + } + return detail::write_bytes<Char>(out, demangled_name_view); +# elif FMT_MSC_VERSION + const string_view demangled_name(ti.name()); + for (std::size_t i = 0; i < demangled_name.size(); ++i) { + auto sub = demangled_name; + sub.remove_prefix(i); + if (sub.starts_with("enum ")) { + i += 4; + continue; + } + if (sub.starts_with("class ") || sub.starts_with("union ")) { + i += 5; + continue; + } + if (sub.starts_with("struct ")) { + i += 6; + continue; + } + if (*sub.begin() != ' ') *out++ = *sub.begin(); + } + return out; +# else + return detail::write_bytes<Char>(out, string_view(ti.name())); +# endif +} + +} // namespace detail + +FMT_EXPORT +template <typename Char> +struct formatter<std::type_info, Char // DEPRECATED! Mixing code unit types. + > { + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) + -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template <typename Context> + auto format(const std::type_info& ti, Context& ctx) const + -> decltype(ctx.out()) { + return detail::write_demangled_name<Char>(ctx.out(), ti); + } +}; +#endif + FMT_EXPORT template <typename T, typename Char> struct formatter< @@ -395,74 +535,23 @@ struct formatter< if (it == end || *it == '}') return it; if (*it == 't') { ++it; - with_typename_ = FMT_USE_TYPEID != 0; + with_typename_ = FMT_USE_RTTI != 0; } return it; } - template <typename OutputIt> - auto format(const std::exception& ex, - basic_format_context<OutputIt, Char>& ctx) const -> OutputIt { - format_specs<Char> spec; + template <typename Context> + auto format(const std::exception& ex, Context& ctx) const + -> decltype(ctx.out()) { auto out = ctx.out(); - 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 - int status = 0; - std::size_t size = 0; - std::unique_ptr<char, void (*)(void*)> demangled_name_ptr( - abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free); - - string_view demangled_name_view; - if (demangled_name_ptr) { - demangled_name_view = demangled_name_ptr.get(); - - // Normalization of stdlib inline namespace names. - // libc++ inline namespaces. - // std::__1::* -> std::* - // std::__1::__fs::* -> std::* - // libstdc++ inline namespaces. - // std::__cxx11::* -> std::* - // std::filesystem::__cxx11::* -> std::filesystem::* - if (demangled_name_view.starts_with("std::")) { - char* begin = demangled_name_ptr.get(); - char* to = begin + 5; // std:: - for (char *from = to, *end = begin + demangled_name_view.size(); - from < end;) { - // This is safe, because demangled_name is NUL-terminated. - if (from[0] == '_' && from[1] == '_') { - char* next = from + 1; - while (next < end && *next != ':') next++; - if (next[0] == ':' && next[1] == ':') { - from = next + 2; - continue; - } - } - *to++ = *from++; - } - demangled_name_view = {begin, detail::to_unsigned(to - begin)}; - } - } else { - demangled_name_view = string_view(ti.name()); +#if FMT_USE_RTTI + if (with_typename_) { + out = detail::write_demangled_name<Char>(out, typeid(ex)); + *out++ = ':'; + *out++ = ' '; } - out = detail::write_bytes(out, demangled_name_view, spec); -# 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 - out = detail::write_bytes(out, string_view(ti.name()), spec); -# endif - *out++ = ':'; - *out++ = ' '; - return detail::write_bytes(out, string_view(ex.what()), spec); #endif + return detail::write_bytes<Char>(out, string_view(ex.what())); } }; @@ -509,6 +598,14 @@ struct formatter<BitRef, Char, } }; +template <typename T, typename Deleter> +auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* { + return p.get(); +} +template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* { + return p.get(); +} + FMT_EXPORT template <typename T, typename Char> struct formatter<std::atomic<T>, Char, @@ -533,5 +630,70 @@ struct formatter<std::atomic_flag, Char> : formatter<bool, Char> { }; #endif // __cpp_lib_atomic_flag_test +FMT_EXPORT +template <typename T, typename Char> struct formatter<std::complex<T>, Char> { + private: + detail::dynamic_format_specs<Char> specs_; + + template <typename FormatContext, typename OutputIt> + FMT_CONSTEXPR auto do_format(const std::complex<T>& c, + detail::dynamic_format_specs<Char>& specs, + FormatContext& ctx, OutputIt out) const + -> OutputIt { + if (c.real() != 0) { + *out++ = Char('('); + out = detail::write<Char>(out, c.real(), specs, ctx.locale()); + specs.sign = sign::plus; + out = detail::write<Char>(out, c.imag(), specs, ctx.locale()); + if (!detail::isfinite(c.imag())) *out++ = Char(' '); + *out++ = Char('i'); + *out++ = Char(')'); + return out; + } + out = detail::write<Char>(out, c.imag(), specs, ctx.locale()); + if (!detail::isfinite(c.imag())) *out++ = Char(' '); + *out++ = Char('i'); + return out; + } + + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) + -> decltype(ctx.begin()) { + if (ctx.begin() == ctx.end() || *ctx.begin() == '}') return ctx.begin(); + return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, + detail::type_constant<T, Char>::value); + } + + template <typename FormatContext> + auto format(const std::complex<T>& c, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto specs = specs_; + if (specs.width_ref.kind != detail::arg_id_kind::none || + specs.precision_ref.kind != detail::arg_id_kind::none) { + detail::handle_dynamic_spec<detail::width_checker>(specs.width, + specs.width_ref, ctx); + detail::handle_dynamic_spec<detail::precision_checker>( + specs.precision, specs.precision_ref, ctx); + } + + if (specs.width == 0) return do_format(c, specs, ctx, ctx.out()); + auto buf = basic_memory_buffer<Char>(); + + auto outer_specs = format_specs(); + outer_specs.width = specs.width; + outer_specs.fill = specs.fill; + outer_specs.align = specs.align; + + specs.width = 0; + specs.fill = {}; + specs.align = align::none; + + do_format(c, specs, ctx, basic_appender<Char>(buf)); + return detail::write<Char>(ctx.out(), + basic_string_view<Char>(buf.data(), buf.size()), + outer_specs); + } +}; + FMT_END_NAMESPACE #endif // FMT_STD_H_ |
