From 543671e53804cb06789a0ca019896e3093e6d988 Mon Sep 17 00:00:00 2001 From: actboy168 Date: Tue, 25 Jun 2024 21:39:10 +0800 Subject: [PATCH] update fmt --- 3rd/fmt/fmt/args.h | 107 +++++------ 3rd/fmt/fmt/base.h | 385 +++++++++++++++++++-------------------- 3rd/fmt/fmt/chrono.h | 143 +++++++-------- 3rd/fmt/fmt/color.h | 102 +++++------ 3rd/fmt/fmt/compile.h | 100 +++++----- 3rd/fmt/fmt/format-inl.h | 29 +-- 3rd/fmt/fmt/format.h | 304 ++++++++++++++----------------- 3rd/fmt/fmt/os.h | 161 +++++++--------- 3rd/fmt/fmt/ostream.h | 34 ++-- 3rd/fmt/fmt/printf.h | 65 +++---- 3rd/fmt/fmt/ranges.h | 369 ++++++++++++++++++++++--------------- 3rd/fmt/fmt/std.h | 211 ++++++++++++--------- 3rd/fmt/fmt/xchar.h | 27 ++- 13 files changed, 1006 insertions(+), 1031 deletions(-) diff --git a/3rd/fmt/fmt/args.h b/3rd/fmt/fmt/args.h index 71c3bb90..31a60e8f 100644 --- a/3rd/fmt/fmt/args.h +++ b/3rd/fmt/fmt/args.h @@ -8,7 +8,7 @@ #ifndef FMT_ARGS_H_ #define FMT_ARGS_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include // std::reference_wrapper # include // std::unique_ptr # include @@ -30,15 +30,18 @@ auto unwrap(const std::reference_wrapper& v) -> const T& { return static_cast(v); } -class dynamic_arg_list { - // Workaround for clang's -Wweak-vtables. Unlike for regular classes, for - // templates it doesn't complain about inability to deduce single translation - // unit for placing vtable. So storage_node_base is made a fake template. - template struct node { - virtual ~node() = default; - std::unique_ptr> next; - }; +// node is defined outside dynamic_arg_list to workaround a C2504 bug in MSVC +// 2022 (v17.10.0). +// +// Workaround for clang's -Wweak-vtables. Unlike for regular classes, for +// templates it doesn't complain about inability to deduce single translation +// unit for placing vtable. So node is made a fake template. +template struct node { + virtual ~node() = default; + std::unique_ptr> next; +}; +class dynamic_arg_list { template struct typed_node : node<> { T value; @@ -64,14 +67,10 @@ class dynamic_arg_list { } // namespace detail /** - \rst - A dynamic version of `fmt::format_arg_store`. - It's equipped with a storage to potentially temporary objects which lifetimes - could be shorter than the format arguments object. - - It can be implicitly converted into `~fmt::basic_format_args` for passing - into type-erased formatting functions such as `~fmt::vformat`. - \endrst + * A dynamic list of formatting arguments with storage. + * + * It can be implicitly converted into `fmt::basic_format_args` for passing + * into type-erased formatting functions such as `fmt::vformat`. */ template class dynamic_format_arg_store @@ -149,22 +148,20 @@ class dynamic_format_arg_store constexpr dynamic_format_arg_store() = default; /** - \rst - Adds an argument into the dynamic store for later passing to a formatting - function. - - Note that custom types and string types (but not string views) are copied - into the store dynamically allocating memory if necessary. - - **Example**:: - - fmt::dynamic_format_arg_store store; - store.push_back(42); - store.push_back("abc"); - store.push_back(1.5f); - std::string result = fmt::vformat("{} and {} and {}", store); - \endrst - */ + * Adds an argument into the dynamic store for later passing to a formatting + * function. + * + * Note that custom types and string types (but not string views) are copied + * into the store dynamically allocating memory if necessary. + * + * **Example**: + * + * fmt::dynamic_format_arg_store store; + * store.push_back(42); + * store.push_back("abc"); + * store.push_back(1.5f); + * std::string result = fmt::vformat("{} and {} and {}", store); + */ template void push_back(const T& arg) { if (detail::const_check(need_copy::value)) emplace_arg(dynamic_args_.push>(arg)); @@ -173,20 +170,18 @@ class dynamic_format_arg_store } /** - \rst - Adds a reference to the argument into the dynamic store for later passing to - a formatting function. - - **Example**:: - - fmt::dynamic_format_arg_store store; - char band[] = "Rolling Stones"; - store.push_back(std::cref(band)); - band[9] = 'c'; // Changing str affects the output. - std::string result = fmt::vformat("{}", store); - // result == "Rolling Scones" - \endrst - */ + * Adds a reference to the argument into the dynamic store for later passing + * to a formatting function. + * + * **Example**: + * + * fmt::dynamic_format_arg_store store; + * char band[] = "Rolling Stones"; + * store.push_back(std::cref(band)); + * band[9] = 'c'; // Changing str affects the output. + * std::string result = fmt::vformat("{}", store); + * // result == "Rolling Scones" + */ template void push_back(std::reference_wrapper arg) { static_assert( need_copy::value, @@ -195,10 +190,10 @@ class dynamic_format_arg_store } /** - Adds named argument into the dynamic store for later passing to a formatting - function. ``std::reference_wrapper`` is supported to avoid copying of the - argument. The name is always copied into the store. - */ + * Adds named argument into the dynamic store for later passing to a + * formatting function. `std::reference_wrapper` is supported to avoid + * copying of the argument. The name is always copied into the store. + */ template void push_back(const detail::named_arg& arg) { const char_type* arg_name = @@ -211,19 +206,15 @@ class dynamic_format_arg_store } } - /** Erase all elements from the store */ + /// Erase all elements from the store. void clear() { data_.clear(); named_info_.clear(); dynamic_args_ = detail::dynamic_arg_list(); } - /** - \rst - Reserves space to store at least *new_cap* arguments including - *new_cap_named* named arguments. - \endrst - */ + /// Reserves space to store at least `new_cap` arguments including + /// `new_cap_named` named arguments. void reserve(size_t new_cap, size_t new_cap_named) { FMT_ASSERT(new_cap >= new_cap_named, "Set of arguments includes set of named arguments"); diff --git a/3rd/fmt/fmt/base.h b/3rd/fmt/fmt/base.h index 26d7da2b..2ba23d5a 100644 --- a/3rd/fmt/fmt/base.h +++ b/3rd/fmt/fmt/base.h @@ -8,16 +8,19 @@ #ifndef FMT_BASE_H_ #define FMT_BASE_H_ -#include // CHAR_BIT -#include // FILE -#include // strlen +#if defined(FMT_IMPORT_STD) && !defined(FMT_MODULE) +# define FMT_MODULE +#endif + +// c headers are preferable for performance reasons +#ifndef FMT_MODULE +# include // CHAR_BIT +# include // FILE +# include // strlen -#ifndef FMT_IMPORT_STD // is also included transitively from . # include // std::byte # include // std::enable_if -#else -import std; #endif // The fmt library version in the form major * 10000 + minor * 100 + patch. @@ -145,10 +148,20 @@ import std; #elif defined(__cpp_nontype_template_args) && \ __cpp_nontype_template_args >= 201911L # define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 +#elif FMT_CLANG_VERSION >= 1200 && FMT_CPLUSPLUS >= 202002L +# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1 #else # define FMT_USE_NONTYPE_TEMPLATE_ARGS 0 #endif +#ifdef FMT_USE_CONCEPTS +// Use the provided definition. +#elif defined(__cpp_concepts) +# define FMT_USE_CONCEPTS 1 +#else +# define FMT_USE_CONCEPTS 0 +#endif + // Check if exceptions are disabled. #ifdef FMT_EXCEPTIONS // Use the provided definition. @@ -276,7 +289,18 @@ import std; #endif #ifndef FMT_UNICODE -# define FMT_UNICODE !FMT_MSC_VERSION +# define FMT_UNICODE 1 +#endif + +// Check if rtti is available. +#ifndef FMT_USE_RTTI +// __RTTI is for EDG compilers. _CPPRTTI is for MSVC. +# if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \ + defined(__INTEL_RTTI__) || defined(__RTTI) +# define FMT_USE_RTTI 1 +# else +# define FMT_USE_RTTI 0 +# endif #endif #define FMT_FWD(...) static_cast(__VA_ARGS__) @@ -371,17 +395,17 @@ template constexpr auto const_check(T value) -> T { return value; } FMT_NORETURN FMT_API void assert_fail(const char* file, int line, const char* message); -#ifndef FMT_ASSERT -# ifdef NDEBUG +#if defined(FMT_ASSERT) +// Use the provided definition. +#elif defined(NDEBUG) // FMT_ASSERT is not empty to avoid -Wempty-body. -# define FMT_ASSERT(condition, message) \ - fmt::detail::ignore_unused((condition), (message)) -# else -# define FMT_ASSERT(condition, message) \ - ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ - ? (void)0 \ - : fmt::detail::assert_fail(__FILE__, __LINE__, (message))) -# endif +# define FMT_ASSERT(condition, message) \ + fmt::detail::ignore_unused((condition), (message)) +#else +# define FMT_ASSERT(condition, message) \ + ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \ + ? (void)0 \ + : fmt::detail::assert_fail(__FILE__, __LINE__, (message))) #endif #ifdef FMT_USE_INT128 @@ -420,13 +444,19 @@ struct is_std_string_like().find_first_of( typename T::value_type(), 0))>> : std::true_type {}; -FMT_CONSTEXPR inline auto is_utf8() -> bool { - FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char section[] = "\u00A7"; +// Returns true iff the literal encoding is UTF-8. +constexpr auto is_utf8_enabled() -> bool { // Avoid an MSVC sign extension bug: https://github.com/fmtlib/fmt/pull/2297. using uchar = unsigned char; - return FMT_UNICODE || (sizeof(section) == 3 && uchar(section[0]) == 0xC2 && - uchar(section[1]) == 0xA7); + return sizeof("\u00A7") == 3 && uchar("\u00A7"[0]) == 0xC2 && + uchar("\u00A7"[1]) == 0xA7; } +constexpr auto use_utf8() -> bool { + return !FMT_MSC_VERSION || is_utf8_enabled(); +} + +static_assert(!FMT_UNICODE || use_utf8(), + "Unicode support requires compiling with /utf-8"); template FMT_CONSTEXPR auto length(const Char* s) -> size_t { size_t len = 0; @@ -468,11 +498,11 @@ inline auto get_container(OutputIt it) -> typename OutputIt::container_type& { template struct is_contiguous : std::false_type {}; /** - An implementation of ``std::basic_string_view`` for pre-C++17. It provides a - subset of the API. ``fmt::basic_string_view`` is used for format strings even - if ``std::string_view`` is available to prevent issues when a library is - compiled with a different ``-std`` option than the client code (which is not - recommended). + * An implementation of `std::basic_string_view` for pre-C++17. It provides a + * subset of the API. `fmt::basic_string_view` is used for format strings even + * if `std::basic_string_view` is available to prevent issues when a library is + * compiled with a different `-std` option than the client code (which is not + * recommended). */ FMT_EXPORT template class basic_string_view { @@ -486,15 +516,13 @@ template class basic_string_view { constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {} - /** Constructs a string reference object from a C string and a size. */ + /// Constructs a string reference object from a C string and a size. constexpr basic_string_view(const Char* s, size_t count) noexcept : data_(s), size_(count) {} constexpr basic_string_view(std::nullptr_t) = delete; - /** - Constructs a string reference object from a C string. - */ + /// Constructs a string reference object from a C string. FMT_CONSTEXPR20 basic_string_view(const Char* s) : data_(s), @@ -503,20 +531,18 @@ template class basic_string_view { ? strlen(reinterpret_cast(s)) : detail::length(s)) {} - /** - Constructs a string reference from a ``std::basic_string`` or a - ``std::basic_string_view`` object. - */ + /// Constructs a string reference from a `std::basic_string` or a + /// `std::basic_string_view` object. template ::value&& std::is_same< typename S::value_type, Char>::value)> FMT_CONSTEXPR basic_string_view(const S& s) noexcept : data_(s.data()), size_(s.size()) {} - /** Returns a pointer to the string data. */ + /// Returns a pointer to the string data. constexpr auto data() const noexcept -> const Char* { return data_; } - /** Returns the string size. */ + /// Returns the string size. constexpr auto size() const noexcept -> size_t { return size_; } constexpr auto begin() const noexcept -> iterator { return data_; } @@ -575,7 +601,7 @@ template class basic_string_view { FMT_EXPORT using string_view = basic_string_view; -/** Specifies if ``T`` is a character type. Can be specialized by users. */ +/// Specifies if `T` is a character type. Can be specialized by users. FMT_EXPORT template struct is_char : std::false_type {}; template <> struct is_char : std::true_type {}; @@ -693,10 +719,8 @@ enum { }; } // namespace detail -/** - Reports a format error at compile time or, via a ``format_error`` exception, - at runtime. - */ +/// Reports a format error at compile time or, via a `format_error` exception, +/// at runtime. // This function is intentionally not constexpr to give a compile-time error. FMT_NORETURN FMT_API void report_error(const char* message); @@ -705,17 +729,15 @@ FMT_DEPRECATED FMT_NORETURN inline void throw_format_error( report_error(message); } -/** String's character (code unit) type. */ +/// String's character (code unit) type. template ()))> using char_t = typename V::value_type; /** - \rst - Parsing context consisting of a format string range being parsed and an - argument counter for automatic indexing. - You can use the ``format_parse_context`` type alias for ``char`` instead. - \endrst + * Parsing context consisting of a format string range being parsed and an + * argument counter for automatic indexing. + * You can use the `format_parse_context` type alias for `char` instead. */ FMT_EXPORT template class basic_format_parse_context { @@ -733,28 +755,22 @@ template class basic_format_parse_context { basic_string_view format_str, int next_arg_id = 0) : format_str_(format_str), next_arg_id_(next_arg_id) {} - /** - Returns an iterator to the beginning of the format string range being - parsed. - */ + /// Returns an iterator to the beginning of the format string range being + /// parsed. constexpr auto begin() const noexcept -> iterator { return format_str_.begin(); } - /** - Returns an iterator past the end of the format string range being parsed. - */ + /// Returns an iterator past the end of the format string range being parsed. constexpr auto end() const noexcept -> iterator { return format_str_.end(); } - /** Advances the begin iterator to ``it``. */ + /// Advances the begin iterator to `it`. FMT_CONSTEXPR void advance_to(iterator it) { format_str_.remove_prefix(detail::to_unsigned(it - begin())); } - /** - Reports an error if using the manual argument indexing; otherwise returns - the next argument index and switches to the automatic indexing. - */ + /// Reports an error if using the manual argument indexing; otherwise returns + /// the next argument index and switches to the automatic indexing. FMT_CONSTEXPR auto next_arg_id() -> int { if (next_arg_id_ < 0) { report_error("cannot switch from manual to automatic argument indexing"); @@ -765,10 +781,8 @@ template class basic_format_parse_context { return id; } - /** - Reports an error if using the automatic argument indexing; otherwise - switches to the manual indexing. - */ + /// Reports an error if using the automatic argument indexing; otherwise + /// switches to the manual indexing. FMT_CONSTEXPR void check_arg_id(int id) { if (next_arg_id_ > 0) { report_error("cannot switch from automatic to manual argument indexing"); @@ -823,12 +837,8 @@ class compile_parse_context : public basic_format_parse_context { } }; -/** - \rst - A contiguous memory buffer with an optional growing ability. It is an internal - class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`. - \endrst - */ +/// A contiguous memory buffer with an optional growing ability. It is an +/// internal class and shouldn't be used directly, only via `memory_buffer`. template class buffer { private: T* ptr_; @@ -851,7 +861,7 @@ template class buffer { FMT_CONSTEXPR20 ~buffer() = default; buffer(buffer&&) = default; - /** Sets the buffer data and capacity. */ + /// Sets the buffer data and capacity. FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept { ptr_ = buf_data; capacity_ = buf_capacity; @@ -870,27 +880,27 @@ template class buffer { auto begin() const noexcept -> const T* { return ptr_; } auto end() const noexcept -> const T* { return ptr_ + size_; } - /** Returns the size of this buffer. */ + /// Returns the size of this buffer. constexpr auto size() const noexcept -> size_t { return size_; } - /** Returns the capacity of this buffer. */ + /// Returns the capacity of this buffer. constexpr auto capacity() const noexcept -> size_t { return capacity_; } - /** Returns a pointer to the buffer data (not null-terminated). */ + /// Returns a pointer to the buffer data (not null-terminated). FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; } FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; } - /** Clears this buffer. */ + /// Clears this buffer. void clear() { size_ = 0; } - // Tries resizing the buffer to contain *count* elements. If T is a POD type + // Tries resizing the buffer to contain `count` elements. If T is a POD type // the new elements may not be initialized. FMT_CONSTEXPR void try_resize(size_t count) { try_reserve(count); size_ = count <= capacity_ ? count : capacity_; } - // Tries increasing the buffer capacity to *new_capacity*. It can increase the + // Tries increasing the buffer capacity to `new_capacity`. It can increase the // capacity by a smaller amount than requested but guarantees there is space // for at least one additional element either by increasing the capacity or by // flushing the buffer if it is full. @@ -903,7 +913,7 @@ template class buffer { ptr_[size_++] = value; } - /** Appends data to the end of the buffer. */ + /// Appends data to the end of the buffer. template void append(const U* begin, const U* end) { while (begin != end) { auto count = to_unsigned(end - begin); @@ -1746,12 +1756,10 @@ template class basic_format_arg { } /** - \rst - Visits an argument dispatching to the appropriate visit method based on - the argument type. For example, if the argument type is ``double`` then - ``vis(value)`` will be called with the value of type ``double``. - \endrst - */ + * Visits an argument dispatching to the appropriate visit method based on + * the argument type. For example, if the argument type is `double` then + * `vis(value)` will be called with the value of type `double`. + */ template FMT_CONSTEXPR auto visit(Visitor&& vis) -> decltype(vis(0)) { switch (type_) { @@ -1809,14 +1817,12 @@ FMT_DEPRECATED FMT_CONSTEXPR auto visit_format_arg( } /** - \rst - A view of a collection of formatting arguments. To avoid lifetime issues it - should only be used as a parameter type in type-erased functions such as - ``vformat``:: - - void vlog(string_view format_str, format_args args); // OK - format_args args = make_format_args(); // Error: dangling reference - \endrst + * A view of a collection of formatting arguments. To avoid lifetime issues it + * should only be used as a parameter type in type-erased functions such as + * `vformat`: + * + * void vlog(fmt::string_view fmt, fmt::format_args args); // OK + * fmt::format_args args = fmt::make_format_args(); // Dangling reference */ template class basic_format_args { public: @@ -1855,11 +1861,7 @@ template class basic_format_args { public: constexpr basic_format_args() : desc_(0), args_(nullptr) {} - /** - \rst - Constructs a `basic_format_args` object from `~fmt::format_arg_store`. - \endrst - */ + /// Constructs a `basic_format_args` object from `format_arg_store`. template constexpr FMT_ALWAYS_INLINE basic_format_args( @@ -1874,32 +1876,23 @@ template class basic_format_args { store) : desc_(DESC), args_(store.args + (NUM_NAMED_ARGS != 0 ? 1 : 0)) {} - /** - \rst - Constructs a `basic_format_args` object from - `~fmt::dynamic_format_arg_store`. - \endrst - */ + /// Constructs a `basic_format_args` object from `dynamic_format_arg_store`. constexpr basic_format_args(const dynamic_format_arg_store& store) : desc_(store.get_types()), args_(store.data()) {} - /** - \rst - Constructs a `basic_format_args` object from a dynamic list of arguments. - \endrst - */ + /// Constructs a `basic_format_args` object from a dynamic list of arguments. constexpr basic_format_args(const format_arg* args, int count) : desc_(detail::is_unpacked_bit | detail::to_unsigned(count)), args_(args) {} - /** Returns the argument with the specified id. */ + /// Returns the argument with the specified id. FMT_CONSTEXPR auto get(int id) const -> format_arg { format_arg arg; if (!is_packed()) { if (id < max_size()) arg = args_[id]; return arg; } - if (id >= detail::max_packed_args) return arg; + if (static_cast(id) >= detail::max_packed_args) return arg; arg.type_ = type(id); if (arg.type_ == detail::type::none_type) return arg; arg.value_ = values_[id]; @@ -1938,7 +1931,7 @@ class context { detail::locale_ref loc_; public: - /** The character type for the output. */ + /// The character type for the output. using char_type = char; using iterator = appender; @@ -1946,10 +1939,8 @@ class context { using parse_context_type = basic_format_parse_context; template using formatter_type = formatter; - /** - Constructs a ``basic_format_context`` object. References to the arguments - are stored in the object so make sure they have appropriate lifetimes. - */ + /// Constructs a `basic_format_context` object. References to the arguments + /// are stored in the object so make sure they have appropriate lifetimes. FMT_CONSTEXPR context(iterator out, basic_format_args ctx_args, detail::locale_ref loc = {}) : out_(out), args_(ctx_args), loc_(loc) {} @@ -1967,7 +1958,7 @@ class context { // Returns an iterator to the beginning of the output range. FMT_CONSTEXPR auto out() -> iterator { return out_; } - // Advances the begin iterator to ``it``. + // Advances the begin iterator to `it`. void advance_to(iterator) {} FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } @@ -1990,13 +1981,15 @@ using is_formattable = bool_constant>() .map(std::declval()))>::value>; +#if FMT_USE_CONCEPTS +template +concept formattable = is_formattable, Char>::value; +#endif + /** - \rst - Constructs an object that stores references to arguments and can be implicitly - converted to `~fmt::format_args`. `Context` can be omitted in which case it - defaults to `~fmt::format_context`. See `~fmt::arg` for lifetime - considerations. - \endrst + * Constructs an object that stores references to arguments and can be + * implicitly converted to `format_args`. `Context` can be omitted in which case + * it defaults to `format_context`. See `arg` for lifetime considerations. */ // Take arguments by lvalue references to avoid some lifetime issues, e.g. // auto args = make_format_args(std::string()); @@ -2025,15 +2018,13 @@ constexpr auto make_format_args(T&... args) #endif /** - \rst - Returns a named argument to be used in a formatting function. - It should only be used in a call to a formatting function or - `dynamic_format_arg_store::push_back`. - - **Example**:: - - fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23)); - \endrst + * Returns a named argument to be used in a formatting function. + * It should only be used in a call to a formatting function or + * `dynamic_format_arg_store::push_back`. + * + * **Example**: + * + * fmt::print("The answer is {answer}.", fmt::arg("answer", 42)); */ template inline auto arg(const Char* name, const T& arg) -> detail::named_arg { @@ -2042,7 +2033,7 @@ inline auto arg(const Char* name, const T& arg) -> detail::named_arg { } FMT_END_EXPORT -/** An alias to ``basic_format_args``. */ +/// An alias for `basic_format_args`. // A separate type would result in shorter symbols but break ABI compatibility // between clang and gcc on ARM (#1919). FMT_EXPORT using format_args = basic_format_args; @@ -2787,6 +2778,11 @@ void check_format_string(S format_str) { ignore_unused(error); } +// Report truncation to prevent silent data loss. +inline void report_truncation(bool truncated) { + if (truncated) report_error("output is truncated"); +} + // Use vformat_args and avoid type_identity to keep symbols short and workaround // a GCC <= 4.8 bug. template struct vformat_args { @@ -2847,7 +2843,7 @@ template struct runtime_format_string { basic_string_view str; }; -/** A compile-time format string. */ +/// A compile-time format string. template class basic_format_string { private: basic_string_view str_; @@ -2890,19 +2886,17 @@ inline auto runtime(string_view s) -> string_view { return s; } template using format_string = basic_format_string...>; /** - \rst - Creates a runtime format string. - - **Example**:: - - // Check format string at runtime instead of compile-time. - fmt::print(fmt::runtime("{:d}"), "I am not a number"); - \endrst + * Creates a runtime format string. + * + * **Example**: + * + * // Check format string at runtime instead of compile-time. + * fmt::print(fmt::runtime("{:d}"), "I am not a number"); */ inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; } #endif -/** Formats a string and writes the output to ``out``. */ +/// Formats a string and writes the output to `out`. template , char>::value)> @@ -2914,16 +2908,14 @@ auto vformat_to(OutputIt&& out, string_view fmt, format_args args) } /** - \rst - Formats ``args`` according to specifications in ``fmt``, writes the result to - the output iterator ``out`` and returns the iterator past the end of the output - range. `format_to` does not append a terminating null character. - - **Example**:: - - auto out = std::vector(); - fmt::format_to(std::back_inserter(out), "{}", 42); - \endrst + * Formats `args` according to specifications in `fmt`, writes the result to + * the output iterator `out` and returns the iterator past the end of the output + * range. `format_to` does not append a terminating null character. + * + * **Example**: + * + * auto out = std::vector(); + * fmt::format_to(std::back_inserter(out), "{}", 42); */ template , @@ -2934,9 +2926,9 @@ FMT_INLINE auto format_to(OutputIt&& out, format_string fmt, T&&... args) } template struct format_to_n_result { - /** Iterator past the end of the output range. */ + /// Iterator past the end of the output range. OutputIt out; - /** Total (not truncated) output size. */ + /// Total (not truncated) output size. size_t size; }; @@ -2951,12 +2943,10 @@ auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args) } /** - \rst - Formats ``args`` according to specifications in ``fmt``, writes up to ``n`` - characters of the result to the output iterator ``out`` and returns the total - (not truncated) output size and the iterator past the end of the output range. - `format_to_n` does not append a terminating null character. - \endrst + * Formats `args` according to specifications in `fmt`, writes up to `n` + * characters of the result to the output iterator `out` and returns the total + * (not truncated) output size and the iterator past the end of the output + * range. `format_to_n` does not append a terminating null character. */ template ::value)> @@ -2967,14 +2957,21 @@ FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string fmt, template struct format_to_result { - /** Iterator pointing to just after the last successful write in the range. */ + /// Iterator pointing to just after the last successful write in the range. OutputIt out; - /** Specifies if the output was truncated. */ + /// Specifies if the output was truncated. bool truncated; - FMT_CONSTEXPR operator OutputIt&() & noexcept { return out; } - FMT_CONSTEXPR operator const OutputIt&() const& noexcept { return out; } - FMT_CONSTEXPR operator OutputIt&&() && noexcept { + FMT_CONSTEXPR operator OutputIt&() & { + detail::report_truncation(truncated); + return out; + } + FMT_CONSTEXPR operator const OutputIt&() const& { + detail::report_truncation(truncated); + return out; + } + FMT_CONSTEXPR operator OutputIt&&() && { + detail::report_truncation(truncated); return static_cast(out); } }; @@ -2993,7 +2990,7 @@ FMT_INLINE auto format_to(char (&out)[N], format_string fmt, T&&... args) return {result.out, result.size > N}; } -/** Returns the number of chars in the output of ``format(fmt, args...)``. */ +/// Returns the number of chars in the output of `format(fmt, args...)`. template FMT_NODISCARD FMT_INLINE auto formatted_size(format_string fmt, T&&... args) -> size_t { @@ -3004,60 +3001,52 @@ FMT_NODISCARD FMT_INLINE auto formatted_size(format_string fmt, FMT_API void vprint(string_view fmt, format_args args); FMT_API void vprint(FILE* f, string_view fmt, format_args args); -FMT_API void vprint_locked(FILE* f, string_view fmt, format_args args); +FMT_API void vprint_buffered(FILE* f, string_view fmt, format_args args); FMT_API void vprintln(FILE* f, string_view fmt, format_args args); /** - \rst - Formats ``args`` according to specifications in ``fmt`` and writes the output - to ``stdout``. - - **Example**:: - - fmt::print("Elapsed time: {0:.2f} seconds", 1.23); - \endrst + * Formats `args` according to specifications in `fmt` and writes the output + * to `stdout`. + * + * **Example**: + * + * fmt::print("The answer is {}.", 42); */ template FMT_INLINE void print(format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - if (!detail::is_utf8()) return detail::vprint_mojibake(stdout, fmt, vargs); - return detail::is_locking() ? vprint(fmt, vargs) - : vprint_locked(stdout, fmt, vargs); + if (!detail::use_utf8()) return detail::vprint_mojibake(stdout, fmt, vargs); + return detail::is_locking() ? vprint_buffered(stdout, fmt, vargs) + : vprint(fmt, vargs); } /** - \rst - Formats ``args`` according to specifications in ``fmt`` and writes the - output to the file ``f``. - - **Example**:: - - fmt::print(stderr, "Don't {}!", "panic"); - \endrst + * Formats `args` according to specifications in `fmt` and writes the + * output to the file `f`. + * + * **Example**: + * + * fmt::print(stderr, "Don't {}!", "panic"); */ template FMT_INLINE void print(FILE* f, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - if (!detail::is_utf8()) return detail::vprint_mojibake(f, fmt, vargs); - return detail::is_locking() ? vprint(f, fmt, vargs) - : vprint_locked(f, fmt, vargs); + if (!detail::use_utf8()) return detail::vprint_mojibake(f, fmt, vargs); + return detail::is_locking() ? vprint_buffered(f, fmt, vargs) + : vprint(f, fmt, vargs); } -/** - Formats ``args`` according to specifications in ``fmt`` and writes the - output to the file ``f`` followed by a newline. - */ +/// Formats `args` according to specifications in `fmt` and writes the output +/// to the file `f` followed by a newline. template FMT_INLINE void println(FILE* f, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - return detail::is_utf8() ? vprintln(f, fmt, vargs) - : detail::vprint_mojibake(f, fmt, vargs, true); + return detail::use_utf8() ? vprintln(f, fmt, vargs) + : detail::vprint_mojibake(f, fmt, vargs, true); } -/** - Formats ``args`` according to specifications in ``fmt`` and writes the output - to ``stdout`` followed by a newline. - */ +/// Formats `args` according to specifications in `fmt` and writes the output +/// to `stdout` followed by a newline. template FMT_INLINE void println(format_string fmt, T&&... args) { return fmt::println(stdout, fmt, static_cast(args)...); diff --git a/3rd/fmt/fmt/chrono.h b/3rd/fmt/fmt/chrono.h index 6360d903..c93123fd 100644 --- a/3rd/fmt/fmt/chrono.h +++ b/3rd/fmt/fmt/chrono.h @@ -8,7 +8,7 @@ #ifndef FMT_CHRONO_H_ #define FMT_CHRONO_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include # include # include // std::isfinite @@ -96,10 +96,8 @@ FMT_CONSTEXPR auto lossless_integral_conversion(const From from, int& ec) return static_cast(from); } -/** - * converts From to To, without loss. If the dynamic value of from - * can't be converted to To without loss, ec is set. - */ +/// Converts From to To, without loss. If the dynamic value of from +/// can't be converted to To without loss, ec is set. template ::value && std::numeric_limits::is_signed != @@ -187,9 +185,7 @@ FMT_CONSTEXPR auto safe_float_conversion(const From from, int& ec) -> To { return from; } -/** - * safe duration cast between integral durations - */ +/// Safe duration cast between integral durations template ::value), FMT_ENABLE_IF(std::is_integral::value)> @@ -239,9 +235,7 @@ auto safe_duration_cast(std::chrono::duration from, return ec ? To() : To(tocount); } -/** - * safe duration_cast between floating point durations - */ +/// Safe duration_cast between floating point durations template ::value), FMT_ENABLE_IF(std::is_floating_point::value)> @@ -397,7 +391,7 @@ void write_codecvt(codecvt_result& out, string_view in_buf, template auto write_encoded_tm_str(OutputIt out, string_view in, const std::locale& loc) -> OutputIt { - if (detail::is_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 || \ @@ -518,9 +512,9 @@ auto to_time_t( FMT_BEGIN_EXPORT /** - Converts given time since epoch as ``std::time_t`` value into calendar time, - expressed in local time. Unlike ``std::localtime``, this function is - thread-safe on most platforms. + * Converts given time since epoch as `std::time_t` value into calendar time, + * expressed in local time. Unlike `std::localtime`, this function is + * thread-safe on most platforms. */ inline auto localtime(std::time_t time) -> std::tm { struct dispatcher { @@ -567,9 +561,9 @@ inline auto localtime(std::chrono::local_time time) -> std::tm { #endif /** - Converts given time since epoch as ``std::time_t`` value into calendar time, - expressed in Coordinated Universal Time (UTC). Unlike ``std::gmtime``, this - function is thread-safe on most platforms. + * Converts given time since epoch as `std::time_t` value into calendar time, + * expressed in Coordinated Universal Time (UTC). Unlike `std::gmtime`, this + * function is thread-safe on most platforms. */ inline auto gmtime(std::time_t time) -> std::tm { struct dispatcher { @@ -682,12 +676,10 @@ enum class numeric_system { // Glibc extensions for formatting numeric values. enum class pad_type { - unspecified, + // Pad a numeric result string with zeros (the default). + zero, // Do not pad a numeric result string. none, - // Pad a numeric result string with zeros even if the conversion specifier - // character uses space-padding by default. - zero, // Pad a numeric result string with spaces. space, }; @@ -712,7 +704,7 @@ FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end, if (*begin != '%') FMT_THROW(format_error("invalid format")); auto ptr = begin; while (ptr != end) { - pad_type pad = pad_type::unspecified; + pad_type pad = pad_type::zero; auto c = *ptr; if (c == '}') break; if (c != '%') { @@ -732,10 +724,6 @@ FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end, pad = pad_type::none; ++ptr; break; - case '0': - pad = pad_type::zero; - ++ptr; - break; } if (ptr == end) FMT_THROW(format_error("invalid format")); c = *ptr++; @@ -795,22 +783,22 @@ FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end, break; // Day of the year/month: case 'U': - handler.on_dec0_week_of_year(numeric_system::standard); + handler.on_dec0_week_of_year(numeric_system::standard, pad); break; case 'W': - handler.on_dec1_week_of_year(numeric_system::standard); + handler.on_dec1_week_of_year(numeric_system::standard, pad); break; case 'V': - handler.on_iso_week_of_year(numeric_system::standard); + handler.on_iso_week_of_year(numeric_system::standard, pad); break; case 'j': handler.on_day_of_year(); break; case 'd': - handler.on_day_of_month(numeric_system::standard); + handler.on_day_of_month(numeric_system::standard, pad); break; case 'e': - handler.on_day_of_month_space(numeric_system::standard); + handler.on_day_of_month(numeric_system::standard, pad_type::space); break; // Hour, minute, second: case 'H': @@ -907,19 +895,19 @@ FMT_CONSTEXPR auto parse_chrono_format(const Char* begin, const Char* end, handler.on_dec_month(numeric_system::alternative); break; case 'U': - handler.on_dec0_week_of_year(numeric_system::alternative); + handler.on_dec0_week_of_year(numeric_system::alternative, pad); break; case 'W': - handler.on_dec1_week_of_year(numeric_system::alternative); + handler.on_dec1_week_of_year(numeric_system::alternative, pad); break; case 'V': - handler.on_iso_week_of_year(numeric_system::alternative); + handler.on_iso_week_of_year(numeric_system::alternative, pad); break; case 'd': - handler.on_day_of_month(numeric_system::alternative); + handler.on_day_of_month(numeric_system::alternative, pad); break; case 'e': - handler.on_day_of_month_space(numeric_system::alternative); + handler.on_day_of_month(numeric_system::alternative, pad_type::space); break; case 'w': handler.on_dec0_weekday(numeric_system::alternative); @@ -972,12 +960,19 @@ template struct null_chrono_spec_handler { FMT_CONSTEXPR void on_abbr_month() { unsupported(); } FMT_CONSTEXPR void on_full_month() { unsupported(); } FMT_CONSTEXPR void on_dec_month(numeric_system) { unsupported(); } - FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) { unsupported(); } - FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) { unsupported(); } - FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) { + unsupported(); + } + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) { + unsupported(); + } FMT_CONSTEXPR void on_day_of_year() { unsupported(); } - FMT_CONSTEXPR void on_day_of_month(numeric_system) { unsupported(); } - FMT_CONSTEXPR void on_day_of_month_space(numeric_system) { unsupported(); } + FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) { + unsupported(); + } FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); } FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); } FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); } @@ -1015,12 +1010,11 @@ struct tm_format_checker : null_chrono_spec_handler { FMT_CONSTEXPR void on_abbr_month() {} FMT_CONSTEXPR void on_full_month() {} FMT_CONSTEXPR void on_dec_month(numeric_system) {} - FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system) {} - FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system) {} - FMT_CONSTEXPR void on_iso_week_of_year(numeric_system) {} + FMT_CONSTEXPR void on_dec0_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_dec1_week_of_year(numeric_system, pad_type) {} + FMT_CONSTEXPR void on_iso_week_of_year(numeric_system, pad_type) {} FMT_CONSTEXPR void on_day_of_year() {} - FMT_CONSTEXPR void on_day_of_month(numeric_system) {} - FMT_CONSTEXPR void on_day_of_month_space(numeric_system) {} + FMT_CONSTEXPR void on_day_of_month(numeric_system, pad_type) {} FMT_CONSTEXPR void on_24_hour(numeric_system, pad_type) {} FMT_CONSTEXPR void on_12_hour(numeric_system, pad_type) {} FMT_CONSTEXPR void on_minute(numeric_system, pad_type) {} @@ -1097,9 +1091,10 @@ inline auto to_nonnegative_int(T value, Int upper) -> Int { } template ::value)> inline auto to_nonnegative_int(T value, Int upper) -> Int { - if (value < 0 || value > static_cast(upper)) + auto int_value = static_cast(value); + if (int_value < 0 || value > static_cast(upper)) FMT_THROW(format_error("invalid value")); - return static_cast(value); + return int_value; } constexpr auto pow10(std::uint32_t n) -> long long { @@ -1453,7 +1448,7 @@ class tm_writer { *out_++ = ' '; on_abbr_month(); *out_++ = ' '; - on_day_of_month_space(numeric_system::standard); + on_day_of_month(numeric_system::standard, pad_type::space); *out_++ = ' '; on_iso_time(); *out_++ = ' '; @@ -1540,24 +1535,26 @@ class tm_writer { format_localized('m', 'O'); } - void on_dec0_week_of_year(numeric_system ns) { + void on_dec0_week_of_year(numeric_system ns, pad_type pad) { if (is_classic_ || ns == numeric_system::standard) - return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week); + return write2((tm_yday() + days_per_week - tm_wday()) / days_per_week, + pad); format_localized('U', 'O'); } - void on_dec1_week_of_year(numeric_system ns) { + void on_dec1_week_of_year(numeric_system ns, pad_type pad) { if (is_classic_ || ns == numeric_system::standard) { auto wday = tm_wday(); write2((tm_yday() + days_per_week - (wday == 0 ? (days_per_week - 1) : (wday - 1))) / - days_per_week); + days_per_week, + pad); } else { format_localized('W', 'O'); } } - void on_iso_week_of_year(numeric_system ns) { + void on_iso_week_of_year(numeric_system ns, pad_type pad) { if (is_classic_ || ns == numeric_system::standard) - return write2(tm_iso_week_of_year()); + return write2(tm_iso_week_of_year(), pad); format_localized('V', 'O'); } @@ -1571,20 +1568,11 @@ class tm_writer { write1(yday / 100); write2(yday % 100); } - void on_day_of_month(numeric_system ns) { - if (is_classic_ || ns == numeric_system::standard) return write2(tm_mday()); + void on_day_of_month(numeric_system ns, pad_type pad) { + if (is_classic_ || ns == numeric_system::standard) + return write2(tm_mday(), pad); format_localized('d', 'O'); } - void on_day_of_month_space(numeric_system ns) { - if (is_classic_ || ns == numeric_system::standard) { - auto mday = to_unsigned(tm_mday()) % 100; - const char* d2 = digits2(mday); - *out_++ = mday < 10 ? ' ' : d2[0]; - *out_++ = d2[1]; - } else { - format_localized('e', 'O'); - } - } void on_24_hour(numeric_system ns, pad_type pad) { if (is_classic_ || ns == numeric_system::standard) @@ -1643,7 +1631,7 @@ class tm_writer { void on_iso_time() { on_24_hour_time(); *out_++ = ':'; - on_second(numeric_system::standard, pad_type::unspecified); + on_second(numeric_system::standard, pad_type::zero); } void on_am_pm() { @@ -1786,8 +1774,10 @@ class get_locale { public: get_locale(bool localized, locale_ref loc) : has_locale_(localized) { +#ifndef FMT_STATIC_THOUSANDS_SEPARATOR if (localized) ::new (&locale_) std::locale(loc.template get()); +#endif } ~get_locale() { if (has_locale_) locale_.~locale(); @@ -1882,7 +1872,7 @@ struct chrono_formatter { } } - void write(Rep value, int width, pad_type pad = pad_type::unspecified) { + void write(Rep value, int width, pad_type pad = pad_type::zero) { write_sign(); if (isnan(value)) return write_nan(); uint32_or_64_or_128_t n = @@ -1932,11 +1922,10 @@ struct chrono_formatter { void on_iso_week_based_year() {} void on_iso_week_based_short_year() {} void on_dec_month(numeric_system) {} - void on_dec0_week_of_year(numeric_system) {} - void on_dec1_week_of_year(numeric_system) {} - void on_iso_week_of_year(numeric_system) {} - void on_day_of_month(numeric_system) {} - void on_day_of_month_space(numeric_system) {} + void on_dec0_week_of_year(numeric_system, pad_type) {} + void on_dec1_week_of_year(numeric_system, pad_type) {} + void on_iso_week_of_year(numeric_system, pad_type) {} + void on_day_of_month(numeric_system, pad_type) {} void on_day_of_year() { if (handle_nan_inf()) return; @@ -2016,7 +2005,7 @@ struct chrono_formatter { on_24_hour_time(); *out++ = ':'; if (handle_nan_inf()) return; - on_second(numeric_system::standard, pad_type::unspecified); + on_second(numeric_system::standard, pad_type::zero); } void on_am_pm() { @@ -2155,7 +2144,7 @@ struct formatter : private formatter { if (use_tm_formatter_) return formatter::format(time, ctx); detail::get_locale loc(false, ctx.locale()); auto w = detail::tm_writer(loc, ctx.out(), time); - w.on_day_of_month(detail::numeric_system::standard); + w.on_day_of_month(detail::numeric_system::standard, detail::pad_type::zero); return w.out(); } }; diff --git a/3rd/fmt/fmt/color.h b/3rd/fmt/fmt/color.h index 25ee275f..f0e9dd94 100644 --- a/3rd/fmt/fmt/color.h +++ b/3rd/fmt/fmt/color.h @@ -227,7 +227,7 @@ struct color_type { }; } // namespace detail -/** A text style consisting of foreground and background colors and emphasis. */ +/// A text style consisting of foreground and background colors and emphasis. class text_style { public: FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept @@ -310,13 +310,13 @@ class text_style { emphasis ems; }; -/** Creates a text style from the foreground (text) color. */ +/// Creates a text style from the foreground (text) color. FMT_CONSTEXPR inline auto fg(detail::color_type foreground) noexcept -> text_style { return text_style(true, foreground); } -/** Creates a text style from the background color. */ +/// Creates a text style from the background color. FMT_CONSTEXPR inline auto bg(detail::color_type background) noexcept -> text_style { return text_style(false, background); @@ -474,15 +474,13 @@ inline void vprint(FILE* f, const text_style& ts, string_view fmt, } /** - \rst - Formats a string and prints it to the specified file stream using ANSI - escape sequences to specify text formatting. - - **Example**:: - - fmt::print(fmt::emphasis::bold | fg(fmt::color::red), - "Elapsed time: {0:.2f} seconds", 1.23); - \endrst + * Formats a string and prints it to the specified file stream using ANSI + * escape sequences to specify text formatting. + * + * **Example**: + * + * fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + * "Elapsed time: {0:.2f} seconds", 1.23); */ template void print(FILE* f, const text_style& ts, format_string fmt, @@ -491,15 +489,13 @@ void print(FILE* f, const text_style& ts, format_string fmt, } /** - \rst - Formats a string and prints it to stdout using ANSI escape sequences to - specify text formatting. - - **Example**:: - - fmt::print(fmt::emphasis::bold | fg(fmt::color::red), - "Elapsed time: {0:.2f} seconds", 1.23); - \endrst + * Formats a string and prints it to stdout using ANSI escape sequences to + * specify text formatting. + * + * **Example**: + * + * fmt::print(fmt::emphasis::bold | fg(fmt::color::red), + * "Elapsed time: {0:.2f} seconds", 1.23); */ template void print(const text_style& ts, format_string fmt, T&&... args) { @@ -514,26 +510,24 @@ inline auto vformat(const text_style& ts, string_view fmt, format_args args) } /** - \rst - Formats arguments and returns the result as a string using ANSI - escape sequences to specify text formatting. - - **Example**:: - - #include - std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), - "The answer is {}", 42); - \endrst -*/ + * Formats arguments and returns the result as a string using ANSI escape + * sequences to specify text formatting. + * + * **Example**: + * + * ``` + * #include + * std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red), + * "The answer is {}", 42); + * ``` + */ template inline auto format(const text_style& ts, format_string fmt, T&&... args) -> std::string { return fmt::vformat(ts, fmt, fmt::make_format_args(args...)); } -/** - Formats a string with the given text_style and writes the output to ``out``. - */ +/// Formats a string with the given text_style and writes the output to `out`. template ::value)> auto vformat_to(OutputIt out, const text_style& ts, string_view fmt, @@ -544,17 +538,15 @@ auto vformat_to(OutputIt out, const text_style& ts, string_view fmt, } /** - \rst - Formats arguments with the given text_style, writes the result to the output - iterator ``out`` and returns the iterator past the end of the output range. - - **Example**:: - - std::vector out; - fmt::format_to(std::back_inserter(out), - fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); - \endrst -*/ + * Formats arguments with the given text style, writes the result to the output + * iterator `out` and returns the iterator past the end of the output range. + * + * **Example**: + * + * std::vector out; + * fmt::format_to(std::back_inserter(out), + * fmt::emphasis::bold | fg(fmt::color::red), "{}", 42); + */ template ::value)> inline auto format_to(OutputIt out, const text_style& ts, @@ -599,16 +591,14 @@ struct formatter, Char> : formatter { }; /** - \rst - Returns an argument that will be formatted using ANSI escape sequences, - to be used in a formatting function. - - **Example**:: - - fmt::print("Elapsed time: {0:.2f} seconds", - fmt::styled(1.23, fmt::fg(fmt::color::green) | - fmt::bg(fmt::color::blue))); - \endrst + * Returns an argument that will be formatted using ANSI escape sequences, + * to be used in a formatting function. + * + * **Example**: + * + * fmt::print("Elapsed time: {0:.2f} seconds", + * fmt::styled(1.23, fmt::fg(fmt::color::green) | + * fmt::bg(fmt::color::blue))); */ template FMT_CONSTEXPR auto styled(const T& value, text_style ts) diff --git a/3rd/fmt/fmt/compile.h b/3rd/fmt/fmt/compile.h index 65c68a4b..b2afc2c3 100644 --- a/3rd/fmt/fmt/compile.h +++ b/3rd/fmt/fmt/compile.h @@ -8,13 +8,17 @@ #ifndef FMT_COMPILE_H_ #define FMT_COMPILE_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include // std::back_inserter #endif #include "format.h" FMT_BEGIN_NAMESPACE + +// A compile-time string which is compiled into fast formatting code. +FMT_EXPORT class compiled_string {}; + namespace detail { template @@ -23,28 +27,22 @@ FMT_CONSTEXPR inline auto copy(InputIt begin, InputIt end, counting_iterator it) return it + (end - begin); } -// A compile-time string which is compiled into fast formatting code. -class compiled_string {}; - template struct is_compiled_string : std::is_base_of {}; /** - \rst - Converts a string literal *s* into a format string that will be parsed at - compile time and converted into efficient formatting code. Requires C++17 - ``constexpr if`` compiler support. - - **Example**:: - - // Converts 42 into std::string using the most efficient method and no - // runtime format string processing. - std::string s = fmt::format(FMT_COMPILE("{}"), 42); - \endrst + * Converts a string literal `s` into a format string that will be parsed at + * compile time and converted into efficient formatting code. Requires C++17 + * `constexpr if` compiler support. + * + * **Example**: + * + * // Converts 42 into std::string using the most efficient method and no + * // runtime format string processing. + * std::string s = fmt::format(FMT_COMPILE("{}"), 42); */ #if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction) -# define FMT_COMPILE(s) \ - FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit) +# define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::compiled_string, explicit) #else # define FMT_COMPILE(s) FMT_STRING(s) #endif @@ -148,7 +146,7 @@ template struct field { template constexpr OutputIt format(OutputIt out, const Args&... args) const { const T& arg = get_arg_checked(args...); - if constexpr (std::is_convertible_v>) { + if constexpr (std::is_convertible>::value) { auto s = basic_string_view(arg); return copy(s.begin(), s.end(), out); } @@ -240,13 +238,12 @@ constexpr size_t parse_text(basic_string_view str, size_t pos) { } template -constexpr auto compile_format_string(S format_str); +constexpr auto compile_format_string(S fmt); template -constexpr auto parse_tail(T head, S format_str) { - if constexpr (POS != - basic_string_view(format_str).size()) { - constexpr auto tail = compile_format_string(format_str); +constexpr auto parse_tail(T head, S fmt) { + if constexpr (POS != basic_string_view(fmt).size()) { + constexpr auto tail = compile_format_string(fmt); if constexpr (std::is_same, unknown_format>()) return tail; @@ -317,14 +314,13 @@ struct field_type::value>> { template -constexpr auto parse_replacement_field_then_tail(S format_str) { +constexpr auto parse_replacement_field_then_tail(S fmt) { using char_type = typename S::char_type; - constexpr auto str = basic_string_view(format_str); + constexpr auto str = basic_string_view(fmt); constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); if constexpr (c == '}') { return parse_tail( - field::type, ARG_INDEX>(), - format_str); + field::type, ARG_INDEX>(), fmt); } else if constexpr (c != ':') { FMT_THROW(format_error("expected ':'")); } else { @@ -337,7 +333,7 @@ constexpr auto parse_replacement_field_then_tail(S format_str) { return parse_tail( spec_field::type, ARG_INDEX>{ result.fmt}, - format_str); + fmt); } } } @@ -345,22 +341,21 @@ constexpr auto parse_replacement_field_then_tail(S format_str) { // Compiles a non-empty format string and returns the compiled representation // or unknown_format() on unrecognized input. template -constexpr auto compile_format_string(S format_str) { +constexpr auto compile_format_string(S fmt) { using char_type = typename S::char_type; - constexpr auto str = basic_string_view(format_str); + constexpr auto str = basic_string_view(fmt); if constexpr (str[POS] == '{') { if constexpr (POS + 1 == str.size()) FMT_THROW(format_error("unmatched '{' in format string")); if constexpr (str[POS + 1] == '{') { - return parse_tail(make_text(str, POS, 1), format_str); + return parse_tail(make_text(str, POS, 1), fmt); } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { static_assert(ID != manual_indexing_id, "cannot switch from manual to automatic argument indexing"); constexpr auto next_id = ID != manual_indexing_id ? ID + 1 : manual_indexing_id; return parse_replacement_field_then_tail, Args, - POS + 1, ID, next_id>( - format_str); + POS + 1, ID, next_id>(fmt); } else { constexpr auto arg_id_result = parse_arg_id(str.data() + POS + 1, str.data() + str.size()); @@ -376,7 +371,7 @@ constexpr auto compile_format_string(S format_str) { return parse_replacement_field_then_tail, Args, arg_id_end_pos, arg_index, manual_indexing_id>( - format_str); + fmt); } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) { constexpr auto arg_index = get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{}); @@ -385,11 +380,11 @@ constexpr auto compile_format_string(S format_str) { ID != manual_indexing_id ? ID + 1 : manual_indexing_id; return parse_replacement_field_then_tail< decltype(get_type::value), Args, arg_id_end_pos, - arg_index, next_id>(format_str); + arg_index, next_id>(fmt); } else if constexpr (c == '}') { return parse_tail( runtime_named_field{arg_id_result.arg_id.val.name}, - format_str); + fmt); } else if constexpr (c == ':') { return unknown_format(); // no type info for specs parsing } @@ -398,29 +393,26 @@ constexpr auto compile_format_string(S format_str) { } else if constexpr (str[POS] == '}') { if constexpr (POS + 1 == str.size()) FMT_THROW(format_error("unmatched '}' in format string")); - return parse_tail(make_text(str, POS, 1), format_str); + return parse_tail(make_text(str, POS, 1), fmt); } else { constexpr auto end = parse_text(str, POS + 1); if constexpr (end - POS > 1) { - return parse_tail(make_text(str, POS, end - POS), - format_str); + return parse_tail(make_text(str, POS, end - POS), fmt); } else { - return parse_tail(code_unit{str[POS]}, - format_str); + return parse_tail(code_unit{str[POS]}, fmt); } } } template ::value)> -constexpr auto compile(S format_str) { - constexpr auto str = basic_string_view(format_str); +constexpr auto compile(S fmt) { + constexpr auto str = basic_string_view(fmt); if constexpr (str.size() == 0) { return detail::make_text(str, 0, 0); } else { constexpr auto result = - detail::compile_format_string, 0, 0>( - format_str); + detail::compile_format_string, 0, 0>(fmt); return result; } } @@ -492,35 +484,33 @@ FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { template ::value)> -auto format_to_n(OutputIt out, size_t n, const S& format_str, Args&&... args) +auto format_to_n(OutputIt out, size_t n, const S& fmt, Args&&... args) -> format_to_n_result { using traits = detail::fixed_buffer_traits; auto buf = detail::iterator_buffer(out, n); - fmt::format_to(std::back_inserter(buf), format_str, - std::forward(args)...); + fmt::format_to(std::back_inserter(buf), fmt, std::forward(args)...); return {buf.out(), buf.count()}; } template ::value)> -FMT_CONSTEXPR20 auto formatted_size(const S& format_str, const Args&... args) +FMT_CONSTEXPR20 auto formatted_size(const S& fmt, const Args&... args) -> size_t { - return fmt::format_to(detail::counting_iterator(), format_str, args...) - .count(); + return fmt::format_to(detail::counting_iterator(), fmt, args...).count(); } template ::value)> -void print(std::FILE* f, const S& format_str, const Args&... args) { +void print(std::FILE* f, const S& fmt, const Args&... args) { memory_buffer buffer; - fmt::format_to(std::back_inserter(buffer), format_str, args...); + fmt::format_to(std::back_inserter(buffer), fmt, args...); detail::print(f, {buffer.data(), buffer.size()}); } template ::value)> -void print(const S& format_str, const Args&... args) { - print(stdout, format_str, args...); +void print(const S& fmt, const Args&... args) { + print(stdout, fmt, args...); } #if FMT_USE_NONTYPE_TEMPLATE_ARGS diff --git a/3rd/fmt/fmt/format-inl.h b/3rd/fmt/fmt/format-inl.h index fca26d47..8d07cc67 100644 --- a/3rd/fmt/fmt/format-inl.h +++ b/3rd/fmt/fmt/format-inl.h @@ -8,16 +8,16 @@ #ifndef FMT_FORMAT_INL_H_ #define FMT_FORMAT_INL_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include +# include // errno +# include # include # include -#endif -#include // errno -#include -#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) && !defined(FMT_IMPORT_STD) -# include +# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) +# include +# endif #endif #if defined(_WIN32) && !defined(FMT_USE_WRITE_CONSOLE) @@ -1600,14 +1600,21 @@ template class fallback_file : public file_base { } }; -template +#ifndef FMT_USE_FALLBACK_FILE +# define FMT_USE_FALLBACK_FILE 1 +#endif + +template auto get_file(F* f, int) -> apple_file { return f; } -template +template inline auto get_file(F* f, int) -> glibc_file { return f; } + inline auto get_file(FILE* f, ...) -> fallback_file { return f; } using file_ref = decltype(get_file(static_cast(nullptr), 0)); @@ -1678,14 +1685,14 @@ FMT_FUNC void print(std::FILE* f, string_view text) { } } // namespace detail -FMT_FUNC void vprint(std::FILE* f, string_view fmt, format_args args) { +FMT_FUNC void vprint_buffered(std::FILE* f, string_view fmt, format_args args) { auto buffer = memory_buffer(); detail::vformat_to(buffer, fmt, args); detail::print(f, {buffer.data(), buffer.size()}); } -FMT_FUNC void vprint_locked(std::FILE* f, string_view fmt, format_args args) { - if (!detail::file_ref(f).is_buffered()) return vprint(f, fmt, args); +FMT_FUNC void vprint(std::FILE* f, string_view fmt, format_args args) { + if (!detail::file_ref(f).is_buffered()) return vprint_buffered(f, fmt, args); auto&& buffer = detail::file_print_buffer(f); return detail::vformat_to(buffer, fmt, args); } diff --git a/3rd/fmt/fmt/format.h b/3rd/fmt/fmt/format.h index 884ba3b6..7c2a19b4 100644 --- a/3rd/fmt/fmt/format.h +++ b/3rd/fmt/fmt/format.h @@ -38,7 +38,9 @@ # define FMT_REMOVE_TRANSITIVE_INCLUDES #endif -#ifndef FMT_IMPORT_STD +#include "base.h" + +#ifndef FMT_MODULE # include // std::signbit # include // uint32_t # include // std::memcpy @@ -51,24 +53,19 @@ # include // std::runtime_error # include // std::string # include // std::system_error -#endif - -#include "base.h" // Checking FMT_CPLUSPLUS for warning suppression in MSVC. -#if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 201703L && \ - !defined(FMT_IMPORT_STD) -# include // std::bit_cast -#endif +# if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 201703L +# include // std::bit_cast +# endif // libc++ supports string_view in pre-c++17. -#if FMT_HAS_INCLUDE() && \ - (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) -# ifndef FMT_IMPORT_STD +# if FMT_HAS_INCLUDE() && \ + (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) # include +# define FMT_USE_STRING_VIEW # endif -# define FMT_USE_STRING_VIEW -#endif +#endif // FMT_MODULE #if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L # define FMT_INLINE_VARIABLE inline @@ -813,25 +810,17 @@ FMT_BEGIN_EXPORT enum { inline_buffer_size = 500 }; /** - \rst - A dynamically growing memory buffer for trivially copyable/constructible types - with the first ``SIZE`` elements stored in the object itself. - - You can use the ``memory_buffer`` type alias for ``char`` instead. - - **Example**:: - - auto out = fmt::memory_buffer(); - fmt::format_to(std::back_inserter(out), "The answer is {}.", 42); - - This will append the following output to the ``out`` object: - - .. code-block:: none - - The answer is 42. - - The output can be converted to an ``std::string`` with ``to_string(out)``. - \endrst + * A dynamically growing memory buffer for trivially copyable/constructible + * types with the first `SIZE` elements stored in the object itself. Most + * commonly used via the `memory_buffer` alias for `char`. + * + * **Example**: + * + * auto out = fmt::memory_buffer(); + * fmt::format_to(std::back_inserter(out), "The answer is {}.", 42); + * + * This will append "The answer is 42." to `out`. The buffer content can be + * converted to `std::string` with `to_string(out)`. */ template > @@ -904,22 +893,14 @@ class basic_memory_buffer : public detail::buffer { } public: - /** - \rst - Constructs a :class:`fmt::basic_memory_buffer` object moving the content - of the other object to it. - \endrst - */ + /// Constructs a `basic_memory_buffer` object moving the content of the other + /// object to it. FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept : detail::buffer(grow) { move(other); } - /** - \rst - Moves the content of the other ``basic_memory_buffer`` object to this one. - \endrst - */ + /// Moves the content of the other `basic_memory_buffer` object to this one. auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& { FMT_ASSERT(this != &other, ""); deallocate(); @@ -930,13 +911,11 @@ class basic_memory_buffer : public detail::buffer { // Returns a copy of the allocator associated with this buffer. auto get_allocator() const -> Allocator { return alloc_; } - /** - Resizes the buffer to contain *count* elements. If T is a POD type new - elements may not be initialized. - */ + /// Resizes the buffer to contain `count` elements. If T is a POD type new + /// elements may not be initialized. FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); } - /** Increases the buffer capacity to *new_capacity*. */ + /// Increases the buffer capacity to `new_capacity`. void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } using detail::buffer::append; @@ -965,7 +944,7 @@ FMT_BEGIN_EXPORT # pragma clang diagnostic ignored "-Wweak-vtables" #endif -/** An error reported from a formatting function. */ +/// An error reported from a formatting function. class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error { public: using std::runtime_error::runtime_error; @@ -1087,6 +1066,8 @@ template class format_facet : public Locale::facet { } }; +FMT_END_EXPORT + namespace detail { // Returns true if value is negative, false otherwise. @@ -1186,9 +1167,7 @@ inline auto do_count_digits(uint64_t n) -> int { // except for n == 0 in which case count_digits returns 1. FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int { #ifdef FMT_BUILTIN_CLZLL - if (!is_constant_evaluated()) { - return do_count_digits(n); - } + if (!is_constant_evaluated()) return do_count_digits(n); #endif return count_digits_fallback(n); } @@ -1802,7 +1781,7 @@ auto find_escape(const Char* begin, const Char* end) inline auto find_escape(const char* begin, const char* end) -> find_escape_result { - if (!is_utf8()) return find_escape(begin, end); + if (!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) { @@ -1830,14 +1809,12 @@ inline auto find_escape(const char* begin, const char* end) }() /** - \rst - Constructs a compile-time format string from a string literal *s*. - - **Example**:: - - // A compile-time error because 'd' is an invalid specifier for strings. - std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); - \endrst + * Constructs a compile-time format string from a string literal `s`. + * + * **Example**: + * + * // A compile-time error because 'd' is an invalid specifier for strings. + * std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); */ #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, ) @@ -2695,7 +2672,7 @@ FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, } template constexpr auto isnan(T value) -> bool { - return !(value >= value); // std::isnan doesn't support __float128. + return value != value; // std::isnan doesn't support __float128. } template @@ -3887,25 +3864,24 @@ FMT_API void report_error(format_func func, int error_code, const char* message) noexcept; } // namespace detail +FMT_BEGIN_EXPORT FMT_API auto vsystem_error(int error_code, string_view format_str, format_args args) -> std::system_error; /** - \rst - Constructs :class:`std::system_error` with a message formatted with - ``fmt::format(fmt, args...)``. - *error_code* is a system error code as given by ``errno``. - - **Example**:: - - // This throws std::system_error with the description - // cannot open file 'madeup': No such file or directory - // or similar (system message may vary). - const char* filename = "madeup"; - std::FILE* file = std::fopen(filename, "r"); - if (!file) - throw fmt::system_error(errno, "cannot open file '{}'", filename); - \endrst + * Constructs `std::system_error` with a message formatted with + * `fmt::format(fmt, args...)`. + * `error_code` is a system error code as given by `errno`. + * + * **Example**: + * + * // This throws std::system_error with the description + * // cannot open file 'madeup': No such file or directory + * // or similar (system message may vary). + * const char* filename = "madeup"; + * std::FILE* file = std::fopen(filename, "r"); + * if (!file) + * throw fmt::system_error(errno, "cannot open file '{}'", filename); */ template auto system_error(int error_code, format_string fmt, T&&... args) @@ -3914,20 +3890,17 @@ auto system_error(int error_code, format_string fmt, T&&... args) } /** - \rst - Formats an error message for an error returned by an operating system or a - language runtime, for example a file opening error, and writes it to *out*. - The format is the same as the one used by ``std::system_error(ec, message)`` - where ``ec`` is ``std::error_code(error_code, std::generic_category()})``. - It is implementation-defined but normally looks like: - - .. parsed-literal:: - **: ** - - where ** is the passed message and ** is the system - message corresponding to the error code. - *error_code* is a system error code as given by ``errno``. - \endrst + * Formats an error message for an error returned by an operating system or a + * language runtime, for example a file opening error, and writes it to `out`. + * The format is the same as the one used by `std::system_error(ec, message)` + * where `ec` is `std::error_code(error_code, std::generic_category())`. + * It is implementation-defined but normally looks like: + * + * : + * + * where `` is the passed message and `` is the system + * message corresponding to the error code. + * `error_code` is a system error code as given by `errno`. */ FMT_API void format_system_error(detail::buffer& out, int error_code, const char* message) noexcept; @@ -3936,7 +3909,7 @@ FMT_API void format_system_error(detail::buffer& out, int error_code, // Can be used to report errors from destructors. FMT_API void report_system_error(int error_code, const char* message) noexcept; -/** Fast integer formatter. */ +/// A fast integer formatter. class format_int { private: // Buffer should be large enough to hold all digits (digits10 + 1), @@ -3945,12 +3918,14 @@ class format_int { mutable char buffer_[buffer_size]; char* str_; - template auto format_unsigned(UInt value) -> char* { + template + FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* { auto n = static_cast>(value); return detail::format_decimal(buffer_, n, buffer_size - 1).begin; } - template auto format_signed(Int value) -> char* { + template + FMT_CONSTEXPR20 auto format_signed(Int value) -> char* { auto abs_value = static_cast>(value); bool negative = value < 0; if (negative) abs_value = 0 - abs_value; @@ -3960,39 +3935,35 @@ class format_int { } public: - explicit format_int(int value) : str_(format_signed(value)) {} - explicit format_int(long value) : str_(format_signed(value)) {} - explicit format_int(long long value) : str_(format_signed(value)) {} - explicit format_int(unsigned value) : str_(format_unsigned(value)) {} - explicit format_int(unsigned long value) : str_(format_unsigned(value)) {} - explicit format_int(unsigned long long value) + explicit FMT_CONSTEXPR20 format_int(int value) : str_(format_signed(value)) {} + explicit FMT_CONSTEXPR20 format_int(long value) + : str_(format_signed(value)) {} + explicit FMT_CONSTEXPR20 format_int(long long value) + : str_(format_signed(value)) {} + explicit FMT_CONSTEXPR20 format_int(unsigned value) + : str_(format_unsigned(value)) {} + explicit FMT_CONSTEXPR20 format_int(unsigned long value) + : str_(format_unsigned(value)) {} + explicit FMT_CONSTEXPR20 format_int(unsigned long long value) : str_(format_unsigned(value)) {} - /** Returns the number of characters written to the output buffer. */ - auto size() const -> size_t { + /// Returns the number of characters written to the output buffer. + FMT_CONSTEXPR20 auto size() const -> size_t { return detail::to_unsigned(buffer_ - str_ + buffer_size - 1); } - /** - Returns a pointer to the output buffer content. No terminating null - character is appended. - */ - auto data() const -> const char* { return str_; } + /// Returns a pointer to the output buffer content. No terminating null + /// character is appended. + FMT_CONSTEXPR20 auto data() const -> const char* { return str_; } - /** - Returns a pointer to the output buffer content with terminating null - character appended. - */ - auto c_str() const -> const char* { + /// Returns a pointer to the output buffer content with terminating null + /// character appended. + FMT_CONSTEXPR20 auto c_str() const -> const char* { buffer_[buffer_size - 1] = '\0'; return str_; } - /** - \rst - Returns the content of the output buffer as an ``std::string``. - \endrst - */ + /// Returns the content of the output buffer as an `std::string`. auto str() const -> std::string { return std::string(str_, size()); } }; @@ -4002,7 +3973,8 @@ struct formatter::value>> template auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { using base = formatter, Char>; - return base::format(format_as(value), ctx); + auto&& val = format_as(value); // Make an lvalue reference for format. + return base::format(val, ctx); } }; @@ -4017,22 +3989,23 @@ FMT_FORMAT_AS(unsigned short, unsigned); FMT_FORMAT_AS(long, detail::long_type); FMT_FORMAT_AS(unsigned long, detail::ulong_type); FMT_FORMAT_AS(Char*, const Char*); -FMT_FORMAT_AS(std::basic_string, basic_string_view); FMT_FORMAT_AS(std::nullptr_t, const void*); FMT_FORMAT_AS(detail::std_string_view, basic_string_view); FMT_FORMAT_AS(void*, const void*); +template +class formatter, Char> + : public formatter, Char> {}; + template struct formatter : formatter, Char> {}; /** - \rst - Converts ``p`` to ``const void*`` for pointer formatting. - - **Example**:: - - auto s = fmt::format("{}", fmt::ptr(p)); - \endrst + * Converts `p` to `const void*` for pointer formatting. + * + * **Example**: + * + * auto s = fmt::format("{}", fmt::ptr(p)); */ template auto ptr(T p) -> const void* { static_assert(std::is_pointer::value, ""); @@ -4040,14 +4013,12 @@ template auto ptr(T p) -> const void* { } /** - \rst - Converts ``e`` to the underlying type. - - **Example**:: - - enum class color { red, green, blue }; - auto s = fmt::format("{}", fmt::underlying(color::red)); - \endrst + * Converts `e` to the underlying type. + * + * **Example**: + * + * enum class color { red, green, blue }; + * auto s = fmt::format("{}", fmt::underlying(color::red)); */ template constexpr auto underlying(Enum e) noexcept -> underlying_t { @@ -4098,15 +4069,13 @@ template struct group_digits_view { }; /** - \rst - Returns a view that formats an integer value using ',' as a locale-independent - thousands separator. - - **Example**:: - - fmt::print("{}", fmt::group_digits(12345)); - // Output: "12,345" - \endrst + * Returns a view that formats an integer value using ',' as a + * locale-independent thousands separator. + * + * **Example**: + * + * fmt::print("{}", fmt::group_digits(12345)); + * // Output: "12,345" */ template auto group_digits(T value) -> group_digits_view { return {value}; @@ -4197,15 +4166,11 @@ template struct nested_formatter { }; /** - \rst - Converts *value* to ``std::string`` using the default format for type *T*. - - **Example**:: - - #include - - std::string answer = fmt::to_string(42); - \endrst + * Converts `value` to `std::string` using the default format for type `T`. + * + * **Example**: + * + * std::string answer = fmt::to_string(42); */ template ::value && !detail::has_format_as::value)> @@ -4326,6 +4291,8 @@ extern template FMT_API auto decimal_point_impl(locale_ref) -> char; extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; #endif // FMT_HEADER_ONLY +FMT_END_EXPORT + template template FMT_CONSTEXPR FMT_INLINE auto native_formatter::format( @@ -4341,7 +4308,6 @@ FMT_CONSTEXPR FMT_INLINE auto native_formatter::format( return write(ctx.out(), val, specs, ctx.locale()); } -FMT_END_EXPORT } // namespace detail FMT_BEGIN_EXPORT @@ -4354,14 +4320,12 @@ struct formatter #if FMT_USE_USER_DEFINED_LITERALS inline namespace literals { /** - \rst - User-defined literal equivalent of :func:`fmt::arg`. - - **Example**:: - - using namespace fmt::literals; - fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23); - \endrst + * User-defined literal equivalent of `fmt::arg`. + * + * **Example**: + * + * using namespace fmt::literals; + * fmt::print("The answer is {answer}.", "answer"_a=42); */ # if FMT_USE_NONTYPE_TEMPLATE_ARGS template constexpr auto operator""_a() { @@ -4379,16 +4343,14 @@ constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg { FMT_API auto vformat(string_view fmt, format_args args) -> std::string; /** - \rst - Formats ``args`` according to specifications in ``fmt`` and returns the result - as a string. - - **Example**:: - - #include - std::string message = fmt::format("The answer is {}.", 42); - \endrst -*/ + * Formats `args` according to specifications in `fmt` and returns the result + * as a string. + * + * **Example**: + * + * #include + * std::string message = fmt::format("The answer is {}.", 42); + */ template FMT_NODISCARD FMT_INLINE auto format(format_string fmt, T&&... args) -> std::string { diff --git a/3rd/fmt/fmt/os.h b/3rd/fmt/fmt/os.h index 728a613b..5c85ea08 100644 --- a/3rd/fmt/fmt/os.h +++ b/3rd/fmt/fmt/os.h @@ -8,20 +8,18 @@ #ifndef FMT_OS_H_ #define FMT_OS_H_ -#include -#ifndef FMT_IMPORT_STD +#include "format.h" + +#ifndef FMT_MODULE +# include # include # include # include // std::system_error -#endif - -#include "format.h" -#if defined __APPLE__ || defined(__FreeBSD__) # if FMT_HAS_INCLUDE() -# include // for LC_NUMERIC_MASK on OS X +# include // LC_NUMERIC_MASK on macOS # endif -#endif +#endif // FMT_MODULE #ifndef FMT_USE_FCNTL // UWP doesn't provide _pipe. @@ -79,46 +77,33 @@ FMT_BEGIN_NAMESPACE FMT_BEGIN_EXPORT /** - \rst - A reference to a null-terminated string. It can be constructed from a C - string or ``std::string``. - - You can use one of the following type aliases for common character types: - - +---------------+-----------------------------+ - | Type | Definition | - +===============+=============================+ - | cstring_view | basic_cstring_view | - +---------------+-----------------------------+ - | wcstring_view | basic_cstring_view | - +---------------+-----------------------------+ - - This class is most useful as a parameter type to allow passing - different types of strings to a function, for example:: - - template - std::string format(cstring_view format_str, const Args & ... args); - - format("{}", 42); - format(std::string("{}"), 42); - \endrst + * A reference to a null-terminated string. It can be constructed from a C + * string or `std::string`. + * + * You can use one of the following type aliases for common character types: + * + * +---------------+-----------------------------+ + * | Type | Definition | + * +===============+=============================+ + * | cstring_view | basic_cstring_view | + * +---------------+-----------------------------+ + * | wcstring_view | basic_cstring_view | + * +---------------+-----------------------------+ + * + * This class is most useful as a parameter type for functions that wrap C APIs. */ template class basic_cstring_view { private: const Char* data_; public: - /** Constructs a string reference object from a C string. */ + /// Constructs a string reference object from a C string. basic_cstring_view(const Char* s) : data_(s) {} - /** - \rst - Constructs a string reference from an ``std::string`` object. - \endrst - */ + /// Constructs a string reference from an `std::string` object. basic_cstring_view(const std::basic_string& s) : data_(s.c_str()) {} - /** Returns the pointer to a C string. */ + /// Returns the pointer to a C string. auto c_str() const -> const Char* { return data_; } }; @@ -137,33 +122,30 @@ FMT_API std::system_error vwindows_error(int error_code, string_view format_str, format_args args); /** - \rst - Constructs a :class:`std::system_error` object with the description - of the form - - .. parsed-literal:: - **: ** - - where ** is the formatted message and ** is the - system message corresponding to the error code. - *error_code* is a Windows error code as given by ``GetLastError``. - If *error_code* is not a valid error code such as -1, the system message - will look like "error -1". - - **Example**:: - - // This throws a system_error with the description - // cannot open file 'madeup': The system cannot find the file specified. - // or similar (system message may vary). - const char *filename = "madeup"; - LPOFSTRUCT of = LPOFSTRUCT(); - HFILE file = OpenFile(filename, &of, OF_READ); - if (file == HFILE_ERROR) { - throw fmt::windows_error(GetLastError(), - "cannot open file '{}'", filename); - } - \endrst -*/ + * Constructs a `std::system_error` object with the description of the form + * + * : + * + * where `` is the formatted message and `` is the + * system message corresponding to the error code. + * `error_code` is a Windows error code as given by `GetLastError`. + * If `error_code` is not a valid error code such as -1, the system message + * will look like "error -1". + * + * **Example**: + * + * // This throws a system_error with the description + * // cannot open file 'madeup': The system cannot find the file + * specified. + * // or similar (system message may vary). + * const char *filename = "madeup"; + * LPOFSTRUCT of = LPOFSTRUCT(); + * HFILE file = OpenFile(filename, &of, OF_READ); + * if (file == HFILE_ERROR) { + * throw fmt::windows_error(GetLastError(), + * "cannot open file '{}'", filename); + * } + */ template std::system_error windows_error(int error_code, string_view message, const Args&... args) { @@ -229,17 +211,11 @@ class buffered_file { FMT_API auto descriptor() const -> int; - void vprint(string_view fmt, format_args args) { - fmt::vprint(file_, fmt, args); - } - void vprint_locked(string_view fmt, format_args args) { - fmt::vprint_locked(file_, fmt, args); - } - template inline void print(string_view fmt, const T&... args) { const auto& vargs = fmt::make_format_args(args...); - detail::is_locking() ? vprint(fmt, vargs) : vprint_locked(fmt, vargs); + detail::is_locking() ? fmt::vprint_buffered(file_, fmt, vargs) + : fmt::vprint(file_, fmt, vargs); } }; @@ -390,7 +366,7 @@ class file_buffer final : public buffer { public: FMT_API file_buffer(cstring_view path, const ostream_params& params); - FMT_API file_buffer(file_buffer&& other); + FMT_API file_buffer(file_buffer&& other) noexcept; FMT_API ~file_buffer(); void flush() { @@ -407,11 +383,10 @@ class file_buffer final : public buffer { } // namespace detail -// Added {} below to work around default constructor error known to -// occur in Xcode versions 7.2.1 and 8.2.1. -constexpr detail::buffer_size buffer_size{}; +constexpr auto buffer_size = detail::buffer_size(); -/** A fast output stream which is not thread-safe. */ +/// A fast output stream for writing from a single thread. Writing from +/// multiple threads without external synchronization may result in a data race. class FMT_API ostream { private: FMT_MSC_WARNING(suppress : 4251) @@ -432,29 +407,25 @@ class FMT_API ostream { void close() { buffer_.close(); } - /** - Formats ``args`` according to specifications in ``fmt`` and writes the - output to the file. - */ + /// Formats `args` according to specifications in `fmt` and writes the + /// output to the file. template void print(format_string fmt, T&&... args) { vformat_to(appender(buffer_), fmt, fmt::make_format_args(args...)); } }; /** - \rst - Opens a file for writing. Supported parameters passed in *params*: - - * ````: Flags passed to `open - `_ - (``file::WRONLY | file::CREATE | file::TRUNC`` by default) - * ``buffer_size=``: Output buffer size - - **Example**:: - - auto out = fmt::output_file("guide.txt"); - out.print("Don't {}", "Panic"); - \endrst + * Opens a file for writing. Supported parameters passed in `params`: + * + * - ``: Flags passed to [open]( + * https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html) + * (`file::WRONLY | file::CREATE | file::TRUNC` by default) + * - `buffer_size=`: Output buffer size + * + * **Example**: + * + * auto out = fmt::output_file("guide.txt"); + * out.print("Don't {}", "Panic"); */ template inline auto output_file(cstring_view path, T... params) -> ostream { diff --git a/3rd/fmt/fmt/ostream.h b/3rd/fmt/fmt/ostream.h index 7ab24580..98faef65 100644 --- a/3rd/fmt/fmt/ostream.h +++ b/3rd/fmt/fmt/ostream.h @@ -8,7 +8,7 @@ #ifndef FMT_OSTREAM_H_ #define FMT_OSTREAM_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include // std::filebuf #endif @@ -44,12 +44,12 @@ auto get_file(std::filebuf&) -> FILE*; inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data) -> bool { FILE* f = nullptr; -#if FMT_MSC_VERSION +#if FMT_MSC_VERSION && FMT_USE_RTTI if (auto* buf = dynamic_cast(os.rdbuf())) f = get_file(*buf); else return false; -#elif defined(_WIN32) && defined(__GLIBCXX__) +#elif defined(_WIN32) && defined(__GLIBCXX__) && FMT_USE_RTTI auto* rdbuf = os.rdbuf(); if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf*>(rdbuf)) f = sfbuf->file(); @@ -136,14 +136,12 @@ struct formatter, Char> }; /** - \rst - Returns a view that formats `value` via an ostream ``operator<<``. - - **Example**:: - - fmt::print("Current thread id: {}\n", - fmt::streamed(std::this_thread::get_id())); - \endrst + * Returns a view that formats `value` via an ostream `operator<<`. + * + * **Example**: + * + * fmt::print("Current thread id: {}\n", + * fmt::streamed(std::this_thread::get_id())); */ template constexpr auto streamed(const T& value) -> detail::streamed_view { @@ -172,18 +170,16 @@ void vprint(std::basic_ostream& os, } /** - \rst - Prints formatted data to the stream *os*. - - **Example**:: - - fmt::print(cerr, "Don't {}!", "panic"); - \endrst + * Prints formatted data to the stream `os`. + * + * **Example**: + * + * fmt::print(cerr, "Don't {}!", "panic"); */ FMT_EXPORT template void print(std::ostream& os, format_string fmt, T&&... args) { const auto& vargs = fmt::make_format_args(args...); - if (detail::is_utf8()) + if (detail::use_utf8()) vprint(os, fmt, vargs); else detail::vprint_directly(os, fmt, vargs); diff --git a/3rd/fmt/fmt/printf.h b/3rd/fmt/fmt/printf.h index fb57d235..ee4b06fd 100644 --- a/3rd/fmt/fmt/printf.h +++ b/3rd/fmt/fmt/printf.h @@ -8,7 +8,7 @@ #ifndef FMT_PRINTF_H_ #define FMT_PRINTF_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include // std::max # include // std::numeric_limits #endif @@ -36,12 +36,8 @@ template class basic_printf_context { using parse_context_type = basic_format_parse_context; template using formatter_type = printf_formatter; - /** - \rst - Constructs a ``printf_context`` object. References to the arguments are - stored in the context object so make sure they have appropriate lifetimes. - \endrst - */ + /// Constructs a `printf_context` object. References to the arguments are + /// stored in the context object so make sure they have appropriate lifetimes. basic_printf_context(basic_appender out, basic_format_args args) : out_(out), args_(args) {} @@ -227,7 +223,7 @@ auto make_arg_formatter(basic_appender iter, format_specs& s) return {iter, s, locale_ref()}; } -// The ``printf`` argument formatter. +// The `printf` argument formatter. template class printf_arg_formatter : public arg_formatter { private: @@ -276,7 +272,6 @@ class printf_arg_formatter : public arg_formatter { base::operator()(value); } - /** Formats a null-terminated C string. */ void operator()(const char* value) { if (value) base::operator()(value); @@ -284,7 +279,6 @@ class printf_arg_formatter : public arg_formatter { write_null_pointer(this->specs.type != presentation_type::pointer); } - /** Formats a null-terminated wide C string. */ void operator()(const wchar_t* value) { if (value) base::operator()(value); @@ -294,7 +288,6 @@ class printf_arg_formatter : public arg_formatter { void operator()(basic_string_view value) { base::operator()(value); } - /** Formats a pointer. */ void operator()(const void* value) { if (value) base::operator()(value); @@ -302,7 +295,6 @@ class printf_arg_formatter : public arg_formatter { write_null_pointer(); } - /** Formats an argument of a custom (user-defined) type. */ void operator()(typename basic_format_arg::handle handle) { auto parse_ctx = basic_format_parse_context({}); handle.format(parse_ctx, context_); @@ -573,12 +565,8 @@ using wprintf_context = basic_printf_context; using printf_args = basic_format_args; using wprintf_args = basic_format_args; -/** - \rst - Constructs an `~fmt::format_arg_store` object that contains references to - arguments and can be implicitly converted to `~fmt::printf_args`. - \endrst - */ +/// Constructs an `format_arg_store` object that contains references to +/// arguments and can be implicitly converted to `printf_args`. template inline auto make_printf_args(T&... args) -> decltype(make_format_args>(args...)) { @@ -599,14 +587,13 @@ inline auto vsprintf(basic_string_view fmt, } /** - \rst - Formats arguments and returns the result as a string. - - **Example**:: - - std::string message = fmt::sprintf("The answer is %d", 42); - \endrst -*/ + * Formats `args` according to specifications in `fmt` and returns the result + * as as string. + * + * **Example**: + * + * std::string message = fmt::sprintf("The answer is %d", 42); + */ template > inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string { return vsprintf(detail::to_string_view(fmt), @@ -625,13 +612,12 @@ inline auto vfprintf(std::FILE* f, basic_string_view fmt, } /** - \rst - Prints formatted data to the file *f*. - - **Example**:: - - fmt::fprintf(stderr, "Don't %s!", "panic"); - \endrst + * Formats `args` according to specifications in `fmt` and writes the output + * to `f`. + * + * **Example**: + * + * fmt::fprintf(stderr, "Don't %s!", "panic"); */ template > inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int { @@ -647,13 +633,12 @@ FMT_DEPRECATED inline auto vprintf(basic_string_view fmt, } /** - \rst - Prints formatted data to ``stdout``. - - **Example**:: - - fmt::printf("Elapsed time: %.2f seconds", 1.23); - \endrst + * Formats `args` according to specifications in `fmt` and writes the output + * to `stdout`. + * + * **Example**: + * + * fmt::printf("Elapsed time: %.2f seconds", 1.23); */ template inline auto printf(string_view fmt, const T&... args) -> int { diff --git a/3rd/fmt/fmt/ranges.h b/3rd/fmt/fmt/ranges.h index 86f9e01e..f387903c 100644 --- a/3rd/fmt/fmt/ranges.h +++ b/3rd/fmt/fmt/ranges.h @@ -8,17 +8,22 @@ #ifndef FMT_RANGES_H_ #define FMT_RANGES_H_ -#ifndef FMT_IMPORT_STD +#ifndef FMT_MODULE # include # include +# include # include # include +# include #endif #include "format.h" FMT_BEGIN_NAMESPACE +FMT_EXPORT +enum class range_format { disabled, map, set, sequence, string, debug_string }; + namespace detail { template class is_map { @@ -65,17 +70,17 @@ template struct has_member_fn_begin_end_t : std::false_type {}; template -struct has_member_fn_begin_end_t().begin()), +struct has_member_fn_begin_end_t().begin()), decltype(std::declval().end())>> : std::true_type {}; -// Member function overload +// Member function overloads. template auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast(rng).begin()); template auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast(rng).end()); -// ADL overload. Only participates in overload resolution if member functions +// ADL overloads. Only participate in overload resolution if member functions // are not found. template auto range_begin(T&& rng) @@ -96,15 +101,15 @@ struct has_mutable_begin_end : std::false_type {}; template struct has_const_begin_end< - T, - void_t< - decltype(detail::range_begin(std::declval&>())), - decltype(detail::range_end(std::declval&>()))>> + T, void_t&>())), + decltype(detail::range_end( + std::declval&>()))>> : std::true_type {}; template struct has_mutable_begin_end< - T, void_t())), + T, void_t())), decltype(detail::range_end(std::declval())), // the extra int here is because older versions of MSVC don't // SFINAE properly unless there are distinct types @@ -248,6 +253,18 @@ FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set) template FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {} +template +struct range_format_kind_ + : std::integral_constant, T>::value + ? range_format::disabled + : is_map::value ? range_format::map + : is_set::value ? range_format::set + : range_format::sequence> {}; + +template +using range_format_constant = std::integral_constant; + // These are not generic lambdas for compatibility with C++11. template struct parse_empty_specs { template FMT_CONSTEXPR void operator()(Formatter& f) { @@ -392,6 +409,23 @@ struct range_formatter< detail::string_literal{}; bool is_debug = false; + template ::value)> + auto write_debug_string(Output& out, It it, Sentinel end) const -> Output { + auto buf = basic_memory_buffer(); + for (; it != end; ++it) buf.push_back(*it); + auto specs = format_specs(); + specs.type = presentation_type::debug; + return detail::write( + out, basic_string_view(buf.data(), buf.size()), specs); + } + + template ::value)> + auto write_debug_string(Output& out, It, Sentinel) const -> Output { + return out; + } + public: FMT_CONSTEXPR range_formatter() {} @@ -450,25 +484,9 @@ struct range_formatter< return underlying_.parse(ctx); } - template ::value)> - auto write_debug_string(Output& out, It it, Sentinel end) const -> Output { - auto buf = basic_memory_buffer(); - for (; it != end; ++it) buf.push_back(*it); - auto specs = format_specs(); - specs.type = presentation_type::debug; - return detail::write( - out, basic_string_view(buf.data(), buf.size()), specs); - } - template ::value)> - auto write_debug_string(Output& out, It, Sentinel) const -> Output { - return out; - } - template auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) { - detail::range_mapper> mapper; + auto mapper = detail::range_mapper>(); auto out = ctx.out(); auto it = detail::range_begin(range); auto end = detail::range_end(range); @@ -479,7 +497,8 @@ struct range_formatter< for (; it != end; ++it) { if (i > 0) out = detail::copy(separator_, out); ctx.advance_to(out); - out = underlying_.format(mapper.map(*it), ctx); + auto&& item = *it; // Need an lvalue + out = underlying_.format(mapper.map(item), ctx); ++i; } out = detail::copy(closing_bracket_, out); @@ -487,81 +506,150 @@ struct range_formatter< } }; -enum class range_format { disabled, map, set, sequence, string, debug_string }; - -namespace detail { -template -struct range_format_kind_ - : std::integral_constant, 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; +FMT_EXPORT +template +struct range_format_kind + : conditional_t< + is_range::value, detail::range_format_kind_, + 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)>> { +template +struct formatter< + R, Char, + enable_if_t::value != range_format::disabled && + range_format_kind::value != range_format::map && + range_format_kind::value != range_format::string && + range_format_kind::value != range_format::debug_string> +// Workaround a bug in MSVC 2015 and earlier. +#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910 + , + detail::is_formattable_delayed +#endif + >::value>> { + private: using range_type = detail::maybe_const_range; - range_formatter, Char> underlying_; + range_formatter, Char> range_formatter_; - FMT_CONSTEXPR range_default_formatter() { init(range_format_constant()); } + public: + using nonlocking = void; + + FMT_CONSTEXPR formatter() { + if (detail::const_check(range_format_kind::value != + range_format::set)) + return; + range_formatter_.set_brackets(detail::string_literal{}, + detail::string_literal{}); + } - FMT_CONSTEXPR void init(range_format_constant) { - underlying_.set_brackets(detail::string_literal{}, - detail::string_literal{}); + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return range_formatter_.parse(ctx); } - 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{}); + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + return range_formatter_.format(range, ctx); } +}; + +// A map formatter. +template +struct formatter< + R, Char, + enable_if_t::value == range_format::map>> { + private: + using map_type = detail::maybe_const_range; + using element_type = detail::uncvref_type; - FMT_CONSTEXPR void init(range_format_constant) {} + decltype(detail::tuple::get_formatters( + detail::tuple_index_sequence())) formatters_; + bool no_delimiters_ = false; + + public: + FMT_CONSTEXPR formatter() {} template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { - return underlying_.parse(ctx); + auto it = ctx.begin(); + auto end = ctx.end(); + if (it != end) { + if (detail::to_ascii(*it) == 'n') { + no_delimiters_ = true; + ++it; + } + if (it != end && *it != '}') { + if (*it != ':') report_error("invalid format specifier"); + ++it; + } + ctx.advance_to(it); + } + detail::for_each(formatters_, detail::parse_empty_specs{ctx}); + return it; } template - auto format(range_type& range, FormatContext& ctx) const - -> decltype(ctx.out()) { - return underlying_.format(range, ctx); + auto format(map_type& map, FormatContext& ctx) const -> decltype(ctx.out()) { + auto out = ctx.out(); + basic_string_view open = detail::string_literal{}; + if (!no_delimiters_) out = detail::copy(open, out); + int i = 0; + auto mapper = detail::range_mapper>(); + basic_string_view sep = detail::string_literal{}; + for (auto&& value : map) { + if (i > 0) out = detail::copy(sep, out); + ctx.advance_to(out); + detail::for_each2(formatters_, mapper.map(value), + detail::format_tuple_element{ + 0, ctx, detail::string_literal{}}); + ++i; + } + basic_string_view close = detail::string_literal{}; + if (!no_delimiters_) out = detail::copy(close, out); + return out; } }; -} // namespace detail - -template -struct range_format_kind - : conditional_t< - is_range::value, detail::range_format_kind_, - std::integral_constant> {}; +// A (debug_)string formatter. 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> { + enable_if_t::value == range_format::string || + range_format_kind::value == + range_format::debug_string>> { + private: + using range_type = detail::maybe_const_range; + using string_type = + conditional_t, + decltype(detail::range_begin(std::declval())), + decltype(detail::range_end(std::declval()))>::value, + detail::std_string_view, std::basic_string>; + + formatter underlying_; + + public: + template + FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { + return underlying_.parse(ctx); + } + + template + auto format(range_type& range, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto out = ctx.out(); + if (detail::const_check(range_format_kind::value == + range_format::debug_string)) + *out++ = '"'; + out = underlying_.format( + string_type{detail::range_begin(range), detail::range_end(range)}, ctx); + if (detail::const_check(range_format_kind::value == + range_format::debug_string)) + *out++ = '"'; + return out; + } }; template @@ -571,7 +659,7 @@ struct join_view : detail::view { basic_string_view sep; join_view(It b, Sentinel e, basic_string_view s) - : begin(b), end(e), sep(s) {} + : begin(std::move(b)), end(e), sep(s) {} }; template @@ -585,77 +673,62 @@ struct formatter, Char> { #endif formatter, Char> value_formatter_; + using view_ref = conditional_t::value, + const join_view&, + join_view&&>; + public: + using nonlocking = void; + template FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* { return value_formatter_.parse(ctx); } template - auto format(const join_view& value, - FormatContext& ctx) const -> decltype(ctx.out()) { - auto it = value.begin; + auto format(view_ref& value, FormatContext& ctx) const + -> decltype(ctx.out()) { + auto it = std::forward(value).begin; auto out = ctx.out(); - if (it != value.end) { + if (it == value.end) return out; + out = value_formatter_.format(*it, ctx); + ++it; + while (it != value.end) { + out = detail::copy(value.sep.begin(), value.sep.end(), out); + ctx.advance_to(out); out = value_formatter_.format(*it, ctx); ++it; - while (it != value.end) { - out = detail::copy(value.sep.begin(), value.sep.end(), out); - ctx.advance_to(out); - out = value_formatter_.format(*it, ctx); - ++it; - } } return out; } }; -/** - Returns a view that formats the iterator range `[begin, end)` with elements - separated by `sep`. - */ +/// Returns a view that formats the iterator range `[begin, end)` with elements +/// separated by `sep`. template auto join(It begin, Sentinel end, string_view sep) -> join_view { - return {begin, end, sep}; -} - -namespace detail { -// ADL helpers for fmt::join() -namespace adl { -using std::begin; -using std::end; - -template auto adlbegin(Range& r) -> decltype(begin(r)) { - return begin(r); + return {std::move(begin), end, sep}; } -template auto adlend(Range& r) -> decltype(end(r)) { - return end(r); -} -} // namespace adl -} // namespace detail - /** - \rst - Returns a view that formats `range` with elements separated by `sep`. - - **Example**:: - - std::vector v = {1, 2, 3}; - fmt::print("{}", fmt::join(v, ", ")); - // Output: "1, 2, 3" - - ``fmt::join`` applies passed format specifiers to the range elements:: - - fmt::print("{:02}", fmt::join(v, ", ")); - // Output: "01, 02, 03" - \endrst + * Returns a view that formats `range` with elements separated by `sep`. + * + * **Example**: + * + * auto v = std::vector{1, 2, 3}; + * fmt::print("{}", fmt::join(v, ", ")); + * // Output: 1, 2, 3 + * + * `fmt::join` applies passed format specifiers to the range elements: + * + * fmt::print("{:02}", fmt::join(v, ", ")); + * // Output: 01, 02, 03 */ template -auto join(Range&& range, string_view sep) - -> join_view { - return join(detail::adl::adlbegin(range), detail::adl::adlend(range), sep); +auto join(Range&& r, string_view sep) + -> join_view { + return {detail::range_begin(r), detail::range_end(r), sep}; } template struct tuple_join_view : detail::view { @@ -774,15 +847,13 @@ struct formatter< FMT_BEGIN_EXPORT /** - \rst - Returns an object that formats `tuple` with elements separated by `sep`. - - **Example**:: - - std::tuple t = {1, 'a'}; - fmt::print("{}", fmt::join(t, ", ")); - // Output: "1, a" - \endrst + * Returns an object that formats `std::tuple` with elements separated by `sep`. + * + * **Example**: + * + * auto t = std::tuple{1, 'a'}; + * fmt::print("{}", fmt::join(t, ", ")); + * // Output: 1, a */ template FMT_CONSTEXPR auto join(const std::tuple& tuple, string_view sep) @@ -791,15 +862,13 @@ FMT_CONSTEXPR auto join(const std::tuple& tuple, string_view sep) } /** - \rst - Returns an object that formats `initializer_list` with elements separated by - `sep`. - - **Example**:: - - fmt::print("{}", fmt::join({1, 2, 3}, ", ")); - // Output: "1, 2, 3" - \endrst + * Returns an object that formats `std::initializer_list` with elements + * separated by `sep`. + * + * **Example**: + * + * fmt::print("{}", fmt::join({1, 2, 3}, ", ")); + * // Output: "1, 2, 3" */ template auto join(std::initializer_list list, string_view sep) diff --git a/3rd/fmt/fmt/std.h b/3rd/fmt/fmt/std.h index 5a5026f9..01a61cee 100644 --- a/3rd/fmt/fmt/std.h +++ b/3rd/fmt/fmt/std.h @@ -8,7 +8,10 @@ #ifndef FMT_STD_H_ #define FMT_STD_H_ -#ifndef FMT_IMPORT_STD +#include "format.h" +#include "ostream.h" + +#ifndef FMT_MODULE # include # include # include @@ -20,17 +23,8 @@ # include # include # include -#endif - -#include "format.h" -#include "ostream.h" -#if FMT_HAS_INCLUDE() -# include -#endif - -#ifndef FMT_IMPORT_STD -// Checking FMT_CPLUSPLUS for warning suppression in MSVC. +// Check FMT_CPLUSPLUS to suppress a bogus warning in MSVC. # if FMT_CPLUSPLUS >= 201703L # if FMT_HAS_INCLUDE() # include @@ -42,14 +36,18 @@ # include # endif # endif - -# if FMT_HAS_INCLUDE() && FMT_CPLUSPLUS > 202002L -# include -# endif - +// Use > instead of >= in the version check because may be +// available after C++17 but before C++20 is marked as implemented. # if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE() # include # endif +# if FMT_CPLUSPLUS > 202002L && FMT_HAS_INCLUDE() +# include +# endif +#endif // FMT_MODULE + +#if FMT_HAS_INCLUDE() +# include #endif // GCC 4 does not support FMT_HAS_INCLUDE. @@ -62,17 +60,6 @@ # endif #endif -// Check if typeid is available. -#ifndef FMT_USE_TYPEID -// __RTTI is for EDG compilers. _CPPRTTI is for MSVC. -# if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \ - 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 @@ -171,6 +158,22 @@ template struct formatter { 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 @@ -427,6 +430,95 @@ template struct formatter { } }; +#if FMT_USE_RTTI +namespace detail { + +template +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 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(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(out, string_view(ti.name())); +# endif +} + +} // namespace detail + +FMT_EXPORT +template +struct formatter { + public: + FMT_CONSTEXPR auto parse(basic_format_parse_context& ctx) + -> decltype(ctx.begin()) { + return ctx.begin(); + } + + template + auto format(const std::type_info& ti, Context& ctx) const + -> decltype(ctx.out()) { + return detail::write_demangled_name(ctx.out(), ti); + } +}; +#endif + FMT_EXPORT template struct formatter< @@ -443,7 +535,7 @@ 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; } @@ -452,65 +544,14 @@ struct formatter< 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())); - -#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 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(out, typeid(ex)); + *out++ = ':'; + *out++ = ' '; } - out = detail::write_bytes(out, demangled_name_view); -# 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); -# else - out = detail::write_bytes(out, string_view(ti.name()) - }); -# endif - *out++ = ':'; - *out++ = ' '; - return detail::write_bytes(out, string_view(ex.what())); #endif + return detail::write_bytes(out, string_view(ex.what())); } }; diff --git a/3rd/fmt/fmt/xchar.h b/3rd/fmt/fmt/xchar.h index a6bf47fe..b1f39ed2 100644 --- a/3rd/fmt/fmt/xchar.h +++ b/3rd/fmt/fmt/xchar.h @@ -8,27 +8,20 @@ #ifndef FMT_XCHAR_H_ #define FMT_XCHAR_H_ -#ifndef FMT_IMPORT_STD -# include -#endif - #include "color.h" #include "format.h" #include "ranges.h" -#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) && !defined(FMT_IMPORT_STD) -# include +#ifndef FMT_MODULE +# include +# if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) +# include +# endif #endif FMT_BEGIN_NAMESPACE namespace detail { -#ifdef __cpp_char8_t -using char8_type = char8_t; -#else -enum char8_type : unsigned char {}; -#endif - template using is_exotic_char = bool_constant::value>; @@ -83,10 +76,14 @@ inline auto runtime(wstring_view s) -> runtime_format_string { #endif template <> struct is_char : std::true_type {}; -template <> struct is_char : std::true_type {}; template <> struct is_char : std::true_type {}; template <> struct is_char : std::true_type {}; +#ifdef __cpp_char8_t +template <> +struct is_char : bool_constant {}; +#endif + template constexpr auto make_wformat_args(T&... args) -> decltype(fmt::make_format_args(args...)) { @@ -315,9 +312,7 @@ FMT_DEPRECATED void print(const text_style& ts, wformat_string fmt, return print(stdout, ts, fmt, args...); } -/** - Converts *value* to ``std::wstring`` using the default format for type *T*. - */ +/// Converts `value` to `std::wstring` using the default format for type `T`. template inline auto to_wstring(const T& value) -> std::wstring { return format(FMT_STRING(L"{}"), value); }