mirror of
				https://github.com/VCMP-SqMod/SqMod.git
				synced 2025-10-30 13:57:20 +01:00 
			
		
		
		
	Update cpp fmt library.
This commit is contained in:
		
							
								
								
									
										2
									
								
								vendor/Fmt/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/Fmt/CMakeLists.txt
									
									
									
									
										vendored
									
									
								
							| @@ -1,5 +1,6 @@ | ||||
| # Create library | ||||
| add_library(FmtLib STATIC | ||||
| 	include/fmt/args.h | ||||
| 	include/fmt/chrono.h | ||||
| 	include/fmt/color.h | ||||
| 	include/fmt/compile.h | ||||
| @@ -12,6 +13,7 @@ add_library(FmtLib STATIC | ||||
| 	include/fmt/posix.h | ||||
| 	include/fmt/printf.h | ||||
| 	include/fmt/ranges.h | ||||
| 	include/fmt/xchar.h | ||||
| 	format.cc | ||||
| 	os.cc | ||||
| ) | ||||
|   | ||||
							
								
								
									
										100
									
								
								vendor/Fmt/fmt.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										100
									
								
								vendor/Fmt/fmt.cc
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,100 @@ | ||||
| module; | ||||
| #ifndef __cpp_modules | ||||
| #  error Module not supported. | ||||
| #endif | ||||
|  | ||||
| // put all implementation-provided headers into the global module fragment | ||||
| // to prevent attachment to this module | ||||
| #if !defined(_CRT_SECURE_NO_WARNINGS) && defined(_MSC_VER) | ||||
| #  define _CRT_SECURE_NO_WARNINGS | ||||
| #endif | ||||
| #if !defined(WIN32_LEAN_AND_MEAN) && defined(_WIN32) | ||||
| #  define WIN32_LEAN_AND_MEAN | ||||
| #endif | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <cctype> | ||||
| #include <cerrno> | ||||
| #include <chrono> | ||||
| #include <climits> | ||||
| #include <clocale> | ||||
| #include <cmath> | ||||
| #include <cstdarg> | ||||
| #include <cstddef> | ||||
| #include <cstdint> | ||||
| #include <cstdio> | ||||
| #include <cstdlib> | ||||
| #include <cstring> | ||||
| #include <ctime> | ||||
| #include <cwchar> | ||||
| #include <exception> | ||||
| #include <functional> | ||||
| #include <iterator> | ||||
| #include <limits> | ||||
| #include <locale> | ||||
| #include <memory> | ||||
| #include <ostream> | ||||
| #include <sstream> | ||||
| #include <stdexcept> | ||||
| #include <string> | ||||
| #include <string_view> | ||||
| #include <system_error> | ||||
| #include <type_traits> | ||||
| #include <utility> | ||||
| #include <vector> | ||||
|  | ||||
| #if _MSC_VER | ||||
| #  include <intrin.h> | ||||
| #endif | ||||
| #if defined __APPLE__ || defined(__FreeBSD__) | ||||
| #  include <xlocale.h> | ||||
| #endif | ||||
| #if __has_include(<winapifamily.h>) | ||||
| #  include <winapifamily.h> | ||||
| #endif | ||||
| #if (__has_include(<fcntl.h>) || defined(__APPLE__) || \ | ||||
|      defined(__linux__)) &&                            \ | ||||
|     (!defined(WINAPI_FAMILY) || (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP)) | ||||
| #  include <fcntl.h> | ||||
| #  include <sys/stat.h> | ||||
| #  include <sys/types.h> | ||||
| #  ifndef _WIN32 | ||||
| #    include <unistd.h> | ||||
| #  else | ||||
| #    include <io.h> | ||||
| #  endif | ||||
| #endif | ||||
| #ifdef _WIN32 | ||||
| #  include <windows.h> | ||||
| #endif | ||||
|  | ||||
| export module fmt; | ||||
|  | ||||
| #define FMT_MODULE_EXPORT export | ||||
| #define FMT_MODULE_EXPORT_BEGIN export { | ||||
| #define FMT_MODULE_EXPORT_END } | ||||
| #define FMT_BEGIN_DETAIL_NAMESPACE \ | ||||
|   }                                \ | ||||
|   namespace detail { | ||||
| #define FMT_END_DETAIL_NAMESPACE \ | ||||
|   }                              \ | ||||
|   export { | ||||
|  | ||||
| // all library-provided declarations and definitions | ||||
| // must be in the module purview to be exported | ||||
| #include "fmt/args.h" | ||||
| #include "fmt/chrono.h" | ||||
| #include "fmt/color.h" | ||||
| #include "fmt/compile.h" | ||||
| #include "fmt/format.h" | ||||
| #include "fmt/os.h" | ||||
| #include "fmt/printf.h" | ||||
| #include "fmt/xchar.h" | ||||
|  | ||||
| // gcc doesn't yet implement private module fragments | ||||
| #if !FMT_GCC_VERSION | ||||
| module : private; | ||||
| #endif | ||||
|  | ||||
| #include "format.cc" | ||||
| #include "os.cc" | ||||
							
								
								
									
										38
									
								
								vendor/Fmt/format.cc
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										38
									
								
								vendor/Fmt/format.cc
									
									
									
									
										vendored
									
									
								
							| @@ -28,35 +28,8 @@ template FMT_API dragonbox::decimal_fp<float> dragonbox::to_decimal(float x) | ||||
|     FMT_NOEXCEPT; | ||||
| template FMT_API dragonbox::decimal_fp<double> dragonbox::to_decimal(double x) | ||||
|     FMT_NOEXCEPT; | ||||
|  | ||||
| // DEPRECATED! This function exists for ABI compatibility. | ||||
| template <typename Char> | ||||
| typename basic_format_context<std::back_insert_iterator<buffer<Char>>, | ||||
|                               Char>::iterator | ||||
| vformat_to(buffer<Char>& buf, basic_string_view<Char> format_str, | ||||
|            basic_format_args<basic_format_context< | ||||
|                std::back_insert_iterator<buffer<type_identity_t<Char>>>, | ||||
|                type_identity_t<Char>>> | ||||
|                args) { | ||||
|   using iterator = std::back_insert_iterator<buffer<char>>; | ||||
|   using context = basic_format_context< | ||||
|       std::back_insert_iterator<buffer<type_identity_t<Char>>>, | ||||
|       type_identity_t<Char>>; | ||||
|   auto out = iterator(buf); | ||||
|   format_handler<iterator, Char, context> h(out, format_str, args, {}); | ||||
|   parse_format_string<false>(format_str, h); | ||||
|   return out; | ||||
| } | ||||
| template basic_format_context<std::back_insert_iterator<buffer<char>>, | ||||
|                               char>::iterator | ||||
| vformat_to(buffer<char>&, string_view, | ||||
|            basic_format_args<basic_format_context< | ||||
|                std::back_insert_iterator<buffer<type_identity_t<char>>>, | ||||
|                type_identity_t<char>>>); | ||||
| }  // namespace detail | ||||
|  | ||||
| template struct FMT_INSTANTIATION_DEF_API detail::basic_data<void>; | ||||
|  | ||||
| // Workaround a bug in MSVC2013 that prevents instantiation of format_float. | ||||
| int (*instantiate_format_float)(double, int, detail::float_specs, | ||||
|                                 detail::buffer<char>&) = detail::format_float; | ||||
| @@ -68,8 +41,8 @@ template FMT_API std::locale detail::locale_ref::get<std::locale>() const; | ||||
|  | ||||
| // Explicit instantiations for char. | ||||
|  | ||||
| template FMT_API std::string detail::grouping_impl<char>(locale_ref); | ||||
| template FMT_API char detail::thousands_sep_impl(locale_ref); | ||||
| template FMT_API auto detail::thousands_sep_impl(locale_ref) | ||||
|     -> thousands_sep_result<char>; | ||||
| template FMT_API char detail::decimal_point_impl(locale_ref); | ||||
|  | ||||
| template FMT_API void detail::buffer<char>::append(const char*, const char*); | ||||
| @@ -90,10 +63,13 @@ template FMT_API int detail::format_float(long double, int, detail::float_specs, | ||||
|  | ||||
| // Explicit instantiations for wchar_t. | ||||
|  | ||||
| template FMT_API std::string detail::grouping_impl<wchar_t>(locale_ref); | ||||
| template FMT_API wchar_t detail::thousands_sep_impl(locale_ref); | ||||
| template FMT_API auto detail::thousands_sep_impl(locale_ref) | ||||
|     -> thousands_sep_result<wchar_t>; | ||||
| template FMT_API wchar_t detail::decimal_point_impl(locale_ref); | ||||
|  | ||||
| template FMT_API void detail::buffer<wchar_t>::append(const wchar_t*, | ||||
|                                                       const wchar_t*); | ||||
|  | ||||
| template struct detail::basic_data<void>; | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|   | ||||
							
								
								
									
										312
									
								
								vendor/Fmt/include/fmt/chrono.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										312
									
								
								vendor/Fmt/include/fmt/chrono.h
									
									
									
									
										vendored
									
									
								
							| @@ -15,7 +15,6 @@ | ||||
| #include <sstream> | ||||
|  | ||||
| #include "format.h" | ||||
| #include "locale.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| @@ -283,12 +282,84 @@ To safe_duration_cast(std::chrono::duration<FromRep, FromPeriod> from, | ||||
| #define FMT_NOMACRO | ||||
|  | ||||
| namespace detail { | ||||
| template <typename T = void> struct null {}; | ||||
| 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<>(); } | ||||
|  | ||||
| inline auto do_write(const std::tm& time, const std::locale& loc, char format, | ||||
|                      char modifier) -> std::string { | ||||
|   auto&& os = std::ostringstream(); | ||||
|   os.imbue(loc); | ||||
|   using iterator = std::ostreambuf_iterator<char>; | ||||
|   const auto& facet = std::use_facet<std::time_put<char, iterator>>(loc); | ||||
|   auto end = facet.put(os, os, ' ', &time, format, modifier); | ||||
|   if (end.failed()) FMT_THROW(format_error("failed to format time")); | ||||
|   auto str = os.str(); | ||||
|   if (!detail::is_utf8() || loc == std::locale::classic()) return str; | ||||
|     // char16_t and char32_t codecvts are broken in MSVC (linkage errors) and | ||||
|     // gcc-4. | ||||
| #if FMT_MSC_VER != 0 || \ | ||||
|     (defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)) | ||||
|   // The _GLIBCXX_USE_DUAL_ABI macro is always defined in libstdc++ from gcc-5 | ||||
|   // and newer. | ||||
|   using code_unit = wchar_t; | ||||
| #else | ||||
|   using code_unit = char32_t; | ||||
| #endif | ||||
|   auto& f = std::use_facet<std::codecvt<code_unit, char, std::mbstate_t>>(loc); | ||||
|   auto mb = std::mbstate_t(); | ||||
|   const char* from_next = nullptr; | ||||
|   code_unit* to_next = nullptr; | ||||
|   constexpr size_t buf_size = 32; | ||||
|   code_unit buf[buf_size] = {}; | ||||
|   auto result = f.in(mb, str.data(), str.data() + str.size(), from_next, buf, | ||||
|                      buf + buf_size, to_next); | ||||
|   if (result != std::codecvt_base::ok) | ||||
|     FMT_THROW(format_error("failed to format time")); | ||||
|   str.clear(); | ||||
|   for (code_unit* p = buf; p != to_next; ++p) { | ||||
|     uint32_t c = static_cast<uint32_t>(*p); | ||||
|     if (sizeof(code_unit) == 2 && c >= 0xd800 && c <= 0xdfff) { | ||||
|       // surrogate pair | ||||
|       ++p; | ||||
|       if (p == to_next || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) { | ||||
|         FMT_THROW(format_error("failed to format time")); | ||||
|       } | ||||
|       c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00; | ||||
|     } | ||||
|     if (c < 0x80) { | ||||
|       str.push_back(static_cast<char>(c)); | ||||
|     } else if (c < 0x800) { | ||||
|       str.push_back(static_cast<char>(0xc0 | (c >> 6))); | ||||
|       str.push_back(static_cast<char>(0x80 | (c & 0x3f))); | ||||
|     } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) { | ||||
|       str.push_back(static_cast<char>(0xe0 | (c >> 12))); | ||||
|       str.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6))); | ||||
|       str.push_back(static_cast<char>(0x80 | (c & 0x3f))); | ||||
|     } else if (c >= 0x10000 && c <= 0x10ffff) { | ||||
|       str.push_back(static_cast<char>(0xf0 | (c >> 18))); | ||||
|       str.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12))); | ||||
|       str.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6))); | ||||
|       str.push_back(static_cast<char>(0x80 | (c & 0x3f))); | ||||
|     } else { | ||||
|       FMT_THROW(format_error("failed to format time")); | ||||
|     } | ||||
|   } | ||||
|   return str; | ||||
| } | ||||
|  | ||||
| template <typename OutputIt> | ||||
| auto write(OutputIt out, const std::tm& time, const std::locale& loc, | ||||
|            char format, char modifier = 0) -> OutputIt { | ||||
|   auto str = do_write(time, loc, format, modifier); | ||||
|   return std::copy(str.begin(), str.end(), out); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| /** | ||||
|   Converts given time since epoch as ``std::time_t`` value into calendar time, | ||||
|   expressed in local time. Unlike ``std::localtime``, this function is | ||||
| @@ -380,7 +451,8 @@ inline std::tm gmtime( | ||||
|   return gmtime(std::chrono::system_clock::to_time_t(time_point)); | ||||
| } | ||||
|  | ||||
| namespace detail { | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
|  | ||||
| inline size_t strftime(char* str, size_t count, const char* format, | ||||
|                        const std::tm* time) { | ||||
|   // Assign to a pointer to suppress GCCs -Wformat-nonliteral | ||||
| @@ -399,19 +471,43 @@ inline size_t strftime(wchar_t* str, size_t count, const wchar_t* format, | ||||
|   wcsftime = std::wcsftime; | ||||
|   return wcsftime(str, count, format, time); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| template <typename Char> | ||||
| struct formatter<std::chrono::time_point<std::chrono::system_clock>, Char> | ||||
|     : formatter<std::tm, Char> { | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| template <typename Char, typename Duration> | ||||
| struct formatter<std::chrono::time_point<std::chrono::system_clock, Duration>, | ||||
|                  Char> : formatter<std::tm, Char> { | ||||
|   FMT_CONSTEXPR formatter() { | ||||
|     this->specs = {default_specs, sizeof(default_specs) / sizeof(Char)}; | ||||
|   } | ||||
|  | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     auto it = ctx.begin(); | ||||
|     if (it != ctx.end() && *it == ':') ++it; | ||||
|     auto end = it; | ||||
|     while (end != ctx.end() && *end != '}') ++end; | ||||
|     if (end != it) this->specs = {it, detail::to_unsigned(end - it)}; | ||||
|     return end; | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(std::chrono::time_point<std::chrono::system_clock> val, | ||||
|               FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|     std::tm time = localtime(val); | ||||
|     return formatter<std::tm, Char>::format(time, ctx); | ||||
|   } | ||||
|  | ||||
|   static constexpr Char default_specs[] = {'%', 'Y', '-', '%', 'm', '-', | ||||
|                                            '%', 'd', ' ', '%', 'H', ':', | ||||
|                                            '%', 'M', ':', '%', 'S'}; | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename Duration> | ||||
| constexpr Char | ||||
|     formatter<std::chrono::time_point<std::chrono::system_clock, Duration>, | ||||
|               Char>::default_specs[]; | ||||
|  | ||||
| template <typename Char> struct formatter<std::tm, Char> { | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
| @@ -428,6 +524,10 @@ template <typename Char> struct formatter<std::tm, Char> { | ||||
|       -> decltype(ctx.out()) { | ||||
|     basic_memory_buffer<Char> tm_format; | ||||
|     tm_format.append(specs.begin(), specs.end()); | ||||
|     // By appending an extra space we can distinguish an empty result that | ||||
|     // indicates insufficient buffer size from a guaranteed non-empty result | ||||
|     // https://github.com/fmtlib/fmt/issues/2238 | ||||
|     tm_format.push_back(' '); | ||||
|     tm_format.push_back('\0'); | ||||
|     basic_memory_buffer<Char> buf; | ||||
|     size_t start = buf.size(); | ||||
| @@ -438,83 +538,40 @@ template <typename Char> struct formatter<std::tm, Char> { | ||||
|         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 size_t MIN_GROWTH = 10; | ||||
|       buf.reserve(buf.capacity() + (size > MIN_GROWTH ? size : MIN_GROWTH)); | ||||
|     } | ||||
|     return std::copy(buf.begin(), buf.end(), ctx.out()); | ||||
|     // Remove the extra space. | ||||
|     return std::copy(buf.begin(), buf.end() - 1, ctx.out()); | ||||
|   } | ||||
|  | ||||
|   basic_string_view<Char> specs; | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
| template <typename Period> FMT_CONSTEXPR const char* get_units() { | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
|  | ||||
| template <typename Period> FMT_CONSTEXPR inline const char* get_units() { | ||||
|   if (std::is_same<Period, std::atto>::value) return "as"; | ||||
|   if (std::is_same<Period, std::femto>::value) return "fs"; | ||||
|   if (std::is_same<Period, std::pico>::value) return "ps"; | ||||
|   if (std::is_same<Period, std::nano>::value) return "ns"; | ||||
|   if (std::is_same<Period, std::micro>::value) return "µs"; | ||||
|   if (std::is_same<Period, std::milli>::value) return "ms"; | ||||
|   if (std::is_same<Period, std::centi>::value) return "cs"; | ||||
|   if (std::is_same<Period, std::deci>::value) return "ds"; | ||||
|   if (std::is_same<Period, std::ratio<1>>::value) return "s"; | ||||
|   if (std::is_same<Period, std::deca>::value) return "das"; | ||||
|   if (std::is_same<Period, std::hecto>::value) return "hs"; | ||||
|   if (std::is_same<Period, std::kilo>::value) return "ks"; | ||||
|   if (std::is_same<Period, std::mega>::value) return "Ms"; | ||||
|   if (std::is_same<Period, std::giga>::value) return "Gs"; | ||||
|   if (std::is_same<Period, std::tera>::value) return "Ts"; | ||||
|   if (std::is_same<Period, std::peta>::value) return "Ps"; | ||||
|   if (std::is_same<Period, std::exa>::value) return "Es"; | ||||
|   if (std::is_same<Period, std::ratio<60>>::value) return "m"; | ||||
|   if (std::is_same<Period, std::ratio<3600>>::value) return "h"; | ||||
|   return nullptr; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::atto>() { | ||||
|   return "as"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::femto>() { | ||||
|   return "fs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::pico>() { | ||||
|   return "ps"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::nano>() { | ||||
|   return "ns"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::micro>() { | ||||
|   return "µs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::milli>() { | ||||
|   return "ms"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::centi>() { | ||||
|   return "cs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::deci>() { | ||||
|   return "ds"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<1>>() { | ||||
|   return "s"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::deca>() { | ||||
|   return "das"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::hecto>() { | ||||
|   return "hs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::kilo>() { | ||||
|   return "ks"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::mega>() { | ||||
|   return "Ms"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::giga>() { | ||||
|   return "Gs"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::tera>() { | ||||
|   return "Ts"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::peta>() { | ||||
|   return "Ps"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::exa>() { | ||||
|   return "Es"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<60>>() { | ||||
|   return "m"; | ||||
| } | ||||
| template <> FMT_CONSTEXPR inline const char* get_units<std::ratio<3600>>() { | ||||
|   return "h"; | ||||
| } | ||||
|  | ||||
| enum class numeric_system { | ||||
|   standard, | ||||
| @@ -680,34 +737,50 @@ FMT_CONSTEXPR const Char* parse_chrono_format(const Char* begin, | ||||
|   return ptr; | ||||
| } | ||||
|  | ||||
| struct chrono_format_checker { | ||||
|   FMT_NORETURN void report_no_date() { FMT_THROW(format_error("no date")); } | ||||
| template <typename Derived> struct null_chrono_spec_handler { | ||||
|   FMT_CONSTEXPR void unsupported() { | ||||
|     static_cast<Derived*>(this)->unsupported(); | ||||
|   } | ||||
|   FMT_CONSTEXPR void on_abbr_weekday() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_full_weekday() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_dec0_weekday(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_dec1_weekday(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_abbr_month() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_full_month() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_24_hour(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_12_hour(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_minute(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_second(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_datetime(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_loc_date(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_loc_time(numeric_system) { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_us_date() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_iso_date() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_12_hour_time() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_24_hour_time() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_iso_time() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_am_pm() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_duration_value() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_duration_unit() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_utc_offset() { unsupported(); } | ||||
|   FMT_CONSTEXPR void on_tz_name() { unsupported(); } | ||||
| }; | ||||
|  | ||||
| struct chrono_format_checker : null_chrono_spec_handler<chrono_format_checker> { | ||||
|   FMT_NORETURN void unsupported() { FMT_THROW(format_error("no date")); } | ||||
|  | ||||
|   template <typename Char> | ||||
|   FMT_CONSTEXPR void on_text(const Char*, const Char*) {} | ||||
|   FMT_NORETURN void on_abbr_weekday() { report_no_date(); } | ||||
|   FMT_NORETURN void on_full_weekday() { report_no_date(); } | ||||
|   FMT_NORETURN void on_dec0_weekday(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_dec1_weekday(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_abbr_month() { report_no_date(); } | ||||
|   FMT_NORETURN void on_full_month() { report_no_date(); } | ||||
|   FMT_CONSTEXPR void on_24_hour(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_12_hour(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_minute(numeric_system) {} | ||||
|   FMT_CONSTEXPR void on_second(numeric_system) {} | ||||
|   FMT_NORETURN void on_datetime(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_loc_date(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_loc_time(numeric_system) { report_no_date(); } | ||||
|   FMT_NORETURN void on_us_date() { report_no_date(); } | ||||
|   FMT_NORETURN void on_iso_date() { report_no_date(); } | ||||
|   FMT_CONSTEXPR void on_12_hour_time() {} | ||||
|   FMT_CONSTEXPR void on_24_hour_time() {} | ||||
|   FMT_CONSTEXPR void on_iso_time() {} | ||||
|   FMT_CONSTEXPR void on_am_pm() {} | ||||
|   FMT_CONSTEXPR void on_duration_value() {} | ||||
|   FMT_CONSTEXPR void on_duration_unit() {} | ||||
|   FMT_NORETURN void on_utc_offset() { report_no_date(); } | ||||
|   FMT_NORETURN void on_tz_name() { report_no_date(); } | ||||
| }; | ||||
|  | ||||
| template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> | ||||
| @@ -859,6 +932,7 @@ struct chrono_formatter { | ||||
|   FormatContext& context; | ||||
|   OutputIt out; | ||||
|   int precision; | ||||
|   bool localized = false; | ||||
|   // rep is unsigned to avoid overflow. | ||||
|   using rep = | ||||
|       conditional_t<std::is_integral<Rep>::value && sizeof(Rep) < sizeof(int), | ||||
| @@ -953,13 +1027,9 @@ struct chrono_formatter { | ||||
|  | ||||
|   void format_localized(const tm& time, char format, char modifier = 0) { | ||||
|     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); | ||||
|     std::basic_ostringstream<char_type> os; | ||||
|     os.imbue(locale); | ||||
|     facet.put(os, os, ' ', &time, format, modifier); | ||||
|     auto str = os.str(); | ||||
|     std::copy(str.begin(), str.end(), out); | ||||
|     const auto& loc = localized ? context.locale().template get<std::locale>() | ||||
|                                 : std::locale::classic(); | ||||
|     out = detail::write(out, time, loc, format, modifier); | ||||
|   } | ||||
|  | ||||
|   void on_text(const char_type* begin, const char_type* end) { | ||||
| @@ -1072,7 +1142,48 @@ struct chrono_formatter { | ||||
|     out = format_duration_unit<char_type, Period>(out); | ||||
|   } | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| #if defined(__cpp_lib_chrono) && __cpp_lib_chrono >= 201907 | ||||
| using weekday = std::chrono::weekday; | ||||
| #else | ||||
| // A fallback version of weekday. | ||||
| class weekday { | ||||
|  private: | ||||
|   unsigned char value; | ||||
|  | ||||
|  public: | ||||
|   weekday() = default; | ||||
|   explicit constexpr weekday(unsigned wd) noexcept | ||||
|       : value(static_cast<unsigned char>(wd != 7 ? wd : 0)) {} | ||||
|   constexpr unsigned c_encoding() const noexcept { return value; } | ||||
| }; | ||||
| #endif | ||||
|  | ||||
| // A rudimentary weekday formatter. | ||||
| template <> struct formatter<weekday> { | ||||
|  private: | ||||
|   bool localized = false; | ||||
|  | ||||
|  public: | ||||
|   FMT_CONSTEXPR auto parse(format_parse_context& ctx) -> decltype(ctx.begin()) { | ||||
|     auto begin = ctx.begin(), end = ctx.end(); | ||||
|     if (begin != end && *begin == 'L') { | ||||
|       ++begin; | ||||
|       localized = true; | ||||
|     } | ||||
|     return begin; | ||||
|   } | ||||
|  | ||||
|   auto format(weekday wd, format_context& ctx) -> decltype(ctx.out()) { | ||||
|     auto time = std::tm(); | ||||
|     time.tm_wday = static_cast<int>(wd.c_encoding()); | ||||
|     const auto& loc = localized ? ctx.locale().template get<std::locale>() | ||||
|                                 : std::locale::classic(); | ||||
|     return detail::write(ctx.out(), time, loc, 'a'); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Rep, typename Period, typename Char> | ||||
| struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
| @@ -1082,6 +1193,7 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|   using arg_ref_type = detail::arg_ref<Char>; | ||||
|   arg_ref_type width_ref; | ||||
|   arg_ref_type precision_ref; | ||||
|   bool localized = false; | ||||
|   basic_string_view<Char> format_str; | ||||
|   using duration = std::chrono::duration<Rep, Period>; | ||||
|  | ||||
| @@ -1144,6 +1256,10 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|       else | ||||
|         handler.on_error("precision not allowed for this argument type"); | ||||
|     } | ||||
|     if (begin != end && *begin == 'L') { | ||||
|       ++begin; | ||||
|       localized = true; | ||||
|     } | ||||
|     end = parse_chrono_format(begin, end, detail::chrono_format_checker()); | ||||
|     return {begin, end}; | ||||
|   } | ||||
| @@ -1178,13 +1294,15 @@ struct formatter<std::chrono::duration<Rep, Period>, Char> { | ||||
|       detail::chrono_formatter<FormatContext, decltype(out), Rep, Period> f( | ||||
|           ctx, out, d); | ||||
|       f.precision = precision_copy; | ||||
|       parse_chrono_format(begin, end, f); | ||||
|       f.localized = localized; | ||||
|       detail::parse_chrono_format(begin, end, f); | ||||
|     } | ||||
|     return detail::write( | ||||
|         ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs_copy); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_CHRONO_H_ | ||||
|   | ||||
							
								
								
									
										35
									
								
								vendor/Fmt/include/fmt/color.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										35
									
								
								vendor/Fmt/include/fmt/color.h
									
									
									
									
										vendored
									
									
								
							| @@ -18,6 +18,7 @@ | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| enum class color : uint32_t { | ||||
|   alice_blue = 0xF0F8FF,               // rgb(240,248,255) | ||||
| @@ -205,7 +206,7 @@ struct rgb { | ||||
|   uint8_t b; | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
|  | ||||
| // color is a struct of either a rgb color or a terminal color. | ||||
| struct color_type { | ||||
| @@ -228,7 +229,8 @@ struct color_type { | ||||
|     uint32_t rgb_color; | ||||
|   } value; | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| /** A text style consisting of foreground and background colors and emphasis. */ | ||||
| class text_style { | ||||
| @@ -367,7 +369,7 @@ FMT_CONSTEXPR inline text_style operator|(emphasis lhs, | ||||
|   return text_style(lhs) | rhs; | ||||
| } | ||||
|  | ||||
| namespace detail { | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
|  | ||||
| template <typename Char> struct ansi_color_escape { | ||||
|   FMT_CONSTEXPR ansi_color_escape(detail::color_type text_color, | ||||
| @@ -375,7 +377,7 @@ template <typename Char> struct ansi_color_escape { | ||||
|     // If we have a terminal color, we need to output another escape code | ||||
|     // sequence. | ||||
|     if (!text_color.is_rgb) { | ||||
|       bool is_background = esc == detail::data::background_color; | ||||
|       bool is_background = esc == string_view("\x1b[48;2;"); | ||||
|       uint32_t value = text_color.value.term_color; | ||||
|       // Background ASCII codes are the same as the foreground ones but with | ||||
|       // 10 more. | ||||
| @@ -428,7 +430,7 @@ template <typename Char> struct ansi_color_escape { | ||||
|   FMT_CONSTEXPR operator const Char*() const FMT_NOEXCEPT { return buffer; } | ||||
|  | ||||
|   FMT_CONSTEXPR const Char* begin() const FMT_NOEXCEPT { return buffer; } | ||||
|   FMT_CONSTEXPR const Char* end() const FMT_NOEXCEPT { | ||||
|   FMT_CONSTEXPR_CHAR_TRAITS const Char* end() const FMT_NOEXCEPT { | ||||
|     return buffer + std::char_traits<Char>::length(buffer); | ||||
|   } | ||||
|  | ||||
| @@ -447,13 +449,13 @@ template <typename Char> struct ansi_color_escape { | ||||
| template <typename Char> | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> make_foreground_color( | ||||
|     detail::color_type foreground) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(foreground, detail::data::foreground_color); | ||||
|   return ansi_color_escape<Char>(foreground, "\x1b[38;2;"); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| FMT_CONSTEXPR ansi_color_escape<Char> make_background_color( | ||||
|     detail::color_type background) FMT_NOEXCEPT { | ||||
|   return ansi_color_escape<Char>(background, detail::data::background_color); | ||||
|   return ansi_color_escape<Char>(background, "\x1b[48;2;"); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| @@ -472,18 +474,17 @@ inline void fputs<wchar_t>(const wchar_t* chars, FILE* stream) FMT_NOEXCEPT { | ||||
| } | ||||
|  | ||||
| template <typename Char> inline void reset_color(FILE* stream) FMT_NOEXCEPT { | ||||
|   fputs(detail::data::reset_color, stream); | ||||
|   fputs("\x1b[0m", stream); | ||||
| } | ||||
|  | ||||
| template <> inline void reset_color<wchar_t>(FILE* stream) FMT_NOEXCEPT { | ||||
|   fputs(detail::data::wreset_color, stream); | ||||
|   fputs(L"\x1b[0m", stream); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| inline void reset_color(buffer<Char>& buffer) FMT_NOEXCEPT { | ||||
|   const char* begin = data::reset_color; | ||||
|   const char* end = begin + sizeof(data::reset_color) - 1; | ||||
|   buffer.append(begin, end); | ||||
|   auto reset_color = string_view("\x1b[0m"); | ||||
|   buffer.append(reset_color.begin(), reset_color.end()); | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| @@ -509,7 +510,8 @@ void vformat_to(buffer<Char>& buf, const text_style& ts, | ||||
|   detail::vformat_to(buf, format_str, args); | ||||
|   if (has_style) detail::reset_color<Char>(buf); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| template <typename S, typename Char = char_t<S>> | ||||
| void vprint(std::FILE* f, const text_style& ts, const S& format, | ||||
| @@ -580,8 +582,8 @@ inline std::basic_string<Char> vformat( | ||||
| 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 vformat(ts, to_string_view(format_str), | ||||
|                  fmt::make_args_checked<Args...>(format_str, args...)); | ||||
|   return fmt::vformat(ts, to_string_view(format_str), | ||||
|                       fmt::make_args_checked<Args...>(format_str, args...)); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -592,7 +594,7 @@ template <typename OutputIt, typename Char, | ||||
| OutputIt vformat_to( | ||||
|     OutputIt out, const text_style& ts, basic_string_view<Char> format_str, | ||||
|     basic_format_args<buffer_context<type_identity_t<Char>>> args) { | ||||
|   decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out)); | ||||
|   auto&& buf = detail::get_buffer<Char>(out); | ||||
|   detail::vformat_to(buf, ts, format_str, args); | ||||
|   return detail::get_iterator(buf); | ||||
| } | ||||
| @@ -619,6 +621,7 @@ inline auto format_to(OutputIt out, const text_style& ts, const S& format_str, | ||||
|                     fmt::make_args_checked<Args...>(format_str, args...)); | ||||
| } | ||||
|  | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_COLOR_H_ | ||||
|   | ||||
							
								
								
									
										671
									
								
								vendor/Fmt/include/fmt/compile.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										671
									
								
								vendor/Fmt/include/fmt/compile.h
									
									
									
									
										vendored
									
									
								
							| @@ -8,23 +8,56 @@ | ||||
| #ifndef FMT_COMPILE_H_ | ||||
| #define FMT_COMPILE_H_ | ||||
|  | ||||
| #include <algorithm> | ||||
| #include <vector> | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| #ifndef FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| #  if defined(__cpp_nontype_template_parameter_class) && \ | ||||
|       (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 903) | ||||
| #    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 1 | ||||
| #  else | ||||
| #    define FMT_USE_NONTYPE_TEMPLATE_PARAMETERS 0 | ||||
| #  endif | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| namespace detail { | ||||
|  | ||||
| // An output iterator that counts the number of objects written to it and | ||||
| // discards them. | ||||
| class counting_iterator { | ||||
|  private: | ||||
|   size_t count_; | ||||
|  | ||||
|  public: | ||||
|   using iterator_category = std::output_iterator_tag; | ||||
|   using difference_type = std::ptrdiff_t; | ||||
|   using pointer = void; | ||||
|   using reference = void; | ||||
|   using _Unchecked_type = counting_iterator;  // Mark iterator as checked. | ||||
|  | ||||
|   struct value_type { | ||||
|     template <typename T> void operator=(const T&) {} | ||||
|   }; | ||||
|  | ||||
|   counting_iterator() : count_(0) {} | ||||
|  | ||||
|   size_t count() const { return count_; } | ||||
|  | ||||
|   counting_iterator& operator++() { | ||||
|     ++count_; | ||||
|     return *this; | ||||
|   } | ||||
|   counting_iterator operator++(int) { | ||||
|     auto it = *this; | ||||
|     ++*this; | ||||
|     return it; | ||||
|   } | ||||
|  | ||||
|   friend counting_iterator operator+(counting_iterator it, difference_type n) { | ||||
|     it.count_ += static_cast<size_t>(n); | ||||
|     return it; | ||||
|   } | ||||
|  | ||||
|   value_type operator*() const { return {}; } | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename InputIt> | ||||
| inline counting_iterator copy_str(InputIt begin, InputIt end, | ||||
|                                   counting_iterator it) { | ||||
|   return it + (end - begin); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt> class truncating_iterator_base { | ||||
|  protected: | ||||
|   OutputIt out_; | ||||
| @@ -123,18 +156,16 @@ struct is_compiled_string : std::is_base_of<compiled_string, S> {}; | ||||
|     std::string s = fmt::format(FMT_COMPILE("{}"), 42); | ||||
|   \endrst | ||||
|  */ | ||||
| #define FMT_COMPILE(s) FMT_STRING_IMPL(s, fmt::detail::compiled_string) | ||||
| #ifdef __cpp_if_constexpr | ||||
| #  define FMT_COMPILE(s) \ | ||||
|     FMT_STRING_IMPL(s, fmt::detail::compiled_string, explicit) | ||||
| #else | ||||
| #  define FMT_COMPILE(s) FMT_STRING(s) | ||||
| #endif | ||||
|  | ||||
| #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| template <typename Char, size_t N> struct fixed_string { | ||||
|   constexpr fixed_string(const Char (&str)[N]) { | ||||
|     copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str), str + N, | ||||
|                                        data); | ||||
|   } | ||||
|   Char data[N]{}; | ||||
| }; | ||||
|  | ||||
| template <typename Char, size_t N, fixed_string<Char, N> Str> | ||||
| template <typename Char, size_t N, | ||||
|           fmt::detail_exported::fixed_string<Char, N> Str> | ||||
| struct udl_compiled_string : compiled_string { | ||||
|   using char_type = Char; | ||||
|   constexpr operator basic_string_view<char_type>() const { | ||||
| @@ -148,333 +179,6 @@ const T& first(const T& value, const Tail&...) { | ||||
|   return value; | ||||
| } | ||||
|  | ||||
| // Part of a compiled format string. It can be either literal text or a | ||||
| // replacement field. | ||||
| template <typename Char> struct format_part { | ||||
|   enum class kind { arg_index, arg_name, text, replacement }; | ||||
|  | ||||
|   struct replacement { | ||||
|     arg_ref<Char> arg_id; | ||||
|     dynamic_format_specs<Char> specs; | ||||
|   }; | ||||
|  | ||||
|   kind part_kind; | ||||
|   union value { | ||||
|     int arg_index; | ||||
|     basic_string_view<Char> str; | ||||
|     replacement repl; | ||||
|  | ||||
|     FMT_CONSTEXPR value(int index = 0) : arg_index(index) {} | ||||
|     FMT_CONSTEXPR value(basic_string_view<Char> s) : str(s) {} | ||||
|     FMT_CONSTEXPR value(replacement r) : repl(r) {} | ||||
|   } val; | ||||
|   // Position past the end of the argument id. | ||||
|   const Char* arg_id_end = nullptr; | ||||
|  | ||||
|   FMT_CONSTEXPR format_part(kind k = kind::arg_index, value v = {}) | ||||
|       : part_kind(k), val(v) {} | ||||
|  | ||||
|   static FMT_CONSTEXPR format_part make_arg_index(int index) { | ||||
|     return format_part(kind::arg_index, index); | ||||
|   } | ||||
|   static FMT_CONSTEXPR format_part make_arg_name(basic_string_view<Char> name) { | ||||
|     return format_part(kind::arg_name, name); | ||||
|   } | ||||
|   static FMT_CONSTEXPR format_part make_text(basic_string_view<Char> text) { | ||||
|     return format_part(kind::text, text); | ||||
|   } | ||||
|   static FMT_CONSTEXPR format_part make_replacement(replacement repl) { | ||||
|     return format_part(kind::replacement, repl); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| 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 int on_arg_id() { return ++num_parts, 0; } | ||||
|   FMT_CONSTEXPR int on_arg_id(int) { return ++num_parts, 0; } | ||||
|   FMT_CONSTEXPR int on_arg_id(basic_string_view<Char>) { | ||||
|     return ++num_parts, 0; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_replacement_field(int, const Char*) {} | ||||
|  | ||||
|   FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin, | ||||
|                                             const Char* end) { | ||||
|     // Find the matching brace. | ||||
|     unsigned brace_counter = 0; | ||||
|     for (; begin != end; ++begin) { | ||||
|       if (*begin == '{') { | ||||
|         ++brace_counter; | ||||
|       } else if (*begin == '}') { | ||||
|         if (brace_counter == 0u) break; | ||||
|         --brace_counter; | ||||
|       } | ||||
|     } | ||||
|     return begin; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_error(const char*) {} | ||||
| }; | ||||
|  | ||||
| // Counts the number of parts in a format string. | ||||
| template <typename Char> | ||||
| FMT_CONSTEXPR unsigned count_parts(basic_string_view<Char> format_str) { | ||||
|   part_counter<Char> counter; | ||||
|   parse_format_string<true>(format_str, counter); | ||||
|   return counter.num_parts; | ||||
| } | ||||
|  | ||||
| template <typename Char, typename PartHandler> | ||||
| class format_string_compiler : public error_handler { | ||||
|  private: | ||||
|   using part = format_part<Char>; | ||||
|  | ||||
|   PartHandler handler_; | ||||
|   part part_; | ||||
|   basic_string_view<Char> format_str_; | ||||
|   basic_format_parse_context<Char> parse_context_; | ||||
|  | ||||
|  public: | ||||
|   FMT_CONSTEXPR format_string_compiler(basic_string_view<Char> format_str, | ||||
|                                        PartHandler handler) | ||||
|       : handler_(handler), | ||||
|         format_str_(format_str), | ||||
|         parse_context_(format_str) {} | ||||
|  | ||||
|   FMT_CONSTEXPR void on_text(const Char* begin, const Char* end) { | ||||
|     if (begin != end) | ||||
|       handler_(part::make_text({begin, to_unsigned(end - begin)})); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR int on_arg_id() { | ||||
|     part_ = part::make_arg_index(parse_context_.next_arg_id()); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR int on_arg_id(int id) { | ||||
|     parse_context_.check_arg_id(id); | ||||
|     part_ = part::make_arg_index(id); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR int on_arg_id(basic_string_view<Char> id) { | ||||
|     part_ = part::make_arg_name(id); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_replacement_field(int, const Char* ptr) { | ||||
|     part_.arg_id_end = ptr; | ||||
|     handler_(part_); | ||||
|   } | ||||
|  | ||||
|   FMT_CONSTEXPR const Char* on_format_specs(int, const Char* begin, | ||||
|                                             const Char* end) { | ||||
|     auto repl = typename part::replacement(); | ||||
|     dynamic_specs_handler<basic_format_parse_context<Char>> handler( | ||||
|         repl.specs, parse_context_); | ||||
|     auto it = parse_format_specs(begin, end, handler); | ||||
|     if (*it != '}') on_error("missing '}' in format string"); | ||||
|     repl.arg_id = part_.part_kind == part::kind::arg_index | ||||
|                       ? arg_ref<Char>(part_.val.arg_index) | ||||
|                       : arg_ref<Char>(part_.val.str); | ||||
|     auto replacement_part = part::make_replacement(repl); | ||||
|     replacement_part.arg_id_end = begin; | ||||
|     handler_(replacement_part); | ||||
|     return it; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // Compiles a format string and invokes handler(part) for each parsed part. | ||||
| template <bool IS_CONSTEXPR, typename Char, typename PartHandler> | ||||
| FMT_CONSTEXPR void compile_format_string(basic_string_view<Char> format_str, | ||||
|                                          PartHandler handler) { | ||||
|   parse_format_string<IS_CONSTEXPR>( | ||||
|       format_str, | ||||
|       format_string_compiler<Char, PartHandler>(format_str, handler)); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename Context, typename Id> | ||||
| void format_arg( | ||||
|     basic_format_parse_context<typename Context::char_type>& parse_ctx, | ||||
|     Context& ctx, Id arg_id) { | ||||
|   auto arg = ctx.arg(arg_id); | ||||
|   if (arg.type() == type::custom_type) { | ||||
|     visit_format_arg(custom_formatter<Context>(parse_ctx, ctx), arg); | ||||
|   } else { | ||||
|     ctx.advance_to(visit_format_arg( | ||||
|         default_arg_formatter<OutputIt, typename Context::char_type>{ | ||||
|             ctx.out(), ctx.args(), ctx.locale()}, | ||||
|         arg)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // vformat_to is defined in a subnamespace to prevent ADL. | ||||
| namespace cf { | ||||
| template <typename Context, typename OutputIt, typename CompiledFormat> | ||||
| auto vformat_to(OutputIt out, CompiledFormat& cf, | ||||
|                 basic_format_args<Context> args) -> typename Context::iterator { | ||||
|   using char_type = typename Context::char_type; | ||||
|   basic_format_parse_context<char_type> parse_ctx( | ||||
|       to_string_view(cf.format_str_)); | ||||
|   Context ctx(out, args); | ||||
|  | ||||
|   const auto& parts = cf.parts(); | ||||
|   for (auto part_it = std::begin(parts); part_it != std::end(parts); | ||||
|        ++part_it) { | ||||
|     const auto& part = *part_it; | ||||
|     const auto& value = part.val; | ||||
|  | ||||
|     using format_part_t = format_part<char_type>; | ||||
|     switch (part.part_kind) { | ||||
|     case format_part_t::kind::text: { | ||||
|       const auto text = value.str; | ||||
|       auto output = ctx.out(); | ||||
|       auto&& it = reserve(output, text.size()); | ||||
|       it = std::copy_n(text.begin(), text.size(), it); | ||||
|       ctx.advance_to(output); | ||||
|       break; | ||||
|     } | ||||
|  | ||||
|     case format_part_t::kind::arg_index: | ||||
|       advance_to(parse_ctx, part.arg_id_end); | ||||
|       detail::format_arg<OutputIt>(parse_ctx, ctx, value.arg_index); | ||||
|       break; | ||||
|  | ||||
|     case format_part_t::kind::arg_name: | ||||
|       advance_to(parse_ctx, part.arg_id_end); | ||||
|       detail::format_arg<OutputIt>(parse_ctx, ctx, value.str); | ||||
|       break; | ||||
|  | ||||
|     case format_part_t::kind::replacement: { | ||||
|       const auto& arg_id_value = value.repl.arg_id.val; | ||||
|       const auto arg = value.repl.arg_id.kind == arg_id_kind::index | ||||
|                            ? ctx.arg(arg_id_value.index) | ||||
|                            : ctx.arg(arg_id_value.name); | ||||
|  | ||||
|       auto specs = value.repl.specs; | ||||
|  | ||||
|       handle_dynamic_spec<width_checker>(specs.width, specs.width_ref, ctx); | ||||
|       handle_dynamic_spec<precision_checker>(specs.precision, | ||||
|                                              specs.precision_ref, ctx); | ||||
|  | ||||
|       error_handler h; | ||||
|       numeric_specs_checker<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(); | ||||
|  | ||||
|       advance_to(parse_ctx, part.arg_id_end); | ||||
|       ctx.advance_to(visit_format_arg( | ||||
|           arg_formatter<OutputIt, typename Context::char_type>(ctx, specs), | ||||
|           arg)); | ||||
|       break; | ||||
|     } | ||||
|     } | ||||
|   } | ||||
|   return ctx.out(); | ||||
| } | ||||
| }  // namespace cf | ||||
|  | ||||
| struct basic_compiled_format {}; | ||||
|  | ||||
| template <typename S, typename = void> | ||||
| struct compiled_format_base : basic_compiled_format { | ||||
|   using char_type = char_t<S>; | ||||
|   using parts_container = std::vector<detail::format_part<char_type>>; | ||||
|  | ||||
|   parts_container compiled_parts; | ||||
|  | ||||
|   explicit compiled_format_base(basic_string_view<char_type> format_str) { | ||||
|     compile_format_string<false>(format_str, | ||||
|                                  [this](const format_part<char_type>& part) { | ||||
|                                    compiled_parts.push_back(part); | ||||
|                                  }); | ||||
|   } | ||||
|  | ||||
|   const parts_container& parts() const { return compiled_parts; } | ||||
| }; | ||||
|  | ||||
| template <typename Char, unsigned N> struct format_part_array { | ||||
|   format_part<Char> data[N] = {}; | ||||
|   FMT_CONSTEXPR format_part_array() = default; | ||||
| }; | ||||
|  | ||||
| template <typename Char, unsigned N> | ||||
| FMT_CONSTEXPR format_part_array<Char, N> compile_to_parts( | ||||
|     basic_string_view<Char> format_str) { | ||||
|   format_part_array<Char, N> parts; | ||||
|   unsigned counter = 0; | ||||
|   // This is not a lambda for compatibility with older compilers. | ||||
|   struct { | ||||
|     format_part<Char>* parts; | ||||
|     unsigned* counter; | ||||
|     FMT_CONSTEXPR void operator()(const format_part<Char>& part) { | ||||
|       parts[(*counter)++] = part; | ||||
|     } | ||||
|   } collector{parts.data, &counter}; | ||||
|   compile_format_string<true>(format_str, collector); | ||||
|   if (counter < N) { | ||||
|     parts.data[counter] = | ||||
|         format_part<Char>::make_text(basic_string_view<Char>()); | ||||
|   } | ||||
|   return parts; | ||||
| } | ||||
|  | ||||
| template <typename T> constexpr const T& constexpr_max(const T& a, const T& b) { | ||||
|   return (a < b) ? b : a; | ||||
| } | ||||
|  | ||||
| template <typename S> | ||||
| struct compiled_format_base<S, enable_if_t<is_compile_string<S>::value>> | ||||
|     : basic_compiled_format { | ||||
|   using char_type = char_t<S>; | ||||
|  | ||||
|   FMT_CONSTEXPR explicit compiled_format_base(basic_string_view<char_type>) {} | ||||
|  | ||||
| // Workaround for old compilers. Format string compilation will not be | ||||
| // performed there anyway. | ||||
| #if FMT_USE_CONSTEXPR | ||||
|   static FMT_CONSTEXPR_DECL const unsigned num_format_parts = | ||||
|       constexpr_max(count_parts(to_string_view(S())), 1u); | ||||
| #else | ||||
|   static const unsigned num_format_parts = 1; | ||||
| #endif | ||||
|  | ||||
|   using parts_container = format_part<char_type>[num_format_parts]; | ||||
|  | ||||
|   const parts_container& parts() const { | ||||
|     static FMT_CONSTEXPR_DECL const auto compiled_parts = | ||||
|         compile_to_parts<char_type, num_format_parts>( | ||||
|             detail::to_string_view(S())); | ||||
|     return compiled_parts.data; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename S, typename... Args> | ||||
| class compiled_format : private compiled_format_base<S> { | ||||
|  public: | ||||
|   using typename compiled_format_base<S>::char_type; | ||||
|  | ||||
|  private: | ||||
|   basic_string_view<char_type> format_str_; | ||||
|  | ||||
|   template <typename Context, typename OutputIt, typename CompiledFormat> | ||||
|   friend auto cf::vformat_to(OutputIt out, CompiledFormat& cf, | ||||
|                              basic_format_args<Context> args) -> | ||||
|       typename Context::iterator; | ||||
|  | ||||
|  public: | ||||
|   compiled_format() = delete; | ||||
|   explicit constexpr compiled_format(basic_string_view<char_type> format_str) | ||||
|       : compiled_format_base<S>(format_str), format_str_(format_str) {} | ||||
| }; | ||||
|  | ||||
| #ifdef __cpp_if_constexpr | ||||
| template <typename... Args> struct type_list {}; | ||||
|  | ||||
| @@ -489,6 +193,12 @@ constexpr const auto& get([[maybe_unused]] const T& first, | ||||
|     return get<N - 1>(rest...); | ||||
| } | ||||
|  | ||||
| template <typename Char, typename... Args> | ||||
| constexpr int get_arg_index_by_name(basic_string_view<Char> name, | ||||
|                                     type_list<Args...>) { | ||||
|   return get_arg_index_by_name<Args...>(name); | ||||
| } | ||||
|  | ||||
| template <int N, typename> struct get_type_impl; | ||||
|  | ||||
| template <int N, typename... Args> struct get_type_impl<N, type_list<Args...>> { | ||||
| @@ -529,6 +239,17 @@ template <typename Char> struct code_unit { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // This ensures that the argument type is convertible to `const T&`. | ||||
| template <typename T, int N, typename... Args> | ||||
| constexpr const T& get_arg_checked(const Args&... args) { | ||||
|   const auto& arg = get<N>(args...); | ||||
|   if constexpr (detail::is_named_arg<remove_cvref_t<decltype(arg)>>()) { | ||||
|     return arg.value; | ||||
|   } else { | ||||
|     return arg; | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename Char> | ||||
| struct is_compiled_format<code_unit<Char>> : std::true_type {}; | ||||
|  | ||||
| @@ -538,14 +259,7 @@ template <typename Char, typename T, int N> struct field { | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   constexpr OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     if constexpr (is_named_arg<typename std::remove_cv<T>::type>::value) { | ||||
|       const auto& arg = get<N>(args...).value; | ||||
|       return write<Char>(out, arg); | ||||
|     } else { | ||||
|       // This ensures that the argument type is convertile to `const T&`. | ||||
|       const T& arg = get<N>(args...); | ||||
|       return write<Char>(out, arg); | ||||
|     } | ||||
|     return write<Char>(out, get_arg_checked<T, N>(args...)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -590,13 +304,12 @@ template <typename Char, typename T, int N> struct spec_field { | ||||
|   formatter<T, Char> fmt; | ||||
|  | ||||
|   template <typename OutputIt, typename... Args> | ||||
|   constexpr OutputIt format(OutputIt out, const Args&... args) const { | ||||
|     // This ensures that the argument type is convertile to `const T&`. | ||||
|     const T& arg = get<N>(args...); | ||||
|   constexpr FMT_INLINE OutputIt format(OutputIt out, | ||||
|                                        const Args&... args) const { | ||||
|     const auto& vargs = | ||||
|         make_format_args<basic_format_context<OutputIt, Char>>(args...); | ||||
|         fmt::make_format_args<basic_format_context<OutputIt, Char>>(args...); | ||||
|     basic_format_context<OutputIt, Char> ctx(out, vargs); | ||||
|     return fmt.format(arg, ctx); | ||||
|     return fmt.format(get_arg_checked<T, N>(args...), ctx); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -671,24 +384,22 @@ constexpr parse_specs_result<T, Char> parse_specs(basic_string_view<Char> str, | ||||
| } | ||||
|  | ||||
| template <typename Char> struct arg_id_handler { | ||||
|   constexpr void on_error(const char* message) { throw format_error(message); } | ||||
|   arg_ref<Char> arg_id; | ||||
|  | ||||
|   constexpr int on_arg_id() { | ||||
|   constexpr int operator()() { | ||||
|     FMT_ASSERT(false, "handler cannot be used with automatic indexing"); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   constexpr int on_arg_id(int id) { | ||||
|   constexpr int operator()(int id) { | ||||
|     arg_id = arg_ref<Char>(id); | ||||
|     return 0; | ||||
|   } | ||||
|   constexpr int operator()(basic_string_view<Char> id) { | ||||
|     arg_id = arg_ref<Char>(id); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   constexpr int on_arg_id(basic_string_view<Char> id) { | ||||
|     arg_id = arg_ref<Char>(id); | ||||
|     return 0; | ||||
|   } | ||||
|  | ||||
|   arg_ref<Char> arg_id; | ||||
|   constexpr void on_error(const char* message) { throw format_error(message); } | ||||
| }; | ||||
|  | ||||
| template <typename Char> struct parse_arg_id_result { | ||||
| @@ -699,17 +410,45 @@ template <typename Char> struct parse_arg_id_result { | ||||
| template <int ID, typename Char> | ||||
| constexpr auto parse_arg_id(const Char* begin, const Char* end) { | ||||
|   auto handler = arg_id_handler<Char>{arg_ref<Char>{}}; | ||||
|   auto adapter = id_adapter<arg_id_handler<Char>, Char>{handler, 0}; | ||||
|   auto arg_id_end = parse_arg_id(begin, end, adapter); | ||||
|   auto arg_id_end = parse_arg_id(begin, end, handler); | ||||
|   return parse_arg_id_result<Char>{handler.arg_id, arg_id_end}; | ||||
| } | ||||
|  | ||||
| template <typename T, typename Enable = void> struct field_type { | ||||
|   using type = remove_cvref_t<T>; | ||||
| }; | ||||
|  | ||||
| template <typename T> | ||||
| struct field_type<T, enable_if_t<detail::is_named_arg<T>::value>> { | ||||
|   using type = remove_cvref_t<decltype(T::value)>; | ||||
| }; | ||||
|  | ||||
| template <typename T, typename Args, size_t END_POS, int ARG_INDEX, int NEXT_ID, | ||||
|           typename S> | ||||
| constexpr auto parse_replacement_field_then_tail(S format_str) { | ||||
|   using char_type = typename S::char_type; | ||||
|   constexpr auto str = basic_string_view<char_type>(format_str); | ||||
|   constexpr char_type c = END_POS != str.size() ? str[END_POS] : char_type(); | ||||
|   if constexpr (c == '}') { | ||||
|     return parse_tail<Args, END_POS + 1, NEXT_ID>( | ||||
|         field<char_type, typename field_type<T>::type, ARG_INDEX>(), | ||||
|         format_str); | ||||
|   } else if constexpr (c == ':') { | ||||
|     constexpr auto result = parse_specs<typename field_type<T>::type>( | ||||
|         str, END_POS + 1, NEXT_ID == manual_indexing_id ? 0 : NEXT_ID); | ||||
|     return parse_tail<Args, result.end, result.next_arg_id>( | ||||
|         spec_field<char_type, typename field_type<T>::type, ARG_INDEX>{ | ||||
|             result.fmt}, | ||||
|         format_str); | ||||
|   } | ||||
| } | ||||
|  | ||||
| // Compiles a non-empty format string and returns the compiled representation | ||||
| // or unknown_format() on unrecognized input. | ||||
| template <typename Args, size_t POS, int ID, typename S> | ||||
| constexpr auto compile_format_string(S format_str) { | ||||
|   using char_type = typename S::char_type; | ||||
|   constexpr basic_string_view<char_type> str = format_str; | ||||
|   constexpr auto str = basic_string_view<char_type>(format_str); | ||||
|   if constexpr (str[POS] == '{') { | ||||
|     if constexpr (POS + 1 == str.size()) | ||||
|       throw format_error("unmatched '{' in format string"); | ||||
| @@ -718,17 +457,11 @@ constexpr auto compile_format_string(S format_str) { | ||||
|     } else if constexpr (str[POS + 1] == '}' || str[POS + 1] == ':') { | ||||
|       static_assert(ID != manual_indexing_id, | ||||
|                     "cannot switch from manual to automatic argument indexing"); | ||||
|       using id_type = get_type<ID, Args>; | ||||
|       if constexpr (str[POS + 1] == '}') { | ||||
|         constexpr auto next_id = | ||||
|             ID != manual_indexing_id ? ID + 1 : manual_indexing_id; | ||||
|         return parse_tail<Args, POS + 2, next_id>( | ||||
|             field<char_type, id_type, ID>(), format_str); | ||||
|       } else { | ||||
|         constexpr auto result = parse_specs<id_type>(str, POS + 2, ID + 1); | ||||
|         return parse_tail<Args, result.end, result.next_arg_id>( | ||||
|             spec_field<char_type, id_type, ID>{result.fmt}, format_str); | ||||
|       } | ||||
|       constexpr auto next_id = | ||||
|           ID != manual_indexing_id ? ID + 1 : manual_indexing_id; | ||||
|       return parse_replacement_field_then_tail<get_type<ID, Args>, Args, | ||||
|                                                POS + 1, ID, next_id>( | ||||
|           format_str); | ||||
|     } else { | ||||
|       constexpr auto arg_id_result = | ||||
|           parse_arg_id<ID>(str.data() + POS + 1, str.data() + str.size()); | ||||
| @@ -741,24 +474,27 @@ constexpr auto compile_format_string(S format_str) { | ||||
|             ID == manual_indexing_id || ID == 0, | ||||
|             "cannot switch from automatic to manual argument indexing"); | ||||
|         constexpr auto arg_index = arg_id_result.arg_id.val.index; | ||||
|         using id_type = get_type<arg_index, Args>; | ||||
|         if constexpr (c == '}') { | ||||
|           return parse_tail<Args, arg_id_end_pos + 1, manual_indexing_id>( | ||||
|               field<char_type, id_type, arg_index>(), format_str); | ||||
|         } else if constexpr (c == ':') { | ||||
|           constexpr auto result = | ||||
|               parse_specs<id_type>(str, arg_id_end_pos + 1, 0); | ||||
|           return parse_tail<Args, result.end, result.next_arg_id>( | ||||
|               spec_field<char_type, id_type, arg_index>{result.fmt}, | ||||
|               format_str); | ||||
|         } | ||||
|         return parse_replacement_field_then_tail<get_type<arg_index, Args>, | ||||
|                                                  Args, arg_id_end_pos, | ||||
|                                                  arg_index, manual_indexing_id>( | ||||
|             format_str); | ||||
|       } else if constexpr (arg_id_result.arg_id.kind == arg_id_kind::name) { | ||||
|         if constexpr (c == '}') { | ||||
|           return parse_tail<Args, arg_id_end_pos + 1, ID>( | ||||
|               runtime_named_field<char_type>{arg_id_result.arg_id.val.name}, | ||||
|               format_str); | ||||
|         } else if constexpr (c == ':') { | ||||
|           return unknown_format();  // no type info for specs parsing | ||||
|         constexpr auto arg_index = | ||||
|             get_arg_index_by_name(arg_id_result.arg_id.val.name, Args{}); | ||||
|         if constexpr (arg_index != invalid_arg_index) { | ||||
|           constexpr auto next_id = | ||||
|               ID != manual_indexing_id ? ID + 1 : manual_indexing_id; | ||||
|           return parse_replacement_field_then_tail< | ||||
|               decltype(get_type<arg_index, Args>::value), Args, arg_id_end_pos, | ||||
|               arg_index, next_id>(format_str); | ||||
|         } else { | ||||
|           if constexpr (c == '}') { | ||||
|             return parse_tail<Args, arg_id_end_pos + 1, ID>( | ||||
|                 runtime_named_field<char_type>{arg_id_result.arg_id.val.name}, | ||||
|                 format_str); | ||||
|           } else if constexpr (c == ':') { | ||||
|             return unknown_format();  // no type info for specs parsing | ||||
|           } | ||||
|         } | ||||
|       } | ||||
|     } | ||||
| @@ -779,10 +515,9 @@ constexpr auto compile_format_string(S format_str) { | ||||
| } | ||||
|  | ||||
| template <typename... Args, typename S, | ||||
|           FMT_ENABLE_IF(is_compile_string<S>::value || | ||||
|                         detail::is_compiled_string<S>::value)> | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| constexpr auto compile(S format_str) { | ||||
|   constexpr basic_string_view<typename S::char_type> str = format_str; | ||||
|   constexpr auto str = basic_string_view<typename S::char_type>(format_str); | ||||
|   if constexpr (str.size() == 0) { | ||||
|     return detail::make_text(str, 0, 0); | ||||
|   } else { | ||||
| @@ -792,71 +527,36 @@ constexpr auto compile(S format_str) { | ||||
|     return result; | ||||
|   } | ||||
| } | ||||
| #else | ||||
| template <typename... Args, typename S, | ||||
|           FMT_ENABLE_IF(is_compile_string<S>::value)> | ||||
| constexpr auto compile(S format_str) -> detail::compiled_format<S, Args...> { | ||||
|   return detail::compiled_format<S, Args...>(to_string_view(format_str)); | ||||
| } | ||||
| #endif  // __cpp_if_constexpr | ||||
|  | ||||
| // Compiles the format string which must be a string literal. | ||||
| template <typename... Args, typename Char, size_t N> | ||||
| auto compile(const Char (&format_str)[N]) | ||||
|     -> detail::compiled_format<const Char*, Args...> { | ||||
|   return detail::compiled_format<const Char*, Args...>( | ||||
|       basic_string_view<Char>(format_str, N - 1)); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| // DEPRECATED! use FMT_COMPILE instead. | ||||
| template <typename... Args> | ||||
| FMT_DEPRECATED auto compile(const Args&... args) | ||||
|     -> decltype(detail::compile(args...)) { | ||||
|   return detail::compile(args...); | ||||
| } | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| #if FMT_USE_CONSTEXPR | ||||
| #  ifdef __cpp_if_constexpr | ||||
| #ifdef __cpp_if_constexpr | ||||
|  | ||||
| template <typename CompiledFormat, typename... Args, | ||||
|           typename Char = typename CompiledFormat::char_type, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)> | ||||
| FMT_INLINE std::basic_string<Char> format(const CompiledFormat& cf, | ||||
|                                           const Args&... args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   cf.format(detail::buffer_appender<Char>(buffer), args...); | ||||
|   return to_string(buffer); | ||||
|   auto s = std::basic_string<Char>(); | ||||
|   cf.format(std::back_inserter(s), args...); | ||||
|   return s; | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_format<CompiledFormat>::value)> | ||||
| constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                              const Args&... args) { | ||||
| constexpr FMT_INLINE OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                                         const Args&... args) { | ||||
|   return cf.format(out, args...); | ||||
| } | ||||
| #  endif  // __cpp_if_constexpr | ||||
| #endif    // FMT_USE_CONSTEXPR | ||||
|  | ||||
| template <typename CompiledFormat, typename... Args, | ||||
|           typename Char = typename CompiledFormat::char_type, | ||||
|           FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format, | ||||
|                                         CompiledFormat>::value)> | ||||
| std::basic_string<Char> format(const CompiledFormat& cf, const Args&... args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   using context = buffer_context<Char>; | ||||
|   detail::cf::vformat_to<context>(detail::buffer_appender<Char>(buffer), cf, | ||||
|                                   make_format_args<context>(args...)); | ||||
|   return to_string(buffer); | ||||
| } | ||||
|  | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| FMT_INLINE std::basic_string<typename S::char_type> format(const S&, | ||||
|                                                            Args&&... args) { | ||||
| #ifdef __cpp_if_constexpr | ||||
|   if constexpr (std::is_same<typename S::char_type, char>::value) { | ||||
|     constexpr basic_string_view<typename S::char_type> str = S(); | ||||
|     constexpr auto str = basic_string_view<typename S::char_type>(S()); | ||||
|     if constexpr (str.size() == 2 && str[0] == '{' && str[1] == '}') { | ||||
|       const auto& first = detail::first(args...); | ||||
|       if constexpr (detail::is_named_arg< | ||||
| @@ -867,9 +567,7 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&, | ||||
|       } | ||||
|     } | ||||
|   } | ||||
| #endif | ||||
|   constexpr auto compiled = detail::compile<Args...>(S()); | ||||
| #ifdef __cpp_if_constexpr | ||||
|   if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>, | ||||
|                              detail::unknown_format>()) { | ||||
|     return format(static_cast<basic_string_view<typename S::char_type>>(S()), | ||||
| @@ -877,27 +575,12 @@ FMT_INLINE std::basic_string<typename S::char_type> format(const S&, | ||||
|   } else { | ||||
|     return format(compiled, std::forward<Args>(args)...); | ||||
|   } | ||||
| #else | ||||
|   return format(compiled, std::forward<Args>(args)...); | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format, | ||||
|                                         CompiledFormat>::value)> | ||||
| constexpr OutputIt format_to(OutputIt out, const CompiledFormat& cf, | ||||
|                              const Args&... args) { | ||||
|   using char_type = typename CompiledFormat::char_type; | ||||
|   using context = format_context_t<OutputIt, char_type>; | ||||
|   return detail::cf::vformat_to<context>(out, cf, | ||||
|                                          make_format_args<context>(args...)); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { | ||||
|   constexpr auto compiled = detail::compile<Args...>(S()); | ||||
| #ifdef __cpp_if_constexpr | ||||
|   if constexpr (std::is_same<remove_cvref_t<decltype(compiled)>, | ||||
|                              detail::unknown_format>()) { | ||||
|     return format_to(out, | ||||
| @@ -906,53 +589,51 @@ FMT_CONSTEXPR OutputIt format_to(OutputIt out, const S&, Args&&... args) { | ||||
|   } else { | ||||
|     return format_to(out, compiled, std::forward<Args>(args)...); | ||||
|   } | ||||
| #else | ||||
|   return format_to(out, compiled, std::forward<Args>(args)...); | ||||
| } | ||||
| #endif | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename CompiledFormat, typename... Args> | ||||
| auto format_to_n(OutputIt out, size_t n, const CompiledFormat& cf, | ||||
|                  const Args&... args) -> | ||||
|     typename std::enable_if< | ||||
|         detail::is_output_iterator<OutputIt, | ||||
|                                    typename CompiledFormat::char_type>::value && | ||||
|             std::is_base_of<detail::basic_compiled_format, | ||||
|                             CompiledFormat>::value, | ||||
|         format_to_n_result<OutputIt>>::type { | ||||
|   auto it = | ||||
|       format_to(detail::truncating_iterator<OutputIt>(out, n), cf, args...); | ||||
|   return {it.base(), it.count()}; | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, const S&, | ||||
|                                          Args&&... args) { | ||||
|   auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), S(), | ||||
| format_to_n_result<OutputIt> format_to_n(OutputIt out, size_t n, | ||||
|                                          const S& format_str, Args&&... args) { | ||||
|   auto it = format_to(detail::truncating_iterator<OutputIt>(out, n), format_str, | ||||
|                       std::forward<Args>(args)...); | ||||
|   return {it.base(), it.count()}; | ||||
| } | ||||
|  | ||||
| template <typename CompiledFormat, typename... Args, | ||||
|           FMT_ENABLE_IF(std::is_base_of<detail::basic_compiled_format, | ||||
|                                         CompiledFormat>::value || | ||||
|                         detail::is_compiled_string<CompiledFormat>::value)> | ||||
| size_t formatted_size(const CompiledFormat& cf, const Args&... args) { | ||||
|   return format_to(detail::counting_iterator(), cf, args...).count(); | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| size_t formatted_size(const S& format_str, const Args&... args) { | ||||
|   return format_to(detail::counting_iterator(), format_str, args...).count(); | ||||
| } | ||||
|  | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| void print(std::FILE* f, const S& format_str, const Args&... args) { | ||||
|   memory_buffer buffer; | ||||
|   format_to(std::back_inserter(buffer), format_str, args...); | ||||
|   detail::print(f, {buffer.data(), buffer.size()}); | ||||
| } | ||||
|  | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_compiled_string<S>::value)> | ||||
| void print(const S& format_str, const Args&... args) { | ||||
|   print(stdout, format_str, args...); | ||||
| } | ||||
|  | ||||
| #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| inline namespace literals { | ||||
| template <detail::fixed_string Str> | ||||
| constexpr detail::udl_compiled_string<remove_cvref_t<decltype(Str.data[0])>, | ||||
|                                       sizeof(Str.data), Str> | ||||
| template <detail_exported::fixed_string Str> | ||||
| constexpr detail::udl_compiled_string< | ||||
|     remove_cvref_t<decltype(Str.data[0])>, | ||||
|     sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> | ||||
| operator""_cf() { | ||||
|   return {}; | ||||
| } | ||||
| }  // namespace literals | ||||
| #endif | ||||
|  | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_COMPILE_H_ | ||||
|   | ||||
							
								
								
									
										1893
									
								
								vendor/Fmt/include/fmt/core.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1893
									
								
								vendor/Fmt/include/fmt/core.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										1902
									
								
								vendor/Fmt/include/fmt/format-inl.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										1902
									
								
								vendor/Fmt/include/fmt/format-inl.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										3009
									
								
								vendor/Fmt/include/fmt/format.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3009
									
								
								vendor/Fmt/include/fmt/format.h
									
									
									
									
										vendored
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										66
									
								
								vendor/Fmt/include/fmt/locale.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										66
									
								
								vendor/Fmt/include/fmt/locale.h
									
									
									
									
										vendored
									
									
								
							| @@ -1,64 +1,2 @@ | ||||
| // Formatting library for C++ - std::locale support | ||||
| // | ||||
| // Copyright (c) 2012 - present, Victor Zverovich | ||||
| // All rights reserved. | ||||
| // | ||||
| // For the license information refer to format.h. | ||||
|  | ||||
| #ifndef FMT_LOCALE_H_ | ||||
| #define FMT_LOCALE_H_ | ||||
|  | ||||
| #include <locale> | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| namespace detail { | ||||
| template <typename Char> | ||||
| std::basic_string<Char> vformat( | ||||
|     const std::locale& loc, basic_string_view<Char> format_str, | ||||
|     basic_format_args<buffer_context<type_identity_t<Char>>> args) { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc)); | ||||
|   return fmt::to_string(buffer); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| 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<buffer_context<type_identity_t<Char>>> args) { | ||||
|   return detail::vformat(loc, to_string_view(format_str), 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 detail::vformat(loc, to_string_view(format_str), | ||||
|                          fmt::make_args_checked<Args...>(format_str, args...)); | ||||
| } | ||||
|  | ||||
| template <typename S, typename OutputIt, typename... Args, | ||||
|           typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value)> | ||||
| inline OutputIt vformat_to( | ||||
|     OutputIt out, const std::locale& loc, const S& format_str, | ||||
|     basic_format_args<buffer_context<type_identity_t<Char>>> args) { | ||||
|   decltype(detail::get_buffer<Char>(out)) buf(detail::get_buffer_init(out)); | ||||
|   vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc)); | ||||
|   return detail::get_iterator(buf); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           bool enable = detail::is_output_iterator<OutputIt, char_t<S>>::value> | ||||
| inline auto format_to(OutputIt out, const std::locale& loc, const S& format_str, | ||||
|                       Args&&... args) -> | ||||
|     typename std::enable_if<enable, OutputIt>::type { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   return vformat_to(out, loc, to_string_view(format_str), vargs); | ||||
| } | ||||
|  | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_LOCALE_H_ | ||||
| #include "xchar.h" | ||||
| #warning fmt/locale.h is deprecated, include fmt/format.h or fmt/xchar.h instead | ||||
|   | ||||
							
								
								
									
										149
									
								
								vendor/Fmt/include/fmt/os.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										149
									
								
								vendor/Fmt/include/fmt/os.h
									
									
									
									
										vendored
									
									
								
							| @@ -9,10 +9,11 @@ | ||||
| #define FMT_OS_H_ | ||||
|  | ||||
| #include <cerrno> | ||||
| #include <clocale>  // for locale_t | ||||
| #include <clocale>  // locale_t | ||||
| #include <cstddef> | ||||
| #include <cstdio> | ||||
| #include <cstdlib>  // for strtod_l | ||||
| #include <cstdlib>       // strtod_l | ||||
| #include <system_error>  // std::system_error | ||||
|  | ||||
| #if defined __APPLE__ || defined(__FreeBSD__) | ||||
| #  include <xlocale.h>  // for LC_NUMERIC_MASK on OS X | ||||
| @@ -69,6 +70,7 @@ | ||||
| #define FMT_RETRY(result, expression) FMT_RETRY_VAL(result, expression, -1) | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
| @@ -117,19 +119,28 @@ template <typename Char> class basic_cstring_view { | ||||
| using cstring_view = basic_cstring_view<char>; | ||||
| using wcstring_view = basic_cstring_view<wchar_t>; | ||||
|  | ||||
| // An error code. | ||||
| class error_code { | ||||
|  private: | ||||
|   int value_; | ||||
| template <typename Char> struct formatter<std::error_code, Char> { | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   explicit error_code(int value = 0) FMT_NOEXCEPT : value_(value) {} | ||||
|  | ||||
|   int get() const FMT_NOEXCEPT { return value_; } | ||||
|   template <typename FormatContext> | ||||
|   FMT_CONSTEXPR auto format(const std::error_code& ec, FormatContext& ctx) const | ||||
|       -> decltype(ctx.out()) { | ||||
|     auto out = ctx.out(); | ||||
|     out = detail::write_bytes(out, ec.category().name(), | ||||
|                               basic_format_specs<Char>()); | ||||
|     out = detail::write<Char>(out, Char(':')); | ||||
|     out = detail::write<Char>(out, ec.value()); | ||||
|     return out; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| namespace detail { | ||||
| FMT_API const std::error_category& system_category() FMT_NOEXCEPT; | ||||
|  | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
| // A converter from UTF-16 to UTF-8. | ||||
| // It is only provided for Windows since other systems support UTF-8 natively. | ||||
| class utf16_to_utf8 { | ||||
| @@ -138,7 +149,7 @@ class utf16_to_utf8 { | ||||
|  | ||||
|  public: | ||||
|   utf16_to_utf8() {} | ||||
|   FMT_API explicit utf16_to_utf8(wstring_view s); | ||||
|   FMT_API explicit utf16_to_utf8(basic_string_view<wchar_t> s); | ||||
|   operator string_view() const { return string_view(&buffer_[0], size()); } | ||||
|   size_t size() const { return buffer_.size() - 1; } | ||||
|   const char* c_str() const { return &buffer_[0]; } | ||||
| @@ -147,59 +158,68 @@ class utf16_to_utf8 { | ||||
|   // Performs conversion returning a system error code instead of | ||||
|   // throwing exception on conversion error. This method may still throw | ||||
|   // in case of memory allocation error. | ||||
|   FMT_API int convert(wstring_view s); | ||||
|   FMT_API int convert(basic_string_view<wchar_t> s); | ||||
| }; | ||||
|  | ||||
| FMT_API void format_windows_error(buffer<char>& out, int error_code, | ||||
|                                   string_view message) FMT_NOEXCEPT; | ||||
| }  // namespace detail | ||||
|                                   const char* message) FMT_NOEXCEPT; | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| /** A Windows error. */ | ||||
| class windows_error : public system_error { | ||||
|  private: | ||||
|   FMT_API void init(int error_code, string_view format_str, format_args args); | ||||
| FMT_API std::system_error vwindows_error(int error_code, string_view format_str, | ||||
|                                          format_args args); | ||||
|  | ||||
|  public: | ||||
|   /** | ||||
|    \rst | ||||
|    Constructs a :class:`fmt::windows_error` object with the description | ||||
|    of the form | ||||
| /** | ||||
|  \rst | ||||
|  Constructs a :class:`std::system_error` object with the description | ||||
|  of the form | ||||
|  | ||||
|    .. parsed-literal:: | ||||
|      *<message>*: *<system-message>* | ||||
|  .. parsed-literal:: | ||||
|    *<message>*: *<system-message>* | ||||
|  | ||||
|    where *<message>* is the formatted message and *<system-message>* is the | ||||
|    system message corresponding to the error code. | ||||
|    *error_code* is a Windows error code as given by ``GetLastError``. | ||||
|    If *error_code* is not a valid error code such as -1, the system message | ||||
|    will look like "error -1". | ||||
|  where *<message>* is the formatted message and *<system-message>* is the | ||||
|  system message corresponding to the error code. | ||||
|  *error_code* is a Windows error code as given by ``GetLastError``. | ||||
|  If *error_code* is not a valid error code such as -1, the system message | ||||
|  will look like "error -1". | ||||
|  | ||||
|    **Example**:: | ||||
|  **Example**:: | ||||
|  | ||||
|      // This throws a windows_error with the description | ||||
|      //   cannot open file 'madeup': The system cannot find the file specified. | ||||
|      // or similar (system message may vary). | ||||
|      const char *filename = "madeup"; | ||||
|      LPOFSTRUCT of = LPOFSTRUCT(); | ||||
|      HFILE file = OpenFile(filename, &of, OF_READ); | ||||
|      if (file == HFILE_ERROR) { | ||||
|        throw fmt::windows_error(GetLastError(), | ||||
|                                 "cannot open file '{}'", filename); | ||||
|      } | ||||
|    \endrst | ||||
|   */ | ||||
|   template <typename... Args> | ||||
|   windows_error(int error_code, string_view message, const Args&... args) { | ||||
|     init(error_code, message, make_format_args(args...)); | ||||
|   } | ||||
| }; | ||||
|    // This throws a system_error with the description | ||||
|    //   cannot open file 'madeup': The system cannot find the file specified. | ||||
|    // or similar (system message may vary). | ||||
|    const char *filename = "madeup"; | ||||
|    LPOFSTRUCT of = LPOFSTRUCT(); | ||||
|    HFILE file = OpenFile(filename, &of, OF_READ); | ||||
|    if (file == HFILE_ERROR) { | ||||
|      throw fmt::windows_error(GetLastError(), | ||||
|                               "cannot open file '{}'", filename); | ||||
|    } | ||||
|  \endrst | ||||
| */ | ||||
| template <typename... Args> | ||||
| std::system_error windows_error(int error_code, string_view message, | ||||
|                                 const Args&... args) { | ||||
|   return vwindows_error(error_code, message, fmt::make_format_args(args...)); | ||||
| } | ||||
|  | ||||
| // Reports a Windows error without throwing an exception. | ||||
| // Can be used to report errors from destructors. | ||||
| FMT_API void report_windows_error(int error_code, | ||||
|                                   string_view message) FMT_NOEXCEPT; | ||||
|                                   const char* message) FMT_NOEXCEPT; | ||||
| #else | ||||
| inline const std::error_category& system_category() FMT_NOEXCEPT { | ||||
|   return std::system_category(); | ||||
| } | ||||
| #endif  // _WIN32 | ||||
|  | ||||
| // std::system is not available on some platforms such as iOS (#2248). | ||||
| #ifdef __OSX__ | ||||
| template <typename S, typename... Args, typename Char = char_t<S>> | ||||
| void say(const S& format_str, Args&&... args) { | ||||
|   std::system(format("say \"{}\"", format(format_str, args...)).c_str()); | ||||
| } | ||||
| #endif | ||||
|  | ||||
| // A buffered file. | ||||
| class buffered_file { | ||||
|  private: | ||||
| @@ -250,7 +270,7 @@ class buffered_file { | ||||
|  | ||||
|   template <typename... Args> | ||||
|   inline void print(string_view format_str, const Args&... args) { | ||||
|     vprint(format_str, make_format_args(args...)); | ||||
|     vprint(format_str, fmt::make_format_args(args...)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -291,7 +311,8 @@ class file { | ||||
|  | ||||
|   file(file&& other) FMT_NOEXCEPT : fd_(other.fd_) { other.fd_ = -1; } | ||||
|  | ||||
|   file& operator=(file&& other) FMT_NOEXCEPT { | ||||
|   // Move assignment is not noexcept because close may throw. | ||||
|   file& operator=(file&& other) { | ||||
|     close(); | ||||
|     fd_ = other.fd_; | ||||
|     other.fd_ = -1; | ||||
| @@ -327,7 +348,7 @@ 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, std::error_code& ec) FMT_NOEXCEPT; | ||||
|  | ||||
|   // Creates a pipe setting up read_end and write_end file objects for reading | ||||
|   // and writing respectively. | ||||
| @@ -341,7 +362,7 @@ class file { | ||||
| // Returns the memory page size. | ||||
| long getpagesize(); | ||||
|  | ||||
| namespace detail { | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
|  | ||||
| struct buffer_size { | ||||
|   buffer_size() = default; | ||||
| @@ -370,12 +391,13 @@ struct ostream_params { | ||||
|     this->buffer_size = bs.value; | ||||
|   } | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| static constexpr detail::buffer_size buffer_size; | ||||
|  | ||||
| /** A fast output stream which is not thread-safe. */ | ||||
| class ostream final : private detail::buffer<char> { | ||||
| class FMT_API ostream final : private detail::buffer<char> { | ||||
|  private: | ||||
|   file file_; | ||||
|  | ||||
| @@ -385,7 +407,7 @@ class ostream final : private detail::buffer<char> { | ||||
|     clear(); | ||||
|   } | ||||
|  | ||||
|   FMT_API void grow(size_t) override final; | ||||
|   void grow(size_t) override; | ||||
|  | ||||
|   ostream(cstring_view path, const detail::ostream_params& params) | ||||
|       : file_(path, params.oflag) { | ||||
| @@ -396,6 +418,7 @@ class ostream final : private detail::buffer<char> { | ||||
|   ostream(ostream&& other) | ||||
|       : detail::buffer<char>(other.data(), other.size(), other.capacity()), | ||||
|         file_(std::move(other.file_)) { | ||||
|     other.clear(); | ||||
|     other.set(nullptr, 0); | ||||
|   } | ||||
|   ~ostream() { | ||||
| @@ -412,13 +435,12 @@ class ostream final : private detail::buffer<char> { | ||||
|   } | ||||
|  | ||||
|   /** | ||||
|     Formats ``args`` according to specifications in ``format_str`` and writes | ||||
|     the output to the file. | ||||
|     Formats ``args`` according to specifications in ``fmt`` and writes the | ||||
|     output to the file. | ||||
|    */ | ||||
|   template <typename S, typename... Args> | ||||
|   void print(const S& format_str, Args&&... args) { | ||||
|     format_to(detail::buffer_appender<char>(*this), format_str, | ||||
|               std::forward<Args>(args)...); | ||||
|   template <typename... T> void print(format_string<T...> fmt, T&&... args) { | ||||
|     vformat_to(detail::buffer_appender<char>(*this), fmt, | ||||
|                fmt::make_format_args(args...)); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| @@ -487,6 +509,7 @@ class locale { | ||||
| }; | ||||
| using Locale FMT_DEPRECATED_ALIAS = locale; | ||||
| #endif  // FMT_LOCALE | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_OS_H_ | ||||
|   | ||||
							
								
								
									
										2
									
								
								vendor/Fmt/include/fmt/ostream.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								vendor/Fmt/include/fmt/ostream.h
									
									
									
									
										vendored
									
									
								
							| @@ -151,6 +151,7 @@ struct fallback_formatter<T, Char, enable_if_t<is_streamable<T, Char>::value>> | ||||
| }; | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_MODULE_EXPORT | ||||
| template <typename Char> | ||||
| void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str, | ||||
|             basic_format_args<buffer_context<type_identity_t<Char>>> args) { | ||||
| @@ -168,6 +169,7 @@ void vprint(std::basic_ostream<Char>& os, basic_string_view<Char> format_str, | ||||
|     fmt::print(cerr, "Don't {}!", "panic"); | ||||
|   \endrst | ||||
|  */ | ||||
| FMT_MODULE_EXPORT | ||||
| template <typename S, typename... Args, | ||||
|           typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>> | ||||
| void print(std::basic_ostream<Char>& os, const S& format_str, Args&&... args) { | ||||
|   | ||||
							
								
								
									
										388
									
								
								vendor/Fmt/include/fmt/printf.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										388
									
								
								vendor/Fmt/include/fmt/printf.h
									
									
									
									
										vendored
									
									
								
							| @@ -10,11 +10,54 @@ | ||||
|  | ||||
| #include <algorithm>  // std::max | ||||
| #include <limits>     // std::numeric_limits | ||||
| #include <ostream> | ||||
|  | ||||
| #include "ostream.h" | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| namespace detail { | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| template <typename T> struct printf_formatter { printf_formatter() = delete; }; | ||||
|  | ||||
| template <typename Char> | ||||
| class basic_printf_parse_context : public basic_format_parse_context<Char> { | ||||
|   using basic_format_parse_context<Char>::basic_format_parse_context; | ||||
| }; | ||||
|  | ||||
| template <typename OutputIt, typename Char> class basic_printf_context { | ||||
|  private: | ||||
|   OutputIt out_; | ||||
|   basic_format_args<basic_printf_context> args_; | ||||
|  | ||||
|  public: | ||||
|   using char_type = Char; | ||||
|   using format_arg = basic_format_arg<basic_printf_context>; | ||||
|   using parse_context_type = basic_printf_parse_context<Char>; | ||||
|   template <typename T> using formatter_type = printf_formatter<T>; | ||||
|  | ||||
|   /** | ||||
|     \rst | ||||
|     Constructs a ``printf_context`` object. References to the arguments are | ||||
|     stored in the context object so make sure they have appropriate lifetimes. | ||||
|     \endrst | ||||
|    */ | ||||
|   basic_printf_context(OutputIt out, | ||||
|                        basic_format_args<basic_printf_context> args) | ||||
|       : out_(out), args_(args) {} | ||||
|  | ||||
|   OutputIt out() { return out_; } | ||||
|   void advance_to(OutputIt it) { out_ = it; } | ||||
|  | ||||
|   detail::locale_ref locale() { return {}; } | ||||
|  | ||||
|   format_arg arg(int id) const { return args_.get(id); } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_error(const char* message) { | ||||
|     detail::error_handler().on_error(message); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| FMT_BEGIN_DETAIL_NAMESPACE | ||||
|  | ||||
| // Checks if a value fits in int - used to avoid warnings about comparing | ||||
| // signed and unsigned integers. | ||||
| @@ -178,61 +221,34 @@ template <typename Char> class printf_width_handler { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename Context> | ||||
| void vprintf(buffer<Char>& buf, basic_string_view<Char> format, | ||||
|              basic_format_args<Context> args) { | ||||
|   Context(buffer_appender<Char>(buf), format, args).format(); | ||||
| } | ||||
| }  // namespace detail | ||||
|  | ||||
| // For printing into memory_buffer. | ||||
| template <typename Char, typename Context> | ||||
| FMT_DEPRECATED void printf(detail::buffer<Char>& buf, | ||||
|                            basic_string_view<Char> format, | ||||
|                            basic_format_args<Context> args) { | ||||
|   return detail::vprintf(buf, format, args); | ||||
| } | ||||
| using detail::vprintf; | ||||
|  | ||||
| template <typename Char> | ||||
| class basic_printf_parse_context : public basic_format_parse_context<Char> { | ||||
|   using basic_format_parse_context<Char>::basic_format_parse_context; | ||||
| }; | ||||
| template <typename OutputIt, typename Char> class basic_printf_context; | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   The ``printf`` argument formatter. | ||||
|   \endrst | ||||
|  */ | ||||
| // The ``printf`` argument formatter. | ||||
| template <typename OutputIt, typename Char> | ||||
| class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> { | ||||
| class printf_arg_formatter : public arg_formatter<Char> { | ||||
|  private: | ||||
|   using base = detail::arg_formatter_base<OutputIt, Char>; | ||||
|   using base = arg_formatter<Char>; | ||||
|   using context_type = basic_printf_context<OutputIt, Char>; | ||||
|   using format_specs = typename base::format_specs; | ||||
|   using format_specs = basic_format_specs<Char>; | ||||
|  | ||||
|   context_type& context_; | ||||
|  | ||||
|   OutputIt write_null_pointer(bool is_string = false) { | ||||
|     auto s = this->specs(); | ||||
|     auto s = this->specs; | ||||
|     s.type = 0; | ||||
|     return detail::write(this->out(), | ||||
|                          string_view(is_string ? "(null)" : "(nil)"), s); | ||||
|     return write_bytes(this->out, is_string ? "(null)" : "(nil)", s); | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   printf_arg_formatter(OutputIt iter, format_specs& specs, context_type& ctx) | ||||
|       : base(iter, specs, detail::locale_ref()), context_(ctx) {} | ||||
|   printf_arg_formatter(OutputIt iter, format_specs& s, context_type& ctx) | ||||
|       : base{iter, s, locale_ref()}, context_(ctx) {} | ||||
|  | ||||
|   OutputIt operator()(monostate value) { return base::operator()(value); } | ||||
|  | ||||
|   template <typename T, FMT_ENABLE_IF(fmt::detail::is_integral<T>::value)> | ||||
|   template <typename T, FMT_ENABLE_IF(detail::is_integral<T>::value)> | ||||
|   OutputIt operator()(T value) { | ||||
|     // MSVC2013 fails to compile separate overloads for bool and Char so use | ||||
|     // std::is_same instead. | ||||
|     if (std::is_same<T, Char>::value) { | ||||
|       format_specs fmt_specs = this->specs(); | ||||
|       format_specs fmt_specs = this->specs; | ||||
|       if (fmt_specs.type && fmt_specs.type != 'c') | ||||
|         return (*this)(static_cast<int>(value)); | ||||
|       fmt_specs.sign = sign::none; | ||||
| @@ -242,7 +258,7 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> { | ||||
|       // ignored for non-numeric types | ||||
|       if (fmt_specs.align == align::none || fmt_specs.align == align::numeric) | ||||
|         fmt_specs.align = align::right; | ||||
|       return write_char(this->out(), static_cast<Char>(value), fmt_specs); | ||||
|       return write<Char>(this->out, static_cast<Char>(value), fmt_specs); | ||||
|     } | ||||
|     return base::operator()(value); | ||||
|   } | ||||
| @@ -255,13 +271,13 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> { | ||||
|   /** Formats a null-terminated C string. */ | ||||
|   OutputIt operator()(const char* value) { | ||||
|     if (value) return base::operator()(value); | ||||
|     return write_null_pointer(this->specs().type != 'p'); | ||||
|     return write_null_pointer(this->specs.type != 'p'); | ||||
|   } | ||||
|  | ||||
|   /** Formats a null-terminated wide C string. */ | ||||
|   OutputIt operator()(const wchar_t* value) { | ||||
|     if (value) return base::operator()(value); | ||||
|     return write_null_pointer(this->specs().type != 'p'); | ||||
|     return write_null_pointer(this->specs.type != 'p'); | ||||
|   } | ||||
|  | ||||
|   OutputIt operator()(basic_string_view<Char> value) { | ||||
| @@ -275,88 +291,16 @@ class printf_arg_formatter : public detail::arg_formatter_base<OutputIt, Char> { | ||||
|  | ||||
|   /** Formats an argument of a custom (user-defined) type. */ | ||||
|   OutputIt operator()(typename basic_format_arg<context_type>::handle handle) { | ||||
|     handle.format(context_.parse_context(), context_); | ||||
|     return this->out(); | ||||
|     auto parse_ctx = | ||||
|         basic_printf_parse_context<Char>(basic_string_view<Char>()); | ||||
|     handle.format(parse_ctx, context_); | ||||
|     return this->out; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename T> struct printf_formatter { | ||||
|   printf_formatter() = delete; | ||||
|  | ||||
|   template <typename ParseContext> | ||||
|   auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   auto format(const T& value, FormatContext& ctx) -> decltype(ctx.out()) { | ||||
|     detail::format_value(detail::get_container(ctx.out()), value); | ||||
|     return ctx.out(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  This template formats data and writes the output through an output iterator. | ||||
|  */ | ||||
| template <typename OutputIt, typename Char> class basic_printf_context { | ||||
|  public: | ||||
|   /** The character type for the output. */ | ||||
|   using char_type = Char; | ||||
|   using iterator = OutputIt; | ||||
|   using format_arg = basic_format_arg<basic_printf_context>; | ||||
|   using parse_context_type = basic_printf_parse_context<Char>; | ||||
|   template <typename T> using formatter_type = printf_formatter<T>; | ||||
|  | ||||
|  private: | ||||
|   using format_specs = basic_format_specs<char_type>; | ||||
|  | ||||
|   OutputIt out_; | ||||
|   basic_format_args<basic_printf_context> args_; | ||||
|   parse_context_type parse_ctx_; | ||||
|  | ||||
|   static void parse_flags(format_specs& specs, const Char*& it, | ||||
|                           const Char* end); | ||||
|  | ||||
|   // Returns the argument with specified index or, if arg_index is -1, the next | ||||
|   // argument. | ||||
|   format_arg get_arg(int arg_index = -1); | ||||
|  | ||||
|   // Parses argument index, flags and width and returns the argument index. | ||||
|   int parse_header(const Char*& it, const Char* end, format_specs& specs); | ||||
|  | ||||
|  public: | ||||
|   /** | ||||
|    \rst | ||||
|    Constructs a ``printf_context`` object. References to the arguments are | ||||
|    stored in the context object so make sure they have appropriate lifetimes. | ||||
|    \endrst | ||||
|    */ | ||||
|   basic_printf_context(OutputIt out, basic_string_view<char_type> format_str, | ||||
|                        basic_format_args<basic_printf_context> args) | ||||
|       : out_(out), args_(args), parse_ctx_(format_str) {} | ||||
|  | ||||
|   OutputIt out() { return out_; } | ||||
|   void advance_to(OutputIt it) { out_ = it; } | ||||
|  | ||||
|   detail::locale_ref locale() { return {}; } | ||||
|  | ||||
|   format_arg arg(int id) const { return args_.get(id); } | ||||
|  | ||||
|   parse_context_type& parse_context() { return parse_ctx_; } | ||||
|  | ||||
|   FMT_CONSTEXPR void on_error(const char* message) { | ||||
|     parse_ctx_.on_error(message); | ||||
|   } | ||||
|  | ||||
|   /** Formats stored arguments and writes the output to the range. */ | ||||
|   template <typename ArgFormatter = printf_arg_formatter<OutputIt, Char>> | ||||
|   OutputIt format(); | ||||
| }; | ||||
|  | ||||
| template <typename OutputIt, typename Char> | ||||
| void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs, | ||||
|                                                        const Char*& it, | ||||
|                                                        const Char* end) { | ||||
| template <typename Char> | ||||
| void parse_flags(basic_format_specs<Char>& specs, const Char*& it, | ||||
|                  const Char* end) { | ||||
|   for (; it != end; ++it) { | ||||
|     switch (*it) { | ||||
|     case '-': | ||||
| @@ -382,35 +326,24 @@ void basic_printf_context<OutputIt, Char>::parse_flags(format_specs& specs, | ||||
|   } | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename Char> | ||||
| typename basic_printf_context<OutputIt, Char>::format_arg | ||||
| basic_printf_context<OutputIt, Char>::get_arg(int arg_index) { | ||||
|   if (arg_index < 0) | ||||
|     arg_index = parse_ctx_.next_arg_id(); | ||||
|   else | ||||
|     parse_ctx_.check_arg_id(--arg_index); | ||||
|   return detail::get_arg(*this, arg_index); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename Char> | ||||
| int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it, | ||||
|                                                        const Char* end, | ||||
|                                                        format_specs& specs) { | ||||
| template <typename Char, typename GetArg> | ||||
| int parse_header(const Char*& it, const Char* end, | ||||
|                  basic_format_specs<Char>& specs, GetArg get_arg) { | ||||
|   int arg_index = -1; | ||||
|   char_type c = *it; | ||||
|   Char c = *it; | ||||
|   if (c >= '0' && c <= '9') { | ||||
|     // Parse an argument index (if followed by '$') or a width possibly | ||||
|     // preceded with '0' flag(s). | ||||
|     detail::error_handler eh; | ||||
|     int value = parse_nonnegative_int(it, end, eh); | ||||
|     int value = parse_nonnegative_int(it, end, -1); | ||||
|     if (it != end && *it == '$') {  // value is an argument index | ||||
|       ++it; | ||||
|       arg_index = value; | ||||
|       arg_index = value != -1 ? value : max_value<int>(); | ||||
|     } else { | ||||
|       if (c == '0') specs.fill[0] = '0'; | ||||
|       if (value != 0) { | ||||
|         // Nonzero value means that we parsed width and don't need to | ||||
|         // parse it or flags again, so return now. | ||||
|         if (value == -1) FMT_THROW(format_error("number is too big")); | ||||
|         specs.width = value; | ||||
|         return arg_index; | ||||
|       } | ||||
| @@ -420,30 +353,44 @@ int basic_printf_context<OutputIt, Char>::parse_header(const Char*& it, | ||||
|   // Parse width. | ||||
|   if (it != end) { | ||||
|     if (*it >= '0' && *it <= '9') { | ||||
|       detail::error_handler eh; | ||||
|       specs.width = parse_nonnegative_int(it, end, eh); | ||||
|       specs.width = parse_nonnegative_int(it, end, -1); | ||||
|       if (specs.width == -1) FMT_THROW(format_error("number is too big")); | ||||
|     } else if (*it == '*') { | ||||
|       ++it; | ||||
|       specs.width = static_cast<int>(visit_format_arg( | ||||
|           detail::printf_width_handler<char_type>(specs), get_arg())); | ||||
|           detail::printf_width_handler<Char>(specs), get_arg(-1))); | ||||
|     } | ||||
|   } | ||||
|   return arg_index; | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename Char> | ||||
| template <typename ArgFormatter> | ||||
| OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|   auto out = this->out(); | ||||
|   const Char* start = parse_ctx_.begin(); | ||||
|   const Char* end = parse_ctx_.end(); | ||||
| template <typename Char, typename Context> | ||||
| void vprintf(buffer<Char>& buf, basic_string_view<Char> format, | ||||
|              basic_format_args<Context> args) { | ||||
|   using OutputIt = buffer_appender<Char>; | ||||
|   auto out = OutputIt(buf); | ||||
|   auto context = basic_printf_context<OutputIt, Char>(out, args); | ||||
|   auto parse_ctx = basic_printf_parse_context<Char>(format); | ||||
|  | ||||
|   // Returns the argument with specified index or, if arg_index is -1, the next | ||||
|   // argument. | ||||
|   auto get_arg = [&](int arg_index) { | ||||
|     if (arg_index < 0) | ||||
|       arg_index = parse_ctx.next_arg_id(); | ||||
|     else | ||||
|       parse_ctx.check_arg_id(--arg_index); | ||||
|     return detail::get_arg(context, arg_index); | ||||
|   }; | ||||
|  | ||||
|   const Char* start = parse_ctx.begin(); | ||||
|   const Char* end = parse_ctx.end(); | ||||
|   auto it = start; | ||||
|   while (it != end) { | ||||
|     if (!detail::find<false, Char>(it, end, '%', it)) { | ||||
|       it = end;  // detail::find leaves it == nullptr if it doesn't find '%' | ||||
|       break; | ||||
|     } | ||||
|     char_type c = *it++; | ||||
|     Char c = *it++; | ||||
|     if (it != end && *it == c) { | ||||
|       out = detail::write( | ||||
|           out, basic_string_view<Char>(start, detail::to_unsigned(it - start))); | ||||
| @@ -453,30 +400,29 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|     out = detail::write(out, basic_string_view<Char>( | ||||
|                                  start, detail::to_unsigned(it - 1 - start))); | ||||
|  | ||||
|     format_specs specs; | ||||
|     basic_format_specs<Char> specs; | ||||
|     specs.align = align::right; | ||||
|  | ||||
|     // Parse argument index, flags and width. | ||||
|     int arg_index = parse_header(it, end, specs); | ||||
|     if (arg_index == 0) on_error("argument not found"); | ||||
|     int arg_index = parse_header(it, end, specs, get_arg); | ||||
|     if (arg_index == 0) parse_ctx.on_error("argument not found"); | ||||
|  | ||||
|     // Parse precision. | ||||
|     if (it != end && *it == '.') { | ||||
|       ++it; | ||||
|       c = it != end ? *it : 0; | ||||
|       if ('0' <= c && c <= '9') { | ||||
|         detail::error_handler eh; | ||||
|         specs.precision = parse_nonnegative_int(it, end, eh); | ||||
|         specs.precision = parse_nonnegative_int(it, end, 0); | ||||
|       } else if (c == '*') { | ||||
|         ++it; | ||||
|         specs.precision = static_cast<int>( | ||||
|             visit_format_arg(detail::printf_precision_handler(), get_arg())); | ||||
|             visit_format_arg(detail::printf_precision_handler(), get_arg(-1))); | ||||
|       } else { | ||||
|         specs.precision = 0; | ||||
|       } | ||||
|     } | ||||
|  | ||||
|     format_arg arg = get_arg(arg_index); | ||||
|     auto arg = get_arg(arg_index); | ||||
|     // For d, i, o, u, x, and X conversion specifiers, if a precision is | ||||
|     // specified, the '0' flag is ignored | ||||
|     if (specs.precision >= 0 && arg.is_integral()) | ||||
| @@ -486,9 +432,10 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|       auto str = visit_format_arg(detail::get_cstring<Char>(), arg); | ||||
|       auto str_end = str + specs.precision; | ||||
|       auto nul = std::find(str, str_end, Char()); | ||||
|       arg = detail::make_arg<basic_printf_context>(basic_string_view<Char>( | ||||
|           str, | ||||
|           detail::to_unsigned(nul != str_end ? nul - str : specs.precision))); | ||||
|       arg = detail::make_arg<basic_printf_context<OutputIt, Char>>( | ||||
|           basic_string_view<Char>( | ||||
|               str, detail::to_unsigned(nul != str_end ? nul - str | ||||
|                                                       : specs.precision))); | ||||
|     } | ||||
|     if (specs.alt && visit_format_arg(detail::is_zero_int(), arg)) | ||||
|       specs.alt = false; | ||||
| @@ -502,7 +449,7 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|  | ||||
|     // Parse length and convert the argument to the required type. | ||||
|     c = it != end ? *it++ : 0; | ||||
|     char_type t = it != end ? *it : 0; | ||||
|     Char t = it != end ? *it : 0; | ||||
|     using detail::convert_arg; | ||||
|     switch (c) { | ||||
|     case 'h': | ||||
| @@ -552,8 +499,9 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|         specs.type = 'd'; | ||||
|         break; | ||||
|       case 'c': | ||||
|         visit_format_arg(detail::char_converter<basic_printf_context>(arg), | ||||
|                          arg); | ||||
|         visit_format_arg( | ||||
|             detail::char_converter<basic_printf_context<OutputIt, Char>>(arg), | ||||
|             arg); | ||||
|         break; | ||||
|       } | ||||
|     } | ||||
| @@ -561,11 +509,12 @@ OutputIt basic_printf_context<OutputIt, Char>::format() { | ||||
|     start = it; | ||||
|  | ||||
|     // Format argument. | ||||
|     out = visit_format_arg(ArgFormatter(out, specs, *this), arg); | ||||
|     out = visit_format_arg( | ||||
|         detail::printf_arg_formatter<OutputIt, Char>(out, specs, context), arg); | ||||
|   } | ||||
|   return detail::write( | ||||
|       out, basic_string_view<Char>(start, detail::to_unsigned(it - start))); | ||||
|   detail::write(out, basic_string_view<Char>(start, to_unsigned(it - start))); | ||||
| } | ||||
| FMT_END_DETAIL_NAMESPACE | ||||
|  | ||||
| template <typename Char> | ||||
| using basic_printf_context_t = | ||||
| @@ -583,9 +532,9 @@ using wprintf_args = basic_format_args<wprintf_context>; | ||||
|   arguments and can be implicitly converted to `~fmt::printf_args`. | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename... Args> | ||||
| inline format_arg_store<printf_context, Args...> make_printf_args( | ||||
|     const Args&... args) { | ||||
| template <typename... T> | ||||
| inline auto make_printf_args(const T&... args) | ||||
|     -> format_arg_store<printf_context, T...> { | ||||
|   return {args...}; | ||||
| } | ||||
|  | ||||
| @@ -595,18 +544,19 @@ inline format_arg_store<printf_context, Args...> make_printf_args( | ||||
|   arguments and can be implicitly converted to `~fmt::wprintf_args`. | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename... Args> | ||||
| inline format_arg_store<wprintf_context, Args...> make_wprintf_args( | ||||
|     const Args&... args) { | ||||
| template <typename... T> | ||||
| inline auto make_wprintf_args(const T&... args) | ||||
|     -> format_arg_store<wprintf_context, T...> { | ||||
|   return {args...}; | ||||
| } | ||||
|  | ||||
| template <typename S, typename Char = char_t<S>> | ||||
| inline std::basic_string<Char> vsprintf( | ||||
|     const S& format, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) { | ||||
| inline auto vsprintf( | ||||
|     const S& fmt, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) | ||||
|     -> std::basic_string<Char> { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   vprintf(buffer, to_string_view(format), args); | ||||
|   vprintf(buffer, to_string_view(fmt), args); | ||||
|   return to_string(buffer); | ||||
| } | ||||
|  | ||||
| @@ -619,19 +569,20 @@ inline std::basic_string<Char> vsprintf( | ||||
|     std::string message = fmt::sprintf("The answer is %d", 42); | ||||
|   \endrst | ||||
| */ | ||||
| template <typename S, typename... Args, | ||||
| template <typename S, typename... T, | ||||
|           typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>> | ||||
| inline std::basic_string<Char> sprintf(const S& format, const Args&... args) { | ||||
| inline auto sprintf(const S& fmt, const T&... args) -> std::basic_string<Char> { | ||||
|   using context = basic_printf_context_t<Char>; | ||||
|   return vsprintf(to_string_view(format), make_format_args<context>(args...)); | ||||
|   return vsprintf(to_string_view(fmt), fmt::make_format_args<context>(args...)); | ||||
| } | ||||
|  | ||||
| template <typename S, typename Char = char_t<S>> | ||||
| inline int vfprintf( | ||||
|     std::FILE* f, const S& format, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) { | ||||
| inline auto vfprintf( | ||||
|     std::FILE* f, const S& fmt, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) | ||||
|     -> int { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   vprintf(buffer, to_string_view(format), args); | ||||
|   vprintf(buffer, to_string_view(fmt), args); | ||||
|   size_t size = buffer.size(); | ||||
|   return std::fwrite(buffer.data(), sizeof(Char), size, f) < size | ||||
|              ? -1 | ||||
| @@ -647,19 +598,19 @@ inline int vfprintf( | ||||
|     fmt::fprintf(stderr, "Don't %s!", "panic"); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename S, typename... Args, | ||||
|           typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>> | ||||
| inline int fprintf(std::FILE* f, const S& format, const Args&... args) { | ||||
| template <typename S, typename... T, typename Char = char_t<S>> | ||||
| inline auto fprintf(std::FILE* f, const S& fmt, const T&... args) -> int { | ||||
|   using context = basic_printf_context_t<Char>; | ||||
|   return vfprintf(f, to_string_view(format), | ||||
|                   make_format_args<context>(args...)); | ||||
|   return vfprintf(f, to_string_view(fmt), | ||||
|                   fmt::make_format_args<context>(args...)); | ||||
| } | ||||
|  | ||||
| template <typename S, typename Char = char_t<S>> | ||||
| inline int vprintf( | ||||
|     const S& format, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) { | ||||
|   return vfprintf(stdout, to_string_view(format), args); | ||||
| inline auto vprintf( | ||||
|     const S& fmt, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) | ||||
|     -> int { | ||||
|   return vfprintf(stdout, to_string_view(fmt), args); | ||||
| } | ||||
|  | ||||
| /** | ||||
| @@ -671,52 +622,31 @@ inline int vprintf( | ||||
|     fmt::printf("Elapsed time: %.2f seconds", 1.23); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename S, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_string<S>::value)> | ||||
| inline int printf(const S& format_str, const Args&... args) { | ||||
|   using context = basic_printf_context_t<char_t<S>>; | ||||
|   return vprintf(to_string_view(format_str), | ||||
|                  make_format_args<context>(args...)); | ||||
| template <typename S, typename... T, FMT_ENABLE_IF(detail::is_string<S>::value)> | ||||
| inline auto printf(const S& fmt, const T&... args) -> int { | ||||
|   return vprintf( | ||||
|       to_string_view(fmt), | ||||
|       fmt::make_format_args<basic_printf_context_t<char_t<S>>>(args...)); | ||||
| } | ||||
|  | ||||
| template <typename S, typename Char = char_t<S>> | ||||
| inline int vfprintf( | ||||
|     std::basic_ostream<Char>& os, const S& format, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) { | ||||
| FMT_DEPRECATED auto vfprintf( | ||||
|     std::basic_ostream<Char>& os, const S& fmt, | ||||
|     basic_format_args<basic_printf_context_t<type_identity_t<Char>>> args) | ||||
|     -> int { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   vprintf(buffer, to_string_view(format), args); | ||||
|   detail::write_buffer(os, buffer); | ||||
|   vprintf(buffer, to_string_view(fmt), args); | ||||
|   os.write(buffer.data(), static_cast<std::streamsize>(buffer.size())); | ||||
|   return static_cast<int>(buffer.size()); | ||||
| } | ||||
|  | ||||
| /** Formats arguments and writes the output to the range. */ | ||||
| template <typename ArgFormatter, typename Char, | ||||
|           typename Context = | ||||
|               basic_printf_context<typename ArgFormatter::iterator, Char>> | ||||
| typename ArgFormatter::iterator vprintf( | ||||
|     detail::buffer<Char>& out, basic_string_view<Char> format_str, | ||||
|     basic_format_args<type_identity_t<Context>> args) { | ||||
|   typename ArgFormatter::iterator iter(out); | ||||
|   Context(iter, format_str, args).template format<ArgFormatter>(); | ||||
|   return iter; | ||||
| template <typename S, typename... T, typename Char = char_t<S>> | ||||
| FMT_DEPRECATED auto fprintf(std::basic_ostream<Char>& os, const S& fmt, | ||||
|                             const T&... args) -> int { | ||||
|   return vfprintf(os, to_string_view(fmt), | ||||
|                   fmt::make_format_args<basic_printf_context_t<Char>>(args...)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   Prints formatted data to the stream *os*. | ||||
|  | ||||
|   **Example**:: | ||||
|  | ||||
|     fmt::fprintf(cerr, "Don't %s!", "panic"); | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename S, typename... Args, typename Char = char_t<S>> | ||||
| inline int fprintf(std::basic_ostream<Char>& os, const S& format_str, | ||||
|                    const Args&... args) { | ||||
|   using context = basic_printf_context_t<Char>; | ||||
|   return vfprintf(os, to_string_view(format_str), | ||||
|                   make_format_args<context>(args...)); | ||||
| } | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_PRINTF_H_ | ||||
|   | ||||
							
								
								
									
										122
									
								
								vendor/Fmt/include/fmt/ranges.h
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										122
									
								
								vendor/Fmt/include/fmt/ranges.h
									
									
									
									
										vendored
									
									
								
							| @@ -17,33 +17,31 @@ | ||||
|  | ||||
| #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 | ||||
| #endif | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| template <typename Char> struct formatting_base { | ||||
| template <typename Char, typename Enable = void> struct formatting_range { | ||||
| #ifdef FMT_DEPRECATED_BRACED_RANGES | ||||
|   Char prefix = '{'; | ||||
|   Char postfix = '}'; | ||||
| #else | ||||
|   Char prefix = '['; | ||||
|   Char postfix = ']'; | ||||
| #endif | ||||
|  | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename Enable = void> | ||||
| struct formatting_range : formatting_base<Char> { | ||||
|   static FMT_CONSTEXPR_DECL const size_t range_length_limit = | ||||
|       FMT_RANGE_OUTPUT_LENGTH_LIMIT;  // output only up to N items from the | ||||
|                                       // range. | ||||
|   Char prefix = '{'; | ||||
|   Char postfix = '}'; | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename Enable = void> | ||||
| struct formatting_tuple : formatting_base<Char> { | ||||
| template <typename Char, typename Enable = void> struct formatting_tuple { | ||||
|   Char prefix = '('; | ||||
|   Char postfix = ')'; | ||||
|  | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| namespace detail { | ||||
| @@ -67,8 +65,14 @@ OutputIterator copy(char ch, OutputIterator out) { | ||||
|   return out; | ||||
| } | ||||
|  | ||||
| template <typename OutputIterator> | ||||
| OutputIterator copy(wchar_t 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_std_string_like { | ||||
|   template <typename U> | ||||
|   static auto check(U* p) | ||||
|       -> decltype((void)p->find('a'), p->length(), (void)p->data(), int()); | ||||
| @@ -80,7 +84,7 @@ template <typename T> class is_like_std_string { | ||||
| }; | ||||
|  | ||||
| template <typename Char> | ||||
| struct is_like_std_string<fmt::basic_string_view<Char>> : std::true_type {}; | ||||
| struct is_std_string_like<fmt::basic_string_view<Char>> : std::true_type {}; | ||||
|  | ||||
| template <typename... Ts> struct conditional_helper {}; | ||||
|  | ||||
| @@ -249,7 +253,7 @@ template <typename OutputIt> OutputIt write_delimiter(OutputIt out) { | ||||
|  | ||||
| template < | ||||
|     typename Char, typename OutputIt, typename Arg, | ||||
|     FMT_ENABLE_IF(is_like_std_string<typename std::decay<Arg>::type>::value)> | ||||
|     FMT_ENABLE_IF(is_std_string_like<typename std::decay<Arg>::type>::value)> | ||||
| OutputIt write_range_entry(OutputIt out, const Arg& v) { | ||||
|   *out++ = '"'; | ||||
|   out = write<Char>(out, v); | ||||
| @@ -268,7 +272,7 @@ OutputIt write_range_entry(OutputIt out, const Arg v) { | ||||
|  | ||||
| template < | ||||
|     typename Char, typename OutputIt, typename Arg, | ||||
|     FMT_ENABLE_IF(!is_like_std_string<typename std::decay<Arg>::type>::value && | ||||
|     FMT_ENABLE_IF(!is_std_string_like<typename std::decay<Arg>::type>::value && | ||||
|                   !std::is_same<Arg, Char>::value)> | ||||
| OutputIt write_range_entry(OutputIt out, const Arg& v) { | ||||
|   return write<Char>(out, v); | ||||
| @@ -293,8 +297,8 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> { | ||||
|     } | ||||
|     formatting_tuple<Char>& formatting; | ||||
|     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: | ||||
| @@ -320,7 +324,7 @@ struct formatter<TupleT, Char, enable_if_t<fmt::is_tuple_like<TupleT>::value>> { | ||||
|  | ||||
| template <typename T, typename Char> struct is_range { | ||||
|   static FMT_CONSTEXPR_DECL const bool value = | ||||
|       detail::is_range_<T>::value && !detail::is_like_std_string<T>::value && | ||||
|       detail::is_range_<T>::value && !detail::is_std_string_like<T>::value && | ||||
|       !std::is_convertible<T, std::basic_string<Char>>::value && | ||||
|       !std::is_constructible<detail::std_string_view<Char>, T>::value; | ||||
| }; | ||||
| @@ -328,15 +332,14 @@ template <typename T, typename Char> struct is_range { | ||||
| template <typename T, typename Char> | ||||
| struct formatter< | ||||
|     T, Char, | ||||
|     enable_if_t<fmt::is_range<T, Char>::value | ||||
|     enable_if_t< | ||||
|         fmt::is_range<T, Char>::value | ||||
| // Workaround a bug in MSVC 2017 and earlier. | ||||
| #if !FMT_MSC_VER || FMT_MSC_VER >= 1927 | ||||
|                 && | ||||
|                 (has_formatter<detail::value_type<T>, format_context>::value || | ||||
|                  detail::has_fallback_formatter<detail::value_type<T>, | ||||
|                                                 format_context>::value) | ||||
|         && (has_formatter<detail::value_type<T>, format_context>::value || | ||||
|             detail::has_fallback_formatter<detail::value_type<T>, Char>::value) | ||||
| #endif | ||||
|                 >> { | ||||
|         >> { | ||||
|   formatting_range<Char> formatting; | ||||
|  | ||||
|   template <typename ParseContext> | ||||
| @@ -354,59 +357,58 @@ struct formatter< | ||||
|     for (; it != end; ++it) { | ||||
|       if (i > 0) out = detail::write_delimiter(out); | ||||
|       out = detail::write_range_entry<Char>(out, *it); | ||||
|       if (++i > formatting.range_length_limit) { | ||||
|         out = format_to(out, FMT_STRING("{}"), " ... <other elements>"); | ||||
|         break; | ||||
|       } | ||||
|       ++i; | ||||
|     } | ||||
|     return detail::copy(formatting.postfix, out); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename... T> struct tuple_arg_join : detail::view { | ||||
| template <typename Char, typename... T> struct tuple_join_view : detail::view { | ||||
|   const std::tuple<T...>& tuple; | ||||
|   basic_string_view<Char> sep; | ||||
|  | ||||
|   tuple_arg_join(const std::tuple<T...>& t, basic_string_view<Char> s) | ||||
|   tuple_join_view(const std::tuple<T...>& t, basic_string_view<Char> s) | ||||
|       : tuple(t), sep{s} {} | ||||
| }; | ||||
|  | ||||
| template <typename Char, typename... T> | ||||
| struct formatter<tuple_arg_join<Char, T...>, Char> { | ||||
| using tuple_arg_join = tuple_join_view<Char, T...>; | ||||
|  | ||||
| template <typename Char, typename... T> | ||||
| struct formatter<tuple_join_view<Char, T...>, Char> { | ||||
|   template <typename ParseContext> | ||||
|   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { | ||||
|     return ctx.begin(); | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   typename FormatContext::iterator format( | ||||
|       const tuple_arg_join<Char, T...>& value, FormatContext& ctx) { | ||||
|   auto format(const tuple_join_view<Char, T...>& value, FormatContext& ctx) -> | ||||
|       typename FormatContext::iterator { | ||||
|     return format(value, ctx, detail::make_index_sequence<sizeof...(T)>{}); | ||||
|   } | ||||
|  | ||||
|  private: | ||||
|   template <typename FormatContext, size_t... N> | ||||
|   typename FormatContext::iterator format( | ||||
|       const tuple_arg_join<Char, T...>& value, FormatContext& ctx, | ||||
|       detail::index_sequence<N...>) { | ||||
|   auto format(const tuple_join_view<Char, T...>& value, FormatContext& ctx, | ||||
|               detail::index_sequence<N...>) -> | ||||
|       typename FormatContext::iterator { | ||||
|     return format_args(value, ctx, std::get<N>(value.tuple)...); | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext> | ||||
|   typename FormatContext::iterator format_args( | ||||
|       const tuple_arg_join<Char, T...>&, FormatContext& ctx) { | ||||
|   auto format_args(const tuple_join_view<Char, T...>&, FormatContext& ctx) -> | ||||
|       typename FormatContext::iterator { | ||||
|     // NOTE: for compilers that support C++17, this empty function instantiation | ||||
|     // can be replaced with a constexpr branch in the variadic overload. | ||||
|     return ctx.out(); | ||||
|   } | ||||
|  | ||||
|   template <typename FormatContext, typename Arg, typename... Args> | ||||
|   typename FormatContext::iterator format_args( | ||||
|       const tuple_arg_join<Char, T...>& value, FormatContext& ctx, | ||||
|       const Arg& arg, const Args&... args) { | ||||
|   auto format_args(const tuple_join_view<Char, T...>& value, FormatContext& ctx, | ||||
|                    const Arg& arg, const Args&... args) -> | ||||
|       typename FormatContext::iterator { | ||||
|     using base = formatter<typename std::decay<Arg>::type, Char>; | ||||
|     auto out = ctx.out(); | ||||
|     out = base{}.format(arg, ctx); | ||||
|     auto out = base().format(arg, ctx); | ||||
|     if (sizeof...(Args) > 0) { | ||||
|       out = std::copy(value.sep.begin(), value.sep.end(), out); | ||||
|       ctx.advance_to(out); | ||||
| @@ -416,6 +418,8 @@ struct formatter<tuple_arg_join<Char, T...>, Char> { | ||||
|   } | ||||
| }; | ||||
|  | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| /** | ||||
|   \rst | ||||
|   Returns an object that formats `tuple` with elements separated by `sep`. | ||||
| @@ -428,14 +432,15 @@ struct formatter<tuple_arg_join<Char, T...>, Char> { | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename... T> | ||||
| FMT_CONSTEXPR tuple_arg_join<char, T...> join(const std::tuple<T...>& tuple, | ||||
|                                               string_view sep) { | ||||
| FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, string_view sep) | ||||
|     -> tuple_join_view<char, T...> { | ||||
|   return {tuple, sep}; | ||||
| } | ||||
|  | ||||
| template <typename... T> | ||||
| FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple, | ||||
|                                                  wstring_view sep) { | ||||
| FMT_CONSTEXPR auto join(const std::tuple<T...>& tuple, | ||||
|                         basic_string_view<wchar_t> sep) | ||||
|     -> tuple_join_view<wchar_t, T...> { | ||||
|   return {tuple, sep}; | ||||
| } | ||||
|  | ||||
| @@ -451,17 +456,12 @@ FMT_CONSTEXPR tuple_arg_join<wchar_t, T...> join(const std::tuple<T...>& tuple, | ||||
|   \endrst | ||||
|  */ | ||||
| template <typename T> | ||||
| arg_join<const T*, const T*, char> join(std::initializer_list<T> list, | ||||
|                                         string_view sep) { | ||||
|   return join(std::begin(list), std::end(list), sep); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| arg_join<const T*, const T*, wchar_t> join(std::initializer_list<T> list, | ||||
|                                            wstring_view sep) { | ||||
| auto join(std::initializer_list<T> list, string_view sep) | ||||
|     -> join_view<const T*, const T*> { | ||||
|   return join(std::begin(list), std::end(list), sep); | ||||
| } | ||||
|  | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_RANGES_H_ | ||||
|   | ||||
							
								
								
									
										236
									
								
								vendor/Fmt/include/fmt/xchar.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										236
									
								
								vendor/Fmt/include/fmt/xchar.h
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,236 @@ | ||||
| // Formatting library for C++ - optional wchar_t and exotic character support | ||||
| // | ||||
| // Copyright (c) 2012 - present, Victor Zverovich | ||||
| // All rights reserved. | ||||
| // | ||||
| // For the license information refer to format.h. | ||||
|  | ||||
| #ifndef FMT_WCHAR_H_ | ||||
| #define FMT_WCHAR_H_ | ||||
|  | ||||
| #include <cwchar> | ||||
| #include <tuple> | ||||
|  | ||||
| #include "format.h" | ||||
|  | ||||
| FMT_BEGIN_NAMESPACE | ||||
| namespace detail { | ||||
| template <typename T> | ||||
| using is_exotic_char = bool_constant<!std::is_same<T, char>::value>; | ||||
| } | ||||
|  | ||||
| FMT_MODULE_EXPORT_BEGIN | ||||
|  | ||||
| using wstring_view = basic_string_view<wchar_t>; | ||||
| using wformat_parse_context = basic_format_parse_context<wchar_t>; | ||||
| using wformat_context = buffer_context<wchar_t>; | ||||
| using wformat_args = basic_format_args<wformat_context>; | ||||
| using wmemory_buffer = basic_memory_buffer<wchar_t>; | ||||
|  | ||||
| #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409 | ||||
| // Workaround broken conversion on older gcc. | ||||
| template <typename... Args> using wformat_string = wstring_view; | ||||
| #else | ||||
| template <typename... Args> | ||||
| using wformat_string = basic_format_string<wchar_t, type_identity_t<Args>...>; | ||||
| #endif | ||||
|  | ||||
| template <> struct is_char<wchar_t> : std::true_type {}; | ||||
| template <> struct is_char<detail::char8_type> : std::true_type {}; | ||||
| template <> struct is_char<char16_t> : std::true_type {}; | ||||
| template <> struct is_char<char32_t> : std::true_type {}; | ||||
|  | ||||
| template <typename... Args> | ||||
| constexpr format_arg_store<wformat_context, Args...> make_wformat_args( | ||||
|     const Args&... args) { | ||||
|   return {args...}; | ||||
| } | ||||
|  | ||||
| inline namespace literals { | ||||
| constexpr auto operator"" _format(const wchar_t* s, size_t n) | ||||
|     -> detail::udl_formatter<wchar_t> { | ||||
|   return {{s, n}}; | ||||
| } | ||||
|  | ||||
| #if FMT_USE_USER_DEFINED_LITERALS && !FMT_USE_NONTYPE_TEMPLATE_PARAMETERS | ||||
| constexpr detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) { | ||||
|   return {s}; | ||||
| } | ||||
| #endif | ||||
| }  // namespace literals | ||||
|  | ||||
| template <typename It, typename Sentinel> | ||||
| auto join(It begin, Sentinel end, wstring_view sep) | ||||
|     -> join_view<It, Sentinel, wchar_t> { | ||||
|   return {begin, end, sep}; | ||||
| } | ||||
|  | ||||
| template <typename Range> | ||||
| auto join(Range&& range, wstring_view sep) | ||||
|     -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>, | ||||
|                  wchar_t> { | ||||
|   return join(std::begin(range), std::end(range), sep); | ||||
| } | ||||
|  | ||||
| template <typename T> | ||||
| auto join(std::initializer_list<T> list, wstring_view sep) | ||||
|     -> join_view<const T*, const T*, wchar_t> { | ||||
|   return join(std::begin(list), std::end(list), sep); | ||||
| } | ||||
|  | ||||
| template <typename Char, FMT_ENABLE_IF(!std::is_same<Char, char>::value)> | ||||
| auto vformat(basic_string_view<Char> format_str, | ||||
|              basic_format_args<buffer_context<type_identity_t<Char>>> args) | ||||
|     -> std::basic_string<Char> { | ||||
|   basic_memory_buffer<Char> buffer; | ||||
|   detail::vformat_to(buffer, format_str, args); | ||||
|   return to_string(buffer); | ||||
| } | ||||
|  | ||||
| // Pass char_t as a default template parameter instead of using | ||||
| // std::basic_string<char_t<S>> to reduce the symbol size. | ||||
| template <typename S, typename... Args, typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(!std::is_same<Char, char>::value)> | ||||
| auto format(const S& format_str, Args&&... args) -> std::basic_string<Char> { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   return vformat(to_string_view(format_str), vargs); | ||||
| } | ||||
|  | ||||
| template <typename Locale, typename S, typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_locale<Locale>::value&& | ||||
|                             detail::is_exotic_char<Char>::value)> | ||||
| inline auto vformat( | ||||
|     const Locale& loc, const S& format_str, | ||||
|     basic_format_args<buffer_context<type_identity_t<Char>>> args) | ||||
|     -> std::basic_string<Char> { | ||||
|   return detail::vformat(loc, to_string_view(format_str), args); | ||||
| } | ||||
|  | ||||
| template <typename Locale, typename S, typename... Args, | ||||
|           typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_locale<Locale>::value&& | ||||
|                             detail::is_exotic_char<Char>::value)> | ||||
| inline auto format(const Locale& loc, const S& format_str, Args&&... args) | ||||
|     -> std::basic_string<Char> { | ||||
|   return detail::vformat(loc, to_string_view(format_str), | ||||
|                          fmt::make_args_checked<Args...>(format_str, args...)); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& | ||||
|                             detail::is_exotic_char<Char>::value)> | ||||
| auto vformat_to(OutputIt out, const S& format_str, | ||||
|                 basic_format_args<buffer_context<type_identity_t<Char>>> args) | ||||
|     -> OutputIt { | ||||
|   auto&& buf = detail::get_buffer<Char>(out); | ||||
|   detail::vformat_to(buf, to_string_view(format_str), args); | ||||
|   return detail::get_iterator(buf); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& | ||||
|                             detail::is_exotic_char<Char>::value)> | ||||
| inline auto format_to(OutputIt out, const S& fmt, Args&&... args) -> OutputIt { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...); | ||||
|   return vformat_to(out, to_string_view(fmt), vargs); | ||||
| } | ||||
|  | ||||
| template <typename S, typename... Args, typename Char, size_t SIZE, | ||||
|           typename Allocator, FMT_ENABLE_IF(detail::is_string<S>::value)> | ||||
| FMT_DEPRECATED auto format_to(basic_memory_buffer<Char, SIZE, Allocator>& buf, | ||||
|                               const S& format_str, Args&&... args) -> | ||||
|     typename buffer_context<Char>::iterator { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   detail::vformat_to(buf, to_string_view(format_str), vargs); | ||||
|   return detail::buffer_appender<Char>(buf); | ||||
| } | ||||
|  | ||||
| template <typename Locale, typename S, typename OutputIt, typename... Args, | ||||
|           typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& | ||||
|                             detail::is_locale<Locale>::value&& | ||||
|                                 detail::is_exotic_char<Char>::value)> | ||||
| inline auto vformat_to( | ||||
|     OutputIt out, const Locale& loc, const S& format_str, | ||||
|     basic_format_args<buffer_context<type_identity_t<Char>>> args) -> OutputIt { | ||||
|   auto&& buf = detail::get_buffer<Char>(out); | ||||
|   vformat_to(buf, to_string_view(format_str), args, detail::locale_ref(loc)); | ||||
|   return detail::get_iterator(buf); | ||||
| } | ||||
|  | ||||
| template < | ||||
|     typename OutputIt, typename Locale, typename S, typename... Args, | ||||
|     typename Char = char_t<S>, | ||||
|     bool enable = detail::is_output_iterator<OutputIt, Char>::value&& | ||||
|         detail::is_locale<Locale>::value&& detail::is_exotic_char<Char>::value> | ||||
| inline auto format_to(OutputIt out, const Locale& loc, const S& format_str, | ||||
|                       Args&&... args) -> | ||||
|     typename std::enable_if<enable, OutputIt>::type { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...); | ||||
|   return vformat_to(out, loc, to_string_view(format_str), vargs); | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename Char, typename... Args, | ||||
|           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& | ||||
|                             detail::is_exotic_char<Char>::value)> | ||||
| inline auto vformat_to_n( | ||||
|     OutputIt out, size_t n, basic_string_view<Char> format_str, | ||||
|     basic_format_args<buffer_context<type_identity_t<Char>>> args) | ||||
|     -> format_to_n_result<OutputIt> { | ||||
|   detail::iterator_buffer<OutputIt, Char, detail::fixed_buffer_traits> buf(out, | ||||
|                                                                            n); | ||||
|   detail::vformat_to(buf, format_str, args); | ||||
|   return {buf.out(), buf.count()}; | ||||
| } | ||||
|  | ||||
| template <typename OutputIt, typename S, typename... Args, | ||||
|           typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, Char>::value&& | ||||
|                             detail::is_exotic_char<Char>::value)> | ||||
| inline auto format_to_n(OutputIt out, size_t n, const S& fmt, | ||||
|                         const Args&... args) -> format_to_n_result<OutputIt> { | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...); | ||||
|   return vformat_to_n(out, n, to_string_view(fmt), vargs); | ||||
| } | ||||
|  | ||||
| template <typename S, typename... Args, typename Char = char_t<S>, | ||||
|           FMT_ENABLE_IF(detail::is_exotic_char<Char>::value)> | ||||
| inline auto formatted_size(const S& fmt, Args&&... args) -> size_t { | ||||
|   detail::counting_buffer<Char> buf; | ||||
|   const auto& vargs = fmt::make_args_checked<Args...>(fmt, args...); | ||||
|   detail::vformat_to(buf, to_string_view(fmt), vargs); | ||||
|   return buf.count(); | ||||
| } | ||||
|  | ||||
| inline void vprint(std::FILE* f, wstring_view fmt, wformat_args args) { | ||||
|   wmemory_buffer buffer; | ||||
|   detail::vformat_to(buffer, fmt, args); | ||||
|   buffer.push_back(L'\0'); | ||||
|   if (std::fputws(buffer.data(), f) == -1) | ||||
|     FMT_THROW(system_error(errno, FMT_STRING("cannot write to file"))); | ||||
| } | ||||
|  | ||||
| inline void vprint(wstring_view fmt, wformat_args args) { | ||||
|   vprint(stdout, fmt, args); | ||||
| } | ||||
|  | ||||
| template <typename... T> | ||||
| void print(std::FILE* f, wformat_string<T...> fmt, T&&... args) { | ||||
|   return vprint(f, wstring_view(fmt), make_wformat_args(args...)); | ||||
| } | ||||
|  | ||||
| template <typename... T> void print(wformat_string<T...> fmt, T&&... args) { | ||||
|   return vprint(wstring_view(fmt), make_wformat_args(args...)); | ||||
| } | ||||
|  | ||||
| /** | ||||
|   Converts *value* to ``std::wstring`` using the default format for type *T*. | ||||
|  */ | ||||
| template <typename T> inline auto to_wstring(const T& value) -> std::wstring { | ||||
|   return format(FMT_STRING(L"{}"), value); | ||||
| } | ||||
| FMT_MODULE_EXPORT_END | ||||
| FMT_END_NAMESPACE | ||||
|  | ||||
| #endif  // FMT_WCHAR_H_ | ||||
							
								
								
									
										114
									
								
								vendor/Fmt/os.cc
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										114
									
								
								vendor/Fmt/os.cc
									
									
									
									
										vendored
									
									
								
							| @@ -25,7 +25,6 @@ | ||||
| #      define WIN32_LEAN_AND_MEAN | ||||
| #    endif | ||||
| #    include <io.h> | ||||
| #    include <windows.h> | ||||
|  | ||||
| #    define O_CREAT _O_CREAT | ||||
| #    define O_TRUNC _O_TRUNC | ||||
| @@ -55,7 +54,7 @@ | ||||
| namespace { | ||||
| #ifdef _WIN32 | ||||
| // Return type of read and write functions. | ||||
| using RWResult = int; | ||||
| using rwresult = int; | ||||
|  | ||||
| // On Windows the count argument to read and write is unsigned, so convert | ||||
| // it from size_t preventing integer overflow. | ||||
| @@ -64,7 +63,7 @@ inline unsigned convert_rwcount(std::size_t count) { | ||||
| } | ||||
| #elif FMT_USE_FCNTL | ||||
| // Return type of read and write functions. | ||||
| using RWResult = ssize_t; | ||||
| using rwresult = ssize_t; | ||||
|  | ||||
| inline std::size_t convert_rwcount(std::size_t count) { return count; } | ||||
| #endif | ||||
| @@ -73,14 +72,14 @@ inline std::size_t convert_rwcount(std::size_t count) { return count; } | ||||
| FMT_BEGIN_NAMESPACE | ||||
|  | ||||
| #ifdef _WIN32 | ||||
| detail::utf16_to_utf8::utf16_to_utf8(wstring_view s) { | ||||
| detail::utf16_to_utf8::utf16_to_utf8(basic_string_view<wchar_t> s) { | ||||
|   if (int error_code = convert(s)) { | ||||
|     FMT_THROW(windows_error(error_code, | ||||
|                             "cannot convert string from UTF-16 to UTF-8")); | ||||
|   } | ||||
| } | ||||
|  | ||||
| int detail::utf16_to_utf8::convert(wstring_view s) { | ||||
| int detail::utf16_to_utf8::convert(basic_string_view<wchar_t> s) { | ||||
|   if (s.size() > INT_MAX) return ERROR_INVALID_PARAMETER; | ||||
|   int s_size = static_cast<int>(s.size()); | ||||
|   if (s_size == 0) { | ||||
| @@ -101,46 +100,85 @@ int detail::utf16_to_utf8::convert(wstring_view s) { | ||||
|   return 0; | ||||
| } | ||||
|  | ||||
| void windows_error::init(int err_code, string_view format_str, | ||||
|                          format_args args) { | ||||
|   error_code_ = err_code; | ||||
|   memory_buffer buffer; | ||||
|   detail::format_windows_error(buffer, err_code, vformat(format_str, args)); | ||||
|   std::runtime_error& base = *this; | ||||
|   base = std::runtime_error(to_string(buffer)); | ||||
| namespace detail { | ||||
|  | ||||
| class system_message { | ||||
|   system_message(const system_message&) = delete; | ||||
|   void operator=(const system_message&) = delete; | ||||
|  | ||||
|   unsigned long result_; | ||||
|   wchar_t* message_; | ||||
|  | ||||
|   static bool is_whitespace(wchar_t c) FMT_NOEXCEPT { | ||||
|     return c == L' ' || c == L'\n' || c == L'\r' || c == L'\t' || c == L'\0'; | ||||
|   } | ||||
|  | ||||
|  public: | ||||
|   explicit system_message(unsigned long error_code) | ||||
|       : result_(0), message_(nullptr) { | ||||
|     result_ = FormatMessageW( | ||||
|         FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | | ||||
|             FORMAT_MESSAGE_IGNORE_INSERTS, | ||||
|         nullptr, error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||||
|         reinterpret_cast<wchar_t*>(&message_), 0, nullptr); | ||||
|     if (result_ != 0) { | ||||
|       while (result_ != 0 && is_whitespace(message_[result_ - 1])) { | ||||
|         --result_; | ||||
|       } | ||||
|     } | ||||
|   } | ||||
|   ~system_message() { LocalFree(message_); } | ||||
|   explicit operator bool() const FMT_NOEXCEPT { return result_ != 0; } | ||||
|   operator basic_string_view<wchar_t>() const FMT_NOEXCEPT { | ||||
|     return basic_string_view<wchar_t>(message_, result_); | ||||
|   } | ||||
| }; | ||||
|  | ||||
| class utf8_system_category final : public std::error_category { | ||||
|  public: | ||||
|   const char* name() const FMT_NOEXCEPT override { return "system"; } | ||||
|   std::string message(int error_code) const override { | ||||
|     system_message msg(error_code); | ||||
|     if (msg) { | ||||
|       utf16_to_utf8 utf8_message; | ||||
|       if (utf8_message.convert(msg) == ERROR_SUCCESS) { | ||||
|         return utf8_message.str(); | ||||
|       } | ||||
|     } | ||||
|     return "unknown error"; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| }  // namespace detail | ||||
|  | ||||
| FMT_API const std::error_category& system_category() FMT_NOEXCEPT { | ||||
|   static const detail::utf8_system_category category; | ||||
|   return category; | ||||
| } | ||||
|  | ||||
| std::system_error vwindows_error(int err_code, string_view format_str, | ||||
|                                  format_args args) { | ||||
|   auto ec = std::error_code(err_code, system_category()); | ||||
|   return std::system_error(ec, vformat(format_str, args)); | ||||
| } | ||||
|  | ||||
| void detail::format_windows_error(detail::buffer<char>& out, int error_code, | ||||
|                                   string_view message) FMT_NOEXCEPT { | ||||
|                                   const char* message) FMT_NOEXCEPT { | ||||
|   FMT_TRY { | ||||
|     wmemory_buffer buf; | ||||
|     buf.resize(inline_buffer_size); | ||||
|     for (;;) { | ||||
|       wchar_t* system_message = &buf[0]; | ||||
|       int result = FormatMessageW( | ||||
|           FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, nullptr, | ||||
|           error_code, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), system_message, | ||||
|           static_cast<uint32_t>(buf.size()), nullptr); | ||||
|       if (result != 0) { | ||||
|         utf16_to_utf8 utf8_message; | ||||
|         if (utf8_message.convert(system_message) == ERROR_SUCCESS) { | ||||
|           format_to(buffer_appender<char>(out), "{}: {}", message, | ||||
|                     utf8_message); | ||||
|           return; | ||||
|         } | ||||
|         break; | ||||
|     system_message msg(error_code); | ||||
|     if (msg) { | ||||
|       utf16_to_utf8 utf8_message; | ||||
|       if (utf8_message.convert(msg) == ERROR_SUCCESS) { | ||||
|         format_to(buffer_appender<char>(out), "{}: {}", message, utf8_message); | ||||
|         return; | ||||
|       } | ||||
|       if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) | ||||
|         break;  // Can't get error message, report error code instead. | ||||
|       buf.resize(buf.size() * 2); | ||||
|     } | ||||
|   } | ||||
|   FMT_CATCH(...) {} | ||||
|   format_error_code(out, error_code, message); | ||||
| } | ||||
|  | ||||
| void report_windows_error(int error_code, | ||||
|                           fmt::string_view message) FMT_NOEXCEPT { | ||||
| void report_windows_error(int error_code, const char* message) FMT_NOEXCEPT { | ||||
|   report_error(detail::format_windows_error, error_code, message); | ||||
| } | ||||
| #endif  // _WIN32 | ||||
| @@ -229,14 +267,14 @@ long long file::size() const { | ||||
| } | ||||
|  | ||||
| std::size_t file::read(void* buffer, std::size_t count) { | ||||
|   RWResult result = 0; | ||||
|   rwresult result = 0; | ||||
|   FMT_RETRY(result, FMT_POSIX_CALL(read(fd_, buffer, convert_rwcount(count)))); | ||||
|   if (result < 0) FMT_THROW(system_error(errno, "cannot read from file")); | ||||
|   return detail::to_unsigned(result); | ||||
| } | ||||
|  | ||||
| std::size_t file::write(const void* buffer, std::size_t count) { | ||||
|   RWResult result = 0; | ||||
|   rwresult result = 0; | ||||
|   FMT_RETRY(result, FMT_POSIX_CALL(write(fd_, buffer, convert_rwcount(count)))); | ||||
|   if (result < 0) FMT_THROW(system_error(errno, "cannot write to file")); | ||||
|   return detail::to_unsigned(result); | ||||
| @@ -260,10 +298,10 @@ void file::dup2(int fd) { | ||||
|   } | ||||
| } | ||||
|  | ||||
| void file::dup2(int fd, error_code& ec) FMT_NOEXCEPT { | ||||
| void file::dup2(int fd, std::error_code& ec) FMT_NOEXCEPT { | ||||
|   int result = 0; | ||||
|   FMT_RETRY(result, FMT_POSIX_CALL(dup2(fd_, fd))); | ||||
|   if (result == -1) ec = error_code(errno); | ||||
|   if (result == -1) ec = std::error_code(errno, std::generic_category()); | ||||
| } | ||||
|  | ||||
| void file::pipe(file& read_end, file& write_end) { | ||||
|   | ||||
		Reference in New Issue
	
	Block a user