// Formatting library for C++ - formatters for standard library types // // Copyright (c) 2012 - present, Victor Zverovich // All rights reserved. // // For the license information refer to format.h. #ifndef FMT_STD_H_ #define FMT_STD_H_ #include <thread> #include <type_traits> #include <utility> #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> # endif # if FMT_HAS_INCLUDE(<variant>) # include <variant> # endif #endif #ifdef __cpp_lib_filesystem FMT_BEGIN_NAMESPACE namespace detail { template <typename Char> void write_escaped_path(basic_memory_buffer<Char>& quoted, const std::filesystem::path& p) { write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>()); } # ifdef _WIN32 template <> inline void write_escaped_path<char>(basic_memory_buffer<char>& quoted, const std::filesystem::path& p) { auto s = p.u8string(); write_escaped_string<char>( std::back_inserter(quoted), string_view(reinterpret_cast<const char*>(s.c_str()), s.size())); } # endif template <> inline void write_escaped_path<std::filesystem::path::value_type>( basic_memory_buffer<std::filesystem::path::value_type>& quoted, const std::filesystem::path& p) { write_escaped_string<std::filesystem::path::value_type>( std::back_inserter(quoted), p.native()); } } // namespace detail template <typename Char> struct formatter<std::filesystem::path, Char> : formatter<basic_string_view<Char>> { template <typename FormatContext> auto format(const std::filesystem::path& p, FormatContext& ctx) const -> typename FormatContext::iterator { basic_memory_buffer<Char> quoted; detail::write_escaped_path(quoted, p); return formatter<basic_string_view<Char>>::format( basic_string_view<Char>(quoted.data(), quoted.size()), ctx); } }; FMT_END_NAMESPACE #endif FMT_BEGIN_NAMESPACE template <typename Char> struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {}; FMT_END_NAMESPACE #ifdef __cpp_lib_variant FMT_BEGIN_NAMESPACE template <typename Char> struct formatter<std::monostate, Char> { template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } template <typename FormatContext> auto format(const std::monostate&, FormatContext& ctx) const -> decltype(ctx.out()) { auto out = ctx.out(); out = detail::write<Char>(out, "monostate"); return out; } }; namespace detail { template <typename T> using variant_index_sequence = std::make_index_sequence<std::variant_size<T>::value>; // variant_size and variant_alternative check. template <typename T, typename U = void> struct is_variant_like_ : std::false_type {}; template <typename T> struct is_variant_like_<T, std::void_t<decltype(std::variant_size<T>::value)>> : std::true_type {}; // formattable element check template <typename T, typename C> class is_variant_formattable_ { template <std::size_t... I> static std::conjunction< is_formattable<std::variant_alternative_t<I, T>, C>...> check(std::index_sequence<I...>); public: static constexpr const bool value = 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 { static constexpr const bool value = detail::is_variant_like_<T>::value; }; template <typename T, typename C> struct is_variant_formattable { static constexpr const bool value = detail::is_variant_formattable_<T, C>::value; }; template <typename Variant, typename Char> struct formatter< Variant, Char, std::enable_if_t<std::conjunction_v< is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> { template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { return ctx.begin(); } template <typename FormatContext> auto format(const Variant& value, FormatContext& ctx) const -> decltype(ctx.out()) { auto out = ctx.out(); out = detail::write<Char>(out, "variant("); std::visit( [&](const auto& v) { out = detail::write_variant_alternative<Char>(out, v); }, value); *out++ = ')'; return out; } }; FMT_END_NAMESPACE #endif #endif // FMT_STD_H_