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