update and change how we build with spdlog
This commit is contained in:
		| @@ -31,8 +31,7 @@ public: | ||||
|     bytes_range(It range_begin, It range_end) | ||||
|         : begin_(range_begin) | ||||
|         , end_(range_end) | ||||
|     { | ||||
|     } | ||||
|     {} | ||||
|  | ||||
|     It begin() const | ||||
|     { | ||||
| @@ -117,7 +116,11 @@ struct formatter<spdlog::details::bytes_range<T>> | ||||
|  | ||||
|         std::size_t pos = 0; | ||||
|         std::size_t column = line_size; | ||||
| #if FMT_VERSION < 60000 | ||||
|         auto inserter = ctx.begin(); | ||||
| #else | ||||
|         auto inserter = ctx.out(); | ||||
| #endif | ||||
|  | ||||
|         for (auto &item : the_range) | ||||
|         { | ||||
|   | ||||
| @@ -1,23 +1,27 @@ | ||||
| Copyright (c) 2012 - 2016, Victor Zverovich | ||||
| Copyright (c) 2012 - present, Victor Zverovich | ||||
|  | ||||
| All rights reserved. | ||||
| Permission is hereby granted, free of charge, to any person obtaining | ||||
| a copy of this software and associated documentation files (the | ||||
| "Software"), to deal in the Software without restriction, including | ||||
| without limitation the rights to use, copy, modify, merge, publish, | ||||
| distribute, sublicense, and/or sell copies of the Software, and to | ||||
| permit persons to whom the Software is furnished to do so, subject to | ||||
| the following conditions: | ||||
|  | ||||
| Redistribution and use in source and binary forms, with or without | ||||
| modification, are permitted provided that the following conditions are met: | ||||
| The above copyright notice and this permission notice shall be | ||||
| included in all copies or substantial portions of the Software. | ||||
|  | ||||
| 1. Redistributions of source code must retain the above copyright notice, this | ||||
|    list of conditions and the following disclaimer. | ||||
| 2. Redistributions in binary form must reproduce the above copyright notice, | ||||
|    this list of conditions and the following disclaimer in the documentation | ||||
|    and/or other materials provided with the distribution. | ||||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, | ||||
| EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF | ||||
| MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND | ||||
| NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE | ||||
| LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION | ||||
| OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION | ||||
| WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||||
|  | ||||
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | ||||
| ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED | ||||
| WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | ||||
| DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR | ||||
| ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | ||||
| (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; | ||||
| LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND | ||||
| ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||||
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | ||||
| SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||||
| --- Optional exception to the license --- | ||||
|  | ||||
| As an exception, if, as a result of your compiling your source code, portions | ||||
| of this Software are embedded into a machine-executable object form of such | ||||
| source code, you may redistribute such embedded portions in such object form | ||||
| without including the above copyright and permission notices. | ||||
|   | ||||
| @@ -16,9 +16,181 @@ | ||||
| #include <locale> | ||||
| #include <sstream> | ||||
|  | ||||
| // enable safe chrono durations, unless explicitly disabled | ||||
| #ifndef FMT_SAFE_DURATION_CAST | ||||
| #  define FMT_SAFE_DURATION_CAST 1 | ||||
| #endif | ||||
|  | ||||
| #if FMT_SAFE_DURATION_CAST | ||||
| #  include "safe-duration-cast.h" | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| namespace internal{ | ||||
| // Prevents expansion of a preceding token as a function-style macro. | ||||
| // Usage: f FMT_NOMACRO() | ||||
| #define FMT_NOMACRO | ||||
|  | ||||
| namespace internal { | ||||
| inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); } | ||||
| inline null<> localtime_s(...) { return null<>(); } | ||||
| inline null<> gmtime_r(...) { return null<>(); } | ||||
| inline null<> gmtime_s(...) { return null<>(); } | ||||
| }  // namespace internal | ||||
|  | ||||
| // Thread-safe replacement for std::localtime | ||||
| inline std::tm localtime(std::time_t time) { | ||||
|   struct dispatcher { | ||||
|     std::time_t time_; | ||||
|     std::tm tm_; | ||||
|  | ||||
|     dispatcher(std::time_t t) : time_(t) {} | ||||
|  | ||||
|     bool run() { | ||||
|       using namespace fmt::internal; | ||||
|       return handle(localtime_r(&time_, &tm_)); | ||||
|     } | ||||
|  | ||||
|     bool handle(std::tm* tm) { return tm != nullptr; } | ||||
|  | ||||
|     bool handle(internal::null<>) { | ||||
|       using namespace fmt::internal; | ||||
|       return fallback(localtime_s(&tm_, &time_)); | ||||
|     } | ||||
|  | ||||
|     bool fallback(int res) { return res == 0; } | ||||
|  | ||||
| #if !FMT_MSC_VER | ||||
|     bool fallback(internal::null<>) { | ||||
|       using namespace fmt::internal; | ||||
|       std::tm* tm = std::localtime(&time_); | ||||
|       if (tm) tm_ = *tm; | ||||
|       return tm != nullptr; | ||||
|     } | ||||
| #endif | ||||
|   }; | ||||
|   dispatcher lt(time); | ||||
|   // Too big time values may be unsupported. | ||||
|   if (!lt.run()) FMT_THROW(format_error("time_t value out of range")); | ||||
|   return lt.tm_; | ||||
| } | ||||
|  | ||||
| // Thread-safe replacement for std::gmtime | ||||
| inline std::tm gmtime(std::time_t time) { | ||||
|   struct dispatcher { | ||||
|     std::time_t time_; | ||||
|     std::tm tm_; | ||||
|  | ||||
|     dispatcher(std::time_t t) : time_(t) {} | ||||
|  | ||||
|     bool run() { | ||||
|       using namespace fmt::internal; | ||||
|       return handle(gmtime_r(&time_, &tm_)); | ||||
|     } | ||||
|  | ||||
|     bool handle(std::tm* tm) { return tm != nullptr; } | ||||
|  | ||||
|     bool handle(internal::null<>) { | ||||
|       using namespace fmt::internal; | ||||
|       return fallback(gmtime_s(&tm_, &time_)); | ||||
|     } | ||||
|  | ||||
|     bool fallback(int res) { return res == 0; } | ||||
|  | ||||
| #if !FMT_MSC_VER | ||||
|     bool fallback(internal::null<>) { | ||||
|       std::tm* tm = std::gmtime(&time_); | ||||
|       if (tm) tm_ = *tm; | ||||
|       return tm != nullptr; | ||||
|     } | ||||
| #endif | ||||
|   }; | ||||
|   dispatcher gt(time); | ||||
|   // Too big time values may be unsupported. | ||||
|   if (!gt.run()) FMT_THROW(format_error("time_t value out of range")); | ||||
|   return gt.tm_; | ||||
| } | ||||
|  | ||||
| namespace internal { | ||||
| inline std::size_t strftime(char* str, std::size_t count, const char* format, | ||||
|                             const std::tm* time) { | ||||
|   return std::strftime(str, count, format, time); | ||||
| } | ||||
|  | ||||
| inline std::size_t strftime(wchar_t* str, std::size_t count, | ||||
|                             const wchar_t* format, const std::tm* time) { | ||||
|   return std::wcsftime(str, count, format, time); | ||||
| } | ||||
| }  // namespace internal | ||||
|  | ||||
| template <typename Char> struct formatter<std::tm, Char> { | ||||
|   template <typename ParseContext> | ||||
|   auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     auto it = ctx.begin(); | ||||
|     if (it != ctx.end() && *it == ':') ++it; | ||||
|     auto end = it; | ||||
|     while (end != ctx.end() && *end != '}') ++end; | ||||
|     tm_format.reserve(internal::to_unsigned(end - it + 1)); | ||||
|     tm_format.append(it, end); | ||||
|     tm_format.push_back('\0'); | ||||
|     return end; | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(const std::tm& tm, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|     basic_memory_buffer<Char> buf; | ||||
|     std::size_t start = buf.size(); | ||||
|     for (;;) { | ||||
|       std::size_t size = buf.capacity() - start; | ||||
|       std::size_t count = | ||||
|           internal::strftime(&buf[start], size, &tm_format[0], &tm); | ||||
|       if (count != 0) { | ||||
|         buf.resize(start + count); | ||||
|         break; | ||||
|       } | ||||
|       if (size >= tm_format.size() * 256) { | ||||
|         // If the buffer is 256 times larger than the format string, assume | ||||
|         // that `strftime` gives an empty result. There doesn't seem to be a | ||||
|         // better way to distinguish the two cases: | ||||
|         // https://github.com/fmtlib/fmt/issues/367 | ||||
|         break; | ||||
|       } | ||||
|       const std::size_t MIN_GROWTH = 10; | ||||
|       buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); | ||||
|     } | ||||
|     return std::copy(buf.begin(), buf.end(), ctx.out()); | ||||
|   } | ||||
|  | ||||
|   basic_memory_buffer<Char> tm_format; | ||||
| }; | ||||
|  | ||||
| namespace internal { | ||||
| template <typename Period> FMT_CONSTEXPR const char* get_units() { | ||||
|   return nullptr; | ||||
| } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::atto>() { return "as"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::femto>() { return "fs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::pico>() { return "ps"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::nano>() { return "ns"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::micro>() { return "µs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::milli>() { return "ms"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::centi>() { return "cs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::deci>() { return "ds"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::ratio<1>>() { return "s"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::deca>() { return "das"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::hecto>() { return "hs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::kilo>() { return "ks"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::mega>() { return "Ms"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::giga>() { return "Gs"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::tera>() { return "Ts"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::peta>() { return "Ps"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::exa>() { return "Es"; } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::ratio<60>>() { | ||||
|   return "m"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR const char* get_units<std::ratio<3600>>() { | ||||
|   return "h"; | ||||
| } | ||||
|  | ||||
| enum class numeric_system { | ||||
|   standard, | ||||
| @@ -28,8 +200,9 @@ enum class numeric_system { | ||||
|  | ||||
| // Parses a put_time-like format string and invokes handler actions. | ||||
| template <typename Char, typename Handler> | ||||
| FMT_CONSTEXPR const Char *parse_chrono_format( | ||||
|     const Char *begin, const Char *end, Handler &&handler) { | ||||
| FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin, | ||||
|                                               const Char* end, | ||||
|                                               Handler&& handler) { | ||||
|   auto ptr = begin; | ||||
|   while (ptr != end) { | ||||
|     auto c = *ptr; | ||||
| @@ -38,11 +211,9 @@ FMT_CONSTEXPR const Char *parse_chrono_format( | ||||
|       ++ptr; | ||||
|       continue; | ||||
|     } | ||||
|     if (begin != ptr) | ||||
|       handler.on_text(begin, ptr); | ||||
|     ++ptr; // consume '%' | ||||
|     if (ptr == end) | ||||
|       throw format_error("invalid format"); | ||||
|     if (begin != ptr) handler.on_text(begin, ptr); | ||||
|     ++ptr;  // consume '%' | ||||
|     if (ptr == end) FMT_THROW(format_error("invalid format")); | ||||
|     c = *ptr++; | ||||
|     switch (c) { | ||||
|     case '%': | ||||
| @@ -119,6 +290,12 @@ FMT_CONSTEXPR const Char *parse_chrono_format( | ||||
|     case 'p': | ||||
|       handler.on_am_pm(); | ||||
|       break; | ||||
|     case 'Q': | ||||
|       handler.on_duration_value(); | ||||
|       break; | ||||
|     case 'q': | ||||
|       handler.on_duration_unit(); | ||||
|       break; | ||||
|     case 'z': | ||||
|       handler.on_utc_offset(); | ||||
|       break; | ||||
| @@ -127,8 +304,7 @@ FMT_CONSTEXPR const Char *parse_chrono_format( | ||||
|       break; | ||||
|     // Alternative representation: | ||||
|     case 'E': { | ||||
|       if (ptr == end) | ||||
|         throw format_error("invalid format"); | ||||
|       if (ptr == end) FMT_THROW(format_error("invalid format")); | ||||
|       c = *ptr++; | ||||
|       switch (c) { | ||||
|       case 'c': | ||||
| @@ -141,13 +317,12 @@ FMT_CONSTEXPR const Char *parse_chrono_format( | ||||
|         handler.on_loc_time(numeric_system::alternative); | ||||
|         break; | ||||
|       default: | ||||
|         throw format_error("invalid format"); | ||||
|         FMT_THROW(format_error("invalid format")); | ||||
|       } | ||||
|       break; | ||||
|     } | ||||
|     case 'O': | ||||
|       if (ptr == end) | ||||
|         throw format_error("invalid format"); | ||||
|       if (ptr == end) FMT_THROW(format_error("invalid format")); | ||||
|       c = *ptr++; | ||||
|       switch (c) { | ||||
|       case 'w': | ||||
| @@ -169,96 +344,259 @@ FMT_CONSTEXPR const Char *parse_chrono_format( | ||||
|         handler.on_second(numeric_system::alternative); | ||||
|         break; | ||||
|       default: | ||||
|         throw format_error("invalid format"); | ||||
|         FMT_THROW(format_error("invalid format")); | ||||
|       } | ||||
|       break; | ||||
|     default: | ||||
|       throw format_error("invalid format"); | ||||
|       FMT_THROW(format_error("invalid format")); | ||||
|     } | ||||
|     begin = ptr; | ||||
|   } | ||||
|   if (begin != ptr) | ||||
|     handler.on_text(begin, ptr); | ||||
|   if (begin != ptr) handler.on_text(begin, ptr); | ||||
|   return ptr; | ||||
| } | ||||
|  | ||||
| struct chrono_format_checker { | ||||
|   void report_no_date() { throw format_error("no date"); } | ||||
|   FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); } | ||||
|  | ||||
|   template <typename Char> | ||||
|   void on_text(const Char *, const Char *) {} | ||||
|   void on_abbr_weekday() { report_no_date(); } | ||||
|   void on_full_weekday() { report_no_date(); } | ||||
|   void on_dec0_weekday(numeric_system) { report_no_date(); } | ||||
|   void on_dec1_weekday(numeric_system) { report_no_date(); } | ||||
|   void on_abbr_month() { report_no_date(); } | ||||
|   void on_full_month() { report_no_date(); } | ||||
|   template <typename Char> void on_text(const Char*, const Char*) {} | ||||
|   FMT_NORETURN void on_abbr_weekday() { report_no_date(); } | ||||
|   FMT_NORETURN void on_full_weekday() { report_no_date(); } | ||||
|   FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_abbr_month() { report_no_date(); } | ||||
|   FMT_NORETURN void on_full_month() { report_no_date(); } | ||||
|   void on_24_hour(numeric_system) {} | ||||
|   void on_12_hour(numeric_system) {} | ||||
|   void on_minute(numeric_system) {} | ||||
|   void on_second(numeric_system) {} | ||||
|   void on_datetime(numeric_system) { report_no_date(); } | ||||
|   void on_loc_date(numeric_system) { report_no_date(); } | ||||
|   void on_loc_time(numeric_system) { report_no_date(); } | ||||
|   void on_us_date() { report_no_date(); } | ||||
|   void on_iso_date() { report_no_date(); } | ||||
|   FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_us_date() { report_no_date(); } | ||||
|   FMT_NORETURN void on_iso_date() { report_no_date(); } | ||||
|   void on_12_hour_time() {} | ||||
|   void on_24_hour_time() {} | ||||
|   void on_iso_time() {} | ||||
|   void on_am_pm() {} | ||||
|   void on_utc_offset() { report_no_date(); } | ||||
|   void on_tz_name() { report_no_date(); } | ||||
|   void on_duration_value() {} | ||||
|   void on_duration_unit() {} | ||||
|   FMT_NORETURN void on_utc_offset() { report_no_date(); } | ||||
|   FMT_NORETURN void on_tz_name() { report_no_date(); } | ||||
| }; | ||||
|  | ||||
| template <typename Int> | ||||
| inline int to_int(Int value) { | ||||
|   FMT_ASSERT(value >= (std::numeric_limits<int>::min)() && | ||||
|              value <= (std::numeric_limits<int>::max)(), "invalid value"); | ||||
| template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> | ||||
| inline bool isnan(T) { | ||||
|   return false; | ||||
| } | ||||
| template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> | ||||
| inline bool isnan(T value) { | ||||
|   return std::isnan(value); | ||||
| } | ||||
|  | ||||
| template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> | ||||
| inline bool isfinite(T) { | ||||
|   return true; | ||||
| } | ||||
| template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> | ||||
| inline bool isfinite(T value) { | ||||
|   return std::isfinite(value); | ||||
| } | ||||
|  | ||||
| // Convers value to int and checks that it's in the range [0, upper). | ||||
| template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> | ||||
| inline int to_nonnegative_int(T value, int upper) { | ||||
|   FMT_ASSERT(value >= 0 && value <= upper, "invalid value"); | ||||
|   (void)upper; | ||||
|   return static_cast<int>(value); | ||||
| } | ||||
| template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)> | ||||
| inline int to_nonnegative_int(T value, int upper) { | ||||
|   FMT_ASSERT( | ||||
|       std::isnan(value) || (value >= 0 && value <= static_cast<T>(upper)), | ||||
|       "invalid value"); | ||||
|   (void)upper; | ||||
|   return static_cast<int>(value); | ||||
| } | ||||
|  | ||||
| template <typename FormatContext, typename OutputIt> | ||||
| template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> | ||||
| inline T mod(T x, int y) { | ||||
|   return x % y; | ||||
| } | ||||
| template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)> | ||||
| inline T mod(T x, int y) { | ||||
|   return std::fmod(x, static_cast<T>(y)); | ||||
| } | ||||
|  | ||||
| // If T is an integral type, maps T to its unsigned counterpart, otherwise | ||||
| // leaves it unchanged (unlike std::make_unsigned). | ||||
| template <typename T, bool INTEGRAL = std::is_integral<T>::value> | ||||
| struct make_unsigned_or_unchanged { | ||||
|   using type = T; | ||||
| }; | ||||
|  | ||||
| template <typename T> struct make_unsigned_or_unchanged<T, true> { | ||||
|   using type = typename std::make_unsigned<T>::type; | ||||
| }; | ||||
|  | ||||
| #if FMT_SAFE_DURATION_CAST | ||||
| // throwing version of safe_duration_cast | ||||
| template <typename To, typename FromRep, typename FromPeriod> | ||||
| To fmt_safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from) { | ||||
|   int ec; | ||||
|   To to = safe_duration_cast::safe_duration_cast<To>(from, ec); | ||||
|   if (ec) FMT_THROW(format_error("cannot format duration")); | ||||
|   return to; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename Rep, typename Period, | ||||
|           FMT_ENABLE_IF(std::is_integral<Rep>::value)> | ||||
| inline std::chrono::duration<Rep, std::milli> get_milliseconds( | ||||
|     std::chrono::duration<Rep, Period> d) { | ||||
|   // this may overflow and/or the result may not fit in the | ||||
|   // target type. | ||||
| #if FMT_SAFE_DURATION_CAST | ||||
|   using CommonSecondsType = | ||||
|       typename std::common_type<decltype(d), std::chrono::seconds>::type; | ||||
|   const auto d_as_common = fmt_safe_duration_cast<CommonSecondsType>(d); | ||||
|   const auto d_as_whole_seconds = | ||||
|       fmt_safe_duration_cast<std::chrono::seconds>(d_as_common); | ||||
|   // this conversion should be nonproblematic | ||||
|   const auto diff = d_as_common - d_as_whole_seconds; | ||||
|   const auto ms = | ||||
|       fmt_safe_duration_cast<std::chrono::duration<Rep, std::milli>>(diff); | ||||
|   return ms; | ||||
| #else | ||||
|   auto s = std::chrono::duration_cast<std::chrono::seconds>(d); | ||||
|   return std::chrono::duration_cast<std::chrono::milliseconds>(d - s); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <typename Rep, typename Period, | ||||
|           FMT_ENABLE_IF(std::is_floating_point<Rep>::value)> | ||||
| inline std::chrono::duration<Rep, std::milli> get_milliseconds( | ||||
|     std::chrono::duration<Rep, Period> d) { | ||||
|   using common_type = typename std::common_type<Rep, std::intmax_t>::type; | ||||
|   auto ms = mod(d.count() * static_cast<common_type>(Period::num) / | ||||
|                     static_cast<common_type>(Period::den) * 1000, | ||||
|                 1000); | ||||
|   return std::chrono::duration<Rep, std::milli>(static_cast<Rep>(ms)); | ||||
| } | ||||
|  | ||||
| template <typename Rep, typename OutputIt> | ||||
| OutputIt format_chrono_duration_value(OutputIt out, Rep val, int precision) { | ||||
|   if (precision >= 0) return format_to(out, "{:.{}f}", val, precision); | ||||
|   return format_to(out, std::is_floating_point<Rep>::value ? "{:g}" : "{}", | ||||
|                    val); | ||||
| } | ||||
|  | ||||
| template <typename Period, typename OutputIt> | ||||
| static OutputIt format_chrono_duration_unit(OutputIt out) { | ||||
|   if (const char* unit = get_units<Period>()) return format_to(out, "{}", unit); | ||||
|   if (Period::den == 1) return format_to(out, "[{}]s", Period::num); | ||||
|   return format_to(out, "[{}/{}]s", Period::num, Period::den); | ||||
| } | ||||
|  | ||||
| template <typename FormatContext, typename OutputIt, typename Rep, | ||||
|           typename Period> | ||||
| struct chrono_formatter { | ||||
|   FormatContext &context; | ||||
|   FormatContext& context; | ||||
|   OutputIt out; | ||||
|   std::chrono::seconds s; | ||||
|   std::chrono::milliseconds ms; | ||||
|   int precision; | ||||
|   // rep is unsigned to avoid overflow. | ||||
|   using rep = | ||||
|       conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int), | ||||
|                     unsigned, typename make_unsigned_or_unchanged<Rep>::type>; | ||||
|   rep val; | ||||
|   using seconds = std::chrono::duration<rep>; | ||||
|   seconds s; | ||||
|   using milliseconds = std::chrono::duration<rep, std::milli>; | ||||
|   bool negative; | ||||
|  | ||||
|   typedef typename FormatContext::char_type char_type; | ||||
|   using char_type = typename FormatContext::char_type; | ||||
|  | ||||
|   explicit chrono_formatter(FormatContext &ctx, OutputIt o) | ||||
|     : context(ctx), out(o) {} | ||||
|   explicit chrono_formatter(FormatContext& ctx, OutputIt o, | ||||
|                             std::chrono::duration<Rep, Period> d) | ||||
|       : context(ctx), out(o), val(d.count()), negative(false) { | ||||
|     if (d.count() < 0) { | ||||
|       val = 0 - val; | ||||
|       negative = true; | ||||
|     } | ||||
|  | ||||
|   int hour() const { return to_int((s.count() / 3600) % 24); } | ||||
|  | ||||
|   int hour12() const { | ||||
|     auto hour = to_int((s.count() / 3600) % 12); | ||||
|     return hour > 0 ? hour : 12; | ||||
|     // this may overflow and/or the result may not fit in the | ||||
|     // target type. | ||||
| #if FMT_SAFE_DURATION_CAST | ||||
|     // might need checked conversion (rep!=Rep) | ||||
|     auto tmpval = std::chrono::duration<rep, Period>(val); | ||||
|     s = fmt_safe_duration_cast<seconds>(tmpval); | ||||
| #else | ||||
|     s = std::chrono::duration_cast<seconds>( | ||||
|         std::chrono::duration<rep, Period>(val)); | ||||
| #endif | ||||
|   } | ||||
|  | ||||
|   int minute() const { return to_int((s.count() / 60) % 60); } | ||||
|   int second() const { return to_int(s.count() % 60); } | ||||
|   // returns true if nan or inf, writes to out. | ||||
|   bool handle_nan_inf() { | ||||
|     if (isfinite(val)) { | ||||
|       return false; | ||||
|     } | ||||
|     if (isnan(val)) { | ||||
|       write_nan(); | ||||
|       return true; | ||||
|     } | ||||
|     // must be +-inf | ||||
|     if (val > 0) { | ||||
|       write_pinf(); | ||||
|     } else { | ||||
|       write_ninf(); | ||||
|     } | ||||
|     return true; | ||||
|   } | ||||
|  | ||||
|   Rep hour() const { return static_cast<Rep>(mod((s.count() / 3600), 24)); } | ||||
|  | ||||
|   Rep hour12() const { | ||||
|     Rep hour = static_cast<Rep>(mod((s.count() / 3600), 12)); | ||||
|     return hour <= 0 ? 12 : hour; | ||||
|   } | ||||
|  | ||||
|   Rep minute() const { return static_cast<Rep>(mod((s.count() / 60), 60)); } | ||||
|   Rep second() const { return static_cast<Rep>(mod(s.count(), 60)); } | ||||
|  | ||||
|   std::tm time() const { | ||||
|     auto time = std::tm(); | ||||
|     time.tm_hour = hour(); | ||||
|     time.tm_min = minute(); | ||||
|     time.tm_sec = second(); | ||||
|     time.tm_hour = to_nonnegative_int(hour(), 24); | ||||
|     time.tm_min = to_nonnegative_int(minute(), 60); | ||||
|     time.tm_sec = to_nonnegative_int(second(), 60); | ||||
|     return time; | ||||
|   } | ||||
|  | ||||
|   void write(int value, int width) { | ||||
|     typedef typename int_traits<int>::main_type main_type; | ||||
|     main_type n = to_unsigned(value); | ||||
|   void write_sign() { | ||||
|     if (negative) { | ||||
|       *out++ = '-'; | ||||
|       negative = false; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   void write(Rep value, int width) { | ||||
|     write_sign(); | ||||
|     if (isnan(value)) return write_nan(); | ||||
|     uint32_or_64_t<int> n = to_unsigned( | ||||
|         to_nonnegative_int(value, (std::numeric_limits<int>::max)())); | ||||
|     int num_digits = internal::count_digits(n); | ||||
|     if (width > num_digits) | ||||
|       out = std::fill_n(out, width - num_digits, '0'); | ||||
|     if (width > num_digits) out = std::fill_n(out, width - num_digits, '0'); | ||||
|     out = format_decimal<char_type>(out, n, num_digits); | ||||
|   } | ||||
|  | ||||
|   void format_localized(const tm &time, const char *format) { | ||||
|   void write_nan() { std::copy_n("nan", 3, out); } | ||||
|   void write_pinf() { std::copy_n("inf", 3, out); } | ||||
|   void write_ninf() { std::copy_n("-inf", 4, out); } | ||||
|  | ||||
|   void format_localized(const tm& time, const char* format) { | ||||
|     if (isnan(val)) return write_nan(); | ||||
|     auto locale = context.locale().template get<std::locale>(); | ||||
|     auto &facet = std::use_facet<std::time_put<char_type>>(locale); | ||||
|     auto& facet = std::use_facet<std::time_put<char_type>>(locale); | ||||
|     std::basic_ostringstream<char_type> os; | ||||
|     os.imbue(locale); | ||||
|     facet.put(os, os, ' ', &time, format, format + std::strlen(format)); | ||||
| @@ -266,7 +604,7 @@ struct chrono_formatter { | ||||
|     std::copy(str.begin(), str.end(), out); | ||||
|   } | ||||
|  | ||||
|   void on_text(const char_type *begin, const char_type *end) { | ||||
|   void on_text(const char_type* begin, const char_type* end) { | ||||
|     std::copy(begin, end, out); | ||||
|   } | ||||
|  | ||||
| @@ -286,46 +624,70 @@ struct chrono_formatter { | ||||
|   void on_tz_name() {} | ||||
|  | ||||
|   void on_24_hour(numeric_system ns) { | ||||
|     if (ns == numeric_system::standard) | ||||
|       return write(hour(), 2); | ||||
|     if (handle_nan_inf()) return; | ||||
|  | ||||
|     if (ns == numeric_system::standard) return write(hour(), 2); | ||||
|     auto time = tm(); | ||||
|     time.tm_hour = hour(); | ||||
|     time.tm_hour = to_nonnegative_int(hour(), 24); | ||||
|     format_localized(time, "%OH"); | ||||
|   } | ||||
|  | ||||
|   void on_12_hour(numeric_system ns) { | ||||
|     if (ns == numeric_system::standard) | ||||
|       return write(hour12(), 2); | ||||
|     if (handle_nan_inf()) return; | ||||
|  | ||||
|     if (ns == numeric_system::standard) return write(hour12(), 2); | ||||
|     auto time = tm(); | ||||
|     time.tm_hour = hour(); | ||||
|     time.tm_hour = to_nonnegative_int(hour12(), 12); | ||||
|     format_localized(time, "%OI"); | ||||
|   } | ||||
|  | ||||
|   void on_minute(numeric_system ns) { | ||||
|     if (ns == numeric_system::standard) | ||||
|       return write(minute(), 2); | ||||
|     if (handle_nan_inf()) return; | ||||
|  | ||||
|     if (ns == numeric_system::standard) return write(minute(), 2); | ||||
|     auto time = tm(); | ||||
|     time.tm_min = minute(); | ||||
|     time.tm_min = to_nonnegative_int(minute(), 60); | ||||
|     format_localized(time, "%OM"); | ||||
|   } | ||||
|  | ||||
|   void on_second(numeric_system ns) { | ||||
|     if (handle_nan_inf()) return; | ||||
|  | ||||
|     if (ns == numeric_system::standard) { | ||||
|       write(second(), 2); | ||||
| #if FMT_SAFE_DURATION_CAST | ||||
|       // convert rep->Rep | ||||
|       using duration_rep = std::chrono::duration<rep, Period>; | ||||
|       using duration_Rep = std::chrono::duration<Rep, Period>; | ||||
|       auto tmpval = fmt_safe_duration_cast<duration_Rep>(duration_rep{val}); | ||||
| #else | ||||
|       auto tmpval = std::chrono::duration<Rep, Period>(val); | ||||
| #endif | ||||
|       auto ms = get_milliseconds(tmpval); | ||||
|       if (ms != std::chrono::milliseconds(0)) { | ||||
|         *out++ = '.'; | ||||
|         write(to_int(ms.count()), 3); | ||||
|         write(ms.count(), 3); | ||||
|       } | ||||
|       return; | ||||
|     } | ||||
|     auto time = tm(); | ||||
|     time.tm_sec = second(); | ||||
|     time.tm_sec = to_nonnegative_int(second(), 60); | ||||
|     format_localized(time, "%OS"); | ||||
|   } | ||||
|  | ||||
|   void on_12_hour_time() { format_localized(time(), "%r"); } | ||||
|   void on_12_hour_time() { | ||||
|     if (handle_nan_inf()) return; | ||||
|  | ||||
|     format_localized(time(), "%r"); | ||||
|   } | ||||
|  | ||||
|   void on_24_hour_time() { | ||||
|     if (handle_nan_inf()) { | ||||
|       *out++ = ':'; | ||||
|       handle_nan_inf(); | ||||
|       return; | ||||
|     } | ||||
|  | ||||
|     write(hour(), 2); | ||||
|     *out++ = ':'; | ||||
|     write(minute(), 2); | ||||
| @@ -334,115 +696,130 @@ struct chrono_formatter { | ||||
|   void on_iso_time() { | ||||
|     on_24_hour_time(); | ||||
|     *out++ = ':'; | ||||
|     if (handle_nan_inf()) return; | ||||
|     write(second(), 2); | ||||
|   } | ||||
|  | ||||
|   void on_am_pm() { format_localized(time(), "%p"); } | ||||
|   void on_am_pm() { | ||||
|     if (handle_nan_inf()) return; | ||||
|     format_localized(time(), "%p"); | ||||
|   } | ||||
|  | ||||
|   void on_duration_value() { | ||||
|     if (handle_nan_inf()) return; | ||||
|     write_sign(); | ||||
|     out = format_chrono_duration_value(out, val, precision); | ||||
|   } | ||||
|  | ||||
|   void on_duration_unit() { out = format_chrono_duration_unit<Period>(out); } | ||||
| }; | ||||
| }  // namespace internal | ||||
|  | ||||
| template <typename Period> FMT_CONSTEXPR const char *get_units() { | ||||
|   return FMT_NULL; | ||||
| } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::atto>() { return "as"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::femto>() { return "fs"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::pico>() { return "ps"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::nano>() { return "ns"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::micro>() { return "µs"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::milli>() { return "ms"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::centi>() { return "cs"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::deci>() { return "ds"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::ratio<1>>() { return "s"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::deca>() { return "das"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::hecto>() { return "hs"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::kilo>() { return "ks"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::mega>() { return "Ms"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::giga>() { return "Gs"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::tera>() { return "Ts"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::peta>() { return "Ps"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::exa>() { return "Es"; } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::ratio<60>>() { | ||||
|   return "m"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR const char *get_units<std::ratio<3600>>() { | ||||
|   return "h"; | ||||
| } | ||||
|  | ||||
| template <typename Rep, typename Period, typename Char> | ||||
| struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|  private: | ||||
|   align_spec spec; | ||||
|   internal::arg_ref<Char> width_ref; | ||||
|   basic_format_specs<Char> specs; | ||||
|   int precision; | ||||
|   using arg_ref_type = internal::arg_ref<Char>; | ||||
|   arg_ref_type width_ref; | ||||
|   arg_ref_type precision_ref; | ||||
|   mutable basic_string_view<Char> format_str; | ||||
|   typedef std::chrono::duration<Rep, Period> duration; | ||||
|   using duration = std::chrono::duration<Rep, Period>; | ||||
|  | ||||
|   struct spec_handler { | ||||
|     formatter &f; | ||||
|     basic_parse_context<Char> &context; | ||||
|     formatter& f; | ||||
|     basic_parse_context<Char>& context; | ||||
|     basic_string_view<Char> format_str; | ||||
|  | ||||
|     typedef internal::arg_ref<Char> arg_ref_type; | ||||
|  | ||||
|     template <typename Id> | ||||
|     FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) { | ||||
|     template <typename Id> FMT_CONSTEXPR arg_ref_type make_arg_ref(Id arg_id) { | ||||
|       context.check_arg_id(arg_id); | ||||
|       return arg_ref_type(arg_id); | ||||
|     } | ||||
|  | ||||
|     FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<Char> arg_id) { | ||||
|       context.check_arg_id(arg_id); | ||||
|       const auto str_val = internal::string_view_metadata(format_str, arg_id); | ||||
|       return arg_ref_type(str_val); | ||||
|     } | ||||
|  | ||||
|     FMT_CONSTEXPR arg_ref_type make_arg_ref(internal::auto_id) { | ||||
|       return arg_ref_type(context.next_arg_id()); | ||||
|     } | ||||
|  | ||||
|     void on_error(const char *msg) { throw format_error(msg); } | ||||
|     void on_fill(Char fill) { f.spec.fill_ = fill; } | ||||
|     void on_align(alignment align) { f.spec.align_ = align; } | ||||
|     void on_width(unsigned width) { f.spec.width_ = width; } | ||||
|     void on_error(const char* msg) { FMT_THROW(format_error(msg)); } | ||||
|     void on_fill(Char fill) { f.specs.fill[0] = fill; } | ||||
|     void on_align(align_t align) { f.specs.align = align; } | ||||
|     void on_width(unsigned width) { f.specs.width = width; } | ||||
|     void on_precision(unsigned precision) { f.precision = precision; } | ||||
|     void end_precision() {} | ||||
|  | ||||
|     template <typename Id> | ||||
|     void on_dynamic_width(Id arg_id) { | ||||
|     template <typename Id> void on_dynamic_width(Id arg_id) { | ||||
|       f.width_ref = make_arg_ref(arg_id); | ||||
|     } | ||||
|  | ||||
|     template <typename Id> void on_dynamic_precision(Id arg_id) { | ||||
|       f.precision_ref = make_arg_ref(arg_id); | ||||
|     } | ||||
|   }; | ||||
|  | ||||
|  public: | ||||
|   formatter() : spec() {} | ||||
|   using iterator = typename basic_parse_context<Char>::iterator; | ||||
|   struct parse_range { | ||||
|     iterator begin; | ||||
|     iterator end; | ||||
|   }; | ||||
|  | ||||
|   FMT_CONSTEXPR auto parse(basic_parse_context<Char> &ctx) | ||||
|       -> decltype(ctx.begin()) { | ||||
|   FMT_CONSTEXPR parse_range do_parse(basic_parse_context<Char>& ctx) { | ||||
|     auto begin = ctx.begin(), end = ctx.end(); | ||||
|     if (begin == end) return begin; | ||||
|     spec_handler handler{*this, ctx}; | ||||
|     if (begin == end || *begin == '}') return {begin, begin}; | ||||
|     spec_handler handler{*this, ctx, format_str}; | ||||
|     begin = internal::parse_align(begin, end, handler); | ||||
|     if (begin == end) return begin; | ||||
|     if (begin == end) return {begin, begin}; | ||||
|     begin = internal::parse_width(begin, end, handler); | ||||
|     if (begin == end) return {begin, begin}; | ||||
|     if (*begin == '.') { | ||||
|       if (std::is_floating_point<Rep>::value) | ||||
|         begin = internal::parse_precision(begin, end, handler); | ||||
|       else | ||||
|         handler.on_error("precision not allowed for this argument type"); | ||||
|     } | ||||
|     end = parse_chrono_format(begin, end, internal::chrono_format_checker()); | ||||
|     format_str = basic_string_view<Char>(&*begin, internal::to_unsigned(end - begin)); | ||||
|     return end; | ||||
|     return {begin, end}; | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   formatter() : precision(-1) {} | ||||
|  | ||||
|   FMT_CONSTEXPR auto parse(basic_parse_context<Char>& ctx) | ||||
|       -> decltype(ctx.begin()) { | ||||
|     auto range = do_parse(ctx); | ||||
|     format_str = basic_string_view<Char>( | ||||
|         &*range.begin, internal::to_unsigned(range.end - range.begin)); | ||||
|     return range.end; | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(const duration &d, FormatContext &ctx) | ||||
|       -> decltype(ctx.out()) { | ||||
|   auto format(const duration& d, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|     auto begin = format_str.begin(), end = format_str.end(); | ||||
|     memory_buffer buf; | ||||
|     typedef output_range<decltype(ctx.out()), Char> range; | ||||
|     basic_writer<range> w(range(ctx.out())); | ||||
|     // As a possible future optimization, we could avoid extra copying if width | ||||
|     // is not specified. | ||||
|     basic_memory_buffer<Char> buf; | ||||
|     auto out = std::back_inserter(buf); | ||||
|     using range = internal::output_range<decltype(ctx.out()), Char>; | ||||
|     internal::basic_writer<range> w(range(ctx.out())); | ||||
|     internal::handle_dynamic_spec<internal::width_checker>( | ||||
|         specs.width, width_ref, ctx, format_str.begin()); | ||||
|     internal::handle_dynamic_spec<internal::precision_checker>( | ||||
|         precision, precision_ref, ctx, format_str.begin()); | ||||
|     if (begin == end || *begin == '}') { | ||||
|       if (const char *unit = get_units<Period>()) | ||||
|         format_to(buf, "{}{}", d.count(), unit); | ||||
|       else if (Period::den == 1) | ||||
|         format_to(buf, "{}[{}]s", d.count(), Period::num); | ||||
|       else | ||||
|         format_to(buf, "{}[{}/{}]s", d.count(), Period::num, Period::den); | ||||
|       internal::handle_dynamic_spec<internal::width_checker>( | ||||
|         spec.width_, width_ref, ctx); | ||||
|       out = internal::format_chrono_duration_value(out, d.count(), precision); | ||||
|       internal::format_chrono_duration_unit<Period>(out); | ||||
|     } else { | ||||
|       auto out = std::back_inserter(buf); | ||||
|       internal::chrono_formatter<FormatContext, decltype(out)> f(ctx, out); | ||||
|       f.s = std::chrono::duration_cast<std::chrono::seconds>(d); | ||||
|       f.ms = std::chrono::duration_cast<std::chrono::milliseconds>(d - f.s); | ||||
|       internal::chrono_formatter<FormatContext, decltype(out), Rep, Period> f( | ||||
|           ctx, out, d); | ||||
|       f.precision = precision; | ||||
|       parse_chrono_format(begin, end, f); | ||||
|     } | ||||
|     w.write(buf.data(), buf.size(), spec); | ||||
|     w.write(buf.data(), buf.size(), specs); | ||||
|     return w.out(); | ||||
|   } | ||||
| }; | ||||
|   | ||||
| @@ -12,184 +12,149 @@ | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| #ifdef FMT_DEPRECATED_COLORS | ||||
|  | ||||
| // color and (v)print_colored are deprecated. | ||||
| enum color { black, red, green, yellow, blue, magenta, cyan, white }; | ||||
| FMT_API void vprint_colored(color c, string_view format, format_args args); | ||||
| FMT_API void vprint_colored(color c, wstring_view format, wformat_args args); | ||||
| template <typename... Args> | ||||
| inline void print_colored(color c, string_view format_str, | ||||
|                           const Args & ... args) { | ||||
|   vprint_colored(c, format_str, make_format_args(args...)); | ||||
| } | ||||
| template <typename... Args> | ||||
| inline void print_colored(color c, wstring_view format_str, | ||||
|                           const Args & ... args) { | ||||
|   vprint_colored(c, format_str, make_format_args<wformat_context>(args...)); | ||||
| } | ||||
|  | ||||
| inline void vprint_colored(color c, string_view format, format_args args) { | ||||
|   char escape[] = "\x1b[30m"; | ||||
|   escape[3] = static_cast<char>('0' + c); | ||||
|   std::fputs(escape, stdout); | ||||
|   vprint(format, args); | ||||
|   std::fputs(internal::data::RESET_COLOR, stdout); | ||||
| } | ||||
|  | ||||
| inline void vprint_colored(color c, wstring_view format, wformat_args args) { | ||||
|   wchar_t escape[] = L"\x1b[30m"; | ||||
|   escape[3] = static_cast<wchar_t>('0' + c); | ||||
|   std::fputws(escape, stdout); | ||||
|   vprint(format, args); | ||||
|   std::fputws(internal::data::WRESET_COLOR, stdout); | ||||
| } | ||||
|  | ||||
| #else | ||||
|  | ||||
| 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 | ||||
|   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, | ||||
| @@ -208,27 +173,26 @@ enum class terminal_color : uint8_t { | ||||
|   bright_magenta, | ||||
|   bright_cyan, | ||||
|   bright_white | ||||
| };  // enum class terminal_color | ||||
| }; | ||||
|  | ||||
| enum class emphasis : uint8_t { | ||||
|   bold = 1, | ||||
|   italic = 1 << 1, | ||||
|   underline = 1 << 2, | ||||
|   strikethrough = 1 << 3 | ||||
| };  // enum class emphasis | ||||
| }; | ||||
|  | ||||
| // rgb is a struct for red, green and blue colors. | ||||
| // We use rgb as name because some editors will show it as color direct in the | ||||
| // editor. | ||||
| // Using the name "rgb" makes some editors show the color in a tooltip. | ||||
| struct rgb { | ||||
|   FMT_CONSTEXPR_DECL rgb() : r(0), g(0), b(0) {} | ||||
|   FMT_CONSTEXPR_DECL rgb(uint8_t r_, uint8_t g_, uint8_t b_) | ||||
|     : r(r_), g(g_), b(b_) {} | ||||
|   FMT_CONSTEXPR_DECL rgb(uint32_t hex) | ||||
|     : r((hex >> 16) & 0xFF), g((hex >> 8) & 0xFF), b((hex) & 0xFF) {} | ||||
|   FMT_CONSTEXPR_DECL rgb(color hex) | ||||
|     : r((uint32_t(hex) >> 16) & 0xFF), g((uint32_t(hex) >> 8) & 0xFF), | ||||
|       b(uint32_t(hex) & 0xFF) {} | ||||
|   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; | ||||
| @@ -238,19 +202,17 @@ namespace internal { | ||||
|  | ||||
| // color is a struct of either a rgb color or a terminal color. | ||||
| struct color_type { | ||||
|   FMT_CONSTEXPR color_type() FMT_NOEXCEPT | ||||
|     : is_rgb(), value{} {} | ||||
|   FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT | ||||
|     : is_rgb(true), value{} { | ||||
|   FMT_CONSTEXPR color_type() FMT_NOEXCEPT : is_rgb(), value{} {} | ||||
|   FMT_CONSTEXPR color_type(color rgb_color) FMT_NOEXCEPT : is_rgb(true), | ||||
|                                                            value{} { | ||||
|     value.rgb_color = static_cast<uint32_t>(rgb_color); | ||||
|   } | ||||
|   FMT_CONSTEXPR color_type(rgb rgb_color) FMT_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(rgb rgb_color) FMT_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) FMT_NOEXCEPT | ||||
|     : is_rgb(), value{} { | ||||
|   FMT_CONSTEXPR color_type(terminal_color term_color) FMT_NOEXCEPT : is_rgb(), | ||||
|                                                                      value{} { | ||||
|     value.term_color = static_cast<uint8_t>(term_color); | ||||
|   } | ||||
|   bool is_rgb; | ||||
| @@ -259,21 +221,23 @@ struct color_type { | ||||
|     uint32_t rgb_color; | ||||
|   } value; | ||||
| }; | ||||
| } // namespace internal | ||||
| }  // namespace internal | ||||
|  | ||||
| // Experimental text formatting support. | ||||
| class text_style { | ||||
|  public: | ||||
|   FMT_CONSTEXPR text_style(emphasis em = emphasis()) FMT_NOEXCEPT | ||||
|       : set_foreground_color(), set_background_color(), ems(em) {} | ||||
|       : set_foreground_color(), | ||||
|         set_background_color(), | ||||
|         ems(em) {} | ||||
|  | ||||
|   FMT_CONSTEXPR text_style &operator|=(const text_style &rhs) { | ||||
|   FMT_CONSTEXPR text_style& operator|=(const text_style& rhs) { | ||||
|     if (!set_foreground_color) { | ||||
|       set_foreground_color = rhs.set_foreground_color; | ||||
|       foreground_color = rhs.foreground_color; | ||||
|     } else if (rhs.set_foreground_color) { | ||||
|       if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb) | ||||
|         throw format_error("can't OR a terminal color"); | ||||
|         FMT_THROW(format_error("can't OR a terminal color")); | ||||
|       foreground_color.value.rgb_color |= rhs.foreground_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
| @@ -282,7 +246,7 @@ class text_style { | ||||
|       background_color = rhs.background_color; | ||||
|     } else if (rhs.set_background_color) { | ||||
|       if (!background_color.is_rgb || !rhs.background_color.is_rgb) | ||||
|         throw format_error("can't OR a terminal color"); | ||||
|         FMT_THROW(format_error("can't OR a terminal color")); | ||||
|       background_color.value.rgb_color |= rhs.background_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
| @@ -291,18 +255,18 @@ class text_style { | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   friend FMT_CONSTEXPR | ||||
|   text_style operator|(text_style lhs, const text_style &rhs) { | ||||
|   friend FMT_CONSTEXPR text_style operator|(text_style lhs, | ||||
|                                             const text_style& rhs) { | ||||
|     return lhs |= rhs; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR text_style &operator&=(const text_style &rhs) { | ||||
|   FMT_CONSTEXPR text_style& operator&=(const text_style& rhs) { | ||||
|     if (!set_foreground_color) { | ||||
|       set_foreground_color = rhs.set_foreground_color; | ||||
|       foreground_color = rhs.foreground_color; | ||||
|     } else if (rhs.set_foreground_color) { | ||||
|       if (!foreground_color.is_rgb || !rhs.foreground_color.is_rgb) | ||||
|         throw format_error("can't AND a terminal color"); | ||||
|         FMT_THROW(format_error("can't AND a terminal color")); | ||||
|       foreground_color.value.rgb_color &= rhs.foreground_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
| @@ -311,7 +275,7 @@ class text_style { | ||||
|       background_color = rhs.background_color; | ||||
|     } else if (rhs.set_background_color) { | ||||
|       if (!background_color.is_rgb || !rhs.background_color.is_rgb) | ||||
|         throw format_error("can't AND a terminal color"); | ||||
|         FMT_THROW(format_error("can't AND a terminal color")); | ||||
|       background_color.value.rgb_color &= rhs.background_color.value.rgb_color; | ||||
|     } | ||||
|  | ||||
| @@ -320,8 +284,8 @@ class text_style { | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
|   friend FMT_CONSTEXPR | ||||
|   text_style operator&(text_style lhs, const text_style &rhs) { | ||||
|   friend FMT_CONSTEXPR text_style operator&(text_style lhs, | ||||
|                                             const text_style& rhs) { | ||||
|     return lhs &= rhs; | ||||
|   } | ||||
|  | ||||
| @@ -347,20 +311,20 @@ class text_style { | ||||
|     return ems; | ||||
|   } | ||||
|  | ||||
| private: | ||||
|  FMT_CONSTEXPR text_style(bool is_foreground, | ||||
|                           internal::color_type text_color) FMT_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; | ||||
|    } | ||||
|  } | ||||
|  private: | ||||
|   FMT_CONSTEXPR text_style(bool is_foreground, | ||||
|                            internal::color_type text_color) FMT_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_DECL text_style fg(internal::color_type foreground) | ||||
|       FMT_NOEXCEPT; | ||||
| @@ -388,19 +352,17 @@ FMT_CONSTEXPR text_style operator|(emphasis lhs, emphasis rhs) FMT_NOEXCEPT { | ||||
|  | ||||
| namespace internal { | ||||
|  | ||||
| template <typename Char> | ||||
| struct ansi_color_escape { | ||||
| template <typename Char> struct ansi_color_escape { | ||||
|   FMT_CONSTEXPR ansi_color_escape(internal::color_type text_color, | ||||
|                                   const char * esc) FMT_NOEXCEPT { | ||||
|                                   const char* esc) FMT_NOEXCEPT { | ||||
|     // If we have a terminal color, we need to output another escape code | ||||
|     // sequence. | ||||
|     if (!text_color.is_rgb) { | ||||
|       bool is_background = esc == internal::data::BACKGROUND_COLOR; | ||||
|       bool is_background = esc == internal::data::background_color; | ||||
|       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; | ||||
|       if (is_background) value += 10u; | ||||
|  | ||||
|       std::size_t index = 0; | ||||
|       buffer[index++] = static_cast<Char>('\x1b'); | ||||
| @@ -422,7 +384,7 @@ struct ansi_color_escape { | ||||
|       buffer[i] = static_cast<Char>(esc[i]); | ||||
|     } | ||||
|     rgb color(text_color.value.rgb_color); | ||||
|     to_esc(color.r, buffer +  7, ';'); | ||||
|     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); | ||||
| @@ -430,19 +392,15 @@ struct ansi_color_escape { | ||||
|   FMT_CONSTEXPR ansi_color_escape(emphasis em) FMT_NOEXCEPT { | ||||
|     uint8_t em_codes[4] = {}; | ||||
|     uint8_t em_bits = static_cast<uint8_t>(em); | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::bold)) | ||||
|       em_codes[0] = 1; | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::italic)) | ||||
|       em_codes[1] = 3; | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::underline)) | ||||
|       em_codes[2] = 4; | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::bold)) em_codes[0] = 1; | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::italic)) em_codes[1] = 3; | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::underline)) em_codes[2] = 4; | ||||
|     if (em_bits & static_cast<uint8_t>(emphasis::strikethrough)) | ||||
|       em_codes[3] = 9; | ||||
|  | ||||
|     std::size_t index = 0; | ||||
|     for (int i = 0; i < 4; ++i) { | ||||
|       if (!em_codes[i]) | ||||
|         continue; | ||||
|       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]); | ||||
| @@ -450,12 +408,17 @@ struct ansi_color_escape { | ||||
|     } | ||||
|     buffer[index++] = static_cast<Char>(0); | ||||
|   } | ||||
|   FMT_CONSTEXPR operator const Char *() const FMT_NOEXCEPT { return buffer; } | ||||
|   FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; } | ||||
|  | ||||
| private: | ||||
|   FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; } | ||||
|   FMT_CONSTEXPR const Char* end() const FMT_NOEXCEPT { | ||||
|     return buffer + std::strlen(buffer); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   Char buffer[7u + 3u * 4u + 1u]; | ||||
|  | ||||
|   static FMT_CONSTEXPR void to_esc(uint8_t c, Char *out, | ||||
|   static FMT_CONSTEXPR void to_esc(uint8_t c, Char* out, | ||||
|                                    char delimiter) FMT_NOEXCEPT { | ||||
|     out[0] = static_cast<Char>('0' + c / 100); | ||||
|     out[1] = static_cast<Char>('0' + c / 10 % 10); | ||||
| @@ -465,67 +428,90 @@ private: | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> | ||||
| make_foreground_color(internal::color_type foreground) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(foreground, internal::data::FOREGROUND_COLOR); | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color( | ||||
|     internal::color_type foreground) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(foreground, internal::data::foreground_color); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> | ||||
| make_background_color(internal::color_type background) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(background, internal::data::BACKGROUND_COLOR); | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> make_background_color( | ||||
|     internal::color_type background) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(background, internal::data::background_color); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> | ||||
| make_emphasis(emphasis em) FMT_NOEXCEPT { | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> make_emphasis(emphasis em) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(em); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| inline void fputs(const Char *chars, FILE *stream) FMT_NOEXCEPT { | ||||
| inline void fputs(const Char* chars, FILE* stream) FMT_NOEXCEPT { | ||||
|   std::fputs(chars, stream); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline void fputs<wchar_t>(const wchar_t *chars, FILE *stream) FMT_NOEXCEPT { | ||||
| inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT { | ||||
|   std::fputws(chars, stream); | ||||
| } | ||||
|  | ||||
| template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT { | ||||
|   fputs(internal::data::reset_color, stream); | ||||
| } | ||||
|  | ||||
| template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT { | ||||
|   fputs(internal::data::wreset_color, stream); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| inline void reset_color(FILE *stream) FMT_NOEXCEPT { | ||||
|   fputs(internal::data::RESET_COLOR, stream); | ||||
| inline void reset_color(basic_memory_buffer<Char>& buffer) FMT_NOEXCEPT { | ||||
|   const char* begin = data::reset_color; | ||||
|   const char* end = begin + sizeof(data::reset_color) - 1; | ||||
|   buffer.append(begin, end); | ||||
| } | ||||
|  | ||||
| template <> | ||||
| inline void reset_color<wchar_t>(FILE *stream) FMT_NOEXCEPT { | ||||
|   fputs(internal::data::WRESET_COLOR, stream); | ||||
| } | ||||
|  | ||||
| // The following specialiazation disables using std::FILE as a character type, | ||||
| // which is needed because or else | ||||
| //   fmt::print(stderr, fmt::emphasis::bold, ""); | ||||
| // would take stderr (a std::FILE *) as the format string. | ||||
| template <> | ||||
| struct is_string<std::FILE *> : std::false_type {}; | ||||
| template <> | ||||
| struct is_string<const std::FILE *> : std::false_type {}; | ||||
| } // namespace internal | ||||
|  | ||||
| template < | ||||
|   typename S, typename Char = typename internal::char_t<S>::type> | ||||
| void vprint(std::FILE *f, const text_style &ts, const S &format, | ||||
|             basic_format_args<typename buffer_context<Char>::type> args) { | ||||
| template <typename Char> | ||||
| std::basic_string<Char> vformat(const text_style& ts, | ||||
|                                 basic_string_view<Char> format_str, | ||||
|                                 basic_format_args<buffer_context<Char> > args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   bool has_style = false; | ||||
|   if (ts.has_emphasis()) { | ||||
|     has_style = true; | ||||
|     internal::fputs<Char>( | ||||
|           internal::make_emphasis<Char>(ts.get_emphasis()), f); | ||||
|     ansi_color_escape<Char> escape = make_emphasis<Char>(ts.get_emphasis()); | ||||
|     buffer.append(escape.begin(), escape.end()); | ||||
|   } | ||||
|   if (ts.has_foreground()) { | ||||
|     has_style = true; | ||||
|     ansi_color_escape<Char> escape = | ||||
|         make_foreground_color<Char>(ts.get_foreground()); | ||||
|     buffer.append(escape.begin(), escape.end()); | ||||
|   } | ||||
|   if (ts.has_background()) { | ||||
|     has_style = true; | ||||
|     ansi_color_escape<Char> escape = | ||||
|         make_background_color<Char>(ts.get_background()); | ||||
|     buffer.append(escape.begin(), escape.end()); | ||||
|   } | ||||
|   internal::vformat_to(buffer, format_str, args); | ||||
|   if (has_style) { | ||||
|     reset_color<Char>(buffer); | ||||
|   } | ||||
|   return fmt::to_string(buffer); | ||||
| } | ||||
| }  // namespace internal | ||||
|  | ||||
| template <typename S, typename Char = char_t<S> > | ||||
| void vprint(std::FILE* f, const text_style& ts, const S& format, | ||||
|             basic_format_args<buffer_context<Char> > args) { | ||||
|   bool has_style = false; | ||||
|   if (ts.has_emphasis()) { | ||||
|     has_style = true; | ||||
|     internal::fputs<Char>(internal::make_emphasis<Char>(ts.get_emphasis()), f); | ||||
|   } | ||||
|   if (ts.has_foreground()) { | ||||
|     has_style = true; | ||||
|     internal::fputs<Char>( | ||||
|           internal::make_foreground_color<Char>(ts.get_foreground()), f); | ||||
|         internal::make_foreground_color<Char>(ts.get_foreground()), f); | ||||
|   } | ||||
|   if (ts.has_background()) { | ||||
|     has_style = true; | ||||
| @@ -545,15 +531,14 @@ void vprint(std::FILE *f, const text_style &ts, const S &format, | ||||
|     fmt::print(fmt::emphasis::bold | fg(fmt::color::red), | ||||
|                "Elapsed time: {0:.2f} seconds", 1.23); | ||||
|  */ | ||||
| template <typename String, typename... Args> | ||||
| typename std::enable_if<internal::is_string<String>::value>::type print( | ||||
|     std::FILE *f, const text_style &ts, const String &format_str, | ||||
|     const Args &... args) { | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(internal::is_string<S>::value)> | ||||
| void print(std::FILE* f, const text_style& ts, const S& format_str, | ||||
|            const Args&... args) { | ||||
|   internal::check_format_string<Args...>(format_str); | ||||
|   typedef typename internal::char_t<String>::type char_t; | ||||
|   typedef typename buffer_context<char_t>::type context_t; | ||||
|   format_arg_store<context_t, Args...> as{args...}; | ||||
|   vprint(f, ts, format_str, basic_format_args<context_t>(as)); | ||||
|   using context = buffer_context<char_t<S> >; | ||||
|   format_arg_store<context, Args...> as{args...}; | ||||
|   vprint(f, ts, format_str, basic_format_args<context>(as)); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -563,14 +548,37 @@ typename std::enable_if<internal::is_string<String>::value>::type print( | ||||
|     fmt::print(fmt::emphasis::bold | fg(fmt::color::red), | ||||
|                "Elapsed time: {0:.2f} seconds", 1.23); | ||||
|  */ | ||||
| template <typename String, typename... Args> | ||||
| typename std::enable_if<internal::is_string<String>::value>::type print( | ||||
|     const text_style &ts, const String &format_str, | ||||
|     const Args &... args) { | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(internal::is_string<S>::value)> | ||||
| void print(const text_style& ts, const S& format_str, const Args&... args) { | ||||
|   return print(stdout, ts, format_str, args...); | ||||
| } | ||||
|  | ||||
| #endif | ||||
| template <typename S, typename Char = char_t<S> > | ||||
| inline std::basic_string<Char> vformat( | ||||
|     const text_style& ts, const S& format_str, | ||||
|     basic_format_args<buffer_context<Char> > args) { | ||||
|   return internal::vformat(ts, to_string_view(format_str), args); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   \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 std::basic_string<Char> format(const text_style& ts, const S& format_str, | ||||
|                                       const Args&... args) { | ||||
|   return internal::vformat(ts, to_string_view(format_str), | ||||
|                            {internal::make_args_checked(format_str, args...)}); | ||||
| } | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
|   | ||||
							
								
								
									
										466
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/compile.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										466
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/compile.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,466 @@ | ||||
| // 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 <vector> | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| namespace internal { | ||||
|  | ||||
| template <typename Char> struct format_part { | ||||
|  public: | ||||
|   struct named_argument_id { | ||||
|     FMT_CONSTEXPR named_argument_id(internal::string_view_metadata id) | ||||
|         : id(id) {} | ||||
|     internal::string_view_metadata id; | ||||
|   }; | ||||
|  | ||||
|   struct argument_id { | ||||
|     FMT_CONSTEXPR argument_id() : argument_id(0u) {} | ||||
|  | ||||
|     FMT_CONSTEXPR argument_id(unsigned id) | ||||
|         : which(which_arg_id::index), val(id) {} | ||||
|  | ||||
|     FMT_CONSTEXPR argument_id(internal::string_view_metadata id) | ||||
|         : which(which_arg_id::named_index), val(id) {} | ||||
|  | ||||
|     enum class which_arg_id { index, named_index }; | ||||
|  | ||||
|     which_arg_id which; | ||||
|  | ||||
|     union value { | ||||
|       FMT_CONSTEXPR value() : index(0u) {} | ||||
|       FMT_CONSTEXPR value(unsigned id) : index(id) {} | ||||
|       FMT_CONSTEXPR value(internal::string_view_metadata id) | ||||
|           : named_index(id) {} | ||||
|  | ||||
|       unsigned index; | ||||
|       internal::string_view_metadata named_index; | ||||
|     } val; | ||||
|   }; | ||||
|  | ||||
|   struct specification { | ||||
|     FMT_CONSTEXPR specification() : arg_id(0u) {} | ||||
|     FMT_CONSTEXPR specification(unsigned id) : arg_id(id) {} | ||||
|  | ||||
|     FMT_CONSTEXPR specification(internal::string_view_metadata id) | ||||
|         : arg_id(id) {} | ||||
|  | ||||
|     argument_id arg_id; | ||||
|     internal::dynamic_format_specs<Char> parsed_specs; | ||||
|   }; | ||||
|  | ||||
|   FMT_CONSTEXPR format_part() | ||||
|       : which(kind::argument_id), end_of_argument_id(0u), val(0u) {} | ||||
|  | ||||
|   FMT_CONSTEXPR format_part(internal::string_view_metadata text) | ||||
|       : which(kind::text), end_of_argument_id(0u), val(text) {} | ||||
|  | ||||
|   FMT_CONSTEXPR format_part(unsigned id) | ||||
|       : which(kind::argument_id), end_of_argument_id(0u), val(id) {} | ||||
|  | ||||
|   FMT_CONSTEXPR format_part(named_argument_id arg_id) | ||||
|       : which(kind::named_argument_id), end_of_argument_id(0u), val(arg_id) {} | ||||
|  | ||||
|   FMT_CONSTEXPR format_part(specification spec) | ||||
|       : which(kind::specification), end_of_argument_id(0u), val(spec) {} | ||||
|  | ||||
|   enum class kind { argument_id, named_argument_id, text, specification }; | ||||
|  | ||||
|   kind which; | ||||
|   std::size_t end_of_argument_id; | ||||
|   union value { | ||||
|     FMT_CONSTEXPR value() : arg_id(0u) {} | ||||
|     FMT_CONSTEXPR value(unsigned id) : arg_id(id) {} | ||||
|     FMT_CONSTEXPR value(named_argument_id named_id) | ||||
|         : named_arg_id(named_id.id) {} | ||||
|     FMT_CONSTEXPR value(internal::string_view_metadata t) : text(t) {} | ||||
|     FMT_CONSTEXPR value(specification s) : spec(s) {} | ||||
|     unsigned arg_id; | ||||
|     internal::string_view_metadata named_arg_id; | ||||
|     internal::string_view_metadata text; | ||||
|     specification spec; | ||||
|   } val; | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename PartsContainer> | ||||
| class format_preparation_handler : public internal::error_handler { | ||||
|  private: | ||||
|   using part = format_part<Char>; | ||||
|  | ||||
|  public: | ||||
|   using iterator = typename basic_string_view<Char>::iterator; | ||||
|  | ||||
|   FMT_CONSTEXPR format_preparation_handler(basic_string_view<Char> format, | ||||
|                                            PartsContainer& parts) | ||||
|       : parts_(parts), format_(format), parse_context_(format) {} | ||||
|  | ||||
|   FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { | ||||
|     if (begin == end) return; | ||||
|     const auto offset = begin - format_.data(); | ||||
|     const auto size = end - begin; | ||||
|     parts_.push_back(part(string_view_metadata(offset, size))); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_arg_id() { | ||||
|     parts_.push_back(part(parse_context_.next_arg_id())); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_arg_id(unsigned id) { | ||||
|     parse_context_.check_arg_id(id); | ||||
|     parts_.push_back(part(id)); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_arg_id(basic_string_view<Char> id) { | ||||
|     const auto view = string_view_metadata(format_, id); | ||||
|     const auto arg_id = typename part::named_argument_id(view); | ||||
|     parts_.push_back(part(arg_id)); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_replacement_field(const Char* ptr) { | ||||
|     parts_.back().end_of_argument_id = ptr - format_.begin(); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR const Char* on_format_specs(const Char* begin, | ||||
|                                             const Char* end) { | ||||
|     const auto specs_offset = to_unsigned(begin - format_.begin()); | ||||
|  | ||||
|     using parse_context = basic_parse_context<Char>; | ||||
|     internal::dynamic_format_specs<Char> parsed_specs; | ||||
|     dynamic_specs_handler<parse_context> handler(parsed_specs, parse_context_); | ||||
|     begin = parse_format_specs(begin, end, handler); | ||||
|  | ||||
|     if (*begin != '}') on_error("missing '}' in format string"); | ||||
|  | ||||
|     auto& last_part = parts_.back(); | ||||
|     auto specs = last_part.which == part::kind::argument_id | ||||
|                      ? typename part::specification(last_part.val.arg_id) | ||||
|                      : typename part::specification(last_part.val.named_arg_id); | ||||
|     specs.parsed_specs = parsed_specs; | ||||
|     last_part = part(specs); | ||||
|     last_part.end_of_argument_id = specs_offset; | ||||
|     return begin; | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   PartsContainer& parts_; | ||||
|   basic_string_view<Char> format_; | ||||
|   basic_parse_context<Char> parse_context_; | ||||
| }; | ||||
|  | ||||
| template <typename Format, typename PreparedPartsProvider, typename... Args> | ||||
| class prepared_format { | ||||
|  public: | ||||
|   using char_type = char_t<Format>; | ||||
|   using format_part_t = format_part<char_type>; | ||||
|  | ||||
|   constexpr prepared_format(Format f) | ||||
|       : format_(std::move(f)), parts_provider_(to_string_view(format_)) {} | ||||
|  | ||||
|   prepared_format() = delete; | ||||
|  | ||||
|   using context = buffer_context<char_type>; | ||||
|  | ||||
|   template <typename Range, typename Context> | ||||
|   auto vformat_to(Range out, basic_format_args<Context> args) const -> | ||||
|       typename Context::iterator { | ||||
|     const auto format_view = internal::to_string_view(format_); | ||||
|     basic_parse_context<char_type> parse_ctx(format_view); | ||||
|     Context ctx(out.begin(), args); | ||||
|  | ||||
|     const auto& parts = parts_provider_.parts(); | ||||
|     for (auto part_it = parts.begin(); part_it != parts.end(); ++part_it) { | ||||
|       const auto& part = *part_it; | ||||
|       const auto& value = part.val; | ||||
|  | ||||
|       switch (part.which) { | ||||
|       case format_part_t::kind::text: { | ||||
|         const auto text = value.text.to_view(format_view.data()); | ||||
|         auto output = ctx.out(); | ||||
|         auto&& it = internal::reserve(output, text.size()); | ||||
|         it = std::copy_n(text.begin(), text.size(), it); | ||||
|         ctx.advance_to(output); | ||||
|       } break; | ||||
|  | ||||
|       case format_part_t::kind::argument_id: { | ||||
|         advance_parse_context_to_specification(parse_ctx, part); | ||||
|         format_arg<Range>(parse_ctx, ctx, value.arg_id); | ||||
|       } break; | ||||
|  | ||||
|       case format_part_t::kind::named_argument_id: { | ||||
|         advance_parse_context_to_specification(parse_ctx, part); | ||||
|         const auto named_arg_id = | ||||
|             value.named_arg_id.to_view(format_view.data()); | ||||
|         format_arg<Range>(parse_ctx, ctx, named_arg_id); | ||||
|       } break; | ||||
|       case format_part_t::kind::specification: { | ||||
|         const auto& arg_id_value = value.spec.arg_id.val; | ||||
|         const auto arg = value.spec.arg_id.which == | ||||
|                                  format_part_t::argument_id::which_arg_id::index | ||||
|                              ? ctx.arg(arg_id_value.index) | ||||
|                              : ctx.arg(arg_id_value.named_index.to_view( | ||||
|                                    to_string_view(format_).data())); | ||||
|  | ||||
|         auto specs = value.spec.parsed_specs; | ||||
|  | ||||
|         handle_dynamic_spec<internal::width_checker>( | ||||
|             specs.width, specs.width_ref, ctx, format_view.begin()); | ||||
|         handle_dynamic_spec<internal::precision_checker>( | ||||
|             specs.precision, specs.precision_ref, ctx, format_view.begin()); | ||||
|  | ||||
|         check_prepared_specs(specs, arg.type()); | ||||
|         advance_parse_context_to_specification(parse_ctx, part); | ||||
|         ctx.advance_to( | ||||
|             visit_format_arg(arg_formatter<Range>(ctx, nullptr, &specs), arg)); | ||||
|       } break; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     return ctx.out(); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   void advance_parse_context_to_specification( | ||||
|       basic_parse_context<char_type>& parse_ctx, | ||||
|       const format_part_t& part) const { | ||||
|     const auto view = to_string_view(format_); | ||||
|     const auto specification_begin = view.data() + part.end_of_argument_id; | ||||
|     advance_to(parse_ctx, specification_begin); | ||||
|   } | ||||
|  | ||||
|   template <typename Range, typename Context, typename Id> | ||||
|   void format_arg(basic_parse_context<char_type>& parse_ctx, Context& ctx, | ||||
|                   Id arg_id) const { | ||||
|     parse_ctx.check_arg_id(arg_id); | ||||
|     const auto stopped_at = | ||||
|         visit_format_arg(arg_formatter<Range>(ctx), ctx.arg(arg_id)); | ||||
|     ctx.advance_to(stopped_at); | ||||
|   } | ||||
|  | ||||
|   template <typename Char> | ||||
|   void check_prepared_specs(const basic_format_specs<Char>& specs, | ||||
|                             internal::type arg_type) const { | ||||
|     internal::error_handler h; | ||||
|     numeric_specs_checker<internal::error_handler> checker(h, arg_type); | ||||
|     if (specs.align == align::numeric) checker.require_numeric_argument(); | ||||
|     if (specs.sign != sign::none) checker.check_sign(); | ||||
|     if (specs.alt) checker.require_numeric_argument(); | ||||
|     if (specs.precision >= 0) checker.check_precision(); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   Format format_; | ||||
|   PreparedPartsProvider parts_provider_; | ||||
| }; | ||||
|  | ||||
| template <typename Char> struct part_counter { | ||||
|   unsigned num_parts = 0; | ||||
|  | ||||
|   FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { | ||||
|     if (begin != end) ++num_parts; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_arg_id() { ++num_parts; } | ||||
|   FMT_CONSTEXPR void on_arg_id(unsigned) { ++num_parts; } | ||||
|   FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) { ++num_parts; } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_replacement_field(const Char*) {} | ||||
|  | ||||
|   FMT_CONSTEXPR const Char* on_format_specs(const Char* begin, | ||||
|                                             const Char* end) { | ||||
|     // Find the matching brace. | ||||
|     unsigned braces_counter = 0; | ||||
|     for (; begin != end; ++begin) { | ||||
|       if (*begin == '{') { | ||||
|         ++braces_counter; | ||||
|       } else if (*begin == '}') { | ||||
|         if (braces_counter == 0u) break; | ||||
|         --braces_counter; | ||||
|       } | ||||
|     } | ||||
|     return begin; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_error(const char*) {} | ||||
| }; | ||||
|  | ||||
| template <typename Format> class compiletime_prepared_parts_type_provider { | ||||
|  private: | ||||
|   using char_type = char_t<Format>; | ||||
|  | ||||
|   static FMT_CONSTEXPR unsigned count_parts() { | ||||
|     FMT_CONSTEXPR_DECL const auto text = to_string_view(Format{}); | ||||
|     part_counter<char_type> counter; | ||||
|     internal::parse_format_string</*IS_CONSTEXPR=*/true>(text, counter); | ||||
|     return counter.num_parts; | ||||
|   } | ||||
|  | ||||
| // Workaround for old compilers. Compiletime parts preparation will not be | ||||
| // performed with them anyway. | ||||
| #if FMT_USE_CONSTEXPR | ||||
|   static FMT_CONSTEXPR_DECL const unsigned number_of_format_parts = | ||||
|       compiletime_prepared_parts_type_provider::count_parts(); | ||||
| #else | ||||
|   static const unsigned number_of_format_parts = 0u; | ||||
| #endif | ||||
|  | ||||
|  public: | ||||
|   template <unsigned N> struct format_parts_array { | ||||
|     using value_type = format_part<char_type>; | ||||
|  | ||||
|     FMT_CONSTEXPR format_parts_array() : arr{} {} | ||||
|  | ||||
|     FMT_CONSTEXPR value_type& operator[](unsigned ind) { return arr[ind]; } | ||||
|  | ||||
|     FMT_CONSTEXPR const value_type* begin() const { return arr; } | ||||
|     FMT_CONSTEXPR const value_type* end() const { return begin() + N; } | ||||
|  | ||||
|    private: | ||||
|     value_type arr[N]; | ||||
|   }; | ||||
|  | ||||
|   struct empty { | ||||
|     // Parts preparator will search for it | ||||
|     using value_type = format_part<char_type>; | ||||
|   }; | ||||
|  | ||||
|   using type = conditional_t<number_of_format_parts != 0, | ||||
|                              format_parts_array<number_of_format_parts>, empty>; | ||||
| }; | ||||
|  | ||||
| template <typename Parts> class compiletime_prepared_parts_collector { | ||||
|  private: | ||||
|   using format_part = typename Parts::value_type; | ||||
|  | ||||
|  public: | ||||
|   FMT_CONSTEXPR explicit compiletime_prepared_parts_collector(Parts& parts) | ||||
|       : parts_{parts}, counter_{0u} {} | ||||
|  | ||||
|   FMT_CONSTEXPR void push_back(format_part part) { parts_[counter_++] = part; } | ||||
|  | ||||
|   FMT_CONSTEXPR format_part& back() { return parts_[counter_ - 1]; } | ||||
|  | ||||
|  private: | ||||
|   Parts& parts_; | ||||
|   unsigned counter_; | ||||
| }; | ||||
|  | ||||
| template <typename PartsContainer, typename Char> | ||||
| FMT_CONSTEXPR PartsContainer prepare_parts(basic_string_view<Char> format) { | ||||
|   PartsContainer parts; | ||||
|   internal::parse_format_string</*IS_CONSTEXPR=*/false>( | ||||
|       format, format_preparation_handler<Char, PartsContainer>(format, parts)); | ||||
|   return parts; | ||||
| } | ||||
|  | ||||
| template <typename PartsContainer, typename Char> | ||||
| FMT_CONSTEXPR PartsContainer | ||||
| prepare_compiletime_parts(basic_string_view<Char> format) { | ||||
|   using collector = compiletime_prepared_parts_collector<PartsContainer>; | ||||
|  | ||||
|   PartsContainer parts; | ||||
|   collector c(parts); | ||||
|   internal::parse_format_string</*IS_CONSTEXPR=*/true>( | ||||
|       format, format_preparation_handler<Char, collector>(format, c)); | ||||
|   return parts; | ||||
| } | ||||
|  | ||||
| template <typename PartsContainer> class runtime_parts_provider { | ||||
|  public: | ||||
|   runtime_parts_provider() = delete; | ||||
|   template <typename Char> | ||||
|   runtime_parts_provider(basic_string_view<Char> format) | ||||
|       : parts_(prepare_parts<PartsContainer>(format)) {} | ||||
|  | ||||
|   const PartsContainer& parts() const { return parts_; } | ||||
|  | ||||
|  private: | ||||
|   PartsContainer parts_; | ||||
| }; | ||||
|  | ||||
| template <typename Format, typename PartsContainer> | ||||
| struct compiletime_parts_provider { | ||||
|   compiletime_parts_provider() = delete; | ||||
|   template <typename Char> | ||||
|   FMT_CONSTEXPR compiletime_parts_provider(basic_string_view<Char>) {} | ||||
|  | ||||
|   const PartsContainer& parts() const { | ||||
|     static FMT_CONSTEXPR_DECL const PartsContainer prepared_parts = | ||||
|         prepare_compiletime_parts<PartsContainer>( | ||||
|             internal::to_string_view(Format{})); | ||||
|  | ||||
|     return prepared_parts; | ||||
|   } | ||||
| }; | ||||
| }  // namespace internal | ||||
|  | ||||
| #if FMT_USE_CONSTEXPR | ||||
| template <typename... Args, typename S, | ||||
|           FMT_ENABLE_IF(is_compile_string<S>::value)> | ||||
| FMT_CONSTEXPR auto compile(S format_str) -> internal::prepared_format< | ||||
|     S, | ||||
|     internal::compiletime_parts_provider< | ||||
|         S, | ||||
|         typename internal::compiletime_prepared_parts_type_provider<S>::type>, | ||||
|     Args...> { | ||||
|   return format_str; | ||||
| } | ||||
| #endif | ||||
|  | ||||
| template <typename... Args, typename Char, size_t N> | ||||
| auto compile(const Char (&format_str)[N]) -> internal::prepared_format< | ||||
|     std::basic_string<Char>, | ||||
|     internal::runtime_parts_provider<std::vector<internal::format_part<Char>>>, | ||||
|     Args...> { | ||||
|   return std::basic_string<Char>(format_str, N - 1); | ||||
| } | ||||
|  | ||||
| template <typename CompiledFormat, typename... Args, | ||||
|           typename Char = typename CompiledFormat::char_type> | ||||
| std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   using range = internal::buffer_range<Char>; | ||||
|   using context = buffer_context<Char>; | ||||
|   cf.template vformat_to<range, context>(range(buffer), | ||||
|                                          {make_format_args<context>(args...)}); | ||||
|   return to_string(buffer); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args> | ||||
| OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                    const Args&... args) { | ||||
|   using char_type = typename CompiledFormat::char_type; | ||||
|   using range = internal::output_range<OutputIt, char_type>; | ||||
|   using context = format_context_t<OutputIt, char_type>; | ||||
|   return cf.template vformat_to<range, context>( | ||||
|       range(out), {make_format_args<context>(args...)}); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)> | ||||
| format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, | ||||
|                                          const CompiledFormat& cf, | ||||
|                                          const Args&... args) { | ||||
|   auto it = | ||||
|       format_to(internal::truncating_iterator<OutputIt>(out, n), cf, args...); | ||||
|   return {it.base(), it.count()}; | ||||
| } | ||||
|  | ||||
| template <typename CompiledFormat, typename... Args> | ||||
| std::size_t formatted_size(const CompiledFormat& cf, const Args&... args) { | ||||
|   return fmt::format_to( | ||||
|              internal::counting_iterator<typename CompiledFormat::char_type>(), | ||||
|              cf, args...) | ||||
|       .count(); | ||||
| } | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_COMPILE_H_ | ||||
							
								
								
									
										1900
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/core.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1900
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/core.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3871
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/format.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3871
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/format.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -8,65 +8,65 @@ | ||||
| #ifndef FMT_LOCALE_H_ | ||||
| #define FMT_LOCALE_H_ | ||||
|  | ||||
| #include "format.h" | ||||
| #include <locale> | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| namespace internal { | ||||
| template <typename Char> | ||||
| typename buffer_context<Char>::type::iterator vformat_to( | ||||
|     const std::locale &loc, basic_buffer<Char> &buf, | ||||
| typename buffer_context<Char>::iterator vformat_to( | ||||
|     const std::locale& loc, buffer<Char>& buf, | ||||
|     basic_string_view<Char> format_str, | ||||
|     basic_format_args<typename buffer_context<Char>::type> args) { | ||||
|   typedef back_insert_range<basic_buffer<Char> > range; | ||||
|   return vformat_to<arg_formatter<range>>( | ||||
|     buf, to_string_view(format_str), args, internal::locale_ref(loc)); | ||||
|     basic_format_args<buffer_context<Char>> args) { | ||||
|   using range = buffer_range<Char>; | ||||
|   return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str), args, | ||||
|                                           internal::locale_ref(loc)); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| std::basic_string<Char> vformat( | ||||
|     const std::locale &loc, basic_string_view<Char> format_str, | ||||
|     basic_format_args<typename buffer_context<Char>::type> args) { | ||||
| std::basic_string<Char> vformat(const std::locale& loc, | ||||
|                                 basic_string_view<Char> format_str, | ||||
|                                 basic_format_args<buffer_context<Char>> args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   internal::vformat_to(loc, buffer, format_str, args); | ||||
|   return fmt::to_string(buffer); | ||||
| } | ||||
| } | ||||
| }  // namespace internal | ||||
|  | ||||
| template <typename S, typename Char = FMT_CHAR(S)> | ||||
| template <typename S, typename Char = char_t<S>> | ||||
| inline std::basic_string<Char> vformat( | ||||
|     const std::locale &loc, const S &format_str, | ||||
|     basic_format_args<typename buffer_context<Char>::type> args) { | ||||
|     const std::locale& loc, const S& format_str, | ||||
|     basic_format_args<buffer_context<Char>> args) { | ||||
|   return internal::vformat(loc, to_string_view(format_str), args); | ||||
| } | ||||
|  | ||||
| template <typename S, typename... Args> | ||||
| inline std::basic_string<FMT_CHAR(S)> format( | ||||
|     const std::locale &loc, const S &format_str, const Args &... args) { | ||||
| template <typename S, typename... Args, typename Char = char_t<S>> | ||||
| inline std::basic_string<Char> format(const std::locale& loc, | ||||
|                                       const S& format_str, Args&&... args) { | ||||
|   return internal::vformat( | ||||
|     loc, to_string_view(format_str), | ||||
|     *internal::checked_args<S, Args...>(format_str, args...)); | ||||
|       loc, to_string_view(format_str), | ||||
|       {internal::make_args_checked<Args...>(format_str, args...)}); | ||||
| } | ||||
|  | ||||
| template <typename String, typename OutputIt, typename... Args> | ||||
| inline typename std::enable_if<internal::is_output_iterator<OutputIt>::value, | ||||
|                                OutputIt>::type | ||||
|     vformat_to(OutputIt out, const std::locale &loc, const String &format_str, | ||||
|                typename format_args_t<OutputIt, FMT_CHAR(String)>::type args) { | ||||
|   typedef output_range<OutputIt, FMT_CHAR(String)> range; | ||||
| template <typename S, typename OutputIt, typename... Args, | ||||
|           typename Char = enable_if_t< | ||||
|               internal::is_output_iterator<OutputIt>::value, char_t<S>>> | ||||
| inline OutputIt vformat_to(OutputIt out, const std::locale& loc, | ||||
|                            const S& format_str, | ||||
|                            format_args_t<OutputIt, Char> args) { | ||||
|   using range = internal::output_range<OutputIt, Char>; | ||||
|   return vformat_to<arg_formatter<range>>( | ||||
|     range(out), to_string_view(format_str), args, internal::locale_ref(loc)); | ||||
|       range(out), to_string_view(format_str), args, internal::locale_ref(loc)); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args> | ||||
| inline typename std::enable_if< | ||||
|     internal::is_string<S>::value && | ||||
|     internal::is_output_iterator<OutputIt>::value, OutputIt>::type | ||||
|     format_to(OutputIt out, const std::locale &loc, const S &format_str, | ||||
|               const Args &... args) { | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value&& | ||||
|                             internal::is_string<S>::value)> | ||||
| inline OutputIt format_to(OutputIt out, const std::locale& loc, | ||||
|                           const S& format_str, Args&&... args) { | ||||
|   internal::check_format_string<Args...>(format_str); | ||||
|   typedef typename format_context_t<OutputIt, FMT_CHAR(S)>::type context; | ||||
|   using context = format_context_t<OutputIt, char_t<S>>; | ||||
|   format_arg_store<context, Args...> as{args...}; | ||||
|   return vformat_to(out, loc, to_string_view(format_str), | ||||
|                     basic_format_args<context>(as)); | ||||
|   | ||||
| @@ -8,22 +8,21 @@ | ||||
| #ifndef FMT_OSTREAM_H_ | ||||
| #define FMT_OSTREAM_H_ | ||||
|  | ||||
| #include "format.h" | ||||
| #include <ostream> | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| namespace internal { | ||||
|  | ||||
| template <class Char> | ||||
| class formatbuf : public std::basic_streambuf<Char> { | ||||
| template <class Char> class formatbuf : public std::basic_streambuf<Char> { | ||||
|  private: | ||||
|   typedef typename std::basic_streambuf<Char>::int_type int_type; | ||||
|   typedef typename std::basic_streambuf<Char>::traits_type traits_type; | ||||
|   using int_type = typename std::basic_streambuf<Char>::int_type; | ||||
|   using traits_type = typename std::basic_streambuf<Char>::traits_type; | ||||
|  | ||||
|   basic_buffer<Char> &buffer_; | ||||
|   buffer<Char>& buffer_; | ||||
|  | ||||
|  public: | ||||
|   formatbuf(basic_buffer<Char> &buffer) : buffer_(buffer) {} | ||||
|   formatbuf(buffer<Char>& buf) : buffer_(buf) {} | ||||
|  | ||||
|  protected: | ||||
|   // The put-area is actually always empty. This makes the implementation | ||||
| @@ -39,33 +38,32 @@ class formatbuf : public std::basic_streambuf<Char> { | ||||
|     return ch; | ||||
|   } | ||||
|  | ||||
|   std::streamsize xsputn(const Char *s, std::streamsize count) FMT_OVERRIDE { | ||||
|   std::streamsize xsputn(const Char* s, std::streamsize count) FMT_OVERRIDE { | ||||
|     buffer_.append(s, s + count); | ||||
|     return count; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| struct test_stream : std::basic_ostream<Char> { | ||||
| template <typename Char> struct test_stream : std::basic_ostream<Char> { | ||||
|  private: | ||||
|   struct null; | ||||
|   // Hide all operator<< from std::basic_ostream<Char>. | ||||
|   void operator<<(null); | ||||
| }; | ||||
|  | ||||
| // Checks if T has a user-defined operator<< (e.g. not a member of std::ostream). | ||||
| template <typename T, typename Char> | ||||
| class is_streamable { | ||||
| // Checks if T has a user-defined operator<< (e.g. not a member of | ||||
| // std::ostream). | ||||
| template <typename T, typename Char> class is_streamable { | ||||
|  private: | ||||
|   template <typename U> | ||||
|   static decltype( | ||||
|     internal::declval<test_stream<Char>&>() | ||||
|       << internal::declval<U>(), std::true_type()) test(int); | ||||
|   static decltype((void)(std::declval<test_stream<Char>&>() | ||||
|                          << std::declval<U>()), | ||||
|                   std::true_type()) | ||||
|   test(int); | ||||
|  | ||||
|   template <typename> | ||||
|   static std::false_type test(...); | ||||
|   template <typename> static std::false_type test(...); | ||||
|  | ||||
|   typedef decltype(test<T>(0)) result; | ||||
|   using result = decltype(test<T>(0)); | ||||
|  | ||||
|  public: | ||||
|   static const bool value = result::value; | ||||
| @@ -73,65 +71,51 @@ class is_streamable { | ||||
|  | ||||
| // Write the content of buf to os. | ||||
| template <typename Char> | ||||
| void write(std::basic_ostream<Char> &os, basic_buffer<Char> &buf) { | ||||
|   const Char *data = buf.data(); | ||||
|   typedef std::make_unsigned<std::streamsize>::type UnsignedStreamSize; | ||||
|   UnsignedStreamSize size = buf.size(); | ||||
|   UnsignedStreamSize max_size = | ||||
|       internal::to_unsigned((std::numeric_limits<std::streamsize>::max)()); | ||||
| void write(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((std::numeric_limits<std::streamsize>::max)()); | ||||
|   do { | ||||
|     UnsignedStreamSize n = size <= max_size ? size : max_size; | ||||
|     os.write(data, static_cast<std::streamsize>(n)); | ||||
|     data += n; | ||||
|     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(basic_buffer<Char> &buffer, const T &value) { | ||||
|   internal::formatbuf<Char> format_buf(buffer); | ||||
| void format_value(buffer<Char>& buf, const T& value) { | ||||
|   formatbuf<Char> format_buf(buf); | ||||
|   std::basic_ostream<Char> output(&format_buf); | ||||
|   output.exceptions(std::ios_base::failbit | std::ios_base::badbit); | ||||
|   output << value; | ||||
|   buffer.resize(buffer.size()); | ||||
|   buf.resize(buf.size()); | ||||
| } | ||||
| }  // namespace internal | ||||
|  | ||||
| // Disable conversion to int if T has an overloaded operator<< which is a free | ||||
| // function (not a member of std::ostream). | ||||
| template <typename T, typename Char> | ||||
| struct convert_to_int<T, Char, void> { | ||||
|   static const bool value = | ||||
|     convert_to_int<T, Char, int>::value && | ||||
|     !internal::is_streamable<T, Char>::value; | ||||
| }; | ||||
|  | ||||
| // Formats an object of type T that has an overloaded ostream operator<<. | ||||
| template <typename T, typename Char> | ||||
| struct formatter<T, Char, | ||||
|     typename std::enable_if< | ||||
|       internal::is_streamable<T, Char>::value && | ||||
|       !internal::format_type< | ||||
|         typename buffer_context<Char>::type, T>::value>::type> | ||||
| struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>> | ||||
|     : formatter<basic_string_view<Char>, Char> { | ||||
|  | ||||
|   template <typename Context> | ||||
|   auto format(const T &value, Context &ctx) -> decltype(ctx.out()) { | ||||
|   auto format(const T& value, Context& ctx) -> decltype(ctx.out()) { | ||||
|     basic_memory_buffer<Char> buffer; | ||||
|     internal::format_value(buffer, value); | ||||
|     format_value(buffer, value); | ||||
|     basic_string_view<Char> str(buffer.data(), buffer.size()); | ||||
|     return formatter<basic_string_view<Char>, Char>::format(str, ctx); | ||||
|   } | ||||
| }; | ||||
| }  // namespace internal | ||||
|  | ||||
| template <typename Char> | ||||
| inline void vprint(std::basic_ostream<Char> &os, | ||||
|                    basic_string_view<Char> format_str, | ||||
|                    basic_format_args<typename buffer_context<Char>::type> args) { | ||||
| void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str, | ||||
|             basic_format_args<buffer_context<Char>> args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   internal::vformat_to(buffer, format_str, args); | ||||
|   internal::write(os, buffer); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   Prints formatted data to the stream *os*. | ||||
| @@ -141,12 +125,11 @@ inline void vprint(std::basic_ostream<Char> &os, | ||||
|     fmt::print(cerr, "Don't {}!", "panic"); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename S, typename... Args> | ||||
| inline typename std::enable_if<internal::is_string<S>::value>::type | ||||
| print(std::basic_ostream<FMT_CHAR(S)> &os, const S &format_str, | ||||
|       const Args & ... args) { | ||||
|   internal::checked_args<S, Args...> ca(format_str, args...); | ||||
|   vprint(os, to_string_view(format_str), *ca); | ||||
| template <typename S, typename... Args, | ||||
|           typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>> | ||||
| void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) { | ||||
|   vprint(os, to_string_view(format_str), | ||||
|          {internal::make_args_checked<Args...>(format_str, args...)}); | ||||
| } | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
|   | ||||
| @@ -10,7 +10,7 @@ | ||||
|  | ||||
| #if defined(__MINGW32__) || defined(__CYGWIN__) | ||||
| // Workaround MinGW bug https://sourceforge.net/p/mingw/bugs/2024/. | ||||
| # undef __STRICT_ANSI__ | ||||
| #  undef __STRICT_ANSI__ | ||||
| #endif | ||||
|  | ||||
| #include <errno.h> | ||||
| @@ -22,42 +22,42 @@ | ||||
| #include <cstddef> | ||||
|  | ||||
| #if defined __APPLE__ || defined(__FreeBSD__) | ||||
| # include <xlocale.h>  // for LC_NUMERIC_MASK on OS X | ||||
| #  include <xlocale.h>  // for LC_NUMERIC_MASK on OS X | ||||
| #endif | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| #ifndef FMT_POSIX | ||||
| # if defined(_WIN32) && !defined(__MINGW32__) | ||||
| #  if defined(_WIN32) && !defined(__MINGW32__) | ||||
| // Fix warnings about deprecated symbols. | ||||
| #  define FMT_POSIX(call) _##call | ||||
| # else | ||||
| #  define FMT_POSIX(call) call | ||||
| # endif | ||||
| #    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_POSIX_CALL(call) FMT_SYSTEM(call) | ||||
| #  define FMT_POSIX_CALL(call) FMT_SYSTEM(call) | ||||
| #else | ||||
| # define FMT_SYSTEM(call) call | ||||
| # ifdef _WIN32 | ||||
| #  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 | ||||
| #    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) | ||||
| #  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) | ||||
| #  define FMT_RETRY_VAL(result, expression, error_result) result = (expression) | ||||
| #endif | ||||
|  | ||||
| #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) | ||||
| @@ -69,7 +69,7 @@ FMT_BEGIN_NAMESPACE | ||||
|   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 typedefs for common character types: | ||||
|   You can use one of the following type aliases for common character types: | ||||
|  | ||||
|   +---------------+-----------------------------+ | ||||
|   | Type          | Definition                  | | ||||
| @@ -89,28 +89,27 @@ FMT_BEGIN_NAMESPACE | ||||
|     format(std::string("{}"), 42); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename Char> | ||||
| class basic_cstring_view { | ||||
| template <typename Char> class basic_cstring_view { | ||||
|  private: | ||||
|   const Char *data_; | ||||
|   const Char* data_; | ||||
|  | ||||
|  public: | ||||
|   /** Constructs a string reference object from a C string. */ | ||||
|   basic_cstring_view(const Char *s) : data_(s) {} | ||||
|   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()) {} | ||||
|   basic_cstring_view(const std::basic_string<Char>& s) : data_(s.c_str()) {} | ||||
|  | ||||
|   /** Returns the pointer to a C string. */ | ||||
|   const Char *c_str() const { return data_; } | ||||
|   const Char* c_str() const { return data_; } | ||||
| }; | ||||
|  | ||||
| typedef basic_cstring_view<char> cstring_view; | ||||
| typedef basic_cstring_view<wchar_t> wcstring_view; | ||||
| using cstring_view = basic_cstring_view<char>; | ||||
| using wcstring_view = basic_cstring_view<wchar_t>; | ||||
|  | ||||
| // An error code. | ||||
| class error_code { | ||||
| @@ -126,33 +125,32 @@ class error_code { | ||||
| // A buffered file. | ||||
| class buffered_file { | ||||
|  private: | ||||
|   FILE *file_; | ||||
|   FILE* file_; | ||||
|  | ||||
|   friend class file; | ||||
|  | ||||
|   explicit buffered_file(FILE *f) : file_(f) {} | ||||
|   explicit buffered_file(FILE* f) : file_(f) {} | ||||
|  | ||||
|  public: | ||||
|   // Constructs a buffered_file object which doesn't represent any file. | ||||
|   buffered_file() FMT_NOEXCEPT : file_(FMT_NULL) {} | ||||
|   buffered_file() FMT_NOEXCEPT : file_(nullptr) {} | ||||
|  | ||||
|   // Destroys the object closing the file it represents if any. | ||||
|   FMT_API ~buffered_file() FMT_NOEXCEPT; | ||||
|  | ||||
|  private: | ||||
|   buffered_file(const buffered_file &) = delete; | ||||
|   void operator=(const buffered_file &) = delete; | ||||
|  | ||||
|   buffered_file(const buffered_file&) = delete; | ||||
|   void operator=(const buffered_file&) = delete; | ||||
|  | ||||
|  public: | ||||
|   buffered_file(buffered_file &&other) FMT_NOEXCEPT : file_(other.file_) { | ||||
|     other.file_ = FMT_NULL; | ||||
|   buffered_file(buffered_file&& other) FMT_NOEXCEPT : file_(other.file_) { | ||||
|     other.file_ = nullptr; | ||||
|   } | ||||
|  | ||||
|   buffered_file& operator=(buffered_file &&other) { | ||||
|   buffered_file& operator=(buffered_file&& other) { | ||||
|     close(); | ||||
|     file_ = other.file_; | ||||
|     other.file_ = FMT_NULL; | ||||
|     other.file_ = nullptr; | ||||
|     return *this; | ||||
|   } | ||||
|  | ||||
| @@ -163,18 +161,18 @@ class buffered_file { | ||||
|   FMT_API void close(); | ||||
|  | ||||
|   // Returns the pointer to a FILE object representing this file. | ||||
|   FILE *get() const FMT_NOEXCEPT { return file_; } | ||||
|   FILE* get() const FMT_NOEXCEPT { return file_; } | ||||
|  | ||||
|   // We place parentheses around fileno to workaround a bug in some versions | ||||
|   // of MinGW that define fileno as a macro. | ||||
|   FMT_API int (fileno)() const; | ||||
|   FMT_API int(fileno)() const; | ||||
|  | ||||
|   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) { | ||||
|   inline void print(string_view format_str, const Args&... args) { | ||||
|     vprint(format_str, make_format_args(args...)); | ||||
|   } | ||||
| }; | ||||
| @@ -195,9 +193,9 @@ class file { | ||||
|  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. | ||||
|     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. | ||||
|   }; | ||||
|  | ||||
|   // Constructs a file object which doesn't represent any file. | ||||
| @@ -207,15 +205,13 @@ class file { | ||||
|   FMT_API file(cstring_view path, int oflag); | ||||
|  | ||||
|  private: | ||||
|   file(const file &) = delete; | ||||
|   void operator=(const file &) = delete; | ||||
|   file(const file&) = delete; | ||||
|   void operator=(const file&) = delete; | ||||
|  | ||||
|  public: | ||||
|   file(file &&other) FMT_NOEXCEPT : fd_(other.fd_) { | ||||
|     other.fd_ = -1; | ||||
|   } | ||||
|   file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } | ||||
|  | ||||
|   file& operator=(file &&other) { | ||||
|   file& operator=(file&& other) { | ||||
|     close(); | ||||
|     fd_ = other.fd_; | ||||
|     other.fd_ = -1; | ||||
| @@ -236,10 +232,10 @@ class file { | ||||
|   FMT_API long long size() const; | ||||
|  | ||||
|   // Attempts to read count bytes from the file into the specified buffer. | ||||
|   FMT_API std::size_t read(void *buffer, std::size_t count); | ||||
|   FMT_API std::size_t read(void* buffer, std::size_t count); | ||||
|  | ||||
|   // Attempts to write count bytes from the specified buffer to the file. | ||||
|   FMT_API std::size_t write(const void *buffer, std::size_t count); | ||||
|   FMT_API std::size_t write(const void* buffer, std::size_t count); | ||||
|  | ||||
|   // Duplicates a file descriptor with the dup function and returns | ||||
|   // the duplicate as a file object. | ||||
| @@ -251,68 +247,59 @@ class file { | ||||
|  | ||||
|   // Makes fd be the copy of this file descriptor, closing fd first if | ||||
|   // necessary. | ||||
|   FMT_API void dup2(int fd, error_code &ec) FMT_NOEXCEPT; | ||||
|   FMT_API void dup2(int fd, error_code& ec) FMT_NOEXCEPT; | ||||
|  | ||||
|   // Creates a pipe setting up read_end and write_end file objects for reading | ||||
|   // and writing respectively. | ||||
|   FMT_API static void pipe(file &read_end, file &write_end); | ||||
|   FMT_API 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. | ||||
|   FMT_API buffered_file fdopen(const char *mode); | ||||
|   FMT_API buffered_file fdopen(const char* mode); | ||||
| }; | ||||
|  | ||||
| // Returns the memory page size. | ||||
| long getpagesize(); | ||||
|  | ||||
| #if (defined(LC_NUMERIC_MASK) || defined(_MSC_VER)) && \ | ||||
|     !defined(__ANDROID__) && !defined(__CYGWIN__) && !defined(__OpenBSD__) && \ | ||||
|     !defined(__NEWLIB_H__) | ||||
| # define FMT_LOCALE | ||||
| #endif | ||||
|  | ||||
| #ifdef FMT_LOCALE | ||||
| // A "C" numeric locale. | ||||
| class Locale { | ||||
|  private: | ||||
| # ifdef _MSC_VER | ||||
|   typedef _locale_t locale_t; | ||||
| #  ifdef _WIN32 | ||||
|   using locale_t = _locale_t; | ||||
|  | ||||
|   enum { LC_NUMERIC_MASK = LC_NUMERIC }; | ||||
|  | ||||
|   static locale_t newlocale(int category_mask, const char *locale, locale_t) { | ||||
|   static locale_t newlocale(int category_mask, const char* locale, locale_t) { | ||||
|     return _create_locale(category_mask, locale); | ||||
|   } | ||||
|  | ||||
|   static void freelocale(locale_t locale) { | ||||
|     _free_locale(locale); | ||||
|   } | ||||
|   static void freelocale(locale_t locale) { _free_locale(locale); } | ||||
|  | ||||
|   static double strtod_l(const char *nptr, char **endptr, _locale_t locale) { | ||||
|   static double strtod_l(const char* nptr, char** endptr, _locale_t locale) { | ||||
|     return _strtod_l(nptr, endptr, locale); | ||||
|   } | ||||
| # endif | ||||
| #  endif | ||||
|  | ||||
|   locale_t locale_; | ||||
|  | ||||
|   Locale(const Locale &) = delete; | ||||
|   void operator=(const Locale &) = delete; | ||||
|   Locale(const Locale&) = delete; | ||||
|   void operator=(const Locale&) = delete; | ||||
|  | ||||
|  public: | ||||
|   typedef locale_t Type; | ||||
|   using type = locale_t; | ||||
|  | ||||
|   Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", FMT_NULL)) { | ||||
|     if (!locale_) | ||||
|       FMT_THROW(system_error(errno, "cannot create locale")); | ||||
|   Locale() : locale_(newlocale(LC_NUMERIC_MASK, "C", nullptr)) { | ||||
|     if (!locale_) FMT_THROW(system_error(errno, "cannot create locale")); | ||||
|   } | ||||
|   ~Locale() { freelocale(locale_); } | ||||
|  | ||||
|   Type get() const { return locale_; } | ||||
|   type get() const { return locale_; } | ||||
|  | ||||
|   // Converts string to floating-point number and advances str past the end | ||||
|   // of the parsed input. | ||||
|   double strtod(const char *&str) const { | ||||
|     char *end = FMT_NULL; | ||||
|   double strtod(const char*& str) const { | ||||
|     char* end = nullptr; | ||||
|     double result = strtod_l(str, &end, locale_); | ||||
|     str = end; | ||||
|     return result; | ||||
|   | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,4 +1,4 @@ | ||||
| // Formatting library for C++ - the core API | ||||
| // Formatting library for C++ - experimental range support | ||||
| // | ||||
| // Copyright (c) 2012 - present, Victor Zverovich | ||||
| // All rights reserved. | ||||
| @@ -12,20 +12,19 @@ | ||||
| #ifndef FMT_RANGES_H_ | ||||
| #define FMT_RANGES_H_ | ||||
|  | ||||
| #include "format.h" | ||||
| #include <type_traits> | ||||
| #include "format.h" | ||||
|  | ||||
| // output only up to N items from the range. | ||||
| #ifndef FMT_RANGE_OUTPUT_LENGTH_LIMIT | ||||
| # define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256 | ||||
| #  define FMT_RANGE_OUTPUT_LENGTH_LIMIT 256 | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| template <typename Char> | ||||
| struct formatting_base { | ||||
| template <typename Char> struct formatting_base { | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
| }; | ||||
| @@ -33,7 +32,8 @@ struct formatting_base { | ||||
| template <typename Char, typename Enable = void> | ||||
| struct formatting_range : formatting_base<Char> { | ||||
|   static FMT_CONSTEXPR_DECL const std::size_t range_length_limit = | ||||
|       FMT_RANGE_OUTPUT_LENGTH_LIMIT; // output only up to N items from the range. | ||||
|       FMT_RANGE_OUTPUT_LENGTH_LIMIT;  // output only up to N items from the | ||||
|                                       // range. | ||||
|   Char prefix; | ||||
|   Char delimiter; | ||||
|   Char postfix; | ||||
| @@ -55,87 +55,78 @@ struct formatting_tuple : formatting_base<Char> { | ||||
| namespace internal { | ||||
|  | ||||
| template <typename RangeT, typename OutputIterator> | ||||
| void copy(const RangeT &range, OutputIterator out) { | ||||
| OutputIterator copy(const RangeT& range, OutputIterator out) { | ||||
|   for (auto it = range.begin(), end = range.end(); it != end; ++it) | ||||
|     *out++ = *it; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| template <typename OutputIterator> | ||||
| void copy(const char *str, OutputIterator out) { | ||||
|   const char *p_curr = str; | ||||
|   while (*p_curr) { | ||||
|     *out++ = *p_curr++; | ||||
|   } | ||||
| OutputIterator copy(const char* str, OutputIterator out) { | ||||
|   while (*str) *out++ = *str++; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| template <typename OutputIterator> | ||||
| void copy(char ch, OutputIterator out) { | ||||
| OutputIterator copy(char ch, OutputIterator out) { | ||||
|   *out++ = ch; | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| /// Return true value if T has std::string interface, like std::string_view. | ||||
| template <typename T> | ||||
| class is_like_std_string { | ||||
| template <typename T> class is_like_std_string { | ||||
|   template <typename U> | ||||
|   static auto check(U *p) -> | ||||
|     decltype(p->find('a'), p->length(), p->data(), int()); | ||||
|   template <typename> | ||||
|   static void check(...); | ||||
|   static auto check(U* p) | ||||
|       -> decltype((void)p->find('a'), p->length(), (void)p->data(), int()); | ||||
|   template <typename> static void check(...); | ||||
|  | ||||
|  public: | ||||
|   static FMT_CONSTEXPR_DECL const bool value = | ||||
|     !std::is_void<decltype(check<T>(FMT_NULL))>::value; | ||||
|       is_string<T>::value || !std::is_void<decltype(check<T>(nullptr))>::value; | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| struct is_like_std_string<fmt::basic_string_view<Char>> : std::true_type {}; | ||||
|  | ||||
| template <typename... Ts> | ||||
| struct conditional_helper {}; | ||||
| template <typename... Ts> struct conditional_helper {}; | ||||
|  | ||||
| template <typename T, typename _ = void> | ||||
| struct is_range_ : std::false_type {}; | ||||
| template <typename T, typename _ = void> struct is_range_ : std::false_type {}; | ||||
|  | ||||
| #if !FMT_MSC_VER || FMT_MSC_VER > 1800 | ||||
| template <typename T> | ||||
| struct is_range_<T, typename std::conditional< | ||||
|                     false, | ||||
|                     conditional_helper<decltype(internal::declval<T>().begin()), | ||||
|                                        decltype(internal::declval<T>().end())>, | ||||
|                     void>::type> : std::true_type {}; | ||||
| struct is_range_< | ||||
|     T, conditional_t<false, | ||||
|                      conditional_helper<decltype(std::declval<T>().begin()), | ||||
|                                         decltype(std::declval<T>().end())>, | ||||
|                      void>> : std::true_type {}; | ||||
| #endif | ||||
|  | ||||
| /// tuple_size and tuple_element check. | ||||
| template <typename T> | ||||
| class is_tuple_like_ { | ||||
| template <typename T> class is_tuple_like_ { | ||||
|   template <typename U> | ||||
|   static auto check(U *p) -> | ||||
|     decltype(std::tuple_size<U>::value, | ||||
|       internal::declval<typename std::tuple_element<0, U>::type>(), int()); | ||||
|   template <typename> | ||||
|   static void check(...); | ||||
|   static auto check(U* p) | ||||
|       -> decltype(std::tuple_size<U>::value, | ||||
|                   (void)std::declval<typename std::tuple_element<0, U>::type>(), | ||||
|                   int()); | ||||
|   template <typename> static void check(...); | ||||
|  | ||||
|  public: | ||||
|   static FMT_CONSTEXPR_DECL const bool value = | ||||
|     !std::is_void<decltype(check<T>(FMT_NULL))>::value; | ||||
|       !std::is_void<decltype(check<T>(nullptr))>::value; | ||||
| }; | ||||
|  | ||||
| // Check for integer_sequence | ||||
| #if defined(__cpp_lib_integer_sequence) || FMT_MSC_VER >= 1900 | ||||
| template <typename T, T... N> | ||||
| using integer_sequence = std::integer_sequence<T, N...>; | ||||
| template <std::size_t... N> | ||||
| using index_sequence = std::index_sequence<N...>; | ||||
| template <std::size_t... N> using index_sequence = std::index_sequence<N...>; | ||||
| template <std::size_t N> | ||||
| using make_index_sequence = std::make_index_sequence<N>; | ||||
| #else | ||||
| template <typename T, T... N> | ||||
| struct integer_sequence { | ||||
|   typedef T value_type; | ||||
| template <typename T, T... N> struct integer_sequence { | ||||
|   using value_type = T; | ||||
|  | ||||
|   static FMT_CONSTEXPR std::size_t size() { | ||||
|     return sizeof...(N); | ||||
|   } | ||||
|   static FMT_CONSTEXPR std::size_t size() { return sizeof...(N); } | ||||
| }; | ||||
|  | ||||
| template <std::size_t... N> | ||||
| @@ -151,7 +142,7 @@ using make_index_sequence = make_integer_sequence<std::size_t, N>; | ||||
| #endif | ||||
|  | ||||
| template <class Tuple, class F, size_t... Is> | ||||
| void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT { | ||||
| void for_each(index_sequence<Is...>, Tuple&& tup, F&& f) FMT_NOEXCEPT { | ||||
|   using std::get; | ||||
|   // using free function get<I>(T) now. | ||||
|   const int _[] = {0, ((void)f(get<Is>(tup)), 0)...}; | ||||
| @@ -159,26 +150,25 @@ void for_each(index_sequence<Is...>, Tuple &&tup, F &&f) FMT_NOEXCEPT { | ||||
| } | ||||
|  | ||||
| template <class T> | ||||
| FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> | ||||
| get_indexes(T const &) { return {}; } | ||||
| FMT_CONSTEXPR make_index_sequence<std::tuple_size<T>::value> get_indexes( | ||||
|     T const&) { | ||||
|   return {}; | ||||
| } | ||||
|  | ||||
| template <class Tuple, class F> | ||||
| void for_each(Tuple &&tup, F &&f) { | ||||
| template <class Tuple, class F> void for_each(Tuple&& tup, F&& f) { | ||||
|   const auto indexes = get_indexes(tup); | ||||
|   for_each(indexes, std::forward<Tuple>(tup), std::forward<F>(f)); | ||||
| } | ||||
|  | ||||
| template<typename Arg> | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&, | ||||
|   typename std::enable_if< | ||||
|     !is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) { | ||||
| template <typename Arg, FMT_ENABLE_IF(!is_like_std_string< | ||||
|                                       typename std::decay<Arg>::type>::value)> | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) { | ||||
|   return add_space ? " {}" : "{}"; | ||||
| } | ||||
|  | ||||
| template<typename Arg> | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&, | ||||
|   typename std::enable_if< | ||||
|     is_like_std_string<typename std::decay<Arg>::type>::value>::type* = nullptr) { | ||||
| template <typename Arg, FMT_ENABLE_IF(is_like_std_string< | ||||
|                                       typename std::decay<Arg>::type>::value)> | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const Arg&) { | ||||
|   return add_space ? " \"{}\"" : "\"{}\""; | ||||
| } | ||||
|  | ||||
| @@ -186,61 +176,58 @@ FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char*) { | ||||
|   return add_space ? " \"{}\"" : "\"{}\""; | ||||
| } | ||||
| FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t*) { | ||||
|     return add_space ? L" \"{}\"" : L"\"{}\""; | ||||
|   return add_space ? L" \"{}\"" : L"\"{}\""; | ||||
| } | ||||
|  | ||||
| FMT_CONSTEXPR const char* format_str_quoted(bool add_space, const char) { | ||||
|     return add_space ? " '{}'" : "'{}'"; | ||||
|   return add_space ? " '{}'" : "'{}'"; | ||||
| } | ||||
| FMT_CONSTEXPR const wchar_t* format_str_quoted(bool add_space, const wchar_t) { | ||||
|     return add_space ? L" '{}'" : L"'{}'"; | ||||
|   return add_space ? L" '{}'" : L"'{}'"; | ||||
| } | ||||
|  | ||||
| }  // namespace internal | ||||
|  | ||||
| template <typename T> | ||||
| struct is_tuple_like { | ||||
| template <typename T> struct is_tuple_like { | ||||
|   static FMT_CONSTEXPR_DECL const bool value = | ||||
|     internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value; | ||||
|       internal::is_tuple_like_<T>::value && !internal::is_range_<T>::value; | ||||
| }; | ||||
|  | ||||
| template <typename TupleT, typename Char> | ||||
| struct formatter<TupleT, Char, | ||||
|     typename std::enable_if<fmt::is_tuple_like<TupleT>::value>::type> { | ||||
| private: | ||||
| struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> { | ||||
|  private: | ||||
|   // C++11 generic lambda for format() | ||||
|   template <typename FormatContext> | ||||
|   struct format_each { | ||||
|     template <typename T> | ||||
|     void operator()(const T& v) { | ||||
|   template <typename FormatContext> struct format_each { | ||||
|     template <typename T> void operator()(const T& v) { | ||||
|       if (i > 0) { | ||||
|         if (formatting.add_prepostfix_space) { | ||||
|           *out++ = ' '; | ||||
|         } | ||||
|         internal::copy(formatting.delimiter, out); | ||||
|         out = internal::copy(formatting.delimiter, out); | ||||
|       } | ||||
|       format_to(out, | ||||
|                 internal::format_str_quoted( | ||||
|                     (formatting.add_delimiter_spaces && i > 0), v), | ||||
|                 v); | ||||
|       out = format_to(out, | ||||
|                       internal::format_str_quoted( | ||||
|                           (formatting.add_delimiter_spaces && i > 0), v), | ||||
|                       v); | ||||
|       ++i; | ||||
|     } | ||||
|  | ||||
|     formatting_tuple<Char>& formatting; | ||||
|     std::size_t& i; | ||||
|     typename std::add_lvalue_reference<decltype(std::declval<FormatContext>().out())>::type out; | ||||
|     typename std::add_lvalue_reference<decltype( | ||||
|         std::declval<FormatContext>().out())>::type out; | ||||
|   }; | ||||
|  | ||||
| public: | ||||
|  public: | ||||
|   formatting_tuple<Char> formatting; | ||||
|  | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return formatting.parse(ctx); | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext = format_context> | ||||
|   auto format(const TupleT &values, FormatContext &ctx) -> decltype(ctx.out()) { | ||||
|   auto format(const TupleT& values, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|     auto out = ctx.out(); | ||||
|     std::size_t i = 0; | ||||
|     internal::copy(formatting.prefix, out); | ||||
| @@ -255,54 +242,47 @@ public: | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct is_range { | ||||
| template <typename T, typename Char> struct is_range { | ||||
|   static FMT_CONSTEXPR_DECL const bool value = | ||||
|     internal::is_range_<T>::value && !internal::is_like_std_string<T>::value; | ||||
|       internal::is_range_<T>::value && | ||||
|       !internal::is_like_std_string<T>::value && | ||||
|       !std::is_convertible<T, std::basic_string<Char>>::value; | ||||
| }; | ||||
|  | ||||
| template <typename RangeT, typename Char> | ||||
| struct formatter<RangeT, Char, | ||||
|     typename std::enable_if<fmt::is_range<RangeT>::value>::type> { | ||||
|  | ||||
|                  enable_if_t<fmt::is_range<RangeT, Char>::value>> { | ||||
|   formatting_range<Char> formatting; | ||||
|  | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return formatting.parse(ctx); | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   typename FormatContext::iterator format( | ||||
|       const RangeT &values, FormatContext &ctx) { | ||||
|     auto out = ctx.out(); | ||||
|     internal::copy(formatting.prefix, out); | ||||
|   typename FormatContext::iterator format(const RangeT& values, | ||||
|                                           FormatContext& ctx) { | ||||
|     auto out = internal::copy(formatting.prefix, ctx.out()); | ||||
|     std::size_t i = 0; | ||||
|     for (auto it = values.begin(), end = values.end(); it != end; ++it) { | ||||
|       if (i > 0) { | ||||
|         if (formatting.add_prepostfix_space) { | ||||
|           *out++ = ' '; | ||||
|         } | ||||
|         internal::copy(formatting.delimiter, out); | ||||
|         if (formatting.add_prepostfix_space) *out++ = ' '; | ||||
|         out = internal::copy(formatting.delimiter, out); | ||||
|       } | ||||
|       format_to(out, | ||||
|                 internal::format_str_quoted( | ||||
|                     (formatting.add_delimiter_spaces && i > 0), *it), | ||||
|                 *it); | ||||
|       out = format_to(out, | ||||
|                       internal::format_str_quoted( | ||||
|                           (formatting.add_delimiter_spaces && i > 0), *it), | ||||
|                       *it); | ||||
|       if (++i > formatting.range_length_limit) { | ||||
|         format_to(out, " ... <other elements>"); | ||||
|         out = format_to(out, " ... <other elements>"); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
|     if (formatting.add_prepostfix_space) { | ||||
|       *out++ = ' '; | ||||
|     } | ||||
|     internal::copy(formatting.postfix, out); | ||||
|     return ctx.out(); | ||||
|     if (formatting.add_prepostfix_space) *out++ = ' '; | ||||
|     return internal::copy(formatting.postfix, out); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif // FMT_RANGES_H_ | ||||
|  | ||||
| #endif  // FMT_RANGES_H_ | ||||
|   | ||||
							
								
								
									
										293
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/safe-duration-cast.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										293
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/safe-duration-cast.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,293 @@ | ||||
| /* | ||||
|  * For conversion between std::chrono::durations without undefined | ||||
|  * behaviour or erroneous results. | ||||
|  * This is a stripped down version of duration_cast, for inclusion in fmt. | ||||
|  * See https://github.com/pauldreik/safe_duration_cast | ||||
|  * | ||||
|  * Copyright Paul Dreik 2019 | ||||
|  * | ||||
|  * This file is licensed under the fmt license, see format.h | ||||
|  */ | ||||
|  | ||||
| #include <chrono> | ||||
| #include <cmath> | ||||
| #include <limits> | ||||
| #include <type_traits> | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| namespace safe_duration_cast { | ||||
|  | ||||
| template <typename To, typename From, | ||||
|           FMT_ENABLE_IF(!std::is_same<From, To>::value && | ||||
|                         std::numeric_limits<From>::is_signed == | ||||
|                             std::numeric_limits<To>::is_signed)> | ||||
| FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { | ||||
|   ec = 0; | ||||
|   using F = std::numeric_limits<From>; | ||||
|   using T = std::numeric_limits<To>; | ||||
|   static_assert(F::is_integer, "From must be integral"); | ||||
|   static_assert(T::is_integer, "To must be integral"); | ||||
|  | ||||
|   // A and B are both signed, or both unsigned. | ||||
|   if (F::digits <= T::digits) { | ||||
|     // From fits in To without any problem. | ||||
|   } else { | ||||
|     // From does not always fit in To, resort to a dynamic check. | ||||
|     if (from < T::min() || from > T::max()) { | ||||
|       // outside range. | ||||
|       ec = 1; | ||||
|       return {}; | ||||
|     } | ||||
|   } | ||||
|   return static_cast<To>(from); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * converts From to To, without loss. If the dynamic value of from | ||||
|  * can't be converted to To without loss, ec is set. | ||||
|  */ | ||||
| template <typename To, typename From, | ||||
|           FMT_ENABLE_IF(!std::is_same<From, To>::value && | ||||
|                         std::numeric_limits<From>::is_signed != | ||||
|                             std::numeric_limits<To>::is_signed)> | ||||
| FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { | ||||
|   ec = 0; | ||||
|   using F = std::numeric_limits<From>; | ||||
|   using T = std::numeric_limits<To>; | ||||
|   static_assert(F::is_integer, "From must be integral"); | ||||
|   static_assert(T::is_integer, "To must be integral"); | ||||
|  | ||||
|   if (F::is_signed && !T::is_signed) { | ||||
|     // From may be negative, not allowed! | ||||
|     if (from < 0) { | ||||
|       ec = 1; | ||||
|       return {}; | ||||
|     } | ||||
|  | ||||
|     // From is positive. Can it always fit in To? | ||||
|     if (F::digits <= T::digits) { | ||||
|       // yes, From always fits in To. | ||||
|     } else { | ||||
|       // from may not fit in To, we have to do a dynamic check | ||||
|       if (from > static_cast<From>(T::max())) { | ||||
|         ec = 1; | ||||
|         return {}; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   if (!F::is_signed && T::is_signed) { | ||||
|     // can from be held in To? | ||||
|     if (F::digits < T::digits) { | ||||
|       // yes, From always fits in To. | ||||
|     } else { | ||||
|       // from may not fit in To, we have to do a dynamic check | ||||
|       if (from > static_cast<From>(T::max())) { | ||||
|         // outside range. | ||||
|         ec = 1; | ||||
|         return {}; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   // reaching here means all is ok for lossless conversion. | ||||
|   return static_cast<To>(from); | ||||
|  | ||||
| }  // function | ||||
|  | ||||
| template <typename To, typename From, | ||||
|           FMT_ENABLE_IF(std::is_same<From, To>::value)> | ||||
| FMT_CONSTEXPR To lossless_integral_conversion(const From from, int& ec) { | ||||
|   ec = 0; | ||||
|   return from; | ||||
| }  // function | ||||
|  | ||||
| // clang-format off | ||||
| /** | ||||
|  * converts From to To if possible, otherwise ec is set. | ||||
|  * | ||||
|  * input                            |    output | ||||
|  * ---------------------------------|--------------- | ||||
|  * NaN                              | NaN | ||||
|  * Inf                              | Inf | ||||
|  * normal, fits in output           | converted (possibly lossy) | ||||
|  * normal, does not fit in output   | ec is set | ||||
|  * subnormal                        | best effort | ||||
|  * -Inf                             | -Inf | ||||
|  */ | ||||
| // clang-format on | ||||
| template <typename To, typename From, | ||||
|           FMT_ENABLE_IF(!std::is_same<From, To>::value)> | ||||
| FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) { | ||||
|   ec = 0; | ||||
|   using T = std::numeric_limits<To>; | ||||
|   static_assert(std::is_floating_point<From>::value, "From must be floating"); | ||||
|   static_assert(std::is_floating_point<To>::value, "To must be floating"); | ||||
|  | ||||
|   // catch the only happy case | ||||
|   if (std::isfinite(from)) { | ||||
|     if (from >= T::lowest() && from <= T::max()) { | ||||
|       return static_cast<To>(from); | ||||
|     } | ||||
|     // not within range. | ||||
|     ec = 1; | ||||
|     return {}; | ||||
|   } | ||||
|  | ||||
|   // nan and inf will be preserved | ||||
|   return static_cast<To>(from); | ||||
| }  // function | ||||
|  | ||||
| template <typename To, typename From, | ||||
|           FMT_ENABLE_IF(std::is_same<From, To>::value)> | ||||
| FMT_CONSTEXPR To safe_float_conversion(const From from, int& ec) { | ||||
|   ec = 0; | ||||
|   static_assert(std::is_floating_point<From>::value, "From must be floating"); | ||||
|   return from; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * safe duration cast between integral durations | ||||
|  */ | ||||
| template <typename To, typename FromRep, typename FromPeriod, | ||||
|           FMT_ENABLE_IF(std::is_integral<FromRep>::value), | ||||
|           FMT_ENABLE_IF(std::is_integral<typename To::rep>::value)> | ||||
| To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from, | ||||
|                       int& ec) { | ||||
|   using From = std::chrono::duration<FromRep, FromPeriod>; | ||||
|   ec = 0; | ||||
|   // the basic idea is that we need to convert from count() in the from type | ||||
|   // to count() in the To type, by multiplying it with this: | ||||
|   using Factor = std::ratio_divide<typename From::period, typename To::period>; | ||||
|  | ||||
|   static_assert(Factor::num > 0, "num must be positive"); | ||||
|   static_assert(Factor::den > 0, "den must be positive"); | ||||
|  | ||||
|   // the conversion is like this: multiply from.count() with Factor::num | ||||
|   // /Factor::den and convert it to To::rep, all this without | ||||
|   // overflow/underflow. let's start by finding a suitable type that can hold | ||||
|   // both To, From and Factor::num | ||||
|   using IntermediateRep = | ||||
|       typename std::common_type<typename From::rep, typename To::rep, | ||||
|                                 decltype(Factor::num)>::type; | ||||
|  | ||||
|   // safe conversion to IntermediateRep | ||||
|   IntermediateRep count = | ||||
|       lossless_integral_conversion<IntermediateRep>(from.count(), ec); | ||||
|   if (ec) { | ||||
|     return {}; | ||||
|   } | ||||
|   // multiply with Factor::num without overflow or underflow | ||||
|   if (Factor::num != 1) { | ||||
|     constexpr auto max1 = | ||||
|         std::numeric_limits<IntermediateRep>::max() / Factor::num; | ||||
|     if (count > max1) { | ||||
|       ec = 1; | ||||
|       return {}; | ||||
|     } | ||||
|     constexpr auto min1 = | ||||
|         std::numeric_limits<IntermediateRep>::min() / Factor::num; | ||||
|     if (count < min1) { | ||||
|       ec = 1; | ||||
|       return {}; | ||||
|     } | ||||
|     count *= Factor::num; | ||||
|   } | ||||
|  | ||||
|   // this can't go wrong, right? den>0 is checked earlier. | ||||
|   if (Factor::den != 1) { | ||||
|     count /= Factor::den; | ||||
|   } | ||||
|   // convert to the to type, safely | ||||
|   using ToRep = typename To::rep; | ||||
|   const ToRep tocount = lossless_integral_conversion<ToRep>(count, ec); | ||||
|   if (ec) { | ||||
|     return {}; | ||||
|   } | ||||
|   return To{tocount}; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * safe duration_cast between floating point durations | ||||
|  */ | ||||
| template <typename To, typename FromRep, typename FromPeriod, | ||||
|           FMT_ENABLE_IF(std::is_floating_point<FromRep>::value), | ||||
|           FMT_ENABLE_IF(std::is_floating_point<typename To::rep>::value)> | ||||
| To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from, | ||||
|                       int& ec) { | ||||
|   using From = std::chrono::duration<FromRep, FromPeriod>; | ||||
|   ec = 0; | ||||
|   if (std::isnan(from.count())) { | ||||
|     // nan in, gives nan out. easy. | ||||
|     return To{std::numeric_limits<typename To::rep>::quiet_NaN()}; | ||||
|   } | ||||
|   // maybe we should also check if from is denormal, and decide what to do about | ||||
|   // it. | ||||
|  | ||||
|   // +-inf should be preserved. | ||||
|   if (std::isinf(from.count())) { | ||||
|     return To{from.count()}; | ||||
|   } | ||||
|  | ||||
|   // the basic idea is that we need to convert from count() in the from type | ||||
|   // to count() in the To type, by multiplying it with this: | ||||
|   using Factor = std::ratio_divide<typename From::period, typename To::period>; | ||||
|  | ||||
|   static_assert(Factor::num > 0, "num must be positive"); | ||||
|   static_assert(Factor::den > 0, "den must be positive"); | ||||
|  | ||||
|   // the conversion is like this: multiply from.count() with Factor::num | ||||
|   // /Factor::den and convert it to To::rep, all this without | ||||
|   // overflow/underflow. let's start by finding a suitable type that can hold | ||||
|   // both To, From and Factor::num | ||||
|   using IntermediateRep = | ||||
|       typename std::common_type<typename From::rep, typename To::rep, | ||||
|                                 decltype(Factor::num)>::type; | ||||
|  | ||||
|   // force conversion of From::rep -> IntermediateRep to be safe, | ||||
|   // even if it will never happen be narrowing in this context. | ||||
|   IntermediateRep count = | ||||
|       safe_float_conversion<IntermediateRep>(from.count(), ec); | ||||
|   if (ec) { | ||||
|     return {}; | ||||
|   } | ||||
|  | ||||
|   // multiply with Factor::num without overflow or underflow | ||||
|   if (Factor::num != 1) { | ||||
|     constexpr auto max1 = std::numeric_limits<IntermediateRep>::max() / | ||||
|                           static_cast<IntermediateRep>(Factor::num); | ||||
|     if (count > max1) { | ||||
|       ec = 1; | ||||
|       return {}; | ||||
|     } | ||||
|     constexpr auto min1 = std::numeric_limits<IntermediateRep>::lowest() / | ||||
|                           static_cast<IntermediateRep>(Factor::num); | ||||
|     if (count < min1) { | ||||
|       ec = 1; | ||||
|       return {}; | ||||
|     } | ||||
|     count *= static_cast<IntermediateRep>(Factor::num); | ||||
|   } | ||||
|  | ||||
|   // this can't go wrong, right? den>0 is checked earlier. | ||||
|   if (Factor::den != 1) { | ||||
|     using common_t = typename std::common_type<IntermediateRep, intmax_t>::type; | ||||
|     count /= static_cast<common_t>(Factor::den); | ||||
|   } | ||||
|  | ||||
|   // convert to the to type, safely | ||||
|   using ToRep = typename To::rep; | ||||
|  | ||||
|   const ToRep tocount = safe_float_conversion<ToRep>(count, ec); | ||||
|   if (ec) { | ||||
|     return {}; | ||||
|   } | ||||
|   return To{tocount}; | ||||
| } | ||||
|  | ||||
| }  // namespace safe_duration_cast | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
							
								
								
									
										160
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/time.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										160
									
								
								third_party/spdlog/include/spdlog/fmt/bundled/time.h
									
									
									
									
										vendored
									
									
								
							| @@ -1,160 +0,0 @@ | ||||
| // Formatting library for C++ - time formatting | ||||
| // | ||||
| // Copyright (c) 2012 - present, Victor Zverovich | ||||
| // All rights reserved. | ||||
| // | ||||
| // For the license information refer to format.h. | ||||
|  | ||||
| #ifndef FMT_TIME_H_ | ||||
| #define FMT_TIME_H_ | ||||
|  | ||||
| #include "format.h" | ||||
| #include <ctime> | ||||
| #include <locale> | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| // Prevents expansion of a preceding token as a function-style macro. | ||||
| // Usage: f FMT_NOMACRO() | ||||
| #define FMT_NOMACRO | ||||
|  | ||||
| namespace internal{ | ||||
| inline null<> localtime_r FMT_NOMACRO(...) { return null<>(); } | ||||
| inline null<> localtime_s(...) { return null<>(); } | ||||
| inline null<> gmtime_r(...) { return null<>(); } | ||||
| inline null<> gmtime_s(...) { return null<>(); } | ||||
| }  // namespace internal | ||||
|  | ||||
| // Thread-safe replacement for std::localtime | ||||
| inline std::tm localtime(std::time_t time) { | ||||
|   struct dispatcher { | ||||
|     std::time_t time_; | ||||
|     std::tm tm_; | ||||
|  | ||||
|     dispatcher(std::time_t t): time_(t) {} | ||||
|  | ||||
|     bool run() { | ||||
|       using namespace fmt::internal; | ||||
|       return handle(localtime_r(&time_, &tm_)); | ||||
|     } | ||||
|  | ||||
|     bool handle(std::tm *tm) { return tm != FMT_NULL; } | ||||
|  | ||||
|     bool handle(internal::null<>) { | ||||
|       using namespace fmt::internal; | ||||
|       return fallback(localtime_s(&tm_, &time_)); | ||||
|     } | ||||
|  | ||||
|     bool fallback(int res) { return res == 0; } | ||||
|  | ||||
| #if !FMT_MSC_VER | ||||
|     bool fallback(internal::null<>) { | ||||
|       using namespace fmt::internal; | ||||
|       std::tm *tm = std::localtime(&time_); | ||||
|       if (tm) tm_ = *tm; | ||||
|       return tm != FMT_NULL; | ||||
|     } | ||||
| #endif | ||||
|   }; | ||||
|   dispatcher lt(time); | ||||
|   // Too big time values may be unsupported. | ||||
|   if (!lt.run()) | ||||
|     FMT_THROW(format_error("time_t value out of range")); | ||||
|   return lt.tm_; | ||||
| } | ||||
|  | ||||
| // Thread-safe replacement for std::gmtime | ||||
| inline std::tm gmtime(std::time_t time) { | ||||
|   struct dispatcher { | ||||
|     std::time_t time_; | ||||
|     std::tm tm_; | ||||
|  | ||||
|     dispatcher(std::time_t t): time_(t) {} | ||||
|  | ||||
|     bool run() { | ||||
|       using namespace fmt::internal; | ||||
|       return handle(gmtime_r(&time_, &tm_)); | ||||
|     } | ||||
|  | ||||
|     bool handle(std::tm *tm) { return tm != FMT_NULL; } | ||||
|  | ||||
|     bool handle(internal::null<>) { | ||||
|       using namespace fmt::internal; | ||||
|       return fallback(gmtime_s(&tm_, &time_)); | ||||
|     } | ||||
|  | ||||
|     bool fallback(int res) { return res == 0; } | ||||
|  | ||||
| #if !FMT_MSC_VER | ||||
|     bool fallback(internal::null<>) { | ||||
|       std::tm *tm = std::gmtime(&time_); | ||||
|       if (tm) tm_ = *tm; | ||||
|       return tm != FMT_NULL; | ||||
|     } | ||||
| #endif | ||||
|   }; | ||||
|   dispatcher gt(time); | ||||
|   // Too big time values may be unsupported. | ||||
|   if (!gt.run()) | ||||
|     FMT_THROW(format_error("time_t value out of range")); | ||||
|   return gt.tm_; | ||||
| } | ||||
|  | ||||
| namespace internal { | ||||
| inline std::size_t strftime(char *str, std::size_t count, const char *format, | ||||
|                             const std::tm *time) { | ||||
|   return std::strftime(str, count, format, time); | ||||
| } | ||||
|  | ||||
| inline std::size_t strftime(wchar_t *str, std::size_t count, | ||||
|                             const wchar_t *format, const std::tm *time) { | ||||
|   return std::wcsftime(str, count, format, time); | ||||
| } | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| struct formatter<std::tm, Char> { | ||||
|   template <typename ParseContext> | ||||
|   auto parse(ParseContext &ctx) -> decltype(ctx.begin()) { | ||||
|     auto it = ctx.begin(); | ||||
|     if (it != ctx.end() && *it == ':') | ||||
|       ++it; | ||||
|     auto end = it; | ||||
|     while (end != ctx.end() && *end != '}') | ||||
|       ++end; | ||||
|     tm_format.reserve(internal::to_unsigned(end - it + 1)); | ||||
|     tm_format.append(it, end); | ||||
|     tm_format.push_back('\0'); | ||||
|     return end; | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(const std::tm &tm, FormatContext &ctx) -> decltype(ctx.out()) { | ||||
|     basic_memory_buffer<Char> buf; | ||||
|     std::size_t start = buf.size(); | ||||
|     for (;;) { | ||||
|       std::size_t size = buf.capacity() - start; | ||||
|       std::size_t count = | ||||
|         internal::strftime(&buf[start], size, &tm_format[0], &tm); | ||||
|       if (count != 0) { | ||||
|         buf.resize(start + count); | ||||
|         break; | ||||
|       } | ||||
|       if (size >= tm_format.size() * 256) { | ||||
|         // If the buffer is 256 times larger than the format string, assume | ||||
|         // that `strftime` gives an empty result. There doesn't seem to be a | ||||
|         // better way to distinguish the two cases: | ||||
|         // https://github.com/fmtlib/fmt/issues/367 | ||||
|         break; | ||||
|       } | ||||
|       const std::size_t MIN_GROWTH = 10; | ||||
|       buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); | ||||
|     } | ||||
|     return std::copy(buf.begin(), buf.end(), ctx.out()); | ||||
|   } | ||||
|  | ||||
|   basic_memory_buffer<Char> tm_format; | ||||
| }; | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_TIME_H_ | ||||
							
								
								
									
										8
									
								
								third_party/spdlog/include/spdlog/fmt/fmt.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										8
									
								
								third_party/spdlog/include/spdlog/fmt/fmt.h
									
									
									
									
										vendored
									
									
								
							| @@ -11,15 +11,17 @@ | ||||
| // | ||||
|  | ||||
| #if !defined(SPDLOG_FMT_EXTERNAL) | ||||
| #ifdef SPDLOG_HEADER_ONLY | ||||
| #ifndef FMT_HEADER_ONLY | ||||
| #define FMT_HEADER_ONLY | ||||
| #endif | ||||
| #endif | ||||
| #ifndef FMT_USE_WINDOWS_H | ||||
| #define FMT_USE_WINDOWS_H 0 | ||||
| #endif | ||||
| #include "bundled/core.h" | ||||
| #include "bundled/format.h" | ||||
| #else // external fmtlib | ||||
| #include <fmt/core.h> | ||||
| #include <fmt/format.h> | ||||
| #else // SPDLOG_FMT_EXTERNAL is defined - use external fmtlib | ||||
| #include "fmt/core.h" | ||||
| #include "fmt/format.h" | ||||
| #endif | ||||
|   | ||||
		Reference in New Issue
	
	Block a user