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