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