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