mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-10-30 13:57:20 +01:00 
			
		
		
		
	Update fmt library.
This commit is contained in:
		
							
								
								
									
										232
									
								
								vendor/Fmt/include/fmt/args.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								vendor/Fmt/include/fmt/args.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | ||||
| // Formatting library for C++ - dynamic format arguments | ||||
| // | ||||
| // Copyright (c) 2012 - present, Victor Zverovich | ||||
| // All rights reserved. | ||||
| // | ||||
| // For the license information refer to format.h. | ||||
|  | ||||
| #ifndef FMT_ARGS_H_ | ||||
| #define FMT_ARGS_H_ | ||||
|  | ||||
| #include <functional>  // std::reference_wrapper | ||||
| #include <memory>      // std::unique_ptr | ||||
| #include <vector> | ||||
|  | ||||
| #include "core.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| namespace detail { | ||||
|  | ||||
| template <typename T> struct is_reference_wrapper : std::false_type {}; | ||||
| template <typename T> | ||||
| struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {}; | ||||
|  | ||||
| template <typename T> const T& unwrap(const T& v) { return v; } | ||||
| template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) { | ||||
|   return static_cast<const T&>(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 <typename = void> struct node { | ||||
|     virtual ~node() = default; | ||||
|     std::unique_ptr<node<>> next; | ||||
|   }; | ||||
|  | ||||
|   template <typename T> struct typed_node : node<> { | ||||
|     T value; | ||||
|  | ||||
|     template <typename Arg> | ||||
|     FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} | ||||
|  | ||||
|     template <typename Char> | ||||
|     FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg) | ||||
|         : value(arg.data(), arg.size()) {} | ||||
|   }; | ||||
|  | ||||
|   std::unique_ptr<node<>> head_; | ||||
|  | ||||
|  public: | ||||
|   template <typename T, typename Arg> const T& push(const Arg& arg) { | ||||
|     auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg)); | ||||
|     auto& value = new_node->value; | ||||
|     new_node->next = std::move(head_); | ||||
|     head_ = std::move(new_node); | ||||
|     return value; | ||||
|   } | ||||
| }; | ||||
| }  // 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 | ||||
|  */ | ||||
| template <typename Context> | ||||
| class dynamic_format_arg_store | ||||
| #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 | ||||
|     // Workaround a GCC template argument substitution bug. | ||||
|     : public basic_format_args<Context> | ||||
| #endif | ||||
| { | ||||
|  private: | ||||
|   using char_type = typename Context::char_type; | ||||
|  | ||||
|   template <typename T> struct need_copy { | ||||
|     static constexpr detail::type mapped_type = | ||||
|         detail::mapped_type_constant<T, Context>::value; | ||||
|  | ||||
|     enum { | ||||
|       value = !(detail::is_reference_wrapper<T>::value || | ||||
|                 std::is_same<T, basic_string_view<char_type>>::value || | ||||
|                 std::is_same<T, detail::std_string_view<char_type>>::value || | ||||
|                 (mapped_type != detail::type::cstring_type && | ||||
|                  mapped_type != detail::type::string_type && | ||||
|                  mapped_type != detail::type::custom_type)) | ||||
|     }; | ||||
|   }; | ||||
|  | ||||
|   template <typename T> | ||||
|   using stored_type = conditional_t<detail::is_string<T>::value && | ||||
|                                         !has_formatter<T, Context>::value && | ||||
|                                         !detail::is_reference_wrapper<T>::value, | ||||
|                                     std::basic_string<char_type>, T>; | ||||
|  | ||||
|   // Storage of basic_format_arg must be contiguous. | ||||
|   std::vector<basic_format_arg<Context>> data_; | ||||
|   std::vector<detail::named_arg_info<char_type>> named_info_; | ||||
|  | ||||
|   // Storage of arguments not fitting into basic_format_arg must grow | ||||
|   // without relocation because items in data_ refer to it. | ||||
|   detail::dynamic_arg_list dynamic_args_; | ||||
|  | ||||
|   friend class basic_format_args<Context>; | ||||
|  | ||||
|   unsigned long long get_types() const { | ||||
|     return detail::is_unpacked_bit | data_.size() | | ||||
|            (named_info_.empty() | ||||
|                 ? 0ULL | ||||
|                 : static_cast<unsigned long long>(detail::has_named_args_bit)); | ||||
|   } | ||||
|  | ||||
|   const basic_format_arg<Context>* data() const { | ||||
|     return named_info_.empty() ? data_.data() : data_.data() + 1; | ||||
|   } | ||||
|  | ||||
|   template <typename T> void emplace_arg(const T& arg) { | ||||
|     data_.emplace_back(detail::make_arg<Context>(arg)); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   void emplace_arg(const detail::named_arg<char_type, T>& arg) { | ||||
|     if (named_info_.empty()) { | ||||
|       constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr}; | ||||
|       data_.insert(data_.begin(), {zero_ptr, 0}); | ||||
|     } | ||||
|     data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value))); | ||||
|     auto pop_one = [](std::vector<basic_format_arg<Context>>* data) { | ||||
|       data->pop_back(); | ||||
|     }; | ||||
|     std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)> | ||||
|         guard{&data_, pop_one}; | ||||
|     named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)}); | ||||
|     data_[0].value_.named_args = {named_info_.data(), named_info_.size()}; | ||||
|     guard.release(); | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   /** | ||||
|     \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<fmt::format_context> store; | ||||
|       store.push_back(42); | ||||
|       store.push_back("abc"); | ||||
|       store.push_back(1.5f); | ||||
|       std::string result = fmt::vformat("{} and {} and {}", store); | ||||
|     \endrst | ||||
|   */ | ||||
|   template <typename T> void push_back(const T& arg) { | ||||
|     if (detail::const_check(need_copy<T>::value)) | ||||
|       emplace_arg(dynamic_args_.push<stored_type<T>>(arg)); | ||||
|     else | ||||
|       emplace_arg(detail::unwrap(arg)); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|     \rst | ||||
|     Adds a reference to the argument into the dynamic store for later passing to | ||||
|     a formatting function. | ||||
|  | ||||
|     **Example**:: | ||||
|  | ||||
|       fmt::dynamic_format_arg_store<fmt::format_context> 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 | ||||
|   */ | ||||
|   template <typename T> void push_back(std::reference_wrapper<T> arg) { | ||||
|     static_assert( | ||||
|         need_copy<T>::value, | ||||
|         "objects of built-in types and string views are always copied"); | ||||
|     emplace_arg(arg.get()); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|     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 <typename T> | ||||
|   void push_back(const detail::named_arg<char_type, T>& arg) { | ||||
|     const char_type* arg_name = | ||||
|         dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str(); | ||||
|     if (detail::const_check(need_copy<T>::value)) { | ||||
|       emplace_arg( | ||||
|           fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value))); | ||||
|     } else { | ||||
|       emplace_arg(fmt::arg(arg_name, arg.value)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** 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 | ||||
|   */ | ||||
|   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"); | ||||
|     data_.reserve(new_cap); | ||||
|     named_info_.reserve(new_cap_named); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_ARGS_H_ | ||||
							
								
								
									
										214
									
								
								vendor/Fmt/include/fmt/chrono.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										214
									
								
								vendor/Fmt/include/fmt/chrono.h
									
									
									
									
										vendored
									
									
								
							| @@ -8,6 +8,7 @@ | ||||
| #ifndef FMT_CHRONO_H_ | ||||
| #define FMT_CHRONO_H_ | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <chrono> | ||||
| #include <ctime> | ||||
| #include <locale> | ||||
| @@ -288,7 +289,11 @@ inline null<> gmtime_r(...) { return null<>(); } | ||||
| inline null<> gmtime_s(...) { return null<>(); } | ||||
| }  // namespace detail | ||||
|  | ||||
| // Thread-safe replacement for std::localtime | ||||
| /** | ||||
|   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 std::tm localtime(std::time_t time) { | ||||
|   struct dispatcher { | ||||
|     std::time_t time_; | ||||
| @@ -330,7 +335,11 @@ inline std::tm localtime( | ||||
|   return localtime(std::chrono::system_clock::to_time_t(time_point)); | ||||
| } | ||||
|  | ||||
| // Thread-safe replacement for std::gmtime | ||||
| /** | ||||
|   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 std::tm gmtime(std::time_t time) { | ||||
|   struct dispatcher { | ||||
|     std::time_t time_; | ||||
| @@ -374,12 +383,21 @@ inline std::tm gmtime( | ||||
| namespace detail { | ||||
| inline size_t strftime(char* str, size_t count, const char* format, | ||||
|                        const std::tm* time) { | ||||
|   return std::strftime(str, count, format, time); | ||||
|   // Assign to a pointer to suppress GCCs -Wformat-nonliteral | ||||
|   // First assign the nullptr to suppress -Wsuggest-attribute=format | ||||
|   std::size_t (*strftime)(char*, std::size_t, const char*, const std::tm*) = | ||||
|       nullptr; | ||||
|   strftime = std::strftime; | ||||
|   return strftime(str, count, format, time); | ||||
| } | ||||
|  | ||||
| inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format, | ||||
|                        const std::tm* time) { | ||||
|   return std::wcsftime(str, count, format, time); | ||||
|   // See above | ||||
|   std::size_t (*wcsftime)(wchar_t*, std::size_t, const wchar_t*, | ||||
|                           const std::tm*) = nullptr; | ||||
|   wcsftime = std::wcsftime; | ||||
|   return wcsftime(str, count, format, time); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| @@ -396,19 +414,21 @@ struct formatter<std::chrono::time_point<std::chrono::system_clock>, Char> | ||||
|  | ||||
| template <typename Char> struct formatter<std::tm, Char> { | ||||
|   template <typename ParseContext> | ||||
|   auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     auto it = ctx.begin(); | ||||
|     if (it != ctx.end() && *it == ':') ++it; | ||||
|     auto end = it; | ||||
|     while (end != ctx.end() && *end != '}') ++end; | ||||
|     tm_format.reserve(detail::to_unsigned(end - it + 1)); | ||||
|     tm_format.append(it, end); | ||||
|     tm_format.push_back('\0'); | ||||
|     specs = {it, detail::to_unsigned(end - it)}; | ||||
|     return end; | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|   auto format(const std::tm& tm, FormatContext& ctx) const | ||||
|       -> decltype(ctx.out()) { | ||||
|     basic_memory_buffer<Char> tm_format; | ||||
|     tm_format.append(specs.begin(), specs.end()); | ||||
|     tm_format.push_back('\0'); | ||||
|     basic_memory_buffer<Char> buf; | ||||
|     size_t start = buf.size(); | ||||
|     for (;;) { | ||||
| @@ -431,34 +451,68 @@ template <typename Char> struct formatter<std::tm, Char> { | ||||
|     return std::copy(buf.begin(), buf.end(), ctx.out()); | ||||
|   } | ||||
|  | ||||
|   basic_memory_buffer<Char> tm_format; | ||||
|   basic_string_view<Char> specs; | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
| template <typename Period> FMT_CONSTEXPR const char* get_units() { | ||||
|   return nullptr; | ||||
| } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::atto>() { return "as"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::femto>() { return "fs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::pico>() { return "ps"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::nano>() { return "ns"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::micro>() { return "µs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::milli>() { return "ms"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::centi>() { return "cs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::deci>() { return "ds"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::deca>() { return "das"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::hecto>() { return "hs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::kilo>() { return "ks"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::mega>() { return "Ms"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::giga>() { return "Gs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::tera>() { return "Ts"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::peta>() { return "Ps"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::exa>() { return "Es"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::ratio<60>>() { | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::atto>() { | ||||
|   return "as"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::femto>() { | ||||
|   return "fs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::pico>() { | ||||
|   return "ps"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::nano>() { | ||||
|   return "ns"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::micro>() { | ||||
|   return "µs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::milli>() { | ||||
|   return "ms"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::centi>() { | ||||
|   return "cs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::deci>() { | ||||
|   return "ds"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<1>>() { | ||||
|   return "s"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::deca>() { | ||||
|   return "das"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::hecto>() { | ||||
|   return "hs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::kilo>() { | ||||
|   return "ks"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::mega>() { | ||||
|   return "Ms"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::giga>() { | ||||
|   return "Gs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::tera>() { | ||||
|   return "Ts"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::peta>() { | ||||
|   return "Ps"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::exa>() { | ||||
|   return "Es"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<60>>() { | ||||
|   return "m"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::ratio<3600>>() { | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<3600>>() { | ||||
|   return "h"; | ||||
| } | ||||
|  | ||||
| @@ -629,28 +683,29 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin, | ||||
| struct chrono_format_checker { | ||||
|   FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); } | ||||
|  | ||||
|   template <typename Char> void on_text(const Char*, const Char*) {} | ||||
|   template <typename Char> | ||||
|   FMT_CONSTEXPR void on_text(const Char*, const Char*) {} | ||||
|   FMT_NORETURN void on_abbr_weekday() { report_no_date(); } | ||||
|   FMT_NORETURN void on_full_weekday() { report_no_date(); } | ||||
|   FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_abbr_month() { report_no_date(); } | ||||
|   FMT_NORETURN void on_full_month() { report_no_date(); } | ||||
|   void on_24_hour(numeric_system) {} | ||||
|   void on_12_hour(numeric_system) {} | ||||
|   void on_minute(numeric_system) {} | ||||
|   void on_second(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_24_hour(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_12_hour(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_minute(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_second(numeric_system) {} | ||||
|   FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_us_date() { report_no_date(); } | ||||
|   FMT_NORETURN void on_iso_date() { report_no_date(); } | ||||
|   void on_12_hour_time() {} | ||||
|   void on_24_hour_time() {} | ||||
|   void on_iso_time() {} | ||||
|   void on_am_pm() {} | ||||
|   void on_duration_value() {} | ||||
|   void on_duration_unit() {} | ||||
|   FMT_CONSTEXPR void on_12_hour_time() {} | ||||
|   FMT_CONSTEXPR void on_24_hour_time() {} | ||||
|   FMT_CONSTEXPR void on_iso_time() {} | ||||
|   FMT_CONSTEXPR void on_am_pm() {} | ||||
|   FMT_CONSTEXPR void on_duration_value() {} | ||||
|   FMT_CONSTEXPR void on_duration_unit() {} | ||||
|   FMT_NORETURN void on_utc_offset() { report_no_date(); } | ||||
|   FMT_NORETURN void on_tz_name() { report_no_date(); } | ||||
| }; | ||||
| @@ -676,7 +731,8 @@ inline bool isfinite(T value) { | ||||
| // Converts value to int and checks that it's in the range [0, upper). | ||||
| template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> | ||||
| inline int to_nonnegative_int(T value, int upper) { | ||||
|   FMT_ASSERT(value >= 0 && value <= upper, "invalid value"); | ||||
|   FMT_ASSERT(value >= 0 && to_unsigned(value) <= to_unsigned(upper), | ||||
|              "invalid value"); | ||||
|   (void)upper; | ||||
|   return static_cast<int>(value); | ||||
| } | ||||
| @@ -754,15 +810,21 @@ inline std::chrono::duration<Rep, std::milli> get_milliseconds( | ||||
|   return std::chrono::duration<Rep, std::milli>(static_cast<Rep>(ms)); | ||||
| } | ||||
|  | ||||
| template <typename Char, typename Rep, typename OutputIt> | ||||
| OutputIt format_duration_value(OutputIt out, Rep val, int precision) { | ||||
|   const Char pr_f[] = {'{', ':', '.', '{', '}', 'f', '}', 0}; | ||||
|   if (precision >= 0) return format_to(out, pr_f, val, precision); | ||||
|   const Char fp_f[] = {'{', ':', 'g', '}', 0}; | ||||
|   const Char format[] = {'{', '}', 0}; | ||||
|   return format_to(out, std::is_floating_point<Rep>::value ? fp_f : format, | ||||
|                    val); | ||||
| template <typename Char, typename Rep, typename OutputIt, | ||||
|           FMT_ENABLE_IF(std::is_integral<Rep>::value)> | ||||
| OutputIt format_duration_value(OutputIt out, Rep val, int) { | ||||
|   return write<Char>(out, val); | ||||
| } | ||||
|  | ||||
| template <typename Char, typename Rep, typename OutputIt, | ||||
|           FMT_ENABLE_IF(std::is_floating_point<Rep>::value)> | ||||
| OutputIt format_duration_value(OutputIt out, Rep val, int precision) { | ||||
|   auto specs = basic_format_specs<Char>(); | ||||
|   specs.precision = precision; | ||||
|   specs.type = precision > 0 ? 'f' : 'g'; | ||||
|   return write<Char>(out, val, specs); | ||||
| } | ||||
|  | ||||
| template <typename Char, typename OutputIt> | ||||
| OutputIt copy_unit(string_view unit, OutputIt out, Char) { | ||||
|   return std::copy(unit.begin(), unit.end(), out); | ||||
| @@ -780,10 +842,15 @@ template <typename Char, typename Period, typename OutputIt> | ||||
| OutputIt format_duration_unit(OutputIt out) { | ||||
|   if (const char* unit = get_units<Period>()) | ||||
|     return copy_unit(string_view(unit), out, Char()); | ||||
|   const Char num_f[] = {'[', '{', '}', ']', 's', 0}; | ||||
|   if (const_check(Period::den == 1)) return format_to(out, num_f, Period::num); | ||||
|   const Char num_def_f[] = {'[', '{', '}', '/', '{', '}', ']', 's', 0}; | ||||
|   return format_to(out, num_def_f, Period::num, Period::den); | ||||
|   *out++ = '['; | ||||
|   out = write<Char>(out, Period::num); | ||||
|   if (const_check(Period::den != 1)) { | ||||
|     *out++ = '/'; | ||||
|     out = write<Char>(out, Period::den); | ||||
|   } | ||||
|   *out++ = ']'; | ||||
|   *out++ = 's'; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| template <typename FormatContext, typename OutputIt, typename Rep, | ||||
| @@ -1011,11 +1078,11 @@ template <typename Rep, typename Period, typename Char> | ||||
| struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|  private: | ||||
|   basic_format_specs<Char> specs; | ||||
|   int precision; | ||||
|   int precision = -1; | ||||
|   using arg_ref_type = detail::arg_ref<Char>; | ||||
|   arg_ref_type width_ref; | ||||
|   arg_ref_type precision_ref; | ||||
|   mutable basic_string_view<Char> format_str; | ||||
|   basic_string_view<Char> format_str; | ||||
|   using duration = std::chrono::duration<Rep, Period>; | ||||
|  | ||||
|   struct spec_handler { | ||||
| @@ -1038,17 +1105,21 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|     } | ||||
|  | ||||
|     void on_error(const char* msg) { FMT_THROW(format_error(msg)); } | ||||
|     void on_fill(basic_string_view<Char> fill) { f.specs.fill = fill; } | ||||
|     void on_align(align_t align) { f.specs.align = align; } | ||||
|     void on_width(int width) { f.specs.width = width; } | ||||
|     void on_precision(int _precision) { f.precision = _precision; } | ||||
|     void end_precision() {} | ||||
|     FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) { | ||||
|       f.specs.fill = fill; | ||||
|     } | ||||
|     FMT_CONSTEXPR void on_align(align_t align) { f.specs.align = align; } | ||||
|     FMT_CONSTEXPR void on_width(int width) { f.specs.width = width; } | ||||
|     FMT_CONSTEXPR void on_precision(int _precision) { | ||||
|       f.precision = _precision; | ||||
|     } | ||||
|     FMT_CONSTEXPR void end_precision() {} | ||||
|  | ||||
|     template <typename Id> void on_dynamic_width(Id arg_id) { | ||||
|     template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) { | ||||
|       f.width_ref = make_arg_ref(arg_id); | ||||
|     } | ||||
|  | ||||
|     template <typename Id> void on_dynamic_precision(Id arg_id) { | ||||
|     template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) { | ||||
|       f.precision_ref = make_arg_ref(arg_id); | ||||
|     } | ||||
|   }; | ||||
| @@ -1078,8 +1149,6 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   formatter() : precision(-1) {} | ||||
|  | ||||
|   FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) | ||||
|       -> decltype(ctx.begin()) { | ||||
|     auto range = do_parse(ctx); | ||||
| @@ -1089,27 +1158,30 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(const duration& d, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|   auto format(const duration& d, FormatContext& ctx) const | ||||
|       -> decltype(ctx.out()) { | ||||
|     auto specs_copy = specs; | ||||
|     auto precision_copy = precision; | ||||
|     auto begin = format_str.begin(), end = format_str.end(); | ||||
|     // As a possible future optimization, we could avoid extra copying if width | ||||
|     // is not specified. | ||||
|     basic_memory_buffer<Char> buf; | ||||
|     auto out = std::back_inserter(buf); | ||||
|     detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref, | ||||
|                                                        ctx); | ||||
|     detail::handle_dynamic_spec<detail::precision_checker>(precision, | ||||
|     detail::handle_dynamic_spec<detail::width_checker>(specs_copy.width, | ||||
|                                                        width_ref, ctx); | ||||
|     detail::handle_dynamic_spec<detail::precision_checker>(precision_copy, | ||||
|                                                            precision_ref, ctx); | ||||
|     if (begin == end || *begin == '}') { | ||||
|       out = detail::format_duration_value<Char>(out, d.count(), precision); | ||||
|       out = detail::format_duration_value<Char>(out, d.count(), precision_copy); | ||||
|       detail::format_duration_unit<Char, Period>(out); | ||||
|     } else { | ||||
|       detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f( | ||||
|           ctx, out, d); | ||||
|       f.precision = precision; | ||||
|       f.precision = precision_copy; | ||||
|       parse_chrono_format(begin, end, f); | ||||
|     } | ||||
|     return detail::write( | ||||
|         ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs); | ||||
|         ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy); | ||||
|   } | ||||
| }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										85
									
								
								vendor/Fmt/include/fmt/color.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										85
									
								
								vendor/Fmt/include/fmt/color.h
									
									
									
									
										vendored
									
									
								
							| @@ -10,6 +10,13 @@ | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| // __declspec(deprecated) is broken in some MSVC versions. | ||||
| #if FMT_MSC_VER | ||||
| #  define FMT_DEPRECATED_NONMSVC | ||||
| #else | ||||
| #  define FMT_DEPRECATED_NONMSVC FMT_DEPRECATED | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| enum class color : uint32_t { | ||||
| @@ -223,7 +230,7 @@ struct color_type { | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| // Experimental text formatting support. | ||||
| /** A text style consisting of foreground and background colors and emphasis. */ | ||||
| class text_style { | ||||
|  public: | ||||
|   FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT | ||||
| @@ -260,33 +267,14 @@ class text_style { | ||||
|     return lhs |= rhs; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR text_style& operator&=(const text_style& rhs) { | ||||
|     if (!set_foreground_color) { | ||||
|       set_foreground_color = rhs.set_foreground_color; | ||||
|       foreground_color = rhs.foreground_color; | ||||
|     } else if (rhs.set_foreground_color) { | ||||
|       if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb) | ||||
|         FMT_THROW(format_error("can't AND a terminal color")); | ||||
|       foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
|     if (!set_background_color) { | ||||
|       set_background_color = rhs.set_background_color; | ||||
|       background_color = rhs.background_color; | ||||
|     } else if (rhs.set_background_color) { | ||||
|       if (!background_color.is_rgb || !rhs.background_color.is_rgb) | ||||
|         FMT_THROW(format_error("can't AND a terminal color")); | ||||
|       background_color.value.rgb_color &= rhs.background_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
|     ems = static_cast<emphasis>(static_cast<uint8_t>(ems) & | ||||
|                                 static_cast<uint8_t>(rhs.ems)); | ||||
|     return *this; | ||||
|   FMT_DEPRECATED_NONMSVC FMT_CONSTEXPR text_style& operator&=( | ||||
|       const text_style& rhs) { | ||||
|     return and_assign(rhs); | ||||
|   } | ||||
|  | ||||
|   friend FMT_CONSTEXPR text_style operator&(text_style lhs, | ||||
|                                             const text_style& rhs) { | ||||
|     return lhs &= rhs; | ||||
|   FMT_DEPRECATED_NONMSVC friend FMT_CONSTEXPR text_style | ||||
|   operator&(text_style lhs, const text_style& rhs) { | ||||
|     return lhs.and_assign(rhs); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR bool has_foreground() const FMT_NOEXCEPT { | ||||
| @@ -326,8 +314,34 @@ class text_style { | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // DEPRECATED! | ||||
|   FMT_CONSTEXPR text_style& and_assign(const text_style& rhs) { | ||||
|     if (!set_foreground_color) { | ||||
|       set_foreground_color = rhs.set_foreground_color; | ||||
|       foreground_color = rhs.foreground_color; | ||||
|     } else if (rhs.set_foreground_color) { | ||||
|       if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb) | ||||
|         FMT_THROW(format_error("can't AND a terminal color")); | ||||
|       foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
|     if (!set_background_color) { | ||||
|       set_background_color = rhs.set_background_color; | ||||
|       background_color = rhs.background_color; | ||||
|     } else if (rhs.set_background_color) { | ||||
|       if (!background_color.is_rgb || !rhs.background_color.is_rgb) | ||||
|         FMT_THROW(format_error("can't AND a terminal color")); | ||||
|       background_color.value.rgb_color &= rhs.background_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
|     ems = static_cast<emphasis>(static_cast<uint8_t>(ems) & | ||||
|                                 static_cast<uint8_t>(rhs.ems)); | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   friend FMT_CONSTEXPR_DECL text_style fg(detail::color_type foreground) | ||||
|       FMT_NOEXCEPT; | ||||
|  | ||||
|   friend FMT_CONSTEXPR_DECL text_style bg(detail::color_type background) | ||||
|       FMT_NOEXCEPT; | ||||
|  | ||||
| @@ -338,15 +352,18 @@ class text_style { | ||||
|   emphasis ems; | ||||
| }; | ||||
|  | ||||
| FMT_CONSTEXPR text_style fg(detail::color_type foreground) FMT_NOEXCEPT { | ||||
|   return text_style(/*is_foreground=*/true, foreground); | ||||
| /** Creates a text style from the foreground (text) color. */ | ||||
| FMT_CONSTEXPR inline text_style fg(detail::color_type foreground) FMT_NOEXCEPT { | ||||
|   return text_style(true, foreground); | ||||
| } | ||||
|  | ||||
| FMT_CONSTEXPR text_style bg(detail::color_type background) FMT_NOEXCEPT { | ||||
|   return text_style(/*is_foreground=*/false, background); | ||||
| /** Creates a text style from the background color. */ | ||||
| FMT_CONSTEXPR inline text_style bg(detail::color_type background) FMT_NOEXCEPT { | ||||
|   return text_style(false, background); | ||||
| } | ||||
|  | ||||
| FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT { | ||||
| FMT_CONSTEXPR inline text_style operator|(emphasis lhs, | ||||
|                                           emphasis rhs) FMT_NOEXCEPT { | ||||
|   return text_style(lhs) | rhs; | ||||
| } | ||||
|  | ||||
| @@ -523,11 +540,15 @@ void print(std::FILE* f, const text_style& ts, const S& format_str, | ||||
| } | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   Formats a string and prints it to stdout using ANSI escape sequences to | ||||
|   specify text formatting. | ||||
|   Example: | ||||
|  | ||||
|   **Example**:: | ||||
|  | ||||
|     fmt::print(fmt::emphasis::bold | fg(fmt::color::red), | ||||
|                "Elapsed time: {0:.2f} seconds", 1.23); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_string<S>::value)> | ||||
|   | ||||
							
								
								
									
										363
									
								
								vendor/Fmt/include/fmt/compile.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										363
									
								
								vendor/Fmt/include/fmt/compile.h
									
									
									
									
										vendored
									
									
								
							| @@ -8,13 +8,102 @@ | ||||
| #ifndef FMT_COMPILE_H_ | ||||
| #define FMT_COMPILE_H_ | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <vector> | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| #ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| #  if defined(__cpp_nontype_template_parameter_class) && \ | ||||
|       (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 903) | ||||
| #    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1 | ||||
| #  else | ||||
| #    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0 | ||||
| #  endif | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| namespace detail { | ||||
|  | ||||
| template <typename OutputIt> class truncating_iterator_base { | ||||
|  protected: | ||||
|   OutputIt out_; | ||||
|   size_t limit_; | ||||
|   size_t count_ = 0; | ||||
|  | ||||
|   truncating_iterator_base() : out_(), limit_(0) {} | ||||
|  | ||||
|   truncating_iterator_base(OutputIt out, size_t limit) | ||||
|       : out_(out), limit_(limit) {} | ||||
|  | ||||
|  public: | ||||
|   using iterator_category = std::output_iterator_tag; | ||||
|   using value_type = typename std::iterator_traits<OutputIt>::value_type; | ||||
|   using difference_type = std::ptrdiff_t; | ||||
|   using pointer = void; | ||||
|   using reference = void; | ||||
|   using _Unchecked_type = | ||||
|       truncating_iterator_base;  // Mark iterator as checked. | ||||
|  | ||||
|   OutputIt base() const { return out_; } | ||||
|   size_t count() const { return count_; } | ||||
| }; | ||||
|  | ||||
| // An output iterator that truncates the output and counts the number of objects | ||||
| // written to it. | ||||
| template <typename OutputIt, | ||||
|           typename Enable = typename std::is_void< | ||||
|               typename std::iterator_traits<OutputIt>::value_type>::type> | ||||
| class truncating_iterator; | ||||
|  | ||||
| template <typename OutputIt> | ||||
| class truncating_iterator<OutputIt, std::false_type> | ||||
|     : public truncating_iterator_base<OutputIt> { | ||||
|   mutable typename truncating_iterator_base<OutputIt>::value_type blackhole_; | ||||
|  | ||||
|  public: | ||||
|   using value_type = typename truncating_iterator_base<OutputIt>::value_type; | ||||
|  | ||||
|   truncating_iterator() = default; | ||||
|  | ||||
|   truncating_iterator(OutputIt out, size_t limit) | ||||
|       : truncating_iterator_base<OutputIt>(out, limit) {} | ||||
|  | ||||
|   truncating_iterator& operator++() { | ||||
|     if (this->count_++ < this->limit_) ++this->out_; | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   truncating_iterator operator++(int) { | ||||
|     auto it = *this; | ||||
|     ++*this; | ||||
|     return it; | ||||
|   } | ||||
|  | ||||
|   value_type& operator*() const { | ||||
|     return this->count_ < this->limit_ ? *this->out_ : blackhole_; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename OutputIt> | ||||
| class truncating_iterator<OutputIt, std::true_type> | ||||
|     : public truncating_iterator_base<OutputIt> { | ||||
|  public: | ||||
|   truncating_iterator() = default; | ||||
|  | ||||
|   truncating_iterator(OutputIt out, size_t limit) | ||||
|       : truncating_iterator_base<OutputIt>(out, limit) {} | ||||
|  | ||||
|   template <typename T> truncating_iterator& operator=(T val) { | ||||
|     if (this->count_++ < this->limit_) *this->out_++ = val; | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   truncating_iterator& operator++() { return *this; } | ||||
|   truncating_iterator& operator++(int) { return *this; } | ||||
|   truncating_iterator& operator*() { return *this; } | ||||
| }; | ||||
|  | ||||
| // A compile-time string which is compiled into fast formatting code. | ||||
| class compiled_string {}; | ||||
|  | ||||
| @@ -36,6 +125,24 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {}; | ||||
|  */ | ||||
| #define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string) | ||||
|  | ||||
| #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| template <typename Char, size_t N> struct fixed_string { | ||||
|   constexpr fixed_string(const Char (&str)[N]) { | ||||
|     copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str), str + N, | ||||
|                                        data); | ||||
|   } | ||||
|   Char data[N]{}; | ||||
| }; | ||||
|  | ||||
| template <typename Char, size_t N, fixed_string<Char, N> Str> | ||||
| struct udl_compiled_string : compiled_string { | ||||
|   using char_type = Char; | ||||
|   constexpr operator basic_string_view<char_type>() const { | ||||
|     return {Str.data, N - 1}; | ||||
|   } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| template <typename T, typename... Tail> | ||||
| const T& first(const T& value, const Tail&...) { | ||||
|   return value; | ||||
| @@ -175,9 +282,9 @@ class format_string_compiler : public error_handler { | ||||
|     repl.arg_id = part_.part_kind == part::kind::arg_index | ||||
|                       ? arg_ref<Char>(part_.val.arg_index) | ||||
|                       : arg_ref<Char>(part_.val.str); | ||||
|     auto part = part::make_replacement(repl); | ||||
|     part.arg_id_end = begin; | ||||
|     handler_(part); | ||||
|     auto replacement_part = part::make_replacement(repl); | ||||
|     replacement_part.arg_id_end = begin; | ||||
|     handler_(replacement_part); | ||||
|     return it; | ||||
|   } | ||||
| }; | ||||
| @@ -195,9 +302,15 @@ template <typename OutputIt, typename Context, typename Id> | ||||
| void format_arg( | ||||
|     basic_format_parse_context<typename Context::char_type>& parse_ctx, | ||||
|     Context& ctx, Id arg_id) { | ||||
|   ctx.advance_to(visit_format_arg( | ||||
|       arg_formatter<OutputIt, typename Context::char_type>(ctx, &parse_ctx), | ||||
|       ctx.arg(arg_id))); | ||||
|   auto arg = ctx.arg(arg_id); | ||||
|   if (arg.type() == type::custom_type) { | ||||
|     visit_format_arg(custom_formatter<Context>(parse_ctx, ctx), arg); | ||||
|   } else { | ||||
|     ctx.advance_to(visit_format_arg( | ||||
|         default_arg_formatter<OutputIt, typename Context::char_type>{ | ||||
|             ctx.out(), ctx.args(), ctx.locale()}, | ||||
|         arg)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // vformat_to is defined in a subnamespace to prevent ADL. | ||||
| @@ -257,10 +370,9 @@ auto vformat_to(OutputIt out, CompiledFormat& cf, | ||||
|       if (specs.precision >= 0) checker.check_precision(); | ||||
|  | ||||
|       advance_to(parse_ctx, part.arg_id_end); | ||||
|       ctx.advance_to( | ||||
|           visit_format_arg(arg_formatter<OutputIt, typename Context::char_type>( | ||||
|                                ctx, nullptr, &specs), | ||||
|                            arg)); | ||||
|       ctx.advance_to(visit_format_arg( | ||||
|           arg_formatter<OutputIt, typename Context::char_type>(ctx, specs), | ||||
|           arg)); | ||||
|       break; | ||||
|     } | ||||
|     } | ||||
| @@ -393,7 +505,7 @@ template <typename Char> struct text { | ||||
|   using char_type = Char; | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   OutputIt format(OutputIt out, const Args&...) const { | ||||
|   constexpr OutputIt format(OutputIt out, const Args&...) const { | ||||
|     return write<Char>(out, data); | ||||
|   } | ||||
| }; | ||||
| @@ -412,7 +524,7 @@ template <typename Char> struct code_unit { | ||||
|   using char_type = Char; | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   OutputIt format(OutputIt out, const Args&...) const { | ||||
|   constexpr OutputIt format(OutputIt out, const Args&...) const { | ||||
|     return write<Char>(out, value); | ||||
|   } | ||||
| }; | ||||
| @@ -425,23 +537,60 @@ template <typename Char, typename T, int N> struct field { | ||||
|   using char_type = Char; | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     // This ensures that the argument type is convertile to `const T&`. | ||||
|     const T& arg = get<N>(args...); | ||||
|     return write<Char>(out, arg); | ||||
|   constexpr OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) { | ||||
|       const auto& arg = get<N>(args...).value; | ||||
|       return write<Char>(out, arg); | ||||
|     } else { | ||||
|       // This ensures that the argument type is convertile to `const T&`. | ||||
|       const T& arg = get<N>(args...); | ||||
|       return write<Char>(out, arg); | ||||
|     } | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename T, int N> | ||||
| struct is_compiled_format<field<Char, T, N>> : std::true_type {}; | ||||
|  | ||||
| // A replacement field that refers to argument with name. | ||||
| template <typename Char> struct runtime_named_field { | ||||
|   using char_type = Char; | ||||
|   basic_string_view<Char> name; | ||||
|  | ||||
|   template <typename OutputIt, typename T> | ||||
|   constexpr static bool try_format_argument( | ||||
|       OutputIt& out, | ||||
|       // [[maybe_unused]] due to unused-but-set-parameter warning in GCC 7,8,9 | ||||
|       [[maybe_unused]] basic_string_view<Char> arg_name, const T& arg) { | ||||
|     if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) { | ||||
|       if (arg_name == arg.name) { | ||||
|         out = write<Char>(out, arg.value); | ||||
|         return true; | ||||
|       } | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   constexpr OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     bool found = (try_format_argument(out, name, args) || ...); | ||||
|     if (!found) { | ||||
|       throw format_error("argument with specified name is not found"); | ||||
|     } | ||||
|     return out; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| struct is_compiled_format<runtime_named_field<Char>> : std::true_type {}; | ||||
|  | ||||
| // A replacement field that refers to argument N and has format specifiers. | ||||
| template <typename Char, typename T, int N> struct spec_field { | ||||
|   using char_type = Char; | ||||
|   mutable formatter<T, Char> fmt; | ||||
|   formatter<T, Char> fmt; | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   OutputIt format(OutputIt out, const Args&... args) const { | ||||
|   constexpr OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     // This ensures that the argument type is convertile to `const T&`. | ||||
|     const T& arg = get<N>(args...); | ||||
|     const auto& vargs = | ||||
| @@ -460,7 +609,7 @@ template <typename L, typename R> struct concat { | ||||
|   using char_type = typename L::char_type; | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   OutputIt format(OutputIt out, const Args&... args) const { | ||||
|   constexpr OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     out = lhs.format(out, args...); | ||||
|     return rhs.format(out, args...); | ||||
|   } | ||||
| @@ -508,14 +657,51 @@ template <typename T, typename Char> struct parse_specs_result { | ||||
|   int next_arg_id; | ||||
| }; | ||||
|  | ||||
| constexpr int manual_indexing_id = -1; | ||||
|  | ||||
| template <typename T, typename Char> | ||||
| constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str, | ||||
|                                                   size_t pos, int arg_id) { | ||||
|                                                   size_t pos, int next_arg_id) { | ||||
|   str.remove_prefix(pos); | ||||
|   auto ctx = basic_format_parse_context<Char>(str, {}, arg_id + 1); | ||||
|   auto ctx = basic_format_parse_context<Char>(str, {}, next_arg_id); | ||||
|   auto f = formatter<T, Char>(); | ||||
|   auto end = f.parse(ctx); | ||||
|   return {f, pos + (end - str.data()) + 1, ctx.next_arg_id()}; | ||||
|   return {f, pos + fmt::detail::to_unsigned(end - str.data()) + 1, | ||||
|           next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()}; | ||||
| } | ||||
|  | ||||
| template <typename Char> struct arg_id_handler { | ||||
|   constexpr void on_error(const char* message) { throw format_error(message); } | ||||
|  | ||||
|   constexpr int on_arg_id() { | ||||
|     FMT_ASSERT(false, "handler cannot be used with automatic indexing"); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   constexpr int on_arg_id(int id) { | ||||
|     arg_id = arg_ref<Char>(id); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   constexpr int on_arg_id(basic_string_view<Char> id) { | ||||
|     arg_id = arg_ref<Char>(id); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   arg_ref<Char> arg_id; | ||||
| }; | ||||
|  | ||||
| template <typename Char> struct parse_arg_id_result { | ||||
|   arg_ref<Char> arg_id; | ||||
|   const Char* arg_id_end; | ||||
| }; | ||||
|  | ||||
| template <int ID, typename Char> | ||||
| constexpr auto parse_arg_id(const Char* begin, const Char* end) { | ||||
|   auto handler = arg_id_handler<Char>{arg_ref<Char>{}}; | ||||
|   auto adapter = id_adapter<arg_id_handler<Char>, Char>{handler, 0}; | ||||
|   auto arg_id_end = parse_arg_id(begin, end, adapter); | ||||
|   return parse_arg_id_result<Char>{handler.arg_id, arg_id_end}; | ||||
| } | ||||
|  | ||||
| // Compiles a non-empty format string and returns the compiled representation | ||||
| @@ -525,24 +711,59 @@ constexpr auto compile_format_string(S format_str) { | ||||
|   using char_type = typename S::char_type; | ||||
|   constexpr basic_string_view<char_type> str = format_str; | ||||
|   if constexpr (str[POS] == '{') { | ||||
|     if (POS + 1 == str.size()) | ||||
|     if constexpr (POS + 1 == str.size()) | ||||
|       throw format_error("unmatched '{' in format string"); | ||||
|     if constexpr (str[POS + 1] == '{') { | ||||
|       return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str); | ||||
|     } else if constexpr (str[POS + 1] == '}') { | ||||
|       using type = get_type<ID, Args>; | ||||
|       return parse_tail<Args, POS + 2, ID + 1>(field<char_type, type, ID>(), | ||||
|                                                format_str); | ||||
|     } else if constexpr (str[POS + 1] == ':') { | ||||
|       using type = get_type<ID, Args>; | ||||
|       constexpr auto result = parse_specs<type>(str, POS + 2, ID); | ||||
|       return parse_tail<Args, result.end, result.next_arg_id>( | ||||
|           spec_field<char_type, type, ID>{result.fmt}, format_str); | ||||
|     } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { | ||||
|       static_assert(ID != manual_indexing_id, | ||||
|                     "cannot switch from manual to automatic argument indexing"); | ||||
|       using id_type = get_type<ID, Args>; | ||||
|       if constexpr (str[POS + 1] == '}') { | ||||
|         constexpr auto next_id = | ||||
|             ID != manual_indexing_id ? ID + 1 : manual_indexing_id; | ||||
|         return parse_tail<Args, POS + 2, next_id>( | ||||
|             field<char_type, id_type, ID>(), format_str); | ||||
|       } else { | ||||
|         constexpr auto result = parse_specs<id_type>(str, POS + 2, ID + 1); | ||||
|         return parse_tail<Args, result.end, result.next_arg_id>( | ||||
|             spec_field<char_type, id_type, ID>{result.fmt}, format_str); | ||||
|       } | ||||
|     } else { | ||||
|       return unknown_format(); | ||||
|       constexpr auto arg_id_result = | ||||
|           parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size()); | ||||
|       constexpr auto arg_id_end_pos = arg_id_result.arg_id_end - str.data(); | ||||
|       constexpr char_type c = | ||||
|           arg_id_end_pos != str.size() ? str[arg_id_end_pos] : char_type(); | ||||
|       static_assert(c == '}' || c == ':', "missing '}' in format string"); | ||||
|       if constexpr (arg_id_result.arg_id.kind == arg_id_kind::index) { | ||||
|         static_assert( | ||||
|             ID == manual_indexing_id || ID == 0, | ||||
|             "cannot switch from automatic to manual argument indexing"); | ||||
|         constexpr auto arg_index = arg_id_result.arg_id.val.index; | ||||
|         using id_type = get_type<arg_index, Args>; | ||||
|         if constexpr (c == '}') { | ||||
|           return parse_tail<Args, arg_id_end_pos + 1, manual_indexing_id>( | ||||
|               field<char_type, id_type, arg_index>(), format_str); | ||||
|         } else if constexpr (c == ':') { | ||||
|           constexpr auto result = | ||||
|               parse_specs<id_type>(str, arg_id_end_pos + 1, 0); | ||||
|           return parse_tail<Args, result.end, result.next_arg_id>( | ||||
|               spec_field<char_type, id_type, arg_index>{result.fmt}, | ||||
|               format_str); | ||||
|         } | ||||
|       } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) { | ||||
|         if constexpr (c == '}') { | ||||
|           return parse_tail<Args, arg_id_end_pos + 1, ID>( | ||||
|               runtime_named_field<char_type>{arg_id_result.arg_id.val.name}, | ||||
|               format_str); | ||||
|         } else if constexpr (c == ':') { | ||||
|           return unknown_format();  // no type info for specs parsing | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   } else if constexpr (str[POS] == '}') { | ||||
|     if (POS + 1 == str.size()) | ||||
|     if constexpr (POS + 1 == str.size()) | ||||
|       throw format_error("unmatched '}' in format string"); | ||||
|     return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str); | ||||
|   } else { | ||||
| @@ -568,12 +789,7 @@ constexpr auto compile(S format_str) { | ||||
|     constexpr auto result = | ||||
|         detail::compile_format_string<detail::type_list<Args...>, 0, 0>( | ||||
|             format_str); | ||||
|     if constexpr (std::is_same<remove_cvref_t<decltype(result)>, | ||||
|                                detail::unknown_format>()) { | ||||
|       return detail::compiled_format<S, Args...>(to_string_view(format_str)); | ||||
|     } else { | ||||
|       return result; | ||||
|     } | ||||
|     return result; | ||||
|   } | ||||
| } | ||||
| #else | ||||
| @@ -615,8 +831,8 @@ FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf, | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)> | ||||
| OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                    const Args&... args) { | ||||
| constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                              const Args&... args) { | ||||
|   return cf.format(out, args...); | ||||
| } | ||||
| #  endif  // __cpp_if_constexpr | ||||
| @@ -641,19 +857,36 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&, | ||||
| #ifdef __cpp_if_constexpr | ||||
|   if constexpr (std::is_same<typename S::char_type, char>::value) { | ||||
|     constexpr basic_string_view<typename S::char_type> str = S(); | ||||
|     if (str.size() == 2 && str[0] == '{' && str[1] == '}') | ||||
|       return fmt::to_string(detail::first(args...)); | ||||
|     if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { | ||||
|       const auto& first = detail::first(args...); | ||||
|       if constexpr (detail::is_named_arg< | ||||
|                         remove_cvref_t<decltype(first)>>::value) { | ||||
|         return fmt::to_string(first.value); | ||||
|       } else { | ||||
|         return fmt::to_string(first); | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
|   constexpr auto compiled = detail::compile<Args...>(S()); | ||||
| #ifdef __cpp_if_constexpr | ||||
|   if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>, | ||||
|                              detail::unknown_format>()) { | ||||
|     return format(static_cast<basic_string_view<typename S::char_type>>(S()), | ||||
|                   std::forward<Args>(args)...); | ||||
|   } else { | ||||
|     return format(compiled, std::forward<Args>(args)...); | ||||
|   } | ||||
| #else | ||||
|   return format(compiled, std::forward<Args>(args)...); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format, | ||||
|                                         CompiledFormat>::value)> | ||||
| OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                    const Args&... args) { | ||||
| constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                              const Args&... args) { | ||||
|   using char_type = typename CompiledFormat::char_type; | ||||
|   using context = format_context_t<OutputIt, char_type>; | ||||
|   return detail::cf::vformat_to<context>(out, cf, | ||||
| @@ -662,9 +895,20 @@ OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| OutputIt format_to(OutputIt out, const S&, const Args&... args) { | ||||
| FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { | ||||
|   constexpr auto compiled = detail::compile<Args...>(S()); | ||||
|   return format_to(out, compiled, args...); | ||||
| #ifdef __cpp_if_constexpr | ||||
|   if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>, | ||||
|                              detail::unknown_format>()) { | ||||
|     return format_to(out, | ||||
|                      static_cast<basic_string_view<typename S::char_type>>(S()), | ||||
|                      std::forward<Args>(args)...); | ||||
|   } else { | ||||
|     return format_to(out, compiled, std::forward<Args>(args)...); | ||||
|   } | ||||
| #else | ||||
|   return format_to(out, compiled, std::forward<Args>(args)...); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args> | ||||
| @@ -684,18 +928,31 @@ auto format_to_n(OutputIt out, size_t n, const CompiledFormat& cf, | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, const S&, | ||||
|                                          const Args&... args) { | ||||
|   constexpr auto compiled = detail::compile<Args...>(S()); | ||||
|   auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), compiled, | ||||
|                       args...); | ||||
|                                          Args&&... args) { | ||||
|   auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), S(), | ||||
|                       std::forward<Args>(args)...); | ||||
|   return {it.base(), it.count()}; | ||||
| } | ||||
|  | ||||
| template <typename CompiledFormat, typename... Args> | ||||
| template <typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format, | ||||
|                                         CompiledFormat>::value || | ||||
|                         detail::is_compiled_string<CompiledFormat>::value)> | ||||
| size_t formatted_size(const CompiledFormat& cf, const Args&... args) { | ||||
|   return format_to(detail::counting_iterator(), cf, args...).count(); | ||||
| } | ||||
|  | ||||
| #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| inline namespace literals { | ||||
| template <detail::fixed_string Str> | ||||
| constexpr detail::udl_compiled_string<remove_cvref_t<decltype(Str.data[0])>, | ||||
|                                       sizeof(Str.data), Str> | ||||
| operator""_cf() { | ||||
|   return {}; | ||||
| } | ||||
| }  // namespace literals | ||||
| #endif | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_COMPILE_H_ | ||||
|   | ||||
							
								
								
									
										485
									
								
								vendor/Fmt/include/fmt/core.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										485
									
								
								vendor/Fmt/include/fmt/core.h
									
									
									
									
										vendored
									
									
								
							| @@ -10,12 +10,9 @@ | ||||
|  | ||||
| #include <cstdio>  // std::FILE | ||||
| #include <cstring> | ||||
| #include <functional> | ||||
| #include <iterator> | ||||
| #include <memory> | ||||
| #include <string> | ||||
| #include <type_traits> | ||||
| #include <vector> | ||||
|  | ||||
| // The fmt library version in the form major * 10000 + minor * 100 + patch. | ||||
| #define FMT_VERSION 70103 | ||||
| @@ -28,8 +25,10 @@ | ||||
|  | ||||
| #if defined(__GNUC__) && !defined(__clang__) | ||||
| #  define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__) | ||||
| #  define FMT_GCC_PRAGMA(arg) _Pragma(arg) | ||||
| #else | ||||
| #  define FMT_GCC_VERSION 0 | ||||
| #  define FMT_GCC_PRAGMA(arg) | ||||
| #endif | ||||
|  | ||||
| #if defined(__INTEL_COMPILER) | ||||
| @@ -52,10 +51,10 @@ | ||||
|  | ||||
| #ifdef _MSC_VER | ||||
| #  define FMT_MSC_VER _MSC_VER | ||||
| #  define FMT_SUPPRESS_MSC_WARNING(n) __pragma(warning(suppress : n)) | ||||
| #  define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__)) | ||||
| #else | ||||
| #  define FMT_MSC_VER 0 | ||||
| #  define FMT_SUPPRESS_MSC_WARNING(n) | ||||
| #  define FMT_MSC_WARNING(...) | ||||
| #endif | ||||
|  | ||||
| #ifdef __has_feature | ||||
| @@ -95,7 +94,7 @@ | ||||
| #  define FMT_CONSTEXPR constexpr | ||||
| #  define FMT_CONSTEXPR_DECL constexpr | ||||
| #else | ||||
| #  define FMT_CONSTEXPR inline | ||||
| #  define FMT_CONSTEXPR | ||||
| #  define FMT_CONSTEXPR_DECL | ||||
| #endif | ||||
|  | ||||
| @@ -180,7 +179,7 @@ | ||||
|  | ||||
| #ifndef FMT_USE_INLINE_NAMESPACES | ||||
| #  if FMT_HAS_FEATURE(cxx_inline_namespaces) || FMT_GCC_VERSION >= 404 || \ | ||||
|       (FMT_MSC_VER >= 1900 && !_MANAGED) | ||||
|       (FMT_MSC_VER >= 1900 && (!defined(_MANAGED) || !_MANAGED)) | ||||
| #    define FMT_USE_INLINE_NAMESPACES 1 | ||||
| #  else | ||||
| #    define FMT_USE_INLINE_NAMESPACES 0 | ||||
| @@ -206,7 +205,7 @@ | ||||
| #endif | ||||
|  | ||||
| #if !defined(FMT_HEADER_ONLY) && defined(_WIN32) | ||||
| #  define FMT_CLASS_API FMT_SUPPRESS_MSC_WARNING(4275) | ||||
| #  define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275) | ||||
| #  ifdef FMT_EXPORT | ||||
| #    define FMT_API __declspec(dllexport) | ||||
| #    define FMT_EXTERN_TEMPLATE_API FMT_API | ||||
| @@ -248,8 +247,15 @@ | ||||
| #ifndef FMT_UNICODE | ||||
| #  define FMT_UNICODE !FMT_MSC_VER | ||||
| #endif | ||||
| #if FMT_UNICODE && FMT_MSC_VER | ||||
| #  pragma execution_character_set("utf-8") | ||||
|  | ||||
| #ifndef FMT_COMPILE_TIME_CHECKS | ||||
| #  define FMT_COMPILE_TIME_CHECKS 0 | ||||
| #endif | ||||
|  | ||||
| // Enable minimal optimizations for more compact code in debug mode. | ||||
| FMT_GCC_PRAGMA("GCC push_options") | ||||
| #ifndef __OPTIMIZE__ | ||||
| FMT_GCC_PRAGMA("GCC optimize(\"Og\")") | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| @@ -274,10 +280,22 @@ struct monostate {}; | ||||
| // An enable_if helper to be used in template parameters which results in much | ||||
| // shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed | ||||
| // to workaround a bug in MSVC 2019 (see #1140 and #1186). | ||||
| #define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 | ||||
| #ifdef FMT_DOC | ||||
| #  define FMT_ENABLE_IF(...) | ||||
| #else | ||||
| #  define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0 | ||||
| #endif | ||||
|  | ||||
| namespace detail { | ||||
|  | ||||
| constexpr bool is_constant_evaluated() FMT_NOEXCEPT { | ||||
| #ifdef __cpp_lib_is_constant_evaluated | ||||
|   return std::is_constant_evaluated(); | ||||
| #else | ||||
|   return false; | ||||
| #endif | ||||
| } | ||||
|  | ||||
| // A helper function to suppress "conditional expression is constant" warnings. | ||||
| template <typename T> constexpr T const_check(T value) { return value; } | ||||
|  | ||||
| @@ -327,7 +345,7 @@ FMT_CONSTEXPR typename std::make_unsigned<Int>::type to_unsigned(Int value) { | ||||
|   return static_cast<typename std::make_unsigned<Int>::type>(value); | ||||
| } | ||||
|  | ||||
| FMT_SUPPRESS_MSC_WARNING(4566) constexpr unsigned char micro[] = "\u00B5"; | ||||
| FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char micro[] = "\u00B5"; | ||||
|  | ||||
| template <typename Char> constexpr bool is_unicode() { | ||||
|   return FMT_UNICODE || sizeof(Char) != 1 || | ||||
| @@ -377,8 +395,12 @@ template <typename Char> class basic_string_view { | ||||
| #if __cplusplus >= 201703L  // C++17's char_traits::length() is constexpr. | ||||
|   FMT_CONSTEXPR | ||||
| #endif | ||||
|   basic_string_view(const Char* s) | ||||
|       : data_(s), size_(std::char_traits<Char>::length(s)) {} | ||||
|   FMT_INLINE basic_string_view(const Char* s) : data_(s) { | ||||
|     if (std::is_same<Char, char>::value) | ||||
|       size_ = std::strlen(reinterpret_cast<const char*>(s)); | ||||
|     else | ||||
|       size_ = std::char_traits<Char>::length(s); | ||||
|   } | ||||
|  | ||||
|   /** Constructs a string reference from a ``std::basic_string`` object. */ | ||||
|   template <typename Traits, typename Alloc> | ||||
| @@ -465,7 +487,7 @@ template <> struct is_char<char32_t> : std::true_type {}; | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)> | ||||
| inline basic_string_view<Char> to_string_view(const Char* s) { | ||||
| FMT_INLINE basic_string_view<Char> to_string_view(const Char* s) { | ||||
|   return s; | ||||
| } | ||||
|  | ||||
| @@ -476,7 +498,7 @@ inline basic_string_view<Char> to_string_view( | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| inline basic_string_view<Char> to_string_view(basic_string_view<Char> s) { | ||||
| constexpr basic_string_view<Char> to_string_view(basic_string_view<Char> s) { | ||||
|   return s; | ||||
| } | ||||
|  | ||||
| @@ -670,7 +692,7 @@ template <typename T> class buffer { | ||||
|  | ||||
|  protected: | ||||
|   // Don't initialize ptr_ since it is not accessed to save a few cycles. | ||||
|   FMT_SUPPRESS_MSC_WARNING(26495) | ||||
|   FMT_MSC_WARNING(suppress : 26495) | ||||
|   buffer(size_t sz) FMT_NOEXCEPT : size_(sz), capacity_(sz) {} | ||||
|  | ||||
|   buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) FMT_NOEXCEPT | ||||
| @@ -783,9 +805,7 @@ class iterator_buffer final : public Traits, public buffer<T> { | ||||
|  | ||||
|  public: | ||||
|   explicit iterator_buffer(OutputIt out, size_t n = buffer_size) | ||||
|       : Traits(n), | ||||
|         buffer<T>(data_, 0, buffer_size), | ||||
|         out_(out) {} | ||||
|       : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {} | ||||
|   ~iterator_buffer() { flush(); } | ||||
|  | ||||
|   OutputIt out() { | ||||
| @@ -935,9 +955,9 @@ struct arg_data<T, Char, NUM_ARGS, 0> { | ||||
|   T args_[NUM_ARGS != 0 ? NUM_ARGS : +1]; | ||||
|  | ||||
|   template <typename... U> | ||||
|   FMT_INLINE arg_data(const U&... init) : args_{init...} {} | ||||
|   FMT_INLINE const T* args() const { return args_; } | ||||
|   FMT_INLINE std::nullptr_t named_args() { return nullptr; } | ||||
|   FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {} | ||||
|   FMT_CONSTEXPR FMT_INLINE const T* args() const { return args_; } | ||||
|   FMT_CONSTEXPR FMT_INLINE std::nullptr_t named_args() { return nullptr; } | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| @@ -958,7 +978,8 @@ void init_named_args(named_arg_info<Char>* named_args, int arg_count, | ||||
| } | ||||
|  | ||||
| template <typename... Args> | ||||
| FMT_INLINE void init_named_args(std::nullptr_t, int, int, const Args&...) {} | ||||
| FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int, | ||||
|                                               const Args&...) {} | ||||
|  | ||||
| template <typename T> struct is_named_arg : std::false_type {}; | ||||
|  | ||||
| @@ -1070,17 +1091,20 @@ template <typename Context> class value { | ||||
|  | ||||
|   constexpr FMT_INLINE value(int val = 0) : int_value(val) {} | ||||
|   constexpr FMT_INLINE value(unsigned val) : uint_value(val) {} | ||||
|   FMT_INLINE value(long long val) : long_long_value(val) {} | ||||
|   FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} | ||||
|   constexpr FMT_INLINE value(long long val) : long_long_value(val) {} | ||||
|   constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {} | ||||
|   FMT_INLINE value(int128_t val) : int128_value(val) {} | ||||
|   FMT_INLINE value(uint128_t val) : uint128_value(val) {} | ||||
|   FMT_INLINE value(float val) : float_value(val) {} | ||||
|   FMT_INLINE value(double val) : double_value(val) {} | ||||
|   FMT_INLINE value(long double val) : long_double_value(val) {} | ||||
|   FMT_INLINE value(bool val) : bool_value(val) {} | ||||
|   FMT_INLINE value(char_type val) : char_value(val) {} | ||||
|   FMT_INLINE value(const char_type* val) { string.data = val; } | ||||
|   FMT_INLINE value(basic_string_view<char_type> val) { | ||||
|   constexpr FMT_INLINE value(bool val) : bool_value(val) {} | ||||
|   constexpr FMT_INLINE value(char_type val) : char_value(val) {} | ||||
|   FMT_CONSTEXPR FMT_INLINE value(const char_type* val) { | ||||
|     string.data = val; | ||||
|     if (is_constant_evaluated()) string.size = {}; | ||||
|   } | ||||
|   FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) { | ||||
|     string.data = val.data(); | ||||
|     string.size = val.size(); | ||||
|   } | ||||
| @@ -1126,36 +1150,40 @@ struct unformattable {}; | ||||
| template <typename Context> struct arg_mapper { | ||||
|   using char_type = typename Context::char_type; | ||||
|  | ||||
|   FMT_CONSTEXPR int map(signed char val) { return val; } | ||||
|   FMT_CONSTEXPR unsigned map(unsigned char val) { return val; } | ||||
|   FMT_CONSTEXPR int map(short val) { return val; } | ||||
|   FMT_CONSTEXPR unsigned map(unsigned short val) { return val; } | ||||
|   FMT_CONSTEXPR int map(int val) { return val; } | ||||
|   FMT_CONSTEXPR unsigned map(unsigned val) { return val; } | ||||
|   FMT_CONSTEXPR long_type map(long val) { return val; } | ||||
|   FMT_CONSTEXPR ulong_type map(unsigned long val) { return val; } | ||||
|   FMT_CONSTEXPR long long map(long long val) { return val; } | ||||
|   FMT_CONSTEXPR unsigned long long map(unsigned long long val) { return val; } | ||||
|   FMT_CONSTEXPR int128_t map(int128_t val) { return val; } | ||||
|   FMT_CONSTEXPR uint128_t map(uint128_t val) { return val; } | ||||
|   FMT_CONSTEXPR bool map(bool val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE int map(signed char val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE unsigned map(unsigned char val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE int map(short val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE unsigned map(unsigned short val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE int map(int val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE unsigned map(unsigned val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE long_type map(long val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE ulong_type map(unsigned long val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE long long map(long long val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE unsigned long long map(unsigned long long val) { | ||||
|     return val; | ||||
|   } | ||||
|   FMT_CONSTEXPR FMT_INLINE int128_t map(int128_t val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE uint128_t map(uint128_t val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE bool map(bool val) { return val; } | ||||
|  | ||||
|   template <typename T, FMT_ENABLE_IF(is_char<T>::value)> | ||||
|   FMT_CONSTEXPR char_type map(T val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE char_type map(T val) { | ||||
|     static_assert( | ||||
|         std::is_same<T, char>::value || std::is_same<T, char_type>::value, | ||||
|         "mixing character types is disallowed"); | ||||
|     return val; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR float map(float val) { return val; } | ||||
|   FMT_CONSTEXPR double map(double val) { return val; } | ||||
|   FMT_CONSTEXPR long double map(long double val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE float map(float val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE double map(double val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE long double map(long double val) { return val; } | ||||
|  | ||||
|   FMT_CONSTEXPR const char_type* map(char_type* val) { return val; } | ||||
|   FMT_CONSTEXPR const char_type* map(const char_type* val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE const char_type* map(char_type* val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE const char_type* map(const char_type* val) { | ||||
|     return val; | ||||
|   } | ||||
|   template <typename T, FMT_ENABLE_IF(is_string<T>::value)> | ||||
|   FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE basic_string_view<char_type> map(const T& val) { | ||||
|     static_assert(std::is_same<char_type, char_t<T>>::value, | ||||
|                   "mixing character types is disallowed"); | ||||
|     return to_string_view(val); | ||||
| @@ -1165,7 +1193,7 @@ template <typename Context> struct arg_mapper { | ||||
|                 std::is_constructible<basic_string_view<char_type>, T>::value && | ||||
|                 !is_string<T>::value && !has_formatter<T, Context>::value && | ||||
|                 !has_fallback_formatter<T, Context>::value)> | ||||
|   FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE basic_string_view<char_type> map(const T& val) { | ||||
|     return basic_string_view<char_type>(val); | ||||
|   } | ||||
|   template < | ||||
| @@ -1175,30 +1203,34 @@ template <typename Context> struct arg_mapper { | ||||
|           !std::is_constructible<basic_string_view<char_type>, T>::value && | ||||
|           !is_string<T>::value && !has_formatter<T, Context>::value && | ||||
|           !has_fallback_formatter<T, Context>::value)> | ||||
|   FMT_CONSTEXPR basic_string_view<char_type> map(const T& val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE basic_string_view<char_type> map(const T& val) { | ||||
|     return std_string_view<char_type>(val); | ||||
|   } | ||||
|   FMT_CONSTEXPR const char* map(const signed char* val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE const char* map(const signed char* val) { | ||||
|     static_assert(std::is_same<char_type, char>::value, "invalid string type"); | ||||
|     return reinterpret_cast<const char*>(val); | ||||
|   } | ||||
|   FMT_CONSTEXPR const char* map(const unsigned char* val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE const char* map(const unsigned char* val) { | ||||
|     static_assert(std::is_same<char_type, char>::value, "invalid string type"); | ||||
|     return reinterpret_cast<const char*>(val); | ||||
|   } | ||||
|   FMT_CONSTEXPR const char* map(signed char* val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE const char* map(signed char* val) { | ||||
|     const auto* const_val = val; | ||||
|     return map(const_val); | ||||
|   } | ||||
|   FMT_CONSTEXPR const char* map(unsigned char* val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE const char* map(unsigned char* val) { | ||||
|     const auto* const_val = val; | ||||
|     return map(const_val); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR const void* map(void* val) { return val; } | ||||
|   FMT_CONSTEXPR const void* map(const void* val) { return val; } | ||||
|   FMT_CONSTEXPR const void* map(std::nullptr_t val) { return val; } | ||||
|   template <typename T> FMT_CONSTEXPR int map(const T*) { | ||||
|   FMT_CONSTEXPR FMT_INLINE const void* map(void* val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE const void* map(const void* val) { return val; } | ||||
|   FMT_CONSTEXPR FMT_INLINE const void* map(std::nullptr_t val) { return val; } | ||||
|  | ||||
|   // We use SFINAE instead of a const T* parameter to avoid conflicting with | ||||
|   // the C array overload. | ||||
|   template <typename T> | ||||
|   FMT_CONSTEXPR auto map(T) -> enable_if_t<std::is_pointer<T>::value, int> { | ||||
|     // Formatting of arbitrary pointers is disallowed. If you want to output | ||||
|     // a pointer cast it to "void *" or "const void *". In particular, this | ||||
|     // forbids formatting of "[const] volatile char *" which is printed as bool | ||||
| @@ -1207,11 +1239,16 @@ template <typename Context> struct arg_mapper { | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   template <typename T, std::size_t N> | ||||
|   FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] { | ||||
|     return values; | ||||
|   } | ||||
|  | ||||
|   template <typename T, | ||||
|             FMT_ENABLE_IF(std::is_enum<T>::value && | ||||
|                           !has_formatter<T, Context>::value && | ||||
|                           !has_fallback_formatter<T, Context>::value)> | ||||
|   FMT_CONSTEXPR auto map(const T& val) | ||||
|   FMT_CONSTEXPR FMT_INLINE auto map(const T& val) | ||||
|       -> decltype(std::declval<arg_mapper>().map( | ||||
|           static_cast<typename std::underlying_type<T>::type>(val))) { | ||||
|     return map(static_cast<typename std::underlying_type<T>::type>(val)); | ||||
| @@ -1220,12 +1257,12 @@ template <typename Context> struct arg_mapper { | ||||
|             FMT_ENABLE_IF(!is_string<T>::value && !is_char<T>::value && | ||||
|                           (has_formatter<T, Context>::value || | ||||
|                            has_fallback_formatter<T, Context>::value))> | ||||
|   FMT_CONSTEXPR const T& map(const T& val) { | ||||
|   FMT_CONSTEXPR FMT_INLINE const T& map(const T& val) { | ||||
|     return val; | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   FMT_CONSTEXPR auto map(const named_arg<char_type, T>& val) | ||||
|   FMT_CONSTEXPR FMT_INLINE auto map(const named_arg<char_type, T>& val) | ||||
|       -> decltype(std::declval<arg_mapper>().map(val.value)) { | ||||
|     return map(val.value); | ||||
|   } | ||||
| @@ -1354,14 +1391,16 @@ FMT_CONSTEXPR_DECL FMT_INLINE auto visit_format_arg( | ||||
|   return vis(monostate()); | ||||
| } | ||||
|  | ||||
| template <typename T> struct formattable : std::false_type {}; | ||||
|  | ||||
| namespace detail { | ||||
|  | ||||
| #if FMT_GCC_VERSION && FMT_GCC_VERSION < 500 | ||||
| // A workaround for gcc 4.8 to make void_t work in a SFINAE context. | ||||
| template <typename... Ts> struct void_t_impl { using type = void; }; | ||||
| template <typename... Ts> | ||||
| using void_t = typename detail::void_t_impl<Ts...>::type; | ||||
| #else | ||||
| template <typename...> using void_t = void; | ||||
| #endif | ||||
|  | ||||
| template <typename It, typename T, typename Enable = void> | ||||
| struct is_output_iterator : std::false_type {}; | ||||
| @@ -1394,7 +1433,7 @@ class locale_ref { | ||||
|   const void* locale_;  // A type-erased pointer to std::locale. | ||||
|  | ||||
|  public: | ||||
|   locale_ref() : locale_(nullptr) {} | ||||
|   constexpr locale_ref() : locale_(nullptr) {} | ||||
|   template <typename Locale> explicit locale_ref(const Locale& loc); | ||||
|  | ||||
|   explicit operator bool() const FMT_NOEXCEPT { return locale_ != nullptr; } | ||||
| @@ -1418,24 +1457,18 @@ FMT_CONSTEXPR basic_format_arg<Context> make_arg(const T& value) { | ||||
|   return arg; | ||||
| } | ||||
|  | ||||
| template <typename T> int check(unformattable) { | ||||
|   static_assert( | ||||
|       formattable<T>(), | ||||
|       "Cannot format an argument. To make type T formattable provide a " | ||||
|       "formatter<T> specialization: https://fmt.dev/latest/api.html#udt"); | ||||
|   return 0; | ||||
| } | ||||
| template <typename T, typename U> inline const U& check(const U& val) { | ||||
|   return val; | ||||
| } | ||||
|  | ||||
| // The type template parameter is there to avoid an ODR violation when using | ||||
| // a fallback formatter in one translation unit and an implicit conversion in | ||||
| // another (not recommended). | ||||
| template <bool IS_PACKED, typename Context, type, typename T, | ||||
|           FMT_ENABLE_IF(IS_PACKED)> | ||||
| inline value<Context> make_arg(const T& val) { | ||||
|   return check<T>(arg_mapper<Context>().map(val)); | ||||
| FMT_CONSTEXPR FMT_INLINE value<Context> make_arg(const T& val) { | ||||
|   const auto& arg = arg_mapper<Context>().map(val); | ||||
|   static_assert( | ||||
|       !std::is_same<decltype(arg), const unformattable&>::value, | ||||
|       "Cannot format an argument. To make type T formattable provide a " | ||||
|       "formatter<T> specialization: https://fmt.dev/latest/api.html#udt"); | ||||
|   return arg; | ||||
| } | ||||
|  | ||||
| template <bool IS_PACKED, typename Context, type, typename T, | ||||
| @@ -1443,47 +1476,6 @@ template <bool IS_PACKED, typename Context, type, typename T, | ||||
| inline basic_format_arg<Context> make_arg(const T& value) { | ||||
|   return make_arg<Context>(value); | ||||
| } | ||||
|  | ||||
| template <typename T> struct is_reference_wrapper : std::false_type {}; | ||||
| template <typename T> | ||||
| struct is_reference_wrapper<std::reference_wrapper<T>> : std::true_type {}; | ||||
|  | ||||
| template <typename T> const T& unwrap(const T& v) { return v; } | ||||
| template <typename T> const T& unwrap(const std::reference_wrapper<T>& v) { | ||||
|   return static_cast<const T&>(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 <typename = void> struct node { | ||||
|     virtual ~node() = default; | ||||
|     std::unique_ptr<node<>> next; | ||||
|   }; | ||||
|  | ||||
|   template <typename T> struct typed_node : node<> { | ||||
|     T value; | ||||
|  | ||||
|     template <typename Arg> | ||||
|     FMT_CONSTEXPR typed_node(const Arg& arg) : value(arg) {} | ||||
|  | ||||
|     template <typename Char> | ||||
|     FMT_CONSTEXPR typed_node(const basic_string_view<Char>& arg) | ||||
|         : value(arg.data(), arg.size()) {} | ||||
|   }; | ||||
|  | ||||
|   std::unique_ptr<node<>> head_; | ||||
|  | ||||
|  public: | ||||
|   template <typename T, typename Arg> const T& push(const Arg& arg) { | ||||
|     auto new_node = std::unique_ptr<typed_node<T>>(new typed_node<T>(arg)); | ||||
|     auto& value = new_node->value; | ||||
|     new_node->next = std::move(head_); | ||||
|     head_ = std::move(new_node); | ||||
|     return value; | ||||
|   } | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| // Formatting context. | ||||
| @@ -1509,28 +1501,30 @@ template <typename OutputIt, typename Char> class basic_format_context { | ||||
|    Constructs a ``basic_format_context`` object. References to the arguments are | ||||
|    stored in the object so make sure they have appropriate lifetimes. | ||||
|    */ | ||||
|   basic_format_context(OutputIt out, | ||||
|                        basic_format_args<basic_format_context> ctx_args, | ||||
|                        detail::locale_ref loc = detail::locale_ref()) | ||||
|   constexpr basic_format_context( | ||||
|       OutputIt out, basic_format_args<basic_format_context> ctx_args, | ||||
|       detail::locale_ref loc = detail::locale_ref()) | ||||
|       : out_(out), args_(ctx_args), loc_(loc) {} | ||||
|  | ||||
|   format_arg arg(int id) const { return args_.get(id); } | ||||
|   format_arg arg(basic_string_view<char_type> name) { return args_.get(name); } | ||||
|   constexpr format_arg arg(int id) const { return args_.get(id); } | ||||
|   FMT_CONSTEXPR format_arg arg(basic_string_view<char_type> name) { | ||||
|     return args_.get(name); | ||||
|   } | ||||
|   int arg_id(basic_string_view<char_type> name) { return args_.get_id(name); } | ||||
|   const basic_format_args<basic_format_context>& args() const { return args_; } | ||||
|  | ||||
|   detail::error_handler error_handler() { return {}; } | ||||
|   FMT_CONSTEXPR detail::error_handler error_handler() { return {}; } | ||||
|   void on_error(const char* message) { error_handler().on_error(message); } | ||||
|  | ||||
|   // Returns an iterator to the beginning of the output range. | ||||
|   iterator out() { return out_; } | ||||
|   FMT_CONSTEXPR iterator out() { return out_; } | ||||
|  | ||||
|   // Advances the begin iterator to ``it``. | ||||
|   void advance_to(iterator it) { | ||||
|     if (!detail::is_back_insert_iterator<iterator>()) out_ = it; | ||||
|   } | ||||
|  | ||||
|   detail::locale_ref locale() { return loc_; } | ||||
|   FMT_CONSTEXPR detail::locale_ref locale() { return loc_; } | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| @@ -1543,6 +1537,11 @@ using wformat_context = buffer_context<wchar_t>; | ||||
| #define FMT_BUFFER_CONTEXT(Char) \ | ||||
|   basic_format_context<detail::buffer_appender<Char>, Char> | ||||
|  | ||||
| template <typename T, typename Char = char> | ||||
| using is_formattable = bool_constant<!std::is_same< | ||||
|     decltype(detail::arg_mapper<buffer_context<Char>>().map(std::declval<T>())), | ||||
|     detail::unformattable>::value>; | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   An array of references to arguments. It can be implicitly converted into | ||||
| @@ -1579,7 +1578,7 @@ class format_arg_store | ||||
|            : 0); | ||||
|  | ||||
|  public: | ||||
|   format_arg_store(const Args&... args) | ||||
|   FMT_CONSTEXPR FMT_INLINE format_arg_store(const Args&... args) | ||||
|       : | ||||
| #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 | ||||
|         basic_format_args<Context>(*this), | ||||
| @@ -1600,7 +1599,7 @@ class format_arg_store | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename Context = format_context, typename... Args> | ||||
| inline format_arg_store<Context, Args...> make_format_args( | ||||
| constexpr format_arg_store<Context, Args...> make_format_args( | ||||
|     const Args&... args) { | ||||
|   return {args...}; | ||||
| } | ||||
| @@ -1614,8 +1613,8 @@ inline format_arg_store<Context, Args...> make_format_args( | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename... Args, typename S, typename Char = char_t<S>> | ||||
| inline auto make_args_checked(const S& format_str, | ||||
|                               const remove_reference_t<Args>&... args) | ||||
| FMT_INLINE auto make_args_checked(const S& format_str, | ||||
|                                   const remove_reference_t<Args>&... args) | ||||
|     -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> { | ||||
|   static_assert( | ||||
|       detail::count<( | ||||
| @@ -1628,8 +1627,9 @@ inline auto make_args_checked(const S& format_str, | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   Returns a named argument to be used in a formatting function. It should only | ||||
|   be used in a call to a formatting function. | ||||
|   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**:: | ||||
|  | ||||
| @@ -1642,179 +1642,6 @@ inline detail::named_arg<Char, T> arg(const Char* name, const T& arg) { | ||||
|   return {name, arg}; | ||||
| } | ||||
|  | ||||
| /** | ||||
|   \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 | ||||
|  */ | ||||
| template <typename Context> | ||||
| class dynamic_format_arg_store | ||||
| #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 | ||||
|     // Workaround a GCC template argument substitution bug. | ||||
|     : public basic_format_args<Context> | ||||
| #endif | ||||
| { | ||||
|  private: | ||||
|   using char_type = typename Context::char_type; | ||||
|  | ||||
|   template <typename T> struct need_copy { | ||||
|     static constexpr detail::type mapped_type = | ||||
|         detail::mapped_type_constant<T, Context>::value; | ||||
|  | ||||
|     enum { | ||||
|       value = !(detail::is_reference_wrapper<T>::value || | ||||
|                 std::is_same<T, basic_string_view<char_type>>::value || | ||||
|                 std::is_same<T, detail::std_string_view<char_type>>::value || | ||||
|                 (mapped_type != detail::type::cstring_type && | ||||
|                  mapped_type != detail::type::string_type && | ||||
|                  mapped_type != detail::type::custom_type)) | ||||
|     }; | ||||
|   }; | ||||
|  | ||||
|   template <typename T> | ||||
|   using stored_type = conditional_t<detail::is_string<T>::value, | ||||
|                                     std::basic_string<char_type>, T>; | ||||
|  | ||||
|   // Storage of basic_format_arg must be contiguous. | ||||
|   std::vector<basic_format_arg<Context>> data_; | ||||
|   std::vector<detail::named_arg_info<char_type>> named_info_; | ||||
|  | ||||
|   // Storage of arguments not fitting into basic_format_arg must grow | ||||
|   // without relocation because items in data_ refer to it. | ||||
|   detail::dynamic_arg_list dynamic_args_; | ||||
|  | ||||
|   friend class basic_format_args<Context>; | ||||
|  | ||||
|   unsigned long long get_types() const { | ||||
|     return detail::is_unpacked_bit | data_.size() | | ||||
|            (named_info_.empty() | ||||
|                 ? 0ULL | ||||
|                 : static_cast<unsigned long long>(detail::has_named_args_bit)); | ||||
|   } | ||||
|  | ||||
|   const basic_format_arg<Context>* data() const { | ||||
|     return named_info_.empty() ? data_.data() : data_.data() + 1; | ||||
|   } | ||||
|  | ||||
|   template <typename T> void emplace_arg(const T& arg) { | ||||
|     data_.emplace_back(detail::make_arg<Context>(arg)); | ||||
|   } | ||||
|  | ||||
|   template <typename T> | ||||
|   void emplace_arg(const detail::named_arg<char_type, T>& arg) { | ||||
|     if (named_info_.empty()) { | ||||
|       constexpr const detail::named_arg_info<char_type>* zero_ptr{nullptr}; | ||||
|       data_.insert(data_.begin(), {zero_ptr, 0}); | ||||
|     } | ||||
|     data_.emplace_back(detail::make_arg<Context>(detail::unwrap(arg.value))); | ||||
|     auto pop_one = [](std::vector<basic_format_arg<Context>>* data) { | ||||
|       data->pop_back(); | ||||
|     }; | ||||
|     std::unique_ptr<std::vector<basic_format_arg<Context>>, decltype(pop_one)> | ||||
|         guard{&data_, pop_one}; | ||||
|     named_info_.push_back({arg.name, static_cast<int>(data_.size() - 2u)}); | ||||
|     data_[0].value_.named_args = {named_info_.data(), named_info_.size()}; | ||||
|     guard.release(); | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   /** | ||||
|     \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<fmt::format_context> store; | ||||
|       store.push_back(42); | ||||
|       store.push_back("abc"); | ||||
|       store.push_back(1.5f); | ||||
|       std::string result = fmt::vformat("{} and {} and {}", store); | ||||
|     \endrst | ||||
|   */ | ||||
|   template <typename T> void push_back(const T& arg) { | ||||
|     if (detail::const_check(need_copy<T>::value)) | ||||
|       emplace_arg(dynamic_args_.push<stored_type<T>>(arg)); | ||||
|     else | ||||
|       emplace_arg(detail::unwrap(arg)); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|     \rst | ||||
|     Adds a reference to the argument into the dynamic store for later passing to | ||||
|     a formatting function. Supports named arguments wrapped in | ||||
|     ``std::reference_wrapper`` via ``std::ref()``/``std::cref()``. | ||||
|  | ||||
|     **Example**:: | ||||
|  | ||||
|       fmt::dynamic_format_arg_store<fmt::format_context> store; | ||||
|       char str[] = "1234567890"; | ||||
|       store.push_back(std::cref(str)); | ||||
|       int a1_val{42}; | ||||
|       auto a1 = fmt::arg("a1_", a1_val); | ||||
|       store.push_back(std::cref(a1)); | ||||
|  | ||||
|       // Changing str affects the output but only for string and custom types. | ||||
|       str[0] = 'X'; | ||||
|  | ||||
|       std::string result = fmt::vformat("{} and {a1_}"); | ||||
|       assert(result == "X234567890 and 42"); | ||||
|     \endrst | ||||
|   */ | ||||
|   template <typename T> void push_back(std::reference_wrapper<T> arg) { | ||||
|     static_assert( | ||||
|         detail::is_named_arg<typename std::remove_cv<T>::type>::value || | ||||
|             need_copy<T>::value, | ||||
|         "objects of built-in types and string views are always copied"); | ||||
|     emplace_arg(arg.get()); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|     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. | ||||
|   */ | ||||
|   template <typename T> | ||||
|   void push_back(const detail::named_arg<char_type, T>& arg) { | ||||
|     const char_type* arg_name = | ||||
|         dynamic_args_.push<std::basic_string<char_type>>(arg.name).c_str(); | ||||
|     if (detail::const_check(need_copy<T>::value)) { | ||||
|       emplace_arg( | ||||
|           fmt::arg(arg_name, dynamic_args_.push<stored_type<T>>(arg.value))); | ||||
|     } else { | ||||
|       emplace_arg(fmt::arg(arg_name, arg.value)); | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   /** 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 | ||||
|   */ | ||||
|   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"); | ||||
|     data_.reserve(new_cap); | ||||
|     named_info_.reserve(new_cap_named); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   A view of a collection of formatting arguments. To avoid lifetime issues it | ||||
| @@ -1846,25 +1673,27 @@ template <typename Context> class basic_format_args { | ||||
|     const format_arg* args_; | ||||
|   }; | ||||
|  | ||||
|   bool is_packed() const { return (desc_ & detail::is_unpacked_bit) == 0; } | ||||
|   constexpr bool is_packed() const { | ||||
|     return (desc_ & detail::is_unpacked_bit) == 0; | ||||
|   } | ||||
|   bool has_named_args() const { | ||||
|     return (desc_ & detail::has_named_args_bit) != 0; | ||||
|   } | ||||
|  | ||||
|   detail::type type(int index) const { | ||||
|   FMT_CONSTEXPR detail::type type(int index) const { | ||||
|     int shift = index * detail::packed_arg_bits; | ||||
|     unsigned int mask = (1 << detail::packed_arg_bits) - 1; | ||||
|     return static_cast<detail::type>((desc_ >> shift) & mask); | ||||
|   } | ||||
|  | ||||
|   basic_format_args(unsigned long long desc, | ||||
|                     const detail::value<Context>* values) | ||||
|   constexpr FMT_INLINE basic_format_args(unsigned long long desc, | ||||
|                                          const detail::value<Context>* values) | ||||
|       : desc_(desc), values_(values) {} | ||||
|   basic_format_args(unsigned long long desc, const format_arg* args) | ||||
|   constexpr basic_format_args(unsigned long long desc, const format_arg* args) | ||||
|       : desc_(desc), args_(args) {} | ||||
|  | ||||
|  public: | ||||
|   basic_format_args() : desc_(0) {} | ||||
|   constexpr basic_format_args() : desc_(0), args_(nullptr) {} | ||||
|  | ||||
|   /** | ||||
|    \rst | ||||
| @@ -1872,8 +1701,10 @@ template <typename Context> class basic_format_args { | ||||
|    \endrst | ||||
|    */ | ||||
|   template <typename... Args> | ||||
|   FMT_INLINE basic_format_args(const format_arg_store<Context, Args...>& store) | ||||
|       : basic_format_args(store.desc, store.data_.args()) {} | ||||
|   constexpr FMT_INLINE basic_format_args( | ||||
|       const format_arg_store<Context, Args...>& store) | ||||
|       : basic_format_args(format_arg_store<Context, Args...>::desc, | ||||
|                           store.data_.args()) {} | ||||
|  | ||||
|   /** | ||||
|    \rst | ||||
| @@ -1881,7 +1712,8 @@ template <typename Context> class basic_format_args { | ||||
|    `~fmt::dynamic_format_arg_store`. | ||||
|    \endrst | ||||
|    */ | ||||
|   FMT_INLINE basic_format_args(const dynamic_format_arg_store<Context>& store) | ||||
|   constexpr FMT_INLINE basic_format_args( | ||||
|       const dynamic_format_arg_store<Context>& store) | ||||
|       : basic_format_args(store.get_types(), store.data()) {} | ||||
|  | ||||
|   /** | ||||
| @@ -1889,12 +1721,12 @@ template <typename Context> class basic_format_args { | ||||
|    Constructs a `basic_format_args` object from a dynamic set of arguments. | ||||
|    \endrst | ||||
|    */ | ||||
|   basic_format_args(const format_arg* args, int count) | ||||
|   constexpr basic_format_args(const format_arg* args, int count) | ||||
|       : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count), | ||||
|                           args) {} | ||||
|  | ||||
|   /** Returns the argument with the specified id. */ | ||||
|   format_arg get(int id) const { | ||||
|   FMT_CONSTEXPR format_arg get(int id) const { | ||||
|     format_arg arg; | ||||
|     if (!is_packed()) { | ||||
|       if (id < max_size()) arg = args_[id]; | ||||
| @@ -2043,11 +1875,11 @@ inline auto format_to_n(OutputIt out, size_t n, const S& format_str, | ||||
|   Returns the number of characters in the output of | ||||
|   ``format(format_str, args...)``. | ||||
|  */ | ||||
| template <typename... Args> | ||||
| inline size_t formatted_size(string_view format_str, Args&&... args) { | ||||
| template <typename S, typename... Args, typename Char = char_t<S>> | ||||
| inline size_t formatted_size(const S& format_str, Args&&... args) { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   detail::counting_buffer<> buf; | ||||
|   detail::vformat_to(buf, format_str, vargs); | ||||
|   detail::vformat_to(buf, to_string_view(format_str), vargs); | ||||
|   return buf.count(); | ||||
| } | ||||
|  | ||||
| @@ -2070,7 +1902,9 @@ FMT_INLINE std::basic_string<Char> vformat( | ||||
| */ | ||||
| // Pass char_t as a default template parameter instead of using | ||||
| // std::basic_string<char_t<S>> to reduce the symbol size. | ||||
| template <typename S, typename... Args, typename Char = char_t<S>> | ||||
| template <typename S, typename... Args, typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(!FMT_COMPILE_TIME_CHECKS || | ||||
|                         !std::is_same<Char, char>::value)> | ||||
| FMT_INLINE std::basic_string<Char> format(const S& format_str, Args&&... args) { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   return detail::vformat(to_string_view(format_str), vargs); | ||||
| @@ -2117,6 +1951,13 @@ inline void print(const S& format_str, Args&&... args) { | ||||
|              : detail::vprint_mojibake(stdout, to_string_view(format_str), | ||||
|                                        vargs); | ||||
| } | ||||
| FMT_GCC_PRAGMA("GCC pop_options") | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_CORE_H_ | ||||
|  | ||||
| // Define FMT_DYNAMIC_ARGS to make core.h provide dynamic_format_arg_store | ||||
| // DEPRECATED! Include fmt/args.h directly instead. | ||||
| #ifdef FMT_DYNAMIC_ARGS | ||||
| #include "args.h" | ||||
| #endif | ||||
|   | ||||
							
								
								
									
										160
									
								
								vendor/Fmt/include/fmt/format-inl.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										160
									
								
								vendor/Fmt/include/fmt/format-inl.h
									
									
									
									
										vendored
									
									
								
							| @@ -8,7 +8,7 @@ | ||||
| #ifndef FMT_FORMAT_INL_H_ | ||||
| #define FMT_FORMAT_INL_H_ | ||||
|  | ||||
| #include <cassert> | ||||
| #include <algorithm> | ||||
| #include <cctype> | ||||
| #include <climits> | ||||
| #include <cmath> | ||||
| @@ -145,9 +145,9 @@ FMT_FUNC void format_error_code(detail::buffer<char>& out, int error_code, | ||||
|   error_code_size += detail::to_unsigned(detail::count_digits(abs_value)); | ||||
|   auto it = buffer_appender<char>(out); | ||||
|   if (message.size() <= inline_buffer_size - error_code_size) | ||||
|     format_to(it, "{}{}", message, SEP); | ||||
|   format_to(it, "{}{}", ERROR_STR, error_code); | ||||
|   assert(out.size() <= inline_buffer_size); | ||||
|     format_to(it, FMT_STRING("{}{}"), message, SEP); | ||||
|   format_to(it, FMT_STRING("{}{}"), ERROR_STR, error_code); | ||||
|   FMT_ASSERT(out.size() <= inline_buffer_size, ""); | ||||
| } | ||||
|  | ||||
| FMT_FUNC void report_error(format_func func, int error_code, | ||||
| @@ -165,11 +165,8 @@ inline void fwrite_fully(const void* ptr, size_t size, size_t count, | ||||
|   size_t written = std::fwrite(ptr, size, count, stream); | ||||
|   if (written < count) FMT_THROW(system_error(errno, "cannot write to file")); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| #if !defined(FMT_STATIC_THOUSANDS_SEPARATOR) | ||||
| namespace detail { | ||||
|  | ||||
| #ifndef FMT_STATIC_THOUSANDS_SEPARATOR | ||||
| template <typename Locale> | ||||
| locale_ref::locale_ref(const Locale& loc) : locale_(&loc) { | ||||
|   static_assert(std::is_same<Locale, std::locale>::value, ""); | ||||
| @@ -191,19 +188,18 @@ template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref loc) { | ||||
|   return std::use_facet<std::numpunct<Char>>(loc.get<std::locale>()) | ||||
|       .decimal_point(); | ||||
| } | ||||
| }  // namespace detail | ||||
| #else | ||||
| template <typename Char> | ||||
| FMT_FUNC std::string detail::grouping_impl(locale_ref) { | ||||
| template <typename Char> FMT_FUNC std::string grouping_impl(locale_ref) { | ||||
|   return "\03"; | ||||
| } | ||||
| template <typename Char> FMT_FUNC Char detail::thousands_sep_impl(locale_ref) { | ||||
| template <typename Char> FMT_FUNC Char thousands_sep_impl(locale_ref) { | ||||
|   return FMT_STATIC_THOUSANDS_SEPARATOR; | ||||
| } | ||||
| template <typename Char> FMT_FUNC Char detail::decimal_point_impl(locale_ref) { | ||||
| template <typename Char> FMT_FUNC Char decimal_point_impl(locale_ref) { | ||||
|   return '.'; | ||||
| } | ||||
| #endif | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_API FMT_FUNC format_error::~format_error() FMT_NOEXCEPT = default; | ||||
| FMT_API FMT_FUNC system_error::~system_error() FMT_NOEXCEPT = default; | ||||
| @@ -247,9 +243,6 @@ const typename basic_data<T>::digit_pair basic_data<T>::digits[] = { | ||||
|     {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'}, | ||||
|     {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}}; | ||||
|  | ||||
| template <typename T> | ||||
| const char basic_data<T>::hex_digits[] = "0123456789abcdef"; | ||||
|  | ||||
| #define FMT_POWERS_OF_10(factor)                                             \ | ||||
|   factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \ | ||||
|       (factor)*1000000, (factor)*10000000, (factor)*100000000,               \ | ||||
| @@ -1070,10 +1063,14 @@ const char basic_data<T>::background_color[] = "\x1b[48;2;"; | ||||
| template <typename T> const char basic_data<T>::reset_color[] = "\x1b[0m"; | ||||
| template <typename T> const wchar_t basic_data<T>::wreset_color[] = L"\x1b[0m"; | ||||
| template <typename T> const char basic_data<T>::signs[] = {0, '-', '+', ' '}; | ||||
|  | ||||
| #if __cplusplus < 201703L | ||||
| template <typename T> constexpr const char basic_data<T>::hex_digits[]; | ||||
| template <typename T> constexpr const unsigned basic_data<T>::prefixes[]; | ||||
| template <typename T> constexpr const char basic_data<T>::left_padding_shifts[]; | ||||
| template <typename T> | ||||
| const char basic_data<T>::left_padding_shifts[] = {31, 31, 0, 1, 0}; | ||||
| template <typename T> | ||||
| const char basic_data<T>::right_padding_shifts[] = {0, 31, 0, 1, 0}; | ||||
| constexpr const char basic_data<T>::right_padding_shifts[]; | ||||
| #endif | ||||
|  | ||||
| template <typename T> struct bits { | ||||
|   static FMT_CONSTEXPR_DECL const int value = | ||||
| @@ -1228,7 +1225,7 @@ struct accumulator { | ||||
|     if (lower < n) ++upper; | ||||
|   } | ||||
|   void operator>>=(int shift) { | ||||
|     assert(shift == 32); | ||||
|     FMT_ASSERT(shift == 32, ""); | ||||
|     (void)shift; | ||||
|     lower = (upper << 32) | (lower >> 32); | ||||
|     upper >>= 32; | ||||
| @@ -1307,7 +1304,7 @@ class bigint { | ||||
|  public: | ||||
|   bigint() : exp_(0) {} | ||||
|   explicit bigint(uint64_t n) { assign(n); } | ||||
|   ~bigint() { assert(bigits_.capacity() <= bigits_capacity); } | ||||
|   ~bigint() { FMT_ASSERT(bigits_.capacity() <= bigits_capacity, ""); } | ||||
|  | ||||
|   bigint(const bigint&) = delete; | ||||
|   void operator=(const bigint&) = delete; | ||||
| @@ -1333,7 +1330,7 @@ class bigint { | ||||
|   int num_bigits() const { return static_cast<int>(bigits_.size()) + exp_; } | ||||
|  | ||||
|   FMT_NOINLINE bigint& operator<<=(int shift) { | ||||
|     assert(shift >= 0); | ||||
|     FMT_ASSERT(shift >= 0, ""); | ||||
|     exp_ += shift / bigit_bits; | ||||
|     shift %= bigit_bits; | ||||
|     if (shift == 0) return *this; | ||||
| @@ -1395,7 +1392,7 @@ class bigint { | ||||
|  | ||||
|   // Assigns pow(10, exp) to this bigint. | ||||
|   void assign_pow10(int exp) { | ||||
|     assert(exp >= 0); | ||||
|     FMT_ASSERT(exp >= 0, ""); | ||||
|     if (exp == 0) return assign(1); | ||||
|     // Find the top bit. | ||||
|     int bitmask = 1; | ||||
| @@ -1646,8 +1643,7 @@ struct fixed_handler { | ||||
| // Implementation of Dragonbox algorithm: https://github.com/jk-jeon/dragonbox. | ||||
| namespace dragonbox { | ||||
| // Computes 128-bit result of multiplication of two 64-bit unsigned integers. | ||||
| FMT_SAFEBUFFERS inline uint128_wrapper umul128(uint64_t x, | ||||
|                                                uint64_t y) FMT_NOEXCEPT { | ||||
| inline uint128_wrapper umul128(uint64_t x, uint64_t y) FMT_NOEXCEPT { | ||||
| #if FMT_USE_INT128 | ||||
|   return static_cast<uint128_t>(x) * static_cast<uint128_t>(y); | ||||
| #elif defined(_MSC_VER) && defined(_M_X64) | ||||
| @@ -1675,8 +1671,7 @@ FMT_SAFEBUFFERS inline uint128_wrapper umul128(uint64_t x, | ||||
| } | ||||
|  | ||||
| // Computes upper 64 bits of multiplication of two 64-bit unsigned integers. | ||||
| FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x, | ||||
|                                                 uint64_t y) FMT_NOEXCEPT { | ||||
| inline uint64_t umul128_upper64(uint64_t x, uint64_t y) FMT_NOEXCEPT { | ||||
| #if FMT_USE_INT128 | ||||
|   auto p = static_cast<uint128_t>(x) * static_cast<uint128_t>(y); | ||||
|   return static_cast<uint64_t>(p >> 64); | ||||
| @@ -1689,8 +1684,7 @@ FMT_SAFEBUFFERS inline uint64_t umul128_upper64(uint64_t x, | ||||
|  | ||||
| // Computes upper 64 bits of multiplication of a 64-bit unsigned integer and a | ||||
| // 128-bit unsigned integer. | ||||
| FMT_SAFEBUFFERS inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) | ||||
|     FMT_NOEXCEPT { | ||||
| inline uint64_t umul192_upper64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT { | ||||
|   uint128_wrapper g0 = umul128(x, y.high()); | ||||
|   g0 += umul128_upper64(x, y.low()); | ||||
|   return g0.high(); | ||||
| @@ -1704,8 +1698,7 @@ inline uint32_t umul96_upper32(uint32_t x, uint64_t y) FMT_NOEXCEPT { | ||||
|  | ||||
| // Computes middle 64 bits of multiplication of a 64-bit unsigned integer and a | ||||
| // 128-bit unsigned integer. | ||||
| FMT_SAFEBUFFERS inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) | ||||
|     FMT_NOEXCEPT { | ||||
| inline uint64_t umul192_middle64(uint64_t x, uint128_wrapper y) FMT_NOEXCEPT { | ||||
|   uint64_t g01 = x * y.high(); | ||||
|   uint64_t g10 = umul128_upper64(x, y.low()); | ||||
|   return g01 + g10; | ||||
| @@ -2124,8 +2117,8 @@ FMT_ALWAYS_INLINE int remove_trailing_zeros(uint64_t& n) FMT_NOEXCEPT { | ||||
|  | ||||
| // The main algorithm for shorter interval case | ||||
| template <class T> | ||||
| FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp<T> shorter_interval_case( | ||||
|     int exponent) FMT_NOEXCEPT { | ||||
| FMT_ALWAYS_INLINE decimal_fp<T> shorter_interval_case(int exponent) | ||||
|     FMT_NOEXCEPT { | ||||
|   decimal_fp<T> ret_value; | ||||
|   // Compute k and beta | ||||
|   const int minus_k = floor_log10_pow2_minus_log10_4_over_3(exponent); | ||||
| @@ -2171,8 +2164,7 @@ FMT_ALWAYS_INLINE FMT_SAFEBUFFERS decimal_fp<T> shorter_interval_case( | ||||
|   return ret_value; | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| FMT_SAFEBUFFERS decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT { | ||||
| template <typename T> decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT { | ||||
|   // Step 1: integer promotion & Schubfach multiplier calculation. | ||||
|  | ||||
|   using carrier_uint = typename float_info<T>::carrier_uint; | ||||
| @@ -2571,11 +2563,11 @@ int snprintf_float(T value, int precision, float_specs specs, | ||||
|       --exp_pos; | ||||
|     } while (*exp_pos != 'e'); | ||||
|     char sign = exp_pos[1]; | ||||
|     assert(sign == '+' || sign == '-'); | ||||
|     FMT_ASSERT(sign == '+' || sign == '-', ""); | ||||
|     int exp = 0; | ||||
|     auto p = exp_pos + 2;  // Skip 'e' and sign. | ||||
|     do { | ||||
|       assert(is_digit(*p)); | ||||
|       FMT_ASSERT(is_digit(*p), ""); | ||||
|       exp = exp * 10 + (*p++ - '0'); | ||||
|     } while (p != end); | ||||
|     if (sign == '-') exp = -exp; | ||||
| @@ -2593,54 +2585,6 @@ int snprintf_float(T value, int precision, float_specs specs, | ||||
|   } | ||||
| } | ||||
|  | ||||
| // A public domain branchless UTF-8 decoder by Christopher Wellons: | ||||
| // https://github.com/skeeto/branchless-utf8 | ||||
| /* Decode the next character, c, from buf, reporting errors in e. | ||||
|  * | ||||
|  * Since this is a branchless decoder, four bytes will be read from the | ||||
|  * buffer regardless of the actual length of the next character. This | ||||
|  * means the buffer _must_ have at least three bytes of zero padding | ||||
|  * following the end of the data stream. | ||||
|  * | ||||
|  * Errors are reported in e, which will be non-zero if the parsed | ||||
|  * character was somehow invalid: invalid byte sequence, non-canonical | ||||
|  * encoding, or a surrogate half. | ||||
|  * | ||||
|  * The function returns a pointer to the next character. When an error | ||||
|  * occurs, this pointer will be a guess that depends on the particular | ||||
|  * error, but it will always advance at least one byte. | ||||
|  */ | ||||
| inline const char* utf8_decode(const char* buf, uint32_t* c, int* e) { | ||||
|   static const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; | ||||
|   static const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; | ||||
|   static const int shiftc[] = {0, 18, 12, 6, 0}; | ||||
|   static const int shifte[] = {0, 6, 4, 2, 0}; | ||||
|  | ||||
|   int len = code_point_length(buf); | ||||
|   const char* next = buf + len; | ||||
|  | ||||
|   // Assume a four-byte character and load four bytes. Unused bits are | ||||
|   // shifted out. | ||||
|   auto s = reinterpret_cast<const unsigned char*>(buf); | ||||
|   *c = uint32_t(s[0] & masks[len]) << 18; | ||||
|   *c |= uint32_t(s[1] & 0x3f) << 12; | ||||
|   *c |= uint32_t(s[2] & 0x3f) << 6; | ||||
|   *c |= uint32_t(s[3] & 0x3f) << 0; | ||||
|   *c >>= shiftc[len]; | ||||
|  | ||||
|   // Accumulate the various error conditions. | ||||
|   *e = (*c < mins[len]) << 6;       // non-canonical encoding | ||||
|   *e |= ((*c >> 11) == 0x1b) << 7;  // surrogate half? | ||||
|   *e |= (*c > 0x10FFFF) << 8;       // out of range? | ||||
|   *e |= (s[1] & 0xc0) >> 2; | ||||
|   *e |= (s[2] & 0xc0) >> 4; | ||||
|   *e |= (s[3]) >> 6; | ||||
|   *e ^= 0x2a;  // top two bits of each tail byte correct? | ||||
|   *e >>= shifte[len]; | ||||
|  | ||||
|   return next; | ||||
| } | ||||
|  | ||||
| struct stringifier { | ||||
|   template <typename T> FMT_INLINE std::string operator()(T value) const { | ||||
|     return to_string(value); | ||||
| @@ -2656,7 +2600,8 @@ struct stringifier { | ||||
| }  // namespace detail | ||||
|  | ||||
| template <> struct formatter<detail::bigint> { | ||||
|   format_parse_context::iterator parse(format_parse_context& ctx) { | ||||
|   FMT_CONSTEXPR format_parse_context::iterator parse( | ||||
|       format_parse_context& ctx) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
|  | ||||
| @@ -2667,23 +2612,21 @@ template <> struct formatter<detail::bigint> { | ||||
|     for (auto i = n.bigits_.size(); i > 0; --i) { | ||||
|       auto value = n.bigits_[i - 1u]; | ||||
|       if (first) { | ||||
|         out = format_to(out, "{:x}", value); | ||||
|         out = format_to(out, FMT_STRING("{:x}"), value); | ||||
|         first = false; | ||||
|         continue; | ||||
|       } | ||||
|       out = format_to(out, "{:08x}", value); | ||||
|       out = format_to(out, FMT_STRING("{:08x}"), value); | ||||
|     } | ||||
|     if (n.exp_ > 0) | ||||
|       out = format_to(out, "p{}", n.exp_ * detail::bigint::bigit_bits); | ||||
|       out = format_to(out, FMT_STRING("p{}"), | ||||
|                       n.exp_ * detail::bigint::bigit_bits); | ||||
|     return out; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { | ||||
|   auto transcode = [this](const char* p) { | ||||
|     auto cp = uint32_t(); | ||||
|     auto error = 0; | ||||
|     p = utf8_decode(p, &cp, &error); | ||||
|   for_each_codepoint(s, [this](uint32_t cp, int error) { | ||||
|     if (error != 0) FMT_THROW(std::runtime_error("invalid utf8")); | ||||
|     if (cp <= 0xFFFF) { | ||||
|       buffer_.push_back(static_cast<wchar_t>(cp)); | ||||
| @@ -2692,21 +2635,7 @@ FMT_FUNC detail::utf8_to_utf16::utf8_to_utf16(string_view s) { | ||||
|       buffer_.push_back(static_cast<wchar_t>(0xD800 + (cp >> 10))); | ||||
|       buffer_.push_back(static_cast<wchar_t>(0xDC00 + (cp & 0x3FF))); | ||||
|     } | ||||
|     return p; | ||||
|   }; | ||||
|   auto p = s.data(); | ||||
|   const size_t block_size = 4;  // utf8_decode always reads blocks of 4 chars. | ||||
|   if (s.size() >= block_size) { | ||||
|     for (auto end = p + s.size() - block_size + 1; p < end;) p = transcode(p); | ||||
|   } | ||||
|   if (auto num_chars_left = s.data() + s.size() - p) { | ||||
|     char buf[2 * block_size - 1] = {}; | ||||
|     memcpy(buf, p, to_unsigned(num_chars_left)); | ||||
|     p = buf; | ||||
|     do { | ||||
|       p = transcode(p); | ||||
|     } while (p - buf < num_chars_left); | ||||
|   } | ||||
|   }); | ||||
|   buffer_.push_back(0); | ||||
| } | ||||
|  | ||||
| @@ -2720,8 +2649,8 @@ FMT_FUNC void format_system_error(detail::buffer<char>& out, int error_code, | ||||
|       int result = | ||||
|           detail::safe_strerror(error_code, system_message, buf.size()); | ||||
|       if (result == 0) { | ||||
|         format_to(detail::buffer_appender<char>(out), "{}: {}", message, | ||||
|                   system_message); | ||||
|         format_to(detail::buffer_appender<char>(out), FMT_STRING("{}: {}"), | ||||
|                   message, system_message); | ||||
|         return; | ||||
|       } | ||||
|       if (result != ERANGE) | ||||
| @@ -2770,12 +2699,13 @@ FMT_FUNC void vprint(std::FILE* f, string_view format_str, format_args args) { | ||||
|   if (_isatty(fd)) { | ||||
|     detail::utf8_to_utf16 u16(string_view(buffer.data(), buffer.size())); | ||||
|     auto written = detail::dword(); | ||||
|     if (!detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)), | ||||
|                                u16.c_str(), static_cast<uint32_t>(u16.size()), | ||||
|                                &written, nullptr)) { | ||||
|       FMT_THROW(format_error("failed to write to console")); | ||||
|     if (detail::WriteConsoleW(reinterpret_cast<void*>(_get_osfhandle(fd)), | ||||
|                               u16.c_str(), static_cast<uint32_t>(u16.size()), | ||||
|                               &written, nullptr)) { | ||||
|       return; | ||||
|     } | ||||
|     return; | ||||
|     // Fallback to fwrite on failure. It can happen if the output has been | ||||
|     // redirected to NUL. | ||||
|   } | ||||
| #endif | ||||
|   detail::fwrite_fully(buffer.data(), 1, buffer.size(), f); | ||||
|   | ||||
							
								
								
									
										1380
									
								
								vendor/Fmt/include/fmt/format.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1380
									
								
								vendor/Fmt/include/fmt/format.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4
									
								
								vendor/Fmt/include/fmt/locale.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								vendor/Fmt/include/fmt/locale.h
									
									
									
									
										vendored
									
									
								
							| @@ -52,8 +52,8 @@ inline OutputIt vformat_to( | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value> | ||||
| inline auto format_to(OutputIt out, const std::locale& loc, | ||||
|                       const S& format_str, Args&&... args) -> | ||||
| inline auto format_to(OutputIt out, const std::locale& loc, const S& format_str, | ||||
|                       Args&&... args) -> | ||||
|     typename std::enable_if<enable, OutputIt>::type { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   return vformat_to(out, loc, to_string_view(format_str), vargs); | ||||
|   | ||||
							
								
								
									
										40
									
								
								vendor/Fmt/include/fmt/os.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										40
									
								
								vendor/Fmt/include/fmt/os.h
									
									
									
									
										vendored
									
									
								
							| @@ -8,11 +8,6 @@ | ||||
| #ifndef FMT_OS_H_ | ||||
| #define FMT_OS_H_ | ||||
|  | ||||
| #if defined(__MINGW32__) || defined(__CYGWIN__) | ||||
| // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. | ||||
| #  undef __STRICT_ANSI__ | ||||
| #endif | ||||
|  | ||||
| #include <cerrno> | ||||
| #include <clocale>  // for locale_t | ||||
| #include <cstddef> | ||||
| @@ -280,7 +275,8 @@ class file { | ||||
|     WRONLY = FMT_POSIX(O_WRONLY),  // Open for writing only. | ||||
|     RDWR = FMT_POSIX(O_RDWR),      // Open for reading and writing. | ||||
|     CREATE = FMT_POSIX(O_CREAT),   // Create if the file doesn't exist. | ||||
|     APPEND = FMT_POSIX(O_APPEND)   // Open in append mode. | ||||
|     APPEND = FMT_POSIX(O_APPEND),  // Open in append mode. | ||||
|     TRUNC = FMT_POSIX(O_TRUNC)     // Truncate the content of the file. | ||||
|   }; | ||||
|  | ||||
|   // Constructs a file object which doesn't represent any file. | ||||
| @@ -348,6 +344,7 @@ long getpagesize(); | ||||
| namespace detail { | ||||
|  | ||||
| struct buffer_size { | ||||
|   buffer_size() = default; | ||||
|   size_t value = 0; | ||||
|   buffer_size operator=(size_t val) const { | ||||
|     auto bs = buffer_size(); | ||||
| @@ -357,14 +354,14 @@ struct buffer_size { | ||||
| }; | ||||
|  | ||||
| struct ostream_params { | ||||
|   int oflag = file::WRONLY | file::CREATE; | ||||
|   int oflag = file::WRONLY | file::CREATE | file::TRUNC; | ||||
|   size_t buffer_size = BUFSIZ > 32768 ? BUFSIZ : 32768; | ||||
|  | ||||
|   ostream_params() {} | ||||
|  | ||||
|   template <typename... T> | ||||
|   ostream_params(T... params, int oflag) : ostream_params(params...) { | ||||
|     this->oflag = oflag; | ||||
|   ostream_params(T... params, int new_oflag) : ostream_params(params...) { | ||||
|     oflag = new_oflag; | ||||
|   } | ||||
|  | ||||
|   template <typename... T> | ||||
| @@ -377,7 +374,7 @@ struct ostream_params { | ||||
|  | ||||
| static constexpr detail::buffer_size buffer_size; | ||||
|  | ||||
| // A fast output stream which is not thread-safe. | ||||
| /** A fast output stream which is not thread-safe. */ | ||||
| class ostream final : private detail::buffer<char> { | ||||
|  private: | ||||
|   file file_; | ||||
| @@ -414,16 +411,31 @@ class ostream final : private detail::buffer<char> { | ||||
|     file_.close(); | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|     Formats ``args`` according to specifications in ``format_str`` and writes | ||||
|     the output to the file. | ||||
|    */ | ||||
|   template <typename S, typename... Args> | ||||
|   void print(const S& format_str, const Args&... args) { | ||||
|     format_to(detail::buffer_appender<char>(*this), format_str, args...); | ||||
|   void print(const S& format_str, Args&&... args) { | ||||
|     format_to(detail::buffer_appender<char>(*this), format_str, | ||||
|               std::forward<Args>(args)...); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|   Opens a file for writing. Supported parameters passed in `params`: | ||||
|   * ``<integer>``: Output flags (``file::WRONLY | file::CREATE`` by default) | ||||
|   \rst | ||||
|   Opens a file for writing. Supported parameters passed in *params*: | ||||
|  | ||||
|   * ``<integer>``: Flags passed to `open | ||||
|     <https://pubs.opengroup.org/onlinepubs/007904875/functions/open.html>`_ | ||||
|     (``file::WRONLY | file::CREATE`` by default) | ||||
|   * ``buffer_size=<integer>``: Output buffer size | ||||
|  | ||||
|   **Example**:: | ||||
|  | ||||
|     auto out = fmt::output_file("guide.txt"); | ||||
|     out.print("Don't {}", "Panic"); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename... T> | ||||
| inline ostream output_file(cstring_view path, T... params) { | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/Fmt/include/fmt/ostream.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/Fmt/include/fmt/ostream.h
									
									
									
									
										vendored
									
									
								
							| @@ -85,6 +85,8 @@ template <typename T, typename Char> class is_streamable { | ||||
|   using result = decltype(test<T>(0)); | ||||
|  | ||||
|  public: | ||||
|   is_streamable() = default; | ||||
|  | ||||
|   static const bool value = result::value; | ||||
| }; | ||||
|  | ||||
|   | ||||
							
								
								
									
										103
									
								
								vendor/Fmt/include/fmt/printf.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										103
									
								
								vendor/Fmt/include/fmt/printf.h
									
									
									
									
										vendored
									
									
								
							| @@ -207,50 +207,32 @@ template <typename OutputIt, typename Char> class basic_printf_context; | ||||
|  */ | ||||
| template <typename OutputIt, typename Char> | ||||
| class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> { | ||||
|  public: | ||||
|   using iterator = OutputIt; | ||||
|  | ||||
|  private: | ||||
|   using char_type = Char; | ||||
|   using base = detail::arg_formatter_base<OutputIt, Char>; | ||||
|   using context_type = basic_printf_context<OutputIt, Char>; | ||||
|   using format_specs = typename base::format_specs; | ||||
|  | ||||
|   context_type& context_; | ||||
|  | ||||
|   void write_null_pointer(char) { | ||||
|     this->specs()->type = 0; | ||||
|     this->write("(nil)"); | ||||
|   } | ||||
|  | ||||
|   void write_null_pointer(wchar_t) { | ||||
|     this->specs()->type = 0; | ||||
|     this->write(L"(nil)"); | ||||
|   OutputIt write_null_pointer(bool is_string = false) { | ||||
|     auto s = this->specs(); | ||||
|     s.type = 0; | ||||
|     return detail::write(this->out(), | ||||
|                          string_view(is_string ? "(null)" : "(nil)"), s); | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   using format_specs = typename base::format_specs; | ||||
|   printf_arg_formatter(OutputIt iter, format_specs& specs, context_type& ctx) | ||||
|       : base(iter, specs, detail::locale_ref()), context_(ctx) {} | ||||
|  | ||||
|   /** | ||||
|     \rst | ||||
|     Constructs an argument formatter object. | ||||
|     *buffer* is a reference to the output buffer and *specs* contains format | ||||
|     specifier information for standard argument types. | ||||
|     \endrst | ||||
|    */ | ||||
|   printf_arg_formatter(iterator iter, format_specs& specs, context_type& ctx) | ||||
|       : base(iter, &specs, detail::locale_ref()), context_(ctx) {} | ||||
|   OutputIt operator()(monostate value) { return base::operator()(value); } | ||||
|  | ||||
|   template <typename T, FMT_ENABLE_IF(fmt::detail::is_integral<T>::value)> | ||||
|   iterator operator()(T value) { | ||||
|     // MSVC2013 fails to compile separate overloads for bool and char_type so | ||||
|     // use std::is_same instead. | ||||
|     if (std::is_same<T, bool>::value) { | ||||
|       format_specs& fmt_specs = *this->specs(); | ||||
|       if (fmt_specs.type != 's') return base::operator()(value ? 1 : 0); | ||||
|       fmt_specs.type = 0; | ||||
|       this->write(value != 0); | ||||
|     } else if (std::is_same<T, char_type>::value) { | ||||
|       format_specs& fmt_specs = *this->specs(); | ||||
|   OutputIt operator()(T value) { | ||||
|     // MSVC2013 fails to compile separate overloads for bool and Char so use | ||||
|     // std::is_same instead. | ||||
|     if (std::is_same<T, Char>::value) { | ||||
|       format_specs fmt_specs = this->specs(); | ||||
|       if (fmt_specs.type && fmt_specs.type != 'c') | ||||
|         return (*this)(static_cast<int>(value)); | ||||
|       fmt_specs.sign = sign::none; | ||||
| @@ -260,56 +242,39 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> { | ||||
|       // ignored for non-numeric types | ||||
|       if (fmt_specs.align == align::none || fmt_specs.align == align::numeric) | ||||
|         fmt_specs.align = align::right; | ||||
|       return base::operator()(value); | ||||
|     } else { | ||||
|       return base::operator()(value); | ||||
|       return write_char(this->out(), static_cast<Char>(value), fmt_specs); | ||||
|     } | ||||
|     return this->out(); | ||||
|     return base::operator()(value); | ||||
|   } | ||||
|  | ||||
|   template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> | ||||
|   iterator operator()(T value) { | ||||
|   OutputIt operator()(T value) { | ||||
|     return base::operator()(value); | ||||
|   } | ||||
|  | ||||
|   /** Formats a null-terminated C string. */ | ||||
|   iterator operator()(const char* value) { | ||||
|     if (value) | ||||
|       base::operator()(value); | ||||
|     else if (this->specs()->type == 'p') | ||||
|       write_null_pointer(char_type()); | ||||
|     else | ||||
|       this->write("(null)"); | ||||
|     return this->out(); | ||||
|   OutputIt operator()(const char* value) { | ||||
|     if (value) return base::operator()(value); | ||||
|     return write_null_pointer(this->specs().type != 'p'); | ||||
|   } | ||||
|  | ||||
|   /** Formats a null-terminated wide C string. */ | ||||
|   iterator operator()(const wchar_t* value) { | ||||
|     if (value) | ||||
|       base::operator()(value); | ||||
|     else if (this->specs()->type == 'p') | ||||
|       write_null_pointer(char_type()); | ||||
|     else | ||||
|       this->write(L"(null)"); | ||||
|     return this->out(); | ||||
|   OutputIt operator()(const wchar_t* value) { | ||||
|     if (value) return base::operator()(value); | ||||
|     return write_null_pointer(this->specs().type != 'p'); | ||||
|   } | ||||
|  | ||||
|   iterator operator()(basic_string_view<char_type> value) { | ||||
|   OutputIt operator()(basic_string_view<Char> value) { | ||||
|     return base::operator()(value); | ||||
|   } | ||||
|  | ||||
|   iterator operator()(monostate value) { return base::operator()(value); } | ||||
|  | ||||
|   /** Formats a pointer. */ | ||||
|   iterator operator()(const void* value) { | ||||
|     if (value) return base::operator()(value); | ||||
|     this->specs()->type = 0; | ||||
|     write_null_pointer(char_type()); | ||||
|     return this->out(); | ||||
|   OutputIt operator()(const void* value) { | ||||
|     return value ? base::operator()(value) : write_null_pointer(); | ||||
|   } | ||||
|  | ||||
|   /** Formats an argument of a custom (user-defined) type. */ | ||||
|   iterator operator()(typename basic_format_arg<context_type>::handle handle) { | ||||
|   OutputIt operator()(typename basic_format_arg<context_type>::handle handle) { | ||||
|     handle.format(context_.parse_context(), context_); | ||||
|     return this->out(); | ||||
|   } | ||||
| @@ -474,14 +439,19 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|   const Char* end = parse_ctx_.end(); | ||||
|   auto it = start; | ||||
|   while (it != end) { | ||||
|     if (!detail::find<false, Char>(it, end, '%', it)) { | ||||
|       it = end;  // detail::find leaves it == nullptr if it doesn't find '%' | ||||
|       break; | ||||
|     } | ||||
|     char_type c = *it++; | ||||
|     if (c != '%') continue; | ||||
|     if (it != end && *it == c) { | ||||
|       out = std::copy(start, it, out); | ||||
|       out = detail::write( | ||||
|           out, basic_string_view<Char>(start, detail::to_unsigned(it - start))); | ||||
|       start = ++it; | ||||
|       continue; | ||||
|     } | ||||
|     out = std::copy(start, it - 1, out); | ||||
|     out = detail::write(out, basic_string_view<Char>( | ||||
|                                  start, detail::to_unsigned(it - 1 - start))); | ||||
|  | ||||
|     format_specs specs; | ||||
|     specs.align = align::right; | ||||
| @@ -593,7 +563,8 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|     // Format argument. | ||||
|     out = visit_format_arg(ArgFormatter(out, specs, *this), arg); | ||||
|   } | ||||
|   return std::copy(start, it, out); | ||||
|   return detail::write( | ||||
|       out, basic_string_view<Char>(start, detail::to_unsigned(it - start))); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
|   | ||||
							
								
								
									
										199
									
								
								vendor/Fmt/include/fmt/ranges.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										199
									
								
								vendor/Fmt/include/fmt/ranges.h
									
									
									
									
										vendored
									
									
								
							| @@ -36,22 +36,14 @@ struct formatting_range : formatting_base<Char> { | ||||
|   static FMT_CONSTEXPR_DECL const size_t range_length_limit = | ||||
|       FMT_RANGE_OUTPUT_LENGTH_LIMIT;  // output only up to N items from the | ||||
|                                       // range. | ||||
|   Char prefix; | ||||
|   Char delimiter; | ||||
|   Char postfix; | ||||
|   formatting_range() : prefix('{'), delimiter(','), postfix('}') {} | ||||
|   static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true; | ||||
|   static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false; | ||||
|   Char prefix = '{'; | ||||
|   Char postfix = '}'; | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename Enable = void> | ||||
| struct formatting_tuple : formatting_base<Char> { | ||||
|   Char prefix; | ||||
|   Char delimiter; | ||||
|   Char postfix; | ||||
|   formatting_tuple() : prefix('('), delimiter(','), postfix(')') {} | ||||
|   static FMT_CONSTEXPR_DECL const bool add_delimiter_spaces = true; | ||||
|   static FMT_CONSTEXPR_DECL const bool add_prepostfix_space = false; | ||||
|   Char prefix = '('; | ||||
|   Char postfix = ')'; | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
| @@ -95,12 +87,100 @@ template <typename... Ts> struct conditional_helper {}; | ||||
| template <typename T, typename _ = void> struct is_range_ : std::false_type {}; | ||||
|  | ||||
| #if !FMT_MSC_VER || FMT_MSC_VER > 1800 | ||||
|  | ||||
| #  define FMT_DECLTYPE_RETURN(val)  \ | ||||
|     ->decltype(val) { return val; } \ | ||||
|     static_assert(                  \ | ||||
|         true, "")  // This makes it so that a semicolon is required after the | ||||
|                    // macro, which helps clang-format handle the formatting. | ||||
|  | ||||
| // C array overload | ||||
| template <typename T, std::size_t N> | ||||
| auto range_begin(const T (&arr)[N]) -> const T* { | ||||
|   return arr; | ||||
| } | ||||
| template <typename T, std::size_t N> | ||||
| auto range_end(const T (&arr)[N]) -> const T* { | ||||
|   return arr + N; | ||||
| } | ||||
|  | ||||
| template <typename T, typename Enable = void> | ||||
| struct has_member_fn_begin_end_t : std::false_type {}; | ||||
|  | ||||
| template <typename T> | ||||
| struct is_range_< | ||||
|     T, conditional_t<false, | ||||
|                      conditional_helper<decltype(std::declval<T>().begin()), | ||||
|                                         decltype(std::declval<T>().end())>, | ||||
|                      void>> : std::true_type {}; | ||||
| struct has_member_fn_begin_end_t<T, void_t<decltype(std::declval<T>().begin()), | ||||
|                                            decltype(std::declval<T>().end())>> | ||||
|     : std::true_type {}; | ||||
|  | ||||
| // Member function overload | ||||
| template <typename T> | ||||
| auto range_begin(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).begin()); | ||||
| template <typename T> | ||||
| auto range_end(T&& rng) FMT_DECLTYPE_RETURN(static_cast<T&&>(rng).end()); | ||||
|  | ||||
| // ADL overload. Only participates in overload resolution if member functions | ||||
| // are not found. | ||||
| template <typename T> | ||||
| auto range_begin(T&& rng) | ||||
|     -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value, | ||||
|                    decltype(begin(static_cast<T&&>(rng)))> { | ||||
|   return begin(static_cast<T&&>(rng)); | ||||
| } | ||||
| template <typename T> | ||||
| auto range_end(T&& rng) -> enable_if_t<!has_member_fn_begin_end_t<T&&>::value, | ||||
|                                        decltype(end(static_cast<T&&>(rng)))> { | ||||
|   return end(static_cast<T&&>(rng)); | ||||
| } | ||||
|  | ||||
| template <typename T, typename Enable = void> | ||||
| struct has_const_begin_end : std::false_type {}; | ||||
| template <typename T, typename Enable = void> | ||||
| struct has_mutable_begin_end : std::false_type {}; | ||||
|  | ||||
| template <typename T> | ||||
| struct has_const_begin_end< | ||||
|     T, void_t<decltype(detail::range_begin( | ||||
|                   std::declval<const remove_cvref_t<T>&>())), | ||||
|               decltype(detail::range_begin( | ||||
|                   std::declval<const remove_cvref_t<T>&>()))>> | ||||
|     : std::true_type {}; | ||||
|  | ||||
| template <typename T> | ||||
| struct has_mutable_begin_end< | ||||
|     T, void_t<decltype(detail::range_begin(std::declval<T>())), | ||||
|               decltype(detail::range_begin(std::declval<T>())), | ||||
|               enable_if_t<std::is_copy_constructible<T>::value>>> | ||||
|     : std::true_type {}; | ||||
|  | ||||
| template <typename T> | ||||
| struct is_range_<T, void> | ||||
|     : std::integral_constant<bool, (has_const_begin_end<T>::value || | ||||
|                                     has_mutable_begin_end<T>::value)> {}; | ||||
|  | ||||
| template <typename T, typename Enable = void> struct range_to_view; | ||||
| template <typename T> | ||||
| struct range_to_view<T, enable_if_t<has_const_begin_end<T>::value>> { | ||||
|   struct view_t { | ||||
|     const T* m_range_ptr; | ||||
|  | ||||
|     auto begin() const FMT_DECLTYPE_RETURN(detail::range_begin(*m_range_ptr)); | ||||
|     auto end() const FMT_DECLTYPE_RETURN(detail::range_end(*m_range_ptr)); | ||||
|   }; | ||||
|   static auto view(const T& range) -> view_t { return {&range}; } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct range_to_view<T, enable_if_t<!has_const_begin_end<T>::value && | ||||
|                                     has_mutable_begin_end<T>::value>> { | ||||
|   struct view_t { | ||||
|     T m_range_copy; | ||||
|  | ||||
|     auto begin() FMT_DECLTYPE_RETURN(detail::range_begin(m_range_copy)); | ||||
|     auto end() FMT_DECLTYPE_RETURN(detail::range_end(m_range_copy)); | ||||
|   }; | ||||
|   static auto view(const T& range) -> view_t { return {range}; } | ||||
| }; | ||||
| #  undef FMT_DECLTYPE_RETURN | ||||
| #endif | ||||
|  | ||||
| /// tuple_size and tuple_element check. | ||||
| @@ -158,33 +238,42 @@ template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) { | ||||
| } | ||||
|  | ||||
| template <typename Range> | ||||
| using value_type = remove_cvref_t<decltype(*std::declval<Range>().begin())>; | ||||
| using value_type = | ||||
|     remove_cvref_t<decltype(*detail::range_begin(std::declval<Range>()))>; | ||||
|  | ||||
| template <typename Arg, FMT_ENABLE_IF(!is_like_std_string< | ||||
|                                       typename std::decay<Arg>::type>::value)> | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) { | ||||
|   return add_space ? " {}" : "{}"; | ||||
| template <typename OutputIt> OutputIt write_delimiter(OutputIt out) { | ||||
|   *out++ = ','; | ||||
|   *out++ = ' '; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| template <typename Arg, FMT_ENABLE_IF(is_like_std_string< | ||||
|                                       typename std::decay<Arg>::type>::value)> | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) { | ||||
|   return add_space ? " \"{}\"" : "\"{}\""; | ||||
| template < | ||||
|     typename Char, typename OutputIt, typename Arg, | ||||
|     FMT_ENABLE_IF(is_like_std_string<typename std::decay<Arg>::type>::value)> | ||||
| OutputIt write_range_entry(OutputIt out, const Arg& v) { | ||||
|   *out++ = '"'; | ||||
|   out = write<Char>(out, v); | ||||
|   *out++ = '"'; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) { | ||||
|   return add_space ? " \"{}\"" : "\"{}\""; | ||||
| } | ||||
| FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) { | ||||
|   return add_space ? L" \"{}\"" : L"\"{}\""; | ||||
| template <typename Char, typename OutputIt, typename Arg, | ||||
|           FMT_ENABLE_IF(std::is_same<Arg, Char>::value)> | ||||
| OutputIt write_range_entry(OutputIt out, const Arg v) { | ||||
|   *out++ = '\''; | ||||
|   *out++ = v; | ||||
|   *out++ = '\''; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) { | ||||
|   return add_space ? " '{}'" : "'{}'"; | ||||
| } | ||||
| FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) { | ||||
|   return add_space ? L" '{}'" : L"'{}'"; | ||||
| template < | ||||
|     typename Char, typename OutputIt, typename Arg, | ||||
|     FMT_ENABLE_IF(!is_like_std_string<typename std::decay<Arg>::type>::value && | ||||
|                   !std::is_same<Arg, Char>::value)> | ||||
| OutputIt write_range_entry(OutputIt out, const Arg& v) { | ||||
|   return write<Char>(out, v); | ||||
| } | ||||
|  | ||||
| }  // namespace detail | ||||
|  | ||||
| template <typename T> struct is_tuple_like { | ||||
| @@ -198,19 +287,10 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> { | ||||
|   // C++11 generic lambda for format() | ||||
|   template <typename FormatContext> struct format_each { | ||||
|     template <typename T> void operator()(const T& v) { | ||||
|       if (i > 0) { | ||||
|         if (formatting.add_prepostfix_space) { | ||||
|           *out++ = ' '; | ||||
|         } | ||||
|         out = detail::copy(formatting.delimiter, out); | ||||
|       } | ||||
|       out = format_to(out, | ||||
|                       detail::format_str_quoted( | ||||
|                           (formatting.add_delimiter_spaces && i > 0), v), | ||||
|                       v); | ||||
|       if (i > 0) out = detail::write_delimiter(out); | ||||
|       out = detail::write_range_entry<Char>(out, v); | ||||
|       ++i; | ||||
|     } | ||||
|  | ||||
|     formatting_tuple<Char>& formatting; | ||||
|     size_t& i; | ||||
|     typename std::add_lvalue_reference<decltype( | ||||
| @@ -229,12 +309,9 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> { | ||||
|   auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|     auto out = ctx.out(); | ||||
|     size_t i = 0; | ||||
|     detail::copy(formatting.prefix, out); | ||||
|  | ||||
|     detail::copy(formatting.prefix, out); | ||||
|     detail::for_each(values, format_each<FormatContext>{formatting, i, out}); | ||||
|     if (formatting.add_prepostfix_space) { | ||||
|       *out++ = ' '; | ||||
|     } | ||||
|     detail::copy(formatting.postfix, out); | ||||
|  | ||||
|     return ctx.out(); | ||||
| @@ -271,23 +348,17 @@ struct formatter< | ||||
|   typename FormatContext::iterator format(const T& values, FormatContext& ctx) { | ||||
|     auto out = detail::copy(formatting.prefix, ctx.out()); | ||||
|     size_t i = 0; | ||||
|     auto it = values.begin(); | ||||
|     auto end = values.end(); | ||||
|     auto view = detail::range_to_view<T>::view(values); | ||||
|     auto it = view.begin(); | ||||
|     auto end = view.end(); | ||||
|     for (; it != end; ++it) { | ||||
|       if (i > 0) { | ||||
|         if (formatting.add_prepostfix_space) *out++ = ' '; | ||||
|         out = detail::copy(formatting.delimiter, out); | ||||
|       } | ||||
|       out = format_to(out, | ||||
|                       detail::format_str_quoted( | ||||
|                           (formatting.add_delimiter_spaces && i > 0), *it), | ||||
|                       *it); | ||||
|       if (i > 0) out = detail::write_delimiter(out); | ||||
|       out = detail::write_range_entry<Char>(out, *it); | ||||
|       if (++i > formatting.range_length_limit) { | ||||
|         out = format_to(out, " ... <other elements>"); | ||||
|         out = format_to(out, FMT_STRING("{}"), " ... <other elements>"); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if (formatting.add_prepostfix_space) *out++ = ' '; | ||||
|     return detail::copy(formatting.postfix, out); | ||||
|   } | ||||
| }; | ||||
| @@ -297,7 +368,7 @@ template <typename Char, typename... T> struct tuple_arg_join : detail::view { | ||||
|   basic_string_view<Char> sep; | ||||
|  | ||||
|   tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s) | ||||
|       : tuple{t}, sep{s} {} | ||||
|       : tuple(t), sep{s} {} | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename... T> | ||||
|   | ||||
		Reference in New Issue
	
	Block a user