change:C++标准由20改为17,使用三方fmt替换std::format。
This commit is contained in:
		
							parent
							
								
									19e8a2da6a
								
							
						
					
					
						commit
						85f24a28f2
					
				
							
								
								
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.vscode/settings.json
									
									
									
									
										vendored
									
									
								
							@ -109,6 +109,8 @@
 | 
			
		||||
        "mutex": "cpp",
 | 
			
		||||
        "optional": "cpp",
 | 
			
		||||
        "stop_token": "cpp",
 | 
			
		||||
        "thread": "cpp"
 | 
			
		||||
        "thread": "cpp",
 | 
			
		||||
        "bitset": "cpp",
 | 
			
		||||
        "variant": "cpp"
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										235
									
								
								3rd/fmt/args.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										235
									
								
								3rd/fmt/args.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,235 @@
 | 
			
		||||
// Formatting library for C++ - dynamic argument lists
 | 
			
		||||
//
 | 
			
		||||
// 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> auto unwrap(const T& v) -> const T& { return v; }
 | 
			
		||||
template <typename T>
 | 
			
		||||
auto unwrap(const std::reference_wrapper<T>& v) -> const T& {
 | 
			
		||||
  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> auto push(const Arg& arg) -> const T& {
 | 
			
		||||
    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<
 | 
			
		||||
      std::is_convertible<T, std::basic_string<char_type>>::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>;
 | 
			
		||||
 | 
			
		||||
  auto get_types() const -> unsigned long long {
 | 
			
		||||
    return detail::is_unpacked_bit | data_.size() |
 | 
			
		||||
           (named_info_.empty()
 | 
			
		||||
                ? 0ULL
 | 
			
		||||
                : static_cast<unsigned long long>(detail::has_named_args_bit));
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto data() const -> const basic_format_arg<Context>* {
 | 
			
		||||
    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:
 | 
			
		||||
  constexpr dynamic_format_arg_store() = default;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    \rst
 | 
			
		||||
    Adds an argument into the dynamic store for later passing to a formatting
 | 
			
		||||
    function.
 | 
			
		||||
 | 
			
		||||
    Note that custom types and string types (but not string views) are copied
 | 
			
		||||
    into the store dynamically allocating memory if necessary.
 | 
			
		||||
 | 
			
		||||
    **Example**::
 | 
			
		||||
 | 
			
		||||
      fmt::dynamic_format_arg_store<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_
 | 
			
		||||
							
								
								
									
										2240
									
								
								3rd/fmt/chrono.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2240
									
								
								3rd/fmt/chrono.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										643
									
								
								3rd/fmt/color.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										643
									
								
								3rd/fmt/color.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,643 @@
 | 
			
		||||
// Formatting library for C++ - color support
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2018 - present, Victor Zverovich and fmt contributors
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_COLOR_H_
 | 
			
		||||
#define FMT_COLOR_H_
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_BEGIN_EXPORT
 | 
			
		||||
 | 
			
		||||
enum class color : uint32_t {
 | 
			
		||||
  alice_blue = 0xF0F8FF,               // rgb(240,248,255)
 | 
			
		||||
  antique_white = 0xFAEBD7,            // rgb(250,235,215)
 | 
			
		||||
  aqua = 0x00FFFF,                     // rgb(0,255,255)
 | 
			
		||||
  aquamarine = 0x7FFFD4,               // rgb(127,255,212)
 | 
			
		||||
  azure = 0xF0FFFF,                    // rgb(240,255,255)
 | 
			
		||||
  beige = 0xF5F5DC,                    // rgb(245,245,220)
 | 
			
		||||
  bisque = 0xFFE4C4,                   // rgb(255,228,196)
 | 
			
		||||
  black = 0x000000,                    // rgb(0,0,0)
 | 
			
		||||
  blanched_almond = 0xFFEBCD,          // rgb(255,235,205)
 | 
			
		||||
  blue = 0x0000FF,                     // rgb(0,0,255)
 | 
			
		||||
  blue_violet = 0x8A2BE2,              // rgb(138,43,226)
 | 
			
		||||
  brown = 0xA52A2A,                    // rgb(165,42,42)
 | 
			
		||||
  burly_wood = 0xDEB887,               // rgb(222,184,135)
 | 
			
		||||
  cadet_blue = 0x5F9EA0,               // rgb(95,158,160)
 | 
			
		||||
  chartreuse = 0x7FFF00,               // rgb(127,255,0)
 | 
			
		||||
  chocolate = 0xD2691E,                // rgb(210,105,30)
 | 
			
		||||
  coral = 0xFF7F50,                    // rgb(255,127,80)
 | 
			
		||||
  cornflower_blue = 0x6495ED,          // rgb(100,149,237)
 | 
			
		||||
  cornsilk = 0xFFF8DC,                 // rgb(255,248,220)
 | 
			
		||||
  crimson = 0xDC143C,                  // rgb(220,20,60)
 | 
			
		||||
  cyan = 0x00FFFF,                     // rgb(0,255,255)
 | 
			
		||||
  dark_blue = 0x00008B,                // rgb(0,0,139)
 | 
			
		||||
  dark_cyan = 0x008B8B,                // rgb(0,139,139)
 | 
			
		||||
  dark_golden_rod = 0xB8860B,          // rgb(184,134,11)
 | 
			
		||||
  dark_gray = 0xA9A9A9,                // rgb(169,169,169)
 | 
			
		||||
  dark_green = 0x006400,               // rgb(0,100,0)
 | 
			
		||||
  dark_khaki = 0xBDB76B,               // rgb(189,183,107)
 | 
			
		||||
  dark_magenta = 0x8B008B,             // rgb(139,0,139)
 | 
			
		||||
  dark_olive_green = 0x556B2F,         // rgb(85,107,47)
 | 
			
		||||
  dark_orange = 0xFF8C00,              // rgb(255,140,0)
 | 
			
		||||
  dark_orchid = 0x9932CC,              // rgb(153,50,204)
 | 
			
		||||
  dark_red = 0x8B0000,                 // rgb(139,0,0)
 | 
			
		||||
  dark_salmon = 0xE9967A,              // rgb(233,150,122)
 | 
			
		||||
  dark_sea_green = 0x8FBC8F,           // rgb(143,188,143)
 | 
			
		||||
  dark_slate_blue = 0x483D8B,          // rgb(72,61,139)
 | 
			
		||||
  dark_slate_gray = 0x2F4F4F,          // rgb(47,79,79)
 | 
			
		||||
  dark_turquoise = 0x00CED1,           // rgb(0,206,209)
 | 
			
		||||
  dark_violet = 0x9400D3,              // rgb(148,0,211)
 | 
			
		||||
  deep_pink = 0xFF1493,                // rgb(255,20,147)
 | 
			
		||||
  deep_sky_blue = 0x00BFFF,            // rgb(0,191,255)
 | 
			
		||||
  dim_gray = 0x696969,                 // rgb(105,105,105)
 | 
			
		||||
  dodger_blue = 0x1E90FF,              // rgb(30,144,255)
 | 
			
		||||
  fire_brick = 0xB22222,               // rgb(178,34,34)
 | 
			
		||||
  floral_white = 0xFFFAF0,             // rgb(255,250,240)
 | 
			
		||||
  forest_green = 0x228B22,             // rgb(34,139,34)
 | 
			
		||||
  fuchsia = 0xFF00FF,                  // rgb(255,0,255)
 | 
			
		||||
  gainsboro = 0xDCDCDC,                // rgb(220,220,220)
 | 
			
		||||
  ghost_white = 0xF8F8FF,              // rgb(248,248,255)
 | 
			
		||||
  gold = 0xFFD700,                     // rgb(255,215,0)
 | 
			
		||||
  golden_rod = 0xDAA520,               // rgb(218,165,32)
 | 
			
		||||
  gray = 0x808080,                     // rgb(128,128,128)
 | 
			
		||||
  green = 0x008000,                    // rgb(0,128,0)
 | 
			
		||||
  green_yellow = 0xADFF2F,             // rgb(173,255,47)
 | 
			
		||||
  honey_dew = 0xF0FFF0,                // rgb(240,255,240)
 | 
			
		||||
  hot_pink = 0xFF69B4,                 // rgb(255,105,180)
 | 
			
		||||
  indian_red = 0xCD5C5C,               // rgb(205,92,92)
 | 
			
		||||
  indigo = 0x4B0082,                   // rgb(75,0,130)
 | 
			
		||||
  ivory = 0xFFFFF0,                    // rgb(255,255,240)
 | 
			
		||||
  khaki = 0xF0E68C,                    // rgb(240,230,140)
 | 
			
		||||
  lavender = 0xE6E6FA,                 // rgb(230,230,250)
 | 
			
		||||
  lavender_blush = 0xFFF0F5,           // rgb(255,240,245)
 | 
			
		||||
  lawn_green = 0x7CFC00,               // rgb(124,252,0)
 | 
			
		||||
  lemon_chiffon = 0xFFFACD,            // rgb(255,250,205)
 | 
			
		||||
  light_blue = 0xADD8E6,               // rgb(173,216,230)
 | 
			
		||||
  light_coral = 0xF08080,              // rgb(240,128,128)
 | 
			
		||||
  light_cyan = 0xE0FFFF,               // rgb(224,255,255)
 | 
			
		||||
  light_golden_rod_yellow = 0xFAFAD2,  // rgb(250,250,210)
 | 
			
		||||
  light_gray = 0xD3D3D3,               // rgb(211,211,211)
 | 
			
		||||
  light_green = 0x90EE90,              // rgb(144,238,144)
 | 
			
		||||
  light_pink = 0xFFB6C1,               // rgb(255,182,193)
 | 
			
		||||
  light_salmon = 0xFFA07A,             // rgb(255,160,122)
 | 
			
		||||
  light_sea_green = 0x20B2AA,          // rgb(32,178,170)
 | 
			
		||||
  light_sky_blue = 0x87CEFA,           // rgb(135,206,250)
 | 
			
		||||
  light_slate_gray = 0x778899,         // rgb(119,136,153)
 | 
			
		||||
  light_steel_blue = 0xB0C4DE,         // rgb(176,196,222)
 | 
			
		||||
  light_yellow = 0xFFFFE0,             // rgb(255,255,224)
 | 
			
		||||
  lime = 0x00FF00,                     // rgb(0,255,0)
 | 
			
		||||
  lime_green = 0x32CD32,               // rgb(50,205,50)
 | 
			
		||||
  linen = 0xFAF0E6,                    // rgb(250,240,230)
 | 
			
		||||
  magenta = 0xFF00FF,                  // rgb(255,0,255)
 | 
			
		||||
  maroon = 0x800000,                   // rgb(128,0,0)
 | 
			
		||||
  medium_aquamarine = 0x66CDAA,        // rgb(102,205,170)
 | 
			
		||||
  medium_blue = 0x0000CD,              // rgb(0,0,205)
 | 
			
		||||
  medium_orchid = 0xBA55D3,            // rgb(186,85,211)
 | 
			
		||||
  medium_purple = 0x9370DB,            // rgb(147,112,219)
 | 
			
		||||
  medium_sea_green = 0x3CB371,         // rgb(60,179,113)
 | 
			
		||||
  medium_slate_blue = 0x7B68EE,        // rgb(123,104,238)
 | 
			
		||||
  medium_spring_green = 0x00FA9A,      // rgb(0,250,154)
 | 
			
		||||
  medium_turquoise = 0x48D1CC,         // rgb(72,209,204)
 | 
			
		||||
  medium_violet_red = 0xC71585,        // rgb(199,21,133)
 | 
			
		||||
  midnight_blue = 0x191970,            // rgb(25,25,112)
 | 
			
		||||
  mint_cream = 0xF5FFFA,               // rgb(245,255,250)
 | 
			
		||||
  misty_rose = 0xFFE4E1,               // rgb(255,228,225)
 | 
			
		||||
  moccasin = 0xFFE4B5,                 // rgb(255,228,181)
 | 
			
		||||
  navajo_white = 0xFFDEAD,             // rgb(255,222,173)
 | 
			
		||||
  navy = 0x000080,                     // rgb(0,0,128)
 | 
			
		||||
  old_lace = 0xFDF5E6,                 // rgb(253,245,230)
 | 
			
		||||
  olive = 0x808000,                    // rgb(128,128,0)
 | 
			
		||||
  olive_drab = 0x6B8E23,               // rgb(107,142,35)
 | 
			
		||||
  orange = 0xFFA500,                   // rgb(255,165,0)
 | 
			
		||||
  orange_red = 0xFF4500,               // rgb(255,69,0)
 | 
			
		||||
  orchid = 0xDA70D6,                   // rgb(218,112,214)
 | 
			
		||||
  pale_golden_rod = 0xEEE8AA,          // rgb(238,232,170)
 | 
			
		||||
  pale_green = 0x98FB98,               // rgb(152,251,152)
 | 
			
		||||
  pale_turquoise = 0xAFEEEE,           // rgb(175,238,238)
 | 
			
		||||
  pale_violet_red = 0xDB7093,          // rgb(219,112,147)
 | 
			
		||||
  papaya_whip = 0xFFEFD5,              // rgb(255,239,213)
 | 
			
		||||
  peach_puff = 0xFFDAB9,               // rgb(255,218,185)
 | 
			
		||||
  peru = 0xCD853F,                     // rgb(205,133,63)
 | 
			
		||||
  pink = 0xFFC0CB,                     // rgb(255,192,203)
 | 
			
		||||
  plum = 0xDDA0DD,                     // rgb(221,160,221)
 | 
			
		||||
  powder_blue = 0xB0E0E6,              // rgb(176,224,230)
 | 
			
		||||
  purple = 0x800080,                   // rgb(128,0,128)
 | 
			
		||||
  rebecca_purple = 0x663399,           // rgb(102,51,153)
 | 
			
		||||
  red = 0xFF0000,                      // rgb(255,0,0)
 | 
			
		||||
  rosy_brown = 0xBC8F8F,               // rgb(188,143,143)
 | 
			
		||||
  royal_blue = 0x4169E1,               // rgb(65,105,225)
 | 
			
		||||
  saddle_brown = 0x8B4513,             // rgb(139,69,19)
 | 
			
		||||
  salmon = 0xFA8072,                   // rgb(250,128,114)
 | 
			
		||||
  sandy_brown = 0xF4A460,              // rgb(244,164,96)
 | 
			
		||||
  sea_green = 0x2E8B57,                // rgb(46,139,87)
 | 
			
		||||
  sea_shell = 0xFFF5EE,                // rgb(255,245,238)
 | 
			
		||||
  sienna = 0xA0522D,                   // rgb(160,82,45)
 | 
			
		||||
  silver = 0xC0C0C0,                   // rgb(192,192,192)
 | 
			
		||||
  sky_blue = 0x87CEEB,                 // rgb(135,206,235)
 | 
			
		||||
  slate_blue = 0x6A5ACD,               // rgb(106,90,205)
 | 
			
		||||
  slate_gray = 0x708090,               // rgb(112,128,144)
 | 
			
		||||
  snow = 0xFFFAFA,                     // rgb(255,250,250)
 | 
			
		||||
  spring_green = 0x00FF7F,             // rgb(0,255,127)
 | 
			
		||||
  steel_blue = 0x4682B4,               // rgb(70,130,180)
 | 
			
		||||
  tan = 0xD2B48C,                      // rgb(210,180,140)
 | 
			
		||||
  teal = 0x008080,                     // rgb(0,128,128)
 | 
			
		||||
  thistle = 0xD8BFD8,                  // rgb(216,191,216)
 | 
			
		||||
  tomato = 0xFF6347,                   // rgb(255,99,71)
 | 
			
		||||
  turquoise = 0x40E0D0,                // rgb(64,224,208)
 | 
			
		||||
  violet = 0xEE82EE,                   // rgb(238,130,238)
 | 
			
		||||
  wheat = 0xF5DEB3,                    // rgb(245,222,179)
 | 
			
		||||
  white = 0xFFFFFF,                    // rgb(255,255,255)
 | 
			
		||||
  white_smoke = 0xF5F5F5,              // rgb(245,245,245)
 | 
			
		||||
  yellow = 0xFFFF00,                   // rgb(255,255,0)
 | 
			
		||||
  yellow_green = 0x9ACD32              // rgb(154,205,50)
 | 
			
		||||
};                                     // enum class color
 | 
			
		||||
 | 
			
		||||
enum class terminal_color : uint8_t {
 | 
			
		||||
  black = 30,
 | 
			
		||||
  red,
 | 
			
		||||
  green,
 | 
			
		||||
  yellow,
 | 
			
		||||
  blue,
 | 
			
		||||
  magenta,
 | 
			
		||||
  cyan,
 | 
			
		||||
  white,
 | 
			
		||||
  bright_black = 90,
 | 
			
		||||
  bright_red,
 | 
			
		||||
  bright_green,
 | 
			
		||||
  bright_yellow,
 | 
			
		||||
  bright_blue,
 | 
			
		||||
  bright_magenta,
 | 
			
		||||
  bright_cyan,
 | 
			
		||||
  bright_white
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class emphasis : uint8_t {
 | 
			
		||||
  bold = 1,
 | 
			
		||||
  faint = 1 << 1,
 | 
			
		||||
  italic = 1 << 2,
 | 
			
		||||
  underline = 1 << 3,
 | 
			
		||||
  blink = 1 << 4,
 | 
			
		||||
  reverse = 1 << 5,
 | 
			
		||||
  conceal = 1 << 6,
 | 
			
		||||
  strikethrough = 1 << 7,
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// rgb is a struct for red, green and blue colors.
 | 
			
		||||
// Using the name "rgb" makes some editors show the color in a tooltip.
 | 
			
		||||
struct rgb {
 | 
			
		||||
  FMT_CONSTEXPR rgb() : r(0), g(0), b(0) {}
 | 
			
		||||
  FMT_CONSTEXPR rgb(uint8_t r_, uint8_t g_, uint8_t b_) : r(r_), g(g_), b(b_) {}
 | 
			
		||||
  FMT_CONSTEXPR rgb(uint32_t hex)
 | 
			
		||||
      : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b(hex & 0xFF) {}
 | 
			
		||||
  FMT_CONSTEXPR rgb(color hex)
 | 
			
		||||
      : r((uint32_t(hex) >> 16) & 0xFF),
 | 
			
		||||
        g((uint32_t(hex) >> 8) & 0xFF),
 | 
			
		||||
        b(uint32_t(hex) & 0xFF) {}
 | 
			
		||||
  uint8_t r;
 | 
			
		||||
  uint8_t g;
 | 
			
		||||
  uint8_t b;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
// color is a struct of either a rgb color or a terminal color.
 | 
			
		||||
struct color_type {
 | 
			
		||||
  FMT_CONSTEXPR color_type() noexcept : is_rgb(), value{} {}
 | 
			
		||||
  FMT_CONSTEXPR color_type(color rgb_color) noexcept : is_rgb(true), value{} {
 | 
			
		||||
    value.rgb_color = static_cast<uint32_t>(rgb_color);
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR color_type(rgb rgb_color) noexcept : is_rgb(true), value{} {
 | 
			
		||||
    value.rgb_color = (static_cast<uint32_t>(rgb_color.r) << 16) |
 | 
			
		||||
                      (static_cast<uint32_t>(rgb_color.g) << 8) | rgb_color.b;
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR color_type(terminal_color term_color) noexcept
 | 
			
		||||
      : is_rgb(), value{} {
 | 
			
		||||
    value.term_color = static_cast<uint8_t>(term_color);
 | 
			
		||||
  }
 | 
			
		||||
  bool is_rgb;
 | 
			
		||||
  union color_union {
 | 
			
		||||
    uint8_t term_color;
 | 
			
		||||
    uint32_t rgb_color;
 | 
			
		||||
  } value;
 | 
			
		||||
};
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
/** A text style consisting of foreground and background colors and emphasis. */
 | 
			
		||||
class text_style {
 | 
			
		||||
 public:
 | 
			
		||||
  FMT_CONSTEXPR text_style(emphasis em = emphasis()) noexcept
 | 
			
		||||
      : set_foreground_color(), set_background_color(), ems(em) {}
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR auto operator|=(const text_style& rhs) -> text_style& {
 | 
			
		||||
    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 OR 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 OR 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 auto operator|(text_style lhs, const text_style& rhs)
 | 
			
		||||
      -> text_style {
 | 
			
		||||
    return lhs |= rhs;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR auto has_foreground() const noexcept -> bool {
 | 
			
		||||
    return set_foreground_color;
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR auto has_background() const noexcept -> bool {
 | 
			
		||||
    return set_background_color;
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR auto has_emphasis() const noexcept -> bool {
 | 
			
		||||
    return static_cast<uint8_t>(ems) != 0;
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR auto get_foreground() const noexcept -> detail::color_type {
 | 
			
		||||
    FMT_ASSERT(has_foreground(), "no foreground specified for this style");
 | 
			
		||||
    return foreground_color;
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR auto get_background() const noexcept -> detail::color_type {
 | 
			
		||||
    FMT_ASSERT(has_background(), "no background specified for this style");
 | 
			
		||||
    return background_color;
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR auto get_emphasis() const noexcept -> emphasis {
 | 
			
		||||
    FMT_ASSERT(has_emphasis(), "no emphasis specified for this style");
 | 
			
		||||
    return ems;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  FMT_CONSTEXPR text_style(bool is_foreground,
 | 
			
		||||
                           detail::color_type text_color) noexcept
 | 
			
		||||
      : set_foreground_color(), set_background_color(), ems() {
 | 
			
		||||
    if (is_foreground) {
 | 
			
		||||
      foreground_color = text_color;
 | 
			
		||||
      set_foreground_color = true;
 | 
			
		||||
    } else {
 | 
			
		||||
      background_color = text_color;
 | 
			
		||||
      set_background_color = true;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  friend FMT_CONSTEXPR auto fg(detail::color_type foreground) noexcept
 | 
			
		||||
      -> text_style;
 | 
			
		||||
 | 
			
		||||
  friend FMT_CONSTEXPR auto bg(detail::color_type background) noexcept
 | 
			
		||||
      -> text_style;
 | 
			
		||||
 | 
			
		||||
  detail::color_type foreground_color;
 | 
			
		||||
  detail::color_type background_color;
 | 
			
		||||
  bool set_foreground_color;
 | 
			
		||||
  bool set_background_color;
 | 
			
		||||
  emphasis ems;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/** Creates a text style from the foreground (text) color. */
 | 
			
		||||
FMT_CONSTEXPR inline auto fg(detail::color_type foreground) noexcept
 | 
			
		||||
    -> text_style {
 | 
			
		||||
  return text_style(true, foreground);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/** Creates a text style from the background color. */
 | 
			
		||||
FMT_CONSTEXPR inline auto bg(detail::color_type background) noexcept
 | 
			
		||||
    -> text_style {
 | 
			
		||||
  return text_style(false, background);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_CONSTEXPR inline auto operator|(emphasis lhs, emphasis rhs) noexcept
 | 
			
		||||
    -> text_style {
 | 
			
		||||
  return text_style(lhs) | rhs;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename Char> struct ansi_color_escape {
 | 
			
		||||
  FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color,
 | 
			
		||||
                                  const char* esc) noexcept {
 | 
			
		||||
    // If we have a terminal color, we need to output another escape code
 | 
			
		||||
    // sequence.
 | 
			
		||||
    if (!text_color.is_rgb) {
 | 
			
		||||
      bool is_background = esc == string_view("\x1b[48;2;");
 | 
			
		||||
      uint32_t value = text_color.value.term_color;
 | 
			
		||||
      // Background ASCII codes are the same as the foreground ones but with
 | 
			
		||||
      // 10 more.
 | 
			
		||||
      if (is_background) value += 10u;
 | 
			
		||||
 | 
			
		||||
      size_t index = 0;
 | 
			
		||||
      buffer[index++] = static_cast<Char>('\x1b');
 | 
			
		||||
      buffer[index++] = static_cast<Char>('[');
 | 
			
		||||
 | 
			
		||||
      if (value >= 100u) {
 | 
			
		||||
        buffer[index++] = static_cast<Char>('1');
 | 
			
		||||
        value %= 100u;
 | 
			
		||||
      }
 | 
			
		||||
      buffer[index++] = static_cast<Char>('0' + value / 10u);
 | 
			
		||||
      buffer[index++] = static_cast<Char>('0' + value % 10u);
 | 
			
		||||
 | 
			
		||||
      buffer[index++] = static_cast<Char>('m');
 | 
			
		||||
      buffer[index++] = static_cast<Char>('\0');
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (int i = 0; i < 7; i++) {
 | 
			
		||||
      buffer[i] = static_cast<Char>(esc[i]);
 | 
			
		||||
    }
 | 
			
		||||
    rgb color(text_color.value.rgb_color);
 | 
			
		||||
    to_esc(color.r, buffer + 7, ';');
 | 
			
		||||
    to_esc(color.g, buffer + 11, ';');
 | 
			
		||||
    to_esc(color.b, buffer + 15, 'm');
 | 
			
		||||
    buffer[19] = static_cast<Char>(0);
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR ansi_color_escape(emphasis em) noexcept {
 | 
			
		||||
    uint8_t em_codes[num_emphases] = {};
 | 
			
		||||
    if (has_emphasis(em, emphasis::bold)) em_codes[0] = 1;
 | 
			
		||||
    if (has_emphasis(em, emphasis::faint)) em_codes[1] = 2;
 | 
			
		||||
    if (has_emphasis(em, emphasis::italic)) em_codes[2] = 3;
 | 
			
		||||
    if (has_emphasis(em, emphasis::underline)) em_codes[3] = 4;
 | 
			
		||||
    if (has_emphasis(em, emphasis::blink)) em_codes[4] = 5;
 | 
			
		||||
    if (has_emphasis(em, emphasis::reverse)) em_codes[5] = 7;
 | 
			
		||||
    if (has_emphasis(em, emphasis::conceal)) em_codes[6] = 8;
 | 
			
		||||
    if (has_emphasis(em, emphasis::strikethrough)) em_codes[7] = 9;
 | 
			
		||||
 | 
			
		||||
    size_t index = 0;
 | 
			
		||||
    for (size_t i = 0; i < num_emphases; ++i) {
 | 
			
		||||
      if (!em_codes[i]) continue;
 | 
			
		||||
      buffer[index++] = static_cast<Char>('\x1b');
 | 
			
		||||
      buffer[index++] = static_cast<Char>('[');
 | 
			
		||||
      buffer[index++] = static_cast<Char>('0' + em_codes[i]);
 | 
			
		||||
      buffer[index++] = static_cast<Char>('m');
 | 
			
		||||
    }
 | 
			
		||||
    buffer[index++] = static_cast<Char>(0);
 | 
			
		||||
  }
 | 
			
		||||
  FMT_CONSTEXPR operator const Char*() const noexcept { return buffer; }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR auto begin() const noexcept -> const Char* { return buffer; }
 | 
			
		||||
  FMT_CONSTEXPR_CHAR_TRAITS auto end() const noexcept -> const Char* {
 | 
			
		||||
    return buffer + std::char_traits<Char>::length(buffer);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  static constexpr size_t num_emphases = 8;
 | 
			
		||||
  Char buffer[7u + 3u * num_emphases + 1u];
 | 
			
		||||
 | 
			
		||||
  static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out,
 | 
			
		||||
                                   char delimiter) noexcept {
 | 
			
		||||
    out[0] = static_cast<Char>('0' + c / 100);
 | 
			
		||||
    out[1] = static_cast<Char>('0' + c / 10 % 10);
 | 
			
		||||
    out[2] = static_cast<Char>('0' + c % 10);
 | 
			
		||||
    out[3] = static_cast<Char>(delimiter);
 | 
			
		||||
  }
 | 
			
		||||
  static FMT_CONSTEXPR auto has_emphasis(emphasis em, emphasis mask) noexcept
 | 
			
		||||
      -> bool {
 | 
			
		||||
    return static_cast<uint8_t>(em) & static_cast<uint8_t>(mask);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
FMT_CONSTEXPR auto make_foreground_color(detail::color_type foreground) noexcept
 | 
			
		||||
    -> ansi_color_escape<Char> {
 | 
			
		||||
  return ansi_color_escape<Char>(foreground, "\x1b[38;2;");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
FMT_CONSTEXPR auto make_background_color(detail::color_type background) noexcept
 | 
			
		||||
    -> ansi_color_escape<Char> {
 | 
			
		||||
  return ansi_color_escape<Char>(background, "\x1b[48;2;");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
FMT_CONSTEXPR auto make_emphasis(emphasis em) noexcept
 | 
			
		||||
    -> ansi_color_escape<Char> {
 | 
			
		||||
  return ansi_color_escape<Char>(em);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char> inline void reset_color(buffer<Char>& buffer) {
 | 
			
		||||
  auto reset_color = string_view("\x1b[0m");
 | 
			
		||||
  buffer.append(reset_color.begin(), reset_color.end());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> struct styled_arg : detail::view {
 | 
			
		||||
  const T& value;
 | 
			
		||||
  text_style style;
 | 
			
		||||
  styled_arg(const T& v, text_style s) : value(v), style(s) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
void vformat_to(buffer<Char>& buf, const text_style& ts,
 | 
			
		||||
                basic_string_view<Char> format_str,
 | 
			
		||||
                basic_format_args<buffer_context<type_identity_t<Char>>> args) {
 | 
			
		||||
  bool has_style = false;
 | 
			
		||||
  if (ts.has_emphasis()) {
 | 
			
		||||
    has_style = true;
 | 
			
		||||
    auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
 | 
			
		||||
    buf.append(emphasis.begin(), emphasis.end());
 | 
			
		||||
  }
 | 
			
		||||
  if (ts.has_foreground()) {
 | 
			
		||||
    has_style = true;
 | 
			
		||||
    auto foreground = detail::make_foreground_color<Char>(ts.get_foreground());
 | 
			
		||||
    buf.append(foreground.begin(), foreground.end());
 | 
			
		||||
  }
 | 
			
		||||
  if (ts.has_background()) {
 | 
			
		||||
    has_style = true;
 | 
			
		||||
    auto background = detail::make_background_color<Char>(ts.get_background());
 | 
			
		||||
    buf.append(background.begin(), background.end());
 | 
			
		||||
  }
 | 
			
		||||
  detail::vformat_to(buf, format_str, args, {});
 | 
			
		||||
  if (has_style) detail::reset_color<Char>(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
inline void vprint(std::FILE* f, const text_style& ts, string_view fmt,
 | 
			
		||||
                   format_args args) {
 | 
			
		||||
  // Legacy wide streams are not supported.
 | 
			
		||||
  auto buf = memory_buffer();
 | 
			
		||||
  detail::vformat_to(buf, ts, fmt, args);
 | 
			
		||||
  if (detail::is_utf8()) {
 | 
			
		||||
    detail::print(f, string_view(buf.begin(), buf.size()));
 | 
			
		||||
    return;
 | 
			
		||||
  }
 | 
			
		||||
  buf.push_back('\0');
 | 
			
		||||
  int result = std::fputs(buf.data(), f);
 | 
			
		||||
  if (result < 0)
 | 
			
		||||
    FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Formats a string and prints it to the specified file stream using ANSI
 | 
			
		||||
  escape sequences to specify text formatting.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
 | 
			
		||||
               "Elapsed time: {0:.2f} seconds", 1.23);
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_string<S>::value)>
 | 
			
		||||
void print(std::FILE* f, const text_style& ts, const S& format_str,
 | 
			
		||||
           const Args&... args) {
 | 
			
		||||
  vprint(f, ts, format_str,
 | 
			
		||||
         fmt::make_format_args<buffer_context<char_t<S>>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Formats a string and prints it to stdout using ANSI escape sequences to
 | 
			
		||||
  specify text formatting.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::print(fmt::emphasis::bold | fg(fmt::color::red),
 | 
			
		||||
               "Elapsed time: {0:.2f} seconds", 1.23);
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_string<S>::value)>
 | 
			
		||||
void print(const text_style& ts, const S& format_str, const Args&... args) {
 | 
			
		||||
  return print(stdout, ts, format_str, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename S, typename Char = char_t<S>>
 | 
			
		||||
inline auto vformat(
 | 
			
		||||
    const text_style& ts, const S& format_str,
 | 
			
		||||
    basic_format_args<buffer_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> std::basic_string<Char> {
 | 
			
		||||
  basic_memory_buffer<Char> buf;
 | 
			
		||||
  detail::vformat_to(buf, ts, detail::to_string_view(format_str), args);
 | 
			
		||||
  return fmt::to_string(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Formats arguments and returns the result as a string using ANSI
 | 
			
		||||
  escape sequences to specify text formatting.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    #include <fmt/color.h>
 | 
			
		||||
    std::string message = fmt::format(fmt::emphasis::bold | fg(fmt::color::red),
 | 
			
		||||
                                      "The answer is {}", 42);
 | 
			
		||||
  \endrst
 | 
			
		||||
*/
 | 
			
		||||
template <typename S, typename... Args, typename Char = char_t<S>>
 | 
			
		||||
inline auto format(const text_style& ts, const S& format_str,
 | 
			
		||||
                   const Args&... args) -> std::basic_string<Char> {
 | 
			
		||||
  return fmt::vformat(ts, detail::to_string_view(format_str),
 | 
			
		||||
                      fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Formats a string with the given text_style and writes the output to ``out``.
 | 
			
		||||
 */
 | 
			
		||||
template <typename OutputIt, typename Char,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)>
 | 
			
		||||
auto vformat_to(OutputIt out, const text_style& ts,
 | 
			
		||||
                basic_string_view<Char> format_str,
 | 
			
		||||
                basic_format_args<buffer_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> OutputIt {
 | 
			
		||||
  auto&& buf = detail::get_buffer<Char>(out);
 | 
			
		||||
  detail::vformat_to(buf, ts, format_str, args);
 | 
			
		||||
  return detail::get_iterator(buf, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Formats arguments with the given text_style, writes the result to the output
 | 
			
		||||
  iterator ``out`` and returns the iterator past the end of the output range.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    std::vector<char> out;
 | 
			
		||||
    fmt::format_to(std::back_inserter(out),
 | 
			
		||||
                   fmt::emphasis::bold | fg(fmt::color::red), "{}", 42);
 | 
			
		||||
  \endrst
 | 
			
		||||
*/
 | 
			
		||||
template <
 | 
			
		||||
    typename OutputIt, typename S, typename... Args,
 | 
			
		||||
    bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value &&
 | 
			
		||||
                  detail::is_string<S>::value>
 | 
			
		||||
inline auto format_to(OutputIt out, const text_style& ts, const S& format_str,
 | 
			
		||||
                      Args&&... args) ->
 | 
			
		||||
    typename std::enable_if<enable, OutputIt>::type {
 | 
			
		||||
  return vformat_to(out, ts, detail::to_string_view(format_str),
 | 
			
		||||
                    fmt::make_format_args<buffer_context<char_t<S>>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct formatter<detail::styled_arg<T>, Char> : formatter<T, Char> {
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const detail::styled_arg<T>& arg, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    const auto& ts = arg.style;
 | 
			
		||||
    const auto& value = arg.value;
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
 | 
			
		||||
    bool has_style = false;
 | 
			
		||||
    if (ts.has_emphasis()) {
 | 
			
		||||
      has_style = true;
 | 
			
		||||
      auto emphasis = detail::make_emphasis<Char>(ts.get_emphasis());
 | 
			
		||||
      out = std::copy(emphasis.begin(), emphasis.end(), out);
 | 
			
		||||
    }
 | 
			
		||||
    if (ts.has_foreground()) {
 | 
			
		||||
      has_style = true;
 | 
			
		||||
      auto foreground =
 | 
			
		||||
          detail::make_foreground_color<Char>(ts.get_foreground());
 | 
			
		||||
      out = std::copy(foreground.begin(), foreground.end(), out);
 | 
			
		||||
    }
 | 
			
		||||
    if (ts.has_background()) {
 | 
			
		||||
      has_style = true;
 | 
			
		||||
      auto background =
 | 
			
		||||
          detail::make_background_color<Char>(ts.get_background());
 | 
			
		||||
      out = std::copy(background.begin(), background.end(), out);
 | 
			
		||||
    }
 | 
			
		||||
    out = formatter<T, Char>::format(value, ctx);
 | 
			
		||||
    if (has_style) {
 | 
			
		||||
      auto reset_color = string_view("\x1b[0m");
 | 
			
		||||
      out = std::copy(reset_color.begin(), reset_color.end(), out);
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Returns an argument that will be formatted using ANSI escape sequences,
 | 
			
		||||
  to be used in a formatting function.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::print("Elapsed time: {0:.2f} seconds",
 | 
			
		||||
               fmt::styled(1.23, fmt::fg(fmt::color::green) |
 | 
			
		||||
                                 fmt::bg(fmt::color::blue)));
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
FMT_CONSTEXPR auto styled(const T& value, text_style ts)
 | 
			
		||||
    -> detail::styled_arg<remove_cvref_t<T>> {
 | 
			
		||||
  return detail::styled_arg<remove_cvref_t<T>>{value, ts};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_END_EXPORT
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_COLOR_H_
 | 
			
		||||
							
								
								
									
										535
									
								
								3rd/fmt/compile.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										535
									
								
								3rd/fmt/compile.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,535 @@
 | 
			
		||||
// Formatting library for C++ - experimental format string compilation
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - present, Victor Zverovich and fmt contributors
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_COMPILE_H_
 | 
			
		||||
#define FMT_COMPILE_H_
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename InputIt>
 | 
			
		||||
FMT_CONSTEXPR inline auto copy_str(InputIt begin, InputIt end,
 | 
			
		||||
                                   counting_iterator it) -> counting_iterator {
 | 
			
		||||
  return it + (end - begin);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// A compile-time string which is compiled into fast formatting code.
 | 
			
		||||
class compiled_string {};
 | 
			
		||||
 | 
			
		||||
template <typename S>
 | 
			
		||||
struct is_compiled_string : std::is_base_of<compiled_string, S> {};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Converts a string literal *s* into a format string that will be parsed at
 | 
			
		||||
  compile time and converted into efficient formatting code. Requires C++17
 | 
			
		||||
  ``constexpr if`` compiler support.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    // Converts 42 into std::string using the most efficient method and no
 | 
			
		||||
    // runtime format string processing.
 | 
			
		||||
    std::string s = fmt::format(FMT_COMPILE("{}"), 42);
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
 | 
			
		||||
#  define FMT_COMPILE(s) \
 | 
			
		||||
    FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit)
 | 
			
		||||
#else
 | 
			
		||||
#  define FMT_COMPILE(s) FMT_STRING(s)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
 | 
			
		||||
template <typename Char, size_t N,
 | 
			
		||||
          fmt::detail_exported::fixed_string<Char, N> Str>
 | 
			
		||||
struct udl_compiled_string : compiled_string {
 | 
			
		||||
  using char_type = Char;
 | 
			
		||||
  explicit constexpr operator basic_string_view<char_type>() const {
 | 
			
		||||
    return {Str.data, N - 1};
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename T, typename... Tail>
 | 
			
		||||
auto first(const T& value, const Tail&...) -> const T& {
 | 
			
		||||
  return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
 | 
			
		||||
template <typename... Args> struct type_list {};
 | 
			
		||||
 | 
			
		||||
// Returns a reference to the argument at index N from [first, rest...].
 | 
			
		||||
template <int N, typename T, typename... Args>
 | 
			
		||||
constexpr const auto& get([[maybe_unused]] const T& first,
 | 
			
		||||
                          [[maybe_unused]] const Args&... rest) {
 | 
			
		||||
  static_assert(N < 1 + sizeof...(Args), "index is out of bounds");
 | 
			
		||||
  if constexpr (N == 0)
 | 
			
		||||
    return first;
 | 
			
		||||
  else
 | 
			
		||||
    return detail::get<N - 1>(rest...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename... Args>
 | 
			
		||||
constexpr int get_arg_index_by_name(basic_string_view<Char> name,
 | 
			
		||||
                                    type_list<Args...>) {
 | 
			
		||||
  return get_arg_index_by_name<Args...>(name);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <int N, typename> struct get_type_impl;
 | 
			
		||||
 | 
			
		||||
template <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> {
 | 
			
		||||
  using type =
 | 
			
		||||
      remove_cvref_t<decltype(detail::get<N>(std::declval<Args>()...))>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <int N, typename T>
 | 
			
		||||
using get_type = typename get_type_impl<N, T>::type;
 | 
			
		||||
 | 
			
		||||
template <typename T> struct is_compiled_format : std::false_type {};
 | 
			
		||||
 | 
			
		||||
template <typename Char> struct text {
 | 
			
		||||
  basic_string_view<Char> data;
 | 
			
		||||
  using char_type = Char;
 | 
			
		||||
 | 
			
		||||
  template <typename OutputIt, typename... Args>
 | 
			
		||||
  constexpr OutputIt format(OutputIt out, const Args&...) const {
 | 
			
		||||
    return write<Char>(out, data);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
struct is_compiled_format<text<Char>> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
constexpr text<Char> make_text(basic_string_view<Char> s, size_t pos,
 | 
			
		||||
                               size_t size) {
 | 
			
		||||
  return {{&s[pos], size}};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char> struct code_unit {
 | 
			
		||||
  Char value;
 | 
			
		||||
  using char_type = Char;
 | 
			
		||||
 | 
			
		||||
  template <typename OutputIt, typename... Args>
 | 
			
		||||
  constexpr OutputIt format(OutputIt out, const Args&...) const {
 | 
			
		||||
    *out++ = value;
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// This ensures that the argument type is convertible to `const T&`.
 | 
			
		||||
template <typename T, int N, typename... Args>
 | 
			
		||||
constexpr const T& get_arg_checked(const Args&... args) {
 | 
			
		||||
  const auto& arg = detail::get<N>(args...);
 | 
			
		||||
  if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) {
 | 
			
		||||
    return arg.value;
 | 
			
		||||
  } else {
 | 
			
		||||
    return arg;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
struct is_compiled_format<code_unit<Char>> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
// A replacement field that refers to argument N.
 | 
			
		||||
template <typename Char, typename T, int N> struct field {
 | 
			
		||||
  using char_type = Char;
 | 
			
		||||
 | 
			
		||||
  template <typename OutputIt, typename... Args>
 | 
			
		||||
  constexpr OutputIt format(OutputIt out, const Args&... args) const {
 | 
			
		||||
    const T& arg = get_arg_checked<T, N>(args...);
 | 
			
		||||
    if constexpr (std::is_convertible_v<T, basic_string_view<Char>>) {
 | 
			
		||||
      auto s = basic_string_view<Char>(arg);
 | 
			
		||||
      return copy_str<Char>(s.begin(), s.end(), out);
 | 
			
		||||
    }
 | 
			
		||||
    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) {
 | 
			
		||||
      FMT_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;
 | 
			
		||||
  formatter<T, Char> fmt;
 | 
			
		||||
 | 
			
		||||
  template <typename OutputIt, typename... Args>
 | 
			
		||||
  constexpr FMT_INLINE OutputIt format(OutputIt out,
 | 
			
		||||
                                       const Args&... args) const {
 | 
			
		||||
    const auto& vargs =
 | 
			
		||||
        fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...);
 | 
			
		||||
    basic_format_context<OutputIt, Char> ctx(out, vargs);
 | 
			
		||||
    return fmt.format(get_arg_checked<T, N>(args...), ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename T, int N>
 | 
			
		||||
struct is_compiled_format<spec_field<Char, T, N>> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename L, typename R> struct concat {
 | 
			
		||||
  L lhs;
 | 
			
		||||
  R rhs;
 | 
			
		||||
  using char_type = typename L::char_type;
 | 
			
		||||
 | 
			
		||||
  template <typename OutputIt, typename... Args>
 | 
			
		||||
  constexpr OutputIt format(OutputIt out, const Args&... args) const {
 | 
			
		||||
    out = lhs.format(out, args...);
 | 
			
		||||
    return rhs.format(out, args...);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename L, typename R>
 | 
			
		||||
struct is_compiled_format<concat<L, R>> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename L, typename R>
 | 
			
		||||
constexpr concat<L, R> make_concat(L lhs, R rhs) {
 | 
			
		||||
  return {lhs, rhs};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
struct unknown_format {};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
constexpr size_t parse_text(basic_string_view<Char> str, size_t pos) {
 | 
			
		||||
  for (size_t size = str.size(); pos != size; ++pos) {
 | 
			
		||||
    if (str[pos] == '{' || str[pos] == '}') break;
 | 
			
		||||
  }
 | 
			
		||||
  return pos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Args, size_t POS, int ID, typename S>
 | 
			
		||||
constexpr auto compile_format_string(S format_str);
 | 
			
		||||
 | 
			
		||||
template <typename Args, size_t POS, int ID, typename T, typename S>
 | 
			
		||||
constexpr auto parse_tail(T head, S format_str) {
 | 
			
		||||
  if constexpr (POS !=
 | 
			
		||||
                basic_string_view<typename S::char_type>(format_str).size()) {
 | 
			
		||||
    constexpr auto tail = compile_format_string<Args, POS, ID>(format_str);
 | 
			
		||||
    if constexpr (std::is_same<remove_cvref_t<decltype(tail)>,
 | 
			
		||||
                               unknown_format>())
 | 
			
		||||
      return tail;
 | 
			
		||||
    else
 | 
			
		||||
      return make_concat(head, tail);
 | 
			
		||||
  } else {
 | 
			
		||||
    return head;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char> struct parse_specs_result {
 | 
			
		||||
  formatter<T, Char> fmt;
 | 
			
		||||
  size_t end;
 | 
			
		||||
  int next_arg_id;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum { 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 next_arg_id) {
 | 
			
		||||
  str.remove_prefix(pos);
 | 
			
		||||
  auto ctx =
 | 
			
		||||
      compile_parse_context<Char>(str, max_value<int>(), nullptr, next_arg_id);
 | 
			
		||||
  auto f = formatter<T, Char>();
 | 
			
		||||
  auto end = f.parse(ctx);
 | 
			
		||||
  return {f, pos + fmt::detail::to_unsigned(end - str.data()),
 | 
			
		||||
          next_arg_id == 0 ? manual_indexing_id : ctx.next_arg_id()};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char> struct arg_id_handler {
 | 
			
		||||
  arg_ref<Char> arg_id;
 | 
			
		||||
 | 
			
		||||
  constexpr int on_auto() {
 | 
			
		||||
    FMT_ASSERT(false, "handler cannot be used with automatic indexing");
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  constexpr int on_index(int id) {
 | 
			
		||||
    arg_id = arg_ref<Char>(id);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
  constexpr int on_name(basic_string_view<Char> id) {
 | 
			
		||||
    arg_id = arg_ref<Char>(id);
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
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 arg_id_end = parse_arg_id(begin, end, handler);
 | 
			
		||||
  return parse_arg_id_result<Char>{handler.arg_id, arg_id_end};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Enable = void> struct field_type {
 | 
			
		||||
  using type = remove_cvref_t<T>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> {
 | 
			
		||||
  using type = remove_cvref_t<decltype(T::value)>;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID,
 | 
			
		||||
          typename S>
 | 
			
		||||
constexpr auto parse_replacement_field_then_tail(S format_str) {
 | 
			
		||||
  using char_type = typename S::char_type;
 | 
			
		||||
  constexpr auto str = basic_string_view<char_type>(format_str);
 | 
			
		||||
  constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type();
 | 
			
		||||
  if constexpr (c == '}') {
 | 
			
		||||
    return parse_tail<Args, END_POS + 1, NEXT_ID>(
 | 
			
		||||
        field<char_type, typename field_type<T>::type, ARG_INDEX>(),
 | 
			
		||||
        format_str);
 | 
			
		||||
  } else if constexpr (c != ':') {
 | 
			
		||||
    FMT_THROW(format_error("expected ':'"));
 | 
			
		||||
  } else {
 | 
			
		||||
    constexpr auto result = parse_specs<typename field_type<T>::type>(
 | 
			
		||||
        str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID);
 | 
			
		||||
    if constexpr (result.end >= str.size() || str[result.end] != '}') {
 | 
			
		||||
      FMT_THROW(format_error("expected '}'"));
 | 
			
		||||
      return 0;
 | 
			
		||||
    } else {
 | 
			
		||||
      return parse_tail<Args, result.end + 1, result.next_arg_id>(
 | 
			
		||||
          spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{
 | 
			
		||||
              result.fmt},
 | 
			
		||||
          format_str);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Compiles a non-empty format string and returns the compiled representation
 | 
			
		||||
// or unknown_format() on unrecognized input.
 | 
			
		||||
template <typename Args, size_t POS, int ID, typename S>
 | 
			
		||||
constexpr auto compile_format_string(S format_str) {
 | 
			
		||||
  using char_type = typename S::char_type;
 | 
			
		||||
  constexpr auto str = basic_string_view<char_type>(format_str);
 | 
			
		||||
  if constexpr (str[POS] == '{') {
 | 
			
		||||
    if constexpr (POS + 1 == str.size())
 | 
			
		||||
      FMT_THROW(format_error("unmatched '{' in format string"));
 | 
			
		||||
    if constexpr (str[POS + 1] == '{') {
 | 
			
		||||
      return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), 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");
 | 
			
		||||
      constexpr auto next_id =
 | 
			
		||||
          ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
 | 
			
		||||
      return parse_replacement_field_then_tail<get_type<ID, Args>, Args,
 | 
			
		||||
                                               POS + 1, ID, next_id>(
 | 
			
		||||
          format_str);
 | 
			
		||||
    } else {
 | 
			
		||||
      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;
 | 
			
		||||
        return parse_replacement_field_then_tail<get_type<arg_index, Args>,
 | 
			
		||||
                                                 Args, arg_id_end_pos,
 | 
			
		||||
                                                 arg_index, manual_indexing_id>(
 | 
			
		||||
            format_str);
 | 
			
		||||
      } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) {
 | 
			
		||||
        constexpr auto arg_index =
 | 
			
		||||
            get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{});
 | 
			
		||||
        if constexpr (arg_index >= 0) {
 | 
			
		||||
          constexpr auto next_id =
 | 
			
		||||
              ID != manual_indexing_id ? ID + 1 : manual_indexing_id;
 | 
			
		||||
          return parse_replacement_field_then_tail<
 | 
			
		||||
              decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos,
 | 
			
		||||
              arg_index, next_id>(format_str);
 | 
			
		||||
        } else 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 constexpr (POS + 1 == str.size())
 | 
			
		||||
      FMT_THROW(format_error("unmatched '}' in format string"));
 | 
			
		||||
    return parse_tail<Args, POS + 2, ID>(make_text(str, POS, 1), format_str);
 | 
			
		||||
  } else {
 | 
			
		||||
    constexpr auto end = parse_text(str, POS + 1);
 | 
			
		||||
    if constexpr (end - POS > 1) {
 | 
			
		||||
      return parse_tail<Args, end, ID>(make_text(str, POS, end - POS),
 | 
			
		||||
                                       format_str);
 | 
			
		||||
    } else {
 | 
			
		||||
      return parse_tail<Args, end, ID>(code_unit<char_type>{str[POS]},
 | 
			
		||||
                                       format_str);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... Args, typename S,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
constexpr auto compile(S format_str) {
 | 
			
		||||
  constexpr auto str = basic_string_view<typename S::char_type>(format_str);
 | 
			
		||||
  if constexpr (str.size() == 0) {
 | 
			
		||||
    return detail::make_text(str, 0, 0);
 | 
			
		||||
  } else {
 | 
			
		||||
    constexpr auto result =
 | 
			
		||||
        detail::compile_format_string<detail::type_list<Args...>, 0, 0>(
 | 
			
		||||
            format_str);
 | 
			
		||||
    return result;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif  // defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_EXPORT
 | 
			
		||||
 | 
			
		||||
#if defined(__cpp_if_constexpr) && defined(__cpp_return_type_deduction)
 | 
			
		||||
 | 
			
		||||
template <typename CompiledFormat, typename... Args,
 | 
			
		||||
          typename Char = typename CompiledFormat::char_type,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
 | 
			
		||||
FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf,
 | 
			
		||||
                                          const Args&... args) {
 | 
			
		||||
  auto s = std::basic_string<Char>();
 | 
			
		||||
  cf.format(std::back_inserter(s), args...);
 | 
			
		||||
  return s;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename CompiledFormat, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)>
 | 
			
		||||
constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf,
 | 
			
		||||
                                        const Args&... args) {
 | 
			
		||||
  return cf.format(out, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
FMT_INLINE std::basic_string<typename S::char_type> format(const S&,
 | 
			
		||||
                                                           Args&&... args) {
 | 
			
		||||
  if constexpr (std::is_same<typename S::char_type, char>::value) {
 | 
			
		||||
    constexpr auto str = basic_string_view<typename S::char_type>(S());
 | 
			
		||||
    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);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  constexpr auto compiled = detail::compile<Args...>(S());
 | 
			
		||||
  if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
 | 
			
		||||
                             detail::unknown_format>()) {
 | 
			
		||||
    return fmt::format(
 | 
			
		||||
        static_cast<basic_string_view<typename S::char_type>>(S()),
 | 
			
		||||
        std::forward<Args>(args)...);
 | 
			
		||||
  } else {
 | 
			
		||||
    return fmt::format(compiled, std::forward<Args>(args)...);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) {
 | 
			
		||||
  constexpr auto compiled = detail::compile<Args...>(S());
 | 
			
		||||
  if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>,
 | 
			
		||||
                             detail::unknown_format>()) {
 | 
			
		||||
    return fmt::format_to(
 | 
			
		||||
        out, static_cast<basic_string_view<typename S::char_type>>(S()),
 | 
			
		||||
        std::forward<Args>(args)...);
 | 
			
		||||
  } else {
 | 
			
		||||
    return fmt::format_to(out, compiled, std::forward<Args>(args)...);
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
auto format_to_n(OutputIt out, size_t n, const S& format_str, Args&&... args)
 | 
			
		||||
    -> format_to_n_result<OutputIt> {
 | 
			
		||||
  using traits = detail::fixed_buffer_traits;
 | 
			
		||||
  auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
 | 
			
		||||
  fmt::format_to(std::back_inserter(buf), format_str,
 | 
			
		||||
                 std::forward<Args>(args)...);
 | 
			
		||||
  return {buf.out(), buf.count()};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
FMT_CONSTEXPR20 auto formatted_size(const S& format_str, const Args&... args)
 | 
			
		||||
    -> size_t {
 | 
			
		||||
  return fmt::format_to(detail::counting_iterator(), format_str, args...)
 | 
			
		||||
      .count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
void print(std::FILE* f, const S& format_str, const Args&... args) {
 | 
			
		||||
  memory_buffer buffer;
 | 
			
		||||
  fmt::format_to(std::back_inserter(buffer), format_str, args...);
 | 
			
		||||
  detail::print(f, {buffer.data(), buffer.size()});
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename S, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_compiled_string<S>::value)>
 | 
			
		||||
void print(const S& format_str, const Args&... args) {
 | 
			
		||||
  print(stdout, format_str, args...);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_NONTYPE_TEMPLATE_ARGS
 | 
			
		||||
inline namespace literals {
 | 
			
		||||
template <detail_exported::fixed_string Str> constexpr auto operator""_cf() {
 | 
			
		||||
  using char_t = remove_cvref_t<decltype(Str.data[0])>;
 | 
			
		||||
  return detail::udl_compiled_string<char_t, sizeof(Str.data) / sizeof(char_t),
 | 
			
		||||
                                     Str>();
 | 
			
		||||
}
 | 
			
		||||
}  // namespace literals
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
FMT_END_EXPORT
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_COMPILE_H_
 | 
			
		||||
							
								
								
									
										2969
									
								
								3rd/fmt/core.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										2969
									
								
								3rd/fmt/core.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1678
									
								
								3rd/fmt/format-inl.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1678
									
								
								3rd/fmt/format-inl.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										4535
									
								
								3rd/fmt/format.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4535
									
								
								3rd/fmt/format.h
									
									
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										455
									
								
								3rd/fmt/os.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										455
									
								
								3rd/fmt/os.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,455 @@
 | 
			
		||||
// Formatting library for C++ - optional OS-specific functionality
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - present, Victor Zverovich
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_OS_H_
 | 
			
		||||
#define FMT_OS_H_
 | 
			
		||||
 | 
			
		||||
#include <cerrno>
 | 
			
		||||
#include <cstddef>
 | 
			
		||||
#include <cstdio>
 | 
			
		||||
#include <system_error>  // std::system_error
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
#if defined __APPLE__ || defined(__FreeBSD__)
 | 
			
		||||
#  if FMT_HAS_INCLUDE(<xlocale.h>)
 | 
			
		||||
#    include <xlocale.h>  // for LC_NUMERIC_MASK on OS X
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_USE_FCNTL
 | 
			
		||||
// UWP doesn't provide _pipe.
 | 
			
		||||
#  if FMT_HAS_INCLUDE("winapifamily.h")
 | 
			
		||||
#    include <winapifamily.h>
 | 
			
		||||
#  endif
 | 
			
		||||
#  if (FMT_HAS_INCLUDE(<fcntl.h>) || defined(__APPLE__) || \
 | 
			
		||||
       defined(__linux__)) &&                              \
 | 
			
		||||
      (!defined(WINAPI_FAMILY) ||                          \
 | 
			
		||||
       (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP))
 | 
			
		||||
#    include <fcntl.h>  // for O_RDONLY
 | 
			
		||||
#    define FMT_USE_FCNTL 1
 | 
			
		||||
#  else
 | 
			
		||||
#    define FMT_USE_FCNTL 0
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_POSIX
 | 
			
		||||
#  if defined(_WIN32) && !defined(__MINGW32__)
 | 
			
		||||
// Fix warnings about deprecated symbols.
 | 
			
		||||
#    define FMT_POSIX(call) _##call
 | 
			
		||||
#  else
 | 
			
		||||
#    define FMT_POSIX(call) call
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Calls to system functions are wrapped in FMT_SYSTEM for testability.
 | 
			
		||||
#ifdef FMT_SYSTEM
 | 
			
		||||
#  define FMT_HAS_SYSTEM
 | 
			
		||||
#  define FMT_POSIX_CALL(call) FMT_SYSTEM(call)
 | 
			
		||||
#else
 | 
			
		||||
#  define FMT_SYSTEM(call) ::call
 | 
			
		||||
#  ifdef _WIN32
 | 
			
		||||
// Fix warnings about deprecated symbols.
 | 
			
		||||
#    define FMT_POSIX_CALL(call) ::_##call
 | 
			
		||||
#  else
 | 
			
		||||
#    define FMT_POSIX_CALL(call) ::call
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Retries the expression while it evaluates to error_result and errno
 | 
			
		||||
// equals to EINTR.
 | 
			
		||||
#ifndef _WIN32
 | 
			
		||||
#  define FMT_RETRY_VAL(result, expression, error_result) \
 | 
			
		||||
    do {                                                  \
 | 
			
		||||
      (result) = (expression);                            \
 | 
			
		||||
    } while ((result) == (error_result) && errno == EINTR)
 | 
			
		||||
#else
 | 
			
		||||
#  define FMT_RETRY_VAL(result, expression, error_result) result = (expression)
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1)
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_BEGIN_EXPORT
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  A reference to a null-terminated string. It can be constructed from a C
 | 
			
		||||
  string or ``std::string``.
 | 
			
		||||
 | 
			
		||||
  You can use one of the following type aliases for common character types:
 | 
			
		||||
 | 
			
		||||
  +---------------+-----------------------------+
 | 
			
		||||
  | Type          | Definition                  |
 | 
			
		||||
  +===============+=============================+
 | 
			
		||||
  | cstring_view  | basic_cstring_view<char>    |
 | 
			
		||||
  +---------------+-----------------------------+
 | 
			
		||||
  | wcstring_view | basic_cstring_view<wchar_t> |
 | 
			
		||||
  +---------------+-----------------------------+
 | 
			
		||||
 | 
			
		||||
  This class is most useful as a parameter type to allow passing
 | 
			
		||||
  different types of strings to a function, for example::
 | 
			
		||||
 | 
			
		||||
    template <typename... Args>
 | 
			
		||||
    std::string format(cstring_view format_str, const Args & ... args);
 | 
			
		||||
 | 
			
		||||
    format("{}", 42);
 | 
			
		||||
    format(std::string("{}"), 42);
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename Char> class basic_cstring_view {
 | 
			
		||||
 private:
 | 
			
		||||
  const Char* data_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  /** Constructs a string reference object from a C string. */
 | 
			
		||||
  basic_cstring_view(const Char* s) : data_(s) {}
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    \rst
 | 
			
		||||
    Constructs a string reference from an ``std::string`` object.
 | 
			
		||||
    \endrst
 | 
			
		||||
   */
 | 
			
		||||
  basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {}
 | 
			
		||||
 | 
			
		||||
  /** Returns the pointer to a C string. */
 | 
			
		||||
  auto c_str() const -> const Char* { return data_; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using cstring_view = basic_cstring_view<char>;
 | 
			
		||||
using wcstring_view = basic_cstring_view<wchar_t>;
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
FMT_API const std::error_category& system_category() noexcept;
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
FMT_API void format_windows_error(buffer<char>& out, int error_code,
 | 
			
		||||
                                  const char* message) noexcept;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_API std::system_error vwindows_error(int error_code, string_view format_str,
 | 
			
		||||
                                         format_args args);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 \rst
 | 
			
		||||
 Constructs a :class:`std::system_error` object with the description
 | 
			
		||||
 of the form
 | 
			
		||||
 | 
			
		||||
 .. parsed-literal::
 | 
			
		||||
   *<message>*: *<system-message>*
 | 
			
		||||
 | 
			
		||||
 where *<message>* is the formatted message and *<system-message>* is the
 | 
			
		||||
 system message corresponding to the error code.
 | 
			
		||||
 *error_code* is a Windows error code as given by ``GetLastError``.
 | 
			
		||||
 If *error_code* is not a valid error code such as -1, the system message
 | 
			
		||||
 will look like "error -1".
 | 
			
		||||
 | 
			
		||||
 **Example**::
 | 
			
		||||
 | 
			
		||||
   // This throws a system_error with the description
 | 
			
		||||
   //   cannot open file 'madeup': The system cannot find the file specified.
 | 
			
		||||
   // or similar (system message may vary).
 | 
			
		||||
   const char *filename = "madeup";
 | 
			
		||||
   LPOFSTRUCT of = LPOFSTRUCT();
 | 
			
		||||
   HFILE file = OpenFile(filename, &of, OF_READ);
 | 
			
		||||
   if (file == HFILE_ERROR) {
 | 
			
		||||
     throw fmt::windows_error(GetLastError(),
 | 
			
		||||
                              "cannot open file '{}'", filename);
 | 
			
		||||
   }
 | 
			
		||||
 \endrst
 | 
			
		||||
*/
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
std::system_error windows_error(int error_code, string_view message,
 | 
			
		||||
                                const Args&... args) {
 | 
			
		||||
  return vwindows_error(error_code, message, fmt::make_format_args(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Reports a Windows error without throwing an exception.
 | 
			
		||||
// Can be used to report errors from destructors.
 | 
			
		||||
FMT_API void report_windows_error(int error_code, const char* message) noexcept;
 | 
			
		||||
#else
 | 
			
		||||
inline auto system_category() noexcept -> const std::error_category& {
 | 
			
		||||
  return std::system_category();
 | 
			
		||||
}
 | 
			
		||||
#endif  // _WIN32
 | 
			
		||||
 | 
			
		||||
// std::system is not available on some platforms such as iOS (#2248).
 | 
			
		||||
#ifdef __OSX__
 | 
			
		||||
template <typename S, typename... Args, typename Char = char_t<S>>
 | 
			
		||||
void say(const S& format_str, Args&&... args) {
 | 
			
		||||
  std::system(format("say \"{}\"", format(format_str, args...)).c_str());
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// A buffered file.
 | 
			
		||||
class buffered_file {
 | 
			
		||||
 private:
 | 
			
		||||
  FILE* file_;
 | 
			
		||||
 | 
			
		||||
  friend class file;
 | 
			
		||||
 | 
			
		||||
  explicit buffered_file(FILE* f) : file_(f) {}
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  buffered_file(const buffered_file&) = delete;
 | 
			
		||||
  void operator=(const buffered_file&) = delete;
 | 
			
		||||
 | 
			
		||||
  // Constructs a buffered_file object which doesn't represent any file.
 | 
			
		||||
  buffered_file() noexcept : file_(nullptr) {}
 | 
			
		||||
 | 
			
		||||
  // Destroys the object closing the file it represents if any.
 | 
			
		||||
  FMT_API ~buffered_file() noexcept;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  buffered_file(buffered_file&& other) noexcept : file_(other.file_) {
 | 
			
		||||
    other.file_ = nullptr;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto operator=(buffered_file&& other) -> buffered_file& {
 | 
			
		||||
    close();
 | 
			
		||||
    file_ = other.file_;
 | 
			
		||||
    other.file_ = nullptr;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Opens a file.
 | 
			
		||||
  FMT_API buffered_file(cstring_view filename, cstring_view mode);
 | 
			
		||||
 | 
			
		||||
  // Closes the file.
 | 
			
		||||
  FMT_API void close();
 | 
			
		||||
 | 
			
		||||
  // Returns the pointer to a FILE object representing this file.
 | 
			
		||||
  auto get() const noexcept -> FILE* { return file_; }
 | 
			
		||||
 | 
			
		||||
  FMT_API auto descriptor() const -> int;
 | 
			
		||||
 | 
			
		||||
  void vprint(string_view format_str, format_args args) {
 | 
			
		||||
    fmt::vprint(file_, format_str, args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename... Args>
 | 
			
		||||
  inline void print(string_view format_str, const Args&... args) {
 | 
			
		||||
    vprint(format_str, fmt::make_format_args(args...));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_FCNTL
 | 
			
		||||
// A file. Closed file is represented by a file object with descriptor -1.
 | 
			
		||||
// Methods that are not declared with noexcept may throw
 | 
			
		||||
// fmt::system_error in case of failure. Note that some errors such as
 | 
			
		||||
// closing the file multiple times will cause a crash on Windows rather
 | 
			
		||||
// than an exception. You can get standard behavior by overriding the
 | 
			
		||||
// invalid parameter handler with _set_invalid_parameter_handler.
 | 
			
		||||
class FMT_API file {
 | 
			
		||||
 private:
 | 
			
		||||
  int fd_;  // File descriptor.
 | 
			
		||||
 | 
			
		||||
  // Constructs a file object with a given descriptor.
 | 
			
		||||
  explicit file(int fd) : fd_(fd) {}
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  // Possible values for the oflag argument to the constructor.
 | 
			
		||||
  enum {
 | 
			
		||||
    RDONLY = FMT_POSIX(O_RDONLY),  // Open for reading only.
 | 
			
		||||
    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.
 | 
			
		||||
    TRUNC = FMT_POSIX(O_TRUNC)     // Truncate the content of the file.
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  // Constructs a file object which doesn't represent any file.
 | 
			
		||||
  file() noexcept : fd_(-1) {}
 | 
			
		||||
 | 
			
		||||
  // Opens a file and constructs a file object representing this file.
 | 
			
		||||
  file(cstring_view path, int oflag);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  file(const file&) = delete;
 | 
			
		||||
  void operator=(const file&) = delete;
 | 
			
		||||
 | 
			
		||||
  file(file&& other) noexcept : fd_(other.fd_) { other.fd_ = -1; }
 | 
			
		||||
 | 
			
		||||
  // Move assignment is not noexcept because close may throw.
 | 
			
		||||
  auto operator=(file&& other) -> file& {
 | 
			
		||||
    close();
 | 
			
		||||
    fd_ = other.fd_;
 | 
			
		||||
    other.fd_ = -1;
 | 
			
		||||
    return *this;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // Destroys the object closing the file it represents if any.
 | 
			
		||||
  ~file() noexcept;
 | 
			
		||||
 | 
			
		||||
  // Returns the file descriptor.
 | 
			
		||||
  auto descriptor() const noexcept -> int { return fd_; }
 | 
			
		||||
 | 
			
		||||
  // Closes the file.
 | 
			
		||||
  void close();
 | 
			
		||||
 | 
			
		||||
  // Returns the file size. The size has signed type for consistency with
 | 
			
		||||
  // stat::st_size.
 | 
			
		||||
  auto size() const -> long long;
 | 
			
		||||
 | 
			
		||||
  // Attempts to read count bytes from the file into the specified buffer.
 | 
			
		||||
  auto read(void* buffer, size_t count) -> size_t;
 | 
			
		||||
 | 
			
		||||
  // Attempts to write count bytes from the specified buffer to the file.
 | 
			
		||||
  auto write(const void* buffer, size_t count) -> size_t;
 | 
			
		||||
 | 
			
		||||
  // Duplicates a file descriptor with the dup function and returns
 | 
			
		||||
  // the duplicate as a file object.
 | 
			
		||||
  static auto dup(int fd) -> file;
 | 
			
		||||
 | 
			
		||||
  // Makes fd be the copy of this file descriptor, closing fd first if
 | 
			
		||||
  // necessary.
 | 
			
		||||
  void dup2(int fd);
 | 
			
		||||
 | 
			
		||||
  // Makes fd be the copy of this file descriptor, closing fd first if
 | 
			
		||||
  // necessary.
 | 
			
		||||
  void dup2(int fd, std::error_code& ec) noexcept;
 | 
			
		||||
 | 
			
		||||
  // Creates a pipe setting up read_end and write_end file objects for reading
 | 
			
		||||
  // and writing respectively.
 | 
			
		||||
  // DEPRECATED! Taking files as out parameters is deprecated.
 | 
			
		||||
  static void pipe(file& read_end, file& write_end);
 | 
			
		||||
 | 
			
		||||
  // Creates a buffered_file object associated with this file and detaches
 | 
			
		||||
  // this file object from the file.
 | 
			
		||||
  auto fdopen(const char* mode) -> buffered_file;
 | 
			
		||||
 | 
			
		||||
#  if defined(_WIN32) && !defined(__MINGW32__)
 | 
			
		||||
  // Opens a file and constructs a file object representing this file by
 | 
			
		||||
  // wcstring_view filename. Windows only.
 | 
			
		||||
  static file open_windows_file(wcstring_view path, int oflag);
 | 
			
		||||
#  endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Returns the memory page size.
 | 
			
		||||
auto getpagesize() -> long;
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
struct buffer_size {
 | 
			
		||||
  buffer_size() = default;
 | 
			
		||||
  size_t value = 0;
 | 
			
		||||
  auto operator=(size_t val) const -> buffer_size {
 | 
			
		||||
    auto bs = buffer_size();
 | 
			
		||||
    bs.value = val;
 | 
			
		||||
    return bs;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct ostream_params {
 | 
			
		||||
  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 new_oflag) : ostream_params(params...) {
 | 
			
		||||
    oflag = new_oflag;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename... T>
 | 
			
		||||
  ostream_params(T... params, detail::buffer_size bs)
 | 
			
		||||
      : ostream_params(params...) {
 | 
			
		||||
    this->buffer_size = bs.value;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
// Intel has a bug that results in failure to deduce a constructor
 | 
			
		||||
// for empty parameter packs.
 | 
			
		||||
#  if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 2000
 | 
			
		||||
  ostream_params(int new_oflag) : oflag(new_oflag) {}
 | 
			
		||||
  ostream_params(detail::buffer_size bs) : buffer_size(bs.value) {}
 | 
			
		||||
#  endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class file_buffer final : public buffer<char> {
 | 
			
		||||
  file file_;
 | 
			
		||||
 | 
			
		||||
  FMT_API void grow(size_t) override;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  FMT_API file_buffer(cstring_view path, const ostream_params& params);
 | 
			
		||||
  FMT_API file_buffer(file_buffer&& other);
 | 
			
		||||
  FMT_API ~file_buffer();
 | 
			
		||||
 | 
			
		||||
  void flush() {
 | 
			
		||||
    if (size() == 0) return;
 | 
			
		||||
    file_.write(data(), size() * sizeof(data()[0]));
 | 
			
		||||
    clear();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void close() {
 | 
			
		||||
    flush();
 | 
			
		||||
    file_.close();
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
// Added {} below to work around default constructor error known to
 | 
			
		||||
// occur in Xcode versions 7.2.1 and 8.2.1.
 | 
			
		||||
constexpr detail::buffer_size buffer_size{};
 | 
			
		||||
 | 
			
		||||
/** A fast output stream which is not thread-safe. */
 | 
			
		||||
class FMT_API ostream {
 | 
			
		||||
 private:
 | 
			
		||||
  FMT_MSC_WARNING(suppress : 4251)
 | 
			
		||||
  detail::file_buffer buffer_;
 | 
			
		||||
 | 
			
		||||
  ostream(cstring_view path, const detail::ostream_params& params)
 | 
			
		||||
      : buffer_(path, params) {}
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  ostream(ostream&& other) : buffer_(std::move(other.buffer_)) {}
 | 
			
		||||
 | 
			
		||||
  ~ostream();
 | 
			
		||||
 | 
			
		||||
  void flush() { buffer_.flush(); }
 | 
			
		||||
 | 
			
		||||
  template <typename... T>
 | 
			
		||||
  friend auto output_file(cstring_view path, T... params) -> ostream;
 | 
			
		||||
 | 
			
		||||
  void close() { buffer_.close(); }
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    Formats ``args`` according to specifications in ``fmt`` and writes the
 | 
			
		||||
    output to the file.
 | 
			
		||||
   */
 | 
			
		||||
  template <typename... T> void print(format_string<T...> fmt, T&&... args) {
 | 
			
		||||
    vformat_to(std::back_inserter(buffer_), fmt,
 | 
			
		||||
               fmt::make_format_args(args...));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \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 | file::TRUNC`` 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 auto output_file(cstring_view path, T... params) -> ostream {
 | 
			
		||||
  return {path, detail::ostream_params(params...)};
 | 
			
		||||
}
 | 
			
		||||
#endif  // FMT_USE_FCNTL
 | 
			
		||||
 | 
			
		||||
FMT_END_EXPORT
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_OS_H_
 | 
			
		||||
							
								
								
									
										245
									
								
								3rd/fmt/ostream.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										245
									
								
								3rd/fmt/ostream.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,245 @@
 | 
			
		||||
// Formatting library for C++ - std::ostream support
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - present, Victor Zverovich
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_OSTREAM_H_
 | 
			
		||||
#define FMT_OSTREAM_H_
 | 
			
		||||
 | 
			
		||||
#include <fstream>  // std::filebuf
 | 
			
		||||
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
#  ifdef __GLIBCXX__
 | 
			
		||||
#    include <ext/stdio_filebuf.h>
 | 
			
		||||
#    include <ext/stdio_sync_filebuf.h>
 | 
			
		||||
#  endif
 | 
			
		||||
#  include <io.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename Streambuf> class formatbuf : public Streambuf {
 | 
			
		||||
 private:
 | 
			
		||||
  using char_type = typename Streambuf::char_type;
 | 
			
		||||
  using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));
 | 
			
		||||
  using int_type = typename Streambuf::int_type;
 | 
			
		||||
  using traits_type = typename Streambuf::traits_type;
 | 
			
		||||
 | 
			
		||||
  buffer<char_type>& buffer_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}
 | 
			
		||||
 | 
			
		||||
 protected:
 | 
			
		||||
  // The put area is always empty. This makes the implementation simpler and has
 | 
			
		||||
  // the advantage that the streambuf and the buffer are always in sync and
 | 
			
		||||
  // sputc never writes into uninitialized memory. A disadvantage is that each
 | 
			
		||||
  // call to sputc always results in a (virtual) call to overflow. There is no
 | 
			
		||||
  // disadvantage here for sputn since this always results in a call to xsputn.
 | 
			
		||||
 | 
			
		||||
  auto overflow(int_type ch) -> int_type override {
 | 
			
		||||
    if (!traits_type::eq_int_type(ch, traits_type::eof()))
 | 
			
		||||
      buffer_.push_back(static_cast<char_type>(ch));
 | 
			
		||||
    return ch;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  auto xsputn(const char_type* s, streamsize count) -> streamsize override {
 | 
			
		||||
    buffer_.append(s, s + count);
 | 
			
		||||
    return count;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Generate a unique explicit instantion in every translation unit using a tag
 | 
			
		||||
// type in an anonymous namespace.
 | 
			
		||||
namespace {
 | 
			
		||||
struct file_access_tag {};
 | 
			
		||||
}  // namespace
 | 
			
		||||
template <typename Tag, typename BufType, FILE* BufType::*FileMemberPtr>
 | 
			
		||||
class file_access {
 | 
			
		||||
  friend auto get_file(BufType& obj) -> FILE* { return obj.*FileMemberPtr; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#if FMT_MSC_VERSION
 | 
			
		||||
template class file_access<file_access_tag, std::filebuf,
 | 
			
		||||
                           &std::filebuf::_Myfile>;
 | 
			
		||||
auto get_file(std::filebuf&) -> FILE*;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
inline auto write_ostream_unicode(std::ostream& os, fmt::string_view data)
 | 
			
		||||
    -> bool {
 | 
			
		||||
  FILE* f = nullptr;
 | 
			
		||||
#if FMT_MSC_VERSION
 | 
			
		||||
  if (auto* buf = dynamic_cast<std::filebuf*>(os.rdbuf()))
 | 
			
		||||
    f = get_file(*buf);
 | 
			
		||||
  else
 | 
			
		||||
    return false;
 | 
			
		||||
#elif defined(_WIN32) && defined(__GLIBCXX__)
 | 
			
		||||
  auto* rdbuf = os.rdbuf();
 | 
			
		||||
  if (auto* sfbuf = dynamic_cast<__gnu_cxx::stdio_sync_filebuf<char>*>(rdbuf))
 | 
			
		||||
    f = sfbuf->file();
 | 
			
		||||
  else if (auto* fbuf = dynamic_cast<__gnu_cxx::stdio_filebuf<char>*>(rdbuf))
 | 
			
		||||
    f = fbuf->file();
 | 
			
		||||
  else
 | 
			
		||||
    return false;
 | 
			
		||||
#else
 | 
			
		||||
  ignore_unused(os, data, f);
 | 
			
		||||
#endif
 | 
			
		||||
#ifdef _WIN32
 | 
			
		||||
  if (f) {
 | 
			
		||||
    int fd = _fileno(f);
 | 
			
		||||
    if (_isatty(fd)) {
 | 
			
		||||
      os.flush();
 | 
			
		||||
      return write_console(fd, data);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
#endif
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
inline auto write_ostream_unicode(std::wostream&,
 | 
			
		||||
                                  fmt::basic_string_view<wchar_t>) -> bool {
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Write the content of buf to os.
 | 
			
		||||
// It is a separate function rather than a part of vprint to simplify testing.
 | 
			
		||||
template <typename Char>
 | 
			
		||||
void write_buffer(std::basic_ostream<Char>& os, buffer<Char>& buf) {
 | 
			
		||||
  const Char* buf_data = buf.data();
 | 
			
		||||
  using unsigned_streamsize = std::make_unsigned<std::streamsize>::type;
 | 
			
		||||
  unsigned_streamsize size = buf.size();
 | 
			
		||||
  unsigned_streamsize max_size = to_unsigned(max_value<std::streamsize>());
 | 
			
		||||
  do {
 | 
			
		||||
    unsigned_streamsize n = size <= max_size ? size : max_size;
 | 
			
		||||
    os.write(buf_data, static_cast<std::streamsize>(n));
 | 
			
		||||
    buf_data += n;
 | 
			
		||||
    size -= n;
 | 
			
		||||
  } while (size != 0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename T>
 | 
			
		||||
void format_value(buffer<Char>& buf, const T& value) {
 | 
			
		||||
  auto&& format_buf = formatbuf<std::basic_streambuf<Char>>(buf);
 | 
			
		||||
  auto&& output = std::basic_ostream<Char>(&format_buf);
 | 
			
		||||
#if !defined(FMT_STATIC_THOUSANDS_SEPARATOR)
 | 
			
		||||
  output.imbue(std::locale::classic());  // The default is always unlocalized.
 | 
			
		||||
#endif
 | 
			
		||||
  output << value;
 | 
			
		||||
  output.exceptions(std::ios_base::failbit | std::ios_base::badbit);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T> struct streamed_view {
 | 
			
		||||
  const T& value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
// Formats an object of type T that has an overloaded ostream operator<<.
 | 
			
		||||
template <typename Char>
 | 
			
		||||
struct basic_ostream_formatter : formatter<basic_string_view<Char>, Char> {
 | 
			
		||||
  void set_debug_format() = delete;
 | 
			
		||||
 | 
			
		||||
  template <typename T, typename OutputIt>
 | 
			
		||||
  auto format(const T& value, basic_format_context<OutputIt, Char>& ctx) const
 | 
			
		||||
      -> OutputIt {
 | 
			
		||||
    auto buffer = basic_memory_buffer<Char>();
 | 
			
		||||
    detail::format_value(buffer, value);
 | 
			
		||||
    return formatter<basic_string_view<Char>, Char>::format(
 | 
			
		||||
        {buffer.data(), buffer.size()}, ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
using ostream_formatter = basic_ostream_formatter<char>;
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct formatter<detail::streamed_view<T>, Char>
 | 
			
		||||
    : basic_ostream_formatter<Char> {
 | 
			
		||||
  template <typename OutputIt>
 | 
			
		||||
  auto format(detail::streamed_view<T> view,
 | 
			
		||||
              basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
 | 
			
		||||
    return basic_ostream_formatter<Char>::format(view.value, ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Returns a view that formats `value` via an ostream ``operator<<``.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::print("Current thread id: {}\n",
 | 
			
		||||
               fmt::streamed(std::this_thread::get_id()));
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
constexpr auto streamed(const T& value) -> detail::streamed_view<T> {
 | 
			
		||||
  return {value};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
inline void vprint_directly(std::ostream& os, string_view format_str,
 | 
			
		||||
                            format_args args) {
 | 
			
		||||
  auto buffer = memory_buffer();
 | 
			
		||||
  detail::vformat_to(buffer, format_str, args);
 | 
			
		||||
  detail::write_buffer(os, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT template <typename Char>
 | 
			
		||||
void vprint(std::basic_ostream<Char>& os,
 | 
			
		||||
            basic_string_view<type_identity_t<Char>> format_str,
 | 
			
		||||
            basic_format_args<buffer_context<type_identity_t<Char>>> args) {
 | 
			
		||||
  auto buffer = basic_memory_buffer<Char>();
 | 
			
		||||
  detail::vformat_to(buffer, format_str, args);
 | 
			
		||||
  if (detail::write_ostream_unicode(os, {buffer.data(), buffer.size()})) return;
 | 
			
		||||
  detail::write_buffer(os, buffer);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to the stream *os*.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::print(cerr, "Don't {}!", "panic");
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
FMT_EXPORT template <typename... T>
 | 
			
		||||
void print(std::ostream& os, format_string<T...> fmt, T&&... args) {
 | 
			
		||||
  const auto& vargs = fmt::make_format_args(args...);
 | 
			
		||||
  if (detail::is_utf8())
 | 
			
		||||
    vprint(os, fmt, vargs);
 | 
			
		||||
  else
 | 
			
		||||
    detail::vprint_directly(os, fmt, vargs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
void print(std::wostream& os,
 | 
			
		||||
           basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
 | 
			
		||||
           Args&&... args) {
 | 
			
		||||
  vprint(os, fmt, fmt::make_format_args<buffer_context<wchar_t>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT template <typename... T>
 | 
			
		||||
void println(std::ostream& os, format_string<T...> fmt, T&&... args) {
 | 
			
		||||
  fmt::print(os, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
void println(std::wostream& os,
 | 
			
		||||
             basic_format_string<wchar_t, type_identity_t<Args>...> fmt,
 | 
			
		||||
             Args&&... args) {
 | 
			
		||||
  print(os, L"{}\n", fmt::format(fmt, std::forward<Args>(args)...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_OSTREAM_H_
 | 
			
		||||
							
								
								
									
										675
									
								
								3rd/fmt/printf.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										675
									
								
								3rd/fmt/printf.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,675 @@
 | 
			
		||||
// Formatting library for C++ - legacy printf implementation
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - 2016, Victor Zverovich
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_PRINTF_H_
 | 
			
		||||
#define FMT_PRINTF_H_
 | 
			
		||||
 | 
			
		||||
#include <algorithm>  // std::max
 | 
			
		||||
#include <limits>     // std::numeric_limits
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_BEGIN_EXPORT
 | 
			
		||||
 | 
			
		||||
template <typename T> struct printf_formatter {
 | 
			
		||||
  printf_formatter() = delete;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char> class basic_printf_context {
 | 
			
		||||
 private:
 | 
			
		||||
  detail::buffer_appender<Char> out_;
 | 
			
		||||
  basic_format_args<basic_printf_context> args_;
 | 
			
		||||
 | 
			
		||||
  static_assert(std::is_same<Char, char>::value ||
 | 
			
		||||
                    std::is_same<Char, wchar_t>::value,
 | 
			
		||||
                "Unsupported code unit type.");
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  using char_type = Char;
 | 
			
		||||
  using parse_context_type = basic_format_parse_context<Char>;
 | 
			
		||||
  template <typename T> using formatter_type = printf_formatter<T>;
 | 
			
		||||
 | 
			
		||||
  /**
 | 
			
		||||
    \rst
 | 
			
		||||
    Constructs a ``printf_context`` object. References to the arguments are
 | 
			
		||||
    stored in the context object so make sure they have appropriate lifetimes.
 | 
			
		||||
    \endrst
 | 
			
		||||
   */
 | 
			
		||||
  basic_printf_context(detail::buffer_appender<Char> out,
 | 
			
		||||
                       basic_format_args<basic_printf_context> args)
 | 
			
		||||
      : out_(out), args_(args) {}
 | 
			
		||||
 | 
			
		||||
  auto out() -> detail::buffer_appender<Char> { return out_; }
 | 
			
		||||
  void advance_to(detail::buffer_appender<Char>) {}
 | 
			
		||||
 | 
			
		||||
  auto locale() -> detail::locale_ref { return {}; }
 | 
			
		||||
 | 
			
		||||
  auto arg(int id) const -> basic_format_arg<basic_printf_context> {
 | 
			
		||||
    return args_.get(id);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void on_error(const char* message) {
 | 
			
		||||
    detail::error_handler().on_error(message);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
// Checks if a value fits in int - used to avoid warnings about comparing
 | 
			
		||||
// signed and unsigned integers.
 | 
			
		||||
template <bool IsSigned> struct int_checker {
 | 
			
		||||
  template <typename T> static auto fits_in_int(T value) -> bool {
 | 
			
		||||
    unsigned max = max_value<int>();
 | 
			
		||||
    return value <= max;
 | 
			
		||||
  }
 | 
			
		||||
  static auto fits_in_int(bool) -> bool { return true; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <> struct int_checker<true> {
 | 
			
		||||
  template <typename T> static auto fits_in_int(T value) -> bool {
 | 
			
		||||
    return value >= (std::numeric_limits<int>::min)() &&
 | 
			
		||||
           value <= max_value<int>();
 | 
			
		||||
  }
 | 
			
		||||
  static auto fits_in_int(int) -> bool { return true; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
struct printf_precision_handler {
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
 | 
			
		||||
  auto operator()(T value) -> int {
 | 
			
		||||
    if (!int_checker<std::numeric_limits<T>::is_signed>::fits_in_int(value))
 | 
			
		||||
      throw_format_error("number is too big");
 | 
			
		||||
    return (std::max)(static_cast<int>(value), 0);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
 | 
			
		||||
  auto operator()(T) -> int {
 | 
			
		||||
    throw_format_error("precision is not integer");
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// An argument visitor that returns true iff arg is a zero integer.
 | 
			
		||||
struct is_zero_int {
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
 | 
			
		||||
  auto operator()(T value) -> bool {
 | 
			
		||||
    return value == 0;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
 | 
			
		||||
  auto operator()(T) -> bool {
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T> struct make_unsigned_or_bool : std::make_unsigned<T> {};
 | 
			
		||||
 | 
			
		||||
template <> struct make_unsigned_or_bool<bool> {
 | 
			
		||||
  using type = bool;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Context> class arg_converter {
 | 
			
		||||
 private:
 | 
			
		||||
  using char_type = typename Context::char_type;
 | 
			
		||||
 | 
			
		||||
  basic_format_arg<Context>& arg_;
 | 
			
		||||
  char_type type_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  arg_converter(basic_format_arg<Context>& arg, char_type type)
 | 
			
		||||
      : arg_(arg), type_(type) {}
 | 
			
		||||
 | 
			
		||||
  void operator()(bool value) {
 | 
			
		||||
    if (type_ != 's') operator()<bool>(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename U, FMT_ENABLE_IF(std::is_integral<U>::value)>
 | 
			
		||||
  void operator()(U value) {
 | 
			
		||||
    bool is_signed = type_ == 'd' || type_ == 'i';
 | 
			
		||||
    using target_type = conditional_t<std::is_same<T, void>::value, U, T>;
 | 
			
		||||
    if (const_check(sizeof(target_type) <= sizeof(int))) {
 | 
			
		||||
      // Extra casts are used to silence warnings.
 | 
			
		||||
      if (is_signed) {
 | 
			
		||||
        auto n = static_cast<int>(static_cast<target_type>(value));
 | 
			
		||||
        arg_ = detail::make_arg<Context>(n);
 | 
			
		||||
      } else {
 | 
			
		||||
        using unsigned_type = typename make_unsigned_or_bool<target_type>::type;
 | 
			
		||||
        auto n = static_cast<unsigned>(static_cast<unsigned_type>(value));
 | 
			
		||||
        arg_ = detail::make_arg<Context>(n);
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      if (is_signed) {
 | 
			
		||||
        // glibc's printf doesn't sign extend arguments of smaller types:
 | 
			
		||||
        //   std::printf("%lld", -42);  // prints "4294967254"
 | 
			
		||||
        // but we don't have to do the same because it's a UB.
 | 
			
		||||
        auto n = static_cast<long long>(value);
 | 
			
		||||
        arg_ = detail::make_arg<Context>(n);
 | 
			
		||||
      } else {
 | 
			
		||||
        auto n = static_cast<typename make_unsigned_or_bool<U>::type>(value);
 | 
			
		||||
        arg_ = detail::make_arg<Context>(n);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename U, FMT_ENABLE_IF(!std::is_integral<U>::value)>
 | 
			
		||||
  void operator()(U) {}  // No conversion needed for non-integral types.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Converts an integer argument to T for printf, if T is an integral type.
 | 
			
		||||
// If T is void, the argument is converted to corresponding signed or unsigned
 | 
			
		||||
// type depending on the type specifier: 'd' and 'i' - signed, other -
 | 
			
		||||
// unsigned).
 | 
			
		||||
template <typename T, typename Context, typename Char>
 | 
			
		||||
void convert_arg(basic_format_arg<Context>& arg, Char type) {
 | 
			
		||||
  visit_format_arg(arg_converter<T, Context>(arg, type), arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Converts an integer argument to char for printf.
 | 
			
		||||
template <typename Context> class char_converter {
 | 
			
		||||
 private:
 | 
			
		||||
  basic_format_arg<Context>& arg_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit char_converter(basic_format_arg<Context>& arg) : arg_(arg) {}
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
 | 
			
		||||
  void operator()(T value) {
 | 
			
		||||
    auto c = static_cast<typename Context::char_type>(value);
 | 
			
		||||
    arg_ = detail::make_arg<Context>(c);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
 | 
			
		||||
  void operator()(T) {}  // No conversion needed for non-integral types.
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// An argument visitor that return a pointer to a C string if argument is a
 | 
			
		||||
// string or null otherwise.
 | 
			
		||||
template <typename Char> struct get_cstring {
 | 
			
		||||
  template <typename T> auto operator()(T) -> const Char* { return nullptr; }
 | 
			
		||||
  auto operator()(const Char* s) -> const Char* { return s; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Checks if an argument is a valid printf width specifier and sets
 | 
			
		||||
// left alignment if it is negative.
 | 
			
		||||
template <typename Char> class printf_width_handler {
 | 
			
		||||
 private:
 | 
			
		||||
  format_specs<Char>& specs_;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  explicit printf_width_handler(format_specs<Char>& specs) : specs_(specs) {}
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
 | 
			
		||||
  auto operator()(T value) -> unsigned {
 | 
			
		||||
    auto width = static_cast<uint32_or_64_or_128_t<T>>(value);
 | 
			
		||||
    if (detail::is_negative(value)) {
 | 
			
		||||
      specs_.align = align::left;
 | 
			
		||||
      width = 0 - width;
 | 
			
		||||
    }
 | 
			
		||||
    unsigned int_max = max_value<int>();
 | 
			
		||||
    if (width > int_max) throw_format_error("number is too big");
 | 
			
		||||
    return static_cast<unsigned>(width);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
 | 
			
		||||
  auto operator()(T) -> unsigned {
 | 
			
		||||
    throw_format_error("width is not integer");
 | 
			
		||||
    return 0;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Workaround for a bug with the XL compiler when initializing
 | 
			
		||||
// printf_arg_formatter's base class.
 | 
			
		||||
template <typename Char>
 | 
			
		||||
auto make_arg_formatter(buffer_appender<Char> iter, format_specs<Char>& s)
 | 
			
		||||
    -> arg_formatter<Char> {
 | 
			
		||||
  return {iter, s, locale_ref()};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// The ``printf`` argument formatter.
 | 
			
		||||
template <typename Char>
 | 
			
		||||
class printf_arg_formatter : public arg_formatter<Char> {
 | 
			
		||||
 private:
 | 
			
		||||
  using base = arg_formatter<Char>;
 | 
			
		||||
  using context_type = basic_printf_context<Char>;
 | 
			
		||||
 | 
			
		||||
  context_type& context_;
 | 
			
		||||
 | 
			
		||||
  void write_null_pointer(bool is_string = false) {
 | 
			
		||||
    auto s = this->specs;
 | 
			
		||||
    s.type = presentation_type::none;
 | 
			
		||||
    write_bytes(this->out, is_string ? "(null)" : "(nil)", s);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  printf_arg_formatter(buffer_appender<Char> iter, format_specs<Char>& s,
 | 
			
		||||
                       context_type& ctx)
 | 
			
		||||
      : base(make_arg_formatter(iter, s)), context_(ctx) {}
 | 
			
		||||
 | 
			
		||||
  void operator()(monostate value) { base::operator()(value); }
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)>
 | 
			
		||||
  void 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) {
 | 
			
		||||
      base::operator()(value);
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
    format_specs<Char> fmt_specs = this->specs;
 | 
			
		||||
    if (fmt_specs.type != presentation_type::none &&
 | 
			
		||||
        fmt_specs.type != presentation_type::chr) {
 | 
			
		||||
      return (*this)(static_cast<int>(value));
 | 
			
		||||
    }
 | 
			
		||||
    fmt_specs.sign = sign::none;
 | 
			
		||||
    fmt_specs.alt = false;
 | 
			
		||||
    fmt_specs.fill[0] = ' ';  // Ignore '0' flag for char types.
 | 
			
		||||
    // align::numeric needs to be overwritten here since the '0' flag is
 | 
			
		||||
    // ignored for non-numeric types
 | 
			
		||||
    if (fmt_specs.align == align::none || fmt_specs.align == align::numeric)
 | 
			
		||||
      fmt_specs.align = align::right;
 | 
			
		||||
    write<Char>(this->out, static_cast<Char>(value), fmt_specs);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
 | 
			
		||||
  void operator()(T value) {
 | 
			
		||||
    base::operator()(value);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats a null-terminated C string. */
 | 
			
		||||
  void operator()(const char* value) {
 | 
			
		||||
    if (value)
 | 
			
		||||
      base::operator()(value);
 | 
			
		||||
    else
 | 
			
		||||
      write_null_pointer(this->specs.type != presentation_type::pointer);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats a null-terminated wide C string. */
 | 
			
		||||
  void operator()(const wchar_t* value) {
 | 
			
		||||
    if (value)
 | 
			
		||||
      base::operator()(value);
 | 
			
		||||
    else
 | 
			
		||||
      write_null_pointer(this->specs.type != presentation_type::pointer);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void operator()(basic_string_view<Char> value) { base::operator()(value); }
 | 
			
		||||
 | 
			
		||||
  /** Formats a pointer. */
 | 
			
		||||
  void operator()(const void* value) {
 | 
			
		||||
    if (value)
 | 
			
		||||
      base::operator()(value);
 | 
			
		||||
    else
 | 
			
		||||
      write_null_pointer();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Formats an argument of a custom (user-defined) type. */
 | 
			
		||||
  void operator()(typename basic_format_arg<context_type>::handle handle) {
 | 
			
		||||
    auto parse_ctx = basic_format_parse_context<Char>({});
 | 
			
		||||
    handle.format(parse_ctx, context_);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
void parse_flags(format_specs<Char>& specs, const Char*& it, const Char* end) {
 | 
			
		||||
  for (; it != end; ++it) {
 | 
			
		||||
    switch (*it) {
 | 
			
		||||
    case '-':
 | 
			
		||||
      specs.align = align::left;
 | 
			
		||||
      break;
 | 
			
		||||
    case '+':
 | 
			
		||||
      specs.sign = sign::plus;
 | 
			
		||||
      break;
 | 
			
		||||
    case '0':
 | 
			
		||||
      specs.fill[0] = '0';
 | 
			
		||||
      break;
 | 
			
		||||
    case ' ':
 | 
			
		||||
      if (specs.sign != sign::plus) specs.sign = sign::space;
 | 
			
		||||
      break;
 | 
			
		||||
    case '#':
 | 
			
		||||
      specs.alt = true;
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      return;
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename GetArg>
 | 
			
		||||
auto parse_header(const Char*& it, const Char* end, format_specs<Char>& specs,
 | 
			
		||||
                  GetArg get_arg) -> int {
 | 
			
		||||
  int arg_index = -1;
 | 
			
		||||
  Char c = *it;
 | 
			
		||||
  if (c >= '0' && c <= '9') {
 | 
			
		||||
    // Parse an argument index (if followed by '$') or a width possibly
 | 
			
		||||
    // preceded with '0' flag(s).
 | 
			
		||||
    int value = parse_nonnegative_int(it, end, -1);
 | 
			
		||||
    if (it != end && *it == '$') {  // value is an argument index
 | 
			
		||||
      ++it;
 | 
			
		||||
      arg_index = value != -1 ? value : max_value<int>();
 | 
			
		||||
    } else {
 | 
			
		||||
      if (c == '0') specs.fill[0] = '0';
 | 
			
		||||
      if (value != 0) {
 | 
			
		||||
        // Nonzero value means that we parsed width and don't need to
 | 
			
		||||
        // parse it or flags again, so return now.
 | 
			
		||||
        if (value == -1) throw_format_error("number is too big");
 | 
			
		||||
        specs.width = value;
 | 
			
		||||
        return arg_index;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  parse_flags(specs, it, end);
 | 
			
		||||
  // Parse width.
 | 
			
		||||
  if (it != end) {
 | 
			
		||||
    if (*it >= '0' && *it <= '9') {
 | 
			
		||||
      specs.width = parse_nonnegative_int(it, end, -1);
 | 
			
		||||
      if (specs.width == -1) throw_format_error("number is too big");
 | 
			
		||||
    } else if (*it == '*') {
 | 
			
		||||
      ++it;
 | 
			
		||||
      specs.width = static_cast<int>(visit_format_arg(
 | 
			
		||||
          detail::printf_width_handler<Char>(specs), get_arg(-1)));
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  return arg_index;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline auto parse_printf_presentation_type(char c, type t)
 | 
			
		||||
    -> presentation_type {
 | 
			
		||||
  using pt = presentation_type;
 | 
			
		||||
  constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
 | 
			
		||||
  switch (c) {
 | 
			
		||||
  case 'd':
 | 
			
		||||
    return in(t, integral_set) ? pt::dec : pt::none;
 | 
			
		||||
  case 'o':
 | 
			
		||||
    return in(t, integral_set) ? pt::oct : pt::none;
 | 
			
		||||
  case 'x':
 | 
			
		||||
    return in(t, integral_set) ? pt::hex_lower : pt::none;
 | 
			
		||||
  case 'X':
 | 
			
		||||
    return in(t, integral_set) ? pt::hex_upper : pt::none;
 | 
			
		||||
  case 'a':
 | 
			
		||||
    return in(t, float_set) ? pt::hexfloat_lower : pt::none;
 | 
			
		||||
  case 'A':
 | 
			
		||||
    return in(t, float_set) ? pt::hexfloat_upper : pt::none;
 | 
			
		||||
  case 'e':
 | 
			
		||||
    return in(t, float_set) ? pt::exp_lower : pt::none;
 | 
			
		||||
  case 'E':
 | 
			
		||||
    return in(t, float_set) ? pt::exp_upper : pt::none;
 | 
			
		||||
  case 'f':
 | 
			
		||||
    return in(t, float_set) ? pt::fixed_lower : pt::none;
 | 
			
		||||
  case 'F':
 | 
			
		||||
    return in(t, float_set) ? pt::fixed_upper : pt::none;
 | 
			
		||||
  case 'g':
 | 
			
		||||
    return in(t, float_set) ? pt::general_lower : pt::none;
 | 
			
		||||
  case 'G':
 | 
			
		||||
    return in(t, float_set) ? pt::general_upper : pt::none;
 | 
			
		||||
  case 'c':
 | 
			
		||||
    return in(t, integral_set) ? pt::chr : pt::none;
 | 
			
		||||
  case 's':
 | 
			
		||||
    return in(t, string_set | cstring_set) ? pt::string : pt::none;
 | 
			
		||||
  case 'p':
 | 
			
		||||
    return in(t, pointer_set | cstring_set) ? pt::pointer : pt::none;
 | 
			
		||||
  default:
 | 
			
		||||
    return pt::none;
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename Context>
 | 
			
		||||
void vprintf(buffer<Char>& buf, basic_string_view<Char> format,
 | 
			
		||||
             basic_format_args<Context> args) {
 | 
			
		||||
  using iterator = buffer_appender<Char>;
 | 
			
		||||
  auto out = iterator(buf);
 | 
			
		||||
  auto context = basic_printf_context<Char>(out, args);
 | 
			
		||||
  auto parse_ctx = basic_format_parse_context<Char>(format);
 | 
			
		||||
 | 
			
		||||
  // Returns the argument with specified index or, if arg_index is -1, the next
 | 
			
		||||
  // argument.
 | 
			
		||||
  auto get_arg = [&](int arg_index) {
 | 
			
		||||
    if (arg_index < 0)
 | 
			
		||||
      arg_index = parse_ctx.next_arg_id();
 | 
			
		||||
    else
 | 
			
		||||
      parse_ctx.check_arg_id(--arg_index);
 | 
			
		||||
    return detail::get_arg(context, arg_index);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  const Char* start = parse_ctx.begin();
 | 
			
		||||
  const Char* end = parse_ctx.end();
 | 
			
		||||
  auto it = start;
 | 
			
		||||
  while (it != end) {
 | 
			
		||||
    if (!find<false, Char>(it, end, '%', it)) {
 | 
			
		||||
      it = end;  // find leaves it == nullptr if it doesn't find '%'.
 | 
			
		||||
      break;
 | 
			
		||||
    }
 | 
			
		||||
    Char c = *it++;
 | 
			
		||||
    if (it != end && *it == c) {
 | 
			
		||||
      write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
 | 
			
		||||
      start = ++it;
 | 
			
		||||
      continue;
 | 
			
		||||
    }
 | 
			
		||||
    write(out, basic_string_view<Char>(start, to_unsigned(it - 1 - start)));
 | 
			
		||||
 | 
			
		||||
    auto specs = format_specs<Char>();
 | 
			
		||||
    specs.align = align::right;
 | 
			
		||||
 | 
			
		||||
    // Parse argument index, flags and width.
 | 
			
		||||
    int arg_index = parse_header(it, end, specs, get_arg);
 | 
			
		||||
    if (arg_index == 0) throw_format_error("argument not found");
 | 
			
		||||
 | 
			
		||||
    // Parse precision.
 | 
			
		||||
    if (it != end && *it == '.') {
 | 
			
		||||
      ++it;
 | 
			
		||||
      c = it != end ? *it : 0;
 | 
			
		||||
      if ('0' <= c && c <= '9') {
 | 
			
		||||
        specs.precision = parse_nonnegative_int(it, end, 0);
 | 
			
		||||
      } else if (c == '*') {
 | 
			
		||||
        ++it;
 | 
			
		||||
        specs.precision = static_cast<int>(
 | 
			
		||||
            visit_format_arg(printf_precision_handler(), get_arg(-1)));
 | 
			
		||||
      } else {
 | 
			
		||||
        specs.precision = 0;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    auto arg = get_arg(arg_index);
 | 
			
		||||
    // For d, i, o, u, x, and X conversion specifiers, if a precision is
 | 
			
		||||
    // specified, the '0' flag is ignored
 | 
			
		||||
    if (specs.precision >= 0 && arg.is_integral()) {
 | 
			
		||||
      // Ignore '0' for non-numeric types or if '-' present.
 | 
			
		||||
      specs.fill[0] = ' ';
 | 
			
		||||
    }
 | 
			
		||||
    if (specs.precision >= 0 && arg.type() == type::cstring_type) {
 | 
			
		||||
      auto str = visit_format_arg(get_cstring<Char>(), arg);
 | 
			
		||||
      auto str_end = str + specs.precision;
 | 
			
		||||
      auto nul = std::find(str, str_end, Char());
 | 
			
		||||
      auto sv = basic_string_view<Char>(
 | 
			
		||||
          str, to_unsigned(nul != str_end ? nul - str : specs.precision));
 | 
			
		||||
      arg = make_arg<basic_printf_context<Char>>(sv);
 | 
			
		||||
    }
 | 
			
		||||
    if (specs.alt && visit_format_arg(is_zero_int(), arg)) specs.alt = false;
 | 
			
		||||
    if (specs.fill[0] == '0') {
 | 
			
		||||
      if (arg.is_arithmetic() && specs.align != align::left)
 | 
			
		||||
        specs.align = align::numeric;
 | 
			
		||||
      else
 | 
			
		||||
        specs.fill[0] = ' ';  // Ignore '0' flag for non-numeric types or if '-'
 | 
			
		||||
                              // flag is also present.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Parse length and convert the argument to the required type.
 | 
			
		||||
    c = it != end ? *it++ : 0;
 | 
			
		||||
    Char t = it != end ? *it : 0;
 | 
			
		||||
    switch (c) {
 | 
			
		||||
    case 'h':
 | 
			
		||||
      if (t == 'h') {
 | 
			
		||||
        ++it;
 | 
			
		||||
        t = it != end ? *it : 0;
 | 
			
		||||
        convert_arg<signed char>(arg, t);
 | 
			
		||||
      } else {
 | 
			
		||||
        convert_arg<short>(arg, t);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case 'l':
 | 
			
		||||
      if (t == 'l') {
 | 
			
		||||
        ++it;
 | 
			
		||||
        t = it != end ? *it : 0;
 | 
			
		||||
        convert_arg<long long>(arg, t);
 | 
			
		||||
      } else {
 | 
			
		||||
        convert_arg<long>(arg, t);
 | 
			
		||||
      }
 | 
			
		||||
      break;
 | 
			
		||||
    case 'j':
 | 
			
		||||
      convert_arg<intmax_t>(arg, t);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'z':
 | 
			
		||||
      convert_arg<size_t>(arg, t);
 | 
			
		||||
      break;
 | 
			
		||||
    case 't':
 | 
			
		||||
      convert_arg<std::ptrdiff_t>(arg, t);
 | 
			
		||||
      break;
 | 
			
		||||
    case 'L':
 | 
			
		||||
      // printf produces garbage when 'L' is omitted for long double, no
 | 
			
		||||
      // need to do the same.
 | 
			
		||||
      break;
 | 
			
		||||
    default:
 | 
			
		||||
      --it;
 | 
			
		||||
      convert_arg<void>(arg, c);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Parse type.
 | 
			
		||||
    if (it == end) throw_format_error("invalid format string");
 | 
			
		||||
    char type = static_cast<char>(*it++);
 | 
			
		||||
    if (arg.is_integral()) {
 | 
			
		||||
      // Normalize type.
 | 
			
		||||
      switch (type) {
 | 
			
		||||
      case 'i':
 | 
			
		||||
      case 'u':
 | 
			
		||||
        type = 'd';
 | 
			
		||||
        break;
 | 
			
		||||
      case 'c':
 | 
			
		||||
        visit_format_arg(char_converter<basic_printf_context<Char>>(arg), arg);
 | 
			
		||||
        break;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    specs.type = parse_printf_presentation_type(type, arg.type());
 | 
			
		||||
    if (specs.type == presentation_type::none)
 | 
			
		||||
      throw_format_error("invalid format specifier");
 | 
			
		||||
 | 
			
		||||
    start = it;
 | 
			
		||||
 | 
			
		||||
    // Format argument.
 | 
			
		||||
    visit_format_arg(printf_arg_formatter<Char>(out, specs, context), arg);
 | 
			
		||||
  }
 | 
			
		||||
  write(out, basic_string_view<Char>(start, to_unsigned(it - start)));
 | 
			
		||||
}
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
using printf_context = basic_printf_context<char>;
 | 
			
		||||
using wprintf_context = basic_printf_context<wchar_t>;
 | 
			
		||||
 | 
			
		||||
using printf_args = basic_format_args<printf_context>;
 | 
			
		||||
using wprintf_args = basic_format_args<wprintf_context>;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Constructs an `~fmt::format_arg_store` object that contains references to
 | 
			
		||||
  arguments and can be implicitly converted to `~fmt::printf_args`.
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename... T>
 | 
			
		||||
inline auto make_printf_args(const T&... args)
 | 
			
		||||
    -> format_arg_store<printf_context, T...> {
 | 
			
		||||
  return {args...};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// DEPRECATED!
 | 
			
		||||
template <typename... T>
 | 
			
		||||
inline auto make_wprintf_args(const T&... args)
 | 
			
		||||
    -> format_arg_store<wprintf_context, T...> {
 | 
			
		||||
  return {args...};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
inline auto vsprintf(
 | 
			
		||||
    basic_string_view<Char> fmt,
 | 
			
		||||
    basic_format_args<basic_printf_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> std::basic_string<Char> {
 | 
			
		||||
  auto buf = basic_memory_buffer<Char>();
 | 
			
		||||
  detail::vprintf(buf, fmt, args);
 | 
			
		||||
  return to_string(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Formats arguments and returns the result as a string.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    std::string message = fmt::sprintf("The answer is %d", 42);
 | 
			
		||||
  \endrst
 | 
			
		||||
*/
 | 
			
		||||
template <typename S, typename... T,
 | 
			
		||||
          typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
 | 
			
		||||
inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> {
 | 
			
		||||
  return vsprintf(detail::to_string_view(fmt),
 | 
			
		||||
                  fmt::make_format_args<basic_printf_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
inline auto vfprintf(
 | 
			
		||||
    std::FILE* f, basic_string_view<Char> fmt,
 | 
			
		||||
    basic_format_args<basic_printf_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> int {
 | 
			
		||||
  auto buf = basic_memory_buffer<Char>();
 | 
			
		||||
  detail::vprintf(buf, fmt, args);
 | 
			
		||||
  size_t size = buf.size();
 | 
			
		||||
  return std::fwrite(buf.data(), sizeof(Char), size, f) < size
 | 
			
		||||
             ? -1
 | 
			
		||||
             : static_cast<int>(size);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to the file *f*.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::fprintf(stderr, "Don't %s!", "panic");
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename S, typename... T, typename Char = char_t<S>>
 | 
			
		||||
inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int {
 | 
			
		||||
  return vfprintf(f, detail::to_string_view(fmt),
 | 
			
		||||
                  fmt::make_format_args<basic_printf_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
FMT_DEPRECATED inline auto vprintf(
 | 
			
		||||
    basic_string_view<Char> fmt,
 | 
			
		||||
    basic_format_args<basic_printf_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> int {
 | 
			
		||||
  return vfprintf(stdout, fmt, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Prints formatted data to ``stdout``.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::printf("Elapsed time: %.2f seconds", 1.23);
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename... T>
 | 
			
		||||
inline auto printf(string_view fmt, const T&... args) -> int {
 | 
			
		||||
  return vfprintf(stdout, fmt, make_printf_args(args...));
 | 
			
		||||
}
 | 
			
		||||
template <typename... T>
 | 
			
		||||
FMT_DEPRECATED inline auto printf(basic_string_view<wchar_t> fmt,
 | 
			
		||||
                                  const T&... args) -> int {
 | 
			
		||||
  return vfprintf(stdout, fmt, make_wprintf_args(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_END_EXPORT
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_PRINTF_H_
 | 
			
		||||
							
								
								
									
										738
									
								
								3rd/fmt/ranges.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										738
									
								
								3rd/fmt/ranges.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,738 @@
 | 
			
		||||
// Formatting library for C++ - range and tuple support
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - present, Victor Zverovich and {fmt} contributors
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_RANGES_H_
 | 
			
		||||
#define FMT_RANGES_H_
 | 
			
		||||
 | 
			
		||||
#include <initializer_list>
 | 
			
		||||
#include <tuple>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename Range, typename OutputIt>
 | 
			
		||||
auto copy(const Range& range, OutputIt out) -> OutputIt {
 | 
			
		||||
  for (auto it = range.begin(), end = range.end(); it != end; ++it)
 | 
			
		||||
    *out++ = *it;
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt>
 | 
			
		||||
auto copy(const char* str, OutputIt out) -> OutputIt {
 | 
			
		||||
  while (*str) *out++ = *str++;
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt> auto copy(char ch, OutputIt out) -> OutputIt {
 | 
			
		||||
  *out++ = ch;
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt> auto copy(wchar_t ch, OutputIt out) -> OutputIt {
 | 
			
		||||
  *out++ = ch;
 | 
			
		||||
  return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Returns true if T has a std::string-like interface, like std::string_view.
 | 
			
		||||
template <typename T> class is_std_string_like {
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  static auto check(U* p)
 | 
			
		||||
      -> decltype((void)p->find('a'), p->length(), (void)p->data(), int());
 | 
			
		||||
  template <typename> static void check(...);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      is_string<T>::value ||
 | 
			
		||||
      std::is_convertible<T, std_string_view<char>>::value ||
 | 
			
		||||
      !std::is_void<decltype(check<T>(nullptr))>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char>
 | 
			
		||||
struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename T> class is_map {
 | 
			
		||||
  template <typename U> static auto check(U*) -> typename U::mapped_type;
 | 
			
		||||
  template <typename> static void check(...);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
#ifdef FMT_FORMAT_MAP_AS_LIST  // DEPRECATED!
 | 
			
		||||
  static constexpr const bool value = false;
 | 
			
		||||
#else
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      !std::is_void<decltype(check<T>(nullptr))>::value;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T> class is_set {
 | 
			
		||||
  template <typename U> static auto check(U*) -> typename U::key_type;
 | 
			
		||||
  template <typename> static void check(...);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
#ifdef FMT_FORMAT_SET_AS_LIST  // DEPRECATED!
 | 
			
		||||
  static constexpr const bool value = false;
 | 
			
		||||
#else
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      !std::is_void<decltype(check<T>(nullptr))>::value && !is_map<T>::value;
 | 
			
		||||
#endif
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename... Ts> struct conditional_helper {};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename _ = void> struct is_range_ : std::false_type {};
 | 
			
		||||
 | 
			
		||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION > 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 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_end(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_end(std::declval<T>())),
 | 
			
		||||
              // the extra int here is because older versions of MSVC don't
 | 
			
		||||
              // SFINAE properly unless there are distinct types
 | 
			
		||||
              int>> : 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)> {};
 | 
			
		||||
#  undef FMT_DECLTYPE_RETURN
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// tuple_size and tuple_element check.
 | 
			
		||||
template <typename T> class is_tuple_like_ {
 | 
			
		||||
  template <typename U>
 | 
			
		||||
  static auto check(U* p) -> decltype(std::tuple_size<U>::value, int());
 | 
			
		||||
  template <typename> static void check(...);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      !std::is_void<decltype(check<T>(nullptr))>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Check for integer_sequence
 | 
			
		||||
#if defined(__cpp_lib_integer_sequence) || FMT_MSC_VERSION >= 1900
 | 
			
		||||
template <typename T, T... N>
 | 
			
		||||
using integer_sequence = std::integer_sequence<T, N...>;
 | 
			
		||||
template <size_t... N> using index_sequence = std::index_sequence<N...>;
 | 
			
		||||
template <size_t N> using make_index_sequence = std::make_index_sequence<N>;
 | 
			
		||||
#else
 | 
			
		||||
template <typename T, T... N> struct integer_sequence {
 | 
			
		||||
  using value_type = T;
 | 
			
		||||
 | 
			
		||||
  static FMT_CONSTEXPR auto size() -> size_t { return sizeof...(N); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <size_t... N> using index_sequence = integer_sequence<size_t, N...>;
 | 
			
		||||
 | 
			
		||||
template <typename T, size_t N, T... Ns>
 | 
			
		||||
struct make_integer_sequence : make_integer_sequence<T, N - 1, N - 1, Ns...> {};
 | 
			
		||||
template <typename T, T... Ns>
 | 
			
		||||
struct make_integer_sequence<T, 0, Ns...> : integer_sequence<T, Ns...> {};
 | 
			
		||||
 | 
			
		||||
template <size_t N>
 | 
			
		||||
using make_index_sequence = make_integer_sequence<size_t, N>;
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using tuple_index_sequence = make_index_sequence<std::tuple_size<T>::value>;
 | 
			
		||||
 | 
			
		||||
template <typename T, typename C, bool = is_tuple_like_<T>::value>
 | 
			
		||||
class is_tuple_formattable_ {
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr const bool value = false;
 | 
			
		||||
};
 | 
			
		||||
template <typename T, typename C> class is_tuple_formattable_<T, C, true> {
 | 
			
		||||
  template <std::size_t... Is>
 | 
			
		||||
  static auto check2(index_sequence<Is...>,
 | 
			
		||||
                     integer_sequence<bool, (Is == Is)...>) -> std::true_type;
 | 
			
		||||
  static auto check2(...) -> std::false_type;
 | 
			
		||||
  template <std::size_t... Is>
 | 
			
		||||
  static auto check(index_sequence<Is...>) -> decltype(check2(
 | 
			
		||||
      index_sequence<Is...>{},
 | 
			
		||||
      integer_sequence<bool,
 | 
			
		||||
                       (is_formattable<typename std::tuple_element<Is, T>::type,
 | 
			
		||||
                                       C>::value)...>{}));
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      decltype(check(tuple_index_sequence<T>{}))::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Tuple, typename F, size_t... Is>
 | 
			
		||||
FMT_CONSTEXPR void for_each(index_sequence<Is...>, Tuple&& t, F&& f) {
 | 
			
		||||
  using std::get;
 | 
			
		||||
  // Using a free function get<Is>(Tuple) now.
 | 
			
		||||
  const int unused[] = {0, ((void)f(get<Is>(t)), 0)...};
 | 
			
		||||
  ignore_unused(unused);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Tuple, typename F>
 | 
			
		||||
FMT_CONSTEXPR void for_each(Tuple&& t, F&& f) {
 | 
			
		||||
  for_each(tuple_index_sequence<remove_cvref_t<Tuple>>(),
 | 
			
		||||
           std::forward<Tuple>(t), std::forward<F>(f));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Tuple1, typename Tuple2, typename F, size_t... Is>
 | 
			
		||||
void for_each2(index_sequence<Is...>, Tuple1&& t1, Tuple2&& t2, F&& f) {
 | 
			
		||||
  using std::get;
 | 
			
		||||
  const int unused[] = {0, ((void)f(get<Is>(t1), get<Is>(t2)), 0)...};
 | 
			
		||||
  ignore_unused(unused);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Tuple1, typename Tuple2, typename F>
 | 
			
		||||
void for_each2(Tuple1&& t1, Tuple2&& t2, F&& f) {
 | 
			
		||||
  for_each2(tuple_index_sequence<remove_cvref_t<Tuple1>>(),
 | 
			
		||||
            std::forward<Tuple1>(t1), std::forward<Tuple2>(t2),
 | 
			
		||||
            std::forward<F>(f));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
namespace tuple {
 | 
			
		||||
// Workaround a bug in MSVC 2019 (v140).
 | 
			
		||||
template <typename Char, typename... T>
 | 
			
		||||
using result_t = std::tuple<formatter<remove_cvref_t<T>, Char>...>;
 | 
			
		||||
 | 
			
		||||
using std::get;
 | 
			
		||||
template <typename Tuple, typename Char, std::size_t... Is>
 | 
			
		||||
auto get_formatters(index_sequence<Is...>)
 | 
			
		||||
    -> result_t<Char, decltype(get<Is>(std::declval<Tuple>()))...>;
 | 
			
		||||
}  // namespace tuple
 | 
			
		||||
 | 
			
		||||
#if FMT_MSC_VERSION && FMT_MSC_VERSION < 1920
 | 
			
		||||
// Older MSVC doesn't get the reference type correctly for arrays.
 | 
			
		||||
template <typename R> struct range_reference_type_impl {
 | 
			
		||||
  using type = decltype(*detail::range_begin(std::declval<R&>()));
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, std::size_t N> struct range_reference_type_impl<T[N]> {
 | 
			
		||||
  using type = T&;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using range_reference_type = typename range_reference_type_impl<T>::type;
 | 
			
		||||
#else
 | 
			
		||||
template <typename Range>
 | 
			
		||||
using range_reference_type =
 | 
			
		||||
    decltype(*detail::range_begin(std::declval<Range&>()));
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// We don't use the Range's value_type for anything, but we do need the Range's
 | 
			
		||||
// reference type, with cv-ref stripped.
 | 
			
		||||
template <typename Range>
 | 
			
		||||
using uncvref_type = remove_cvref_t<range_reference_type<Range>>;
 | 
			
		||||
 | 
			
		||||
template <typename Formatter>
 | 
			
		||||
FMT_CONSTEXPR auto maybe_set_debug_format(Formatter& f, bool set)
 | 
			
		||||
    -> decltype(f.set_debug_format(set)) {
 | 
			
		||||
  f.set_debug_format(set);
 | 
			
		||||
}
 | 
			
		||||
template <typename Formatter>
 | 
			
		||||
FMT_CONSTEXPR void maybe_set_debug_format(Formatter&, ...) {}
 | 
			
		||||
 | 
			
		||||
// These are not generic lambdas for compatibility with C++11.
 | 
			
		||||
template <typename ParseContext> struct parse_empty_specs {
 | 
			
		||||
  template <typename Formatter> FMT_CONSTEXPR void operator()(Formatter& f) {
 | 
			
		||||
    f.parse(ctx);
 | 
			
		||||
    detail::maybe_set_debug_format(f, true);
 | 
			
		||||
  }
 | 
			
		||||
  ParseContext& ctx;
 | 
			
		||||
};
 | 
			
		||||
template <typename FormatContext> struct format_tuple_element {
 | 
			
		||||
  using char_type = typename FormatContext::char_type;
 | 
			
		||||
 | 
			
		||||
  template <typename T>
 | 
			
		||||
  void operator()(const formatter<T, char_type>& f, const T& v) {
 | 
			
		||||
    if (i > 0)
 | 
			
		||||
      ctx.advance_to(detail::copy_str<char_type>(separator, ctx.out()));
 | 
			
		||||
    ctx.advance_to(f.format(v, ctx));
 | 
			
		||||
    ++i;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int i;
 | 
			
		||||
  FormatContext& ctx;
 | 
			
		||||
  basic_string_view<char_type> separator;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
template <typename T> struct is_tuple_like {
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      detail::is_tuple_like_<T>::value && !detail::is_range_<T>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename C> struct is_tuple_formattable {
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      detail::is_tuple_formattable_<T, C>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Tuple, typename Char>
 | 
			
		||||
struct formatter<Tuple, Char,
 | 
			
		||||
                 enable_if_t<fmt::is_tuple_like<Tuple>::value &&
 | 
			
		||||
                             fmt::is_tuple_formattable<Tuple, Char>::value>> {
 | 
			
		||||
 private:
 | 
			
		||||
  decltype(detail::tuple::get_formatters<Tuple, Char>(
 | 
			
		||||
      detail::tuple_index_sequence<Tuple>())) formatters_;
 | 
			
		||||
 | 
			
		||||
  basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
 | 
			
		||||
  basic_string_view<Char> opening_bracket_ =
 | 
			
		||||
      detail::string_literal<Char, '('>{};
 | 
			
		||||
  basic_string_view<Char> closing_bracket_ =
 | 
			
		||||
      detail::string_literal<Char, ')'>{};
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  FMT_CONSTEXPR formatter() {}
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
 | 
			
		||||
    separator_ = sep;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
 | 
			
		||||
                                  basic_string_view<Char> close) {
 | 
			
		||||
    opening_bracket_ = open;
 | 
			
		||||
    closing_bracket_ = close;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    auto it = ctx.begin();
 | 
			
		||||
    if (it != ctx.end() && *it != '}')
 | 
			
		||||
      FMT_THROW(format_error("invalid format specifier"));
 | 
			
		||||
    detail::for_each(formatters_, detail::parse_empty_specs<ParseContext>{ctx});
 | 
			
		||||
    return it;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const Tuple& value, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    ctx.advance_to(detail::copy_str<Char>(opening_bracket_, ctx.out()));
 | 
			
		||||
    detail::for_each2(
 | 
			
		||||
        formatters_, value,
 | 
			
		||||
        detail::format_tuple_element<FormatContext>{0, ctx, separator_});
 | 
			
		||||
    return detail::copy_str<Char>(closing_bracket_, ctx.out());
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char> struct is_range {
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      detail::is_range_<T>::value && !detail::is_std_string_like<T>::value &&
 | 
			
		||||
      !std::is_convertible<T, std::basic_string<Char>>::value &&
 | 
			
		||||
      !std::is_convertible<T, detail::std_string_view<Char>>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
template <typename Context> struct range_mapper {
 | 
			
		||||
  using mapper = arg_mapper<Context>;
 | 
			
		||||
 | 
			
		||||
  template <typename T,
 | 
			
		||||
            FMT_ENABLE_IF(has_formatter<remove_cvref_t<T>, Context>::value)>
 | 
			
		||||
  static auto map(T&& value) -> T&& {
 | 
			
		||||
    return static_cast<T&&>(value);
 | 
			
		||||
  }
 | 
			
		||||
  template <typename T,
 | 
			
		||||
            FMT_ENABLE_IF(!has_formatter<remove_cvref_t<T>, Context>::value)>
 | 
			
		||||
  static auto map(T&& value)
 | 
			
		||||
      -> decltype(mapper().map(static_cast<T&&>(value))) {
 | 
			
		||||
    return mapper().map(static_cast<T&&>(value));
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename Element>
 | 
			
		||||
using range_formatter_type =
 | 
			
		||||
    formatter<remove_cvref_t<decltype(range_mapper<buffer_context<Char>>{}.map(
 | 
			
		||||
                  std::declval<Element>()))>,
 | 
			
		||||
              Char>;
 | 
			
		||||
 | 
			
		||||
template <typename R>
 | 
			
		||||
using maybe_const_range =
 | 
			
		||||
    conditional_t<has_const_begin_end<R>::value, const R, R>;
 | 
			
		||||
 | 
			
		||||
// Workaround a bug in MSVC 2015 and earlier.
 | 
			
		||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
 | 
			
		||||
template <typename R, typename Char>
 | 
			
		||||
struct is_formattable_delayed
 | 
			
		||||
    : is_formattable<uncvref_type<maybe_const_range<R>>, Char> {};
 | 
			
		||||
#endif
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
template <typename...> struct conjunction : std::true_type {};
 | 
			
		||||
template <typename P> struct conjunction<P> : P {};
 | 
			
		||||
template <typename P1, typename... Pn>
 | 
			
		||||
struct conjunction<P1, Pn...>
 | 
			
		||||
    : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char, typename Enable = void>
 | 
			
		||||
struct range_formatter;
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct range_formatter<
 | 
			
		||||
    T, Char,
 | 
			
		||||
    enable_if_t<conjunction<std::is_same<T, remove_cvref_t<T>>,
 | 
			
		||||
                            is_formattable<T, Char>>::value>> {
 | 
			
		||||
 private:
 | 
			
		||||
  detail::range_formatter_type<Char, T> underlying_;
 | 
			
		||||
  basic_string_view<Char> separator_ = detail::string_literal<Char, ',', ' '>{};
 | 
			
		||||
  basic_string_view<Char> opening_bracket_ =
 | 
			
		||||
      detail::string_literal<Char, '['>{};
 | 
			
		||||
  basic_string_view<Char> closing_bracket_ =
 | 
			
		||||
      detail::string_literal<Char, ']'>{};
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  FMT_CONSTEXPR range_formatter() {}
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR auto underlying() -> detail::range_formatter_type<Char, T>& {
 | 
			
		||||
    return underlying_;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void set_separator(basic_string_view<Char> sep) {
 | 
			
		||||
    separator_ = sep;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void set_brackets(basic_string_view<Char> open,
 | 
			
		||||
                                  basic_string_view<Char> close) {
 | 
			
		||||
    opening_bracket_ = open;
 | 
			
		||||
    closing_bracket_ = close;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    auto it = ctx.begin();
 | 
			
		||||
    auto end = ctx.end();
 | 
			
		||||
 | 
			
		||||
    if (it != end && *it == 'n') {
 | 
			
		||||
      set_brackets({}, {});
 | 
			
		||||
      ++it;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (it != end && *it != '}') {
 | 
			
		||||
      if (*it != ':') FMT_THROW(format_error("invalid format specifier"));
 | 
			
		||||
      ++it;
 | 
			
		||||
    } else {
 | 
			
		||||
      detail::maybe_set_debug_format(underlying_, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    ctx.advance_to(it);
 | 
			
		||||
    return underlying_.parse(ctx);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename R, typename FormatContext>
 | 
			
		||||
  auto format(R&& range, FormatContext& ctx) const -> decltype(ctx.out()) {
 | 
			
		||||
    detail::range_mapper<buffer_context<Char>> mapper;
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
    out = detail::copy_str<Char>(opening_bracket_, out);
 | 
			
		||||
    int i = 0;
 | 
			
		||||
    auto it = detail::range_begin(range);
 | 
			
		||||
    auto end = detail::range_end(range);
 | 
			
		||||
    for (; it != end; ++it) {
 | 
			
		||||
      if (i > 0) out = detail::copy_str<Char>(separator_, out);
 | 
			
		||||
      ctx.advance_to(out);
 | 
			
		||||
      auto&& item = *it;
 | 
			
		||||
      out = underlying_.format(mapper.map(item), ctx);
 | 
			
		||||
      ++i;
 | 
			
		||||
    }
 | 
			
		||||
    out = detail::copy_str<Char>(closing_bracket_, out);
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
enum class range_format { disabled, map, set, sequence, string, debug_string };
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct range_format_kind_
 | 
			
		||||
    : std::integral_constant<range_format,
 | 
			
		||||
                             std::is_same<uncvref_type<T>, T>::value
 | 
			
		||||
                                 ? range_format::disabled
 | 
			
		||||
                             : is_map<T>::value ? range_format::map
 | 
			
		||||
                             : is_set<T>::value ? range_format::set
 | 
			
		||||
                                                : range_format::sequence> {};
 | 
			
		||||
 | 
			
		||||
template <range_format K, typename R, typename Char, typename Enable = void>
 | 
			
		||||
struct range_default_formatter;
 | 
			
		||||
 | 
			
		||||
template <range_format K>
 | 
			
		||||
using range_format_constant = std::integral_constant<range_format, K>;
 | 
			
		||||
 | 
			
		||||
template <range_format K, typename R, typename Char>
 | 
			
		||||
struct range_default_formatter<
 | 
			
		||||
    K, R, Char,
 | 
			
		||||
    enable_if_t<(K == range_format::sequence || K == range_format::map ||
 | 
			
		||||
                 K == range_format::set)>> {
 | 
			
		||||
  using range_type = detail::maybe_const_range<R>;
 | 
			
		||||
  range_formatter<detail::uncvref_type<range_type>, Char> underlying_;
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR range_default_formatter() { init(range_format_constant<K>()); }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void init(range_format_constant<range_format::set>) {
 | 
			
		||||
    underlying_.set_brackets(detail::string_literal<Char, '{'>{},
 | 
			
		||||
                             detail::string_literal<Char, '}'>{});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void init(range_format_constant<range_format::map>) {
 | 
			
		||||
    underlying_.set_brackets(detail::string_literal<Char, '{'>{},
 | 
			
		||||
                             detail::string_literal<Char, '}'>{});
 | 
			
		||||
    underlying_.underlying().set_brackets({}, {});
 | 
			
		||||
    underlying_.underlying().set_separator(
 | 
			
		||||
        detail::string_literal<Char, ':', ' '>{});
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  FMT_CONSTEXPR void init(range_format_constant<range_format::sequence>) {}
 | 
			
		||||
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    return underlying_.parse(ctx);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(range_type& range, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    return underlying_.format(range, ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char, typename Enable = void>
 | 
			
		||||
struct range_format_kind
 | 
			
		||||
    : conditional_t<
 | 
			
		||||
          is_range<T, Char>::value, detail::range_format_kind_<T>,
 | 
			
		||||
          std::integral_constant<range_format, range_format::disabled>> {};
 | 
			
		||||
 | 
			
		||||
template <typename R, typename Char>
 | 
			
		||||
struct formatter<
 | 
			
		||||
    R, Char,
 | 
			
		||||
    enable_if_t<conjunction<bool_constant<range_format_kind<R, Char>::value !=
 | 
			
		||||
                                          range_format::disabled>
 | 
			
		||||
// Workaround a bug in MSVC 2015 and earlier.
 | 
			
		||||
#if !FMT_MSC_VERSION || FMT_MSC_VERSION >= 1910
 | 
			
		||||
                            ,
 | 
			
		||||
                            detail::is_formattable_delayed<R, Char>
 | 
			
		||||
#endif
 | 
			
		||||
                            >::value>>
 | 
			
		||||
    : detail::range_default_formatter<range_format_kind<R, Char>::value, R,
 | 
			
		||||
                                      Char> {
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename... T> struct tuple_join_view : detail::view {
 | 
			
		||||
  const std::tuple<T...>& tuple;
 | 
			
		||||
  basic_string_view<Char> sep;
 | 
			
		||||
 | 
			
		||||
  tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s)
 | 
			
		||||
      : tuple(t), sep{s} {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
// Define FMT_TUPLE_JOIN_SPECIFIERS to enable experimental format specifiers
 | 
			
		||||
// support in tuple_join. It is disabled by default because of issues with
 | 
			
		||||
// the dynamic width and precision.
 | 
			
		||||
#ifndef FMT_TUPLE_JOIN_SPECIFIERS
 | 
			
		||||
#  define FMT_TUPLE_JOIN_SPECIFIERS 0
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename... T>
 | 
			
		||||
struct formatter<tuple_join_view<Char, T...>, Char> {
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    return do_parse(ctx, std::integral_constant<size_t, sizeof...(T)>());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const tuple_join_view<Char, T...>& value,
 | 
			
		||||
              FormatContext& ctx) const -> typename FormatContext::iterator {
 | 
			
		||||
    return do_format(value, ctx,
 | 
			
		||||
                     std::integral_constant<size_t, sizeof...(T)>());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 private:
 | 
			
		||||
  std::tuple<formatter<typename std::decay<T>::type, Char>...> formatters_;
 | 
			
		||||
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
 | 
			
		||||
                              std::integral_constant<size_t, 0>)
 | 
			
		||||
      -> decltype(ctx.begin()) {
 | 
			
		||||
    return ctx.begin();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename ParseContext, size_t N>
 | 
			
		||||
  FMT_CONSTEXPR auto do_parse(ParseContext& ctx,
 | 
			
		||||
                              std::integral_constant<size_t, N>)
 | 
			
		||||
      -> decltype(ctx.begin()) {
 | 
			
		||||
    auto end = ctx.begin();
 | 
			
		||||
#if FMT_TUPLE_JOIN_SPECIFIERS
 | 
			
		||||
    end = std::get<sizeof...(T) - N>(formatters_).parse(ctx);
 | 
			
		||||
    if (N > 1) {
 | 
			
		||||
      auto end1 = do_parse(ctx, std::integral_constant<size_t, N - 1>());
 | 
			
		||||
      if (end != end1)
 | 
			
		||||
        FMT_THROW(format_error("incompatible format specs for tuple elements"));
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    return end;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto do_format(const tuple_join_view<Char, T...>&, FormatContext& ctx,
 | 
			
		||||
                 std::integral_constant<size_t, 0>) const ->
 | 
			
		||||
      typename FormatContext::iterator {
 | 
			
		||||
    return ctx.out();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext, size_t N>
 | 
			
		||||
  auto do_format(const tuple_join_view<Char, T...>& value, FormatContext& ctx,
 | 
			
		||||
                 std::integral_constant<size_t, N>) const ->
 | 
			
		||||
      typename FormatContext::iterator {
 | 
			
		||||
    auto out = std::get<sizeof...(T) - N>(formatters_)
 | 
			
		||||
                   .format(std::get<sizeof...(T) - N>(value.tuple), ctx);
 | 
			
		||||
    if (N > 1) {
 | 
			
		||||
      out = std::copy(value.sep.begin(), value.sep.end(), out);
 | 
			
		||||
      ctx.advance_to(out);
 | 
			
		||||
      return do_format(value, ctx, std::integral_constant<size_t, N - 1>());
 | 
			
		||||
    }
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
// Check if T has an interface like a container adaptor (e.g. std::stack,
 | 
			
		||||
// std::queue, std::priority_queue).
 | 
			
		||||
template <typename T> class is_container_adaptor_like {
 | 
			
		||||
  template <typename U> static auto check(U* p) -> typename U::container_type;
 | 
			
		||||
  template <typename> static void check(...);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      !std::is_void<decltype(check<T>(nullptr))>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Container> struct all {
 | 
			
		||||
  const Container& c;
 | 
			
		||||
  auto begin() const -> typename Container::const_iterator { return c.begin(); }
 | 
			
		||||
  auto end() const -> typename Container::const_iterator { return c.end(); }
 | 
			
		||||
};
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct formatter<
 | 
			
		||||
    T, Char,
 | 
			
		||||
    enable_if_t<conjunction<detail::is_container_adaptor_like<T>,
 | 
			
		||||
                            bool_constant<range_format_kind<T, Char>::value ==
 | 
			
		||||
                                          range_format::disabled>>::value>>
 | 
			
		||||
    : formatter<detail::all<typename T::container_type>, Char> {
 | 
			
		||||
  using all = detail::all<typename T::container_type>;
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const T& t, FormatContext& ctx) const -> decltype(ctx.out()) {
 | 
			
		||||
    struct getter : T {
 | 
			
		||||
      static auto get(const T& t) -> all {
 | 
			
		||||
        return {t.*(&getter::c)};  // Access c through the derived class.
 | 
			
		||||
      }
 | 
			
		||||
    };
 | 
			
		||||
    return formatter<all>::format(getter::get(t), ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_EXPORT
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Returns an object that formats `tuple` with elements separated by `sep`.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    std::tuple<int, char> t = {1, 'a'};
 | 
			
		||||
    fmt::print("{}", fmt::join(t, ", "));
 | 
			
		||||
    // Output: "1, a"
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename... T>
 | 
			
		||||
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep)
 | 
			
		||||
    -> tuple_join_view<char, T...> {
 | 
			
		||||
  return {tuple, sep};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... T>
 | 
			
		||||
FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple,
 | 
			
		||||
                        basic_string_view<wchar_t> sep)
 | 
			
		||||
    -> tuple_join_view<wchar_t, T...> {
 | 
			
		||||
  return {tuple, sep};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  \rst
 | 
			
		||||
  Returns an object that formats `initializer_list` with elements separated by
 | 
			
		||||
  `sep`.
 | 
			
		||||
 | 
			
		||||
  **Example**::
 | 
			
		||||
 | 
			
		||||
    fmt::print("{}", fmt::join({1, 2, 3}, ", "));
 | 
			
		||||
    // Output: "1, 2, 3"
 | 
			
		||||
  \endrst
 | 
			
		||||
 */
 | 
			
		||||
template <typename T>
 | 
			
		||||
auto join(std::initializer_list<T> list, string_view sep)
 | 
			
		||||
    -> join_view<const T*, const T*> {
 | 
			
		||||
  return join(std::begin(list), std::end(list), sep);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FMT_END_EXPORT
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_RANGES_H_
 | 
			
		||||
							
								
								
									
										537
									
								
								3rd/fmt/std.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										537
									
								
								3rd/fmt/std.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,537 @@
 | 
			
		||||
// Formatting library for C++ - formatters for standard library types
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - present, Victor Zverovich
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_STD_H_
 | 
			
		||||
#define FMT_STD_H_
 | 
			
		||||
 | 
			
		||||
#include <atomic>
 | 
			
		||||
#include <bitset>
 | 
			
		||||
#include <cstdlib>
 | 
			
		||||
#include <exception>
 | 
			
		||||
#include <memory>
 | 
			
		||||
#include <thread>
 | 
			
		||||
#include <type_traits>
 | 
			
		||||
#include <typeinfo>
 | 
			
		||||
#include <utility>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
#include "ostream.h"
 | 
			
		||||
 | 
			
		||||
#if FMT_HAS_INCLUDE(<version>)
 | 
			
		||||
#  include <version>
 | 
			
		||||
#endif
 | 
			
		||||
// Checking FMT_CPLUSPLUS for warning suppression in MSVC.
 | 
			
		||||
#if FMT_CPLUSPLUS >= 201703L
 | 
			
		||||
#  if FMT_HAS_INCLUDE(<filesystem>)
 | 
			
		||||
#    include <filesystem>
 | 
			
		||||
#  endif
 | 
			
		||||
#  if FMT_HAS_INCLUDE(<variant>)
 | 
			
		||||
#    include <variant>
 | 
			
		||||
#  endif
 | 
			
		||||
#  if FMT_HAS_INCLUDE(<optional>)
 | 
			
		||||
#    include <optional>
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if FMT_CPLUSPLUS > 201703L && FMT_HAS_INCLUDE(<source_location>)
 | 
			
		||||
#  include <source_location>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// GCC 4 does not support FMT_HAS_INCLUDE.
 | 
			
		||||
#if FMT_HAS_INCLUDE(<cxxabi.h>) || defined(__GLIBCXX__)
 | 
			
		||||
#  include <cxxabi.h>
 | 
			
		||||
// Android NDK with gabi++ library on some architectures does not implement
 | 
			
		||||
// abi::__cxa_demangle().
 | 
			
		||||
#  ifndef __GABIXX_CXXABI_H__
 | 
			
		||||
#    define FMT_HAS_ABI_CXA_DEMANGLE
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// Check if typeid is available.
 | 
			
		||||
#ifndef FMT_USE_TYPEID
 | 
			
		||||
// __RTTI is for EDG compilers. In MSVC typeid is available without RTTI.
 | 
			
		||||
#  if defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || FMT_MSC_VERSION || \
 | 
			
		||||
      defined(__INTEL_RTTI__) || defined(__RTTI)
 | 
			
		||||
#    define FMT_USE_TYPEID 1
 | 
			
		||||
#  else
 | 
			
		||||
#    define FMT_USE_TYPEID 0
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
// For older Xcode versions, __cpp_lib_xxx flags are inaccurately defined.
 | 
			
		||||
#ifndef FMT_CPP_LIB_FILESYSTEM
 | 
			
		||||
#  ifdef __cpp_lib_filesystem
 | 
			
		||||
#    define FMT_CPP_LIB_FILESYSTEM __cpp_lib_filesystem
 | 
			
		||||
#  else
 | 
			
		||||
#    define FMT_CPP_LIB_FILESYSTEM 0
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_CPP_LIB_VARIANT
 | 
			
		||||
#  ifdef __cpp_lib_variant
 | 
			
		||||
#    define FMT_CPP_LIB_VARIANT __cpp_lib_variant
 | 
			
		||||
#  else
 | 
			
		||||
#    define FMT_CPP_LIB_VARIANT 0
 | 
			
		||||
#  endif
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if FMT_CPP_LIB_FILESYSTEM
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename PathChar>
 | 
			
		||||
auto get_path_string(const std::filesystem::path& p,
 | 
			
		||||
                     const std::basic_string<PathChar>& native) {
 | 
			
		||||
  if constexpr (std::is_same_v<Char, char> && std::is_same_v<PathChar, wchar_t>)
 | 
			
		||||
    return to_utf8<wchar_t>(native, to_utf8_error_policy::replace);
 | 
			
		||||
  else
 | 
			
		||||
    return p.string<Char>();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename PathChar>
 | 
			
		||||
void write_escaped_path(basic_memory_buffer<Char>& quoted,
 | 
			
		||||
                        const std::filesystem::path& p,
 | 
			
		||||
                        const std::basic_string<PathChar>& native) {
 | 
			
		||||
  if constexpr (std::is_same_v<Char, char> &&
 | 
			
		||||
                std::is_same_v<PathChar, wchar_t>) {
 | 
			
		||||
    auto buf = basic_memory_buffer<wchar_t>();
 | 
			
		||||
    write_escaped_string<wchar_t>(std::back_inserter(buf), native);
 | 
			
		||||
    bool valid = to_utf8<wchar_t>::convert(quoted, {buf.data(), buf.size()});
 | 
			
		||||
    FMT_ASSERT(valid, "invalid utf16");
 | 
			
		||||
  } else if constexpr (std::is_same_v<Char, PathChar>) {
 | 
			
		||||
    write_escaped_string<std::filesystem::path::value_type>(
 | 
			
		||||
        std::back_inserter(quoted), native);
 | 
			
		||||
  } else {
 | 
			
		||||
    write_escaped_string<Char>(std::back_inserter(quoted), p.string<Char>());
 | 
			
		||||
  }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename Char> struct formatter<std::filesystem::path, Char> {
 | 
			
		||||
 private:
 | 
			
		||||
  format_specs<Char> specs_;
 | 
			
		||||
  detail::arg_ref<Char> width_ref_;
 | 
			
		||||
  bool debug_ = false;
 | 
			
		||||
  char path_type_ = 0;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  FMT_CONSTEXPR void set_debug_format(bool set = true) { debug_ = set; }
 | 
			
		||||
 | 
			
		||||
  template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
 | 
			
		||||
    auto it = ctx.begin(), end = ctx.end();
 | 
			
		||||
    if (it == end) return it;
 | 
			
		||||
 | 
			
		||||
    it = detail::parse_align(it, end, specs_);
 | 
			
		||||
    if (it == end) return it;
 | 
			
		||||
 | 
			
		||||
    it = detail::parse_dynamic_spec(it, end, specs_.width, width_ref_, ctx);
 | 
			
		||||
    if (it != end && *it == '?') {
 | 
			
		||||
      debug_ = true;
 | 
			
		||||
      ++it;
 | 
			
		||||
    }
 | 
			
		||||
    if (it != end && (*it == 'g')) path_type_ = *it++;
 | 
			
		||||
    return it;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::filesystem::path& p, FormatContext& ctx) const {
 | 
			
		||||
    auto specs = specs_;
 | 
			
		||||
#  ifdef _WIN32
 | 
			
		||||
    auto path_string = !path_type_ ? p.native() : p.generic_wstring();
 | 
			
		||||
#  else
 | 
			
		||||
    auto path_string = !path_type_ ? p.native() : p.generic_string();
 | 
			
		||||
#  endif
 | 
			
		||||
 | 
			
		||||
    detail::handle_dynamic_spec<detail::width_checker>(specs.width, width_ref_,
 | 
			
		||||
                                                       ctx);
 | 
			
		||||
    if (!debug_) {
 | 
			
		||||
      auto s = detail::get_path_string<Char>(p, path_string);
 | 
			
		||||
      return detail::write(ctx.out(), basic_string_view<Char>(s), specs);
 | 
			
		||||
    }
 | 
			
		||||
    auto quoted = basic_memory_buffer<Char>();
 | 
			
		||||
    detail::write_escaped_path(quoted, p, path_string);
 | 
			
		||||
    return detail::write(ctx.out(),
 | 
			
		||||
                         basic_string_view<Char>(quoted.data(), quoted.size()),
 | 
			
		||||
                         specs);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
#endif  // FMT_CPP_LIB_FILESYSTEM
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <std::size_t N, typename Char>
 | 
			
		||||
struct formatter<std::bitset<N>, Char> : nested_formatter<string_view> {
 | 
			
		||||
 private:
 | 
			
		||||
  // Functor because C++11 doesn't support generic lambdas.
 | 
			
		||||
  struct writer {
 | 
			
		||||
    const std::bitset<N>& bs;
 | 
			
		||||
 | 
			
		||||
    template <typename OutputIt>
 | 
			
		||||
    FMT_CONSTEXPR auto operator()(OutputIt out) -> OutputIt {
 | 
			
		||||
      for (auto pos = N; pos > 0; --pos) {
 | 
			
		||||
        out = detail::write<Char>(out, bs[pos - 1] ? Char('1') : Char('0'));
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      return out;
 | 
			
		||||
    }
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::bitset<N>& bs, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    return write_padded(ctx, writer{bs});
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename Char>
 | 
			
		||||
struct formatter<std::thread::id, Char> : basic_ostream_formatter<Char> {};
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#ifdef __cpp_lib_optional
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct formatter<std::optional<T>, Char,
 | 
			
		||||
                 std::enable_if_t<is_formattable<T, Char>::value>> {
 | 
			
		||||
 private:
 | 
			
		||||
  formatter<T, Char> underlying_;
 | 
			
		||||
  static constexpr basic_string_view<Char> optional =
 | 
			
		||||
      detail::string_literal<Char, 'o', 'p', 't', 'i', 'o', 'n', 'a', 'l',
 | 
			
		||||
                             '('>{};
 | 
			
		||||
  static constexpr basic_string_view<Char> none =
 | 
			
		||||
      detail::string_literal<Char, 'n', 'o', 'n', 'e'>{};
 | 
			
		||||
 | 
			
		||||
  template <class U>
 | 
			
		||||
  FMT_CONSTEXPR static auto maybe_set_debug_format(U& u, bool set)
 | 
			
		||||
      -> decltype(u.set_debug_format(set)) {
 | 
			
		||||
    u.set_debug_format(set);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <class U>
 | 
			
		||||
  FMT_CONSTEXPR static void maybe_set_debug_format(U&, ...) {}
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
 | 
			
		||||
    maybe_set_debug_format(underlying_, true);
 | 
			
		||||
    return underlying_.parse(ctx);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::optional<T>& opt, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    if (!opt) return detail::write<Char>(ctx.out(), none);
 | 
			
		||||
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
    out = detail::write<Char>(out, optional);
 | 
			
		||||
    ctx.advance_to(out);
 | 
			
		||||
    out = underlying_.format(*opt, ctx);
 | 
			
		||||
    return detail::write(out, ')');
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
#endif  // __cpp_lib_optional
 | 
			
		||||
 | 
			
		||||
#ifdef __cpp_lib_source_location
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <> struct formatter<std::source_location> {
 | 
			
		||||
  template <typename ParseContext> FMT_CONSTEXPR auto parse(ParseContext& ctx) {
 | 
			
		||||
    return ctx.begin();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::source_location& loc, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
    out = detail::write(out, loc.file_name());
 | 
			
		||||
    out = detail::write(out, ':');
 | 
			
		||||
    out = detail::write<char>(out, loc.line());
 | 
			
		||||
    out = detail::write(out, ':');
 | 
			
		||||
    out = detail::write<char>(out, loc.column());
 | 
			
		||||
    out = detail::write(out, ": ");
 | 
			
		||||
    out = detail::write(out, loc.function_name());
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#if FMT_CPP_LIB_VARIANT
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using variant_index_sequence =
 | 
			
		||||
    std::make_index_sequence<std::variant_size<T>::value>;
 | 
			
		||||
 | 
			
		||||
template <typename> struct is_variant_like_ : std::false_type {};
 | 
			
		||||
template <typename... Types>
 | 
			
		||||
struct is_variant_like_<std::variant<Types...>> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
// formattable element check.
 | 
			
		||||
template <typename T, typename C> class is_variant_formattable_ {
 | 
			
		||||
  template <std::size_t... Is>
 | 
			
		||||
  static std::conjunction<
 | 
			
		||||
      is_formattable<std::variant_alternative_t<Is, T>, C>...>
 | 
			
		||||
      check(std::index_sequence<Is...>);
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      decltype(check(variant_index_sequence<T>{}))::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename Char, typename OutputIt, typename T>
 | 
			
		||||
auto write_variant_alternative(OutputIt out, const T& v) -> OutputIt {
 | 
			
		||||
  if constexpr (is_string<T>::value)
 | 
			
		||||
    return write_escaped_string<Char>(out, detail::to_string_view(v));
 | 
			
		||||
  else if constexpr (std::is_same_v<T, Char>)
 | 
			
		||||
    return write_escaped_char(out, v);
 | 
			
		||||
  else
 | 
			
		||||
    return write<Char>(out, v);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
template <typename T> struct is_variant_like {
 | 
			
		||||
  static constexpr const bool value = detail::is_variant_like_<T>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
template <typename T, typename C> struct is_variant_formattable {
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      detail::is_variant_formattable_<T, C>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename Char> struct formatter<std::monostate, Char> {
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    return ctx.begin();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::monostate&, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    return detail::write<Char>(ctx.out(), "monostate");
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename Variant, typename Char>
 | 
			
		||||
struct formatter<
 | 
			
		||||
    Variant, Char,
 | 
			
		||||
    std::enable_if_t<std::conjunction_v<
 | 
			
		||||
        is_variant_like<Variant>, is_variant_formattable<Variant, Char>>>> {
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    return ctx.begin();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const Variant& value, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
 | 
			
		||||
    out = detail::write<Char>(out, "variant(");
 | 
			
		||||
    FMT_TRY {
 | 
			
		||||
      std::visit(
 | 
			
		||||
          [&](const auto& v) {
 | 
			
		||||
            out = detail::write_variant_alternative<Char>(out, v);
 | 
			
		||||
          },
 | 
			
		||||
          value);
 | 
			
		||||
    }
 | 
			
		||||
    FMT_CATCH(const std::bad_variant_access&) {
 | 
			
		||||
      detail::write<Char>(out, "valueless by exception");
 | 
			
		||||
    }
 | 
			
		||||
    *out++ = ')';
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
#endif  // FMT_CPP_LIB_VARIANT
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename Char> struct formatter<std::error_code, Char> {
 | 
			
		||||
  template <typename ParseContext>
 | 
			
		||||
  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
 | 
			
		||||
    return ctx.begin();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
    out = detail::write_bytes(out, ec.category().name(), format_specs<Char>());
 | 
			
		||||
    out = detail::write<Char>(out, Char(':'));
 | 
			
		||||
    out = detail::write<Char>(out, ec.value());
 | 
			
		||||
    return out;
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct formatter<
 | 
			
		||||
    T, Char,  // DEPRECATED! Mixing code unit types.
 | 
			
		||||
    typename std::enable_if<std::is_base_of<std::exception, T>::value>::type> {
 | 
			
		||||
 private:
 | 
			
		||||
  bool with_typename_ = false;
 | 
			
		||||
 | 
			
		||||
 public:
 | 
			
		||||
  FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx)
 | 
			
		||||
      -> decltype(ctx.begin()) {
 | 
			
		||||
    auto it = ctx.begin();
 | 
			
		||||
    auto end = ctx.end();
 | 
			
		||||
    if (it == end || *it == '}') return it;
 | 
			
		||||
    if (*it == 't') {
 | 
			
		||||
      ++it;
 | 
			
		||||
      with_typename_ = FMT_USE_TYPEID != 0;
 | 
			
		||||
    }
 | 
			
		||||
    return it;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  template <typename OutputIt>
 | 
			
		||||
  auto format(const std::exception& ex,
 | 
			
		||||
              basic_format_context<OutputIt, Char>& ctx) const -> OutputIt {
 | 
			
		||||
    format_specs<Char> spec;
 | 
			
		||||
    auto out = ctx.out();
 | 
			
		||||
    if (!with_typename_)
 | 
			
		||||
      return detail::write_bytes(out, string_view(ex.what()), spec);
 | 
			
		||||
 | 
			
		||||
#if FMT_USE_TYPEID
 | 
			
		||||
    const std::type_info& ti = typeid(ex);
 | 
			
		||||
#  ifdef FMT_HAS_ABI_CXA_DEMANGLE
 | 
			
		||||
    int status = 0;
 | 
			
		||||
    std::size_t size = 0;
 | 
			
		||||
    std::unique_ptr<char, void (*)(void*)> demangled_name_ptr(
 | 
			
		||||
        abi::__cxa_demangle(ti.name(), nullptr, &size, &status), &std::free);
 | 
			
		||||
 | 
			
		||||
    string_view demangled_name_view;
 | 
			
		||||
    if (demangled_name_ptr) {
 | 
			
		||||
      demangled_name_view = demangled_name_ptr.get();
 | 
			
		||||
 | 
			
		||||
      // Normalization of stdlib inline namespace names.
 | 
			
		||||
      // libc++ inline namespaces.
 | 
			
		||||
      //  std::__1::*       -> std::*
 | 
			
		||||
      //  std::__1::__fs::* -> std::*
 | 
			
		||||
      // libstdc++ inline namespaces.
 | 
			
		||||
      //  std::__cxx11::*             -> std::*
 | 
			
		||||
      //  std::filesystem::__cxx11::* -> std::filesystem::*
 | 
			
		||||
      if (demangled_name_view.starts_with("std::")) {
 | 
			
		||||
        char* begin = demangled_name_ptr.get();
 | 
			
		||||
        char* to = begin + 5;  // std::
 | 
			
		||||
        for (char *from = to, *end = begin + demangled_name_view.size();
 | 
			
		||||
             from < end;) {
 | 
			
		||||
          // This is safe, because demangled_name is NUL-terminated.
 | 
			
		||||
          if (from[0] == '_' && from[1] == '_') {
 | 
			
		||||
            char* next = from + 1;
 | 
			
		||||
            while (next < end && *next != ':') next++;
 | 
			
		||||
            if (next[0] == ':' && next[1] == ':') {
 | 
			
		||||
              from = next + 2;
 | 
			
		||||
              continue;
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
          *to++ = *from++;
 | 
			
		||||
        }
 | 
			
		||||
        demangled_name_view = {begin, detail::to_unsigned(to - begin)};
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
      demangled_name_view = string_view(ti.name());
 | 
			
		||||
    }
 | 
			
		||||
    out = detail::write_bytes(out, demangled_name_view, spec);
 | 
			
		||||
#  elif FMT_MSC_VERSION
 | 
			
		||||
    string_view demangled_name_view(ti.name());
 | 
			
		||||
    if (demangled_name_view.starts_with("class "))
 | 
			
		||||
      demangled_name_view.remove_prefix(6);
 | 
			
		||||
    else if (demangled_name_view.starts_with("struct "))
 | 
			
		||||
      demangled_name_view.remove_prefix(7);
 | 
			
		||||
    out = detail::write_bytes(out, demangled_name_view, spec);
 | 
			
		||||
#  else
 | 
			
		||||
    out = detail::write_bytes(out, string_view(ti.name()), spec);
 | 
			
		||||
#  endif
 | 
			
		||||
    *out++ = ':';
 | 
			
		||||
    *out++ = ' ';
 | 
			
		||||
    return detail::write_bytes(out, string_view(ex.what()), spec);
 | 
			
		||||
#endif
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename T, typename Enable = void>
 | 
			
		||||
struct has_flip : std::false_type {};
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
struct has_flip<T, void_t<decltype(std::declval<T>().flip())>>
 | 
			
		||||
    : std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename T> struct is_bit_reference_like {
 | 
			
		||||
  static constexpr const bool value =
 | 
			
		||||
      std::is_convertible<T, bool>::value &&
 | 
			
		||||
      std::is_nothrow_assignable<T, bool>::value && has_flip<T>::value;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef _LIBCPP_VERSION
 | 
			
		||||
 | 
			
		||||
// Workaround for libc++ incompatibility with C++ standard.
 | 
			
		||||
// According to the Standard, `bitset::operator[] const` returns bool.
 | 
			
		||||
template <typename C>
 | 
			
		||||
struct is_bit_reference_like<std::__bit_const_reference<C>> {
 | 
			
		||||
  static constexpr const bool value = true;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
// We can't use std::vector<bool, Allocator>::reference and
 | 
			
		||||
// std::bitset<N>::reference because the compiler can't deduce Allocator and N
 | 
			
		||||
// in partial specialization.
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename BitRef, typename Char>
 | 
			
		||||
struct formatter<BitRef, Char,
 | 
			
		||||
                 enable_if_t<detail::is_bit_reference_like<BitRef>::value>>
 | 
			
		||||
    : formatter<bool, Char> {
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  FMT_CONSTEXPR auto format(const BitRef& v, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    return formatter<bool, Char>::format(v, ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename T, typename Char>
 | 
			
		||||
struct formatter<std::atomic<T>, Char,
 | 
			
		||||
                 enable_if_t<is_formattable<T, Char>::value>>
 | 
			
		||||
    : formatter<T, Char> {
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::atomic<T>& v, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    return formatter<T, Char>::format(v.load(), ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#ifdef __cpp_lib_atomic_flag_test
 | 
			
		||||
FMT_EXPORT
 | 
			
		||||
template <typename Char>
 | 
			
		||||
struct formatter<std::atomic_flag, Char> : formatter<bool, Char> {
 | 
			
		||||
  template <typename FormatContext>
 | 
			
		||||
  auto format(const std::atomic_flag& v, FormatContext& ctx) const
 | 
			
		||||
      -> decltype(ctx.out()) {
 | 
			
		||||
    return formatter<bool, Char>::format(v.test(), ctx);
 | 
			
		||||
  }
 | 
			
		||||
};
 | 
			
		||||
#endif  // __cpp_lib_atomic_flag_test
 | 
			
		||||
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
#endif  // FMT_STD_H_
 | 
			
		||||
							
								
								
									
										259
									
								
								3rd/fmt/xchar.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										259
									
								
								3rd/fmt/xchar.h
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,259 @@
 | 
			
		||||
// Formatting library for C++ - optional wchar_t and exotic character support
 | 
			
		||||
//
 | 
			
		||||
// Copyright (c) 2012 - present, Victor Zverovich
 | 
			
		||||
// All rights reserved.
 | 
			
		||||
//
 | 
			
		||||
// For the license information refer to format.h.
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_XCHAR_H_
 | 
			
		||||
#define FMT_XCHAR_H_
 | 
			
		||||
 | 
			
		||||
#include <cwchar>
 | 
			
		||||
 | 
			
		||||
#include "format.h"
 | 
			
		||||
 | 
			
		||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
 | 
			
		||||
#  include <locale>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_NAMESPACE
 | 
			
		||||
namespace detail {
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
using is_exotic_char = bool_constant<!std::is_same<T, char>::value>;
 | 
			
		||||
 | 
			
		||||
inline auto write_loc(std::back_insert_iterator<detail::buffer<wchar_t>> out,
 | 
			
		||||
                      loc_value value, const format_specs<wchar_t>& specs,
 | 
			
		||||
                      locale_ref loc) -> bool {
 | 
			
		||||
#ifndef FMT_STATIC_THOUSANDS_SEPARATOR
 | 
			
		||||
  auto& numpunct =
 | 
			
		||||
      std::use_facet<std::numpunct<wchar_t>>(loc.get<std::locale>());
 | 
			
		||||
  auto separator = std::wstring();
 | 
			
		||||
  auto grouping = numpunct.grouping();
 | 
			
		||||
  if (!grouping.empty()) separator = std::wstring(1, numpunct.thousands_sep());
 | 
			
		||||
  return value.visit(loc_writer<wchar_t>{out, specs, separator, grouping, {}});
 | 
			
		||||
#endif
 | 
			
		||||
  return false;
 | 
			
		||||
}
 | 
			
		||||
}  // namespace detail
 | 
			
		||||
 | 
			
		||||
FMT_BEGIN_EXPORT
 | 
			
		||||
 | 
			
		||||
using wstring_view = basic_string_view<wchar_t>;
 | 
			
		||||
using wformat_parse_context = basic_format_parse_context<wchar_t>;
 | 
			
		||||
using wformat_context = buffer_context<wchar_t>;
 | 
			
		||||
using wformat_args = basic_format_args<wformat_context>;
 | 
			
		||||
using wmemory_buffer = basic_memory_buffer<wchar_t>;
 | 
			
		||||
 | 
			
		||||
#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
 | 
			
		||||
// Workaround broken conversion on older gcc.
 | 
			
		||||
template <typename... Args> using wformat_string = wstring_view;
 | 
			
		||||
inline auto runtime(wstring_view s) -> wstring_view { return s; }
 | 
			
		||||
#else
 | 
			
		||||
template <typename... Args>
 | 
			
		||||
using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>;
 | 
			
		||||
inline auto runtime(wstring_view s) -> runtime_format_string<wchar_t> {
 | 
			
		||||
  return {{s}};
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
template <> struct is_char<wchar_t> : std::true_type {};
 | 
			
		||||
template <> struct is_char<detail::char8_type> : std::true_type {};
 | 
			
		||||
template <> struct is_char<char16_t> : std::true_type {};
 | 
			
		||||
template <> struct is_char<char32_t> : std::true_type {};
 | 
			
		||||
 | 
			
		||||
template <typename... T>
 | 
			
		||||
constexpr auto make_wformat_args(const T&... args)
 | 
			
		||||
    -> format_arg_store<wformat_context, T...> {
 | 
			
		||||
  return {args...};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline namespace literals {
 | 
			
		||||
#if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_ARGS
 | 
			
		||||
constexpr auto operator""_a(const wchar_t* s, size_t)
 | 
			
		||||
    -> detail::udl_arg<wchar_t> {
 | 
			
		||||
  return {s};
 | 
			
		||||
}
 | 
			
		||||
#endif
 | 
			
		||||
}  // namespace literals
 | 
			
		||||
 | 
			
		||||
template <typename It, typename Sentinel>
 | 
			
		||||
auto join(It begin, Sentinel end, wstring_view sep)
 | 
			
		||||
    -> join_view<It, Sentinel, wchar_t> {
 | 
			
		||||
  return {begin, end, sep};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Range>
 | 
			
		||||
auto join(Range&& range, wstring_view sep)
 | 
			
		||||
    -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>,
 | 
			
		||||
                 wchar_t> {
 | 
			
		||||
  return join(std::begin(range), std::end(range), sep);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename T>
 | 
			
		||||
auto join(std::initializer_list<T> list, wstring_view sep)
 | 
			
		||||
    -> join_view<const T*, const T*, wchar_t> {
 | 
			
		||||
  return join(std::begin(list), std::end(list), sep);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
 | 
			
		||||
auto vformat(basic_string_view<Char> format_str,
 | 
			
		||||
             basic_format_args<buffer_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> std::basic_string<Char> {
 | 
			
		||||
  auto buf = basic_memory_buffer<Char>();
 | 
			
		||||
  detail::vformat_to(buf, format_str, args);
 | 
			
		||||
  return to_string(buf);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... T>
 | 
			
		||||
auto format(wformat_string<T...> fmt, T&&... args) -> std::wstring {
 | 
			
		||||
  return vformat(fmt::wstring_view(fmt), fmt::make_wformat_args(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// 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... T, typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(!std::is_same<Char, char>::value &&
 | 
			
		||||
                        !std::is_same<Char, wchar_t>::value)>
 | 
			
		||||
auto format(const S& format_str, T&&... args) -> std::basic_string<Char> {
 | 
			
		||||
  return vformat(detail::to_string_view(format_str),
 | 
			
		||||
                 fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Locale, typename S, typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
 | 
			
		||||
                            detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto vformat(
 | 
			
		||||
    const Locale& loc, const S& format_str,
 | 
			
		||||
    basic_format_args<buffer_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> std::basic_string<Char> {
 | 
			
		||||
  return detail::vformat(loc, detail::to_string_view(format_str), args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Locale, typename S, typename... T, typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_locale<Locale>::value&&
 | 
			
		||||
                            detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto format(const Locale& loc, const S& format_str, T&&... args)
 | 
			
		||||
    -> std::basic_string<Char> {
 | 
			
		||||
  return detail::vformat(loc, detail::to_string_view(format_str),
 | 
			
		||||
                         fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename S, typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
 | 
			
		||||
                            detail::is_exotic_char<Char>::value)>
 | 
			
		||||
auto vformat_to(OutputIt out, const S& format_str,
 | 
			
		||||
                basic_format_args<buffer_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> OutputIt {
 | 
			
		||||
  auto&& buf = detail::get_buffer<Char>(out);
 | 
			
		||||
  detail::vformat_to(buf, detail::to_string_view(format_str), args);
 | 
			
		||||
  return detail::get_iterator(buf, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename S, typename... T,
 | 
			
		||||
          typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
 | 
			
		||||
                            detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto format_to(OutputIt out, const S& fmt, T&&... args) -> OutputIt {
 | 
			
		||||
  return vformat_to(out, detail::to_string_view(fmt),
 | 
			
		||||
                    fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename Locale, typename S, typename OutputIt, typename... Args,
 | 
			
		||||
          typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
 | 
			
		||||
                            detail::is_locale<Locale>::value&&
 | 
			
		||||
                                detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto vformat_to(
 | 
			
		||||
    OutputIt out, const Locale& loc, const S& format_str,
 | 
			
		||||
    basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt {
 | 
			
		||||
  auto&& buf = detail::get_buffer<Char>(out);
 | 
			
		||||
  vformat_to(buf, detail::to_string_view(format_str), args,
 | 
			
		||||
             detail::locale_ref(loc));
 | 
			
		||||
  return detail::get_iterator(buf, out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename Locale, typename S, typename... T,
 | 
			
		||||
          typename Char = char_t<S>,
 | 
			
		||||
          bool enable = detail::is_output_iterator<OutputIt, Char>::value &&
 | 
			
		||||
                        detail::is_locale<Locale>::value &&
 | 
			
		||||
                        detail::is_exotic_char<Char>::value>
 | 
			
		||||
inline auto format_to(OutputIt out, const Locale& loc, const S& format_str,
 | 
			
		||||
                      T&&... args) ->
 | 
			
		||||
    typename std::enable_if<enable, OutputIt>::type {
 | 
			
		||||
  return vformat_to(out, loc, detail::to_string_view(format_str),
 | 
			
		||||
                    fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename Char, typename... Args,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
 | 
			
		||||
                            detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto vformat_to_n(
 | 
			
		||||
    OutputIt out, size_t n, basic_string_view<Char> format_str,
 | 
			
		||||
    basic_format_args<buffer_context<type_identity_t<Char>>> args)
 | 
			
		||||
    -> format_to_n_result<OutputIt> {
 | 
			
		||||
  using traits = detail::fixed_buffer_traits;
 | 
			
		||||
  auto buf = detail::iterator_buffer<OutputIt, Char, traits>(out, n);
 | 
			
		||||
  detail::vformat_to(buf, format_str, args);
 | 
			
		||||
  return {buf.out(), buf.count()};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename OutputIt, typename S, typename... T,
 | 
			
		||||
          typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&&
 | 
			
		||||
                            detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto format_to_n(OutputIt out, size_t n, const S& fmt, T&&... args)
 | 
			
		||||
    -> format_to_n_result<OutputIt> {
 | 
			
		||||
  return vformat_to_n(out, n, detail::to_string_view(fmt),
 | 
			
		||||
                      fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename S, typename... T, typename Char = char_t<S>,
 | 
			
		||||
          FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)>
 | 
			
		||||
inline auto formatted_size(const S& fmt, T&&... args) -> size_t {
 | 
			
		||||
  auto buf = detail::counting_buffer<Char>();
 | 
			
		||||
  detail::vformat_to(buf, detail::to_string_view(fmt),
 | 
			
		||||
                     fmt::make_format_args<buffer_context<Char>>(args...));
 | 
			
		||||
  return buf.count();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) {
 | 
			
		||||
  auto buf = wmemory_buffer();
 | 
			
		||||
  detail::vformat_to(buf, fmt, args);
 | 
			
		||||
  buf.push_back(L'\0');
 | 
			
		||||
  if (std::fputws(buf.data(), f) == -1)
 | 
			
		||||
    FMT_THROW(system_error(errno, FMT_STRING("cannot write to file")));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
inline void vprint(wstring_view fmt, wformat_args args) {
 | 
			
		||||
  vprint(stdout, fmt, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... T>
 | 
			
		||||
void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
 | 
			
		||||
  return vprint(f, wstring_view(fmt), fmt::make_wformat_args(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... T> void print(wformat_string<T...> fmt, T&&... args) {
 | 
			
		||||
  return vprint(wstring_view(fmt), fmt::make_wformat_args(args...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... T>
 | 
			
		||||
void println(std::FILE* f, wformat_string<T...> fmt, T&&... args) {
 | 
			
		||||
  return print(f, L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
template <typename... T> void println(wformat_string<T...> fmt, T&&... args) {
 | 
			
		||||
  return print(L"{}\n", fmt::format(fmt, std::forward<T>(args)...));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
  Converts *value* to ``std::wstring`` using the default format for type *T*.
 | 
			
		||||
 */
 | 
			
		||||
template <typename T> inline auto to_wstring(const T& value) -> std::wstring {
 | 
			
		||||
  return format(FMT_STRING(L"{}"), value);
 | 
			
		||||
}
 | 
			
		||||
FMT_END_EXPORT
 | 
			
		||||
FMT_END_NAMESPACE
 | 
			
		||||
 | 
			
		||||
#endif  // FMT_XCHAR_H_
 | 
			
		||||
@ -1,7 +1,7 @@
 | 
			
		||||
cmake_minimum_required(VERSION 3.5)
 | 
			
		||||
 | 
			
		||||
project(codecreate LANGUAGES CXX)
 | 
			
		||||
set(CMAKE_CXX_STANDARD 20)
 | 
			
		||||
set(CMAKE_CXX_STANDARD 17)
 | 
			
		||||
set(CMAKE_CXX_STANDARD_REQUIRED ON)
 | 
			
		||||
 | 
			
		||||
if (MSVC)
 | 
			
		||||
@ -19,8 +19,10 @@ message(STATUS "Compiler CXX ID: ${CMAKE_CXX_COMPILER_ID}")
 | 
			
		||||
 | 
			
		||||
include_directories(3rd)
 | 
			
		||||
 | 
			
		||||
add_definitions(-DFMT_HEADER_ONLY)
 | 
			
		||||
 | 
			
		||||
set(PROJECT_SOURCES
 | 
			
		||||
    main.cpp src/pub.cpp src/pub.h
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
add_executable(codecreate ${PROJECT_SOURCES})
 | 
			
		||||
add_executable(cct ${PROJECT_SOURCES})
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										68
									
								
								main.cpp
									
									
									
									
									
								
							
							
						
						
									
										68
									
								
								main.cpp
									
									
									
									
									
								
							@ -1,7 +1,7 @@
 | 
			
		||||
#include "src/pub.h"
 | 
			
		||||
#include <CLI11.hpp>
 | 
			
		||||
#include <filesystem>
 | 
			
		||||
#include <format>
 | 
			
		||||
#include <fmt/format.h>
 | 
			
		||||
#include <fstream>
 | 
			
		||||
#include <iostream>
 | 
			
		||||
#include <list>
 | 
			
		||||
@ -106,12 +106,12 @@ bool copy_dir(const std::string& source_dir, const std::string& des_dir, bool ad
 | 
			
		||||
bool create_base()
 | 
			
		||||
{
 | 
			
		||||
    if (gParam.name.empty()) {
 | 
			
		||||
        std::cout << std::format("project name is empty.") << std::endl;
 | 
			
		||||
        std::cout << fmt::format("project name is empty.") << std::endl;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!fs::exists(gParam.des_path)) {
 | 
			
		||||
        std::cout << std::format("{} is not exit.", gParam.des_path) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("{} is not exit.", gParam.des_path) << std::endl;
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -119,15 +119,15 @@ bool create_base()
 | 
			
		||||
    gParam.des_dir = des_dir.append(gParam.name).string();
 | 
			
		||||
 | 
			
		||||
    if (fs::exists(des_dir)) {
 | 
			
		||||
        std::cout << std::format("{} is already exist.", des_dir.string()) << "\n";
 | 
			
		||||
        std::cout << fmt::format("{} is already exist.", des_dir.string()) << "\n";
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!fs::create_directory(des_dir)) {
 | 
			
		||||
        std::cout << std::format("{} create failed.", des_dir.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("{} create failed.", des_dir.string()) << std::endl;
 | 
			
		||||
        return false;
 | 
			
		||||
    } else {
 | 
			
		||||
        std::cout << std::format("{} create success.", des_dir.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("{} create success.", des_dir.string()) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fs::path point_code_dir(des_dir);
 | 
			
		||||
@ -135,9 +135,9 @@ bool create_base()
 | 
			
		||||
 | 
			
		||||
    if (!fs::exists(point_code_dir)) {
 | 
			
		||||
        if (fs::create_directory(point_code_dir)) {
 | 
			
		||||
            std::cout << std::format("{} create success.", point_code_dir.string()) << std::endl;
 | 
			
		||||
            std::cout << fmt::format("{} create success.", point_code_dir.string()) << std::endl;
 | 
			
		||||
        } else {
 | 
			
		||||
            std::cout << std::format("{} create failed.", point_code_dir.string()) << std::endl;
 | 
			
		||||
            std::cout << fmt::format("{} create failed.", point_code_dir.string()) << std::endl;
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
@ -152,19 +152,19 @@ bool create_base()
 | 
			
		||||
    source_settings.append(".vscode").append("settings.json");
 | 
			
		||||
    clang_format.append("template").append(".clang-format");
 | 
			
		||||
 | 
			
		||||
    std::cout << std::format("source settings is: {}", source_settings.string()) << std::endl;
 | 
			
		||||
    std::cout << std::format("clang_format is: {}", clang_format.string()) << std::endl;
 | 
			
		||||
    std::cout << fmt::format("source settings is: {}", source_settings.string()) << std::endl;
 | 
			
		||||
    std::cout << fmt::format("clang_format is: {}", clang_format.string()) << std::endl;
 | 
			
		||||
 | 
			
		||||
    if (fs::copy_file(source_settings, settings_file)) {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", settings_file.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", settings_file.string()) << std::endl;
 | 
			
		||||
    } else {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", settings_file.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", settings_file.string()) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fs::copy_file(clang_format, clang_file)) {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", clang_format.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", clang_format.string()) << std::endl;
 | 
			
		||||
    } else {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", clang_format.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", clang_format.string()) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return true;
 | 
			
		||||
@ -181,7 +181,7 @@ bool copy_console()
 | 
			
		||||
 | 
			
		||||
    std::string str_content;
 | 
			
		||||
    if (!CUtil::read_txt(cmakelist.string(), str_content)) {
 | 
			
		||||
        std::cout << std::format("can't open file {}", cmakelist.string());
 | 
			
		||||
        std::cout << fmt::format("can't open file {}", cmakelist.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -189,7 +189,7 @@ bool copy_console()
 | 
			
		||||
    std::string ncontent = CUtil::replace(str_content, rep, gParam.name);
 | 
			
		||||
 | 
			
		||||
    if (!CUtil::save_txt(cmakelist.string(), ncontent)) {
 | 
			
		||||
        std::cout << std::format("can't write file {}", cmakelist.string());
 | 
			
		||||
        std::cout << fmt::format("can't write file {}", cmakelist.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -207,7 +207,7 @@ bool copy_qt_widget()
 | 
			
		||||
 | 
			
		||||
    std::string str_content;
 | 
			
		||||
    if (!CUtil::read_txt(cmakelist.string(), str_content)) {
 | 
			
		||||
        std::cout << std::format("can't open file {}", cmakelist.string());
 | 
			
		||||
        std::cout << fmt::format("can't open file {}", cmakelist.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -217,7 +217,7 @@ bool copy_qt_widget()
 | 
			
		||||
    ncontent = CUtil::replace(ncontent, rep2, gParam.name);
 | 
			
		||||
 | 
			
		||||
    if (!CUtil::save_txt(cmakelist.string(), ncontent)) {
 | 
			
		||||
        std::cout << std::format("can't write file {}", cmakelist.string());
 | 
			
		||||
        std::cout << fmt::format("can't write file {}", cmakelist.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -226,7 +226,7 @@ bool copy_qt_widget()
 | 
			
		||||
 | 
			
		||||
    std::string settings_content;
 | 
			
		||||
    if (!CUtil::read_txt(settings.string(), settings_content)) {
 | 
			
		||||
        std::cout << std::format("can't open file {}", settings.string());
 | 
			
		||||
        std::cout << fmt::format("can't open file {}", settings.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -235,7 +235,7 @@ bool copy_qt_widget()
 | 
			
		||||
    settings_content = CUtil::replace(settings_content, from, to);
 | 
			
		||||
 | 
			
		||||
    if (!CUtil::save_txt(settings.string(), settings_content)) {
 | 
			
		||||
        std::cout << std::format("can't write file {}", settings.string());
 | 
			
		||||
        std::cout << fmt::format("can't write file {}", settings.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -256,13 +256,13 @@ bool copy_qt_console()
 | 
			
		||||
    save_main.append("main.cpp");
 | 
			
		||||
 | 
			
		||||
    if (!fs::copy_file(main_file, save_main)) {
 | 
			
		||||
        std::cout << std::format("can't copy main file {}", main_file.string());
 | 
			
		||||
        std::cout << fmt::format("can't copy main file {}", main_file.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string str_content;
 | 
			
		||||
    if (!CUtil::read_txt(cmakelist.string(), str_content)) {
 | 
			
		||||
        std::cout << std::format("can't open file {}", cmakelist.string());
 | 
			
		||||
        std::cout << fmt::format("can't open file {}", cmakelist.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -275,7 +275,7 @@ bool copy_qt_console()
 | 
			
		||||
    save_cmake.append("CMakeLists.txt");
 | 
			
		||||
 | 
			
		||||
    if (!CUtil::save_txt(save_cmake.string(), ncontent)) {
 | 
			
		||||
        std::cout << std::format("can't write file {}", save_cmake.string());
 | 
			
		||||
        std::cout << fmt::format("can't write file {}", save_cmake.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -284,7 +284,7 @@ bool copy_qt_console()
 | 
			
		||||
 | 
			
		||||
    std::string settings_content;
 | 
			
		||||
    if (!CUtil::read_txt(settings.string(), settings_content)) {
 | 
			
		||||
        std::cout << std::format("can't open file {}", settings.string());
 | 
			
		||||
        std::cout << fmt::format("can't open file {}", settings.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -293,7 +293,7 @@ bool copy_qt_console()
 | 
			
		||||
    settings_content = CUtil::replace(settings_content, from, to);
 | 
			
		||||
 | 
			
		||||
    if (!CUtil::save_txt(settings.string(), settings_content)) {
 | 
			
		||||
        std::cout << std::format("can't write file {}", settings.string());
 | 
			
		||||
        std::cout << fmt::format("can't write file {}", settings.string());
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -323,15 +323,15 @@ bool handle_gdb_qtprinter()
 | 
			
		||||
    des_qt6_file.append("qt6.natvis");
 | 
			
		||||
 | 
			
		||||
    if (fs::copy_file(qt5_file, des_qt5_file)) {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", des_qt5_file.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", des_qt5_file.string()) << std::endl;
 | 
			
		||||
    } else {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", des_qt5_file.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", des_qt5_file.string()) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (fs::copy_file(qt6_file, des_qt6_file)) {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", des_qt6_file.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", des_qt6_file.string()) << std::endl;
 | 
			
		||||
    } else {
 | 
			
		||||
        std::cout << std::format("copy to {} success.", des_qt6_file.string()) << std::endl;
 | 
			
		||||
        std::cout << fmt::format("copy to {} success.", des_qt6_file.string()) << std::endl;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
@ -349,9 +349,9 @@ bool handle_gdb_qtprinter()
 | 
			
		||||
 | 
			
		||||
    if (!fs::exists(gdb_des)) {
 | 
			
		||||
        if (fs::copy_file(gdb_source, gdb_des)) {
 | 
			
		||||
            std::cout << std::format("copy to {} success.", gdb_des.string()) << std::endl;
 | 
			
		||||
            std::cout << fmt::format("copy to {} success.", gdb_des.string()) << std::endl;
 | 
			
		||||
        } else {
 | 
			
		||||
            std::cout << std::format("copy to {} success.", gdb_des.string()) << std::endl;
 | 
			
		||||
            std::cout << fmt::format("copy to {} success.", gdb_des.string()) << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@ -383,12 +383,12 @@ int main(int argc, char** argv)
 | 
			
		||||
    std::cout << "Debug Mode." << std::endl;
 | 
			
		||||
    fs::path exe_path(CUtil::get_exe_path());
 | 
			
		||||
    gParam.exe_dir = exe_path.parent_path().parent_path().string();
 | 
			
		||||
    std::cout << std::format("current_path is: {}", gParam.exe_dir) << "\n";
 | 
			
		||||
    std::cout << fmt::format("current_path is: {}", gParam.exe_dir) << "\n";
 | 
			
		||||
#else
 | 
			
		||||
    std::cout << "Release Mode." << std::endl;
 | 
			
		||||
    fs::path exe_path(CUtil::get_exe_path());
 | 
			
		||||
    gParam.exe_dir = exe_path.parent_path().string();
 | 
			
		||||
    std::cout << std::format("current_path is: {}", gParam.exe_dir) << "\n";
 | 
			
		||||
    std::cout << fmt::format("current_path is: {}", gParam.exe_dir) << "\n";
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -430,7 +430,7 @@ int main(int argc, char** argv)
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    default:
 | 
			
		||||
        std::cout << std::format("{} is not support.", static_cast<int>(gParam.type)) << "\n";
 | 
			
		||||
        std::cout << fmt::format("{} is not support.", static_cast<int>(gParam.type)) << "\n";
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user