Photon 1.0.0
Loading...
Searching...
No Matches
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 { \
217 inline namespace v9 \
218 {
219#define FMT_END_NAMESPACE \
220 } \
221 }
222#endif
223
224#ifndef FMT_MODULE_EXPORT
225#define FMT_MODULE_EXPORT
226#define FMT_MODULE_EXPORT_BEGIN
227#define FMT_MODULE_EXPORT_END
228#define FMT_BEGIN_DETAIL_NAMESPACE \
229 namespace detail \
230 {
231#define FMT_END_DETAIL_NAMESPACE }
232#endif
233
234#if !defined(FMT_HEADER_ONLY) && defined(_WIN32)
235#define FMT_CLASS_API FMT_MSC_WARNING(suppress : 4275)
236#ifdef FMT_EXPORT
237#define FMT_API __declspec(dllexport)
238#elif defined(FMT_SHARED)
239#define FMT_API __declspec(dllimport)
240#endif
241#else
242#define FMT_CLASS_API
243#if defined(FMT_EXPORT) || defined(FMT_SHARED)
244#if defined(__GNUC__) || defined(__clang__)
245#define FMT_API __attribute__((visibility("default")))
246#endif
247#endif
248#endif
249#ifndef FMT_API
250#define FMT_API
251#endif
252
253// libc++ supports string_view in pre-c++17.
254#if FMT_HAS_INCLUDE(<string_view>) && \
255 (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
256#include <string_view>
257#define FMT_USE_STRING_VIEW
258#elif FMT_HAS_INCLUDE("experimental/string_view") && FMT_CPLUSPLUS >= 201402L
259#include <experimental/string_view>
260#define FMT_USE_EXPERIMENTAL_STRING_VIEW
261#endif
262
263#ifndef FMT_UNICODE
264#define FMT_UNICODE !FMT_MSC_VERSION
265#endif
266
267#ifndef FMT_CONSTEVAL
268#if ((FMT_GCC_VERSION >= 1000 || FMT_CLANG_VERSION >= 1101) && \
269 FMT_CPLUSPLUS >= 202002L && !defined(__apple_build_version__)) || \
270 (defined(__cpp_consteval) && \
271 (!FMT_MSC_VERSION || _MSC_FULL_VER >= 193030704))
272// consteval is broken in MSVC before VS2022 and Apple clang 13.
273#define FMT_CONSTEVAL consteval
274#define FMT_HAS_CONSTEVAL
275#else
276#define FMT_CONSTEVAL
277#endif
278#endif
279
280#ifndef FMT_USE_NONTYPE_TEMPLATE_ARGS
281#if defined(__cpp_nontype_template_args) && \
282 ((FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L) || \
283 __cpp_nontype_template_args >= 201911L) && \
284 !defined(__NVCOMPILER)
285#define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
286#else
287#define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
288#endif
289#endif
290
291// Enable minimal optimizations for more compact code in debug mode.
292FMT_GCC_PRAGMA("GCC push_options")
293#if !defined(__OPTIMIZE__) && !defined(__NVCOMPILER)
294FMT_GCC_PRAGMA("GCC optimize(\"Og\")")
295#endif
296
299
300// Implementations of enable_if_t and other metafunctions for older systems.
301template <bool B, typename T = void>
302using enable_if_t = typename std::enable_if<B, T>::type;
303template <bool B, typename T, typename F>
304using conditional_t = typename std::conditional<B, T, F>::type;
305template <bool B>
306using bool_constant = std::integral_constant<bool, B>;
307template <typename T>
308using remove_reference_t = typename std::remove_reference<T>::type;
309template <typename T>
310using remove_const_t = typename std::remove_const<T>::type;
311template <typename T>
312using remove_cvref_t = typename std::remove_cv<remove_reference_t<T>>::type;
313template <typename T>
315{
316 using type = T;
317};
318template <typename T>
320template <typename T>
321using underlying_t = typename std::underlying_type<T>::type;
322
323template <typename...>
324struct disjunction : std::false_type
325{
326};
327template <typename P>
329{
330};
331template <typename P1, typename... Pn>
332struct disjunction<P1, Pn...>
333 : conditional_t<bool(P1::value), P1, disjunction<Pn...>>
334{
335};
336
337template <typename...>
338struct conjunction : std::true_type
339{
340};
341template <typename P>
343{
344};
345template <typename P1, typename... Pn>
346struct conjunction<P1, Pn...>
347 : conditional_t<bool(P1::value), conjunction<Pn...>, P1>
348{
349};
350
352{
353 constexpr monostate()
354 {
355 }
356};
357
358// An enable_if helper to be used in template parameters which results in much
359// shorter symbols: https://godbolt.org/z/sWw4vP. Extra parentheses are needed
360// to workaround a bug in MSVC 2019 (see #1140 and #1186).
361#ifdef FMT_DOC
362#define FMT_ENABLE_IF(...)
363#else
364#define FMT_ENABLE_IF(...) enable_if_t<(__VA_ARGS__), int> = 0
365#endif
366
368
369// Suppresses "unused variable" warnings with the method described in
370// https://herbsutter.com/2009/10/18/mailbag-shutting-up-compiler-warnings/.
371// (void)var does not work on many Intel compilers.
372template <typename... T>
374{
375}
376
378 bool default_value = false) noexcept -> bool
379{
380#ifdef __cpp_lib_is_constant_evaluated
381 ignore_unused(default_value);
382 return std::is_constant_evaluated();
383#else
384 return default_value;
385#endif
386}
387
388// Suppresses "conditional expression is constant" warnings.
389template <typename T>
390constexpr FMT_INLINE auto const_check(T value) -> T
391{
392 return value;
393}
394
395FMT_NORETURN FMT_API void assert_fail(const char* file, int line, const char* message);
396
397#ifndef FMT_ASSERT
398#ifdef NDEBUG
399// FMT_ASSERT is not empty to avoid -Wempty-body.
400#define FMT_ASSERT(condition, message) \
401 ::fmt::detail::ignore_unused((condition), (message))
402#else
403#define FMT_ASSERT(condition, message) \
404 ((condition) /* void() fails with -Winvalid-constexpr on clang 4.0.1 */ \
405 ? (void)0 \
406 : ::fmt::detail::assert_fail(__FILE__, __LINE__, (message)))
407#endif
408#endif
409
410#if defined(FMT_USE_STRING_VIEW)
411template <typename Char>
412using std_string_view = std::basic_string_view<Char>;
413#elif defined(FMT_USE_EXPERIMENTAL_STRING_VIEW)
414template <typename Char>
415using std_string_view = std::experimental::basic_string_view<Char>;
416#else
417template <typename T>
419{
420};
421#endif
422
423#ifdef FMT_USE_INT128
424// Do nothing.
425#elif defined(__SIZEOF_INT128__) && !defined(__NVCC__) && \
426 !(FMT_CLANG_VERSION && FMT_MSC_VERSION)
427#define FMT_USE_INT128 1
428using int128_opt = __int128_t; // An optional native 128-bit integer.
429using uint128_opt = __uint128_t;
430template <typename T>
431inline auto convert_for_visit(T value) -> T
432{
433 return value;
434}
435#else
436#define FMT_USE_INT128 0
437#endif
438#if !FMT_USE_INT128
439enum class int128_opt
440{
441};
442enum class uint128_opt
443{
444};
445// Reduce template instantiations.
446template <typename T>
448{
449 return {};
450}
451#endif
452
453// Casts a nonnegative integer to unsigned.
454template <typename Int>
456 typename std::make_unsigned<Int>::type
457{
458 FMT_ASSERT(std::is_unsigned<Int>::value || value >= 0, "negative value");
459 return static_cast<typename std::make_unsigned<Int>::type>(value);
460}
461
462FMT_MSC_WARNING(suppress : 4566)
463constexpr unsigned char micro[] = "\u00B5";
464
465constexpr auto is_utf8() -> bool
466{
467 // Avoid buggy sign extensions in MSVC's constant evaluation mode (#2297).
468 using uchar = unsigned char;
469 return FMT_UNICODE || (sizeof(micro) == 3 && uchar(micro[0]) == 0xC2 &&
470 uchar(micro[1]) == 0xB5);
471}
473
481template <typename Char>
483{
484private:
485 const Char* data_;
486 size_t size_;
487
488public:
489 using value_type = Char;
490 using iterator = const Char*;
491
492 constexpr basic_string_view() noexcept
493 : data_(nullptr), size_(0)
494 {
495 }
496
498 constexpr basic_string_view(const Char* s, size_t count) noexcept
499 : data_(s), size_(count)
500 {
501 }
502
511 basic_string_view(const Char* s)
512 : data_(s),
513 size_(detail::const_check(std::is_same<Char, char>::value &&
515 ? std::strlen(reinterpret_cast<const char*>(s))
516 : std::char_traits<Char>::length(s))
517 {
518 }
519
521 template <typename Traits, typename Alloc>
523 const std::basic_string<Char, Traits, Alloc>& s) noexcept
524 : data_(s.data()), size_(s.size())
525 {
526 }
527
528 template <typename S, FMT_ENABLE_IF(std::is_same<S, detail::std_string_view<Char>>::value)>
530 : data_(s.data()), size_(s.size())
531 {
532 }
533
535 constexpr auto data() const noexcept -> const Char*
536 {
537 return data_;
538 }
539
541 constexpr auto size() const noexcept -> size_t
542 {
543 return size_;
544 }
545
546 constexpr auto begin() const noexcept -> iterator
547 {
548 return data_;
549 }
550 constexpr auto end() const noexcept -> iterator
551 {
552 return data_ + size_;
553 }
554
555 constexpr auto operator[](size_t pos) const noexcept -> const Char&
556 {
557 return data_[pos];
558 }
559
560 FMT_CONSTEXPR void remove_prefix(size_t n) noexcept
561 {
562 data_ += n;
563 size_ -= n;
564 }
565
566 // Lexicographically compare this string reference to other.
568 {
569 size_t str_size = size_ < other.size_ ? size_ : other.size_;
570 int result = std::char_traits<Char>::compare(data_, other.data_, str_size);
571 if (result == 0)
572 result = size_ == other.size_ ? 0 : (size_ < other.size_ ? -1 : 1);
573 return result;
574 }
575
578 -> bool
579 {
580 return lhs.compare(rhs) == 0;
581 }
582 friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool
583 {
584 return lhs.compare(rhs) != 0;
585 }
586 friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool
587 {
588 return lhs.compare(rhs) < 0;
589 }
590 friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool
591 {
592 return lhs.compare(rhs) <= 0;
593 }
594 friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool
595 {
596 return lhs.compare(rhs) > 0;
597 }
598 friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool
599 {
600 return lhs.compare(rhs) >= 0;
601 }
602};
603
605
607template <typename T>
608struct is_char : std::false_type
609{
610};
611template <>
612struct is_char<char> : std::true_type
613{
614};
615
617
618// A base class for compile-time strings.
620{
621};
622
623template <typename S>
624struct is_compile_string : std::is_base_of<compile_string, S>
625{
626};
627
628// Returns a string view of `s`.
629template <typename Char, FMT_ENABLE_IF(is_char<Char>::value)>
631{
632 return s;
633}
634template <typename Char, typename Traits, typename Alloc>
635inline auto to_string_view(const std::basic_string<Char, Traits, Alloc>& s)
637{
638 return s;
639}
640template <typename Char>
643{
644 return s;
645}
646template <typename Char,
649{
650 return s;
651}
652template <typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
659
660// Specifies whether S is a string type convertible to fmt::basic_string_view.
661// It should be a constexpr function but MSVC 2017 fails to compile it in
662// enable_if and MSVC 2015 fails to compile it as an alias template.
663// ADL invocation of to_string_view is DEPRECATED!
664template <typename S>
665struct is_string : std::is_class<decltype(to_string_view(std::declval<S>()))>
666{
667};
668
669template <typename S, typename = void>
671{
672};
673template <typename S>
675{
676 using result = decltype(to_string_view(std::declval<S>()));
677 using type = typename result::value_type;
678};
679
680enum class type
681{
682 none_type,
683 // Integer types should go first,
684 int_type,
685 uint_type,
690 bool_type,
691 char_type,
693 // followed by floating-point types.
702};
703
704// Maps core type T to the corresponding type enum constant.
705template <typename T, typename Char>
706struct type_constant : std::integral_constant<type, type::custom_type>
707{
708};
709
710#define FMT_TYPE_CONSTANT(Type, constant) \
711 template <typename Char> \
712 struct type_constant<Type, Char> \
713 : std::integral_constant<type, type::constant> \
714 { \
715 }
716
731
732constexpr bool is_integral_type(type t)
733{
734 return t > type::none_type && t <= type::last_integer_type;
735}
736
737constexpr bool is_arithmetic_type(type t)
738{
739 return t > type::none_type && t <= type::last_numeric_type;
740}
741
742FMT_NORETURN FMT_API void throw_format_error(const char* message);
743
745{
746 constexpr error_handler() = default;
747 constexpr error_handler(const error_handler&) = default;
748
749 // This function is intentionally not constexpr to give a compile-time error.
750 FMT_NORETURN void on_error(const char* message)
751 {
752 throw_format_error(message);
753 }
754};
756
758template <typename S>
759using char_t = typename detail::char_t_impl<S>::type;
760
768template <typename Char, typename ErrorHandler = detail::error_handler>
769class basic_format_parse_context : private ErrorHandler
770{
771private:
774
776
777public:
778 using char_type = Char;
780
781 explicit constexpr basic_format_parse_context(
782 basic_string_view<Char> format_str, ErrorHandler eh = {}, int next_arg_id = 0)
783 : ErrorHandler(eh), format_str_(format_str), next_arg_id_(next_arg_id)
784 {
785 }
786
791 constexpr auto begin() const noexcept -> iterator
792 {
793 return format_str_.begin();
794 }
795
799 constexpr auto end() const noexcept -> iterator
800 {
801 return format_str_.end();
802 }
803
806 {
807 format_str_.remove_prefix(detail::to_unsigned(it - begin()));
808 }
809
815 {
816 if (next_arg_id_ < 0)
817 {
818 on_error("cannot switch from manual to automatic argument indexing");
819 return 0;
820 }
821 int id = next_arg_id_++;
822 do_check_arg_id(id);
823 return id;
824 }
825
831 {
832 if (next_arg_id_ > 0)
833 {
834 on_error("cannot switch from automatic to manual argument indexing");
835 return;
836 }
837 next_arg_id_ = -1;
838 do_check_arg_id(id);
839 }
844
845 FMT_CONSTEXPR void on_error(const char* message)
846 {
847 ErrorHandler::on_error(message);
848 }
849
850 constexpr auto error_handler() const -> ErrorHandler
851 {
852 return *this;
853 }
854};
855
857
859// A parse context with extra data used only in compile-time checks.
860template <typename Char, typename ErrorHandler = detail::error_handler>
862 : public basic_format_parse_context<Char, ErrorHandler>
863{
864private:
866 const type* types_;
868
869public:
871 basic_string_view<Char> format_str, int num_args, const type* types, ErrorHandler eh = {}, int next_arg_id = 0)
872 : base(format_str, eh, next_arg_id), num_args_(num_args), types_(types)
873 {
874 }
875
876 constexpr auto num_args() const -> int
877 {
878 return num_args_;
879 }
880 constexpr auto arg_type(int id) const -> type
881 {
882 return types_[id];
883 }
884
886 {
887 int id = base::next_arg_id();
888 if (id >= num_args_)
889 this->on_error("argument not found");
890 return id;
891 }
892
894 {
896 if (id >= num_args_)
897 this->on_error("argument not found");
898 }
899 using base::check_arg_id;
900
902 {
903 if (arg_id < num_args_ && types_ && !is_integral_type(types_[arg_id]))
904 this->on_error("width/precision is not integer");
905 }
906};
908
909template <typename Char, typename ErrorHandler>
910FMT_CONSTEXPR void
912{
913 // Argument id is only checked at compile-time during parsing because
914 // formatting has its own validation.
915 if (detail::is_constant_evaluated() && FMT_GCC_VERSION >= 1200)
916 {
917 using context = detail::compile_parse_context<Char, ErrorHandler>;
918 if (id >= static_cast<context*>(this)->num_args())
919 on_error("argument not found");
920 }
921}
922
923template <typename Char, typename ErrorHandler>
924FMT_CONSTEXPR void
926{
927 if (detail::is_constant_evaluated())
928 {
929 using context = detail::compile_parse_context<Char, ErrorHandler>;
930 static_cast<context*>(this)->check_dynamic_spec(arg_id);
931 }
932}
933
934template <typename Context>
935class basic_format_arg;
936template <typename Context>
938template <typename Context>
940
941// A formatter for objects of type T.
942template <typename T, typename Char = char, typename Enable = void>
944{
945 // A deleted default constructor indicates a disabled formatter.
946 formatter() = delete;
947};
948
949// Specifies if T has an enabled formatter specialization. A type can be
950// formattable even if it doesn't have a formatter e.g. via a conversion.
951template <typename T, typename Context>
953 std::is_constructible<typename Context::template formatter_type<T>>;
954
955// Checks whether T is a container with contiguous storage.
956template <typename T>
957struct is_contiguous : std::false_type
958{
959};
960template <typename Char>
961struct is_contiguous<std::basic_string<Char>> : std::true_type
962{
963};
964
965class appender;
966
968
969template <typename Context, typename T>
970constexpr auto has_const_formatter_impl(T*)
971 -> decltype(typename Context::template formatter_type<T>().format(
972 std::declval<const T&>(), std::declval<Context&>()),
973 true)
974{
975 return true;
976}
977template <typename Context>
978constexpr auto has_const_formatter_impl(...) -> bool
979{
980 return false;
981}
982template <typename T, typename Context>
983constexpr auto has_const_formatter() -> bool
984{
985 return has_const_formatter_impl<Context>(static_cast<T*>(nullptr));
986}
987
988// Extracts a reference to the container from back_insert_iterator.
989template <typename Container>
990inline auto get_container(std::back_insert_iterator<Container> it)
991 -> Container&
992{
993 using base = std::back_insert_iterator<Container>;
994 struct accessor : base
995 {
996 accessor(base b)
997 : base(b)
998 {
999 }
1000 using base::container;
1001 };
1002 return *accessor(it).container;
1003}
1004
1005template <typename Char, typename InputIt, typename OutputIt>
1006FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out)
1007 -> OutputIt
1008{
1009 while (begin != end)
1010 *out++ = static_cast<Char>(*begin++);
1011 return out;
1012}
1013
1014template <typename Char, typename T, typename U, FMT_ENABLE_IF(std::is_same<remove_const_t<T>, U>::value&& is_char<U>::value)>
1015FMT_CONSTEXPR auto copy_str(T* begin, T* end, U* out) -> U*
1016{
1018 return copy_str<Char, T*, U*>(begin, end, out);
1019 auto size = to_unsigned(end - begin);
1020 memcpy(out, begin, size * sizeof(U));
1021 return out + size;
1022}
1023
1030template <typename T>
1032{
1033private:
1035 size_t size_;
1037
1038protected:
1039 // Don't initialize ptr_ since it is not accessed to save a few cycles.
1040 FMT_MSC_WARNING(suppress : 26495)
1041 buffer(size_t sz) noexcept
1042 : size_(sz), capacity_(sz)
1043 {
1044 }
1045
1046 FMT_CONSTEXPR20 buffer(T* p = nullptr, size_t sz = 0, size_t cap = 0) noexcept
1047 : ptr_(p), size_(sz), capacity_(cap)
1048 {
1049 }
1050
1052 buffer(buffer&&) = default;
1053
1055 FMT_CONSTEXPR void set(T* buf_data, size_t buf_capacity) noexcept
1056 {
1057 ptr_ = buf_data;
1058 capacity_ = buf_capacity;
1059 }
1060
1062 virtual FMT_CONSTEXPR20 void grow(size_t capacity) = 0;
1063
1064public:
1065 using value_type = T;
1066 using const_reference = const T&;
1067
1068 buffer(const buffer&) = delete;
1069 void operator=(const buffer&) = delete;
1070
1071 auto begin() noexcept -> T*
1072 {
1073 return ptr_;
1074 }
1075 auto end() noexcept -> T*
1076 {
1077 return ptr_ + size_;
1078 }
1079
1080 auto begin() const noexcept -> const T*
1081 {
1082 return ptr_;
1083 }
1084 auto end() const noexcept -> const T*
1085 {
1086 return ptr_ + size_;
1087 }
1088
1090 constexpr auto size() const noexcept -> size_t
1091 {
1092 return size_;
1093 }
1094
1096 constexpr auto capacity() const noexcept -> size_t
1097 {
1098 return capacity_;
1099 }
1100
1102 FMT_CONSTEXPR auto data() noexcept -> T*
1103 {
1104 return ptr_;
1105 }
1106
1108 FMT_CONSTEXPR auto data() const noexcept -> const T*
1109 {
1110 return ptr_;
1111 }
1112
1114 void clear()
1115 {
1116 size_ = 0;
1117 }
1118
1119 // Tries resizing the buffer to contain *count* elements. If T is a POD type
1120 // the new elements may not be initialized.
1122 {
1125 }
1126
1127 // Tries increasing the buffer capacity to *new_capacity*. It can increase the
1128 // capacity by a smaller amount than requested but guarantees there is space
1129 // for at least one additional element either by increasing the capacity or by
1130 // flushing the buffer if it is full.
1131 FMT_CONSTEXPR20 void try_reserve(size_t new_capacity)
1132 {
1133 if (new_capacity > capacity_)
1134 grow(new_capacity);
1135 }
1136
1138 {
1139 try_reserve(size_ + 1);
1140 ptr_[size_++] = value;
1141 }
1142
1144 template <typename U>
1145 void append(const U* begin, const U* end);
1146
1147 template <typename Idx>
1149 {
1150 return ptr_[index];
1151 }
1152 template <typename Idx>
1153 FMT_CONSTEXPR auto operator[](Idx index) const -> const T&
1154 {
1155 return ptr_[index];
1156 }
1157};
1158
1160{
1161 explicit buffer_traits(size_t)
1162 {
1163 }
1164 auto count() const -> size_t
1165 {
1166 return 0;
1167 }
1168 auto limit(size_t size) -> size_t
1169 {
1170 return size;
1171 }
1172};
1173
1175{
1176private:
1177 size_t count_ = 0;
1178 size_t limit_;
1179
1180public:
1182 : limit_(limit)
1183 {
1184 }
1185 auto count() const -> size_t
1186 {
1187 return count_;
1188 }
1189 auto limit(size_t size) -> size_t
1190 {
1191 size_t n = limit_ > count_ ? limit_ - count_ : 0;
1192 count_ += size;
1193 return size < n ? size : n;
1194 }
1195};
1196
1197// A buffer that writes to an output iterator when flushed.
1198template <typename OutputIt, typename T, typename Traits = buffer_traits>
1199class iterator_buffer final : public Traits, public buffer<T>
1200{
1201private:
1202 OutputIt out_;
1203 enum
1204 {
1205 buffer_size = 256
1208
1209protected:
1210 FMT_CONSTEXPR20 void grow(size_t) override
1211 {
1212 if (this->size() == buffer_size)
1213 flush();
1214 }
1215
1216 void flush()
1217 {
1218 auto size = this->size();
1219 this->clear();
1220 out_ = copy_str<T>(data_, data_ + this->limit(size), out_);
1221 }
1222
1223public:
1224 explicit iterator_buffer(OutputIt out, size_t n = buffer_size)
1225 : Traits(n), buffer<T>(data_, 0, buffer_size), out_(out)
1226 {
1227 }
1229 : Traits(other), buffer<T>(data_, 0, buffer_size), out_(other.out_)
1230 {
1231 }
1233 {
1234 flush();
1235 }
1236
1237 auto out() -> OutputIt
1238 {
1239 flush();
1240 return out_;
1241 }
1242 auto count() const -> size_t
1243 {
1244 return Traits::count() + this->size();
1245 }
1246};
1247
1248template <typename T>
1250 : public fixed_buffer_traits,
1251 public buffer<T>
1252{
1253private:
1255 enum
1256 {
1257 buffer_size = 256
1260
1261protected:
1262 FMT_CONSTEXPR20 void grow(size_t) override
1263 {
1264 if (this->size() == this->capacity())
1265 flush();
1266 }
1267
1268 void flush()
1269 {
1270 size_t n = this->limit(this->size());
1271 if (this->data() == out_)
1272 {
1273 out_ += n;
1274 this->set(data_, buffer_size);
1275 }
1276 this->clear();
1277 }
1278
1279public:
1280 explicit iterator_buffer(T* out, size_t n = buffer_size)
1281 : fixed_buffer_traits(n), buffer<T>(out, 0, n), out_(out)
1282 {
1283 }
1285 : fixed_buffer_traits(other),
1286 buffer<T>(std::move(other)),
1287 out_(other.out_)
1288 {
1289 if (this->data() != out_)
1290 {
1291 this->set(data_, buffer_size);
1292 this->clear();
1293 }
1294 }
1296 {
1297 flush();
1298 }
1299
1300 auto out() -> T*
1301 {
1302 flush();
1303 return out_;
1304 }
1305 auto count() const -> size_t
1306 {
1307 return fixed_buffer_traits::count() + this->size();
1308 }
1309};
1310
1311template <typename T>
1312class iterator_buffer<T*, T> final : public buffer<T>
1313{
1314protected:
1315 FMT_CONSTEXPR20 void grow(size_t) override
1316 {
1317 }
1318
1319public:
1320 explicit iterator_buffer(T* out, size_t = 0)
1321 : buffer<T>(out, 0, ~size_t())
1322 {
1323 }
1324
1325 auto out() -> T*
1326 {
1327 return &*this->end();
1328 }
1329};
1330
1331// A buffer that writes to a container with the contiguous storage.
1332template <typename Container>
1333class iterator_buffer<std::back_insert_iterator<Container>,
1334 enable_if_t<is_contiguous<Container>::value,
1335 typename Container::value_type>>
1336 final : public buffer<typename Container::value_type>
1337{
1338private:
1339 Container& container_;
1340
1341protected:
1342 FMT_CONSTEXPR20 void grow(size_t capacity) override
1343 {
1344 container_.resize(capacity);
1345 this->set(&container_[0], capacity);
1346 }
1347
1348public:
1349 explicit iterator_buffer(Container& c)
1350 : buffer<typename Container::value_type>(c.size()), container_(c)
1351 {
1352 }
1353 explicit iterator_buffer(std::back_insert_iterator<Container> out, size_t = 0)
1355 {
1356 }
1357
1358 auto out() -> std::back_insert_iterator<Container>
1359 {
1360 return std::back_inserter(container_);
1361 }
1362};
1363
1364// A buffer that counts the number of code units written discarding the output.
1365template <typename T = char>
1366class counting_buffer final : public buffer<T>
1367{
1368private:
1369 enum
1370 {
1371 buffer_size = 256
1374 size_t count_ = 0;
1375
1376protected:
1377 FMT_CONSTEXPR20 void grow(size_t) override
1378 {
1379 if (this->size() != buffer_size)
1380 return;
1381 count_ += this->size();
1382 this->clear();
1383 }
1384
1385public:
1387 : buffer<T>(data_, 0, buffer_size)
1388 {
1389 }
1390
1391 auto count() -> size_t
1392 {
1393 return count_ + this->size();
1394 }
1395};
1396
1397template <typename T>
1398using buffer_appender = conditional_t<std::is_same<T, char>::value, appender, std::back_insert_iterator<buffer<T>>>;
1399
1400// Maps an output iterator to a buffer.
1401template <typename T, typename OutputIt>
1406
1407template <typename Buffer>
1408auto get_iterator(Buffer& buf) -> decltype(buf.out())
1409{
1410 return buf.out();
1411}
1412template <typename T>
1414{
1415 return buffer_appender<T>(buf);
1416}
1417
1418template <typename T, typename Char = char, typename Enable = void>
1420{
1422};
1423
1424// Specifies if T has an enabled fallback_formatter specialization.
1425template <typename T, typename Char>
1427#ifdef FMT_DEPRECATED_OSTREAM
1428 std::is_constructible<fallback_formatter<T, Char>>;
1429#else
1430 std::false_type;
1431#endif
1432
1433struct view
1434{
1435};
1436
1437template <typename Char, typename T>
1439{
1440 const Char* name;
1441 const T& value;
1442 named_arg(const Char* n, const T& v)
1443 : name(n), value(v)
1444 {
1445 }
1446};
1447
1448template <typename Char>
1450{
1451 const Char* name;
1452 int id;
1453};
1454
1455template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
1457{
1458 // args_[0].named_args points to named_args_ to avoid bloating format_args.
1459 // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
1460 T args_[1 + (NUM_ARGS != 0 ? NUM_ARGS : +1)];
1462
1463 template <typename... U>
1464 arg_data(const U&... init)
1465 : args_{T(named_args_, NUM_NAMED_ARGS), init...}
1466 {
1467 }
1468 arg_data(const arg_data& other) = delete;
1469 auto args() const -> const T*
1470 {
1471 return args_ + 1;
1472 }
1474 {
1475 return named_args_;
1476 }
1477};
1478
1479template <typename T, typename Char, size_t NUM_ARGS>
1480struct arg_data<T, Char, NUM_ARGS, 0>
1481{
1482 // +1 to workaround a bug in gcc 7.5 that causes duplicated-branches warning.
1483 T args_[NUM_ARGS != 0 ? NUM_ARGS : +1];
1484
1485 template <typename... U>
1487 : args_{init...}
1488 {
1489 }
1490 FMT_CONSTEXPR FMT_INLINE auto args() const -> const T*
1491 {
1492 return args_;
1493 }
1494 FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t
1495 {
1496 return nullptr;
1497 }
1498};
1499
1500template <typename Char>
1502{
1503}
1504
1505template <typename T>
1506struct is_named_arg : std::false_type
1507{
1508};
1509template <typename T>
1510struct is_statically_named_arg : std::false_type
1511{
1512};
1513
1514template <typename T, typename Char>
1515struct is_named_arg<named_arg<Char, T>> : std::true_type
1516{
1517};
1518
1519template <typename Char, typename T, typename... Tail, FMT_ENABLE_IF(!is_named_arg<T>::value)>
1520void init_named_args(named_arg_info<Char>* named_args, int arg_count, int named_arg_count, const T&, const Tail&... args)
1521{
1522 init_named_args(named_args, arg_count + 1, named_arg_count, args...);
1523}
1524
1525template <typename Char, typename T, typename... Tail, FMT_ENABLE_IF(is_named_arg<T>::value)>
1526void init_named_args(named_arg_info<Char>* named_args, int arg_count, int named_arg_count, const T& arg, const Tail&... args)
1527{
1528 named_args[named_arg_count++] = {arg.name, arg_count};
1529 init_named_args(named_args, arg_count + 1, named_arg_count, args...);
1530}
1531
1532template <typename... Args>
1533FMT_CONSTEXPR FMT_INLINE void init_named_args(std::nullptr_t, int, int, const Args&...)
1534{
1535}
1536
1537template <bool B = false>
1538constexpr auto count() -> size_t
1539{
1540 return B ? 1 : 0;
1541}
1542template <bool B1, bool B2, bool... Tail>
1543constexpr auto count() -> size_t
1544{
1545 return (B1 ? 1 : 0) + count<B2, Tail...>();
1546}
1547
1548template <typename... Args>
1549constexpr auto count_named_args() -> size_t
1550{
1551 return count<is_named_arg<Args>::value...>();
1552}
1553
1554template <typename... Args>
1555constexpr auto count_statically_named_args() -> size_t
1556{
1557 return count<is_statically_named_arg<Args>::value...>();
1558}
1559
1561{
1562};
1564{
1565};
1572
1573template <typename Char>
1575{
1576 const Char* data;
1577 size_t size;
1578};
1579
1580template <typename Char>
1582{
1584 size_t size;
1585};
1586
1587template <typename Context>
1589{
1590 using parse_context = typename Context::parse_context_type;
1591 void* value;
1592 void (*format)(void* arg, parse_context& parse_ctx, Context& ctx);
1593};
1594
1595// A formatting argument value.
1596template <typename Context>
1598{
1599public:
1600 using char_type = typename Context::char_type;
1601
1602 union {
1605 unsigned uint_value;
1607 unsigned long long ulong_long_value;
1615 const void* pointer;
1619 };
1620
1621 constexpr FMT_INLINE value()
1622 : no_value()
1623 {
1624 }
1625 constexpr FMT_INLINE value(int val)
1626 : int_value(val)
1627 {
1628 }
1629 constexpr FMT_INLINE value(unsigned val)
1630 : uint_value(val)
1631 {
1632 }
1633 constexpr FMT_INLINE value(long long val)
1634 : long_long_value(val)
1635 {
1636 }
1637 constexpr FMT_INLINE value(unsigned long long val)
1638 : ulong_long_value(val)
1639 {
1640 }
1642 : int128_value(val)
1643 {
1644 }
1646 : uint128_value(val)
1647 {
1648 }
1649 constexpr FMT_INLINE value(float val)
1650 : float_value(val)
1651 {
1652 }
1653 constexpr FMT_INLINE value(double val)
1654 : double_value(val)
1655 {
1656 }
1657 FMT_INLINE value(long double val)
1658 : long_double_value(val)
1659 {
1660 }
1661 constexpr FMT_INLINE value(bool val)
1662 : bool_value(val)
1663 {
1664 }
1666 : char_value(val)
1667 {
1668 }
1670 {
1671 string.data = val;
1673 string.size = {};
1674 }
1676 {
1677 string.data = val.data();
1678 string.size = val.size();
1679 }
1680 FMT_INLINE value(const void* val)
1681 : pointer(val)
1682 {
1683 }
1685 : named_args{args, size}
1686 {
1687 }
1688
1689 template <typename T>
1691 {
1692 using value_type = remove_cvref_t<T>;
1693 custom.value = const_cast<value_type*>(&val);
1694 // Get the formatter type through the context to allow different contexts
1695 // have different extension points, e.g. `formatter<T>` for `format` and
1696 // `printf_formatter<T>` for `printf`.
1697 custom.format = format_custom_arg<
1698 value_type,
1700 typename Context::template formatter_type<value_type>,
1702 }
1707
1708private:
1709 // Formats an argument of a custom type, such as a user-defined class.
1710 template <typename T, typename Formatter>
1711 static void format_custom_arg(void* arg,
1712 typename Context::parse_context_type& parse_ctx,
1713 Context& ctx)
1714 {
1715 auto f = Formatter();
1716 parse_ctx.advance_to(f.parse(parse_ctx));
1717 using qualified_type =
1719 ctx.advance_to(f.format(*static_cast<qualified_type*>(arg), ctx));
1720 }
1721};
1722
1723template <typename Context, typename T>
1725
1726// To minimize the number of types we need to deal with, long is translated
1727// either to int or to long long depending on its size.
1728enum
1729{
1730 long_short = sizeof(long) == sizeof(int)
1734
1735#ifdef __cpp_lib_byte
1736inline auto format_as(std::byte b) -> unsigned char
1737{
1738 return static_cast<unsigned char>(b);
1739}
1740#endif
1741
1742template <typename T>
1744{
1745 template <typename U, typename V = decltype(format_as(U())), FMT_ENABLE_IF(std::is_enum<U>::value&& std::is_integral<V>::value)>
1746 static auto check(U*) -> std::true_type;
1747 static auto check(...) -> std::false_type;
1748
1749 enum
1750 {
1751 value = decltype(check(static_cast<T*>(nullptr)))::value
1753};
1754
1755// Maps formatting arguments to core types.
1756// arg_mapper reports errors by returning unformattable instead of using
1757// static_assert because it's used in the is_formattable trait.
1758template <typename Context>
1760{
1761 using char_type = typename Context::char_type;
1762
1763 FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int
1764 {
1765 return val;
1766 }
1767 FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned
1768 {
1769 return val;
1770 }
1771 FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int
1772 {
1773 return val;
1774 }
1775 FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned
1776 {
1777 return val;
1778 }
1779 FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int
1780 {
1781 return val;
1782 }
1783 FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned
1784 {
1785 return val;
1786 }
1788 {
1789 return val;
1790 }
1791 FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type
1792 {
1793 return val;
1794 }
1795 FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long
1796 {
1797 return val;
1798 }
1799 FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val)
1800 -> unsigned long long
1801 {
1802 return val;
1803 }
1805 {
1806 return val;
1807 }
1809 {
1810 return val;
1811 }
1812 FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool
1813 {
1814 return val;
1815 }
1816
1817 template <typename T, FMT_ENABLE_IF(std::is_same<T, char>::value || std::is_same<T, char_type>::value)>
1819 {
1820 return val;
1821 }
1822 template <typename T, enable_if_t<(std::is_same<T, wchar_t>::value ||
1823#ifdef __cpp_char8_t
1824 std::is_same<T, char8_t>::value ||
1825#endif
1826 std::is_same<T, char16_t>::value || std::is_same<T, char32_t>::value) &&
1827 !std::is_same<T, char_type>::value,
1828 int> = 0>
1830 {
1831 return {};
1832 }
1833
1834 FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float
1835 {
1836 return val;
1837 }
1838 FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double
1839 {
1840 return val;
1841 }
1842 FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double
1843 {
1844 return val;
1845 }
1846
1848 {
1849 return val;
1850 }
1852 {
1853 return val;
1854 }
1855 template <typename T,
1856 FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
1857 std::is_same<char_type, char_t<T>>::value)>
1858 FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
1860 {
1861 return to_string_view(val);
1862 }
1863 template <typename T,
1864 FMT_ENABLE_IF(is_string<T>::value && !std::is_pointer<T>::value &&
1865 !std::is_same<char_type, char_t<T>>::value)>
1867 {
1868 return {};
1869 }
1870 template <typename T,
1872 std::is_convertible<T, basic_string_view<char_type>>::value &&
1875 FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
1877 {
1878 return basic_string_view<char_type>(val);
1879 }
1880 template <typename T,
1882 std::is_convertible<T, std_string_view<char_type>>::value &&
1883 !std::is_convertible<T, basic_string_view<char_type>>::value &&
1886 FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
1888 {
1889 return std_string_view<char_type>(val);
1890 }
1891
1892 FMT_CONSTEXPR FMT_INLINE auto map(void* val) -> const void*
1893 {
1894 return val;
1895 }
1896 FMT_CONSTEXPR FMT_INLINE auto map(const void* val) -> const void*
1897 {
1898 return val;
1899 }
1900 FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void*
1901 {
1902 return val;
1903 }
1904
1905 // We use SFINAE instead of a const T* parameter to avoid conflicting with
1906 // the C array overload.
1907 template <
1908 typename T,
1910 std::is_pointer<T>::value || std::is_member_pointer<T>::value ||
1911 std::is_function<typename std::remove_pointer<T>::type>::value ||
1912 (std::is_convertible<const T&, const void*>::value &&
1913 !std::is_convertible<const T&, const char_type*>::value &&
1916 {
1917 return {};
1918 }
1919
1920 template <typename T, std::size_t N, FMT_ENABLE_IF(!std::is_same<T, wchar_t>::value)>
1921 FMT_CONSTEXPR FMT_INLINE auto map(const T (&values)[N]) -> const T (&)[N]
1922 {
1923 return values;
1924 }
1925
1926 template <typename T,
1928 std::is_enum<T>::value&& std::is_convertible<T, int>::value &&
1932 -> decltype(std::declval<arg_mapper>().map(
1933 static_cast<underlying_t<T>>(val)))
1934 {
1935 return map(static_cast<underlying_t<T>>(val));
1936 }
1937
1938 template <typename T, FMT_ENABLE_IF(has_format_as<T>::value && !has_formatter<T, Context>::value)>
1939 FMT_CONSTEXPR FMT_INLINE auto map(const T& val)
1940 -> decltype(std::declval<arg_mapper>().map(format_as(T())))
1941 {
1942 return map(format_as(val));
1943 }
1944
1945 template <typename T, typename U = remove_cvref_t<T>>
1947 : bool_constant<has_const_formatter<U, Context>() ||
1948 !std::is_const<remove_reference_t<T>>::value ||
1949 has_fallback_formatter<U, char_type>::value>
1950 {
1951 };
1952
1953#if (FMT_MSC_VERSION != 0 && FMT_MSC_VERSION < 1910) || \
1954 FMT_ICC_VERSION != 0 || defined(__NVCC__)
1955 // Workaround a bug in MSVC and Intel (Issue 2746).
1956 template <typename T>
1957 FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T&
1958 {
1959 return val;
1960 }
1961#else
1962 template <typename T, FMT_ENABLE_IF(formattable<T>::value)>
1963 FMT_CONSTEXPR FMT_INLINE auto do_map(T&& val) -> T&
1964 {
1965 return val;
1966 }
1967 template <typename T, FMT_ENABLE_IF(!formattable<T>::value)>
1969 {
1970 return {};
1971 }
1972#endif
1973
1974 template <typename T, typename U = remove_cvref_t<T>, FMT_ENABLE_IF(!is_string<U>::value && !is_char<U>::value && !std::is_array<U>::value && !std::is_pointer<U>::value && !has_format_as<U>::value && (has_formatter<U, Context>::value || has_fallback_formatter<U, char_type>::value))>
1976 -> decltype(this->do_map(std::forward<T>(val)))
1977 {
1978 return do_map(std::forward<T>(val));
1979 }
1980
1981 template <typename T, FMT_ENABLE_IF(is_named_arg<T>::value)>
1983 -> decltype(std::declval<arg_mapper>().map(named_arg.value))
1984 {
1985 return map(named_arg.value);
1986 }
1987
1988 auto map(...) -> unformattable
1989 {
1990 return {};
1991 }
1992};
1993
1994// A type constant after applying arg_mapper<Context>.
1995template <typename T, typename Context>
1997 type_constant<decltype(arg_mapper<Context>().map(std::declval<const T&>())),
1998 typename Context::char_type>;
1999
2000enum
2001{
2002 packed_arg_bits = 4
2004// Maximum number of arguments with packed types.
2005enum
2006{
2009enum : unsigned long long
2010{
2011 is_unpacked_bit = 1ULL << 63
2013enum : unsigned long long
2014{
2015 has_named_args_bit = 1ULL << 62
2017
2019
2020// An output iterator that appends to a buffer.
2021// It is used to reduce symbol sizes for the common case.
2022class appender : public std::back_insert_iterator<detail::buffer<char>>
2023{
2024 using base = std::back_insert_iterator<detail::buffer<char>>;
2025
2026 template <typename T>
2027 friend auto get_buffer(appender out) -> detail::buffer<char>&
2028 {
2029 return detail::get_container(out);
2030 }
2031
2032public:
2033 using std::back_insert_iterator<detail::buffer<char>>::back_insert_iterator;
2034 appender(base it) noexcept
2035 : base(it)
2036 {
2037 }
2039
2040 auto operator++() noexcept -> appender&
2041 {
2042 return *this;
2043 }
2044 auto operator++(int) noexcept -> appender
2045 {
2046 return *this;
2047 }
2048};
2049
2050// A formatting argument. It is a trivially copyable/constructible type to
2051// allow storage in basic_memory_buffer.
2052template <typename Context>
2054{
2055private:
2056 detail::value<Context> value_;
2057 detail::type type_;
2058
2059 template <typename ContextType, typename T>
2062
2063 template <typename Visitor, typename Ctx>
2064 friend FMT_CONSTEXPR auto visit_format_arg(Visitor&& vis,
2066 -> decltype(vis(0));
2067
2068 friend class basic_format_args<Context>;
2069 friend class dynamic_format_arg_store<Context>;
2070
2071 using char_type = typename Context::char_type;
2072
2073 template <typename T, typename Char, size_t NUM_ARGS, size_t NUM_NAMED_ARGS>
2074 friend struct detail::arg_data;
2075
2076 basic_format_arg(const detail::named_arg_info<char_type>* args, size_t size)
2077 : value_(args, size)
2078 {
2079 }
2080
2081public:
2083 {
2084 public:
2085 explicit handle(detail::custom_value<Context> custom)
2086 : custom_(custom)
2087 {
2088 }
2089
2090 void format(typename Context::parse_context_type& parse_ctx,
2091 Context& ctx) const
2092 {
2093 custom_.format(custom_.value, parse_ctx, ctx);
2094 }
2095
2096 private:
2097 detail::custom_value<Context> custom_;
2098 };
2099
2102 {
2103 }
2104
2105 constexpr explicit operator bool() const noexcept
2106 {
2107 return type_ != detail::type::none_type;
2108 }
2109
2110 auto type() const -> detail::type
2111 {
2112 return type_;
2113 }
2114
2115 auto is_integral() const -> bool
2116 {
2117 return detail::is_integral_type(type_);
2118 }
2119 auto is_arithmetic() const -> bool
2120 {
2121 return detail::is_arithmetic_type(type_);
2122 }
2123};
2124
2132template <typename Visitor, typename Context>
2134 Visitor&& vis, const basic_format_arg<Context>& arg) -> decltype(vis(0))
2135{
2136 switch (arg.type_)
2137 {
2138 case detail::type::none_type:
2139 break;
2140 case detail::type::int_type:
2141 return vis(arg.value_.int_value);
2142 case detail::type::uint_type:
2143 return vis(arg.value_.uint_value);
2144 case detail::type::long_long_type:
2145 return vis(arg.value_.long_long_value);
2146 case detail::type::ulong_long_type:
2147 return vis(arg.value_.ulong_long_value);
2148 case detail::type::int128_type:
2149 return vis(detail::convert_for_visit(arg.value_.int128_value));
2150 case detail::type::uint128_type:
2151 return vis(detail::convert_for_visit(arg.value_.uint128_value));
2152 case detail::type::bool_type:
2153 return vis(arg.value_.bool_value);
2154 case detail::type::char_type:
2155 return vis(arg.value_.char_value);
2156 case detail::type::float_type:
2157 return vis(arg.value_.float_value);
2158 case detail::type::double_type:
2159 return vis(arg.value_.double_value);
2160 case detail::type::long_double_type:
2161 return vis(arg.value_.long_double_value);
2162 case detail::type::cstring_type:
2163 return vis(arg.value_.string.data);
2164 case detail::type::string_type:
2166 return vis(sv(arg.value_.string.data, arg.value_.string.size));
2167 case detail::type::pointer_type:
2168 return vis(arg.value_.pointer);
2169 case detail::type::custom_type:
2170 return vis(typename basic_format_arg<Context>::handle(arg.value_.custom));
2171 }
2172 return vis(monostate());
2173}
2174
2176
2177template <typename Char, typename InputIt>
2178auto copy_str(InputIt begin, InputIt end, appender out) -> appender
2179{
2180 get_container(out).append(begin, end);
2181 return out;
2182}
2183
2184template <typename Char, typename R, typename OutputIt>
2185FMT_CONSTEXPR auto copy_str(R&& rng, OutputIt out) -> OutputIt
2186{
2187 return detail::copy_str<Char>(rng.begin(), rng.end(), out);
2188}
2189
2190#if FMT_GCC_VERSION && FMT_GCC_VERSION < 500
2191// A workaround for gcc 4.8 to make void_t work in a SFINAE context.
2192template <typename... Ts>
2193struct void_t_impl
2194{
2195 using type = void;
2196};
2197template <typename... Ts>
2198using void_t = typename detail::void_t_impl<Ts...>::type;
2199#else
2200template <typename...>
2201using void_t = void;
2202#endif
2203
2204template <typename It, typename T, typename Enable = void>
2205struct is_output_iterator : std::false_type
2206{
2207};
2208
2209template <typename It, typename T>
2211 It,
2212 T,
2214 decltype(*std::declval<It>() = std::declval<T>())>>
2215 : std::true_type
2216{
2217};
2218
2219template <typename OutputIt>
2220struct is_back_insert_iterator : std::false_type
2221{
2222};
2223template <typename Container>
2225 : std::true_type
2226{
2227};
2228
2229template <typename OutputIt>
2231{
2232};
2233template <typename Container>
2234struct is_contiguous_back_insert_iterator<std::back_insert_iterator<Container>>
2235 : is_contiguous<Container>
2236{
2237};
2238template <>
2240{
2241};
2242
2243// A type-erased reference to an std::locale to avoid a heavy <locale> include.
2245{
2246private:
2247 const void* locale_; // A type-erased pointer to std::locale.
2248
2249public:
2250 constexpr locale_ref()
2251 : locale_(nullptr)
2252 {
2253 }
2254 template <typename Locale>
2255 explicit locale_ref(const Locale& loc);
2256
2257 explicit operator bool() const noexcept
2258 {
2259 return locale_ != nullptr;
2260 }
2261
2262 template <typename Locale>
2263 auto get() const -> Locale;
2264};
2265
2266template <typename>
2267constexpr auto encode_types() -> unsigned long long
2268{
2269 return 0;
2270}
2271
2272template <typename Context, typename Arg, typename... Args>
2273constexpr auto encode_types() -> unsigned long long
2274{
2275 return static_cast<unsigned>(mapped_type_constant<Arg, Context>::value) |
2276 (encode_types<Context, Args...>() << packed_arg_bits);
2277}
2278
2279template <typename Context, typename T>
2281{
2282 const auto& arg = arg_mapper<Context>().map(FMT_FORWARD(val));
2283
2284 constexpr bool formattable_char =
2285 !std::is_same<decltype(arg), const unformattable_char&>::value;
2286 static_assert(formattable_char, "Mixing character types is disallowed.");
2287
2288 constexpr bool formattable_const =
2289 !std::is_same<decltype(arg), const unformattable_const&>::value;
2290 static_assert(formattable_const, "Cannot format a const argument.");
2291
2292 // Formatting of arbitrary pointers is disallowed. If you want to output
2293 // a pointer cast it to "void *" or "const void *". In particular, this
2294 // forbids formatting of "[const] volatile char *" which is printed as bool
2295 // by iostreams.
2296 constexpr bool formattable_pointer =
2297 !std::is_same<decltype(arg), const unformattable_pointer&>::value;
2298 static_assert(formattable_pointer,
2299 "Formatting of non-void pointers is disallowed.");
2300
2301 constexpr bool formattable =
2302 !std::is_same<decltype(arg), const unformattable&>::value;
2303 static_assert(
2304 formattable,
2305 "Cannot format an argument. To make type T formattable provide a "
2306 "formatter<T> specialization: https://fmt.dev/latest/api.html#udt");
2307 return {arg};
2308}
2309
2310template <typename Context, typename T>
2312{
2315 arg.value_ = make_value<Context>(value);
2316 return arg;
2317}
2318
2319// The type template parameter is there to avoid an ODR violation when using
2320// a fallback formatter in one translation unit and an implicit conversion in
2321// another (not recommended).
2322template <bool IS_PACKED, typename Context, type, typename T, FMT_ENABLE_IF(IS_PACKED)>
2324{
2325 return make_value<Context>(val);
2326}
2327
2328template <bool IS_PACKED, typename Context, type, typename T, FMT_ENABLE_IF(!IS_PACKED)>
2330{
2331 return make_arg<Context>(value);
2332}
2334
2335// Formatting context.
2336template <typename OutputIt, typename Char>
2338{
2339public:
2341 using char_type = Char;
2342
2343private:
2344 OutputIt out_;
2346 detail::locale_ref loc_;
2347
2348public:
2349 using iterator = OutputIt;
2352 template <typename T>
2354
2357 void operator=(const basic_format_context&) = delete;
2363 OutputIt out, basic_format_args<basic_format_context> ctx_args, detail::locale_ref loc = detail::locale_ref())
2364 : out_(out), args_(ctx_args), loc_(loc)
2365 {
2366 }
2367
2368 constexpr auto arg(int id) const -> format_arg
2369 {
2370 return args_.get(id);
2371 }
2373 {
2374 return args_.get(name);
2375 }
2377 {
2378 return args_.get_id(name);
2379 }
2381 {
2382 return args_;
2383 }
2384
2385 FMT_CONSTEXPR auto error_handler() -> detail::error_handler
2386 {
2387 return {};
2388 }
2389 void on_error(const char* message)
2390 {
2391 error_handler().on_error(message);
2392 }
2393
2394 // Returns an iterator to the beginning of the output range.
2396 {
2397 return out_;
2398 }
2399
2400 // Advances the begin iterator to ``it``.
2402 {
2403 if (!detail::is_back_insert_iterator<iterator>())
2404 out_ = it;
2405 }
2406
2407 FMT_CONSTEXPR auto locale() -> detail::locale_ref
2408 {
2409 return loc_;
2410 }
2411};
2412
2413template <typename Char>
2417
2418// Workaround an alias issue: https://stackoverflow.com/q/62767544/471164.
2419#define FMT_BUFFER_CONTEXT(Char) \
2420 basic_format_context<detail::buffer_appender<Char>, Char>
2421
2422template <typename T, typename Char = char>
2424 !std::is_base_of<detail::unformattable,
2425 decltype(detail::arg_mapper<buffer_context<Char>>().map(
2426 std::declval<T>()))>::value &&
2427 !detail::has_fallback_formatter<T, Char>::value>;
2428
2436template <typename Context, typename... Args>
2439 // Workaround a GCC template argument substitution bug.
2441#endif
2442{
2443private:
2444 static const size_t num_args = sizeof...(Args);
2445 static const size_t num_named_args = detail::count_named_args<Args...>();
2446 static const bool is_packed = num_args <= detail::max_packed_args;
2447
2449
2450 detail::arg_data<value_type, typename Context::char_type, num_args, num_named_args>
2451 data_;
2452
2453 friend class basic_format_args<Context>;
2454
2455 static constexpr unsigned long long desc =
2456 (is_packed ? detail::encode_types<Context, Args...>()
2457 : detail::is_unpacked_bit | num_args) |
2458 (num_named_args != 0
2459 ? static_cast<unsigned long long>(detail::has_named_args_bit)
2460 : 0);
2461
2462public:
2463 template <typename... T>
2465 :
2467 basic_format_args<Context>(*this),
2468#endif
2469 data_{detail::make_arg<
2470 is_packed,
2471 Context,
2473 FMT_FORWARD(args))...}
2474 {
2475 detail::init_named_args(data_.named_args(), 0, 0, args...);
2476 }
2477};
2478
2487template <typename Context = format_context, typename... Args>
2488constexpr auto make_format_args(Args&&... args)
2490{
2491 return {FMT_FORWARD(args)...};
2492}
2493
2505template <typename Char, typename T>
2506inline auto arg(const Char* name, const T& arg) -> detail::named_arg<Char, T>
2507{
2508 static_assert(!detail::is_named_arg<T>(), "nested named arguments");
2509 return {name, arg};
2510}
2511
2522template <typename Context>
2524{
2525public:
2526 using size_type = int;
2528
2529private:
2530 // A descriptor that contains information about formatting arguments.
2531 // If the number of arguments is less or equal to max_packed_args then
2532 // argument types are passed in the descriptor. This reduces binary code size
2533 // per formatting function call.
2534 unsigned long long desc_;
2535 union {
2536 // If is_packed() returns true then argument values are stored in values_;
2537 // otherwise they are stored in args_. This is done to improve cache
2538 // locality and reduce compiled code size since storing larger objects
2539 // may require more code (at least on x86-64) even if the same amount of
2540 // data is actually copied to stack. It saves ~10% on the bloat test.
2541 const detail::value<Context>* values_;
2543 };
2544
2545 constexpr auto is_packed() const -> bool
2546 {
2547 return (desc_ & detail::is_unpacked_bit) == 0;
2548 }
2549 auto has_named_args() const -> bool
2550 {
2551 return (desc_ & detail::has_named_args_bit) != 0;
2552 }
2553
2554 FMT_CONSTEXPR auto type(int index) const -> detail::type
2555 {
2556 int shift = index * detail::packed_arg_bits;
2557 unsigned int mask = (1 << detail::packed_arg_bits) - 1;
2558 return static_cast<detail::type>((desc_ >> shift) & mask);
2559 }
2560
2561 constexpr FMT_INLINE basic_format_args(unsigned long long desc,
2562 const detail::value<Context>* values)
2563 : desc_(desc), values_(values)
2564 {
2565 }
2566 constexpr basic_format_args(unsigned long long desc, const format_arg* args)
2567 : desc_(desc), args_(args)
2568 {
2569 }
2570
2571public:
2573 : desc_(0), args_(nullptr)
2574 {
2575 }
2576
2582 template <typename... Args>
2585 : basic_format_args(format_arg_store<Context, Args...>::desc,
2586 store.data_.args())
2587 {
2588 }
2589
2598 : basic_format_args(store.get_types(), store.data())
2599 {
2600 }
2601
2607 constexpr basic_format_args(const format_arg* args, int count)
2609 args)
2610 {
2611 }
2612
2614 FMT_CONSTEXPR auto get(int id) const -> format_arg
2615 {
2617 if (!is_packed())
2618 {
2619 if (id < max_size())
2620 arg = args_[id];
2621 return arg;
2622 }
2623 if (id >= detail::max_packed_args)
2624 return arg;
2625 arg.type_ = type(id);
2626 if (arg.type_ == detail::type::none_type)
2627 return arg;
2628 arg.value_ = values_[id];
2629 return arg;
2630 }
2631
2632 template <typename Char>
2634 {
2635 int id = get_id(name);
2636 return id >= 0 ? get(id) : format_arg();
2637 }
2638
2639 template <typename Char>
2641 {
2642 if (!has_named_args())
2643 return -1;
2644 const auto& named_args =
2645 (is_packed() ? values_[-1] : args_[-1].value_).named_args;
2646 for (size_t i = 0; i < named_args.size; ++i)
2647 {
2648 if (named_args.data[i].name == name)
2649 return named_args.data[i].id;
2650 }
2651 return -1;
2652 }
2653
2654 auto max_size() const -> int
2655 {
2656 unsigned long long max_packed = detail::max_packed_args;
2657 return static_cast<int>(is_packed() ? max_packed
2658 : desc_ & ~detail::is_unpacked_bit);
2659 }
2660};
2661
2663// A separate type would result in shorter symbols but break ABI compatibility
2664// between clang and gcc on ARM (#1919).
2666
2667// We cannot use enum classes as bit fields because of a gcc bug, so we put them
2668// in namespaces instead (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414).
2669// Additionally, if an underlying type is specified, older gcc incorrectly warns
2670// that the type is too small. Both bugs are fixed in gcc 9.3.
2671#if FMT_GCC_VERSION && FMT_GCC_VERSION < 903
2672#define FMT_ENUM_UNDERLYING_TYPE(type)
2673#else
2674#define FMT_ENUM_UNDERLYING_TYPE(type) : type
2675#endif
2676namespace align
2677{
2678 enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char)
2679 {
2680 none,
2681 left,
2682 right,
2683 center,
2684 numeric
2685 };
2686}
2687using align_t = align::type;
2688namespace sign
2689{
2690 enum type FMT_ENUM_UNDERLYING_TYPE(unsigned char)
2691 {
2692 none,
2693 minus,
2694 plus,
2695 space
2696 };
2697}
2698using sign_t = sign::type;
2699
2701
2702// Workaround an array initialization issue in gcc 4.8.
2703template <typename Char>
2705{
2706private:
2707 enum
2708 {
2709 max_size = 4
2711 Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
2712 unsigned char size_ = 1;
2713
2714public:
2716 {
2717 auto size = s.size();
2718 if (size > max_size)
2719 return throw_format_error("invalid fill");
2720 for (size_t i = 0; i < size; ++i)
2721 data_[i] = s[i];
2722 size_ = static_cast<unsigned char>(size);
2723 }
2724
2725 constexpr auto size() const -> size_t
2726 {
2727 return size_;
2728 }
2729 constexpr auto data() const -> const Char*
2730 {
2731 return data_;
2732 }
2733
2734 FMT_CONSTEXPR auto operator[](size_t index) -> Char&
2735 {
2736 return data_[index];
2737 }
2738 FMT_CONSTEXPR auto operator[](size_t index) const -> const Char&
2739 {
2740 return data_[index];
2741 }
2742};
2744
2745enum class presentation_type : unsigned char
2746{
2747 none,
2748 // Integer types should go first,
2749 dec, // 'd'
2750 oct, // 'o'
2751 hex_lower, // 'x'
2752 hex_upper, // 'X'
2753 bin_lower, // 'b'
2754 bin_upper, // 'B'
2755 hexfloat_lower, // 'a'
2756 hexfloat_upper, // 'A'
2757 exp_lower, // 'e'
2758 exp_upper, // 'E'
2759 fixed_lower, // 'f'
2760 fixed_upper, // 'F'
2761 general_lower, // 'g'
2762 general_upper, // 'G'
2763 chr, // 'c'
2764 string, // 's'
2765 pointer, // 'p'
2766 debug // '?'
2767};
2768
2769// Format specifiers for built-in and string types.
2770template <typename Char>
2772{
2778 bool alt : 1; // Alternate form ('#').
2779 bool localized : 1;
2780 detail::fill_t<Char> fill;
2781
2783 : width(0),
2784 precision(-1),
2786 align(align::none),
2787 sign(sign::none),
2788 alt(false),
2789 localized(false)
2790 {
2791 }
2792};
2793
2795
2797
2798enum class arg_id_kind
2799{
2800 none,
2801 index,
2802 name
2803};
2804
2805// An argument reference.
2806template <typename Char>
2808{
2810 : kind(arg_id_kind::none), val()
2811 {
2812 }
2813
2815 : kind(arg_id_kind::index), val(index)
2816 {
2817 }
2819 : kind(arg_id_kind::name), val(name)
2820 {
2821 }
2822
2824 {
2825 kind = arg_id_kind::index;
2826 val.index = idx;
2827 return *this;
2828 }
2829
2831 union value {
2833 : index{id}
2834 {
2835 }
2840
2843 } val;
2844};
2845
2846// Format specifiers with width and precision resolved at formatting rather
2847// than parsing time to allow re-using the same parsed specifiers with
2848// different sets of arguments (precompilation of format strings).
2849template <typename Char>
2855
2857{
2858};
2859
2860// A format specifier handler that sets fields in basic_format_specs.
2861template <typename Char>
2863{
2864protected:
2866
2867public:
2869 : specs_(specs)
2870 {
2871 }
2872
2874 : specs_(other.specs_)
2875 {
2876 }
2877
2879 {
2880 specs_.align = align;
2881 }
2883 {
2884 specs_.fill = fill;
2885 }
2887 {
2888 specs_.sign = s;
2889 }
2891 {
2892 specs_.alt = true;
2893 }
2895 {
2896 specs_.localized = true;
2897 }
2898
2900 {
2901 if (specs_.align == align::none)
2902 specs_.align = align::numeric;
2903 specs_.fill[0] = Char('0');
2904 }
2905
2906 FMT_CONSTEXPR void on_width(int width)
2907 {
2908 specs_.width = width;
2909 }
2910 FMT_CONSTEXPR void on_precision(int precision)
2911 {
2912 specs_.precision = precision;
2913 }
2915 {
2916 }
2917
2919 {
2920 specs_.type = type;
2921 }
2922};
2923
2924// Format spec handler that saves references to arguments representing dynamic
2925// width and precision to be resolved at formatting time.
2926template <typename ParseContext>
2928 : public specs_setter<typename ParseContext::char_type>
2929{
2930public:
2931 using char_type = typename ParseContext::char_type;
2932
2934 ParseContext& ctx)
2935 : specs_setter<char_type>(specs), specs_(specs), context_(ctx)
2936 {
2937 }
2938
2940 : specs_setter<char_type>(other),
2941 specs_(other.specs_),
2942 context_(other.context_)
2943 {
2944 }
2945
2946 template <typename Id>
2948 {
2949 specs_.width_ref = make_arg_ref(arg_id);
2950 }
2951
2952 template <typename Id>
2954 {
2955 specs_.precision_ref = make_arg_ref(arg_id);
2956 }
2957
2958 FMT_CONSTEXPR void on_error(const char* message)
2959 {
2960 context_.on_error(message);
2961 }
2962
2963private:
2965 ParseContext& context_;
2966
2968
2970 {
2971 context_.check_arg_id(arg_id);
2972 context_.check_dynamic_spec(arg_id);
2973 return arg_ref_type(arg_id);
2974 }
2975
2977 {
2978 int arg_id = context_.next_arg_id();
2979 context_.check_dynamic_spec(arg_id);
2980 return arg_ref_type(arg_id);
2981 }
2982
2984 -> arg_ref_type
2985 {
2986 context_.check_arg_id(arg_id);
2988 context_.begin(), to_unsigned(context_.end() - context_.begin()));
2989 return arg_ref_type(arg_id);
2990 }
2991};
2992
2993template <typename Char>
2994constexpr bool is_ascii_letter(Char c)
2995{
2996 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
2997}
2998
2999// Converts a character to ASCII. Returns a number > 127 on conversion failure.
3000template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
3001constexpr auto to_ascii(Char c) -> Char
3002{
3003 return c;
3004}
3005template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
3006constexpr auto to_ascii(Char c) -> underlying_t<Char>
3007{
3008 return c;
3009}
3010
3011FMT_CONSTEXPR inline auto code_point_length_impl(char c) -> int
3012{
3013 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"
3014 [static_cast<unsigned char>(c) >> 3];
3015}
3016
3017template <typename Char>
3018FMT_CONSTEXPR auto code_point_length(const Char* begin) -> int
3019{
3020 if (const_check(sizeof(Char) != 1))
3021 return 1;
3022 int len = code_point_length_impl(static_cast<char>(*begin));
3023
3024 // Compute the pointer to the next character early so that the next
3025 // iteration can start working on the next character. Neither Clang
3026 // nor GCC figure out this reordering on their own.
3027 return len + !len;
3028}
3029
3030// Return the result via the out param to workaround gcc bug 77539.
3031template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
3032FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr& out) -> bool
3033{
3034 for (out = first; out != last; ++out)
3035 {
3036 if (*out == value)
3037 return true;
3038 }
3039 return false;
3040}
3041
3042template <>
3043inline auto find<false, char>(const char* first, const char* last, char value, const char*& out) -> bool
3044{
3045 out = static_cast<const char*>(
3046 std::memchr(first, value, to_unsigned(last - first)));
3047 return out != nullptr;
3048}
3049
3050// Parses the range [begin, end) as an unsigned integer. This function assumes
3051// that the range is non-empty and the first character is a digit.
3052template <typename Char>
3053FMT_CONSTEXPR auto parse_nonnegative_int(const Char*& begin, const Char* end, int error_value) noexcept -> int
3054{
3055 FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
3056 unsigned value = 0, prev = 0;
3057 auto p = begin;
3058 do
3059 {
3060 prev = value;
3061 value = value * 10 + unsigned(*p - '0');
3062 ++p;
3063 } while (p != end && '0' <= *p && *p <= '9');
3064 auto num_digits = p - begin;
3065 begin = p;
3066 if (num_digits <= std::numeric_limits<int>::digits10)
3067 return static_cast<int>(value);
3068 // Check for overflow.
3069 const unsigned max = to_unsigned((std::numeric_limits<int>::max)());
3070 return num_digits == std::numeric_limits<int>::digits10 + 1 &&
3071 prev * 10ull + unsigned(p[-1] - '0') <= max
3072 ? static_cast<int>(value)
3073 : error_value;
3074}
3075
3076// Parses fill and alignment.
3077template <typename Char, typename Handler>
3078FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, Handler&& handler) -> const Char*
3079{
3080 FMT_ASSERT(begin != end, "");
3081 auto align = align::none;
3082 auto p = begin + code_point_length(begin);
3083 if (end - p <= 0)
3084 p = begin;
3085 for (;;)
3086 {
3087 switch (to_ascii(*p))
3088 {
3089 case '<':
3090 align = align::left;
3091 break;
3092 case '>':
3093 align = align::right;
3094 break;
3095 case '^':
3096 align = align::center;
3097 break;
3098 default:
3099 break;
3100 }
3101 if (align != align::none)
3102 {
3103 if (p != begin)
3104 {
3105 auto c = *begin;
3106 if (c == '{')
3107 return handler.on_error("invalid fill character '{'"), begin;
3108 handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin)));
3109 begin = p + 1;
3110 }
3111 else
3112 ++begin;
3113 handler.on_align(align);
3114 break;
3115 }
3116 else if (p == begin)
3117 {
3118 break;
3119 }
3120 p = begin;
3121 }
3122 return begin;
3123}
3124
3125template <typename Char>
3127{
3128 return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
3129}
3130
3131template <typename Char, typename IDHandler>
3132FMT_CONSTEXPR auto do_parse_arg_id(const Char* begin, const Char* end, IDHandler&& handler) -> const Char*
3133{
3134 FMT_ASSERT(begin != end, "");
3135 Char c = *begin;
3136 if (c >= '0' && c <= '9')
3137 {
3138 int index = 0;
3139 if (c != '0')
3140 index =
3141 parse_nonnegative_int(begin, end, (std::numeric_limits<int>::max)());
3142 else
3143 ++begin;
3144 if (begin == end || (*begin != '}' && *begin != ':'))
3145 handler.on_error("invalid format string");
3146 else
3147 handler(index);
3148 return begin;
3149 }
3150 if (!is_name_start(c))
3151 {
3152 handler.on_error("invalid format string");
3153 return begin;
3154 }
3155 auto it = begin;
3156 do
3157 {
3158 ++it;
3159 } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9')));
3160 handler(basic_string_view<Char>(begin, to_unsigned(it - begin)));
3161 return it;
3162}
3163
3164template <typename Char, typename IDHandler>
3165FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char* begin, const Char* end, IDHandler&& handler) -> const Char*
3166{
3167 Char c = *begin;
3168 if (c != '}' && c != ':')
3169 return do_parse_arg_id(begin, end, handler);
3170 handler();
3171 return begin;
3172}
3173
3174template <typename Char, typename Handler>
3175FMT_CONSTEXPR auto parse_width(const Char* begin, const Char* end, Handler&& handler) -> const Char*
3176{
3177 using detail::auto_id;
3178 struct width_adapter
3179 {
3180 Handler& handler;
3181
3182 FMT_CONSTEXPR void operator()()
3183 {
3184 handler.on_dynamic_width(auto_id());
3185 }
3186 FMT_CONSTEXPR void operator()(int id)
3187 {
3188 handler.on_dynamic_width(id);
3189 }
3190 FMT_CONSTEXPR void operator()(basic_string_view<Char> id)
3191 {
3192 handler.on_dynamic_width(id);
3193 }
3194 FMT_CONSTEXPR void on_error(const char* message)
3195 {
3196 if (message)
3197 handler.on_error(message);
3198 }
3199 };
3200
3201 FMT_ASSERT(begin != end, "");
3202 if ('0' <= *begin && *begin <= '9')
3203 {
3204 int width = parse_nonnegative_int(begin, end, -1);
3205 if (width != -1)
3206 handler.on_width(width);
3207 else
3208 handler.on_error("number is too big");
3209 }
3210 else if (*begin == '{')
3211 {
3212 ++begin;
3213 if (begin != end)
3214 begin = parse_arg_id(begin, end, width_adapter{handler});
3215 if (begin == end || *begin != '}')
3216 return handler.on_error("invalid format string"), begin;
3217 ++begin;
3218 }
3219 return begin;
3220}
3221
3222template <typename Char, typename Handler>
3223FMT_CONSTEXPR auto parse_precision(const Char* begin, const Char* end, Handler&& handler) -> const Char*
3224{
3225 using detail::auto_id;
3226 struct precision_adapter
3227 {
3228 Handler& handler;
3229
3230 FMT_CONSTEXPR void operator()()
3231 {
3232 handler.on_dynamic_precision(auto_id());
3233 }
3234 FMT_CONSTEXPR void operator()(int id)
3235 {
3236 handler.on_dynamic_precision(id);
3237 }
3238 FMT_CONSTEXPR void operator()(basic_string_view<Char> id)
3239 {
3240 handler.on_dynamic_precision(id);
3241 }
3242 FMT_CONSTEXPR void on_error(const char* message)
3243 {
3244 if (message)
3245 handler.on_error(message);
3246 }
3247 };
3248
3249 ++begin;
3250 auto c = begin != end ? *begin : Char();
3251 if ('0' <= c && c <= '9')
3252 {
3253 auto precision = parse_nonnegative_int(begin, end, -1);
3254 if (precision != -1)
3255 handler.on_precision(precision);
3256 else
3257 handler.on_error("number is too big");
3258 }
3259 else if (c == '{')
3260 {
3261 ++begin;
3262 if (begin != end)
3263 begin = parse_arg_id(begin, end, precision_adapter{handler});
3264 if (begin == end || *begin++ != '}')
3265 return handler.on_error("invalid format string"), begin;
3266 }
3267 else
3268 {
3269 return handler.on_error("missing precision specifier"), begin;
3270 }
3271 handler.end_precision();
3272 return begin;
3273}
3274
3275template <typename Char>
3277{
3278 switch (to_ascii(type))
3279 {
3280 case 'd':
3282 case 'o':
3284 case 'x':
3286 case 'X':
3288 case 'b':
3290 case 'B':
3292 case 'a':
3294 case 'A':
3296 case 'e':
3298 case 'E':
3300 case 'f':
3302 case 'F':
3304 case 'g':
3306 case 'G':
3308 case 'c':
3310 case 's':
3312 case 'p':
3314 case '?':
3316 default:
3318 }
3319}
3320
3321// Parses standard format specifiers and sends notifications about parsed
3322// components to handler.
3323template <typename Char, typename SpecHandler>
3325 const Char* end,
3326 SpecHandler&& handler)
3327 -> const Char*
3328{
3329 if (1 < end - begin && begin[1] == '}' && is_ascii_letter(*begin) &&
3330 *begin != 'L')
3331 {
3334 handler.on_error("invalid type specifier");
3335 handler.on_type(type);
3336 return begin;
3337 }
3338
3339 if (begin == end)
3340 return begin;
3341
3342 begin = parse_align(begin, end, handler);
3343 if (begin == end)
3344 return begin;
3345
3346 // Parse sign.
3347 switch (to_ascii(*begin))
3348 {
3349 case '+':
3350 handler.on_sign(sign::plus);
3351 ++begin;
3352 break;
3353 case '-':
3354 handler.on_sign(sign::minus);
3355 ++begin;
3356 break;
3357 case ' ':
3358 handler.on_sign(sign::space);
3359 ++begin;
3360 break;
3361 default:
3362 break;
3363 }
3364 if (begin == end)
3365 return begin;
3366
3367 if (*begin == '#')
3368 {
3369 handler.on_hash();
3370 if (++begin == end)
3371 return begin;
3372 }
3373
3374 // Parse zero flag.
3375 if (*begin == '0')
3376 {
3377 handler.on_zero();
3378 if (++begin == end)
3379 return begin;
3380 }
3381
3382 begin = parse_width(begin, end, handler);
3383 if (begin == end)
3384 return begin;
3385
3386 // Parse precision.
3387 if (*begin == '.')
3388 {
3389 begin = parse_precision(begin, end, handler);
3390 if (begin == end)
3391 return begin;
3392 }
3393
3394 if (*begin == 'L')
3395 {
3396 handler.on_localized();
3397 ++begin;
3398 }
3399
3400 // Parse type.
3401 if (begin != end && *begin != '}')
3402 {
3405 handler.on_error("invalid type specifier");
3406 handler.on_type(type);
3407 }
3408 return begin;
3409}
3410
3411template <typename Char, typename Handler>
3412FMT_CONSTEXPR auto parse_replacement_field(const Char* begin, const Char* end, Handler&& handler) -> const Char*
3413{
3414 struct id_adapter
3415 {
3416 Handler& handler;
3417 int arg_id;
3418
3419 FMT_CONSTEXPR void operator()()
3420 {
3421 arg_id = handler.on_arg_id();
3422 }
3423 FMT_CONSTEXPR void operator()(int id)
3424 {
3425 arg_id = handler.on_arg_id(id);
3426 }
3427 FMT_CONSTEXPR void operator()(basic_string_view<Char> id)
3428 {
3429 arg_id = handler.on_arg_id(id);
3430 }
3431 FMT_CONSTEXPR void on_error(const char* message)
3432 {
3433 if (message)
3434 handler.on_error(message);
3435 }
3436 };
3437
3438 ++begin;
3439 if (begin == end)
3440 return handler.on_error("invalid format string"), end;
3441 if (*begin == '}')
3442 {
3443 handler.on_replacement_field(handler.on_arg_id(), begin);
3444 }
3445 else if (*begin == '{')
3446 {
3447 handler.on_text(begin, begin + 1);
3448 }
3449 else
3450 {
3451 auto adapter = id_adapter{handler, 0};
3452 begin = parse_arg_id(begin, end, adapter);
3453 Char c = begin != end ? *begin : Char();
3454 if (c == '}')
3455 {
3456 handler.on_replacement_field(adapter.arg_id, begin);
3457 }
3458 else if (c == ':')
3459 {
3460 begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
3461 if (begin == end || *begin != '}')
3462 return handler.on_error("unknown format specifier"), end;
3463 }
3464 else
3465 {
3466 return handler.on_error("missing '}' in format string"), end;
3467 }
3468 }
3469 return begin + 1;
3470}
3471
3472template <bool IS_CONSTEXPR, typename Char, typename Handler>
3474 basic_string_view<Char> format_str, Handler&& handler)
3475{
3476 // Workaround a name-lookup bug in MSVC's modules implementation.
3477 using detail::find;
3478
3479 auto begin = format_str.data();
3480 auto end = begin + format_str.size();
3481 if (end - begin < 32)
3482 {
3483 // Use a simple loop instead of memchr for small strings.
3484 const Char* p = begin;
3485 while (p != end)
3486 {
3487 auto c = *p++;
3488 if (c == '{')
3489 {
3490 handler.on_text(begin, p - 1);
3491 begin = p = parse_replacement_field(p - 1, end, handler);
3492 }
3493 else if (c == '}')
3494 {
3495 if (p == end || *p != '}')
3496 return handler.on_error("unmatched '}' in format string");
3497 handler.on_text(begin, p);
3498 begin = ++p;
3499 }
3500 }
3501 handler.on_text(begin, end);
3502 return;
3503 }
3504 struct writer
3505 {
3506 FMT_CONSTEXPR void operator()(const Char* from, const Char* to)
3507 {
3508 if (from == to)
3509 return;
3510 for (;;)
3511 {
3512 const Char* p = nullptr;
3513 if (!find<IS_CONSTEXPR>(from, to, Char('}'), p))
3514 return handler_.on_text(from, to);
3515 ++p;
3516 if (p == to || *p != '}')
3517 return handler_.on_error("unmatched '}' in format string");
3518 handler_.on_text(from, p);
3519 from = p + 1;
3520 }
3521 }
3522 Handler& handler_;
3523 } write = {handler};
3524 while (begin != end)
3525 {
3526 // Doing two passes with memchr (one for '{' and another for '}') is up to
3527 // 2.5x faster than the naive one-pass implementation on big format strings.
3528 const Char* p = begin;
3529 if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, Char('{'), p))
3530 return write(begin, end);
3531 write(begin, p);
3532 begin = parse_replacement_field(p, end, handler);
3533 }
3534}
3535
3536template <typename T, bool = is_named_arg<T>::value>
3538{
3539 using type = T;
3540};
3541template <typename T>
3542struct strip_named_arg<T, true>
3543{
3544 using type = remove_cvref_t<decltype(T::value)>;
3545};
3546
3547template <typename T, typename ParseContext>
3548FMT_CONSTEXPR auto parse_format_specs(ParseContext& ctx)
3549 -> decltype(ctx.begin())
3550{
3551 using char_type = typename ParseContext::char_type;
3552 using context = buffer_context<char_type>;
3553 using stripped_type = typename strip_named_arg<T>::type;
3554 using mapped_type = conditional_t<
3556 decltype(arg_mapper<context>().map(std::declval<const T&>())),
3557 stripped_type>;
3561 return f.parse(ctx);
3562}
3563
3564template <typename ErrorHandler>
3566 ErrorHandler&& eh)
3567{
3569 eh.on_error("invalid type specifier");
3570}
3571
3572// Checks char specs and returns true if the type spec is char (and not int).
3573template <typename Char, typename ErrorHandler = error_handler>
3575 ErrorHandler&& eh = {}) -> bool
3576{
3577 if (specs.type != presentation_type::none &&
3578 specs.type != presentation_type::chr &&
3580 {
3581 check_int_type_spec(specs.type, eh);
3582 return false;
3583 }
3584 if (specs.align == align::numeric || specs.sign != sign::none || specs.alt)
3585 eh.on_error("invalid format specifier for char");
3586 return true;
3587}
3588
3589// A floating-point presentation format.
3590enum class float_format : unsigned char
3591{
3592 general, // General: exponent notation or fixed point based on magnitude.
3593 exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
3594 fixed, // Fixed point with the default precision of 6, e.g. 0.0012.
3595 hex
3596};
3597
3599{
3603 bool upper : 1;
3604 bool locale : 1;
3605 bool binary32 : 1;
3606 bool showpoint : 1;
3607};
3608
3609template <typename ErrorHandler = error_handler, typename Char>
3611 ErrorHandler&& eh = {})
3612 -> float_specs
3613{
3614 auto result = float_specs();
3615 result.showpoint = specs.alt;
3616 result.locale = specs.localized;
3617 switch (specs.type)
3618 {
3621 break;
3623 result.upper = true;
3627 break;
3629 result.upper = true;
3632 result.format = float_format::exp;
3633 result.showpoint |= specs.precision != 0;
3634 break;
3636 result.upper = true;
3639 result.format = float_format::fixed;
3640 result.showpoint |= specs.precision != 0;
3641 break;
3643 result.upper = true;
3646 result.format = float_format::hex;
3647 break;
3648 default:
3649 eh.on_error("invalid type specifier");
3650 break;
3651 }
3652 return result;
3653}
3654
3655template <typename ErrorHandler = error_handler>
3657 ErrorHandler&& eh = {}) -> bool
3658{
3661 return true;
3663 eh.on_error("invalid type specifier");
3664 return false;
3665}
3666
3667template <typename ErrorHandler = error_handler>
3669 ErrorHandler&& eh = {})
3670{
3673 eh.on_error("invalid type specifier");
3674}
3675
3676template <typename ErrorHandler>
3678 ErrorHandler&& eh)
3679{
3681 eh.on_error("invalid type specifier");
3682}
3683
3684// A parse_format_specs handler that checks if specifiers are consistent with
3685// the argument type.
3686template <typename Handler>
3687class specs_checker : public Handler
3688{
3689private:
3690 detail::type arg_type_;
3691
3693 {
3694 if (!is_arithmetic_type(arg_type_))
3695 this->on_error("format specifier requires numeric argument");
3696 }
3697
3698public:
3699 FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type)
3700 : Handler(handler), arg_type_(arg_type)
3701 {
3702 }
3703
3705 {
3706 if (align == align::numeric)
3707 require_numeric_argument();
3708 Handler::on_align(align);
3709 }
3710
3712 {
3713 require_numeric_argument();
3714 if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
3715 arg_type_ != type::long_long_type && arg_type_ != type::int128_type &&
3716 arg_type_ != type::char_type)
3717 {
3718 this->on_error("format specifier requires signed argument");
3719 }
3720 Handler::on_sign(s);
3721 }
3722
3724 {
3725 require_numeric_argument();
3726 Handler::on_hash();
3727 }
3728
3730 {
3731 require_numeric_argument();
3732 Handler::on_localized();
3733 }
3734
3736 {
3737 require_numeric_argument();
3738 Handler::on_zero();
3739 }
3740
3742 {
3743 if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type)
3744 this->on_error("precision not allowed for this argument type");
3745 }
3746};
3747
3748constexpr int invalid_arg_index = -1;
3749
3750#if FMT_USE_NONTYPE_TEMPLATE_ARGS
3751template <int N, typename T, typename... Args, typename Char>
3753{
3754 if constexpr (detail::is_statically_named_arg<T>())
3755 {
3756 if (name == T::name)
3757 return N;
3758 }
3759 if constexpr (sizeof...(Args) > 0)
3760 return get_arg_index_by_name<N + 1, Args...>(name);
3761 (void)name; // Workaround an MSVC bug about "unused" parameter.
3762 return invalid_arg_index;
3763}
3764#endif
3765
3766template <typename... Args, typename Char>
3768{
3769#if FMT_USE_NONTYPE_TEMPLATE_ARGS
3770 if constexpr (sizeof...(Args) > 0)
3771 return get_arg_index_by_name<0, Args...>(name);
3772#endif
3773 (void)name;
3774 return invalid_arg_index;
3775}
3776
3777template <typename Char, typename ErrorHandler, typename... Args>
3779{
3780private:
3781 // In the future basic_format_parse_context will replace compile_parse_context
3782 // here and will use is_constant_evaluated and downcasting to access the data
3783 // needed for compile-time checks: https://godbolt.org/z/GvWzcTjh1.
3785 static constexpr int num_args = sizeof...(Args);
3786
3787 // Format specifier parsing function.
3788 using parse_func = const Char* (*)(parse_context_type&);
3789
3791 parse_func parse_funcs_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
3792 type types_[num_args > 0 ? static_cast<size_t>(num_args) : 1];
3793
3794public:
3796 basic_string_view<Char> format_str, ErrorHandler eh)
3797 : context_(format_str, num_args, types_, eh),
3798 parse_funcs_{&parse_format_specs<Args, parse_context_type>...},
3799 types_{
3801 basic_format_context<Char*, Char>>::value...}
3802 {
3803 }
3804
3805 FMT_CONSTEXPR void on_text(const Char*, const Char*)
3806 {
3807 }
3808
3810 {
3811 return context_.next_arg_id();
3812 }
3813 FMT_CONSTEXPR auto on_arg_id(int id) -> int
3814 {
3815 return context_.check_arg_id(id), id;
3816 }
3818 {
3819#if FMT_USE_NONTYPE_TEMPLATE_ARGS
3820 auto index = get_arg_index_by_name<Args...>(id);
3821 if (index == invalid_arg_index)
3822 on_error("named argument is not found");
3823 return context_.check_arg_id(index), index;
3824#else
3825 (void)id;
3826 on_error("compile-time checks for named arguments require C++20 support");
3827 return 0;
3828#endif
3829 }
3830
3832 {
3833 }
3834
3835 FMT_CONSTEXPR auto on_format_specs(int id, const Char* begin, const Char*)
3836 -> const Char*
3837 {
3838 context_.advance_to(context_.begin() + (begin - &*context_.begin()));
3839 // id >= 0 check is a workaround for gcc 10 bug (#2065).
3840 return id >= 0 && id < num_args ? parse_funcs_[id](context_) : begin;
3841 }
3842
3843 FMT_CONSTEXPR void on_error(const char* message)
3844 {
3845 context_.on_error(message);
3846 }
3847};
3848
3849// Reports a compile-time error if S is not a valid format string.
3850template <typename..., typename S, FMT_ENABLE_IF(!is_compile_string<S>::value)>
3852{
3853#ifdef FMT_ENFORCE_COMPILE_STRING
3854 static_assert(is_compile_string<S>::value,
3855 "FMT_ENFORCE_COMPILE_STRING requires all format strings to use "
3856 "FMT_STRING.");
3857#endif
3858}
3859template <typename... Args, typename S, FMT_ENABLE_IF(is_compile_string<S>::value)>
3860void check_format_string(S format_str)
3861{
3863 using checker = format_string_checker<typename S::char_type, error_handler,
3865 FMT_CONSTEXPR bool invalid_format =
3866 (parse_format_string<true>(s, checker(s, {})), true);
3867 ignore_unused(invalid_format);
3868}
3869
3870template <typename Char>
3871void vformat_to(
3873
3875#ifndef _WIN32
3876inline void vprint_mojibake(std::FILE*, string_view, format_args)
3877{
3878}
3879#endif
3881
3882// A formatter specialization for the core types corresponding to detail::type
3883// constants.
3884template <typename T, typename Char>
3885struct formatter<T, Char, enable_if_t<detail::type_constant<T, Char>::value != detail::type::custom_type>>
3886{
3887private:
3888 detail::dynamic_format_specs<Char> specs_;
3889
3890public:
3891 // Parses format specifiers stopping either at the end of the range or at the
3892 // terminating '}'.
3893 template <typename ParseContext>
3894 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin())
3895 {
3896 auto begin = ctx.begin(), end = ctx.end();
3897 if (begin == end)
3898 return begin;
3899 using handler_type = detail::dynamic_specs_handler<ParseContext>;
3900 auto type = detail::type_constant<T, Char>::value;
3901 auto checker =
3902 detail::specs_checker<handler_type>(handler_type(specs_, ctx), type);
3903 auto it = detail::parse_format_specs(begin, end, checker);
3904 auto eh = ctx.error_handler();
3905 switch (type)
3906 {
3907 case detail::type::none_type:
3908 FMT_ASSERT(false, "invalid argument type");
3909 break;
3910 case detail::type::bool_type:
3911 if (specs_.type == presentation_type::none ||
3912 specs_.type == presentation_type::string)
3913 {
3914 break;
3915 }
3917 case detail::type::int_type:
3918 case detail::type::uint_type:
3919 case detail::type::long_long_type:
3920 case detail::type::ulong_long_type:
3921 case detail::type::int128_type:
3922 case detail::type::uint128_type:
3923 detail::check_int_type_spec(specs_.type, eh);
3924 break;
3925 case detail::type::char_type:
3926 detail::check_char_specs(specs_, eh);
3927 break;
3928 case detail::type::float_type:
3929 if (detail::const_check(FMT_USE_FLOAT))
3930 detail::parse_float_type_spec(specs_, eh);
3931 else
3932 FMT_ASSERT(false, "float support disabled");
3933 break;
3934 case detail::type::double_type:
3935 if (detail::const_check(FMT_USE_DOUBLE))
3936 detail::parse_float_type_spec(specs_, eh);
3937 else
3938 FMT_ASSERT(false, "double support disabled");
3939 break;
3940 case detail::type::long_double_type:
3941 if (detail::const_check(FMT_USE_LONG_DOUBLE))
3942 detail::parse_float_type_spec(specs_, eh);
3943 else
3944 FMT_ASSERT(false, "long double support disabled");
3945 break;
3946 case detail::type::cstring_type:
3947 detail::check_cstring_type_spec(specs_.type, eh);
3948 break;
3949 case detail::type::string_type:
3950 detail::check_string_type_spec(specs_.type, eh);
3951 break;
3952 case detail::type::pointer_type:
3953 detail::check_pointer_type_spec(specs_.type, eh);
3954 break;
3955 case detail::type::custom_type:
3956 // Custom format specifiers are checked in parse functions of
3957 // formatter specializations.
3958 break;
3959 }
3960 return it;
3961 }
3962
3963 template <detail::type U = detail::type_constant<T, Char>::value,
3964 enable_if_t<(U == detail::type::string_type ||
3965 U == detail::type::cstring_type ||
3966 U == detail::type::char_type),
3967 int> = 0>
3969 {
3970 specs_.type = presentation_type::debug;
3971 }
3972
3973 template <typename FormatContext>
3974 FMT_CONSTEXPR auto format(const T& val, FormatContext& ctx) const
3975 -> decltype(ctx.out());
3976};
3977
3978#define FMT_FORMAT_AS(Type, Base) \
3979 template <typename Char> \
3980 struct formatter<Type, Char> : formatter<Base, Char> \
3981 { \
3982 template <typename FormatContext> \
3983 auto format(Type const& val, FormatContext& ctx) const \
3984 -> decltype(ctx.out()) \
3985 { \
3986 return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
3987 } \
3988 }
3989
3990FMT_FORMAT_AS(signed char, int);
3991FMT_FORMAT_AS(unsigned char, unsigned);
3992FMT_FORMAT_AS(short, int);
3993FMT_FORMAT_AS(unsigned short, unsigned);
3994FMT_FORMAT_AS(long, long long);
3995FMT_FORMAT_AS(unsigned long, unsigned long long);
3996FMT_FORMAT_AS(Char*, const Char*);
3997FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
3998FMT_FORMAT_AS(std::nullptr_t, const void*);
3999FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
4000
4001template <typename Char>
4006
4008template <typename Char, typename... Args>
4010{
4011private:
4013
4014public:
4015 template <typename S,
4017 std::is_convertible<const S&, basic_string_view<Char>>::value)>
4019 : str_(s)
4020 {
4021 static_assert(
4022 detail::count<
4023 (std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
4024 std::is_reference<Args>::value)...>() == 0,
4025 "passing views as lvalues is disallowed");
4026#ifdef FMT_HAS_CONSTEVAL
4027 if constexpr (detail::count_named_args<Args...>() ==
4028 detail::count_statically_named_args<Args...>())
4029 {
4030 using checker = detail::format_string_checker<Char, detail::error_handler,
4032 detail::parse_format_string<true>(str_, checker(s, {}));
4033 }
4034#else
4035 detail::check_format_string<Args...>(s);
4036#endif
4037 }
4039 : str_(r.str)
4040 {
4041 }
4042
4044 {
4045 return str_;
4046 }
4047};
4048
4049#if FMT_GCC_VERSION && FMT_GCC_VERSION < 409
4050// Workaround broken conversion on older gcc.
4051template <typename...>
4053inline auto runtime(string_view s) -> string_view
4054{
4055 return s;
4056}
4057#else
4058template <typename... Args>
4071{
4072 return {{s}};
4073}
4074#endif
4075
4076FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
4077
4089template <typename... T>
4091 -> std::string
4092{
4093 return vformat(fmt, fmt::make_format_args(args...));
4094}
4095
4097template <typename OutputIt,
4098 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
4099auto vformat_to(OutputIt out, string_view fmt, format_args args) -> OutputIt
4100{
4101 using detail::get_buffer;
4102 auto&& buf = get_buffer<char>(out);
4103 detail::vformat_to(buf, fmt, args, {});
4104 return detail::get_iterator(buf);
4105}
4106
4119template <typename OutputIt, typename... T, FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
4120FMT_INLINE auto format_to(OutputIt out, format_string<T...> fmt, T&&... args)
4121 -> OutputIt
4122{
4123 return vformat_to(out, fmt, fmt::make_format_args(args...));
4124}
4125
4126template <typename OutputIt>
4128{
4130 OutputIt out;
4132 size_t size;
4133};
4134
4135template <typename OutputIt, typename... T, FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
4136auto vformat_to_n(OutputIt out, size_t n, string_view fmt, format_args args)
4138{
4139 using traits = detail::fixed_buffer_traits;
4140 auto buf = detail::iterator_buffer<OutputIt, char, traits>(out, n);
4141 detail::vformat_to(buf, fmt, args, {});
4142 return {buf.out(), buf.count()};
4143}
4144
4153template <typename OutputIt, typename... T, FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value)>
4155{
4156 return vformat_to_n(out, n, fmt, fmt::make_format_args(args...));
4157}
4158
4160template <typename... T>
4162 T&&... args) -> size_t
4163{
4164 auto buf = detail::counting_buffer<>();
4165 detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...), {});
4166 return buf.count();
4167}
4168
4170FMT_API void vprint(std::FILE* f, string_view fmt, format_args args);
4171
4182template <typename... T>
4184{
4185 const auto& vargs = fmt::make_format_args(args...);
4186 return detail::is_utf8() ? vprint(fmt, vargs)
4187 : detail::vprint_mojibake(stdout, fmt, vargs);
4188}
4189
4200template <typename... T>
4201FMT_INLINE void print(std::FILE* f, format_string<T...> fmt, T&&... args)
4202{
4203 const auto& vargs = fmt::make_format_args(args...);
4204 return detail::is_utf8() ? vprint(f, fmt, vargs)
4205 : detail::vprint_mojibake(f, fmt, vargs);
4206}
4207
4209FMT_GCC_PRAGMA("GCC pop_options")
4211
4212#ifdef FMT_HEADER_ONLY
4213#include "format.h"
4214#endif
4215#endif // FMT_CORE_H_
Definition core.h:2023
appender(base it) noexcept
Definition core.h:2034
auto operator++() noexcept -> appender &
Definition core.h:2040
std::back_insert_iterator< detail::buffer< char > > base
Definition core.h:2024
auto operator++(int) noexcept -> appender
Definition core.h:2044
FMT_UNCHECKED_ITERATOR(appender)
friend auto get_buffer(appender out) -> detail::buffer< char > &
Definition core.h:2027
Definition core.h:2083
void format(typename Context::parse_context_type &parse_ctx, Context &ctx) const
Definition core.h:2090
handle(detail::custom_value< Context > custom)
Definition core.h:2085
detail::custom_value< Context > custom_
Definition core.h:2097
Definition core.h:2054
constexpr basic_format_arg()
Definition core.h:2100
detail::type type_
Definition core.h:2057
auto type() const -> detail::type
Definition core.h:2110
basic_format_arg(const detail::named_arg_info< char_type > *args, size_t size)
Definition core.h:2076
typename Context::char_type char_type
Definition core.h:2071
detail::value< Context > value_
Definition core.h:2056
friend struct detail::arg_data
Definition core.h:2074
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:2119
auto is_integral() const -> bool
Definition core.h:2115
friend FMT_CONSTEXPR auto detail::make_arg(T &&value) -> basic_format_arg< ContextType >
Definition core.h:2524
constexpr basic_format_args()
Definition core.h:2572
const format_arg * args_
Definition core.h:2542
constexpr basic_format_args(unsigned long long desc, const format_arg *args)
Definition core.h:2566
constexpr basic_format_args(const format_arg *args, int count)
Definition core.h:2607
FMT_CONSTEXPR auto get(int id) const -> format_arg
Definition core.h:2614
const detail::value< Context > * values_
Definition core.h:2541
constexpr FMT_INLINE basic_format_args(unsigned long long desc, const detail::value< Context > *values)
Definition core.h:2561
FMT_CONSTEXPR auto type(int index) const -> detail::type
Definition core.h:2554
constexpr FMT_INLINE basic_format_args(const dynamic_format_arg_store< Context > &store)
Definition core.h:2596
int size_type
Definition core.h:2526
auto max_size() const -> int
Definition core.h:2654
auto has_named_args() const -> bool
Definition core.h:2549
constexpr auto is_packed() const -> bool
Definition core.h:2545
auto get(basic_string_view< Char > name) const -> format_arg
Definition core.h:2633
constexpr FMT_INLINE basic_format_args(const format_arg_store< Context, Args... > &store)
Definition core.h:2583
unsigned long long desc_
Definition core.h:2534
basic_format_arg< Context > format_arg
Definition core.h:2527
auto get_id(basic_string_view< Char > name) const -> int
Definition core.h:2640
Definition core.h:2338
formatter< T, char_type > formatter_type
Definition core.h:2353
basic_format_context(const basic_format_context &)=delete
detail::locale_ref loc_
Definition core.h:2346
OutputIt iterator
Definition core.h:2349
FMT_CONSTEXPR auto locale() -> detail::locale_ref
Definition core.h:2407
basic_format_arg< basic_format_context > format_arg
Definition core.h:2350
FMT_CONSTEXPR auto out() -> iterator
Definition core.h:2395
FMT_CONSTEXPR auto arg(basic_string_view< char_type > name) -> format_arg
Definition core.h:2372
Char char_type
Definition core.h:2341
FMT_CONSTEXPR auto arg_id(basic_string_view< char_type > name) -> int
Definition core.h:2376
void on_error(const char *message)
Definition core.h:2389
OutputIt out_
Definition core.h:2344
basic_format_parse_context< Char > parse_context_type
Definition core.h:2351
FMT_CONSTEXPR auto error_handler() -> detail::error_handler
Definition core.h:2385
constexpr auto arg(int id) const -> format_arg
Definition core.h:2368
auto args() const -> const basic_format_args< basic_format_context > &
Definition core.h:2380
void advance_to(iterator it)
Definition core.h:2401
constexpr basic_format_context(OutputIt out, basic_format_args< basic_format_context > ctx_args, detail::locale_ref loc=detail::locale_ref())
Definition core.h:2362
basic_format_context(basic_format_context &&)=default
void operator=(const basic_format_context &)=delete
basic_format_args< basic_format_context > args_
Definition core.h:2345
Definition core.h:770
FMT_CONSTEXPR void do_check_arg_id(int id)
FMT_CONSTEXPR void check_dynamic_spec(int arg_id)
FMT_CONSTEXPR void check_arg_id(basic_string_view< Char >)
Definition core.h:840
constexpr auto error_handler() const -> ErrorHandler
Definition core.h:850
basic_string_view< Char > format_str_
Definition core.h:772
int next_arg_id_
Definition core.h:773
FMT_CONSTEXPR void on_error(const char *message)
Definition core.h:845
FMT_CONSTEXPR void check_arg_id(int id)
Definition core.h:830
constexpr auto end() const noexcept -> iterator
Definition core.h:799
Char char_type
Definition core.h:778
typename basic_string_view< Char >::iterator iterator
Definition core.h:779
FMT_CONSTEXPR auto next_arg_id() -> int
Definition core.h:814
FMT_CONSTEXPR void advance_to(iterator it)
Definition core.h:805
constexpr auto begin() const noexcept -> iterator
Definition core.h:791
constexpr basic_format_parse_context(basic_string_view< Char > format_str, ErrorHandler eh={}, int next_arg_id=0)
Definition core.h:781
Definition core.h:4010
basic_string_view< Char > str_
Definition core.h:4012
FMT_CONSTEVAL FMT_INLINE basic_format_string(const S &s)
Definition core.h:4018
basic_format_string(basic_runtime< Char > r)
Definition core.h:4038
Definition core.h:483
FMT_CONSTEXPR basic_string_view(const std::basic_string< Char, Traits, Alloc > &s) noexcept
Definition core.h:522
const Char * data_
Definition core.h:485
constexpr auto end() const noexcept -> iterator
Definition core.h:550
const Char * iterator
Definition core.h:490
constexpr auto size() const noexcept -> size_t
Definition core.h:541
constexpr auto data() const noexcept -> const Char *
Definition core.h:535
FMT_CONSTEXPR_CHAR_TRAITS friend auto operator==(basic_string_view lhs, basic_string_view rhs) -> bool
Definition core.h:576
friend auto operator>(basic_string_view lhs, basic_string_view rhs) -> bool
Definition core.h:594
constexpr auto begin() const noexcept -> iterator
Definition core.h:546
friend auto operator<(basic_string_view lhs, basic_string_view rhs) -> bool
Definition core.h:586
Char value_type
Definition core.h:489
FMT_CONSTEXPR basic_string_view(S s) noexcept
Definition core.h:529
friend auto operator<=(basic_string_view lhs, basic_string_view rhs) -> bool
Definition core.h:590
FMT_CONSTEXPR void remove_prefix(size_t n) noexcept
Definition core.h:560
FMT_CONSTEXPR_CHAR_TRAITS FMT_INLINE basic_string_view(const Char *s)
Definition core.h:511
friend auto operator!=(basic_string_view lhs, basic_string_view rhs) -> bool
Definition core.h:582
constexpr auto operator[](size_t pos) const noexcept -> const Char &
Definition core.h:555
constexpr basic_string_view(const Char *s, size_t count) noexcept
Definition core.h:498
constexpr basic_string_view() noexcept
Definition core.h:492
friend auto operator>=(basic_string_view lhs, basic_string_view rhs) -> bool
Definition core.h:598
size_t size_
Definition core.h:486
FMT_CONSTEXPR_CHAR_TRAITS auto compare(basic_string_view other) const -> int
Definition core.h:567
Definition core.h:1032
constexpr auto capacity() const noexcept -> size_t
Definition core.h:1096
void append(const U *begin, const U *end)
FMT_CONSTEXPR20 ~buffer()=default
size_t size_
Definition core.h:1035
auto end() noexcept -> T *
Definition core.h:1075
FMT_CONSTEXPR20 void try_reserve(size_t new_capacity)
Definition core.h:1131
buffer(const buffer &)=delete
void clear()
Definition core.h:1114
FMT_CONSTEXPR20 void push_back(const T &value)
Definition core.h:1137
FMT_CONSTEXPR auto data() noexcept -> T *
Definition core.h:1102
auto begin() const noexcept -> const T *
Definition core.h:1080
FMT_CONSTEXPR auto operator[](Idx index) -> T &
Definition core.h:1148
const T & const_reference
Definition core.h:1066
virtual FMT_CONSTEXPR20 void grow(size_t capacity)=0
T value_type
Definition core.h:1065
auto end() const noexcept -> const T *
Definition core.h:1084
FMT_CONSTEXPR auto operator[](Idx index) const -> const T &
Definition core.h:1153
size_t capacity_
Definition core.h:1036
FMT_CONSTEXPR20 buffer(T *p=nullptr, size_t sz=0, size_t cap=0) noexcept
Definition core.h:1046
T * ptr_
Definition core.h:1034
FMT_CONSTEXPR20 void try_resize(size_t count)
Definition core.h:1121
FMT_CONSTEXPR auto data() const noexcept -> const T *
Definition core.h:1108
void operator=(const buffer &)=delete
FMT_CONSTEXPR void set(T *buf_data, size_t buf_capacity) noexcept
Definition core.h:1055
constexpr auto size() const noexcept -> size_t
Definition core.h:1090
buffer(buffer &&)=default
auto begin() noexcept -> T *
Definition core.h:1071
Definition core.h:863
const type * types_
Definition core.h:866
constexpr auto num_args() const -> int
Definition core.h:876
FMT_CONSTEXPR void check_arg_id(int id)
Definition core.h:893
FMT_CONSTEXPR void check_dynamic_spec(int arg_id)
Definition core.h:901
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:870
basic_format_parse_context< Char, ErrorHandler > base
Definition core.h:867
FMT_CONSTEXPR auto next_arg_id() -> int
Definition core.h:885
int num_args_
Definition core.h:865
constexpr auto arg_type(int id) const -> type
Definition core.h:880
Definition core.h:1367
@ buffer_size
Definition core.h:1371
FMT_CONSTEXPR20 void grow(size_t) override
Definition core.h:1377
auto count() -> size_t
Definition core.h:1391
T data_[buffer_size]
Definition core.h:1373
size_t count_
Definition core.h:1374
counting_buffer()
Definition core.h:1386
Definition args.h:103
Definition core.h:2929
typename ParseContext::char_type char_type
Definition core.h:2931
FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler &other)
Definition core.h:2939
ParseContext & context_
Definition core.h:2965
dynamic_format_specs< char_type > & specs_
Definition core.h:2964
FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs< char_type > &specs, ParseContext &ctx)
Definition core.h:2933
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id)
Definition core.h:2953
FMT_CONSTEXPR auto make_arg_ref(int arg_id) -> arg_ref_type
Definition core.h:2969
FMT_CONSTEXPR void on_error(const char *message)
Definition core.h:2958
FMT_CONSTEXPR void on_dynamic_width(Id arg_id)
Definition core.h:2947
FMT_CONSTEXPR auto make_arg_ref(auto_id) -> arg_ref_type
Definition core.h:2976
FMT_CONSTEXPR auto make_arg_ref(basic_string_view< char_type > arg_id) -> arg_ref_type
Definition core.h:2983
Definition core.h:1175
size_t count_
Definition core.h:1177
size_t limit_
Definition core.h:1178
fixed_buffer_traits(size_t limit)
Definition core.h:1181
auto limit(size_t size) -> size_t
Definition core.h:1189
auto count() const -> size_t
Definition core.h:1185
Definition core.h:2442
FMT_CONSTEXPR FMT_INLINE format_arg_store(T &&... args)
Definition core.h:2464
conditional_t< is_packed, detail::value< Context >, basic_format_arg< Context > > value_type
Definition core.h:2448
Definition core.h:3779
FMT_CONSTEXPR void on_error(const char *message)
Definition core.h:3843
FMT_CONSTEXPR format_string_checker(basic_string_view< Char > format_str, ErrorHandler eh)
Definition core.h:3795
FMT_CONSTEXPR void on_text(const Char *, const Char *)
Definition core.h:3805
const Char *(*)(parse_context_type &) parse_func
Definition core.h:3788
FMT_CONSTEXPR auto on_format_specs(int id, const Char *begin, const Char *) -> const Char *
Definition core.h:3835
parse_context_type context_
Definition core.h:3790
FMT_CONSTEXPR auto on_arg_id(int id) -> int
Definition core.h:3813
FMT_CONSTEXPR void on_replacement_field(int, const Char *)
Definition core.h:3831
FMT_CONSTEXPR auto on_arg_id(basic_string_view< Char > id) -> int
Definition core.h:3817
FMT_CONSTEXPR auto on_arg_id() -> int
Definition core.h:3809
iterator_buffer(T *out, size_t n=buffer_size)
Definition core.h:1280
auto count() const -> size_t
Definition core.h:1305
auto out() -> T *
Definition core.h:1300
FMT_CONSTEXPR20 void grow(size_t) override
Definition core.h:1262
iterator_buffer(iterator_buffer &&other)
Definition core.h:1284
iterator_buffer(T *out, size_t=0)
Definition core.h:1320
auto out() -> T *
Definition core.h:1325
FMT_CONSTEXPR20 void grow(size_t) override
Definition core.h:1315
Definition core.h:1200
auto out() -> OutputIt
Definition core.h:1237
iterator_buffer(OutputIt out, size_t n=buffer_size)
Definition core.h:1224
auto count() const -> size_t
Definition core.h:1242
@ buffer_size
Definition core.h:1205
void flush()
Definition core.h:1216
iterator_buffer(iterator_buffer &&other)
Definition core.h:1228
OutputIt out_
Definition core.h:1202
T data_[buffer_size]
Definition core.h:1207
FMT_CONSTEXPR20 void grow(size_t) override
Definition core.h:1210
~iterator_buffer()
Definition core.h:1232
Definition core.h:2245
const void * locale_
Definition core.h:2247
constexpr locale_ref()
Definition core.h:2250
auto get() const -> Locale
Definition core.h:3688
FMT_CONSTEXPR void end_precision()
Definition core.h:3741
FMT_CONSTEXPR void on_zero()
Definition core.h:3735
detail::type arg_type_
Definition core.h:3690
FMT_CONSTEXPR specs_checker(const Handler &handler, detail::type arg_type)
Definition core.h:3699
FMT_CONSTEXPR void on_align(align_t align)
Definition core.h:3704
FMT_CONSTEXPR void on_hash()
Definition core.h:3723
FMT_CONSTEXPR void require_numeric_argument()
Definition core.h:3692
FMT_CONSTEXPR void on_sign(sign_t s)
Definition core.h:3711
FMT_CONSTEXPR void on_localized()
Definition core.h:3729
Definition core.h:2863
FMT_CONSTEXPR void on_sign(sign_t s)
Definition core.h:2886
basic_format_specs< Char > & specs_
Definition core.h:2865
FMT_CONSTEXPR void on_precision(int precision)
Definition core.h:2910
FMT_CONSTEXPR specs_setter(basic_format_specs< Char > &specs)
Definition core.h:2868
FMT_CONSTEXPR void on_hash()
Definition core.h:2890
FMT_CONSTEXPR void on_zero()
Definition core.h:2899
FMT_CONSTEXPR void on_localized()
Definition core.h:2894
FMT_CONSTEXPR specs_setter(const specs_setter &other)
Definition core.h:2873
FMT_CONSTEXPR void on_width(int width)
Definition core.h:2906
FMT_CONSTEXPR void end_precision()
Definition core.h:2914
FMT_CONSTEXPR void on_align(align_t align)
Definition core.h:2878
FMT_CONSTEXPR void on_type(presentation_type type)
Definition core.h:2918
FMT_CONSTEXPR void on_fill(basic_string_view< Char > fill)
Definition core.h:2882
Definition core.h:1598
FMT_CONSTEXPR FMT_INLINE value(const char_type *val)
Definition core.h:1669
long double long_double_value
Definition core.h:1614
value(unformattable_pointer)
constexpr FMT_INLINE value(char_type val)
Definition core.h:1665
static void format_custom_arg(void *arg, typename Context::parse_context_type &parse_ctx, Context &ctx)
Definition core.h:1711
long long long_long_value
Definition core.h:1606
const void * pointer
Definition core.h:1615
constexpr FMT_INLINE value()
Definition core.h:1621
value(unformattable_char)
constexpr FMT_INLINE value(bool val)
Definition core.h:1661
constexpr FMT_INLINE value(int val)
Definition core.h:1625
constexpr FMT_INLINE value(float val)
Definition core.h:1649
constexpr FMT_INLINE value(unsigned long long val)
Definition core.h:1637
FMT_INLINE value(const named_arg_info< char_type > *args, size_t size)
Definition core.h:1684
value(unformattable)
constexpr FMT_INLINE value(unsigned val)
Definition core.h:1629
constexpr FMT_INLINE value(long long val)
Definition core.h:1633
value(unformattable_const)
bool bool_value
Definition core.h:1610
monostate no_value
Definition core.h:1603
constexpr FMT_INLINE value(double val)
Definition core.h:1653
unsigned long long ulong_long_value
Definition core.h:1607
FMT_INLINE value(uint128_opt val)
Definition core.h:1645
char_type char_value
Definition core.h:1611
int128_opt int128_value
Definition core.h:1608
float float_value
Definition core.h:1612
typename Context::char_type char_type
Definition core.h:1600
int int_value
Definition core.h:1604
FMT_INLINE value(long double val)
Definition core.h:1657
FMT_INLINE value(const void *val)
Definition core.h:1680
unsigned uint_value
Definition core.h:1605
FMT_CONSTEXPR FMT_INLINE value(basic_string_view< char_type > val)
Definition core.h:1675
FMT_CONSTEXPR FMT_INLINE value(T &val)
Definition core.h:1690
custom_value< Context > custom
Definition core.h:1617
named_arg_value< char_type > named_args
Definition core.h:1618
uint128_opt uint128_value
Definition core.h:1609
string_value< char_type > string
Definition core.h:1616
FMT_INLINE value(int128_opt val)
Definition core.h:1641
double double_value
Definition core.h:1613
FMT_CONSTEXPR bool is_name_start(Char c)
Definition core.h:3126
typename std::enable_if< B, T >::type enable_if_t
Definition core.h:302
FMT_CONSTEXPR auto find(Ptr first, Ptr last, T value, Ptr &out) -> bool
Definition core.h:3032
constexpr FMT_INLINE auto const_check(T value) -> T
Definition core.h:390
#define FMT_ASSERT(condition, message)
Definition core.h:403
FMT_NODISCARD FMT_INLINE auto format(format_string< T... > fmt, T &&... args) -> std::string
Definition core.h:4090
FMT_CONSTEXPR FMT_INLINE auto visit_format_arg(Visitor &&vis, const basic_format_arg< Context > &arg) -> decltype(vis(0))
Definition core.h:2133
FMT_CONSTEXPR auto copy_str(InputIt begin, InputIt end, OutputIt out) -> OutputIt
Definition core.h:1006
FMT_CONSTEXPR auto make_arg(T &&value) -> basic_format_arg< Context >
Definition core.h:2311
FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char *begin, const Char *end, SpecHandler &&handler) -> const Char *
Definition core.h:3324
FMT_CONSTEXPR auto code_point_length(const Char *begin) -> int
Definition core.h:3018
#define FMT_ENUM_UNDERLYING_TYPE(type)
Definition core.h:2674
std::integral_constant< bool, B > bool_constant
Definition core.h:306
FMT_NODISCARD FMT_INLINE auto formatted_size(format_string< T... > fmt, T &&... args) -> size_t
Definition core.h:4161
#define FMT_FORMAT_AS(Type, Base)
Definition core.h:3978
#define FMT_USE_LONG_DOUBLE
Definition core.h:192
#define FMT_FORWARD(...)
Definition core.h:204
#define FMT_CONSTEVAL
Definition core.h:276
#define FMT_TYPE_CONSTANT(Type, constant)
Definition core.h:710
constexpr bool is_ascii_letter(Char c)
Definition core.h:2994
basic_string_view< char > string_view
Definition core.h:604
FMT_CONSTEXPR auto parse_replacement_field(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition core.h:3412
FMT_CONSTEXPR auto code_point_length_impl(char c) -> int
Definition core.h:3011
#define FMT_UNICODE
Definition core.h:264
align::type align_t
Definition core.h:2687
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition core.h:2506
conditional_t< long_short, unsigned, unsigned long long > ulong_type
Definition core.h:1733
FMT_CONSTEXPR auto check_char_specs(const basic_format_specs< Char > &specs, ErrorHandler &&eh={}) -> bool
Definition core.h:3574
typename std::remove_const< T >::type remove_const_t
Definition core.h:310
#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:1501
@ packed_arg_bits
Definition core.h:2002
typename std::remove_reference< T >::type remove_reference_t
Definition core.h:308
uint128_opt
Definition core.h:443
typename detail::char_t_impl< S >::type char_t
Definition core.h:759
#define FMT_END_DETAIL_NAMESPACE
Definition core.h:231
buffer_context< char > format_context
Definition core.h:2416
#define FMT_MODULE_EXPORT_BEGIN
Definition core.h:226
FMT_API void vprint(string_view fmt, format_args args)
Definition format-inl.h:1648
#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:4136
FMT_CONSTEXPR auto parse_precision(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition core.h:3223
FMT_CONSTEXPR FMT_INLINE auto make_value(T &&val) -> value< Context >
Definition core.h:2280
FMT_API void vprint_mojibake(std::FILE *, string_view, format_args)
Definition core.h:3876
FMT_CONSTEXPR void check_string_type_spec(presentation_type type, ErrorHandler &&eh={})
Definition core.h:3668
#define FMT_GCC_VERSION
Definition core.h:32
constexpr auto count() -> size_t
Definition core.h:1538
std::false_type has_fallback_formatter
Definition core.h:1430
FMT_CONSTEXPR auto parse_presentation_type(Char type) -> presentation_type
Definition core.h:3276
basic_format_string< char, type_identity_t< Args >... > format_string
Definition core.h:4059
constexpr auto to_ascii(Char c) -> Char
Definition core.h:3001
FMT_INLINE void print(format_string< T... > fmt, T &&... args)
Definition core.h:4183
constexpr auto count_named_args() -> size_t
Definition core.h:1549
int128_opt
Definition core.h:440
constexpr auto make_format_args(Args &&... args) -> format_arg_store< Context, remove_cvref_t< Args >... >
Definition core.h:2488
#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:3473
std::is_constructible< typename Context::template formatter_type< T > > has_formatter
Definition core.h:953
FMT_CONSTEXPR void check_pointer_type_spec(presentation_type type, ErrorHandler &&eh)
Definition core.h:3677
FMT_CONSTEXPR auto parse_width(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition core.h:3175
type
Definition core.h:681
@ 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:732
basic_format_parse_context< char > format_parse_context
Definition core.h:856
arg_id_kind
Definition core.h:2799
float_format
Definition core.h:3591
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:3565
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:2427
#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:1732
FMT_CONSTEXPR auto do_parse_arg_id(const Char *begin, const Char *end, IDHandler &&handler) -> const Char *
Definition core.h:3132
basic_format_specs< char > format_specs
Definition core.h:2794
#define FMT_BEGIN_DETAIL_NAMESPACE
Definition core.h:228
#define FMT_API
Definition core.h:250
FMT_INLINE void check_format_string(const S &)
Definition core.h:3851
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:4857
FMT_BEGIN_DETAIL_NAMESPACE FMT_CONSTEXPR void ignore_unused(const T &...)
Definition core.h:373
constexpr auto encode_types() -> unsigned long long
Definition core.h:2267
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value=false) noexcept -> bool
Definition core.h:377
#define FMT_BUFFER_CONTEXT(Char)
Definition core.h:2419
constexpr auto is_utf8() -> bool
Definition core.h:465
conditional_t< std::is_same< T, char >::value, appender, std::back_insert_iterator< buffer< T > > > buffer_appender
Definition core.h:1398
FMT_CONSTEXPR auto check_cstring_type_spec(presentation_type type, ErrorHandler &&eh={}) -> bool
Definition core.h:3656
@ long_short
Definition core.h:1730
auto get_buffer(OutputIt out) -> iterator_buffer< OutputIt, T >
Definition core.h:1402
@ max_packed_args
Definition core.h:2007
constexpr auto count_statically_named_args() -> size_t
Definition core.h:1555
#define FMT_ENABLE_IF(...)
Definition core.h:364
@ has_named_args_bit
Definition core.h:2015
FMT_INLINE auto format_to_n(OutputIt out, size_t n, format_string< T... > fmt, T &&... args) -> format_to_n_result< OutputIt >
Definition core.h:4154
void void_t
Definition core.h:2201
#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:1408
FMT_CONSTEXPR auto to_unsigned(Int value) -> typename std::make_unsigned< Int >::type
Definition core.h:455
auto convert_for_visit(T) -> monostate
Definition core.h:447
@ is_unpacked_bit
Definition core.h:2011
FMT_CONSTEXPR FMT_INLINE auto parse_arg_id(const Char *begin, const Char *end, IDHandler &&handler) -> const Char *
Definition core.h:3165
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:3053
FMT_INLINE auto to_string_view(const Char *s) -> basic_string_view< Char >
Definition core.h:630
#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:319
FMT_INLINE auto format_to(OutputIt out, format_string< T... > fmt, T &&... args) -> OutputIt
Definition core.h:4120
typename std::conditional< B, T, F >::type conditional_t
Definition core.h:304
#define FMT_CONSTEXPR20
Definition core.h:114
auto get_container(std::back_insert_iterator< Container > it) -> Container &
Definition core.h:990
sign::type sign_t
Definition core.h:2698
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
Definition core.h:312
auto runtime(string_view s) -> basic_runtime< char >
Definition core.h:4070
type_constant< decltype(arg_mapper< Context >().map(std::declval< const T & >())), typename Context::char_type > mapped_type_constant
Definition core.h:1998
constexpr int invalid_arg_index
Definition core.h:3748
#define FMT_USE_DOUBLE
Definition core.h:189
typename std::underlying_type< T >::type underlying_t
Definition core.h:321
presentation_type
Definition core.h:2746
#define FMT_END_NAMESPACE
Definition core.h:219
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:970
constexpr bool is_arithmetic_type(type t)
Definition core.h:737
#define FMT_MODULE_EXPORT_END
Definition core.h:227
constexpr auto has_const_formatter() -> bool
Definition core.h:983
FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs< Char > &specs, ErrorHandler &&eh={}) -> float_specs
Definition core.h:3610
FMT_API auto vformat(string_view fmt, format_args args) -> std::string
Definition format-inl.h:1578
auto find< false, char >(const char *first, const char *last, char value, const char *&out) -> bool
Definition core.h:3043
constexpr unsigned char micro[]
Definition core.h:463
FMT_CONSTEXPR auto get_arg_index_by_name(basic_string_view< Char > name) -> int
Definition core.h:3767
FMT_CONSTEXPR auto parse_align(const Char *begin, const Char *end, Handler &&handler) -> const Char *
Definition core.h:3078
#define out
Definition encodings.cpp:5
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t< Char > &fill) -> OutputIt
Definition format.h:2004
FMT_CONSTEXPR auto write(OutputIt out, Char value, const basic_format_specs< Char > &specs, locale_ref loc={}) -> OutputIt
Definition format.h:2272
const float space
Definition gdiplus_container.cpp:148
Definition core.h:2677
Definition args.h:20
result
Definition format.h:3059
Definition bin_to_hex.h:111
Definition core.h:2689
Definition uuid.h:926
FMT_CONSTEXPR FMT_INLINE auto named_args() -> std::nullptr_t
Definition core.h:1494
FMT_CONSTEXPR FMT_INLINE auto args() const -> const T *
Definition core.h:1490
FMT_CONSTEXPR FMT_INLINE arg_data(const U &... init)
Definition core.h:1486
Definition core.h:1457
T args_[1+(NUM_ARGS !=0 ? NUM_ARGS :+1)]
Definition core.h:1460
arg_data(const arg_data &other)=delete
auto args() const -> const T *
Definition core.h:1469
auto named_args() -> named_arg_info< Char > *
Definition core.h:1473
named_arg_info< Char > named_args_[NUM_NAMED_ARGS]
Definition core.h:1461
arg_data(const U &... init)
Definition core.h:1464
Definition core.h:1950
Definition core.h:1760
FMT_CONSTEXPR FMT_INLINE auto map(float val) -> float
Definition core.h:1834
FMT_CONSTEXPR FMT_INLINE auto map(long double val) -> long double
Definition core.h:1842
FMT_CONSTEXPR FMT_INLINE auto map(const T(&values)[N]) -> const T(&)[N]
Definition core.h:1921
FMT_CONSTEXPR FMT_INLINE auto map(unsigned val) -> unsigned
Definition core.h:1783
typename Context::char_type char_type
Definition core.h:1761
FMT_CONSTEXPR FMT_INLINE auto do_map(T &&val) -> T &
Definition core.h:1963
auto map(...) -> unformattable
Definition core.h:1988
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:1931
FMT_CONSTEXPR FMT_INLINE auto map(double val) -> double
Definition core.h:1838
FMT_CONSTEXPR FMT_INLINE auto map(unsigned long val) -> ulong_type
Definition core.h:1791
FMT_CONSTEXPR FMT_INLINE auto map(const char_type *val) -> const char_type *
Definition core.h:1851
FMT_CONSTEXPR FMT_INLINE auto map(int128_opt val) -> int128_opt
Definition core.h:1804
FMT_CONSTEXPR FMT_INLINE auto map(int val) -> int
Definition core.h:1779
FMT_CONSTEXPR FMT_INLINE auto map(const T &val) -> decltype(std::declval< arg_mapper >().map(format_as(T())))
Definition core.h:1939
FMT_CONSTEXPR FMT_INLINE auto map(long long val) -> long long
Definition core.h:1795
FMT_CONSTEXPR FMT_INLINE auto map(char_type *val) -> const char_type *
Definition core.h:1847
FMT_CONSTEXPR FMT_INLINE auto map(signed char val) -> int
Definition core.h:1763
FMT_CONSTEXPR auto map(const T &) -> unformattable_pointer
Definition core.h:1915
FMT_CONSTEXPR FMT_INLINE auto map(std::nullptr_t val) -> const void *
Definition core.h:1900
FMT_CONSTEXPR FMT_INLINE auto map(T) -> unformattable_char
Definition core.h:1829
FMT_CONSTEXPR FMT_INLINE auto map(bool val) -> bool
Definition core.h:1812
FMT_CONSTEXPR FMT_INLINE auto map(unsigned short val) -> unsigned
Definition core.h:1775
FMT_CONSTEXPR FMT_INLINE auto map(uint128_opt val) -> uint128_opt
Definition core.h:1808
FMT_CONSTEXPR FMT_INLINE auto map(const T &val) -> basic_string_view< char_type >
Definition core.h:1858
FMT_CONSTEXPR FMT_INLINE auto map(void *val) -> const void *
Definition core.h:1892
FMT_CONSTEXPR FMT_INLINE auto map(unsigned long long val) -> unsigned long long
Definition core.h:1799
FMT_CONSTEXPR FMT_INLINE auto map(T &&val) -> decltype(this->do_map(std::forward< T >(val)))
Definition core.h:1975
FMT_CONSTEXPR FMT_INLINE auto map(long val) -> long_type
Definition core.h:1787
FMT_CONSTEXPR FMT_INLINE auto map(T val) -> char_type
Definition core.h:1818
FMT_CONSTEXPR FMT_INLINE auto map(short val) -> int
Definition core.h:1771
FMT_CONSTEXPR FMT_INLINE auto map(const T &) -> unformattable_char
Definition core.h:1866
FMT_CONSTEXPR FMT_INLINE auto map(const void *val) -> const void *
Definition core.h:1896
FMT_CONSTEXPR FMT_INLINE auto do_map(T &&) -> unformattable_const
Definition core.h:1968
FMT_CONSTEXPR FMT_INLINE auto map(unsigned char val) -> unsigned
Definition core.h:1767
FMT_CONSTEXPR FMT_INLINE auto map(const T &named_arg) -> decltype(std::declval< arg_mapper >().map(named_arg.value))
Definition core.h:1982
Definition core.h:2808
FMT_CONSTEXPR arg_ref(basic_string_view< Char > name)
Definition core.h:2818
FMT_CONSTEXPR arg_ref()
Definition core.h:2809
FMT_CONSTEXPR auto operator=(int idx) -> arg_ref &
Definition core.h:2823
arg_id_kind kind
Definition core.h:2830
FMT_CONSTEXPR arg_ref(int index)
Definition core.h:2814
Definition core.h:2857
Definition core.h:2772
presentation_type type
Definition core.h:2775
sign_t sign
Definition core.h:2777
detail::fill_t< Char > fill
Definition core.h:2780
align_t align
Definition core.h:2776
bool alt
Definition core.h:2778
int precision
Definition core.h:2774
constexpr basic_format_specs()
Definition core.h:2782
int width
Definition core.h:2773
bool localized
Definition core.h:2779
Definition core.h:4003
basic_string_view< Char > str
Definition core.h:4004
Definition core.h:1160
buffer_traits(size_t)
Definition core.h:1161
auto limit(size_t size) -> size_t
Definition core.h:1168
auto count() const -> size_t
Definition core.h:1164
decltype(to_string_view(std::declval< S >())) result
Definition core.h:676
typename result::value_type type
Definition core.h:677
Definition core.h:671
Definition core.h:620
Definition core.h:339
Definition core.h:1589
void(* format)(void *arg, parse_context &parse_ctx, Context &ctx)
Definition core.h:1592
void * value
Definition core.h:1591
typename Context::parse_context_type parse_context
Definition core.h:1590
Definition format.h:1901
Definition core.h:325
Definition core.h:2851
arg_ref< Char > precision_ref
Definition core.h:2853
arg_ref< Char > width_ref
Definition core.h:2852
Definition core.h:745
FMT_NORETURN void on_error(const char *message)
Definition core.h:750
constexpr error_handler()=default
constexpr error_handler(const error_handler &)=default
Definition core.h:1420
fallback_formatter()=delete
Definition core.h:2705
FMT_CONSTEXPR void operator=(basic_string_view< Char > s)
Definition core.h:2715
FMT_CONSTEXPR auto operator[](size_t index) const -> const Char &
Definition core.h:2738
constexpr auto size() const -> size_t
Definition core.h:2725
constexpr auto data() const -> const Char *
Definition core.h:2729
FMT_CONSTEXPR auto operator[](size_t index) -> Char &
Definition core.h:2734
Definition core.h:3599
float_format format
Definition core.h:3601
int precision
Definition core.h:3600
bool upper
Definition core.h:3603
bool showpoint
Definition core.h:3606
sign_t sign
Definition core.h:3602
bool binary32
Definition core.h:3605
bool locale
Definition core.h:3604
Definition core.h:4128
OutputIt out
Definition core.h:4130
size_t size
Definition core.h:4132
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition core.h:3894
FMT_CONSTEXPR auto format(const T &val, FormatContext &ctx) const -> decltype(ctx.out())
Definition core.h:944
formatter()=delete
Definition core.h:1744
static auto check(U *) -> std::true_type
static auto check(...) -> std::false_type
Definition core.h:2221
Definition core.h:609
Definition core.h:625
Definition core.h:958
Definition core.h:1507
Definition core.h:2206
Definition core.h:1511
Definition core.h:666
Definition core.h:352
constexpr monostate()
Definition core.h:353
Definition core.h:1450
const Char * name
Definition core.h:1451
int id
Definition core.h:1452
Definition core.h:1582
const named_arg_info< Char > * data
Definition core.h:1583
size_t size
Definition core.h:1584
Definition core.h:1439
const T & value
Definition core.h:1441
const Char * name
Definition core.h:1440
named_arg(const Char *n, const T &v)
Definition core.h:1442
Definition core.h:419
Definition core.h:1575
const Char * data
Definition core.h:1576
size_t size
Definition core.h:1577
remove_cvref_t< decltype(T::value)> type
Definition core.h:3544
Definition core.h:3538
T type
Definition core.h:3539
Definition core.h:707
Definition core.h:315
T type
Definition core.h:316
Definition core.h:1564
Definition core.h:1567
Definition core.h:1570
Definition core.h:1561
Definition core.h:1434
annotation desc
Definition tag_strings.h:99
b
Definition tag_strings.h:61
s
Definition tag_strings.h:47
base
Definition tag_strings.h:7
template
Definition tag_strings.h:13
i
Definition tag_strings.h:60
annotation center
Definition tag_strings.h:147
map
Definition tag_strings.h:86
p
Definition tag_strings.h:29
Definition core.h:2831
int index
Definition core.h:2841
basic_string_view< Char > name
Definition core.h:2842
FMT_CONSTEXPR value(basic_string_view< Char > n)
Definition core.h:2836
FMT_CONSTEXPR value(int id=0)
Definition core.h:2832