]> gitweb.factorcode.org Git - factor.git/blob - vm/fmt/core.h
compiler.tests.codegen: make a note about platform differences
[factor.git] / vm / fmt / core.h
1 // Formatting library for C++ - the core API for char/UTF-8
2 //
3 // Copyright (c) 2012 - present, Victor Zverovich
4 // All rights reserved.
5 //
6 // For the license information refer to format.h.
7
8 #ifndef FMT_CORE_H_
9 #define FMT_CORE_H_
10
11 #include <cstddef>  // std::byte
12 #include <cstdio>   // std::FILE
13 #include <cstring>  // std::strlen
14 #include <iterator>
15 #include <limits>
16 #include <memory>  // std::addressof
17 #include <string>
18 #include <type_traits>
19
20 // The fmt library version in the form major * 10000 + minor * 100 + patch.
21 #define FMT_VERSION 100201
22
23 #if defined(__clang__) && !defined(__ibmxl__)
24 #  define FMT_CLANG_VERSION (__clang_major__ * 100 + __clang_minor__)
25 #else
26 #  define FMT_CLANG_VERSION 0
27 #endif
28
29 #if defined(__GNUC__) && !defined(__clang__) && !defined(__INTEL_COMPILER) && \
30     !defined(__NVCOMPILER)
31 #  define FMT_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
32 #else
33 #  define FMT_GCC_VERSION 0
34 #endif
35
36 #ifndef FMT_GCC_PRAGMA
37 // Workaround _Pragma bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59884.
38 #  if FMT_GCC_VERSION >= 504
39 #    define FMT_GCC_PRAGMA(arg) _Pragma(arg)
40 #  else
41 #    define FMT_GCC_PRAGMA(arg)
42 #  endif
43 #endif
44
45 #ifdef __ICL
46 #  define FMT_ICC_VERSION __ICL
47 #elif defined(__INTEL_COMPILER)
48 #  define FMT_ICC_VERSION __INTEL_COMPILER
49 #else
50 #  define FMT_ICC_VERSION 0
51 #endif
52
53 #ifdef _MSC_VER
54 #  define FMT_MSC_VERSION _MSC_VER
55 #  define FMT_MSC_WARNING(...) __pragma(warning(__VA_ARGS__))
56 #else
57 #  define FMT_MSC_VERSION 0
58 #  define FMT_MSC_WARNING(...)
59 #endif
60
61 #ifdef _MSVC_LANG
62 #  define FMT_CPLUSPLUS _MSVC_LANG
63 #else
64 #  define FMT_CPLUSPLUS __cplusplus
65 #endif
66
67 #ifdef __has_feature
68 #  define FMT_HAS_FEATURE(x) __has_feature(x)
69 #else
70 #  define FMT_HAS_FEATURE(x) 0
71 #endif
72
73 #if defined(__has_include) || FMT_ICC_VERSION >= 1600 || FMT_MSC_VERSION > 1900
74 #  define FMT_HAS_INCLUDE(x) __has_include(x)
75 #else
76 #  define FMT_HAS_INCLUDE(x) 0
77 #endif
78
79 #ifdef __has_cpp_attribute
80 #  define FMT_HAS_CPP_ATTRIBUTE(x) __has_cpp_attribute(x)
81 #else
82 #  define FMT_HAS_CPP_ATTRIBUTE(x) 0
83 #endif
84
85 #define FMT_HAS_CPP14_ATTRIBUTE(attribute) \
86   (FMT_CPLUSPLUS >= 201402L && FMT_HAS_CPP_ATTRIBUTE(attribute))
87
88 #define FMT_HAS_CPP17_ATTRIBUTE(attribute) \
89   (FMT_CPLUSPLUS >= 201703L && FMT_HAS_CPP_ATTRIBUTE(attribute))
90
91 // Check if relaxed C++14 constexpr is supported.
92 // GCC doesn't allow throw in constexpr until version 6 (bug 67371).
93 #ifndef FMT_USE_CONSTEXPR
94 #  if (FMT_HAS_FEATURE(cxx_relaxed_constexpr) || FMT_MSC_VERSION >= 1912 || \
95        (FMT_GCC_VERSION >= 600 && FMT_CPLUSPLUS >= 201402L)) &&             \
96       !FMT_ICC_VERSION && (!defined(__NVCC__) || FMT_CPLUSPLUS >= 202002L)
97 #    define FMT_USE_CONSTEXPR 1
98 #  else
99 #    define FMT_USE_CONSTEXPR 0
100 #  endif
101 #endif
102 #if FMT_USE_CONSTEXPR
103 #  define FMT_CONSTEXPR constexpr
104 #else
105 #  define FMT_CONSTEXPR
106 #endif
107
108 #if (FMT_CPLUSPLUS >= 202002L ||                                \
109      (FMT_CPLUSPLUS >= 201709L && FMT_GCC_VERSION >= 1002)) &&  \
110     ((!defined(_GLIBCXX_RELEASE) || _GLIBCXX_RELEASE >= 10) &&  \
111      (!defined(_LIBCPP_VERSION) || _LIBCPP_VERSION >= 10000) && \
112      (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1928)) &&          \
113     defined(__cpp_lib_is_constant_evaluated)
114 #  define FMT_CONSTEXPR20 constexpr
115 #else
116 #  define FMT_CONSTEXPR20
117 #endif
118
119 // Check if constexpr std::char_traits<>::{compare,length} are supported.
120 #if defined(__GLIBCXX__)
121 #  if FMT_CPLUSPLUS >= 201703L && defined(_GLIBCXX_RELEASE) && \
122       _GLIBCXX_RELEASE >= 7  // GCC 7+ libstdc++ has _GLIBCXX_RELEASE.
123 #    define FMT_CONSTEXPR_CHAR_TRAITS constexpr
124 #  endif
125 #elif defined(_LIBCPP_VERSION) && FMT_CPLUSPLUS >= 201703L && \
126     _LIBCPP_VERSION >= 4000
127 #  define FMT_CONSTEXPR_CHAR_TRAITS constexpr
128 #elif FMT_MSC_VERSION >= 1914 && FMT_CPLUSPLUS >= 201703L
129 #  define FMT_CONSTEXPR_CHAR_TRAITS constexpr
130 #endif
131 #ifndef FMT_CONSTEXPR_CHAR_TRAITS
132 #  define FMT_CONSTEXPR_CHAR_TRAITS
133 #endif
134
135 // Check if exceptions are disabled.
136 #ifndef FMT_EXCEPTIONS
137 #  if (defined(__GNUC__) && !defined(__EXCEPTIONS)) || \
138       (FMT_MSC_VERSION && !_HAS_EXCEPTIONS)
139 #    define FMT_EXCEPTIONS 0
140 #  else
141 #    define FMT_EXCEPTIONS 1
142 #  endif
143 #endif
144
145 // Disable [[noreturn]] on MSVC/NVCC because of bogus unreachable code warnings.
146 #if FMT_EXCEPTIONS && FMT_HAS_CPP_ATTRIBUTE(noreturn) && !FMT_MSC_VERSION && \
147     !defined(__NVCC__)
148 #  define FMT_NORETURN [[noreturn]]
149 #else
150 #  define FMT_NORETURN
151 #endif
152
153 #ifndef FMT_NODISCARD
154 #  if FMT_HAS_CPP17_ATTRIBUTE(nodiscard)
155 #    define FMT_NODISCARD [[nodiscard]]
156 #  else
157 #    define FMT_NODISCARD
158 #  endif
159 #endif
160
161 #ifndef FMT_INLINE
162 #  if FMT_GCC_VERSION || FMT_CLANG_VERSION
163 #    define FMT_INLINE inline __attribute__((always_inline))
164 #  else
165 #    define FMT_INLINE inline
166 #  endif
167 #endif
168
169 #ifdef _MSC_VER
170 #  define FMT_UNCHECKED_ITERATOR(It) \
171     using _Unchecked_type = It  // Mark iterator as checked.
172 #else
173 #  define FMT_UNCHECKED_ITERATOR(It) using unchecked_type = It
174 #endif
175
176 #ifndef FMT_BEGIN_NAMESPACE
177 #  define FMT_BEGIN_NAMESPACE \
178     namespace fmt {           \
179     inline namespace v10 {
180 #  define FMT_END_NAMESPACE \
181     }                       \
182     }
183 #endif
184
185 #ifndef FMT_EXPORT
186 #  define FMT_EXPORT
187 #  define FMT_BEGIN_EXPORT
188 #  define FMT_END_EXPORT
189 #endif
190
191 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
192 #  define FMT_VISIBILITY(value) __attribute__((visibility(value)))
193 #else
194 #  define FMT_VISIBILITY(value)
195 #endif
196
197 #if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
198 #  if defined(FMT_LIB_EXPORT)
199 #    define FMT_API __declspec(dllexport)
200 #  elif defined(FMT_SHARED)
201 #    define FMT_API __declspec(dllimport)
202 #  endif
203 #elif defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
204 #  define FMT_API FMT_VISIBILITY("default")
205 #endif
206 #ifndef FMT_API
207 #  define FMT_API
208 #endif
209
210 // libc++ supports string_view in pre-c++17.
211 #if FMT_HAS_INCLUDE(<string_view>) && \
212     (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
213 #  include <string_view>
214 #  define FMT_USE_STRING_VIEW
215 #elif FMT_HAS_INCLUDE("experimental/string_view") && FMT_CPLUSPLUS >= 201402L
216 #  include <experimental/string_view>
217 #  define FMT_USE_EXPERIMENTAL_STRING_VIEW
218 #endif
219
220 #ifndef FMT_UNICODE
221 #  define FMT_UNICODE !FMT_MSC_VERSION
222 #endif
223
224 #ifndef FMT_CONSTEVAL
225 #  if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \
226        (!defined(__apple_build_version__) ||                     \
227         __apple_build_version__ >= 14000029L) &&                 \
228        FMT_CPLUSPLUS >= 202002L) ||                              \
229       (defined(__cpp_consteval) &&                               \
230        (!FMT_MSC_VERSION || FMT_MSC_VERSION >= 1929))
231 // consteval is broken in MSVC before VS2019 version 16.10 and Apple clang
232 // before 14.
233 #    define FMT_CONSTEVAL consteval
234 #    define FMT_HAS_CONSTEVAL
235 #  else
236 #    define FMT_CONSTEVAL
237 #  endif
238 #endif
239
240 #ifndef FMT_USE_NONTYPE_TEMPLATE_ARGS
241 #  if defined(__cpp_nontype_template_args) &&                  \
242       ((FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L) || \
243        __cpp_nontype_template_args >= 201911L) &&              \
244       !defined(__NVCOMPILER) && !defined(__LCC__)
245 #    define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
246 #  else
247 #    define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
248 #  endif
249 #endif
250
251 // GCC < 5 requires this-> in decltype
252 #ifndef FMT_DECLTYPE_THIS
253 #  if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
254 #    define FMT_DECLTYPE_THIS this->
255 #  else
256 #    define FMT_DECLTYPE_THIS
257 #  endif
258 #endif
259
260 // Enable minimal optimizations for more compact code in debug mode.
261 FMT_GCC_PRAGMA("GCC push_options")
262 #if !defined(__OPTIMIZE__) && !defined(__NVCOMPILER) && !defined(__LCC__) && \
263     !defined(__CUDACC__)
264 FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
265 #endif
266
267 FMT_BEGIN_NAMESPACE
268
269 // Implementations of enable_if_t and other metafunctions for older systems.
270 template <bool B, typename T = void>
271 using enable_if_t = typename std::enable_if<B, T>::type;
272 template <bool B, typename T, typename F>
273 using conditional_t = typename std::conditional<B, T, F>::type;
274 template <bool B> using bool_constant = std::integral_constant<bool, B>;
275 template <typename T>
276 using remove_reference_t = typename std::remove_reference<T>::type;
277 template <typename T>
278 using remove_const_t = typename std::remove_const<T>::type;
279 template <typename T>
280 using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
281 template <typename T> struct type_identity {
282   using type = T;
283 };
284 template <typename T> using type_identity_t = typename type_identity<T>::type;
285 template <typename T>
286 using underlying_t = typename std::underlying_type<T>::type;
287
288 // Checks whether T is a container with contiguous storage.
289 template <typename T> struct is_contiguous : std::false_type {};
290 template <typename Char>
291 struct is_contiguous<std::basic_string<Char>> : std::true_type {};
292
293 struct monostate {
294   constexpr monostate() {}
295 };
296
297 // An enable_if helper to be used in template parameters which results in much
298 // shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
299 // to workaround a bug in MSVC 2019 (see #1140 and #1186).
300 #ifdef FMT_DOC
301 #  define FMT_ENABLE_IF(...)
302 #else
303 #  define FMT_ENABLE_IF(...) fmt::enable_if_t<(__VA_ARGS__), int> = 0
304 #endif
305
306 // This is defined in core.h instead of format.h to avoid injecting in std.
307 // It is a template to avoid undesirable implicit conversions to std::byte.
308 #ifdef __cpp_lib_byte
309 template <typename T, FMT_ENABLE_IF(std::is_same<T, std::byte>::value)>
310 inline auto format_as(T b) -> unsigned char {
311   return static_cast<unsigned char>(b);
312 }
313 #endif
314
315 namespace detail {
316 // Suppresses "unused variable" warnings with the method described in
317 // https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
318 // (void)var does not work on many Intel compilers.
319 template <typename... T> FMT_CONSTEXPR void ignore_unused(const T&...) {}
320
321 constexpr FMT_INLINE auto is_constant_evaluated(
322     bool default_value = false) noexcept -> bool {
323 // Workaround for incompatibility between libstdc++ consteval-based
324 // std::is_constant_evaluated() implementation and clang-14.
325 // https://github.com/fmtlib/fmt/issues/3247
326 #if FMT_CPLUSPLUS >= 202002L && defined(_GLIBCXX_RELEASE) && \
327     _GLIBCXX_RELEASE >= 12 &&                                \
328     (FMT_CLANG_VERSION >= 1400 && FMT_CLANG_VERSION < 1500)
329   ignore_unused(default_value);
330   return __builtin_is_constant_evaluated();
331 #elif defined(__cpp_lib_is_constant_evaluated)
332   ignore_unused(default_value);
333   return std::is_constant_evaluated();
334 #else
335   return default_value;
336 #endif
337 }
338
339 // Suppresses "conditional expression is constant" warnings.
340 template <typename T> constexpr FMT_INLINE auto const_check(T value) -> T {
341   return value;
342 }
343
344 FMT_NORETURN FMT_API void assert_fail(const char* file, int line,
345                                       const char* message);
346
347 #ifndef FMT_ASSERT
348 #  ifdef NDEBUG
349 // FMT_ASSERT is not empty to avoid -Wempty-body.
350 #    define FMT_ASSERT(condition, message) \
351       fmt::detail::ignore_unused((condition), (message))
352 #  else
353 #    define FMT_ASSERT(condition, message)                                    \
354       ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
355            ? (void)0                                                          \
356            : fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
357 #  endif
358 #endif
359
360 #if defined(FMT_USE_STRING_VIEW)
361 template <typename Char> using std_string_view = std::basic_string_view<Char>;
362 #elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
363 template <typename Char>
364 using std_string_view = std::experimental::basic_string_view<Char>;
365 #else
366 template <typename T> struct std_string_view {};
367 #endif
368
369 #ifdef FMT_USE_INT128
370 // Do nothing.
371 #elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \
372     !(FMT_CLANG_VERSION && FMT_MSC_VERSION)
373 #  define FMT_USE_INT128 1
374 using int128_opt = __int128_t;  // An optional native 128-bit integer.
375 using uint128_opt = __uint128_t;
376 template <typename T> inline auto convert_for_visit(T value) -> T {
377   return value;
378 }
379 #else
380 #  define FMT_USE_INT128 0
381 #endif
382 #if !FMT_USE_INT128
383 enum class int128_opt {};
384 enum class uint128_opt {};
385 // Reduce template instantiations.
386 template <typename T> auto convert_for_visit(T) -> monostate { return {}; }
387 #endif
388
389 // Casts a nonnegative integer to unsigned.
390 template <typename Int>
391 FMT_CONSTEXPR auto to_unsigned(Int value) ->
392     typename std::make_unsigned<Int>::type {
393   FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value");
394   return static_cast<typename std::make_unsigned<Int>::type>(value);
395 }
396
397 FMT_CONSTEXPR inline auto is_utf8() -> bool {
398   FMT_MSC_WARNING(suppress : 4566) constexpr unsigned char section[] = "\u00A7";
399
400   // Avoid buggy sign extensions in MSVC's constant evaluation mode (#2297).
401   using uchar = unsigned char;
402   return FMT_UNICODE || (sizeof(section) == 3 && uchar(section[0]) == 0xC2 &&
403                          uchar(section[1]) == 0xA7);
404 }
405 }  // namespace detail
406
407 /**
408   An implementation of ``std::basic_string_view`` for pre-C++17. It provides a
409   subset of the API. ``fmt::basic_string_view`` is used for format strings even
410   if ``std::string_view`` is available to prevent issues when a library is
411   compiled with a different ``-std`` option than the client code (which is not
412   recommended).
413  */
414 FMT_EXPORT
415 template <typename Char> class basic_string_view {
416  private:
417   const Char* data_;
418   size_t size_;
419
420  public:
421   using value_type = Char;
422   using iterator = const Char*;
423
424   constexpr basic_string_view() noexcept : data_(nullptr), size_(0) {}
425
426   /** Constructs a string reference object from a C string and a size. */
427   constexpr basic_string_view(const Char* s, size_t count) noexcept
428       : data_(s), size_(count) {}
429
430   /**
431     \rst
432     Constructs a string reference object from a C string computing
433     the size with ``std::char_traits<Char>::length``.
434     \endrst
435    */
436   FMT_CONSTEXPR_CHAR_TRAITS
437   FMT_INLINE
438   basic_string_view(const Char* s)
439       : data_(s),
440         size_(detail::const_check(std::is_same<Char, char>::value &&
441                                   !detail::is_constant_evaluated(true))
442                   ? std::strlen(reinterpret_cast<const char*>(s))
443                   : std::char_traits<Char>::length(s)) {}
444
445   /** Constructs a string reference from a ``std::basic_string`` object. */
446   template <typename Traits, typename Alloc>
447   FMT_CONSTEXPR basic_string_view(
448       const std::basic_string<Char, Traits, Alloc>& s) noexcept
449       : data_(s.data()), size_(s.size()) {}
450
451   template <typename S, FMT_ENABLE_IF(std::is_same<
452                                       S, detail::std_string_view<Char>>::value)>
453   FMT_CONSTEXPR basic_string_view(S s) noexcept
454       : data_(s.data()), size_(s.size()) {}
455
456   /** Returns a pointer to the string data. */
457   constexpr auto data() const noexcept -> const Char* { return data_; }
458
459   /** Returns the string size. */
460   constexpr auto size() const noexcept -> size_t { return size_; }
461
462   constexpr auto begin() const noexcept -> iterator { return data_; }
463   constexpr auto end() const noexcept -> iterator { return data_ + size_; }
464
465   constexpr auto operator[](size_t pos) const noexcept -> const Char& {
466     return data_[pos];
467   }
468
469   FMT_CONSTEXPR void remove_prefix(size_t n) noexcept {
470     data_ += n;
471     size_ -= n;
472   }
473
474   FMT_CONSTEXPR_CHAR_TRAITS auto starts_with(
475       basic_string_view<Char> sv) const noexcept -> bool {
476     return size_ >= sv.size_ &&
477            std::char_traits<Char>::compare(data_, sv.data_, sv.size_) == 0;
478   }
479   FMT_CONSTEXPR_CHAR_TRAITS auto starts_with(Char c) const noexcept -> bool {
480     return size_ >= 1 && std::char_traits<Char>::eq(*data_, c);
481   }
482   FMT_CONSTEXPR_CHAR_TRAITS auto starts_with(const Char* s) const -> bool {
483     return starts_with(basic_string_view<Char>(s));
484   }
485
486   // Lexicographically compare this string reference to other.
487   FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int {
488     size_t str_size = size_ < other.size_ ? size_ : other.size_;
489     int result = std::char_traits<Char>::compare(data_, other.data_, str_size);
490     if (result == 0)
491       result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
492     return result;
493   }
494
495   FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs,
496                                                    basic_string_view rhs)
497       -> bool {
498     return lhs.compare(rhs) == 0;
499   }
500   friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool {
501     return lhs.compare(rhs) != 0;
502   }
503   friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool {
504     return lhs.compare(rhs) < 0;
505   }
506   friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool {
507     return lhs.compare(rhs) <= 0;
508   }
509   friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool {
510     return lhs.compare(rhs) > 0;
511   }
512   friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool {
513     return lhs.compare(rhs) >= 0;
514   }
515 };
516
517 FMT_EXPORT
518 using string_view = basic_string_view<char>;
519
520 /** Specifies if ``T`` is a character type. Can be specialized by users. */
521 FMT_EXPORT
522 template <typename T> struct is_char : std::false_type {};
523 template <> struct is_char<char> : std::true_type {};
524
525 namespace detail {
526
527 // A base class for compile-time strings.
528 struct compile_string {};
529
530 template <typename S>
531 struct is_compile_string : std::is_base_of<compile_string, S> {};
532
533 template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
534 FMT_INLINE auto to_string_view(const Char* s) -> basic_string_view<Char> {
535   return s;
536 }
537 template <typename Char, typename Traits, typename Alloc>
538 inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s)
539     -> basic_string_view<Char> {
540   return s;
541 }
542 template <typename Char>
543 constexpr auto to_string_view(basic_string_view<Char> s)
544     -> basic_string_view<Char> {
545   return s;
546 }
547 template <typename Char,
548           FMT_ENABLE_IF(!std::is_empty<std_string_view<Char>>::value)>
549 inline auto to_string_view(std_string_view<Char> s) -> basic_string_view<Char> {
550   return s;
551 }
552 template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
553 constexpr auto to_string_view(const S& s)
554     -> basic_string_view<typename S::char_type> {
555   return basic_string_view<typename S::char_type>(s);
556 }
557 void to_string_view(...);
558
559 // Specifies whether S is a string type convertible to fmt::basic_string_view.
560 // It should be a constexpr function but MSVC 2017 fails to compile it in
561 // enable_if and MSVC 2015 fails to compile it as an alias template.
562 // ADL is intentionally disabled as to_string_view is not an extension point.
563 template <typename S>
564 struct is_string
565     : std::is_class<decltype(detail::to_string_view(std::declval<S>()))> {};
566
567 template <typename S, typename = void> struct char_t_impl {};
568 template <typename S> struct char_t_impl<S, enable_if_t<is_string<S>::value>> {
569   using result = decltype(to_string_view(std::declval<S>()));
570   using type = typename result::value_type;
571 };
572
573 enum class type {
574   none_type,
575   // Integer types should go first,
576   int_type,
577   uint_type,
578   long_long_type,
579   ulong_long_type,
580   int128_type,
581   uint128_type,
582   bool_type,
583   char_type,
584   last_integer_type = char_type,
585   // followed by floating-point types.
586   float_type,
587   double_type,
588   long_double_type,
589   last_numeric_type = long_double_type,
590   cstring_type,
591   string_type,
592   pointer_type,
593   custom_type
594 };
595
596 // Maps core type T to the corresponding type enum constant.
597 template <typename T, typename Char>
598 struct type_constant : std::integral_constant<type, type::custom_type> {};
599
600 #define FMT_TYPE_CONSTANT(Type, constant) \
601   template <typename Char>                \
602   struct type_constant<Type, Char>        \
603       : std::integral_constant<type, type::constant> {}
604
605 FMT_TYPE_CONSTANT(int, int_type);
606 FMT_TYPE_CONSTANT(unsigned, uint_type);
607 FMT_TYPE_CONSTANT(long long, long_long_type);
608 FMT_TYPE_CONSTANT(unsigned long long, ulong_long_type);
609 FMT_TYPE_CONSTANT(int128_opt, int128_type);
610 FMT_TYPE_CONSTANT(uint128_opt, uint128_type);
611 FMT_TYPE_CONSTANT(bool, bool_type);
612 FMT_TYPE_CONSTANT(Char, char_type);
613 FMT_TYPE_CONSTANT(float, float_type);
614 FMT_TYPE_CONSTANT(double, double_type);
615 FMT_TYPE_CONSTANT(long double, long_double_type);
616 FMT_TYPE_CONSTANT(const Char*, cstring_type);
617 FMT_TYPE_CONSTANT(basic_string_view<Char>, string_type);
618 FMT_TYPE_CONSTANT(const void*, pointer_type);
619
620 constexpr auto is_integral_type(type t) -> bool {
621   return t > type::none_type && t <= type::last_integer_type;
622 }
623 constexpr auto is_arithmetic_type(type t) -> bool {
624   return t > type::none_type && t <= type::last_numeric_type;
625 }
626
627 constexpr auto set(type rhs) -> int { return 1 << static_cast<int>(rhs); }
628 constexpr auto in(type t, int set) -> bool {
629   return ((set >> static_cast<int>(t)) & 1) != 0;
630 }
631
632 // Bitsets of types.
633 enum {
634   sint_set =
635       set(type::int_type) | set(type::long_long_type) | set(type::int128_type),
636   uint_set = set(type::uint_type) | set(type::ulong_long_type) |
637              set(type::uint128_type),
638   bool_set = set(type::bool_type),
639   char_set = set(type::char_type),
640   float_set = set(type::float_type) | set(type::double_type) |
641               set(type::long_double_type),
642   string_set = set(type::string_type),
643   cstring_set = set(type::cstring_type),
644   pointer_set = set(type::pointer_type)
645 };
646
647 // DEPRECATED!
648 FMT_NORETURN FMT_API void throw_format_error(const char* message);
649
650 struct error_handler {
651   constexpr error_handler() = default;
652
653   // This function is intentionally not constexpr to give a compile-time error.
654   FMT_NORETURN void on_error(const char* message) {
655     throw_format_error(message);
656   }
657 };
658 }  // namespace detail
659
660 /** Throws ``format_error`` with a given message. */
661 using detail::throw_format_error;
662
663 /** String's character type. */
664 template <typename S> using char_t = typename detail::char_t_impl<S>::type;
665
666 /**
667   \rst
668   Parsing context consisting of a format string range being parsed and an
669   argument counter for automatic indexing.
670   You can use the ``format_parse_context`` type alias for ``char`` instead.
671   \endrst
672  */
673 FMT_EXPORT
674 template <typename Char> class basic_format_parse_context {
675  private:
676   basic_string_view<Char> format_str_;
677   int next_arg_id_;
678
679   FMT_CONSTEXPR void do_check_arg_id(int id);
680
681  public:
682   using char_type = Char;
683   using iterator = const Char*;
684
685   explicit constexpr basic_format_parse_context(
686       basic_string_view<Char> format_str, int next_arg_id = 0)
687       : format_str_(format_str), next_arg_id_(next_arg_id) {}
688
689   /**
690     Returns an iterator to the beginning of the format string range being
691     parsed.
692    */
693   constexpr auto begin() const noexcept -> iterator {
694     return format_str_.begin();
695   }
696
697   /**
698     Returns an iterator past the end of the format string range being parsed.
699    */
700   constexpr auto end() const noexcept -> iterator { return format_str_.end(); }
701
702   /** Advances the begin iterator to ``it``. */
703   FMT_CONSTEXPR void advance_to(iterator it) {
704     format_str_.remove_prefix(detail::to_unsigned(it - begin()));
705   }
706
707   /**
708     Reports an error if using the manual argument indexing; otherwise returns
709     the next argument index and switches to the automatic indexing.
710    */
711   FMT_CONSTEXPR auto next_arg_id() -> int {
712     if (next_arg_id_ < 0) {
713       detail::throw_format_error(
714           "cannot switch from manual to automatic argument indexing");
715       return 0;
716     }
717     int id = next_arg_id_++;
718     do_check_arg_id(id);
719     return id;
720   }
721
722   /**
723     Reports an error if using the automatic argument indexing; otherwise
724     switches to the manual indexing.
725    */
726   FMT_CONSTEXPR void check_arg_id(int id) {
727     if (next_arg_id_ > 0) {
728       detail::throw_format_error(
729           "cannot switch from automatic to manual argument indexing");
730       return;
731     }
732     next_arg_id_ = -1;
733     do_check_arg_id(id);
734   }
735   FMT_CONSTEXPR void check_arg_id(basic_string_view<Char>) {}
736   FMT_CONSTEXPR void check_dynamic_spec(int arg_id);
737 };
738
739 FMT_EXPORT
740 using format_parse_context = basic_format_parse_context<char>;
741
742 namespace detail {
743 // A parse context with extra data used only in compile-time checks.
744 template <typename Char>
745 class compile_parse_context : public basic_format_parse_context<Char> {
746  private:
747   int num_args_;
748   const type* types_;
749   using base = basic_format_parse_context<Char>;
750
751  public:
752   explicit FMT_CONSTEXPR compile_parse_context(
753       basic_string_view<Char> format_str, int num_args, const type* types,
754       int next_arg_id = 0)
755       : base(format_str, next_arg_id), num_args_(num_args), types_(types) {}
756
757   constexpr auto num_args() const -> int { return num_args_; }
758   constexpr auto arg_type(int id) const -> type { return types_[id]; }
759
760   FMT_CONSTEXPR auto next_arg_id() -> int {
761     int id = base::next_arg_id();
762     if (id >= num_args_) throw_format_error("argument not found");
763     return id;
764   }
765
766   FMT_CONSTEXPR void check_arg_id(int id) {
767     base::check_arg_id(id);
768     if (id >= num_args_) throw_format_error("argument not found");
769   }
770   using base::check_arg_id;
771
772   FMT_CONSTEXPR void check_dynamic_spec(int arg_id) {
773     detail::ignore_unused(arg_id);
774 #if !defined(__LCC__)
775     if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id]))
776       throw_format_error("width/precision is not integer");
777 #endif
778   }
779 };
780
781 // Extracts a reference to the container from back_insert_iterator.
782 template <typename Container>
783 inline auto get_container(std::back_insert_iterator<Container> it)
784     -> Container& {
785   using base = std::back_insert_iterator<Container>;
786   struct accessor : base {
787     accessor(base b) : base(b) {}
788     using base::container;
789   };
790   return *accessor(it).container;
791 }
792
793 template <typename Char, typename InputIt, typename OutputIt>
794 FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
795     -> OutputIt {
796   while (begin != end) *out++ = static_cast<Char>(*begin++);
797   return out;
798 }
799
800 template <typename Char, typename T, typename U,
801           FMT_ENABLE_IF(
802               std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)>
803 FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U* {
804   if (is_constant_evaluated()) return copy_str<Char, T*, U*>(begin, end, out);
805   auto size = to_unsigned(end - begin);
806   if (size > 0) memcpy(out, begin, size * sizeof(U));
807   return out + size;
808 }
809
810 /**
811   \rst
812   A contiguous memory buffer with an optional growing ability. It is an internal
813   class and shouldn't be used directly, only via `~fmt::basic_memory_buffer`.
814   \endrst
815  */
816 template <typename T> class buffer {
817  private:
818   T* ptr_;
819   size_t size_;
820   size_t capacity_;
821
822  protected:
823   // Don't initialize ptr_ since it is not accessed to save a few cycles.
824   FMT_MSC_WARNING(suppress : 26495)
825   FMT_CONSTEXPR buffer(size_t sz) noexcept : size_(sz), capacity_(sz) {}
826
827   FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept
828       : ptr_(p), size_(sz), capacity_(cap) {}
829
830   FMT_CONSTEXPR20 ~buffer() = default;
831   buffer(buffer&&) = default;
832
833   /** Sets the buffer data and capacity. */
834   FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept {
835     ptr_ = buf_data;
836     capacity_ = buf_capacity;
837   }
838
839   /** Increases the buffer capacity to hold at least *capacity* elements. */
840   // DEPRECATED!
841   virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0;
842
843  public:
844   using value_type = T;
845   using const_reference = const T&;
846
847   buffer(const buffer&) = delete;
848   void operator=(const buffer&) = delete;
849
850   FMT_INLINE auto begin() noexcept -> T* { return ptr_; }
851   FMT_INLINE auto end() noexcept -> T* { return ptr_ + size_; }
852
853   FMT_INLINE auto begin() const noexcept -> const T* { return ptr_; }
854   FMT_INLINE auto end() const noexcept -> const T* { return ptr_ + size_; }
855
856   /** Returns the size of this buffer. */
857   constexpr auto size() const noexcept -> size_t { return size_; }
858
859   /** Returns the capacity of this buffer. */
860   constexpr auto capacity() const noexcept -> size_t { return capacity_; }
861
862   /** Returns a pointer to the buffer data (not null-terminated). */
863   FMT_CONSTEXPR auto data() noexcept -> T* { return ptr_; }
864   FMT_CONSTEXPR auto data() const noexcept -> const T* { return ptr_; }
865
866   /** Clears this buffer. */
867   void clear() { size_ = 0; }
868
869   // Tries resizing the buffer to contain *count* elements. If T is a POD type
870   // the new elements may not be initialized.
871   FMT_CONSTEXPR20 void try_resize(size_t count) {
872     try_reserve(count);
873     size_ = count <= capacity_ ? count : capacity_;
874   }
875
876   // Tries increasing the buffer capacity to *new_capacity*. It can increase the
877   // capacity by a smaller amount than requested but guarantees there is space
878   // for at least one additional element either by increasing the capacity or by
879   // flushing the buffer if it is full.
880   FMT_CONSTEXPR20 void try_reserve(size_t new_capacity) {
881     if (new_capacity > capacity_) grow(new_capacity);
882   }
883
884   FMT_CONSTEXPR20 void push_back(const T& value) {
885     try_reserve(size_ + 1);
886     ptr_[size_++] = value;
887   }
888
889   /** Appends data to the end of the buffer. */
890   template <typename U> void append(const U* begin, const U* end);
891
892   template <typename Idx> FMT_CONSTEXPR auto operator[](Idx index) -> T& {
893     return ptr_[index];
894   }
895   template <typename Idx>
896   FMT_CONSTEXPR auto operator[](Idx index) const -> const T& {
897     return ptr_[index];
898   }
899 };
900
901 struct buffer_traits {
902   explicit buffer_traits(size_t) {}
903   auto count() const -> size_t { return 0; }
904   auto limit(size_t size) -> size_t { return size; }
905 };
906
907 class fixed_buffer_traits {
908  private:
909   size_t count_ = 0;
910   size_t limit_;
911
912  public:
913   explicit fixed_buffer_traits(size_t limit) : limit_(limit) {}
914   auto count() const -> size_t { return count_; }
915   auto limit(size_t size) -> size_t {
916     size_t n = limit_ > count_ ? limit_ - count_ : 0;
917     count_ += size;
918     return size < n ? size : n;
919   }
920 };
921
922 // A buffer that writes to an output iterator when flushed.
923 template <typename OutputIt, typename T, typename Traits = buffer_traits>
924 class iterator_buffer final : public Traits, public buffer<T> {
925  private:
926   OutputIt out_;
927   enum { buffer_size = 256 };
928   T data_[buffer_size];
929
930  protected:
931   FMT_CONSTEXPR20 void grow(size_t) override {
932     if (this->size() == buffer_size) flush();
933   }
934
935   void flush() {
936     auto size = this->size();
937     this->clear();
938     out_ = copy_str<T>(data_, data_ + this->limit(size), out_);
939   }
940
941  public:
942   explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
943       : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out) {}
944   iterator_buffer(iterator_buffer&& other)
945       : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_) {}
946   ~iterator_buffer() { flush(); }
947
948   auto out() -> OutputIt {
949     flush();
950     return out_;
951   }
952   auto count() const -> size_t { return Traits::count() + this->size(); }
953 };
954
955 template <typename T>
956 class iterator_buffer<T*, T, fixed_buffer_traits> final
957     : public fixed_buffer_traits,
958       public buffer<T> {
959  private:
960   T* out_;
961   enum { buffer_size = 256 };
962   T data_[buffer_size];
963
964  protected:
965   FMT_CONSTEXPR20 void grow(size_t) override {
966     if (this->size() == this->capacity()) flush();
967   }
968
969   void flush() {
970     size_t n = this->limit(this->size());
971     if (this->data() == out_) {
972       out_ += n;
973       this->set(data_, buffer_size);
974     }
975     this->clear();
976   }
977
978  public:
979   explicit iterator_buffer(T* out, size_t n = buffer_size)
980       : fixed_buffer_traits(n), buffer<T>(out, 0, n), out_(out) {}
981   iterator_buffer(iterator_buffer&& other)
982       : fixed_buffer_traits(other),
983         buffer<T>(std::move(other)),
984         out_(other.out_) {
985     if (this->data() != out_) {
986       this->set(data_, buffer_size);
987       this->clear();
988     }
989   }
990   ~iterator_buffer() { flush(); }
991
992   auto out() -> T* {
993     flush();
994     return out_;
995   }
996   auto count() const -> size_t {
997     return fixed_buffer_traits::count() + this->size();
998   }
999 };
1000
1001 template <typename T> class iterator_buffer<T*, T> final : public buffer<T> {
1002  protected:
1003   FMT_CONSTEXPR20 void grow(size_t) override {}
1004
1005  public:
1006   explicit iterator_buffer(T* out, size_t = 0) : buffer<T>(out, 0, ~size_t()) {}
1007
1008   auto out() -> T* { return &*this->end(); }
1009 };
1010
1011 // A buffer that writes to a container with the contiguous storage.
1012 template <typename Container>
1013 class iterator_buffer<std::back_insert_iterator<Container>,
1014                       enable_if_t<is_contiguous<Container>::value,
1015                                   typename Container::value_type>>
1016     final : public buffer<typename Container::value_type> {
1017  private:
1018   Container& container_;
1019
1020  protected:
1021   FMT_CONSTEXPR20 void grow(size_t capacity) override {
1022     container_.resize(capacity);
1023     this->set(&container_[0], capacity);
1024   }
1025
1026  public:
1027   explicit iterator_buffer(Container& c)
1028       : buffer<typename Container::value_type>(c.size()), container_(c) {}
1029   explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
1030       : iterator_buffer(get_container(out)) {}
1031
1032   auto out() -> std::back_insert_iterator<Container> {
1033     return std::back_inserter(container_);
1034   }
1035 };
1036
1037 // A buffer that counts the number of code units written discarding the output.
1038 template <typename T = char> class counting_buffer final : public buffer<T> {
1039  private:
1040   enum { buffer_size = 256 };
1041   T data_[buffer_size];
1042   size_t count_ = 0;
1043
1044  protected:
1045   FMT_CONSTEXPR20 void grow(size_t) override {
1046     if (this->size() != buffer_size) return;
1047     count_ += this->size();
1048     this->clear();
1049   }
1050
1051  public:
1052   counting_buffer() : buffer<T>(data_, 0, buffer_size) {}
1053
1054   auto count() -> size_t { return count_ + this->size(); }
1055 };
1056 }  // namespace detail
1057
1058 template <typename Char>
1059 FMT_CONSTEXPR void basic_format_parse_context<Char>::do_check_arg_id(int id) {
1060   // Argument id is only checked at compile-time during parsing because
1061   // formatting has its own validation.
1062   if (detail::is_constant_evaluated() &&
1063       (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) {
1064     using context = detail::compile_parse_context<Char>;
1065     if (id >= static_cast<context*>(this)->num_args())
1066       detail::throw_format_error("argument not found");
1067   }
1068 }
1069
1070 template <typename Char>
1071 FMT_CONSTEXPR void basic_format_parse_context<Char>::check_dynamic_spec(
1072     int arg_id) {
1073   if (detail::is_constant_evaluated() &&
1074       (!FMT_GCC_VERSION || FMT_GCC_VERSION >= 1200)) {
1075     using context = detail::compile_parse_context<Char>;
1076     static_cast<context*>(this)->check_dynamic_spec(arg_id);
1077   }
1078 }
1079
1080 FMT_EXPORT template <typename Context> class basic_format_arg;
1081 FMT_EXPORT template <typename Context> class basic_format_args;
1082 FMT_EXPORT template <typename Context> class dynamic_format_arg_store;
1083
1084 // A formatter for objects of type T.
1085 FMT_EXPORT
1086 template <typename T, typename Char = char, typename Enable = void>
1087 struct formatter {
1088   // A deleted default constructor indicates a disabled formatter.
1089   formatter() = delete;
1090 };
1091
1092 // Specifies if T has an enabled formatter specialization. A type can be
1093 // formattable even if it doesn't have a formatter e.g. via a conversion.
1094 template <typename T, typename Context>
1095 using has_formatter =
1096     std::is_constructible<typename Context::template formatter_type<T>>;
1097
1098 // An output iterator that appends to a buffer.
1099 // It is used to reduce symbol sizes for the common case.
1100 class appender : public std::back_insert_iterator<detail::buffer<char>> {
1101   using base = std::back_insert_iterator<detail::buffer<char>>;
1102
1103  public:
1104   using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
1105   appender(base it) noexcept : base(it) {}
1106   FMT_UNCHECKED_ITERATOR(appender);
1107
1108   auto operator++() noexcept -> appender& { return *this; }
1109   auto operator++(int) noexcept -> appender { return *this; }
1110 };
1111
1112 namespace detail {
1113
1114 template <typename Context, typename T>
1115 constexpr auto has_const_formatter_impl(T*)
1116     -> decltype(typename Context::template formatter_type<T>().format(
1117                     std::declval<const T&>(), std::declval<Context&>()),
1118                 true) {
1119   return true;
1120 }
1121 template <typename Context>
1122 constexpr auto has_const_formatter_impl(...) -> bool {
1123   return false;
1124 }
1125 template <typename T, typename Context>
1126 constexpr auto has_const_formatter() -> bool {
1127   return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));
1128 }
1129
1130 template <typename T>
1131 using buffer_appender = conditional_t<std::is_same<T, char>::value, appender,
1132                                       std::back_insert_iterator<buffer<T>>>;
1133
1134 // Maps an output iterator to a buffer.
1135 template <typename T, typename OutputIt>
1136 auto get_buffer(OutputIt out) -> iterator_buffer<OutputIt, T> {
1137   return iterator_buffer<OutputIt, T>(out);
1138 }
1139 template <typename T, typename Buf,
1140           FMT_ENABLE_IF(std::is_base_of<buffer<char>, Buf>::value)>
1141 auto get_buffer(std::back_insert_iterator<Buf> out) -> buffer<char>& {
1142   return get_container(out);
1143 }
1144
1145 template <typename Buf, typename OutputIt>
1146 FMT_INLINE auto get_iterator(Buf& buf, OutputIt) -> decltype(buf.out()) {
1147   return buf.out();
1148 }
1149 template <typename T, typename OutputIt>
1150 auto get_iterator(buffer<T>&, OutputIt out) -> OutputIt {
1151   return out;
1152 }
1153
1154 struct view {};
1155
1156 template <typename Char, typename T> struct named_arg : view {
1157   const Char* name;
1158   const T& value;
1159   named_arg(const Char* n, const T& v) : name(n), value(v) {}
1160 };
1161
1162 template <typename Char> struct named_arg_info {
1163   const Char* name;
1164   int id;
1165 };
1166
1167 template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
1168 struct arg_data {
1169   // args_[0].named_args points to named_args_ to avoid bloating format_args.
1170   // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
1171   T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
1172   named_arg_info<Char> named_args_[NUM_NAMED_ARGS];
1173
1174   template <typename... U>
1175   arg_data(const U&... init) : args_{T(named_args_, NUM_NAMED_ARGS), init...} {}
1176   arg_data(const arg_data& other) = delete;
1177   auto args() const -> const T* { return args_ + 1; }
1178   auto named_args() -> named_arg_info<Char>* { return named_args_; }
1179 };
1180
1181 template <typename T, typename Char, size_t NUM_ARGS>
1182 struct arg_data<T, Char, NUM_ARGS, 0> {
1183   // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
1184   T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
1185
1186   template <typename... U>
1187   FMT_CONSTEXPR FMT_INLINE arg_data(const U&... init) : args_{init...} {}
1188   FMT_CONSTEXPR FMT_INLINE auto args() const -> const T* { return args_; }
1189   FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t {
1190     return nullptr;
1191   }
1192 };
1193
1194 template <typename Char>
1195 inline void init_named_args(named_arg_info<Char>*, int, int) {}
1196
1197 template <typename T> struct is_named_arg : std::false_type {};
1198 template <typename T> struct is_statically_named_arg : std::false_type {};
1199
1200 template <typename T, typename Char>
1201 struct is_named_arg<named_arg<Char, T>> : std::true_type {};
1202
1203 template <typename Char, typename T, typename... Tail,
1204           FMT_ENABLE_IF(!is_named_arg<T>::value)>
1205 void init_named_args(named_arg_info<Char>* named_args, int arg_count,
1206                      int named_arg_count, const T&, const Tail&... args) {
1207   init_named_args(named_args, arg_count + 1, named_arg_count, args...);
1208 }
1209
1210 template <typename Char, typename T, typename... Tail,
1211           FMT_ENABLE_IF(is_named_arg<T>::value)>
1212 void init_named_args(named_arg_info<Char>* named_args, int arg_count,
1213                      int named_arg_count, const T& arg, const Tail&... args) {
1214   named_args[named_arg_count++] = {arg.name, arg_count};
1215   init_named_args(named_args, arg_count + 1, named_arg_count, args...);
1216 }
1217
1218 template <typename... Args>
1219 FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int,
1220                                               const Args&...) {}
1221
1222 template <bool B = false> constexpr auto count() -> size_t { return B ? 1 : 0; }
1223 template <bool B1, bool B2, bool... Tail> constexpr auto count() -> size_t {
1224   return (B1 ? 1 : 0) + count<B2, Tail...>();
1225 }
1226
1227 template <typename... Args> constexpr auto count_named_args() -> size_t {
1228   return count<is_named_arg<Args>::value...>();
1229 }
1230
1231 template <typename... Args>
1232 constexpr auto count_statically_named_args() -> size_t {
1233   return count<is_statically_named_arg<Args>::value...>();
1234 }
1235
1236 struct unformattable {};
1237 struct unformattable_char : unformattable {};
1238 struct unformattable_pointer : unformattable {};
1239
1240 template <typename Char> struct string_value {
1241   const Char* data;
1242   size_t size;
1243 };
1244
1245 template <typename Char> struct named_arg_value {
1246   const named_arg_info<Char>* data;
1247   size_t size;
1248 };
1249
1250 template <typename Context> struct custom_value {
1251   using parse_context = typename Context::parse_context_type;
1252   void* value;
1253   void (*format)(void* arg, parse_context& parse_ctx, Context& ctx);
1254 };
1255
1256 // A formatting argument value.
1257 template <typename Context> class value {
1258  public:
1259   using char_type = typename Context::char_type;
1260
1261   union {
1262     monostate no_value;
1263     int int_value;
1264     unsigned uint_value;
1265     long long long_long_value;
1266     unsigned long long ulong_long_value;
1267     int128_opt int128_value;
1268     uint128_opt uint128_value;
1269     bool bool_value;
1270     char_type char_value;
1271     float float_value;
1272     double double_value;
1273     long double long_double_value;
1274     const void* pointer;
1275     string_value<char_type> string;
1276     custom_value<Context> custom;
1277     named_arg_value<char_type> named_args;
1278   };
1279
1280   constexpr FMT_INLINE value() : no_value() {}
1281   constexpr FMT_INLINE value(int val) : int_value(val) {}
1282   constexpr FMT_INLINE value(unsigned val) : uint_value(val) {}
1283   constexpr FMT_INLINE value(long long val) : long_long_value(val) {}
1284   constexpr FMT_INLINE value(unsigned long long val) : ulong_long_value(val) {}
1285   FMT_INLINE value(int128_opt val) : int128_value(val) {}
1286   FMT_INLINE value(uint128_opt val) : uint128_value(val) {}
1287   constexpr FMT_INLINE value(float val) : float_value(val) {}
1288   constexpr FMT_INLINE value(double val) : double_value(val) {}
1289   FMT_INLINE value(long double val) : long_double_value(val) {}
1290   constexpr FMT_INLINE value(bool val) : bool_value(val) {}
1291   constexpr FMT_INLINE value(char_type val) : char_value(val) {}
1292   FMT_CONSTEXPR FMT_INLINE value(const char_type* val) {
1293     string.data = val;
1294     if (is_constant_evaluated()) string.size = {};
1295   }
1296   FMT_CONSTEXPR FMT_INLINE value(basic_string_view<char_type> val) {
1297     string.data = val.data();
1298     string.size = val.size();
1299   }
1300   FMT_INLINE value(const void* val) : pointer(val) {}
1301   FMT_INLINE value(const named_arg_info<char_type>* args, size_t size)
1302       : named_args{args, size} {}
1303
1304   template <typename T> FMT_CONSTEXPR20 FMT_INLINE value(T& val) {
1305     using value_type = remove_const_t<T>;
1306     custom.value = const_cast<value_type*>(std::addressof(val));
1307     // Get the formatter type through the context to allow different contexts
1308     // have different extension points, e.g. `formatter<T>` for `format` and
1309     // `printf_formatter<T>` for `printf`.
1310     custom.format = format_custom_arg<
1311         value_type, typename Context::template formatter_type<value_type>>;
1312   }
1313   value(unformattable);
1314   value(unformattable_char);
1315   value(unformattable_pointer);
1316
1317  private:
1318   // Formats an argument of a custom type, such as a user-defined class.
1319   template <typename T, typename Formatter>
1320   static void format_custom_arg(void* arg,
1321                                 typename Context::parse_context_type& parse_ctx,
1322                                 Context& ctx) {
1323     auto f = Formatter();
1324     parse_ctx.advance_to(f.parse(parse_ctx));
1325     using qualified_type =
1326         conditional_t<has_const_formatter<T, Context>(), const T, T>;
1327     // Calling format through a mutable reference is deprecated.
1328     ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx));
1329   }
1330 };
1331
1332 // To minimize the number of types we need to deal with, long is translated
1333 // either to int or to long long depending on its size.
1334 enum { long_short = sizeof(long) == sizeof(int) };
1335 using long_type = conditional_t<long_short, int, long long>;
1336 using ulong_type = conditional_t<long_short, unsigned, unsigned long long>;
1337
1338 template <typename T> struct format_as_result {
1339   template <typename U,
1340             FMT_ENABLE_IF(std::is_enum<U>::value || std::is_class<U>::value)>
1341   static auto map(U*) -> remove_cvref_t<decltype(format_as(std::declval<U>()))>;
1342   static auto map(...) -> void;
1343
1344   using type = decltype(map(static_cast<T*>(nullptr)));
1345 };
1346 template <typename T> using format_as_t = typename format_as_result<T>::type;
1347
1348 template <typename T>
1349 struct has_format_as
1350     : bool_constant<!std::is_same<format_as_t<T>, void>::value> {};
1351
1352 // Maps formatting arguments to core types.
1353 // arg_mapper reports errors by returning unformattable instead of using
1354 // static_assert because it's used in the is_formattable trait.
1355 template <typename Context> struct arg_mapper {
1356   using char_type = typename Context::char_type;
1357
1358   FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int { return val; }
1359   FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned {
1360     return val;
1361   }
1362   FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int { return val; }
1363   FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned {
1364     return val;
1365   }
1366   FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int { return val; }
1367   FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned { return val; }
1368   FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type { return val; }
1369   FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type {
1370     return val;
1371   }
1372   FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long { return val; }
1373   FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val)
1374       -> unsigned long long {
1375     return val;
1376   }
1377   FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt {
1378     return val;
1379   }
1380   FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt {
1381     return val;
1382   }
1383   FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool { return val; }
1384
1385   template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value ||
1386                                       std::is_same<T, char_type>::value)>
1387   FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type {
1388     return val;
1389   }
1390   template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value ||
1391 #ifdef __cpp_char8_t
1392                                      std::is_same<T, char8_t>::value ||
1393 #endif
1394                                      std::is_same<T, char16_t>::value ||
1395                                      std::is_same<T, char32_t>::value) &&
1396                                         !std::is_same<T, char_type>::value,
1397                                     int> = 0>
1398   FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char {
1399     return {};
1400   }
1401
1402   FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float { return val; }
1403   FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double { return val; }
1404   FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double {
1405     return val;
1406   }
1407
1408   FMT_CONSTEXPR FMT_INLINE auto map(char_type* val) -> const char_type* {
1409     return val;
1410   }
1411   FMT_CONSTEXPR FMT_INLINE auto map(const char_type* val) -> const char_type* {
1412     return val;
1413   }
1414   template <typename T,
1415             FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
1416                           std::is_same<char_type, char_t<T>>::value)>
1417   FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
1418       -> basic_string_view<char_type> {
1419     return to_string_view(val);
1420   }
1421   template <typename T,
1422             FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
1423                           !std::is_same<char_type, char_t<T>>::value)>
1424   FMT_CONSTEXPR FMT_INLINE auto map(const T&) -> unformattable_char {
1425     return {};
1426   }
1427
1428   FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void* { return val; }
1429   FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void* {
1430     return val;
1431   }
1432   FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void* {
1433     return val;
1434   }
1435
1436   // Use SFINAE instead of a const T* parameter to avoid a conflict with the
1437   // array overload.
1438   template <
1439       typename T,
1440       FMT_ENABLE_IF(
1441           std::is_pointer<T>::value || std::is_member_pointer<T>::value ||
1442           std::is_function<typename std::remove_pointer<T>::type>::value ||
1443           (std::is_array<T>::value &&
1444            !std::is_convertible<T, const char_type*>::value))>
1445   FMT_CONSTEXPR auto map(const T&) -> unformattable_pointer {
1446     return {};
1447   }
1448
1449   template <typename T, std::size_t N,
1450             FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)>
1451   FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N] {
1452     return values;
1453   }
1454
1455   // Only map owning types because mapping views can be unsafe.
1456   template <typename T, typename U = format_as_t<T>,
1457             FMT_ENABLE_IF(std::is_arithmetic<U>::value)>
1458   FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
1459       -> decltype(FMT_DECLTYPE_THIS map(U())) {
1460     return map(format_as(val));
1461   }
1462
1463   template <typename T, typename U = remove_const_t<T>>
1464   struct formattable : bool_constant<has_const_formatter<U, Context>() ||
1465                                      (has_formatter<U, Context>::value &&
1466                                       !std::is_const<T>::value)> {};
1467
1468   template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
1469   FMT_CONSTEXPR FMT_INLINE auto do_map(T& val) -> T& {
1470     return val;
1471   }
1472   template <typename T, FMT_ENABLE_IF(!formattable<T>::value)>
1473   FMT_CONSTEXPR FMT_INLINE auto do_map(T&) -> unformattable {
1474     return {};
1475   }
1476
1477   template <typename T, typename U = remove_const_t<T>,
1478             FMT_ENABLE_IF((std::is_class<U>::value || std::is_enum<U>::value ||
1479                            std::is_union<U>::value) &&
1480                           !is_string<U>::value && !is_char<U>::value &&
1481                           !is_named_arg<U>::value &&
1482                           !std::is_arithmetic<format_as_t<U>>::value)>
1483   FMT_CONSTEXPR FMT_INLINE auto map(T& val)
1484       -> decltype(FMT_DECLTYPE_THIS do_map(val)) {
1485     return do_map(val);
1486   }
1487
1488   template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
1489   FMT_CONSTEXPR FMT_INLINE auto map(const T& named_arg)
1490       -> decltype(FMT_DECLTYPE_THIS map(named_arg.value)) {
1491     return map(named_arg.value);
1492   }
1493
1494   auto map(...) -> unformattable { return {}; }
1495 };
1496
1497 // A type constant after applying arg_mapper<Context>.
1498 template <typename T, typename Context>
1499 using mapped_type_constant =
1500     type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),
1501                   typename Context::char_type>;
1502
1503 enum { packed_arg_bits = 4 };
1504 // Maximum number of arguments with packed types.
1505 enum { max_packed_args = 62 / packed_arg_bits };
1506 enum : unsigned long long { is_unpacked_bit = 1ULL << 63 };
1507 enum : unsigned long long { has_named_args_bit = 1ULL << 62 };
1508
1509 template <typename Char, typename InputIt>
1510 auto copy_str(InputIt begin, InputIt end, appender out) -> appender {
1511   get_container(out).append(begin, end);
1512   return out;
1513 }
1514 template <typename Char, typename InputIt>
1515 auto copy_str(InputIt begin, InputIt end,
1516               std::back_insert_iterator<std::string> out)
1517     -> std::back_insert_iterator<std::string> {
1518   get_container(out).append(begin, end);
1519   return out;
1520 }
1521
1522 template <typename Char, typename R, typename OutputIt>
1523 FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt {
1524   return detail::copy_str<Char>(rng.begin(), rng.end(), out);
1525 }
1526
1527 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
1528 // A workaround for gcc 4.8 to make void_t work in a SFINAE context.
1529 template <typename...> struct void_t_impl {
1530   using type = void;
1531 };
1532 template <typename... T> using void_t = typename void_t_impl<T...>::type;
1533 #else
1534 template <typename...> using void_t = void;
1535 #endif
1536
1537 template <typename It, typename T, typename Enable = void>
1538 struct is_output_iterator : std::false_type {};
1539
1540 template <typename It, typename T>
1541 struct is_output_iterator<
1542     It, T,
1543     void_t<typename std::iterator_traits<It>::iterator_category,
1544            decltype(*std::declval<It>() = std::declval<T>())>>
1545     : std::true_type {};
1546
1547 template <typename It> struct is_back_insert_iterator : std::false_type {};
1548 template <typename Container>
1549 struct is_back_insert_iterator<std::back_insert_iterator<Container>>
1550     : std::true_type {};
1551
1552 // A type-erased reference to an std::locale to avoid a heavy <locale> include.
1553 class locale_ref {
1554  private:
1555   const void* locale_;  // A type-erased pointer to std::locale.
1556
1557  public:
1558   constexpr FMT_INLINE locale_ref() : locale_(nullptr) {}
1559   template <typename Locale> explicit locale_ref(const Locale& loc);
1560
1561   explicit operator bool() const noexcept { return locale_ != nullptr; }
1562
1563   template <typename Locale> auto get() const -> Locale;
1564 };
1565
1566 template <typename> constexpr auto encode_types() -> unsigned long long {
1567   return 0;
1568 }
1569
1570 template <typename Context, typename Arg, typename... Args>
1571 constexpr auto encode_types() -> unsigned long long {
1572   return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
1573          (encode_types<Context, Args...>() << packed_arg_bits);
1574 }
1575
1576 #if defined(__cpp_if_constexpr)
1577 // This type is intentionally undefined, only used for errors
1578 template <typename T, typename Char> struct type_is_unformattable_for;
1579 #endif
1580
1581 template <bool PACKED, typename Context, typename T, FMT_ENABLE_IF(PACKED)>
1582 FMT_CONSTEXPR FMT_INLINE auto make_arg(T& val) -> value<Context> {
1583   using arg_type = remove_cvref_t<decltype(arg_mapper<Context>().map(val))>;
1584
1585   constexpr bool formattable_char =
1586       !std::is_same<arg_type, unformattable_char>::value;
1587   static_assert(formattable_char, "Mixing character types is disallowed.");
1588
1589   // Formatting of arbitrary pointers is disallowed. If you want to format a
1590   // pointer cast it to `void*` or `const void*`. In particular, this forbids
1591   // formatting of `[const] volatile char*` printed as bool by iostreams.
1592   constexpr bool formattable_pointer =
1593       !std::is_same<arg_type, unformattable_pointer>::value;
1594   static_assert(formattable_pointer,
1595                 "Formatting of non-void pointers is disallowed.");
1596
1597   constexpr bool formattable = !std::is_same<arg_type, unformattable>::value;
1598 #if defined(__cpp_if_constexpr)
1599   if constexpr (!formattable) {
1600     type_is_unformattable_for<T, typename Context::char_type> _;
1601   }
1602 #endif
1603   static_assert(
1604       formattable,
1605       "Cannot format an argument. To make type T formattable provide a "
1606       "formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
1607   return {arg_mapper<Context>().map(val)};
1608 }
1609
1610 template <typename Context, typename T>
1611 FMT_CONSTEXPR auto make_arg(T& val) -> basic_format_arg<Context> {
1612   auto arg = basic_format_arg<Context>();
1613   arg.type_ = mapped_type_constant<T, Context>::value;
1614   arg.value_ = make_arg<true, Context>(val);
1615   return arg;
1616 }
1617
1618 template <bool PACKED, typename Context, typename T, FMT_ENABLE_IF(!PACKED)>
1619 FMT_CONSTEXPR inline auto make_arg(T& val) -> basic_format_arg<Context> {
1620   return make_arg<Context>(val);
1621 }
1622 }  // namespace detail
1623 FMT_BEGIN_EXPORT
1624
1625 // A formatting argument. Context is a template parameter for the compiled API
1626 // where output can be unbuffered.
1627 template <typename Context> class basic_format_arg {
1628  private:
1629   detail::value<Context> value_;
1630   detail::type type_;
1631
1632   template <typename ContextType, typename T>
1633   friend FMT_CONSTEXPR auto detail::make_arg(T& value)
1634       -> basic_format_arg<ContextType>;
1635
1636   template <typename Visitor, typename Ctx>
1637   friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis,
1638                                              const basic_format_arg<Ctx>& arg)
1639       -> decltype(vis(0));
1640
1641   friend class basic_format_args<Context>;
1642   friend class dynamic_format_arg_store<Context>;
1643
1644   using char_type = typename Context::char_type;
1645
1646   template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
1647   friend struct detail::arg_data;
1648
1649   basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
1650       : value_(args, size) {}
1651
1652  public:
1653   class handle {
1654    public:
1655     explicit handle(detail::custom_value<Context> custom) : custom_(custom) {}
1656
1657     void format(typename Context::parse_context_type& parse_ctx,
1658                 Context& ctx) const {
1659       custom_.format(custom_.value, parse_ctx, ctx);
1660     }
1661
1662    private:
1663     detail::custom_value<Context> custom_;
1664   };
1665
1666   constexpr basic_format_arg() : type_(detail::type::none_type) {}
1667
1668   constexpr explicit operator bool() const noexcept {
1669     return type_ != detail::type::none_type;
1670   }
1671
1672   auto type() const -> detail::type { return type_; }
1673
1674   auto is_integral() const -> bool { return detail::is_integral_type(type_); }
1675   auto is_arithmetic() const -> bool {
1676     return detail::is_arithmetic_type(type_);
1677   }
1678
1679   FMT_INLINE auto format_custom(const char_type* parse_begin,
1680                                 typename Context::parse_context_type& parse_ctx,
1681                                 Context& ctx) -> bool {
1682     if (type_ != detail::type::custom_type) return false;
1683     parse_ctx.advance_to(parse_begin);
1684     value_.custom.format(value_.custom.value, parse_ctx, ctx);
1685     return true;
1686   }
1687 };
1688
1689 /**
1690   \rst
1691   Visits an argument dispatching to the appropriate visit method based on
1692   the argument type. For example, if the argument type is ``double`` then
1693   ``vis(value)`` will be called with the value of type ``double``.
1694   \endrst
1695  */
1696 // DEPRECATED!
1697 template <typename Visitor, typename Context>
1698 FMT_CONSTEXPR FMT_INLINE auto visit_format_arg(
1699     Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0)) {
1700   switch (arg.type_) {
1701   case detail::type::none_type:
1702     break;
1703   case detail::type::int_type:
1704     return vis(arg.value_.int_value);
1705   case detail::type::uint_type:
1706     return vis(arg.value_.uint_value);
1707   case detail::type::long_long_type:
1708     return vis(arg.value_.long_long_value);
1709   case detail::type::ulong_long_type:
1710     return vis(arg.value_.ulong_long_value);
1711   case detail::type::int128_type:
1712     return vis(detail::convert_for_visit(arg.value_.int128_value));
1713   case detail::type::uint128_type:
1714     return vis(detail::convert_for_visit(arg.value_.uint128_value));
1715   case detail::type::bool_type:
1716     return vis(arg.value_.bool_value);
1717   case detail::type::char_type:
1718     return vis(arg.value_.char_value);
1719   case detail::type::float_type:
1720     return vis(arg.value_.float_value);
1721   case detail::type::double_type:
1722     return vis(arg.value_.double_value);
1723   case detail::type::long_double_type:
1724     return vis(arg.value_.long_double_value);
1725   case detail::type::cstring_type:
1726     return vis(arg.value_.string.data);
1727   case detail::type::string_type:
1728     using sv = basic_string_view<typename Context::char_type>;
1729     return vis(sv(arg.value_.string.data, arg.value_.string.size));
1730   case detail::type::pointer_type:
1731     return vis(arg.value_.pointer);
1732   case detail::type::custom_type:
1733     return vis(typename basic_format_arg<Context>::handle(arg.value_.custom));
1734   }
1735   return vis(monostate());
1736 }
1737
1738 // Formatting context.
1739 template <typename OutputIt, typename Char> class basic_format_context {
1740  private:
1741   OutputIt out_;
1742   basic_format_args<basic_format_context> args_;
1743   detail::locale_ref loc_;
1744
1745  public:
1746   using iterator = OutputIt;
1747   using format_arg = basic_format_arg<basic_format_context>;
1748   using format_args = basic_format_args<basic_format_context>;
1749   using parse_context_type = basic_format_parse_context<Char>;
1750   template <typename T> using formatter_type = formatter<T, Char>;
1751
1752   /** The character type for the output. */
1753   using char_type = Char;
1754
1755   basic_format_context(basic_format_context&&) = default;
1756   basic_format_context(const basic_format_context&) = delete;
1757   void operator=(const basic_format_context&) = delete;
1758   /**
1759     Constructs a ``basic_format_context`` object. References to the arguments
1760     are stored in the object so make sure they have appropriate lifetimes.
1761    */
1762   constexpr basic_format_context(OutputIt out, format_args ctx_args,
1763                                  detail::locale_ref loc = {})
1764       : out_(out), args_(ctx_args), loc_(loc) {}
1765
1766   constexpr auto arg(int id) const -> format_arg { return args_.get(id); }
1767   FMT_CONSTEXPR auto arg(basic_string_view<Char> name) -> format_arg {
1768     return args_.get(name);
1769   }
1770   FMT_CONSTEXPR auto arg_id(basic_string_view<Char> name) -> int {
1771     return args_.get_id(name);
1772   }
1773   auto args() const -> const format_args& { return args_; }
1774
1775   // DEPRECATED!
1776   FMT_CONSTEXPR auto error_handler() -> detail::error_handler { return {}; }
1777   void on_error(const char* message) { error_handler().on_error(message); }
1778
1779   // Returns an iterator to the beginning of the output range.
1780   FMT_CONSTEXPR auto out() -> iterator { return out_; }
1781
1782   // Advances the begin iterator to ``it``.
1783   void advance_to(iterator it) {
1784     if (!detail::is_back_insert_iterator<iterator>()) out_ = it;
1785   }
1786
1787   FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; }
1788 };
1789
1790 template <typename Char>
1791 using buffer_context =
1792     basic_format_context<detail::buffer_appender<Char>, Char>;
1793 using format_context = buffer_context<char>;
1794
1795 template <typename T, typename Char = char>
1796 using is_formattable = bool_constant<!std::is_base_of<
1797     detail::unformattable, decltype(detail::arg_mapper<buffer_context<Char>>()
1798                                         .map(std::declval<T&>()))>::value>;
1799
1800 /**
1801   \rst
1802   An array of references to arguments. It can be implicitly converted into
1803   `~fmt::basic_format_args` for passing into type-erased formatting functions
1804   such as `~fmt::vformat`.
1805   \endrst
1806  */
1807 template <typename Context, typename... Args>
1808 class format_arg_store
1809 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1810     // Workaround a GCC template argument substitution bug.
1811     : public basic_format_args<Context>
1812 #endif
1813 {
1814  private:
1815   static const size_t num_args = sizeof...(Args);
1816   static constexpr size_t num_named_args = detail::count_named_args<Args...>();
1817   static const bool is_packed = num_args <= detail::max_packed_args;
1818
1819   using value_type = conditional_t<is_packed, detail::value<Context>,
1820                                    basic_format_arg<Context>>;
1821
1822   detail::arg_data<value_type, typename Context::char_type, num_args,
1823                    num_named_args>
1824       data_;
1825
1826   friend class basic_format_args<Context>;
1827
1828   static constexpr unsigned long long desc =
1829       (is_packed ? detail::encode_types<Context, Args...>()
1830                  : detail::is_unpacked_bit | num_args) |
1831       (num_named_args != 0
1832            ? static_cast<unsigned long long>(detail::has_named_args_bit)
1833            : 0);
1834
1835  public:
1836   template <typename... T>
1837   FMT_CONSTEXPR FMT_INLINE format_arg_store(T&... args)
1838       :
1839 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
1840         basic_format_args<Context>(*this),
1841 #endif
1842         data_{detail::make_arg<is_packed, Context>(args)...} {
1843     if (detail::const_check(num_named_args != 0))
1844       detail::init_named_args(data_.named_args(), 0, 0, args...);
1845   }
1846 };
1847
1848 /**
1849   \rst
1850   Constructs a `~fmt::format_arg_store` object that contains references to
1851   arguments and can be implicitly converted to `~fmt::format_args`. `Context`
1852   can be omitted in which case it defaults to `~fmt::format_context`.
1853   See `~fmt::arg` for lifetime considerations.
1854   \endrst
1855  */
1856 // Arguments are taken by lvalue references to avoid some lifetime issues.
1857 template <typename Context = format_context, typename... T>
1858 constexpr auto make_format_args(T&... args)
1859     -> format_arg_store<Context, remove_cvref_t<T>...> {
1860   return {args...};
1861 }
1862
1863 /**
1864   \rst
1865   Returns a named argument to be used in a formatting function.
1866   It should only be used in a call to a formatting function or
1867   `dynamic_format_arg_store::push_back`.
1868
1869   **Example**::
1870
1871     fmt::print("Elapsed time: {s:.2f} seconds", fmt::arg("s", 1.23));
1872   \endrst
1873  */
1874 template <typename Char, typename T>
1875 inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T> {
1876   static_assert(!detail::is_named_arg<T>(), "nested named arguments");
1877   return {name, arg};
1878 }
1879 FMT_END_EXPORT
1880
1881 /**
1882   \rst
1883   A view of a collection of formatting arguments. To avoid lifetime issues it
1884   should only be used as a parameter type in type-erased functions such as
1885   ``vformat``::
1886
1887     void vlog(string_view format_str, format_args args);  // OK
1888     format_args args = make_format_args();  // Error: dangling reference
1889   \endrst
1890  */
1891 template <typename Context> class basic_format_args {
1892  public:
1893   using size_type = int;
1894   using format_arg = basic_format_arg<Context>;
1895
1896  private:
1897   // A descriptor that contains information about formatting arguments.
1898   // If the number of arguments is less or equal to max_packed_args then
1899   // argument types are passed in the descriptor. This reduces binary code size
1900   // per formatting function call.
1901   unsigned long long desc_;
1902   union {
1903     // If is_packed() returns true then argument values are stored in values_;
1904     // otherwise they are stored in args_. This is done to improve cache
1905     // locality and reduce compiled code size since storing larger objects
1906     // may require more code (at least on x86-64) even if the same amount of
1907     // data is actually copied to stack. It saves ~10% on the bloat test.
1908     const detail::value<Context>* values_;
1909     const format_arg* args_;
1910   };
1911
1912   constexpr auto is_packed() const -> bool {
1913     return (desc_ & detail::is_unpacked_bit) == 0;
1914   }
1915   auto has_named_args() const -> bool {
1916     return (desc_ & detail::has_named_args_bit) != 0;
1917   }
1918
1919   FMT_CONSTEXPR auto type(int index) const -> detail::type {
1920     int shift = index * detail::packed_arg_bits;
1921     unsigned int mask = (1 << detail::packed_arg_bits) - 1;
1922     return static_cast<detail::type>((desc_ >> shift) & mask);
1923   }
1924
1925   constexpr FMT_INLINE basic_format_args(unsigned long long desc,
1926                                          const detail::value<Context>* values)
1927       : desc_(desc), values_(values) {}
1928   constexpr basic_format_args(unsigned long long desc, const format_arg* args)
1929       : desc_(desc), args_(args) {}
1930
1931  public:
1932   constexpr basic_format_args() : desc_(0), args_(nullptr) {}
1933
1934   /**
1935    \rst
1936    Constructs a `basic_format_args` object from `~fmt::format_arg_store`.
1937    \endrst
1938    */
1939   template <typename... Args>
1940   constexpr FMT_INLINE basic_format_args(
1941       const format_arg_store<Context, Args...>& store)
1942       : basic_format_args(format_arg_store<Context, Args...>::desc,
1943                           store.data_.args()) {}
1944
1945   /**
1946    \rst
1947    Constructs a `basic_format_args` object from
1948    `~fmt::dynamic_format_arg_store`.
1949    \endrst
1950    */
1951   constexpr FMT_INLINE basic_format_args(
1952       const dynamic_format_arg_store<Context>& store)
1953       : basic_format_args(store.get_types(), store.data()) {}
1954
1955   /**
1956    \rst
1957    Constructs a `basic_format_args` object from a dynamic set of arguments.
1958    \endrst
1959    */
1960   constexpr basic_format_args(const format_arg* args, int count)
1961       : basic_format_args(detail::is_unpacked_bit | detail::to_unsigned(count),
1962                           args) {}
1963
1964   /** Returns the argument with the specified id. */
1965   FMT_CONSTEXPR auto get(int id) const -> format_arg {
1966     format_arg arg;
1967     if (!is_packed()) {
1968       if (id < max_size()) arg = args_[id];
1969       return arg;
1970     }
1971     if (id >= detail::max_packed_args) return arg;
1972     arg.type_ = type(id);
1973     if (arg.type_ == detail::type::none_type) return arg;
1974     arg.value_ = values_[id];
1975     return arg;
1976   }
1977
1978   template <typename Char>
1979   auto get(basic_string_view<Char> name) const -> format_arg {
1980     int id = get_id(name);
1981     return id >= 0 ? get(id) : format_arg();
1982   }
1983
1984   template <typename Char>
1985   auto get_id(basic_string_view<Char> name) const -> int {
1986     if (!has_named_args()) return -1;
1987     const auto& named_args =
1988         (is_packed() ? values_[-1] : args_[-1].value_).named_args;
1989     for (size_t i = 0; i < named_args.size; ++i) {
1990       if (named_args.data[i].name == name) return named_args.data[i].id;
1991     }
1992     return -1;
1993   }
1994
1995   auto max_size() const -> int {
1996     unsigned long long max_packed = detail::max_packed_args;
1997     return static_cast<int>(is_packed() ? max_packed
1998                                         : desc_ & ~detail::is_unpacked_bit);
1999   }
2000 };
2001
2002 /** An alias to ``basic_format_args<format_context>``. */
2003 // A separate type would result in shorter symbols but break ABI compatibility
2004 // between clang and gcc on ARM (#1919).
2005 FMT_EXPORT using format_args = basic_format_args<format_context>;
2006
2007 // We cannot use enum classes as bit fields because of a gcc bug, so we put them
2008 // in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414).
2009 // Additionally, if an underlying type is specified, older gcc incorrectly warns
2010 // that the type is too small. Both bugs are fixed in gcc 9.3.
2011 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
2012 #  define FMT_ENUM_UNDERLYING_TYPE(type)
2013 #else
2014 #  define FMT_ENUM_UNDERLYING_TYPE(type) : type
2015 #endif
2016 namespace align {
2017 enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, left, right, center,
2018                                                   numeric};
2019 }
2020 using align_t = align::type;
2021 namespace sign {
2022 enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char){none, minus, plus, space};
2023 }
2024 using sign_t = sign::type;
2025
2026 namespace detail {
2027
2028 // Workaround an array initialization issue in gcc 4.8.
2029 template <typename Char> struct fill_t {
2030  private:
2031   enum { max_size = 4 };
2032   Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
2033   unsigned char size_ = 1;
2034
2035  public:
2036   FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {
2037     auto size = s.size();
2038     FMT_ASSERT(size <= max_size, "invalid fill");
2039     for (size_t i = 0; i < size; ++i) data_[i] = s[i];
2040     size_ = static_cast<unsigned char>(size);
2041   }
2042
2043   constexpr auto size() const -> size_t { return size_; }
2044   constexpr auto data() const -> const Char* { return data_; }
2045
2046   FMT_CONSTEXPR auto operator[](size_t index) -> Char& { return data_[index]; }
2047   FMT_CONSTEXPR auto operator[](size_t index) const -> const Char& {
2048     return data_[index];
2049   }
2050 };
2051 }  // namespace detail
2052
2053 enum class presentation_type : unsigned char {
2054   none,
2055   dec,             // 'd'
2056   oct,             // 'o'
2057   hex_lower,       // 'x'
2058   hex_upper,       // 'X'
2059   bin_lower,       // 'b'
2060   bin_upper,       // 'B'
2061   hexfloat_lower,  // 'a'
2062   hexfloat_upper,  // 'A'
2063   exp_lower,       // 'e'
2064   exp_upper,       // 'E'
2065   fixed_lower,     // 'f'
2066   fixed_upper,     // 'F'
2067   general_lower,   // 'g'
2068   general_upper,   // 'G'
2069   chr,             // 'c'
2070   string,          // 's'
2071   pointer,         // 'p'
2072   debug            // '?'
2073 };
2074
2075 // Format specifiers for built-in and string types.
2076 template <typename Char = char> struct format_specs {
2077   int width;
2078   int precision;
2079   presentation_type type;
2080   align_t align : 4;
2081   sign_t sign : 3;
2082   bool alt : 1;  // Alternate form ('#').
2083   bool localized : 1;
2084   detail::fill_t<Char> fill;
2085
2086   constexpr format_specs()
2087       : width(0),
2088         precision(-1),
2089         type(presentation_type::none),
2090         align(align::none),
2091         sign(sign::none),
2092         alt(false),
2093         localized(false) {}
2094 };
2095
2096 namespace detail {
2097
2098 enum class arg_id_kind { none, index, name };
2099
2100 // An argument reference.
2101 template <typename Char> struct arg_ref {
2102   FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}
2103
2104   FMT_CONSTEXPR explicit arg_ref(int index)
2105       : kind(arg_id_kind::index), val(index) {}
2106   FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)
2107       : kind(arg_id_kind::name), val(name) {}
2108
2109   FMT_CONSTEXPR auto operator=(int idx) -> arg_ref& {
2110     kind = arg_id_kind::index;
2111     val.index = idx;
2112     return *this;
2113   }
2114
2115   arg_id_kind kind;
2116   union value {
2117     FMT_CONSTEXPR value(int idx = 0) : index(idx) {}
2118     FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {}
2119
2120     int index;
2121     basic_string_view<Char> name;
2122   } val;
2123 };
2124
2125 // Format specifiers with width and precision resolved at formatting rather
2126 // than parsing time to allow reusing the same parsed specifiers with
2127 // different sets of arguments (precompilation of format strings).
2128 template <typename Char = char>
2129 struct dynamic_format_specs : format_specs<Char> {
2130   arg_ref<Char> width_ref;
2131   arg_ref<Char> precision_ref;
2132 };
2133
2134 // Converts a character to ASCII. Returns '\0' on conversion failure.
2135 template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
2136 constexpr auto to_ascii(Char c) -> char {
2137   return c <= 0xff ? static_cast<char>(c) : '\0';
2138 }
2139 template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
2140 constexpr auto to_ascii(Char c) -> char {
2141   return c <= 0xff ? static_cast<char>(c) : '\0';
2142 }
2143
2144 // Returns the number of code units in a code point or 1 on error.
2145 template <typename Char>
2146 FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int {
2147   if (const_check(sizeof(Char) != 1)) return 1;
2148   auto c = static_cast<unsigned char>(*begin);
2149   return static_cast<int>((0x3a55000000000000ull >> (2 * (c >> 3))) & 0x3) + 1;
2150 }
2151
2152 // Return the result via the out param to workaround gcc bug 77539.
2153 template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
2154 FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool {
2155   for (out = first; out != last; ++out) {
2156     if (*out == value) return true;
2157   }
2158   return false;
2159 }
2160
2161 template <>
2162 inline auto find<false, char>(const char* first, const char* last, char value,
2163                               const char*& out) -> bool {
2164   out = static_cast<const char*>(
2165       std::memchr(first, value, to_unsigned(last - first)));
2166   return out != nullptr;
2167 }
2168
2169 // Parses the range [begin, end) as an unsigned integer. This function assumes
2170 // that the range is non-empty and the first character is a digit.
2171 template <typename Char>
2172 FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end,
2173                                          int error_value) noexcept -> int {
2174   FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
2175   unsigned value = 0, prev = 0;
2176   auto p = begin;
2177   do {
2178     prev = value;
2179     value = value * 10 + unsigned(*p - '0');
2180     ++p;
2181   } while (p != end && '0' <= *p && *p <= '9');
2182   auto num_digits = p - begin;
2183   begin = p;
2184   if (num_digits <= std::numeric_limits<int>::digits10)
2185     return static_cast<int>(value);
2186   // Check for overflow.
2187   const unsigned max = to_unsigned((std::numeric_limits<int>::max)());
2188   return num_digits == std::numeric_limits<int>::digits10 + 1 &&
2189                  prev * 10ull + unsigned(p[-1] - '0') <= max
2190              ? static_cast<int>(value)
2191              : error_value;
2192 }
2193
2194 FMT_CONSTEXPR inline auto parse_align(char c) -> align_t {
2195   switch (c) {
2196   case '<':
2197     return align::left;
2198   case '>':
2199     return align::right;
2200   case '^':
2201     return align::center;
2202   }
2203   return align::none;
2204 }
2205
2206 template <typename Char> constexpr auto is_name_start(Char c) -> bool {
2207   return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || c == '_';
2208 }
2209
2210 template <typename Char, typename Handler>
2211 FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end,
2212                                    Handler&& handler) -> const Char* {
2213   Char c = *begin;
2214   if (c >= '0' && c <= '9') {
2215     int index = 0;
2216     constexpr int max = (std::numeric_limits<int>::max)();
2217     if (c != '0')
2218       index = parse_nonnegative_int(begin, end, max);
2219     else
2220       ++begin;
2221     if (begin == end || (*begin != '}' && *begin != ':'))
2222       throw_format_error("invalid format string");
2223     else
2224       handler.on_index(index);
2225     return begin;
2226   }
2227   if (!is_name_start(c)) {
2228     throw_format_error("invalid format string");
2229     return begin;
2230   }
2231   auto it = begin;
2232   do {
2233     ++it;
2234   } while (it != end && (is_name_start(*it) || ('0' <= *it && *it <= '9')));
2235   handler.on_name({begin, to_unsigned(it - begin)});
2236   return it;
2237 }
2238
2239 template <typename Char, typename Handler>
2240 FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end,
2241                                            Handler&& handler) -> const Char* {
2242   FMT_ASSERT(begin != end, "");
2243   Char c = *begin;
2244   if (c != '}' && c != ':') return do_parse_arg_id(begin, end, handler);
2245   handler.on_auto();
2246   return begin;
2247 }
2248
2249 template <typename Char> struct dynamic_spec_id_handler {
2250   basic_format_parse_context<Char>& ctx;
2251   arg_ref<Char>& ref;
2252
2253   FMT_CONSTEXPR void on_auto() {
2254     int id = ctx.next_arg_id();
2255     ref = arg_ref<Char>(id);
2256     ctx.check_dynamic_spec(id);
2257   }
2258   FMT_CONSTEXPR void on_index(int id) {
2259     ref = arg_ref<Char>(id);
2260     ctx.check_arg_id(id);
2261     ctx.check_dynamic_spec(id);
2262   }
2263   FMT_CONSTEXPR void on_name(basic_string_view<Char> id) {
2264     ref = arg_ref<Char>(id);
2265     ctx.check_arg_id(id);
2266   }
2267 };
2268
2269 // Parses [integer | "{" [arg_id] "}"].
2270 template <typename Char>
2271 FMT_CONSTEXPR auto parse_dynamic_spec(const Char* begin, const Char* end,
2272                                       int& value, arg_ref<Char>& ref,
2273                                       basic_format_parse_context<Char>& ctx)
2274     -> const Char* {
2275   FMT_ASSERT(begin != end, "");
2276   if ('0' <= *begin && *begin <= '9') {
2277     int val = parse_nonnegative_int(begin, end, -1);
2278     if (val != -1)
2279       value = val;
2280     else
2281       throw_format_error("number is too big");
2282   } else if (*begin == '{') {
2283     ++begin;
2284     auto handler = dynamic_spec_id_handler<Char>{ctx, ref};
2285     if (begin != end) begin = parse_arg_id(begin, end, handler);
2286     if (begin != end && *begin == '}') return ++begin;
2287     throw_format_error("invalid format string");
2288   }
2289   return begin;
2290 }
2291
2292 template <typename Char>
2293 FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end,
2294                                    int& value, arg_ref<Char>& ref,
2295                                    basic_format_parse_context<Char>& ctx)
2296     -> const Char* {
2297   ++begin;
2298   if (begin == end || *begin == '}') {
2299     throw_format_error("invalid precision");
2300     return begin;
2301   }
2302   return parse_dynamic_spec(begin, end, value, ref, ctx);
2303 }
2304
2305 enum class state { start, align, sign, hash, zero, width, precision, locale };
2306
2307 // Parses standard format specifiers.
2308 template <typename Char>
2309 FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(
2310     const Char* begin, const Char* end, dynamic_format_specs<Char>& specs,
2311     basic_format_parse_context<Char>& ctx, type arg_type) -> const Char* {
2312   auto c = '\0';
2313   if (end - begin > 1) {
2314     auto next = to_ascii(begin[1]);
2315     c = parse_align(next) == align::none ? to_ascii(*begin) : '\0';
2316   } else {
2317     if (begin == end) return begin;
2318     c = to_ascii(*begin);
2319   }
2320
2321   struct {
2322     state current_state = state::start;
2323     FMT_CONSTEXPR void operator()(state s, bool valid = true) {
2324       if (current_state >= s || !valid)
2325         throw_format_error("invalid format specifier");
2326       current_state = s;
2327     }
2328   } enter_state;
2329
2330   using pres = presentation_type;
2331   constexpr auto integral_set = sint_set | uint_set | bool_set | char_set;
2332   struct {
2333     const Char*& begin;
2334     dynamic_format_specs<Char>& specs;
2335     type arg_type;
2336
2337     FMT_CONSTEXPR auto operator()(pres pres_type, int set) -> const Char* {
2338       if (!in(arg_type, set)) {
2339         if (arg_type == type::none_type) return begin;
2340         throw_format_error("invalid format specifier");
2341       }
2342       specs.type = pres_type;
2343       return begin + 1;
2344     }
2345   } parse_presentation_type{begin, specs, arg_type};
2346
2347   for (;;) {
2348     switch (c) {
2349     case '<':
2350     case '>':
2351     case '^':
2352       enter_state(state::align);
2353       specs.align = parse_align(c);
2354       ++begin;
2355       break;
2356     case '+':
2357     case '-':
2358     case ' ':
2359       if (arg_type == type::none_type) return begin;
2360       enter_state(state::sign, in(arg_type, sint_set | float_set));
2361       switch (c) {
2362       case '+':
2363         specs.sign = sign::plus;
2364         break;
2365       case '-':
2366         specs.sign = sign::minus;
2367         break;
2368       case ' ':
2369         specs.sign = sign::space;
2370         break;
2371       }
2372       ++begin;
2373       break;
2374     case '#':
2375       if (arg_type == type::none_type) return begin;
2376       enter_state(state::hash, is_arithmetic_type(arg_type));
2377       specs.alt = true;
2378       ++begin;
2379       break;
2380     case '0':
2381       enter_state(state::zero);
2382       if (!is_arithmetic_type(arg_type)) {
2383         if (arg_type == type::none_type) return begin;
2384         throw_format_error("format specifier requires numeric argument");
2385       }
2386       if (specs.align == align::none) {
2387         // Ignore 0 if align is specified for compatibility with std::format.
2388         specs.align = align::numeric;
2389         specs.fill[0] = Char('0');
2390       }
2391       ++begin;
2392       break;
2393     case '1':
2394     case '2':
2395     case '3':
2396     case '4':
2397     case '5':
2398     case '6':
2399     case '7':
2400     case '8':
2401     case '9':
2402     case '{':
2403       enter_state(state::width);
2404       begin = parse_dynamic_spec(begin, end, specs.width, specs.width_ref, ctx);
2405       break;
2406     case '.':
2407       if (arg_type == type::none_type) return begin;
2408       enter_state(state::precision,
2409                   in(arg_type, float_set | string_set | cstring_set));
2410       begin = parse_precision(begin, end, specs.precision, specs.precision_ref,
2411                               ctx);
2412       break;
2413     case 'L':
2414       if (arg_type == type::none_type) return begin;
2415       enter_state(state::locale, is_arithmetic_type(arg_type));
2416       specs.localized = true;
2417       ++begin;
2418       break;
2419     case 'd':
2420       return parse_presentation_type(pres::dec, integral_set);
2421     case 'o':
2422       return parse_presentation_type(pres::oct, integral_set);
2423     case 'x':
2424       return parse_presentation_type(pres::hex_lower, integral_set);
2425     case 'X':
2426       return parse_presentation_type(pres::hex_upper, integral_set);
2427     case 'b':
2428       return parse_presentation_type(pres::bin_lower, integral_set);
2429     case 'B':
2430       return parse_presentation_type(pres::bin_upper, integral_set);
2431     case 'a':
2432       return parse_presentation_type(pres::hexfloat_lower, float_set);
2433     case 'A':
2434       return parse_presentation_type(pres::hexfloat_upper, float_set);
2435     case 'e':
2436       return parse_presentation_type(pres::exp_lower, float_set);
2437     case 'E':
2438       return parse_presentation_type(pres::exp_upper, float_set);
2439     case 'f':
2440       return parse_presentation_type(pres::fixed_lower, float_set);
2441     case 'F':
2442       return parse_presentation_type(pres::fixed_upper, float_set);
2443     case 'g':
2444       return parse_presentation_type(pres::general_lower, float_set);
2445     case 'G':
2446       return parse_presentation_type(pres::general_upper, float_set);
2447     case 'c':
2448       if (arg_type == type::bool_type)
2449         throw_format_error("invalid format specifier");
2450       return parse_presentation_type(pres::chr, integral_set);
2451     case 's':
2452       return parse_presentation_type(pres::string,
2453                                      bool_set | string_set | cstring_set);
2454     case 'p':
2455       return parse_presentation_type(pres::pointer, pointer_set | cstring_set);
2456     case '?':
2457       return parse_presentation_type(pres::debug,
2458                                      char_set | string_set | cstring_set);
2459     case '}':
2460       return begin;
2461     default: {
2462       if (*begin == '}') return begin;
2463       // Parse fill and alignment.
2464       auto fill_end = begin + code_point_length(begin);
2465       if (end - fill_end <= 0) {
2466         throw_format_error("invalid format specifier");
2467         return begin;
2468       }
2469       if (*begin == '{') {
2470         throw_format_error("invalid fill character '{'");
2471         return begin;
2472       }
2473       auto align = parse_align(to_ascii(*fill_end));
2474       enter_state(state::align, align != align::none);
2475       specs.fill = {begin, to_unsigned(fill_end - begin)};
2476       specs.align = align;
2477       begin = fill_end + 1;
2478     }
2479     }
2480     if (begin == end) return begin;
2481     c = to_ascii(*begin);
2482   }
2483 }
2484
2485 template <typename Char, typename Handler>
2486 FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end,
2487                                            Handler&& handler) -> const Char* {
2488   struct id_adapter {
2489     Handler& handler;
2490     int arg_id;
2491
2492     FMT_CONSTEXPR void on_auto() { arg_id = handler.on_arg_id(); }
2493     FMT_CONSTEXPR void on_index(int id) { arg_id = handler.on_arg_id(id); }
2494     FMT_CONSTEXPR void on_name(basic_string_view<Char> id) {
2495       arg_id = handler.on_arg_id(id);
2496     }
2497   };
2498
2499   ++begin;
2500   if (begin == end) return handler.on_error("invalid format string"), end;
2501   if (*begin == '}') {
2502     handler.on_replacement_field(handler.on_arg_id(), begin);
2503   } else if (*begin == '{') {
2504     handler.on_text(begin, begin + 1);
2505   } else {
2506     auto adapter = id_adapter{handler, 0};
2507     begin = parse_arg_id(begin, end, adapter);
2508     Char c = begin != end ? *begin : Char();
2509     if (c == '}') {
2510       handler.on_replacement_field(adapter.arg_id, begin);
2511     } else if (c == ':') {
2512       begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
2513       if (begin == end || *begin != '}')
2514         return handler.on_error("unknown format specifier"), end;
2515     } else {
2516       return handler.on_error("missing '}' in format string"), end;
2517     }
2518   }
2519   return begin + 1;
2520 }
2521
2522 template <bool IS_CONSTEXPR, typename Char, typename Handler>
2523 FMT_CONSTEXPR FMT_INLINE void parse_format_string(
2524     basic_string_view<Char> format_str, Handler&& handler) {
2525   auto begin = format_str.data();
2526   auto end = begin + format_str.size();
2527   if (end - begin < 32) {
2528     // Use a simple loop instead of memchr for small strings.
2529     const Char* p = begin;
2530     while (p != end) {
2531       auto c = *p++;
2532       if (c == '{') {
2533         handler.on_text(begin, p - 1);
2534         begin = p = parse_replacement_field(p - 1, end, handler);
2535       } else if (c == '}') {
2536         if (p == end || *p != '}')
2537           return handler.on_error("unmatched '}' in format string");
2538         handler.on_text(begin, p);
2539         begin = ++p;
2540       }
2541     }
2542     handler.on_text(begin, end);
2543     return;
2544   }
2545   struct writer {
2546     FMT_CONSTEXPR void operator()(const Char* from, const Char* to) {
2547       if (from == to) return;
2548       for (;;) {
2549         const Char* p = nullptr;
2550         if (!find<IS_CONSTEXPR>(from, to, Char('}'), p))
2551           return handler_.on_text(from, to);
2552         ++p;
2553         if (p == to || *p != '}')
2554           return handler_.on_error("unmatched '}' in format string");
2555         handler_.on_text(from, p);
2556         from = p + 1;
2557       }
2558     }
2559     Handler& handler_;
2560   } write = {handler};
2561   while (begin != end) {
2562     // Doing two passes with memchr (one for '{' and another for '}') is up to
2563     // 2.5x faster than the naive one-pass implementation on big format strings.
2564     const Char* p = begin;
2565     if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p))
2566       return write(begin, end);
2567     write(begin, p);
2568     begin = parse_replacement_field(p, end, handler);
2569   }
2570 }
2571
2572 template <typename T, bool = is_named_arg<T>::value> struct strip_named_arg {
2573   using type = T;
2574 };
2575 template <typename T> struct strip_named_arg<T, true> {
2576   using type = remove_cvref_t<decltype(T::value)>;
2577 };
2578
2579 template <typename T, typename ParseContext>
2580 FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
2581     -> decltype(ctx.begin()) {
2582   using char_type = typename ParseContext::char_type;
2583   using context = buffer_context<char_type>;
2584   using mapped_type = conditional_t<
2585       mapped_type_constant<T, context>::value != type::custom_type,
2586       decltype(arg_mapper<context>().map(std::declval<const T&>())),
2587       typename strip_named_arg<T>::type>;
2588 #if defined(__cpp_if_constexpr)
2589   if constexpr (std::is_default_constructible<
2590                     formatter<mapped_type, char_type>>::value) {
2591     return formatter<mapped_type, char_type>().parse(ctx);
2592   } else {
2593     type_is_unformattable_for<T, char_type> _;
2594     return ctx.begin();
2595   }
2596 #else
2597   return formatter<mapped_type, char_type>().parse(ctx);
2598 #endif
2599 }
2600
2601 // Checks char specs and returns true iff the presentation type is char-like.
2602 template <typename Char>
2603 FMT_CONSTEXPR auto check_char_specs(const format_specs<Char>& specs) -> bool {
2604   if (specs.type != presentation_type::none &&
2605       specs.type != presentation_type::chr &&
2606       specs.type != presentation_type::debug) {
2607     return false;
2608   }
2609   if (specs.align == align::numeric || specs.sign != sign::none || specs.alt)
2610     throw_format_error("invalid format specifier for char");
2611   return true;
2612 }
2613
2614 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
2615 template <int N, typename T, typename... Args, typename Char>
2616 constexpr auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
2617   if constexpr (is_statically_named_arg<T>()) {
2618     if (name == T::name) return N;
2619   }
2620   if constexpr (sizeof...(Args) > 0)
2621     return get_arg_index_by_name<N + 1, Args...>(name);
2622   (void)name;  // Workaround an MSVC bug about "unused" parameter.
2623   return -1;
2624 }
2625 #endif
2626
2627 template <typename... Args, typename Char>
2628 FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view<Char> name) -> int {
2629 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
2630   if constexpr (sizeof...(Args) > 0)
2631     return get_arg_index_by_name<0, Args...>(name);
2632 #endif
2633   (void)name;
2634   return -1;
2635 }
2636
2637 template <typename Char, typename... Args> class format_string_checker {
2638  private:
2639   using parse_context_type = compile_parse_context<Char>;
2640   static constexpr int num_args = sizeof...(Args);
2641
2642   // Format specifier parsing function.
2643   // In the future basic_format_parse_context will replace compile_parse_context
2644   // here and will use is_constant_evaluated and downcasting to access the data
2645   // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1.
2646   using parse_func = const Char* (*)(parse_context_type&);
2647
2648   type types_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
2649   parse_context_type context_;
2650   parse_func parse_funcs_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
2651
2652  public:
2653   explicit FMT_CONSTEXPR format_string_checker(basic_string_view<Char> fmt)
2654       : types_{mapped_type_constant<Args, buffer_context<Char>>::value...},
2655         context_(fmt, num_args, types_),
2656         parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
2657
2658   FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
2659
2660   FMT_CONSTEXPR auto on_arg_id() -> int { return context_.next_arg_id(); }
2661   FMT_CONSTEXPR auto on_arg_id(int id) -> int {
2662     return context_.check_arg_id(id), id;
2663   }
2664   FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
2665 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
2666     auto index = get_arg_index_by_name<Args...>(id);
2667     if (index < 0) on_error("named argument is not found");
2668     return index;
2669 #else
2670     (void)id;
2671     on_error("compile-time checks for named arguments require C++20 support");
2672     return 0;
2673 #endif
2674   }
2675
2676   FMT_CONSTEXPR void on_replacement_field(int id, const Char* begin) {
2677     on_format_specs(id, begin, begin);  // Call parse() on empty specs.
2678   }
2679
2680   FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*)
2681       -> const Char* {
2682     context_.advance_to(begin);
2683     // id >= 0 check is a workaround for gcc 10 bug (#2065).
2684     return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin;
2685   }
2686
2687   FMT_CONSTEXPR void on_error(const char* message) {
2688     throw_format_error(message);
2689   }
2690 };
2691
2692 // Reports a compile-time error if S is not a valid format string.
2693 template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
2694 FMT_INLINE void check_format_string(const S&) {
2695 #ifdef FMT_ENFORCE_COMPILE_STRING
2696   static_assert(is_compile_string<S>::value,
2697                 "FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
2698                 "FMT_STRING.");
2699 #endif
2700 }
2701 template <typename... Args, typename S,
2702           FMT_ENABLE_IF(is_compile_string<S>::value)>
2703 void check_format_string(S format_str) {
2704   using char_t = typename S::char_type;
2705   FMT_CONSTEXPR auto s = basic_string_view<char_t>(format_str);
2706   using checker = format_string_checker<char_t, remove_cvref_t<Args>...>;
2707   FMT_CONSTEXPR bool error = (parse_format_string<true>(s, checker(s)), true);
2708   ignore_unused(error);
2709 }
2710
2711 template <typename Char = char> struct vformat_args {
2712   using type = basic_format_args<
2713       basic_format_context<std::back_insert_iterator<buffer<Char>>, Char>>;
2714 };
2715 template <> struct vformat_args<char> {
2716   using type = format_args;
2717 };
2718
2719 // Use vformat_args and avoid type_identity to keep symbols short.
2720 template <typename Char>
2721 void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt,
2722                 typename vformat_args<Char>::type args, locale_ref loc = {});
2723
2724 FMT_API void vprint_mojibake(std::FILE*, string_view, format_args);
2725 #ifndef _WIN32
2726 inline void vprint_mojibake(std::FILE*, string_view, format_args) {}
2727 #endif
2728 }  // namespace detail
2729
2730 FMT_BEGIN_EXPORT
2731
2732 // A formatter specialization for natively supported types.
2733 template <typename T, typename Char>
2734 struct formatter<T, Char,
2735                  enable_if_t<detail::type_constant<T, Char>::value !=
2736                              detail::type::custom_type>> {
2737  private:
2738   detail::dynamic_format_specs<Char> specs_;
2739
2740  public:
2741   template <typename ParseContext>
2742   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
2743     auto type = detail::type_constant<T, Char>::value;
2744     auto end =
2745         detail::parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, type);
2746     if (type == detail::type::char_type) detail::check_char_specs(specs_);
2747     return end;
2748   }
2749
2750   template <detail::type U = detail::type_constant<T, Char>::value,
2751             FMT_ENABLE_IF(U == detail::type::string_type ||
2752                           U == detail::type::cstring_type ||
2753                           U == detail::type::char_type)>
2754   FMT_CONSTEXPR void set_debug_format(bool set = true) {
2755     specs_.type = set ? presentation_type::debug : presentation_type::none;
2756   }
2757
2758   template <typename FormatContext>
2759   FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
2760       -> decltype(ctx.out());
2761 };
2762
2763 template <typename Char = char> struct runtime_format_string {
2764   basic_string_view<Char> str;
2765 };
2766
2767 /** A compile-time format string. */
2768 template <typename Char, typename... Args> class basic_format_string {
2769  private:
2770   basic_string_view<Char> str_;
2771
2772  public:
2773   template <typename S,
2774             FMT_ENABLE_IF(
2775                 std::is_convertible<const S&, basic_string_view<Char>>::value)>
2776   FMT_CONSTEVAL FMT_INLINE basic_format_string(const S& s) : str_(s) {
2777     static_assert(
2778         detail::count<
2779             (std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
2780              std::is_reference<Args>::value)...>() == 0,
2781         "passing views as lvalues is disallowed");
2782 #ifdef FMT_HAS_CONSTEVAL
2783     if constexpr (detail::count_named_args<Args...>() ==
2784                   detail::count_statically_named_args<Args...>()) {
2785       using checker =
2786           detail::format_string_checker<Char, remove_cvref_t<Args>...>;
2787       detail::parse_format_string<true>(str_, checker(s));
2788     }
2789 #else
2790     detail::check_format_string<Args...>(s);
2791 #endif
2792   }
2793   basic_format_string(runtime_format_string<Char> fmt) : str_(fmt.str) {}
2794
2795   FMT_INLINE operator basic_string_view<Char>() const { return str_; }
2796   FMT_INLINE auto get() const -> basic_string_view<Char> { return str_; }
2797 };
2798
2799 #if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
2800 // Workaround broken conversion on older gcc.
2801 template <typename...> using format_string = string_view;
2802 inline auto runtime(string_view s) -> string_view { return s; }
2803 #else
2804 template <typename... Args>
2805 using format_string = basic_format_string<char, type_identity_t<Args>...>;
2806 /**
2807   \rst
2808   Creates a runtime format string.
2809
2810   **Example**::
2811
2812     // Check format string at runtime instead of compile-time.
2813     fmt::print(fmt::runtime("{:d}"), "I am not a number");
2814   \endrst
2815  */
2816 inline auto runtime(string_view s) -> runtime_format_string<> { return {{s}}; }
2817 #endif
2818
2819 FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
2820
2821 /**
2822   \rst
2823   Formats ``args`` according to specifications in ``fmt`` and returns the result
2824   as a string.
2825
2826   **Example**::
2827
2828     #include <fmt/core.h>
2829     std::string message = fmt::format("The answer is {}.", 42);
2830   \endrst
2831 */
2832 template <typename... T>
2833 FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args)
2834     -> std::string {
2835   return vformat(fmt, fmt::make_format_args(args...));
2836 }
2837
2838 /** Formats a string and writes the output to ``out``. */
2839 template <typename OutputIt,
2840           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2841 auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt {
2842   auto&& buf = detail::get_buffer<char>(out);
2843   detail::vformat_to(buf, fmt, args, {});
2844   return detail::get_iterator(buf, out);
2845 }
2846
2847 /**
2848  \rst
2849  Formats ``args`` according to specifications in ``fmt``, writes the result to
2850  the output iterator ``out`` and returns the iterator past the end of the output
2851  range. `format_to` does not append a terminating null character.
2852
2853  **Example**::
2854
2855    auto out = std::vector<char>();
2856    fmt::format_to(std::back_inserter(out), "{}", 42);
2857  \endrst
2858  */
2859 template <typename OutputIt, typename... T,
2860           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2861 FMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args)
2862     -> OutputIt {
2863   return vformat_to(out, fmt, fmt::make_format_args(args...));
2864 }
2865
2866 template <typename OutputIt> struct format_to_n_result {
2867   /** Iterator past the end of the output range. */
2868   OutputIt out;
2869   /** Total (not truncated) output size. */
2870   size_t size;
2871 };
2872
2873 template <typename OutputIt, typename... T,
2874           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2875 auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)
2876     -> format_to_n_result<OutputIt> {
2877   using traits = detail::fixed_buffer_traits;
2878   auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
2879   detail::vformat_to(buf, fmt, args, {});
2880   return {buf.out(), buf.count()};
2881 }
2882
2883 /**
2884   \rst
2885   Formats ``args`` according to specifications in ``fmt``, writes up to ``n``
2886   characters of the result to the output iterator ``out`` and returns the total
2887   (not truncated) output size and the iterator past the end of the output range.
2888   `format_to_n` does not append a terminating null character.
2889   \endrst
2890  */
2891 template <typename OutputIt, typename... T,
2892           FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
2893 FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string<T...> fmt,
2894                             T&&... args) -> format_to_n_result<OutputIt> {
2895   return vformat_to_n(out, n, fmt, fmt::make_format_args(args...));
2896 }
2897
2898 /** Returns the number of chars in the output of ``format(fmt, args...)``. */
2899 template <typename... T>
2900 FMT_NODISCARD FMT_INLINE auto formatted_size(format_string<T...> fmt,
2901                                              T&&... args) -> size_t {
2902   auto buf = detail::counting_buffer<>();
2903   detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...), {});
2904   return buf.count();
2905 }
2906
2907 FMT_API void vprint(string_view fmt, format_args args);
2908 FMT_API void vprint(std::FILE* f, string_view fmt, format_args args);
2909
2910 /**
2911   \rst
2912   Formats ``args`` according to specifications in ``fmt`` and writes the output
2913   to ``stdout``.
2914
2915   **Example**::
2916
2917     fmt::print("Elapsed time: {0:.2f} seconds", 1.23);
2918   \endrst
2919  */
2920 template <typename... T>
2921 FMT_INLINE void print(format_string<T...> fmt, T&&... args) {
2922   const auto& vargs = fmt::make_format_args(args...);
2923   return detail::is_utf8() ? vprint(fmt, vargs)
2924                            : detail::vprint_mojibake(stdout, fmt, vargs);
2925 }
2926
2927 /**
2928   \rst
2929   Formats ``args`` according to specifications in ``fmt`` and writes the
2930   output to the file ``f``.
2931
2932   **Example**::
2933
2934     fmt::print(stderr, "Don't {}!", "panic");
2935   \endrst
2936  */
2937 template <typename... T>
2938 FMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args) {
2939   const auto& vargs = fmt::make_format_args(args...);
2940   return detail::is_utf8() ? vprint(f, fmt, vargs)
2941                            : detail::vprint_mojibake(f, fmt, vargs);
2942 }
2943
2944 /**
2945   Formats ``args`` according to specifications in ``fmt`` and writes the
2946   output to the file ``f`` followed by a newline.
2947  */
2948 template <typename... T>
2949 FMT_INLINE void println(std::FILE* f, format_string<T...> fmt, T&&... args) {
2950   return fmt::print(f, "{}\n", fmt::format(fmt, std::forward<T>(args)...));
2951 }
2952
2953 /**
2954   Formats ``args`` according to specifications in ``fmt`` and writes the output
2955   to ``stdout`` followed by a newline.
2956  */
2957 template <typename... T>
2958 FMT_INLINE void println(format_string<T...> fmt, T&&... args) {
2959   return fmt::println(stdout, fmt, std::forward<T>(args)...);
2960 }
2961
2962 FMT_END_EXPORT
2963 FMT_GCC_PRAGMA("GCC pop_options")
2964 FMT_END_NAMESPACE
2965
2966 #ifdef FMT_HEADER_ONLY
2967 #  include "format.h"
2968 #endif
2969 #endif  // FMT_CORE_H_