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