WPILibC++ 2027.0.0-alpha-2
Loading...
Searching...
No Matches
format.h
Go to the documentation of this file.
1/*
2 Formatting library for C++
3
4 Copyright (c) 2012 - present, Victor Zverovich
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 --- Optional exception to the license ---
26
27 As an exception, if, as a result of your compiling your source code, portions
28 of this Software are embedded into a machine-executable object form of such
29 source code, you may redistribute such embedded portions in such object form
30 without including the above copyright and permission notices.
31 */
32
33#ifndef FMT_FORMAT_H_
34#define FMT_FORMAT_H_
35
36#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
37# define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
38# define FMT_REMOVE_TRANSITIVE_INCLUDES
39#endif
40
41#include "base.h"
42
43#ifndef FMT_MODULE
44# include <cmath> // std::signbit
45# include <cstddef> // std::byte
46# include <cstdint> // uint32_t
47# include <cstdlib> // std::malloc, std::free
48# include <cstring> // std::memcpy
49# include <limits> // std::numeric_limits
50# include <new> // std::bad_alloc
51# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)
52// Workaround for pre gcc 5 libstdc++.
53# include <memory> // std::allocator_traits
54# endif
55# include <stdexcept> // std::runtime_error
56# include <string> // std::string
57# include <system_error> // std::system_error
58
59// Check FMT_CPLUSPLUS to avoid a warning in MSVC.
60# if FMT_HAS_INCLUDE(<bit>) && FMT_CPLUSPLUS > 201703L
61# include <bit> // std::bit_cast
62# endif
63
64// libc++ supports string_view in pre-c++17.
65# if FMT_HAS_INCLUDE(<string_view>) && \
66 (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
67# include <string_view>
68# define FMT_USE_STRING_VIEW
69# endif
70
71# if FMT_MSC_VERSION
72# include <intrin.h> // _BitScanReverse[64], _umul128
73# endif
74#endif // FMT_MODULE
75
76#if defined(FMT_USE_NONTYPE_TEMPLATE_ARGS)
77// Use the provided definition.
78#elif defined(__NVCOMPILER)
79# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
80#elif FMT_GCC_VERSION >= 903 && FMT_CPLUSPLUS >= 201709L
81# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
82#elif defined(__cpp_nontype_template_args) && \
83 __cpp_nontype_template_args >= 201911L
84# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
85#elif FMT_CLANG_VERSION >= 1200 && FMT_CPLUSPLUS >= 202002L
86# define FMT_USE_NONTYPE_TEMPLATE_ARGS 1
87#else
88# define FMT_USE_NONTYPE_TEMPLATE_ARGS 0
89#endif
90
91#if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
92# define FMT_INLINE_VARIABLE inline
93#else
94# define FMT_INLINE_VARIABLE
95#endif
96
97// Check if RTTI is disabled.
98#ifdef FMT_USE_RTTI
99// Use the provided definition.
100#elif defined(__GXX_RTTI) || FMT_HAS_FEATURE(cxx_rtti) || defined(_CPPRTTI) || \
101 defined(__INTEL_RTTI__) || defined(__RTTI)
102// __RTTI is for EDG compilers. _CPPRTTI is for MSVC.
103# define FMT_USE_RTTI 1
104#else
105# define FMT_USE_RTTI 0
106#endif
107
108// Visibility when compiled as a shared library/object.
109#if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
110# define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value)
111#else
112# define FMT_SO_VISIBILITY(value)
113#endif
114
115#if FMT_GCC_VERSION || FMT_CLANG_VERSION
116# define FMT_NOINLINE __attribute__((noinline))
117#else
118# define FMT_NOINLINE
119#endif
120
121// Detect constexpr std::string.
122#if !FMT_USE_CONSTEVAL
123# define FMT_USE_CONSTEXPR_STRING 0
124#elif defined(__cpp_lib_constexpr_string) && \
125 __cpp_lib_constexpr_string >= 201907L
126# if FMT_CLANG_VERSION && FMT_GLIBCXX_RELEASE
127// clang + libstdc++ are able to work only starting with gcc13.3
128// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113294
129# if FMT_GLIBCXX_RELEASE < 13
130# define FMT_USE_CONSTEXPR_STRING 0
131# elif FMT_GLIBCXX_RELEASE == 13 && __GLIBCXX__ < 20240521
132# define FMT_USE_CONSTEXPR_STRING 0
133# else
134# define FMT_USE_CONSTEXPR_STRING 1
135# endif
136# else
137# define FMT_USE_CONSTEXPR_STRING 1
138# endif
139#else
140# define FMT_USE_CONSTEXPR_STRING 0
141#endif
142#if FMT_USE_CONSTEXPR_STRING
143# define FMT_CONSTEXPR_STRING constexpr
144#else
145# define FMT_CONSTEXPR_STRING
146#endif
147
148// GCC 4.9 doesn't support qualified names in specializations.
149namespace std {
150template <typename T> struct iterator_traits<fmt::basic_appender<T>> {
151 using iterator_category = output_iterator_tag;
152 using value_type = T;
154 decltype(static_cast<int*>(nullptr) - static_cast<int*>(nullptr));
155 using pointer = void;
156 using reference = void;
157};
158} // namespace std
159
160#ifndef FMT_THROW
161# if FMT_USE_EXCEPTIONS
162# if FMT_MSC_VERSION || defined(__NVCC__)
164namespace detail {
165template <typename Exception> inline void do_throw(const Exception& x) {
166 // Silence unreachable code warnings in MSVC and NVCC because these
167 // are nearly impossible to fix in a generic code.
168 volatile bool b = true;
169 if (b) throw x;
170}
171} // namespace detail
173# define FMT_THROW(x) detail::do_throw(x)
174# else
175# define FMT_THROW(x) throw x
176# endif
177# else
178# define FMT_THROW(x) \
179 ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
180# endif // FMT_USE_EXCEPTIONS
181#endif // FMT_THROW
182
183// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
184// integer formatter template instantiations to just one by only using the
185// largest integer type. This results in a reduction in binary size but will
186// cause a decrease in integer formatting performance.
187#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
188# define FMT_REDUCE_INT_INSTANTIATIONS 0
189#endif
190
192
193template <typename Char, typename Traits, typename Allocator>
194struct is_contiguous<std::basic_string<Char, Traits, Allocator>>
195 : std::true_type {};
196
197namespace detail {
198
199// __builtin_clz is broken in clang with Microsoft codegen:
200// https://github.com/fmtlib/fmt/issues/519.
201#if !FMT_MSC_VERSION
202# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
203# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
204# endif
205# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
206# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
207# endif
208#endif
209
210// Some compilers masquerade as both MSVC and GCC but otherwise support
211// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
212// MSVC intrinsics if the clz and clzll builtins are not available.
213#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL)
214// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
215# ifndef __clang__
216# pragma intrinsic(_BitScanReverse)
217# ifdef _WIN64
218# pragma intrinsic(_BitScanReverse64)
219# endif
220# endif
221
222inline auto clz(uint32_t x) -> int {
223 FMT_ASSERT(x != 0, "");
224 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
225 unsigned long r = 0;
226 _BitScanReverse(&r, x);
227 return 31 ^ static_cast<int>(r);
228}
229# define FMT_BUILTIN_CLZ(n) detail::clz(n)
230
231inline auto clzll(uint64_t x) -> int {
232 FMT_ASSERT(x != 0, "");
233 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
234 unsigned long r = 0;
235# ifdef _WIN64
236 _BitScanReverse64(&r, x);
237# else
238 // Scan the high 32 bits.
239 if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
240 return 63 ^ static_cast<int>(r + 32);
241 // Scan the low 32 bits.
242 _BitScanReverse(&r, static_cast<uint32_t>(x));
243# endif
244 return 63 ^ static_cast<int>(r);
245}
246# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
247#endif // FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL)
248
249FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
250 ignore_unused(condition);
251#ifdef FMT_FUZZ
252 if (condition) throw std::runtime_error("fuzzing limit reached");
253#endif
254}
255
256#if defined(FMT_USE_STRING_VIEW)
257template <typename Char> using std_string_view = std::basic_string_view<Char>;
258#else
259template <typename Char> struct std_string_view {
260 operator basic_string_view<Char>() const;
261};
262#endif
263
264template <typename Char, Char... C> struct string_literal {
265 static constexpr Char value[sizeof...(C)] = {C...};
266 constexpr operator basic_string_view<Char>() const {
267 return {value, sizeof...(C)};
268 }
269};
270#if FMT_CPLUSPLUS < 201703L
271template <typename Char, Char... C>
272constexpr Char string_literal<Char, C...>::value[sizeof...(C)];
273#endif
274
275// Implementation of std::bit_cast for pre-C++20.
276template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))>
277FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
278#ifdef __cpp_lib_bit_cast
279 if (is_constant_evaluated()) return std::bit_cast<To>(from);
280#endif
281 auto to = To();
282 // The cast suppresses a bogus -Wclass-memaccess on GCC.
283 std::memcpy(static_cast<void*>(&to), &from, sizeof(to));
284 return to;
285}
286
287inline auto is_big_endian() -> bool {
288#ifdef _WIN32
289 return false;
290#elif defined(__BIG_ENDIAN__)
291 return true;
292#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
293 return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
294#else
295 struct bytes {
296 char data[sizeof(int)];
297 };
298 return bit_cast<bytes>(1).data[0] == 0;
299#endif
300}
301
303 private:
304 uint64_t lo_, hi_;
305
306 public:
307 constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
308 constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
309
310 constexpr auto high() const noexcept -> uint64_t { return hi_; }
311 constexpr auto low() const noexcept -> uint64_t { return lo_; }
312
313 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
314 constexpr explicit operator T() const {
315 return static_cast<T>(lo_);
316 }
317
318 friend constexpr auto operator==(const uint128_fallback& lhs,
319 const uint128_fallback& rhs) -> bool {
320 return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
321 }
322 friend constexpr auto operator!=(const uint128_fallback& lhs,
323 const uint128_fallback& rhs) -> bool {
324 return !(lhs == rhs);
325 }
326 friend constexpr auto operator>(const uint128_fallback& lhs,
327 const uint128_fallback& rhs) -> bool {
328 return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
329 }
330 friend constexpr auto operator|(const uint128_fallback& lhs,
331 const uint128_fallback& rhs)
333 return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
334 }
335 friend constexpr auto operator&(const uint128_fallback& lhs,
336 const uint128_fallback& rhs)
338 return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
339 }
340 friend constexpr auto operator~(const uint128_fallback& n)
342 return {~n.hi_, ~n.lo_};
343 }
345 const uint128_fallback& rhs)
347 auto result = uint128_fallback(lhs);
348 result += rhs;
349 return result;
350 }
351 friend FMT_CONSTEXPR auto operator*(const uint128_fallback& lhs, uint32_t rhs)
353 FMT_ASSERT(lhs.hi_ == 0, "");
354 uint64_t hi = (lhs.lo_ >> 32) * rhs;
355 uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
356 uint64_t new_lo = (hi << 32) + lo;
357 return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
358 }
359 friend constexpr auto operator-(const uint128_fallback& lhs, uint64_t rhs)
361 return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
362 }
363 FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
364 if (shift == 64) return {0, hi_};
365 if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64);
366 return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
367 }
368 FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback {
369 if (shift == 64) return {lo_, 0};
370 if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64);
371 return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
372 }
374 return *this = *this >> shift;
375 }
377 uint64_t new_lo = lo_ + n.lo_;
378 uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0);
379 FMT_ASSERT(new_hi >= hi_, "");
380 lo_ = new_lo;
381 hi_ = new_hi;
382 }
384 lo_ &= n.lo_;
385 hi_ &= n.hi_;
386 }
387
388 FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& {
389 if (is_constant_evaluated()) {
390 lo_ += n;
391 hi_ += (lo_ < n ? 1 : 0);
392 return *this;
393 }
394#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
395 unsigned long long carry;
396 lo_ = __builtin_addcll(lo_, n, 0, &carry);
397 hi_ += carry;
398#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
399 unsigned long long result;
400 auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
401 lo_ = result;
402 hi_ += carry;
403#elif defined(_MSC_VER) && defined(_M_X64)
404 auto carry = _addcarry_u64(0, lo_, n, &lo_);
405 _addcarry_u64(carry, hi_, 0, &hi_);
406#else
407 lo_ += n;
408 hi_ += (lo_ < n ? 1 : 0);
409#endif
410 return *this;
411 }
412};
413
415
416#ifdef UINTPTR_MAX
417using uintptr_t = ::uintptr_t;
418#else
420#endif
421
422// Returns the largest possible value for type T. Same as
423// std::numeric_limits<T>::max() but shorter and not affected by the max macro.
424template <typename T> constexpr auto max_value() -> T {
425 return (std::numeric_limits<T>::max)();
426}
427template <typename T> constexpr auto num_bits() -> int {
428 return std::numeric_limits<T>::digits;
429}
430// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
431template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
432template <> constexpr auto num_bits<uint128_opt>() -> int { return 128; }
433template <> constexpr auto num_bits<uint128_fallback>() -> int { return 128; }
434
435// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
436// and 128-bit pointers to uint128_fallback.
437template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) > sizeof(From))>
438inline auto bit_cast(const From& from) -> To {
439 constexpr auto size = static_cast<int>(sizeof(From) / sizeof(unsigned short));
440 struct data_t {
441 unsigned short value[static_cast<unsigned>(size)];
442 } data = bit_cast<data_t>(from);
443 auto result = To();
444 if (const_check(is_big_endian())) {
445 for (int i = 0; i < size; ++i)
446 result = (result << num_bits<unsigned short>()) | data.value[i];
447 } else {
448 for (int i = size - 1; i >= 0; --i)
449 result = (result << num_bits<unsigned short>()) | data.value[i];
450 }
451 return result;
452}
453
454template <typename UInt>
455FMT_CONSTEXPR20 inline auto countl_zero_fallback(UInt n) -> int {
456 int lz = 0;
457 constexpr UInt msb_mask = static_cast<UInt>(1) << (num_bits<UInt>() - 1);
458 for (; (n & msb_mask) == 0; n <<= 1) lz++;
459 return lz;
460}
461
462FMT_CONSTEXPR20 inline auto countl_zero(uint32_t n) -> int {
463#ifdef FMT_BUILTIN_CLZ
464 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n);
465#endif
466 return countl_zero_fallback(n);
467}
468
469FMT_CONSTEXPR20 inline auto countl_zero(uint64_t n) -> int {
470#ifdef FMT_BUILTIN_CLZLL
471 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n);
472#endif
473 return countl_zero_fallback(n);
474}
475
476FMT_INLINE void assume(bool condition) {
477 (void)condition;
478#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
479 __builtin_assume(condition);
480#elif FMT_GCC_VERSION
481 if (!condition) __builtin_unreachable();
482#endif
483}
484
485// Attempts to reserve space for n extra characters in the output range.
486// Returns a pointer to the reserved range or a reference to it.
487template <typename OutputIt,
488 FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
490#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
491__attribute__((no_sanitize("undefined")))
492#endif
493FMT_CONSTEXPR20 inline auto
494reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* {
495 auto& c = get_container(it);
496 size_t size = c.size();
497 c.resize(size + n);
498 return &c[size];
499}
500
501template <typename T>
504 buffer<T>& buf = get_container(it);
505 buf.try_reserve(buf.size() + n);
506 return it;
507}
508
509template <typename Iterator>
510constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
511 return it;
512}
513
514template <typename OutputIt>
517
518template <typename T, typename OutputIt>
519constexpr auto to_pointer(OutputIt, size_t) -> T* {
520 return nullptr;
521}
522template <typename T>
524 buffer<T>& buf = get_container(it);
525 buf.try_reserve(buf.size() + n);
526 auto size = buf.size();
527 if (buf.capacity() < size + n) return nullptr;
528 buf.try_resize(size + n);
529 return buf.data() + size;
530}
531
532template <typename OutputIt,
533 FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&&
535inline auto base_iterator(OutputIt it,
536 typename OutputIt::container_type::value_type*)
537 -> OutputIt {
538 return it;
539}
540
541template <typename Iterator>
542constexpr auto base_iterator(Iterator, Iterator it) -> Iterator {
543 return it;
544}
545
546// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
547// instead (#1998).
548template <typename OutputIt, typename Size, typename T>
549FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)
550 -> OutputIt {
551 for (Size i = 0; i < count; ++i) *out++ = value;
552 return out;
553}
554template <typename T, typename Size>
555FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
557 static_assert(sizeof(T) == 1,
558 "sizeof(T) must be 1 to use char for initialization");
559 std::memset(out, value, to_unsigned(count));
560 return out + count;
561}
562
563template <typename OutChar, typename InputIt, typename OutputIt>
564FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end,
565 OutputIt out) -> OutputIt {
566 return copy<OutChar>(begin, end, out);
567}
568
569// A public domain branchless UTF-8 decoder by Christopher Wellons:
570// https://github.com/skeeto/branchless-utf8
571/* Decode the next character, c, from s, reporting errors in e.
572 *
573 * Since this is a branchless decoder, four bytes will be read from the
574 * buffer regardless of the actual length of the next character. This
575 * means the buffer _must_ have at least three bytes of zero padding
576 * following the end of the data stream.
577 *
578 * Errors are reported in e, which will be non-zero if the parsed
579 * character was somehow invalid: invalid byte sequence, non-canonical
580 * encoding, or a surrogate half.
581 *
582 * The function returns a pointer to the next character. When an error
583 * occurs, this pointer will be a guess that depends on the particular
584 * error, but it will always advance at least one byte.
585 */
586FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)
587 -> const char* {
588 constexpr int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
589 constexpr uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
590 constexpr int shiftc[] = {0, 18, 12, 6, 0};
591 constexpr int shifte[] = {0, 6, 4, 2, 0};
592
593 int len = "\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"
594 [static_cast<unsigned char>(*s) >> 3];
595 // Compute the pointer to the next character early so that the next
596 // iteration can start working on the next character. Neither Clang
597 // nor GCC figure out this reordering on their own.
598 const char* next = s + len + !len;
599
600 using uchar = unsigned char;
601
602 // Assume a four-byte character and load four bytes. Unused bits are
603 // shifted out.
604 *c = uint32_t(uchar(s[0]) & masks[len]) << 18;
605 *c |= uint32_t(uchar(s[1]) & 0x3f) << 12;
606 *c |= uint32_t(uchar(s[2]) & 0x3f) << 6;
607 *c |= uint32_t(uchar(s[3]) & 0x3f) << 0;
608 *c >>= shiftc[len];
609
610 // Accumulate the various error conditions.
611 *e = (*c < mins[len]) << 6; // non-canonical encoding
612 *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
613 *e |= (*c > 0x10FFFF) << 8; // out of range?
614 *e |= (uchar(s[1]) & 0xc0) >> 2;
615 *e |= (uchar(s[2]) & 0xc0) >> 4;
616 *e |= uchar(s[3]) >> 6;
617 *e ^= 0x2a; // top two bits of each tail byte correct?
618 *e >>= shifte[len];
619
620 return next;
621}
622
623constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point = ~uint32_t();
624
625// Invokes f(cp, sv) for every code point cp in s with sv being the string view
626// corresponding to the code point. cp is invalid_code_point on error.
627template <typename F>
629 auto decode = [f](const char* buf_ptr, const char* ptr) {
630 auto cp = uint32_t();
631 auto error = 0;
632 auto end = utf8_decode(buf_ptr, &cp, &error);
633 bool result = f(error ? invalid_code_point : cp,
634 string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr)));
635 return result ? (error ? buf_ptr + 1 : end) : nullptr;
636 };
637
638 auto p = s.data();
639 const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
640 if (s.size() >= block_size) {
641 for (auto end = p + s.size() - block_size + 1; p < end;) {
642 p = decode(p, p);
643 if (!p) return;
644 }
645 }
646 auto num_chars_left = to_unsigned(s.data() + s.size() - p);
647 if (num_chars_left == 0) return;
648
649 // Suppress bogus -Wstringop-overflow.
650 if (FMT_GCC_VERSION) num_chars_left &= 3;
651 char buf[2 * block_size - 1] = {};
652 copy<char>(p, p + num_chars_left, buf);
653 const char* buf_ptr = buf;
654 do {
655 auto end = decode(buf_ptr, p);
656 if (!end) return;
657 p += end - buf_ptr;
658 buf_ptr = end;
659 } while (buf_ptr < buf + num_chars_left);
660}
661
662FMT_CONSTEXPR inline auto display_width_of(uint32_t cp) noexcept -> size_t {
663 return to_unsigned(
664 1 + (cp >= 0x1100 &&
665 (cp <= 0x115f || // Hangul Jamo init. consonants
666 cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET
667 cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET
668 // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
669 (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
670 (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables
671 (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
672 (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms
673 (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms
674 (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
675 (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms
676 (cp >= 0x20000 && cp <= 0x2fffd) || // CJK
677 (cp >= 0x30000 && cp <= 0x3fffd) ||
678 // Miscellaneous Symbols and Pictographs + Emoticons:
679 (cp >= 0x1f300 && cp <= 0x1f64f) ||
680 // Supplemental Symbols and Pictographs:
681 (cp >= 0x1f900 && cp <= 0x1f9ff))));
682}
683
684template <typename T> struct is_integral : std::is_integral<T> {};
685template <> struct is_integral<int128_opt> : std::true_type {};
686template <> struct is_integral<uint128_t> : std::true_type {};
687
688template <typename T>
690 std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
691 std::is_same<T, int128_opt>::value>;
692
693template <typename T>
695 bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
696 !std::is_same<T, char>::value &&
697 !std::is_same<T, wchar_t>::value>;
698
699#if defined(FMT_USE_FLOAT128)
700// Use the provided definition.
701#elif FMT_CLANG_VERSION >= 309 && FMT_HAS_INCLUDE(<quadmath.h>)
702# define FMT_USE_FLOAT128 1
703#elif FMT_GCC_VERSION && defined(_GLIBCXX_USE_FLOAT128) && \
704 !defined(__STRICT_ANSI__)
705# define FMT_USE_FLOAT128 1
706#else
707# define FMT_USE_FLOAT128 0
708#endif
709#if FMT_USE_FLOAT128
710using float128 = __float128;
711#else
712struct float128 {};
713#endif
714
715template <typename T> using is_float128 = std::is_same<T, float128>;
716
717template <typename T> struct is_floating_point : std::is_floating_point<T> {};
718template <> struct is_floating_point<float128> : std::true_type {};
719
720template <typename T, bool = is_floating_point<T>::value>
721struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
722 sizeof(T) <= sizeof(double)> {};
723template <typename T> struct is_fast_float<T, false> : std::false_type {};
724
725template <typename T>
726using fast_float_t = conditional_t<sizeof(T) == sizeof(double), double, float>;
727
728template <typename T>
729using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
730
731#ifndef FMT_USE_FULL_CACHE_DRAGONBOX
732# define FMT_USE_FULL_CACHE_DRAGONBOX 0
733#endif
734
735// An allocator that uses malloc/free to allow removing dependency on the C++
736// standard libary runtime. std::decay is used for back_inserter to be found by
737// ADL when applied to memory_buffer.
738template <typename T> struct allocator : private std::decay<void> {
739 using value_type = T;
740
741 T* allocate(size_t n) {
742 FMT_ASSERT(n <= max_value<size_t>() / sizeof(T), "");
743 T* p = static_cast<T*>(std::malloc(n * sizeof(T)));
744 if (!p) FMT_THROW(std::bad_alloc());
745 return p;
746 }
747
748 void deallocate(T* p, size_t) { std::free(p); }
749};
750
751} // namespace detail
752
753FMT_BEGIN_EXPORT
754
755// The number of characters to store in the basic_memory_buffer object itself
756// to avoid dynamic memory allocation.
757enum { inline_buffer_size = 500 };
758
759/**
760 * A dynamically growing memory buffer for trivially copyable/constructible
761 * types with the first `SIZE` elements stored in the object itself. Most
762 * commonly used via the `memory_buffer` alias for `char`.
763 *
764 * **Example**:
765 *
766 * auto out = fmt::memory_buffer();
767 * fmt::format_to(std::back_inserter(out), "The answer is {}.", 42);
768 *
769 * This will append "The answer is 42." to `out`. The buffer content can be
770 * converted to `std::string` with `to_string(out)`.
771 */
772template <typename T, size_t SIZE = inline_buffer_size,
773 typename Allocator = detail::allocator<T>>
774class basic_memory_buffer : public detail::buffer<T> {
775 private:
776 T store_[SIZE];
777
778 // Don't inherit from Allocator to avoid generating type_info for it.
779 FMT_NO_UNIQUE_ADDRESS Allocator alloc_;
780
781 // Deallocate memory allocated by the buffer.
782 FMT_CONSTEXPR20 void deallocate() {
783 T* data = this->data();
784 if (data != store_) alloc_.deallocate(data, this->capacity());
785 }
786
787 static FMT_CONSTEXPR20 void grow(detail::buffer<T>& buf, size_t size) {
788 detail::abort_fuzzing_if(size > 5000);
789 auto& self = static_cast<basic_memory_buffer&>(buf);
790 const size_t max_size =
791 std::allocator_traits<Allocator>::max_size(self.alloc_);
792 size_t old_capacity = buf.capacity();
793 size_t new_capacity = old_capacity + old_capacity / 2;
794 if (size > new_capacity)
795 new_capacity = size;
796 else if (new_capacity > max_size)
797 new_capacity = max_of(size, max_size);
798 T* old_data = buf.data();
799 T* new_data = self.alloc_.allocate(new_capacity);
800 // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
801 detail::assume(buf.size() <= new_capacity);
802 // The following code doesn't throw, so the raw pointer above doesn't leak.
803 memcpy(new_data, old_data, buf.size() * sizeof(T));
804 self.set(new_data, new_capacity);
805 // deallocate must not throw according to the standard, but even if it does,
806 // the buffer already uses the new storage and will deallocate it in
807 // destructor.
808 if (old_data != self.store_) self.alloc_.deallocate(old_data, old_capacity);
809 }
810
811 public:
812 using value_type = T;
813 using const_reference = const T&;
814
816 const Allocator& alloc = Allocator())
817 : detail::buffer<T>(grow), alloc_(alloc) {
818 this->set(store_, SIZE);
819 if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T());
820 }
822
823 private:
824 // Move data from other to this buffer.
825 FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
826 alloc_ = std::move(other.alloc_);
827 T* data = other.data();
828 size_t size = other.size(), capacity = other.capacity();
829 if (data == other.store_) {
830 this->set(store_, capacity);
831 detail::copy<T>(other.store_, other.store_ + size, store_);
832 } else {
833 this->set(data, capacity);
834 // Set pointer to the inline array so that delete is not called
835 // when deallocating.
836 other.set(other.store_, 0);
837 other.clear();
838 }
839 this->resize(size);
840 }
841
842 public:
843 /// Constructs a `basic_memory_buffer` object moving the content of the other
844 /// object to it.
846 : detail::buffer<T>(grow) {
847 move(other);
848 }
849
850 /// Moves the content of the other `basic_memory_buffer` object to this one.
852 FMT_ASSERT(this != &other, "");
853 deallocate();
854 move(other);
855 return *this;
856 }
857
858 // Returns a copy of the allocator associated with this buffer.
859 auto get_allocator() const -> Allocator { return alloc_; }
860
861 /// Resizes the buffer to contain `count` elements. If T is a POD type new
862 /// elements may not be initialized.
863 FMT_CONSTEXPR void resize(size_t count) { this->try_resize(count); }
864
865 /// Increases the buffer capacity to `new_capacity`.
866 void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
867
868 using detail::buffer<T>::append;
869 template <typename ContiguousRange>
870 FMT_CONSTEXPR20 void append(const ContiguousRange& range) {
871 append(range.data(), range.data() + range.size());
872 }
873};
874
876
877template <size_t SIZE>
879 -> std::string {
880 auto size = buf.size();
881 detail::assume(size < std::string().max_size());
882 return {buf.data(), size};
883}
884
885// A writer to a buffered stream. It doesn't own the underlying stream.
886class writer {
887 private:
889
890 // We cannot create a file buffer in advance because any write to a FILE may
891 // invalidate it.
892 FILE* file_;
893
894 public:
895 inline writer(FILE* f) : buf_(nullptr), file_(f) {}
896 inline writer(detail::buffer<char>& buf) : buf_(&buf) {}
897
898 /// Formats `args` according to specifications in `fmt` and writes the
899 /// output to the file.
900 template <typename... T> void print(format_string<T...> fmt, T&&... args) {
901 if (buf_)
902 fmt::format_to(appender(*buf_), fmt, std::forward<T>(args)...);
903 else
904 fmt::print(file_, fmt, std::forward<T>(args)...);
905 }
906};
907
909 private:
910 std::string str_;
912
913 public:
914 inline string_buffer() : buf_(str_) {}
915
916 inline operator writer() { return buf_; }
917 inline std::string& str() { return str_; }
918};
919
920template <typename T, size_t SIZE, typename Allocator>
921struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
922};
923
924// Suppress a misleading warning in older versions of clang.
925FMT_PRAGMA_CLANG(diagnostic ignored "-Wweak-vtables")
926
927/// An error reported from a formatting function.
928class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error {
929 public:
930 using std::runtime_error::runtime_error;
931};
932
933class loc_value;
934
936namespace detail {
937FMT_API auto write_console(int fd, string_view text) -> bool;
939} // namespace detail
940
941namespace detail {
942template <typename Char, size_t N> struct fixed_string {
943 FMT_CONSTEXPR20 fixed_string(const Char (&s)[N]) {
944 detail::copy<Char, const Char*, Char*>(static_cast<const Char*>(s), s + N,
945 data);
946 }
947 Char data[N] = {};
948};
949
950// Converts a compile-time string to basic_string_view.
951FMT_EXPORT template <typename Char, size_t N>
952constexpr auto compile_string_to_view(const Char (&s)[N])
954 // Remove trailing NUL character if needed. Won't be present if this is used
955 // with a raw character array (i.e. not defined as a string).
956 return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
957}
958FMT_EXPORT template <typename Char>
961 return s;
962}
963
964// Returns true if value is negative, false otherwise.
965// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
966template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
967constexpr auto is_negative(T value) -> bool {
968 return value < 0;
969}
970template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
971constexpr auto is_negative(T) -> bool {
972 return false;
973}
974
975// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
976// represent all values of an integral type T.
977template <typename T>
980 uint32_t,
981 conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
982template <typename T>
984
985#define FMT_POWERS_OF_10(factor) \
986 factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \
987 (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \
988 (factor) * 100000000, (factor) * 1000000000
989
990// Converts value in the range [0, 100) to a string.
991// GCC generates slightly better code when value is pointer-size.
992inline auto digits2(size_t value) -> const char* {
993 // Align data since unaligned access may be slower when crossing a
994 // hardware-specific boundary.
995 alignas(2) static const char data[] =
996 "0001020304050607080910111213141516171819"
997 "2021222324252627282930313233343536373839"
998 "4041424344454647484950515253545556575859"
999 "6061626364656667686970717273747576777879"
1000 "8081828384858687888990919293949596979899";
1001 return &data[value * 2];
1002}
1003
1004template <typename Char> constexpr auto getsign(sign s) -> Char {
1005 return static_cast<char>(((' ' << 24) | ('+' << 16) | ('-' << 8)) >>
1006 (static_cast<int>(s) * 8));
1007}
1008
1009template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
1010 int count = 1;
1011 for (;;) {
1012 // Integer division is slow so do it for a group of four digits instead
1013 // of for every digit. The idea comes from the talk by Alexandrescu
1014 // "Three Optimization Tips for C++". See speed-test for a comparison.
1015 if (n < 10) return count;
1016 if (n < 100) return count + 1;
1017 if (n < 1000) return count + 2;
1018 if (n < 10000) return count + 3;
1019 n /= 10000u;
1020 count += 4;
1021 }
1022}
1023#if FMT_USE_INT128
1024FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int {
1025 return count_digits_fallback(n);
1026}
1027#endif
1028
1029#ifdef FMT_BUILTIN_CLZLL
1030// It is a separate function rather than a part of count_digits to workaround
1031// the lack of static constexpr in constexpr functions.
1032inline auto do_count_digits(uint64_t n) -> int {
1033 // This has comparable performance to the version by Kendall Willets
1034 // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
1035 // but uses smaller tables.
1036 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
1037 static constexpr uint8_t bsr2log10[] = {
1038 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1039 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1040 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1041 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1042 auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
1043 static constexpr uint64_t zero_or_powers_of_10[] = {
1044 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1045 10000000000000000000ULL};
1046 return t - (n < zero_or_powers_of_10[t]);
1047}
1048#endif
1049
1050// Returns the number of decimal digits in n. Leading zeros are not counted
1051// except for n == 0 in which case count_digits returns 1.
1052FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
1053#ifdef FMT_BUILTIN_CLZLL
1054 if (!is_constant_evaluated() && !FMT_OPTIMIZE_SIZE) return do_count_digits(n);
1055#endif
1056 return count_digits_fallback(n);
1057}
1058
1059// Counts the number of digits in n. BITS = log2(radix).
1060template <int BITS, typename UInt>
1061FMT_CONSTEXPR auto count_digits(UInt n) -> int {
1062#ifdef FMT_BUILTIN_CLZ
1063 if (!is_constant_evaluated() && num_bits<UInt>() == 32)
1064 return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
1065#endif
1066 // Lambda avoids unreachable code warnings from NVHPC.
1067 return [](UInt m) {
1068 int num_digits = 0;
1069 do {
1070 ++num_digits;
1071 } while ((m >>= BITS) != 0);
1072 return num_digits;
1073 }(n);
1074}
1075
1076#ifdef FMT_BUILTIN_CLZ
1077// It is a separate function rather than a part of count_digits to workaround
1078// the lack of static constexpr in constexpr functions.
1079FMT_INLINE auto do_count_digits(uint32_t n) -> int {
1080// An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1081// This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1082# define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1083 static constexpr uint64_t table[] = {
1084 FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1085 FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1086 FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1087 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1088 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1089 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1090 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1091 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1092 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1093 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1094 FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1095 };
1096 auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
1097 return static_cast<int>((n + inc) >> 32);
1098}
1099#endif
1100
1101// Optional version of count_digits for better performance on 32-bit platforms.
1102FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
1103#ifdef FMT_BUILTIN_CLZ
1104 if (!is_constant_evaluated() && !FMT_OPTIMIZE_SIZE) return do_count_digits(n);
1105#endif
1106 return count_digits_fallback(n);
1107}
1108
1109template <typename Int> constexpr auto digits10() noexcept -> int {
1110 return std::numeric_limits<Int>::digits10;
1111}
1112template <> constexpr auto digits10<int128_opt>() noexcept -> int { return 38; }
1113template <> constexpr auto digits10<uint128_t>() noexcept -> int { return 38; }
1114
1115template <typename Char> struct thousands_sep_result {
1116 std::string grouping;
1118};
1119
1120template <typename Char>
1122template <typename Char>
1124 auto result = thousands_sep_impl<char>(loc);
1125 return {result.grouping, Char(result.thousands_sep)};
1126}
1127template <>
1131
1132template <typename Char>
1133FMT_API auto decimal_point_impl(locale_ref loc) -> Char;
1134template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
1135 return Char(decimal_point_impl<char>(loc));
1136}
1137template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
1138 return decimal_point_impl<wchar_t>(loc);
1139}
1140
1141#ifndef FMT_HEADER_ONLY
1147extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
1148extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
1150#endif // FMT_HEADER_ONLY
1151
1152// Compares two characters for equality.
1153template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
1154 return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1155}
1156inline auto equal2(const char* lhs, const char* rhs) -> bool {
1157 return memcmp(lhs, rhs, 2) == 0;
1158}
1159
1160// Writes a two-digit value to out.
1161template <typename Char>
1163 if (!is_constant_evaluated() && std::is_same<Char, char>::value &&
1165 memcpy(out, digits2(value), 2);
1166 return;
1167 }
1168 *out++ = static_cast<Char>('0' + value / 10);
1169 *out = static_cast<Char>('0' + value % 10);
1170}
1171
1172// Formats a decimal unsigned integer value writing to out pointing to a buffer
1173// of specified size. The caller must ensure that the buffer is large enough.
1174template <typename Char, typename UInt>
1175FMT_CONSTEXPR20 auto do_format_decimal(Char* out, UInt value, int size)
1176 -> Char* {
1177 FMT_ASSERT(size >= count_digits(value), "invalid digit count");
1178 unsigned n = to_unsigned(size);
1179 while (value >= 100) {
1180 // Integer division is slow so do it for a group of two digits instead
1181 // of for every digit. The idea comes from the talk by Alexandrescu
1182 // "Three Optimization Tips for C++". See speed-test for a comparison.
1183 n -= 2;
1184 write2digits(out + n, static_cast<unsigned>(value % 100));
1185 value /= 100;
1186 }
1187 if (value >= 10) {
1188 n -= 2;
1189 write2digits(out + n, static_cast<unsigned>(value));
1190 } else {
1191 out[--n] = static_cast<Char>('0' + value);
1192 }
1193 return out + n;
1194}
1195
1196template <typename Char, typename UInt>
1198 int num_digits) -> Char* {
1199 do_format_decimal(out, value, num_digits);
1200 return out + num_digits;
1201}
1202
1203template <typename Char, typename UInt, typename OutputIt,
1205FMT_CONSTEXPR auto format_decimal(OutputIt out, UInt value, int num_digits)
1206 -> OutputIt {
1207 if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1208 do_format_decimal(ptr, value, num_digits);
1209 return out;
1210 }
1211 // Buffer is large enough to hold all digits (digits10 + 1).
1212 char buffer[digits10<UInt>() + 1];
1213 if (is_constant_evaluated()) fill_n(buffer, sizeof(buffer), '\0');
1214 do_format_decimal(buffer, value, num_digits);
1215 return copy_noinline<Char>(buffer, buffer + num_digits, out);
1216}
1217
1218template <typename Char, typename UInt>
1219FMT_CONSTEXPR auto do_format_base2e(int base_bits, Char* out, UInt value,
1220 int size, bool upper = false) -> Char* {
1221 out += size;
1222 do {
1223 const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
1224 unsigned digit = static_cast<unsigned>(value & ((1u << base_bits) - 1));
1225 *--out = static_cast<Char>(base_bits < 4 ? static_cast<char>('0' + digit)
1226 : digits[digit]);
1227 } while ((value >>= base_bits) != 0);
1228 return out;
1229}
1230
1231// Formats an unsigned integer in the power of two base (binary, octal, hex).
1232template <typename Char, typename UInt>
1233FMT_CONSTEXPR auto format_base2e(int base_bits, Char* out, UInt value,
1234 int num_digits, bool upper = false) -> Char* {
1235 do_format_base2e(base_bits, out, value, num_digits, upper);
1236 return out + num_digits;
1237}
1238
1239template <typename Char, typename OutputIt, typename UInt,
1240 FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value)>
1241FMT_CONSTEXPR inline auto format_base2e(int base_bits, OutputIt out, UInt value,
1242 int num_digits, bool upper = false)
1243 -> OutputIt {
1244 if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1245 format_base2e(base_bits, ptr, value, num_digits, upper);
1246 return out;
1247 }
1248 // Make buffer large enough for any base.
1249 char buffer[num_bits<UInt>()];
1250 if (is_constant_evaluated()) fill_n(buffer, sizeof(buffer), '\0');
1251 format_base2e(base_bits, buffer, value, num_digits, upper);
1252 return detail::copy_noinline<Char>(buffer, buffer + num_digits, out);
1253}
1254
1255// A converter from UTF-8 to UTF-16.
1257 private:
1259
1260 public:
1261 FMT_API explicit utf8_to_utf16(string_view s);
1262 inline operator basic_string_view<wchar_t>() const {
1263 return {&buffer_[0], size()};
1264 }
1265 inline auto size() const -> size_t { return buffer_.size() - 1; }
1266 inline auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1267 inline auto str() const -> std::wstring { return {&buffer_[0], size()}; }
1268};
1269
1271
1272// A converter from UTF-16/UTF-32 (host endian) to UTF-8.
1273template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
1274 private:
1275 Buffer buffer_;
1276
1277 public:
1281 static_assert(sizeof(WChar) == 2 || sizeof(WChar) == 4,
1282 "Expect utf16 or utf32");
1283 if (!convert(s, policy))
1284 FMT_THROW(std::runtime_error(sizeof(WChar) == 2 ? "invalid utf16"
1285 : "invalid utf32"));
1286 }
1287 operator string_view() const { return string_view(&buffer_[0], size()); }
1288 auto size() const -> size_t { return buffer_.size() - 1; }
1289 auto c_str() const -> const char* { return &buffer_[0]; }
1290 auto str() const -> std::string { return std::string(&buffer_[0], size()); }
1291
1292 // Performs conversion returning a bool instead of throwing exception on
1293 // conversion error. This method may still throw in case of memory allocation
1294 // error.
1297 -> bool {
1298 if (!convert(buffer_, s, policy)) return false;
1299 buffer_.push_back(0);
1300 return true;
1301 }
1302 static auto convert(Buffer& buf, basic_string_view<WChar> s,
1304 -> bool {
1305 for (auto p = s.begin(); p != s.end(); ++p) {
1306 uint32_t c = static_cast<uint32_t>(*p);
1307 if (sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) {
1308 // Handle a surrogate pair.
1309 ++p;
1310 if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
1311 if (policy == to_utf8_error_policy::abort) return false;
1312 buf.append(string_view("\xEF\xBF\xBD"));
1313 --p;
1314 continue;
1315 } else {
1316 c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
1317 }
1318 }
1319 if (c < 0x80) {
1320 buf.push_back(static_cast<char>(c));
1321 } else if (c < 0x800) {
1322 buf.push_back(static_cast<char>(0xc0 | (c >> 6)));
1323 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1324 } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
1325 buf.push_back(static_cast<char>(0xe0 | (c >> 12)));
1326 buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1327 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1328 } else if (c >= 0x10000 && c <= 0x10ffff) {
1329 buf.push_back(static_cast<char>(0xf0 | (c >> 18)));
1330 buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
1331 buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1332 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1333 } else {
1334 return false;
1335 }
1336 }
1337 return true;
1338 }
1339};
1340
1341// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
1342inline auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback {
1343#if FMT_USE_INT128
1344 auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
1345 return {static_cast<uint64_t>(p >> 64), static_cast<uint64_t>(p)};
1346#elif defined(_MSC_VER) && defined(_M_X64)
1347 auto hi = uint64_t();
1348 auto lo = _umul128(x, y, &hi);
1349 return {hi, lo};
1350#else
1351 const uint64_t mask = static_cast<uint64_t>(max_value<uint32_t>());
1352
1353 uint64_t a = x >> 32;
1354 uint64_t b = x & mask;
1355 uint64_t c = y >> 32;
1356 uint64_t d = y & mask;
1357
1358 uint64_t ac = a * c;
1359 uint64_t bc = b * c;
1360 uint64_t ad = a * d;
1361 uint64_t bd = b * d;
1362
1363 uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
1364
1365 return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
1366 (intermediate << 32) + (bd & mask)};
1367#endif
1368}
1369
1370namespace dragonbox {
1371// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
1372// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
1373inline auto floor_log10_pow2(int e) noexcept -> int {
1374 FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent");
1375 static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
1376 return (e * 315653) >> 20;
1377}
1378
1379inline auto floor_log2_pow10(int e) noexcept -> int {
1380 FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
1381 return (e * 1741647) >> 19;
1382}
1383
1384// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
1385inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t {
1386#if FMT_USE_INT128
1387 auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
1388 return static_cast<uint64_t>(p >> 64);
1389#elif defined(_MSC_VER) && defined(_M_X64)
1390 return __umulh(x, y);
1391#else
1392 return umul128(x, y).high();
1393#endif
1394}
1395
1396// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
1397// 128-bit unsigned integer.
1398inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept
1399 -> uint128_fallback {
1400 uint128_fallback r = umul128(x, y.high());
1401 r += umul128_upper64(x, y.low());
1402 return r;
1403}
1404
1405FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback;
1406
1407// Type-specific information that Dragonbox uses.
1408template <typename T, typename Enable = void> struct float_info;
1409
1410template <> struct float_info<float> {
1411 using carrier_uint = uint32_t;
1412 static const int exponent_bits = 8;
1413 static const int kappa = 1;
1414 static const int big_divisor = 100;
1415 static const int small_divisor = 10;
1416 static const int min_k = -31;
1417 static const int max_k = 46;
1418 static const int shorter_interval_tie_lower_threshold = -35;
1419 static const int shorter_interval_tie_upper_threshold = -35;
1420};
1421
1422template <> struct float_info<double> {
1423 using carrier_uint = uint64_t;
1424 static const int exponent_bits = 11;
1425 static const int kappa = 2;
1426 static const int big_divisor = 1000;
1427 static const int small_divisor = 100;
1428 static const int min_k = -292;
1429 static const int max_k = 341;
1430 static const int shorter_interval_tie_lower_threshold = -77;
1431 static const int shorter_interval_tie_upper_threshold = -77;
1432};
1433
1434// An 80- or 128-bit floating point number.
1435template <typename T>
1436struct float_info<T, enable_if_t<std::numeric_limits<T>::digits == 64 ||
1437 std::numeric_limits<T>::digits == 113 ||
1438 is_float128<T>::value>> {
1440 static const int exponent_bits = 15;
1441};
1442
1443// A double-double floating point number.
1444template <typename T>
1445struct float_info<T, enable_if_t<is_double_double<T>::value>> {
1447};
1448
1454
1455template <typename T> FMT_API auto to_decimal(T x) noexcept -> decimal_fp<T>;
1456} // namespace dragonbox
1457
1458// Returns true iff Float has the implicit bit which is not stored.
1459template <typename Float> constexpr auto has_implicit_bit() -> bool {
1460 // An 80-bit FP number has a 64-bit significand an no implicit bit.
1461 return std::numeric_limits<Float>::digits != 64;
1462}
1463
1464// Returns the number of significand bits stored in Float. The implicit bit is
1465// not counted since it is not stored.
1466template <typename Float> constexpr auto num_significand_bits() -> int {
1467 // std::numeric_limits may not support __float128.
1468 return is_float128<Float>() ? 112
1469 : (std::numeric_limits<Float>::digits -
1470 (has_implicit_bit<Float>() ? 1 : 0));
1471}
1472
1473template <typename Float>
1474constexpr auto exponent_mask() ->
1476 using float_uint = typename dragonbox::float_info<Float>::carrier_uint;
1477 return ((float_uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1)
1479}
1480template <typename Float> constexpr auto exponent_bias() -> int {
1481 // std::numeric_limits may not support __float128.
1482 return is_float128<Float>() ? 16383
1483 : std::numeric_limits<Float>::max_exponent - 1;
1484}
1485
1486FMT_CONSTEXPR inline auto compute_exp_size(int exp) -> int {
1487 auto prefix_size = 2; // sign + 'e'
1488 auto abs_exp = exp >= 0 ? exp : -exp;
1489 if (exp < 100) return prefix_size + 2;
1490 return prefix_size + (abs_exp >= 1000 ? 4 : 3);
1491}
1492
1493// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1494template <typename Char, typename OutputIt>
1495FMT_CONSTEXPR auto write_exponent(int exp, OutputIt out) -> OutputIt {
1496 FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
1497 if (exp < 0) {
1498 *out++ = static_cast<Char>('-');
1499 exp = -exp;
1500 } else {
1501 *out++ = static_cast<Char>('+');
1502 }
1503 auto uexp = static_cast<uint32_t>(exp);
1504 if (is_constant_evaluated()) {
1505 if (uexp < 10) *out++ = '0';
1506 return format_decimal<Char>(out, uexp, count_digits(uexp));
1507 }
1508 if (uexp >= 100u) {
1509 const char* top = digits2(uexp / 100);
1510 if (uexp >= 1000u) *out++ = static_cast<Char>(top[0]);
1511 *out++ = static_cast<Char>(top[1]);
1512 uexp %= 100;
1513 }
1514 const char* d = digits2(uexp);
1515 *out++ = static_cast<Char>(d[0]);
1516 *out++ = static_cast<Char>(d[1]);
1517 return out;
1518}
1519
1520// A floating-point number f * pow(2, e) where F is an unsigned type.
1521template <typename F> struct basic_fp {
1522 F f;
1523 int e;
1524
1525 static constexpr int num_significand_bits =
1526 static_cast<int>(sizeof(F) * num_bits<unsigned char>());
1527
1528 constexpr basic_fp() : f(0), e(0) {}
1529 constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
1530
1531 // Constructs fp from an IEEE754 floating-point number.
1532 template <typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); }
1533
1534 // Assigns n to this and return true iff predecessor is closer than successor.
1535 template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
1536 FMT_CONSTEXPR auto assign(Float n) -> bool {
1537 static_assert(std::numeric_limits<Float>::digits <= 113, "unsupported FP");
1538 // Assume Float is in the format [sign][exponent][significand].
1539 using carrier_uint = typename dragonbox::float_info<Float>::carrier_uint;
1540 const auto num_float_significand_bits =
1542 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
1543 const auto significand_mask = implicit_bit - 1;
1544 auto u = bit_cast<carrier_uint>(n);
1545 f = static_cast<F>(u & significand_mask);
1546 auto biased_e = static_cast<int>((u & exponent_mask<Float>()) >>
1547 num_float_significand_bits);
1548 // The predecessor is closer if n is a normalized power of 2 (f == 0)
1549 // other than the smallest normalized number (biased_e > 1).
1550 auto is_predecessor_closer = f == 0 && biased_e > 1;
1551 if (biased_e == 0)
1552 biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
1553 else if (has_implicit_bit<Float>())
1554 f += static_cast<F>(implicit_bit);
1555 e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
1556 if (!has_implicit_bit<Float>()) ++e;
1557 return is_predecessor_closer;
1558 }
1559
1560 template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
1561 FMT_CONSTEXPR auto assign(Float n) -> bool {
1562 static_assert(std::numeric_limits<double>::is_iec559, "unsupported FP");
1563 return assign(static_cast<double>(n));
1564 }
1565};
1566
1568
1569// Normalizes the value converted from double and multiplied by (1 << SHIFT).
1570template <int SHIFT = 0, typename F>
1572 // Handle subnormals.
1573 const auto implicit_bit = F(1) << num_significand_bits<double>();
1574 const auto shifted_implicit_bit = implicit_bit << SHIFT;
1575 while ((value.f & shifted_implicit_bit) == 0) {
1576 value.f <<= 1;
1577 --value.e;
1578 }
1579 // Subtract 1 to account for hidden bit.
1580 const auto offset = basic_fp<F>::num_significand_bits -
1581 num_significand_bits<double>() - SHIFT - 1;
1582 value.f <<= offset;
1583 value.e -= offset;
1584 return value;
1585}
1586
1587// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
1588FMT_CONSTEXPR inline auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t {
1589#if FMT_USE_INT128
1590 auto product = static_cast<__uint128_t>(lhs) * rhs;
1591 auto f = static_cast<uint64_t>(product >> 64);
1592 return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
1593#else
1594 // Multiply 32-bit parts of significands.
1595 uint64_t mask = (1ULL << 32) - 1;
1596 uint64_t a = lhs >> 32, b = lhs & mask;
1597 uint64_t c = rhs >> 32, d = rhs & mask;
1598 uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
1599 // Compute mid 64-bit of result and round.
1600 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
1601 return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
1602#endif
1603}
1604
1605FMT_CONSTEXPR inline auto operator*(fp x, fp y) -> fp {
1606 return {multiply(x.f, y.f), x.e + y.e + 64};
1607}
1608
1609template <typename T, bool doublish = num_bits<T>() == num_bits<double>()>
1611 conditional_t<std::is_same<T, float>::value || doublish, double, T>;
1612
1613template <typename T>
1615 return static_cast<convert_float_result<T>>(value);
1616}
1617
1618template <typename Char, typename OutputIt>
1619FMT_CONSTEXPR FMT_NOINLINE auto fill(OutputIt it, size_t n,
1620 const basic_specs& specs) -> OutputIt {
1621 auto fill_size = specs.fill_size();
1622 if (fill_size == 1) return detail::fill_n(it, n, specs.fill_unit<Char>());
1623 if (const Char* data = specs.fill<Char>()) {
1624 for (size_t i = 0; i < n; ++i) it = copy<Char>(data, data + fill_size, it);
1625 }
1626 return it;
1627}
1628
1629// Writes the output of f, padded according to format specifications in specs.
1630// size: output size in code units.
1631// width: output display width in (terminal) column positions.
1632template <typename Char, align default_align = align::left, typename OutputIt,
1633 typename F>
1634FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs,
1635 size_t size, size_t width, F&& f) -> OutputIt {
1636 static_assert(default_align == align::left || default_align == align::right,
1637 "");
1638 unsigned spec_width = to_unsigned(specs.width);
1639 size_t padding = spec_width > width ? spec_width - width : 0;
1640 // Shifts are encoded as string literals because static constexpr is not
1641 // supported in constexpr functions.
1642 auto* shifts =
1643 default_align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1644 size_t left_padding = padding >> shifts[static_cast<int>(specs.align())];
1645 size_t right_padding = padding - left_padding;
1646 auto it = reserve(out, size + padding * specs.fill_size());
1647 if (left_padding != 0) it = fill<Char>(it, left_padding, specs);
1648 it = f(it);
1649 if (right_padding != 0) it = fill<Char>(it, right_padding, specs);
1650 return base_iterator(out, it);
1651}
1652
1653template <typename Char, align default_align = align::left, typename OutputIt,
1654 typename F>
1655constexpr auto write_padded(OutputIt out, const format_specs& specs,
1656 size_t size, F&& f) -> OutputIt {
1657 return write_padded<Char, default_align>(out, specs, size, size, f);
1658}
1659
1660template <typename Char, align default_align = align::left, typename OutputIt>
1662 const format_specs& specs = {}) -> OutputIt {
1664 out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
1665 const char* data = bytes.data();
1666 return copy<Char>(data, data + bytes.size(), it);
1667 });
1668}
1669
1670template <typename Char, typename OutputIt, typename UIntPtr>
1671auto write_ptr(OutputIt out, UIntPtr value, const format_specs* specs)
1672 -> OutputIt {
1673 int num_digits = count_digits<4>(value);
1674 auto size = to_unsigned(num_digits) + size_t(2);
1675 auto write = [=](reserve_iterator<OutputIt> it) {
1676 *it++ = static_cast<Char>('0');
1677 *it++ = static_cast<Char>('x');
1678 return format_base2e<Char>(4, it, value, num_digits);
1679 };
1680 return specs ? write_padded<Char, align::right>(out, *specs, size, write)
1681 : base_iterator(out, write(reserve(out, size)));
1682}
1683
1684// Returns true iff the code point cp is printable.
1685FMT_API auto is_printable(uint32_t cp) -> bool;
1686
1687inline auto needs_escape(uint32_t cp) -> bool {
1688 if (cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\') return true;
1689 if (const_check(FMT_OPTIMIZE_SIZE > 1)) return false;
1690 return !is_printable(cp);
1691}
1692
1693template <typename Char> struct find_escape_result {
1694 const Char* begin;
1695 const Char* end;
1696 uint32_t cp;
1697};
1698
1699template <typename Char>
1700auto find_escape(const Char* begin, const Char* end)
1702 for (; begin != end; ++begin) {
1703 uint32_t cp = static_cast<unsigned_char<Char>>(*begin);
1704 if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue;
1705 if (needs_escape(cp)) return {begin, begin + 1, cp};
1706 }
1707 return {begin, nullptr, 0};
1708}
1709
1710inline auto find_escape(const char* begin, const char* end)
1712 if (const_check(!use_utf8)) return find_escape<char>(begin, end);
1713 auto result = find_escape_result<char>{end, nullptr, 0};
1714 for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
1715 [&](uint32_t cp, string_view sv) {
1716 if (needs_escape(cp)) {
1717 result = {sv.begin(), sv.end(), cp};
1718 return false;
1719 }
1720 return true;
1721 });
1722 return result;
1723}
1724
1725template <size_t width, typename Char, typename OutputIt>
1726auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt {
1727 *out++ = static_cast<Char>('\\');
1728 *out++ = static_cast<Char>(prefix);
1729 Char buf[width];
1730 fill_n(buf, width, static_cast<Char>('0'));
1731 format_base2e(4, buf, cp, width);
1732 return copy<Char>(buf, buf + width, out);
1733}
1734
1735template <typename OutputIt, typename Char>
1737 -> OutputIt {
1738 auto c = static_cast<Char>(escape.cp);
1739 switch (escape.cp) {
1740 case '\n':
1741 *out++ = static_cast<Char>('\\');
1742 c = static_cast<Char>('n');
1743 break;
1744 case '\r':
1745 *out++ = static_cast<Char>('\\');
1746 c = static_cast<Char>('r');
1747 break;
1748 case '\t':
1749 *out++ = static_cast<Char>('\\');
1750 c = static_cast<Char>('t');
1751 break;
1752 case '"': FMT_FALLTHROUGH;
1753 case '\'': FMT_FALLTHROUGH;
1754 case '\\': *out++ = static_cast<Char>('\\'); break;
1755 default:
1756 if (escape.cp < 0x100) return write_codepoint<2, Char>(out, 'x', escape.cp);
1757 if (escape.cp < 0x10000)
1758 return write_codepoint<4, Char>(out, 'u', escape.cp);
1759 if (escape.cp < 0x110000)
1760 return write_codepoint<8, Char>(out, 'U', escape.cp);
1761 for (Char escape_char : basic_string_view<Char>(
1762 escape.begin, to_unsigned(escape.end - escape.begin))) {
1763 out = write_codepoint<2, Char>(out, 'x',
1764 static_cast<uint32_t>(escape_char) & 0xFF);
1765 }
1766 return out;
1767 }
1768 *out++ = c;
1769 return out;
1770}
1771
1772template <typename Char, typename OutputIt>
1774 -> OutputIt {
1775 *out++ = static_cast<Char>('"');
1776 auto begin = str.begin(), end = str.end();
1777 do {
1778 auto escape = find_escape(begin, end);
1779 out = copy<Char>(begin, escape.begin, out);
1780 begin = escape.end;
1781 if (!begin) break;
1783 } while (begin != end);
1784 *out++ = static_cast<Char>('"');
1785 return out;
1786}
1787
1788template <typename Char, typename OutputIt>
1789auto write_escaped_char(OutputIt out, Char v) -> OutputIt {
1790 Char v_array[1] = {v};
1791 *out++ = static_cast<Char>('\'');
1792 if ((needs_escape(static_cast<uint32_t>(v)) && v != static_cast<Char>('"')) ||
1793 v == static_cast<Char>('\'')) {
1794 out = write_escaped_cp(out,
1795 find_escape_result<Char>{v_array, v_array + 1,
1796 static_cast<uint32_t>(v)});
1797 } else {
1798 *out++ = v;
1799 }
1800 *out++ = static_cast<Char>('\'');
1801 return out;
1802}
1803
1804template <typename Char, typename OutputIt>
1805FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
1806 const format_specs& specs) -> OutputIt {
1807 bool is_debug = specs.type() == presentation_type::debug;
1808 return write_padded<Char>(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
1809 if (is_debug) return write_escaped_char(it, value);
1810 *it++ = value;
1811 return it;
1812 });
1813}
1814template <typename Char, typename OutputIt>
1815FMT_CONSTEXPR auto write(OutputIt out, Char value, const format_specs& specs,
1816 locale_ref loc = {}) -> OutputIt {
1817 // char is formatted as unsigned char for consistency across platforms.
1818 using unsigned_type =
1819 conditional_t<std::is_same<Char, char>::value, unsigned char, unsigned>;
1820 return check_char_specs(specs)
1821 ? write_char<Char>(out, value, specs)
1822 : write<Char>(out, static_cast<unsigned_type>(value), specs, loc);
1823}
1824
1825template <typename Char> class digit_grouping {
1826 private:
1827 std::string grouping_;
1828 std::basic_string<Char> thousands_sep_;
1829
1830 struct next_state {
1831 std::string::const_iterator group;
1832 int pos;
1833 };
1834 auto initial_state() const -> next_state { return {grouping_.begin(), 0}; }
1835
1836 // Returns the next digit group separator position.
1837 auto next(next_state& state) const -> int {
1838 if (thousands_sep_.empty()) return max_value<int>();
1839 if (state.group == grouping_.end()) return state.pos += grouping_.back();
1840 if (*state.group <= 0 || *state.group == max_value<char>())
1841 return max_value<int>();
1842 state.pos += *state.group++;
1843 return state.pos;
1844 }
1845
1846 public:
1847 template <typename Locale,
1848 FMT_ENABLE_IF(std::is_same<Locale, locale_ref>::value)>
1849 explicit digit_grouping(Locale loc, bool localized = true) {
1850 if (!localized) return;
1851 auto sep = thousands_sep<Char>(loc);
1852 grouping_ = sep.grouping;
1853 if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep);
1854 }
1855 digit_grouping(std::string grouping, std::basic_string<Char> sep)
1856 : grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {}
1857
1858 auto has_separator() const -> bool { return !thousands_sep_.empty(); }
1859
1860 auto count_separators(int num_digits) const -> int {
1861 int count = 0;
1862 auto state = initial_state();
1863 while (num_digits > next(state)) ++count;
1864 return count;
1865 }
1866
1867 // Applies grouping to digits and write the output to out.
1868 template <typename Out, typename C>
1869 auto apply(Out out, basic_string_view<C> digits) const -> Out {
1870 auto num_digits = static_cast<int>(digits.size());
1871 auto separators = basic_memory_buffer<int>();
1872 separators.push_back(0);
1873 auto state = initial_state();
1874 while (int i = next(state)) {
1875 if (i >= num_digits) break;
1876 separators.push_back(i);
1877 }
1878 for (int i = 0, sep_index = static_cast<int>(separators.size() - 1);
1879 i < num_digits; ++i) {
1880 if (num_digits - i == separators[sep_index]) {
1881 out = copy<Char>(thousands_sep_.data(),
1882 thousands_sep_.data() + thousands_sep_.size(), out);
1883 --sep_index;
1884 }
1885 *out++ = static_cast<Char>(digits[to_unsigned(i)]);
1886 }
1887 return out;
1888 }
1889};
1890
1891FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
1892 prefix |= prefix != 0 ? value << 8 : value;
1893 prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
1894}
1895
1896// Writes a decimal integer with digit grouping.
1897template <typename OutputIt, typename UInt, typename Char>
1898auto write_int(OutputIt out, UInt value, unsigned prefix,
1899 const format_specs& specs, const digit_grouping<Char>& grouping)
1900 -> OutputIt {
1901 static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
1902 int num_digits = 0;
1903 auto buffer = memory_buffer();
1904 switch (specs.type()) {
1905 default: FMT_ASSERT(false, ""); FMT_FALLTHROUGH;
1908 num_digits = count_digits(value);
1910 break;
1912 if (specs.alt())
1913 prefix_append(prefix, unsigned(specs.upper() ? 'X' : 'x') << 8 | '0');
1914 num_digits = count_digits<4>(value);
1915 format_base2e<char>(4, appender(buffer), value, num_digits, specs.upper());
1916 break;
1918 num_digits = count_digits<3>(value);
1919 // Octal prefix '0' is counted as a digit, so only add it if precision
1920 // is not greater than the number of digits.
1921 if (specs.alt() && specs.precision <= num_digits && value != 0)
1922 prefix_append(prefix, '0');
1923 format_base2e<char>(3, appender(buffer), value, num_digits);
1924 break;
1926 if (specs.alt())
1927 prefix_append(prefix, unsigned(specs.upper() ? 'B' : 'b') << 8 | '0');
1928 num_digits = count_digits<1>(value);
1929 format_base2e<char>(1, appender(buffer), value, num_digits);
1930 break;
1932 return write_char<Char>(out, static_cast<Char>(value), specs);
1933 }
1934
1935 unsigned size = (prefix != 0 ? prefix >> 24 : 0) + to_unsigned(num_digits) +
1936 to_unsigned(grouping.count_separators(num_digits));
1938 out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
1939 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1940 *it++ = static_cast<Char>(p & 0xff);
1941 return grouping.apply(it, string_view(buffer.data(), buffer.size()));
1942 });
1943}
1944
1945#if FMT_USE_LOCALE
1946// Writes a localized value.
1947FMT_API auto write_loc(appender out, loc_value value, const format_specs& specs,
1948 locale_ref loc) -> bool;
1949#endif
1950template <typename OutputIt>
1951inline auto write_loc(OutputIt, const loc_value&, const format_specs&,
1952 locale_ref) -> bool {
1953 return false;
1954}
1955
1956template <typename UInt> struct write_int_arg {
1958 unsigned prefix;
1959};
1960
1961template <typename T>
1964 auto prefix = 0u;
1965 auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
1966 if (is_negative(value)) {
1967 prefix = 0x01000000 | '-';
1968 abs_value = 0 - abs_value;
1969 } else {
1970 constexpr unsigned prefixes[4] = {0, 0, 0x1000000u | '+', 0x1000000u | ' '};
1971 prefix = prefixes[static_cast<int>(s)];
1972 }
1973 return {abs_value, prefix};
1974}
1975
1976template <typename Char = char> struct loc_writer {
1979 std::basic_string<Char> sep;
1980 std::string grouping;
1981 std::basic_string<Char> decimal_point;
1982
1983 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
1984 auto operator()(T value) -> bool {
1986 write_int(out, static_cast<uint64_or_128_t<T>>(arg.abs_value), arg.prefix,
1988 return true;
1989 }
1990
1991 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
1992 auto operator()(T) -> bool {
1993 return false;
1994 }
1995};
1996
1997// Size and padding computation separate from write_int to avoid template bloat.
1999 unsigned size;
2000 unsigned padding;
2001
2002 FMT_CONSTEXPR size_padding(int num_digits, unsigned prefix,
2003 const format_specs& specs)
2004 : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
2005 if (specs.align() == align::numeric) {
2006 auto width = to_unsigned(specs.width);
2007 if (width > size) {
2008 padding = width - size;
2009 size = width;
2010 }
2011 } else if (specs.precision > num_digits) {
2012 size = (prefix >> 24) + to_unsigned(specs.precision);
2013 padding = to_unsigned(specs.precision - num_digits);
2014 }
2015 }
2016};
2017
2018template <typename Char, typename OutputIt, typename T>
2020 const format_specs& specs) -> OutputIt {
2021 static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, "");
2022
2023 constexpr size_t buffer_size = num_bits<T>();
2024 char buffer[buffer_size];
2025 if (is_constant_evaluated()) fill_n(buffer, buffer_size, '\0');
2026 const char* begin = nullptr;
2027 const char* end = buffer + buffer_size;
2028
2029 auto abs_value = arg.abs_value;
2030 auto prefix = arg.prefix;
2031 switch (specs.type()) {
2032 default: FMT_ASSERT(false, ""); FMT_FALLTHROUGH;
2035 begin = do_format_decimal(buffer, abs_value, buffer_size);
2036 break;
2038 begin = do_format_base2e(4, buffer, abs_value, buffer_size, specs.upper());
2039 if (specs.alt())
2040 prefix_append(prefix, unsigned(specs.upper() ? 'X' : 'x') << 8 | '0');
2041 break;
2043 begin = do_format_base2e(3, buffer, abs_value, buffer_size);
2044 // Octal prefix '0' is counted as a digit, so only add it if precision
2045 // is not greater than the number of digits.
2046 auto num_digits = end - begin;
2047 if (specs.alt() && specs.precision <= num_digits && abs_value != 0)
2048 prefix_append(prefix, '0');
2049 break;
2050 }
2052 begin = do_format_base2e(1, buffer, abs_value, buffer_size);
2053 if (specs.alt())
2054 prefix_append(prefix, unsigned(specs.upper() ? 'B' : 'b') << 8 | '0');
2055 break;
2057 return write_char<Char>(out, static_cast<Char>(abs_value), specs);
2058 }
2059
2060 // Write an integer in the format
2061 // <left-padding><prefix><numeric-padding><digits><right-padding>
2062 // prefix contains chars in three lower bytes and the size in the fourth byte.
2063 int num_digits = static_cast<int>(end - begin);
2064 // Slightly faster check for specs.width == 0 && specs.precision == -1.
2065 if ((specs.width | (specs.precision + 1)) == 0) {
2066 auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
2067 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2068 *it++ = static_cast<Char>(p & 0xff);
2069 return base_iterator(out, copy<Char>(begin, end, it));
2070 }
2071 auto sp = size_padding(num_digits, prefix, specs);
2072 unsigned padding = sp.padding;
2073 return write_padded<Char, align::right>(
2074 out, specs, sp.size, [=](reserve_iterator<OutputIt> it) {
2075 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2076 *it++ = static_cast<Char>(p & 0xff);
2077 it = detail::fill_n(it, padding, static_cast<Char>('0'));
2078 return copy<Char>(begin, end, it);
2079 });
2080}
2081
2082template <typename Char, typename OutputIt, typename T>
2085 const format_specs& specs)
2086 -> OutputIt {
2087 return write_int<Char>(out, arg, specs);
2088}
2089
2090template <typename Char, typename T,
2091 FMT_ENABLE_IF(is_integral<T>::value &&
2092 !std::is_same<T, bool>::value &&
2093 !std::is_same<T, Char>::value)>
2095 const format_specs& specs, locale_ref loc)
2097 if (specs.localized() && write_loc(out, value, specs, loc)) return out;
2098 return write_int_noinline<Char>(out, make_write_int_arg(value, specs.sign()),
2099 specs);
2100}
2101
2102// An inlined version of write used in format string compilation.
2103template <typename Char, typename OutputIt, typename T,
2104 FMT_ENABLE_IF(is_integral<T>::value &&
2105 !std::is_same<T, bool>::value &&
2106 !std::is_same<T, Char>::value &&
2107 !std::is_same<OutputIt, basic_appender<Char>>::value)>
2109 const format_specs& specs, locale_ref loc)
2110 -> OutputIt {
2111 if (specs.localized() && write_loc(out, value, specs, loc)) return out;
2112 return write_int<Char>(out, make_write_int_arg(value, specs.sign()), specs);
2113}
2114
2115template <typename Char, typename OutputIt,
2116 FMT_ENABLE_IF(std::is_same<Char, char>::value)>
2118 const format_specs& specs) -> OutputIt {
2119 bool is_debug = specs.type() == presentation_type::debug;
2120 if (specs.precision < 0 && specs.width == 0) {
2121 auto&& it = reserve(out, s.size());
2122 return is_debug ? write_escaped_string(it, s) : copy<char>(s, it);
2123 }
2124
2125 size_t display_width_limit =
2126 specs.precision < 0 ? SIZE_MAX : to_unsigned(specs.precision);
2127 size_t display_width =
2128 !is_debug || specs.precision == 0 ? 0 : 1; // Account for opening "
2129 size_t size = !is_debug || specs.precision == 0 ? 0 : 1;
2130 for_each_codepoint(s, [&](uint32_t cp, string_view sv) {
2131 if (is_debug && needs_escape(cp)) {
2134 find_escape_result<char>{sv.begin(), sv.end(), cp});
2135 // We're reinterpreting bytes as display width. That's okay
2136 // because write_escaped_cp() only writes ASCII characters.
2137 size_t cp_width = buf.count();
2138 if (display_width + cp_width <= display_width_limit) {
2139 display_width += cp_width;
2140 size += cp_width;
2141 // If this is the end of the string, account for closing "
2142 if (display_width < display_width_limit && sv.end() == s.end()) {
2143 ++display_width;
2144 ++size;
2145 }
2146 return true;
2147 }
2148
2149 size += display_width_limit - display_width;
2150 display_width = display_width_limit;
2151 return false;
2152 }
2153
2154 size_t cp_width = display_width_of(cp);
2155 if (cp_width + display_width <= display_width_limit) {
2156 display_width += cp_width;
2157 size += sv.size();
2158 // If this is the end of the string, account for closing "
2159 if (is_debug && display_width < display_width_limit &&
2160 sv.end() == s.end()) {
2161 ++display_width;
2162 ++size;
2163 }
2164 return true;
2165 }
2166
2167 return false;
2168 });
2169
2170 struct bounded_output_iterator {
2171 reserve_iterator<OutputIt> underlying_iterator;
2172 size_t bound;
2173
2174 FMT_CONSTEXPR auto operator*() -> bounded_output_iterator& { return *this; }
2175 FMT_CONSTEXPR auto operator++() -> bounded_output_iterator& {
2176 return *this;
2177 }
2178 FMT_CONSTEXPR auto operator++(int) -> bounded_output_iterator& {
2179 return *this;
2180 }
2181 FMT_CONSTEXPR auto operator=(char c) -> bounded_output_iterator& {
2182 if (bound > 0) {
2183 *underlying_iterator++ = c;
2184 --bound;
2185 }
2186 return *this;
2187 }
2188 };
2189
2190 return write_padded<char>(
2191 out, specs, size, display_width, [&](reserve_iterator<OutputIt> it) {
2192 return is_debug
2193 ? write_escaped_string(bounded_output_iterator{it, size}, s)
2194 .underlying_iterator
2195 : copy<char>(s.data(), s.data() + size, it);
2196 });
2197}
2198
2199template <typename Char, typename OutputIt,
2200 FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
2201FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s,
2202 const format_specs& specs) -> OutputIt {
2203 auto data = s.data();
2204 auto size = s.size();
2205 if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
2206 size = to_unsigned(specs.precision);
2207
2208 bool is_debug = specs.type() == presentation_type::debug;
2209 if (is_debug) {
2210 auto buf = counting_buffer<Char>();
2211 write_escaped_string(basic_appender<Char>(buf), s);
2212 size = buf.count();
2213 }
2214
2215 return write_padded<Char>(
2216 out, specs, size, [&](reserve_iterator<OutputIt> it) {
2217 return is_debug ? write_escaped_string(it, s)
2218 : copy<Char>(data, data + size, it);
2219 });
2220}
2221
2222template <typename Char, typename OutputIt>
2224 const format_specs& specs, locale_ref) -> OutputIt {
2225 return write<Char>(out, s, specs);
2226}
2227
2228template <typename Char, typename OutputIt>
2229FMT_CONSTEXPR auto write(OutputIt out, const Char* s, const format_specs& specs,
2230 locale_ref) -> OutputIt {
2231 if (specs.type() == presentation_type::pointer)
2232 return write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs);
2233 if (!s) report_error("string pointer is null");
2234 return write<Char>(out, basic_string_view<Char>(s), specs, {});
2235}
2236
2237template <typename Char, typename OutputIt, typename T,
2238 FMT_ENABLE_IF(is_integral<T>::value &&
2239 !std::is_same<T, bool>::value &&
2240 !std::is_same<T, Char>::value)>
2241FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
2242 auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2243 bool negative = is_negative(value);
2244 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2245 if (negative) abs_value = ~abs_value + 1;
2246 int num_digits = count_digits(abs_value);
2247 auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
2248 if (auto ptr = to_pointer<Char>(out, size)) {
2249 if (negative) *ptr++ = static_cast<Char>('-');
2250 format_decimal<Char>(ptr, abs_value, num_digits);
2251 return out;
2252 }
2253 if (negative) *out++ = static_cast<Char>('-');
2254 return format_decimal<Char>(out, abs_value, num_digits);
2255}
2256
2257template <typename Char>
2258FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
2259 format_specs& specs) -> const Char* {
2260 FMT_ASSERT(begin != end, "");
2261 auto alignment = align::none;
2262 auto p = begin + code_point_length(begin);
2263 if (end - p <= 0) p = begin;
2264 for (;;) {
2265 switch (to_ascii(*p)) {
2266 case '<': alignment = align::left; break;
2267 case '>': alignment = align::right; break;
2268 case '^': alignment = align::center; break;
2269 }
2270 if (alignment != align::none) {
2271 if (p != begin) {
2272 auto c = *begin;
2273 if (c == '}') return begin;
2274 if (c == '{') {
2275 report_error("invalid fill character '{'");
2276 return begin;
2277 }
2278 specs.set_fill(basic_string_view<Char>(begin, to_unsigned(p - begin)));
2279 begin = p + 1;
2280 } else {
2281 ++begin;
2282 }
2283 break;
2284 } else if (p == begin) {
2285 break;
2286 }
2287 p = begin;
2288 }
2289 specs.set_align(alignment);
2290 return begin;
2291}
2292
2293template <typename Char, typename OutputIt>
2294FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan,
2295 format_specs specs, sign s) -> OutputIt {
2296 auto str =
2297 isnan ? (specs.upper() ? "NAN" : "nan") : (specs.upper() ? "INF" : "inf");
2298 constexpr size_t str_size = 3;
2299 auto size = str_size + (s != sign::none ? 1 : 0);
2300 // Replace '0'-padding with space for non-finite values.
2301 const bool is_zero_fill =
2302 specs.fill_size() == 1 && specs.fill_unit<Char>() == '0';
2303 if (is_zero_fill) specs.set_fill(' ');
2304 return write_padded<Char>(out, specs, size,
2306 if (s != sign::none)
2307 *it++ = detail::getsign<Char>(s);
2308 return copy<Char>(str, str + str_size, it);
2309 });
2310}
2311
2312// A decimal floating-point number significand * pow(10, exp).
2318
2319constexpr auto get_significand_size(const big_decimal_fp& f) -> int {
2320 return f.significand_size;
2321}
2322template <typename T>
2324 return count_digits(f.significand);
2325}
2326
2327template <typename Char, typename OutputIt>
2328constexpr auto write_significand(OutputIt out, const char* significand,
2329 int significand_size) -> OutputIt {
2330 return copy<Char>(significand, significand + significand_size, out);
2331}
2332template <typename Char, typename OutputIt, typename UInt>
2333inline auto write_significand(OutputIt out, UInt significand,
2334 int significand_size) -> OutputIt {
2335 return format_decimal<Char>(out, significand, significand_size);
2336}
2337template <typename Char, typename OutputIt, typename T, typename Grouping>
2338FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
2339 int significand_size, int exponent,
2340 const Grouping& grouping) -> OutputIt {
2341 if (!grouping.has_separator()) {
2342 out = write_significand<Char>(out, significand, significand_size);
2343 return detail::fill_n(out, exponent, static_cast<Char>('0'));
2344 }
2345 auto buffer = memory_buffer();
2346 write_significand<char>(appender(buffer), significand, significand_size);
2347 detail::fill_n(appender(buffer), exponent, '0');
2348 return grouping.apply(out, string_view(buffer.data(), buffer.size()));
2349}
2350
2351template <typename Char, typename UInt,
2352 FMT_ENABLE_IF(std::is_integral<UInt>::value)>
2353inline auto write_significand(Char* out, UInt significand, int significand_size,
2354 int integral_size, Char decimal_point) -> Char* {
2355 if (!decimal_point) return format_decimal(out, significand, significand_size);
2356 out += significand_size + 1;
2357 Char* end = out;
2358 int floating_size = significand_size - integral_size;
2359 for (int i = floating_size / 2; i > 0; --i) {
2360 out -= 2;
2361 write2digits(out, static_cast<size_t>(significand % 100));
2362 significand /= 100;
2363 }
2364 if (floating_size % 2 != 0) {
2365 *--out = static_cast<Char>('0' + significand % 10);
2366 significand /= 10;
2367 }
2368 *--out = decimal_point;
2369 format_decimal(out - integral_size, significand, integral_size);
2370 return end;
2371}
2372
2373template <typename OutputIt, typename UInt, typename Char,
2374 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
2375inline auto write_significand(OutputIt out, UInt significand,
2376 int significand_size, int integral_size,
2377 Char decimal_point) -> OutputIt {
2378 // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
2379 Char buffer[digits10<UInt>() + 2];
2380 auto end = write_significand(buffer, significand, significand_size,
2381 integral_size, decimal_point);
2382 return detail::copy_noinline<Char>(buffer, end, out);
2383}
2384
2385template <typename OutputIt, typename Char>
2386FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand,
2387 int significand_size, int integral_size,
2388 Char decimal_point) -> OutputIt {
2389 out = detail::copy_noinline<Char>(significand, significand + integral_size,
2390 out);
2391 if (!decimal_point) return out;
2392 *out++ = decimal_point;
2393 return detail::copy_noinline<Char>(significand + integral_size,
2394 significand + significand_size, out);
2395}
2396
2397template <typename OutputIt, typename Char, typename T, typename Grouping>
2398FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
2399 int significand_size, int integral_size,
2400 Char decimal_point,
2401 const Grouping& grouping) -> OutputIt {
2402 if (!grouping.has_separator()) {
2403 return write_significand(out, significand, significand_size, integral_size,
2405 }
2407 write_significand(basic_appender<Char>(buffer), significand, significand_size,
2408 integral_size, decimal_point);
2409 grouping.apply(
2410 out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size)));
2411 return detail::copy_noinline<Char>(buffer.data() + integral_size,
2412 buffer.end(), out);
2413}
2414
2415// Numbers with exponents greater or equal to the returned value will use
2416// the exponential notation.
2417template <typename T> FMT_CONSTEVAL auto exp_upper() -> int {
2418 return std::numeric_limits<T>::digits10 != 0
2419 ? min_of(16, std::numeric_limits<T>::digits10 + 1)
2420 : 16;
2421}
2423// Use the fixed notation if the exponent is in [-4, exp_upper),
2424// e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
2425constexpr auto use_fixed(int exp, int exp_upper) -> bool {
2426 return exp >= -4 && exp < exp_upper;
2427}
2428
2429template <typename Char> class fallback_digit_grouping {
2430 public:
2432
2433 constexpr auto has_separator() const -> bool { return false; }
2434
2435 constexpr auto count_separators(int) const -> int { return 0; }
2436
2437 template <typename Out, typename C>
2438 constexpr auto apply(Out out, basic_string_view<C>) const -> Out {
2439 return out;
2440 }
2441};
2442
2443template <typename Char, typename Grouping, typename OutputIt,
2444 typename DecimalFP>
2445FMT_CONSTEXPR20 auto write_fixed(OutputIt out, const DecimalFP& f,
2446 int significand_size, Char decimal_point,
2447 const format_specs& specs, sign s,
2448 locale_ref loc = {}) -> OutputIt {
2449 using iterator = reserve_iterator<OutputIt>;
2450
2451 int exp = f.exponent + significand_size;
2452 long long size = significand_size + (s != sign::none ? 1 : 0);
2453 if (f.exponent >= 0) {
2454 // 1234e5 -> 123400000[.0+]
2455 size += f.exponent;
2456 int num_zeros = specs.precision - exp;
2457 abort_fuzzing_if(num_zeros > 5000);
2458 if (specs.alt()) {
2459 ++size;
2460 if (num_zeros <= 0 && specs.type() != presentation_type::fixed)
2461 num_zeros = 0;
2462 if (num_zeros > 0) size += num_zeros;
2463 }
2464 auto grouping = Grouping(loc, specs.localized());
2465 size += grouping.count_separators(exp);
2466 return write_padded<Char, align::right>(
2467 out, specs, to_unsigned(size), [&](iterator it) {
2468 if (s != sign::none) *it++ = detail::getsign<Char>(s);
2469 it = write_significand<Char>(it, f.significand, significand_size,
2470 f.exponent, grouping);
2471 if (!specs.alt()) return it;
2472 *it++ = decimal_point;
2473 return num_zeros > 0 ? detail::fill_n(it, num_zeros, Char('0')) : it;
2474 });
2475 }
2476 if (exp > 0) {
2477 // 1234e-2 -> 12.34[0+]
2478 int num_zeros = specs.alt() ? specs.precision - significand_size : 0;
2479 size += 1 + max_of(num_zeros, 0);
2480 auto grouping = Grouping(loc, specs.localized());
2481 size += grouping.count_separators(exp);
2482 return write_padded<Char, align::right>(
2483 out, specs, to_unsigned(size), [&](iterator it) {
2484 if (s != sign::none) *it++ = detail::getsign<Char>(s);
2485 it = write_significand(it, f.significand, significand_size, exp,
2486 decimal_point, grouping);
2487 return num_zeros > 0 ? detail::fill_n(it, num_zeros, Char('0')) : it;
2488 });
2489 }
2490 // 1234e-6 -> 0.001234
2491 int num_zeros = -exp;
2492 if (significand_size == 0 && specs.precision >= 0 &&
2493 specs.precision < num_zeros) {
2494 num_zeros = specs.precision;
2495 }
2496 bool pointy = num_zeros != 0 || significand_size != 0 || specs.alt();
2497 size += 1 + (pointy ? 1 : 0) + num_zeros;
2498 return write_padded<Char, align::right>(
2499 out, specs, to_unsigned(size), [&](iterator it) {
2500 if (s != sign::none) *it++ = detail::getsign<Char>(s);
2501 *it++ = Char('0');
2502 if (!pointy) return it;
2503 *it++ = decimal_point;
2504 it = detail::fill_n(it, num_zeros, Char('0'));
2505 return write_significand<Char>(it, f.significand, significand_size);
2506 });
2507}
2508
2509template <typename Char, typename Grouping, typename OutputIt,
2510 typename DecimalFP>
2511FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f,
2512 const format_specs& specs, sign s,
2513 int exp_upper, locale_ref loc) -> OutputIt {
2514 Char point = specs.localized() ? detail::decimal_point<Char>(loc) : Char('.');
2515 int significand_size = get_significand_size(f);
2516 int exp = f.exponent + significand_size - 1;
2517 if (specs.type() == presentation_type::fixed ||
2518 (specs.type() != presentation_type::exp &&
2519 use_fixed(exp, specs.precision > 0 ? specs.precision : exp_upper))) {
2520 return write_fixed<Char, Grouping>(out, f, significand_size, point, specs,
2521 s, loc);
2522 }
2523
2524 // Write value in the exponential format.
2525 int num_zeros = 0;
2526 long long size = significand_size + (s != sign::none ? 1 : 0);
2527 if (specs.alt()) {
2528 num_zeros = max_of(specs.precision - significand_size, 0);
2529 size += num_zeros;
2530 } else if (significand_size == 1) {
2531 point = Char();
2532 }
2533 size += (point ? 1 : 0) + compute_exp_size(exp);
2534 char exp_char = specs.upper() ? 'E' : 'e';
2535 auto write = [=](reserve_iterator<OutputIt> it) {
2536 if (s != sign::none) *it++ = detail::getsign<Char>(s);
2537 // Insert a decimal point after the first digit and add an exponent.
2538 it = write_significand(it, f.significand, significand_size, 1, point);
2539 if (num_zeros > 0) it = detail::fill_n(it, num_zeros, Char('0'));
2540 *it++ = Char(exp_char);
2541 return write_exponent<Char>(exp, it);
2542 };
2543 auto usize = to_unsigned(size);
2544 return specs.width > 0
2545 ? write_padded<Char, align::right>(out, specs, usize, write)
2546 : base_iterator(out, write(reserve(out, usize)));
2547}
2548
2549template <typename Char, typename OutputIt, typename DecimalFP>
2550FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f,
2551 const format_specs& specs, sign s,
2552 int exp_upper, locale_ref loc) -> OutputIt {
2553 if (is_constant_evaluated()) {
2554 return do_write_float<Char, fallback_digit_grouping<Char>>(out, f, specs, s,
2555 exp_upper, loc);
2556 } else {
2557 return do_write_float<Char, digit_grouping<Char>>(out, f, specs, s,
2558 exp_upper, loc);
2559 }
2560}
2561
2562template <typename T> constexpr auto isnan(T value) -> bool {
2563 return value != value; // std::isnan doesn't support __float128.
2564}
2565
2566template <typename T, typename Enable = void>
2567struct has_isfinite : std::false_type {};
2568
2569template <typename T>
2570struct has_isfinite<T, enable_if_t<sizeof(std::isfinite(T())) != 0>>
2571 : std::true_type {};
2572
2573template <typename T,
2576 constexpr T inf = T(std::numeric_limits<double>::infinity());
2578 return !detail::isnan(value) && value < inf && value > -inf;
2579 return std::isfinite(value);
2580}
2581template <typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)>
2583 T inf = T(std::numeric_limits<double>::infinity());
2584 // std::isfinite doesn't support __float128.
2585 return !detail::isnan(value) && value < inf && value > -inf;
2586}
2587
2588template <typename T, FMT_ENABLE_IF(is_floating_point<T>::value)>
2590 if (is_constant_evaluated()) {
2591#ifdef __cpp_if_constexpr
2592 if constexpr (std::numeric_limits<double>::is_iec559) {
2593 auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
2594 return (bits >> (num_bits<uint64_t>() - 1)) != 0;
2595 }
2596#endif
2597 }
2598 return std::signbit(static_cast<double>(value));
2599}
2600
2601inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) {
2602 // Adjust fixed precision by exponent because it is relative to decimal
2603 // point.
2604 if (exp10 > 0 && precision > max_value<int>() - exp10)
2605 FMT_THROW(format_error("number is too big"));
2606 precision += exp10;
2607}
2608
2609class bigint {
2610 private:
2611 // A bigint is a number in the form bigit_[N - 1] ... bigit_[0] * 32^exp_.
2612 using bigit = uint32_t; // A big digit.
2613 using double_bigit = uint64_t;
2614 enum { bigit_bits = num_bits<bigit>() };
2615 enum { bigits_capacity = 32 };
2617 int exp_;
2618
2619 friend struct formatter<bigint>;
2620
2621 FMT_CONSTEXPR auto get_bigit(int i) const -> bigit {
2622 return i >= exp_ && i < num_bigits() ? bigits_[i - exp_] : 0;
2623 }
2624
2625 FMT_CONSTEXPR void subtract_bigits(int index, bigit other, bigit& borrow) {
2626 auto result = double_bigit(bigits_[index]) - other - borrow;
2627 bigits_[index] = static_cast<bigit>(result);
2628 borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
2629 }
2630
2631 FMT_CONSTEXPR void remove_leading_zeros() {
2632 int num_bigits = static_cast<int>(bigits_.size()) - 1;
2633 while (num_bigits > 0 && bigits_[num_bigits] == 0) --num_bigits;
2634 bigits_.resize(to_unsigned(num_bigits + 1));
2635 }
2636
2637 // Computes *this -= other assuming aligned bigints and *this >= other.
2638 FMT_CONSTEXPR void subtract_aligned(const bigint& other) {
2639 FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
2640 FMT_ASSERT(compare(*this, other) >= 0, "");
2641 bigit borrow = 0;
2642 int i = other.exp_ - exp_;
2643 for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
2644 subtract_bigits(i, other.bigits_[j], borrow);
2645 if (borrow != 0) subtract_bigits(i, 0, borrow);
2646 FMT_ASSERT(borrow == 0, "");
2647 remove_leading_zeros();
2648 }
2649
2650 FMT_CONSTEXPR void multiply(uint32_t value) {
2651 bigit carry = 0;
2652 const double_bigit wide_value = value;
2653 for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2654 double_bigit result = bigits_[i] * wide_value + carry;
2655 bigits_[i] = static_cast<bigit>(result);
2656 carry = static_cast<bigit>(result >> bigit_bits);
2657 }
2658 if (carry != 0) bigits_.push_back(carry);
2659 }
2660
2661 template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
2662 std::is_same<UInt, uint128_t>::value)>
2663 FMT_CONSTEXPR void multiply(UInt value) {
2664 using half_uint =
2666 const int shift = num_bits<half_uint>() - bigit_bits;
2667 const UInt lower = static_cast<half_uint>(value);
2668 const UInt upper = value >> num_bits<half_uint>();
2669 UInt carry = 0;
2670 for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2671 UInt result = lower * bigits_[i] + static_cast<bigit>(carry);
2672 carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
2673 (carry >> bigit_bits);
2674 bigits_[i] = static_cast<bigit>(result);
2675 }
2676 while (carry != 0) {
2677 bigits_.push_back(static_cast<bigit>(carry));
2678 carry >>= bigit_bits;
2679 }
2680 }
2681
2682 template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
2683 std::is_same<UInt, uint128_t>::value)>
2684 FMT_CONSTEXPR void assign(UInt n) {
2685 size_t num_bigits = 0;
2686 do {
2687 bigits_[num_bigits++] = static_cast<bigit>(n);
2688 n >>= bigit_bits;
2689 } while (n != 0);
2690 bigits_.resize(num_bigits);
2691 exp_ = 0;
2692 }
2693
2694 public:
2695 FMT_CONSTEXPR bigint() : exp_(0) {}
2696 explicit bigint(uint64_t n) { assign(n); }
2697
2698 bigint(const bigint&) = delete;
2699 void operator=(const bigint&) = delete;
2700
2701 FMT_CONSTEXPR void assign(const bigint& other) {
2702 auto size = other.bigits_.size();
2703 bigits_.resize(size);
2704 auto data = other.bigits_.data();
2705 copy<bigit>(data, data + size, bigits_.data());
2706 exp_ = other.exp_;
2707 }
2708
2709 template <typename Int> FMT_CONSTEXPR void operator=(Int n) {
2710 FMT_ASSERT(n > 0, "");
2711 assign(uint64_or_128_t<Int>(n));
2712 }
2713
2714 FMT_CONSTEXPR auto num_bigits() const -> int {
2715 return static_cast<int>(bigits_.size()) + exp_;
2716 }
2717
2718 FMT_CONSTEXPR auto operator<<=(int shift) -> bigint& {
2719 FMT_ASSERT(shift >= 0, "");
2720 exp_ += shift / bigit_bits;
2721 shift %= bigit_bits;
2722 if (shift == 0) return *this;
2723 bigit carry = 0;
2724 for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2725 bigit c = bigits_[i] >> (bigit_bits - shift);
2726 bigits_[i] = (bigits_[i] << shift) + carry;
2727 carry = c;
2728 }
2729 if (carry != 0) bigits_.push_back(carry);
2730 return *this;
2731 }
2732
2733 template <typename Int> FMT_CONSTEXPR auto operator*=(Int value) -> bigint& {
2734 FMT_ASSERT(value > 0, "");
2736 return *this;
2737 }
2738
2739 friend FMT_CONSTEXPR auto compare(const bigint& b1, const bigint& b2) -> int {
2740 int num_bigits1 = b1.num_bigits(), num_bigits2 = b2.num_bigits();
2741 if (num_bigits1 != num_bigits2) return num_bigits1 > num_bigits2 ? 1 : -1;
2742 int i = static_cast<int>(b1.bigits_.size()) - 1;
2743 int j = static_cast<int>(b2.bigits_.size()) - 1;
2744 int end = i - j;
2745 if (end < 0) end = 0;
2746 for (; i >= end; --i, --j) {
2747 bigit b1_bigit = b1.bigits_[i], b2_bigit = b2.bigits_[j];
2748 if (b1_bigit != b2_bigit) return b1_bigit > b2_bigit ? 1 : -1;
2749 }
2750 if (i != j) return i > j ? 1 : -1;
2751 return 0;
2752 }
2753
2754 // Returns compare(lhs1 + lhs2, rhs).
2755 friend FMT_CONSTEXPR auto add_compare(const bigint& lhs1, const bigint& lhs2,
2756 const bigint& rhs) -> int {
2757 int max_lhs_bigits = max_of(lhs1.num_bigits(), lhs2.num_bigits());
2758 int num_rhs_bigits = rhs.num_bigits();
2759 if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
2760 if (max_lhs_bigits > num_rhs_bigits) return 1;
2761 double_bigit borrow = 0;
2762 int min_exp = min_of(min_of(lhs1.exp_, lhs2.exp_), rhs.exp_);
2763 for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
2764 double_bigit sum = double_bigit(lhs1.get_bigit(i)) + lhs2.get_bigit(i);
2765 bigit rhs_bigit = rhs.get_bigit(i);
2766 if (sum > rhs_bigit + borrow) return 1;
2767 borrow = rhs_bigit + borrow - sum;
2768 if (borrow > 1) return -1;
2769 borrow <<= bigit_bits;
2770 }
2771 return borrow != 0 ? -1 : 0;
2772 }
2773
2774 // Assigns pow(10, exp) to this bigint.
2776 FMT_ASSERT(exp >= 0, "");
2777 if (exp == 0) return *this = 1;
2778 int bitmask = 1 << (num_bits<unsigned>() -
2779 countl_zero(static_cast<uint32_t>(exp)) - 1);
2780 // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
2781 // repeated squaring and multiplication.
2782 *this = 5;
2783 bitmask >>= 1;
2784 while (bitmask != 0) {
2785 square();
2786 if ((exp & bitmask) != 0) *this *= 5;
2787 bitmask >>= 1;
2788 }
2789 *this <<= exp; // Multiply by pow(2, exp) by shifting.
2790 }
2791
2793 int num_bigits = static_cast<int>(bigits_.size());
2794 int num_result_bigits = 2 * num_bigits;
2795 basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
2796 bigits_.resize(to_unsigned(num_result_bigits));
2797 auto sum = uint128_t();
2798 for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
2799 // Compute bigit at position bigit_index of the result by adding
2800 // cross-product terms n[i] * n[j] such that i + j == bigit_index.
2801 for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
2802 // Most terms are multiplied twice which can be optimized in the future.
2803 sum += double_bigit(n[i]) * n[j];
2804 }
2805 bigits_[bigit_index] = static_cast<bigit>(sum);
2806 sum >>= num_bits<bigit>(); // Compute the carry.
2807 }
2808 // Do the same for the top half.
2809 for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
2810 ++bigit_index) {
2811 for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
2812 sum += double_bigit(n[i++]) * n[j--];
2813 bigits_[bigit_index] = static_cast<bigit>(sum);
2814 sum >>= num_bits<bigit>();
2815 }
2816 remove_leading_zeros();
2817 exp_ *= 2;
2818 }
2819
2820 // If this bigint has a bigger exponent than other, adds trailing zero to make
2821 // exponents equal. This simplifies some operations such as subtraction.
2822 FMT_CONSTEXPR void align(const bigint& other) {
2823 int exp_difference = exp_ - other.exp_;
2824 if (exp_difference <= 0) return;
2825 int num_bigits = static_cast<int>(bigits_.size());
2826 bigits_.resize(to_unsigned(num_bigits + exp_difference));
2827 for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
2828 bigits_[j] = bigits_[i];
2829 fill_n(bigits_.data(), to_unsigned(exp_difference), 0U);
2830 exp_ -= exp_difference;
2831 }
2832
2833 // Divides this bignum by divisor, assigning the remainder to this and
2834 // returning the quotient.
2835 FMT_CONSTEXPR auto divmod_assign(const bigint& divisor) -> int {
2836 FMT_ASSERT(this != &divisor, "");
2837 if (compare(*this, divisor) < 0) return 0;
2838 FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
2839 align(divisor);
2840 int quotient = 0;
2841 do {
2842 subtract_aligned(divisor);
2843 ++quotient;
2844 } while (compare(*this, divisor) >= 0);
2845 return quotient;
2846 }
2847};
2848
2849// format_dragon flags.
2852 fixup = 2, // Run fixup to correct exp10 which can be off by one.
2854};
2855
2856// Formats a floating-point number using a variation of the Fixed-Precision
2857// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
2858// https://fmt.dev/papers/p372-steele.pdf.
2860 unsigned flags, int num_digits,
2861 buffer<char>& buf, int& exp10) {
2862 bigint numerator; // 2 * R in (FPP)^2.
2863 bigint denominator; // 2 * S in (FPP)^2.
2864 // lower and upper are differences between value and corresponding boundaries.
2865 bigint lower; // (M^- in (FPP)^2).
2866 bigint upper_store; // upper's value if different from lower.
2867 bigint* upper = nullptr; // (M^+ in (FPP)^2).
2868 // Shift numerator and denominator by an extra bit or two (if lower boundary
2869 // is closer) to make lower and upper integers. This eliminates multiplication
2870 // by 2 during later computations.
2871 bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0;
2872 int shift = is_predecessor_closer ? 2 : 1;
2873 if (value.e >= 0) {
2874 numerator = value.f;
2875 numerator <<= value.e + shift;
2876 lower = 1;
2877 lower <<= value.e;
2878 if (is_predecessor_closer) {
2879 upper_store = 1;
2880 upper_store <<= value.e + 1;
2881 upper = &upper_store;
2882 }
2883 denominator.assign_pow10(exp10);
2884 denominator <<= shift;
2885 } else if (exp10 < 0) {
2886 numerator.assign_pow10(-exp10);
2887 lower.assign(numerator);
2888 if (is_predecessor_closer) {
2889 upper_store.assign(numerator);
2890 upper_store <<= 1;
2891 upper = &upper_store;
2892 }
2893 numerator *= value.f;
2894 numerator <<= shift;
2895 denominator = 1;
2896 denominator <<= shift - value.e;
2897 } else {
2898 numerator = value.f;
2899 numerator <<= shift;
2900 denominator.assign_pow10(exp10);
2901 denominator <<= shift - value.e;
2902 lower = 1;
2903 if (is_predecessor_closer) {
2904 upper_store = 1ULL << 1;
2905 upper = &upper_store;
2906 }
2907 }
2908 int even = static_cast<int>((value.f & 1) == 0);
2909 if (!upper) upper = &lower;
2910 bool shortest = num_digits < 0;
2911 if ((flags & dragon::fixup) != 0) {
2912 if (add_compare(numerator, *upper, denominator) + even <= 0) {
2913 --exp10;
2914 numerator *= 10;
2915 if (num_digits < 0) {
2916 lower *= 10;
2917 if (upper != &lower) *upper *= 10;
2918 }
2919 }
2920 if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1);
2921 }
2922 // Invariant: value == (numerator / denominator) * pow(10, exp10).
2923 if (shortest) {
2924 // Generate the shortest representation.
2925 num_digits = 0;
2926 char* data = buf.data();
2927 for (;;) {
2928 int digit = numerator.divmod_assign(denominator);
2929 bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower.
2930 // numerator + upper >[=] pow10:
2931 bool high = add_compare(numerator, *upper, denominator) + even > 0;
2932 data[num_digits++] = static_cast<char>('0' + digit);
2933 if (low || high) {
2934 if (!low) {
2935 ++data[num_digits - 1];
2936 } else if (high) {
2937 int result = add_compare(numerator, numerator, denominator);
2938 // Round half to even.
2939 if (result > 0 || (result == 0 && (digit % 2) != 0))
2940 ++data[num_digits - 1];
2941 }
2942 buf.try_resize(to_unsigned(num_digits));
2943 exp10 -= num_digits - 1;
2944 return;
2945 }
2946 numerator *= 10;
2947 lower *= 10;
2948 if (upper != &lower) *upper *= 10;
2949 }
2950 }
2951 // Generate the given number of digits.
2952 exp10 -= num_digits - 1;
2953 if (num_digits <= 0) {
2954 auto digit = '0';
2955 if (num_digits == 0) {
2956 denominator *= 10;
2957 digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
2958 }
2959 buf.push_back(digit);
2960 return;
2961 }
2962 buf.try_resize(to_unsigned(num_digits));
2963 for (int i = 0; i < num_digits - 1; ++i) {
2964 int digit = numerator.divmod_assign(denominator);
2965 buf[i] = static_cast<char>('0' + digit);
2966 numerator *= 10;
2967 }
2968 int digit = numerator.divmod_assign(denominator);
2969 auto result = add_compare(numerator, numerator, denominator);
2970 if (result > 0 || (result == 0 && (digit % 2) != 0)) {
2971 if (digit == 9) {
2972 const auto overflow = '0' + 10;
2973 buf[num_digits - 1] = overflow;
2974 // Propagate the carry.
2975 for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
2976 buf[i] = '0';
2977 ++buf[i - 1];
2978 }
2979 if (buf[0] == overflow) {
2980 buf[0] = '1';
2981 if ((flags & dragon::fixed) != 0)
2982 buf.push_back('0');
2983 else
2984 ++exp10;
2985 }
2986 return;
2987 }
2988 ++digit;
2989 }
2990 buf[num_digits - 1] = static_cast<char>('0' + digit);
2991}
2992
2993// Formats a floating-point number using the hexfloat format.
2994template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
2996 buffer<char>& buf) {
2997 // float is passed as double to reduce the number of instantiations and to
2998 // simplify implementation.
2999 static_assert(!std::is_same<Float, float>::value, "");
3000
3001 using info = dragonbox::float_info<Float>;
3002
3003 // Assume Float is in the format [sign][exponent][significand].
3004 using carrier_uint = typename info::carrier_uint;
3005
3006 const auto num_float_significand_bits = detail::num_significand_bits<Float>();
3007
3009 f.e += num_float_significand_bits;
3010 if (!has_implicit_bit<Float>()) --f.e;
3011
3012 const auto num_fraction_bits =
3013 num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0);
3014 const auto num_xdigits = (num_fraction_bits + 3) / 4;
3015
3016 const auto leading_shift = ((num_xdigits - 1) * 4);
3017 const auto leading_mask = carrier_uint(0xF) << leading_shift;
3018 const auto leading_xdigit =
3019 static_cast<uint32_t>((f.f & leading_mask) >> leading_shift);
3020 if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1);
3021
3022 int print_xdigits = num_xdigits - 1;
3023 if (specs.precision >= 0 && print_xdigits > specs.precision) {
3024 const int shift = ((print_xdigits - specs.precision - 1) * 4);
3025 const auto mask = carrier_uint(0xF) << shift;
3026 const auto v = static_cast<uint32_t>((f.f & mask) >> shift);
3027
3028 if (v >= 8) {
3029 const auto inc = carrier_uint(1) << (shift + 4);
3030 f.f += inc;
3031 f.f &= ~(inc - 1);
3032 }
3033
3034 // Check long double overflow
3035 if (!has_implicit_bit<Float>()) {
3036 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
3037 if ((f.f & implicit_bit) == implicit_bit) {
3038 f.f >>= 4;
3039 f.e += 4;
3040 }
3041 }
3042
3043 print_xdigits = specs.precision;
3044 }
3045
3046 char xdigits[num_bits<carrier_uint>() / 4];
3047 detail::fill_n(xdigits, sizeof(xdigits), '0');
3048 format_base2e(4, xdigits, f.f, num_xdigits, specs.upper());
3049
3050 // Remove zero tail
3051 while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits;
3052
3053 buf.push_back('0');
3054 buf.push_back(specs.upper() ? 'X' : 'x');
3055 buf.push_back(xdigits[0]);
3056 if (specs.alt() || print_xdigits > 0 || print_xdigits < specs.precision)
3057 buf.push_back('.');
3058 buf.append(xdigits + 1, xdigits + 1 + print_xdigits);
3059 for (; print_xdigits < specs.precision; ++print_xdigits) buf.push_back('0');
3060
3061 buf.push_back(specs.upper() ? 'P' : 'p');
3062
3063 uint32_t abs_e;
3064 if (f.e < 0) {
3065 buf.push_back('-');
3066 abs_e = static_cast<uint32_t>(-f.e);
3067 } else {
3068 buf.push_back('+');
3069 abs_e = static_cast<uint32_t>(f.e);
3070 }
3071 format_decimal<char>(appender(buf), abs_e, detail::count_digits(abs_e));
3072}
3073
3074template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
3075FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs,
3076 buffer<char>& buf) {
3077 format_hexfloat(static_cast<double>(value), specs, buf);
3078}
3079
3080constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t {
3081 // For checking rounding thresholds.
3082 // The kth entry is chosen to be the smallest integer such that the
3083 // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k.
3084 // It is equal to ceil(2^31 + 2^32/10^(k + 1)).
3085 // These are stored in a string literal because we cannot have static arrays
3086 // in constexpr functions and non-static ones are poorly optimized.
3087 return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
3088 U"\x800001ae\x8000002b"[index];
3089}
3090
3091template <typename Float>
3092FMT_CONSTEXPR20 auto format_float(Float value, int precision,
3093 const format_specs& specs, bool binary32,
3094 buffer<char>& buf) -> int {
3095 // float is passed as double to reduce the number of instantiations.
3096 static_assert(!std::is_same<Float, float>::value, "");
3097 auto converted_value = convert_float(value);
3098
3099 const bool fixed = specs.type() == presentation_type::fixed;
3100 if (value == 0) {
3101 if (precision <= 0 || !fixed) {
3102 buf.push_back('0');
3103 return 0;
3104 }
3105 buf.try_resize(to_unsigned(precision));
3106 fill_n(buf.data(), precision, '0');
3107 return -precision;
3108 }
3109
3110 int exp = 0;
3111 bool use_dragon = true;
3112 unsigned dragon_flags = 0;
3113 if (!is_fast_float<Float>() || is_constant_evaluated()) {
3114 const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10)
3115 using info = dragonbox::float_info<decltype(converted_value)>;
3116 const auto f = basic_fp<typename info::carrier_uint>(converted_value);
3117 // Compute exp, an approximate power of 10, such that
3118 // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
3119 // This is based on log10(value) == log2(value) / log2(10) and approximation
3120 // of log2(value) by e + num_fraction_bits idea from double-conversion.
3121 auto e = (f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10;
3122 exp = static_cast<int>(e);
3123 if (e > exp) ++exp; // Compute ceil.
3124 dragon_flags = dragon::fixup;
3125 } else {
3126 // Extract significand bits and exponent bits.
3127 using info = dragonbox::float_info<double>;
3128 auto br = bit_cast<uint64_t>(static_cast<double>(value));
3129
3130 const uint64_t significand_mask =
3131 (static_cast<uint64_t>(1) << num_significand_bits<double>()) - 1;
3132 uint64_t significand = (br & significand_mask);
3133 int exponent = static_cast<int>((br & exponent_mask<double>()) >>
3134 num_significand_bits<double>());
3135
3136 if (exponent != 0) { // Check if normal.
3137 exponent -= exponent_bias<double>() + num_significand_bits<double>();
3138 significand |=
3139 (static_cast<uint64_t>(1) << num_significand_bits<double>());
3140 significand <<= 1;
3141 } else {
3142 // Normalize subnormal inputs.
3143 FMT_ASSERT(significand != 0, "zeros should not appear here");
3144 int shift = countl_zero(significand);
3145 FMT_ASSERT(shift >= num_bits<uint64_t>() - num_significand_bits<double>(),
3146 "");
3147 shift -= (num_bits<uint64_t>() - num_significand_bits<double>() - 2);
3148 exponent = (std::numeric_limits<double>::min_exponent -
3149 num_significand_bits<double>()) -
3150 shift;
3151 significand <<= shift;
3152 }
3153
3154 // Compute the first several nonzero decimal significand digits.
3155 // We call the number we get the first segment.
3156 const int k = info::kappa - dragonbox::floor_log10_pow2(exponent);
3157 exp = -k;
3158 const int beta = exponent + dragonbox::floor_log2_pow10(k);
3159 uint64_t first_segment;
3160 bool has_more_segments;
3161 int digits_in_the_first_segment;
3162 {
3163 const auto r = dragonbox::umul192_upper128(
3164 significand << beta, dragonbox::get_cached_power(k));
3165 first_segment = r.high();
3166 has_more_segments = r.low() != 0;
3167
3168 // The first segment can have 18 ~ 19 digits.
3169 if (first_segment >= 1000000000000000000ULL) {
3170 digits_in_the_first_segment = 19;
3171 } else {
3172 // When it is of 18-digits, we align it to 19-digits by adding a bogus
3173 // zero at the end.
3174 digits_in_the_first_segment = 18;
3175 first_segment *= 10;
3176 }
3177 }
3178
3179 // Compute the actual number of decimal digits to print.
3180 if (fixed) adjust_precision(precision, exp + digits_in_the_first_segment);
3181
3182 // Use Dragon4 only when there might be not enough digits in the first
3183 // segment.
3184 if (digits_in_the_first_segment > precision) {
3185 use_dragon = false;
3186
3187 if (precision <= 0) {
3188 exp += digits_in_the_first_segment;
3189
3190 if (precision < 0) {
3191 // Nothing to do, since all we have are just leading zeros.
3192 buf.try_resize(0);
3193 } else {
3194 // We may need to round-up.
3195 buf.try_resize(1);
3196 if ((first_segment | static_cast<uint64_t>(has_more_segments)) >
3197 5000000000000000000ULL) {
3198 buf[0] = '1';
3199 } else {
3200 buf[0] = '0';
3201 }
3202 }
3203 } // precision <= 0
3204 else {
3205 exp += digits_in_the_first_segment - precision;
3206
3207 // When precision > 0, we divide the first segment into three
3208 // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits
3209 // in 32-bits which usually allows faster calculation than in
3210 // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize
3211 // division-by-constant for large 64-bit divisors, we do it here
3212 // manually. The magic number 7922816251426433760 below is equal to
3213 // ceil(2^(64+32) / 10^10).
3214 const uint32_t first_subsegment = static_cast<uint32_t>(
3215 dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >>
3216 32);
3217 const uint64_t second_third_subsegments =
3218 first_segment - first_subsegment * 10000000000ULL;
3219
3220 uint64_t prod;
3221 uint32_t digits;
3222 bool should_round_up;
3223 int number_of_digits_to_print = min_of(precision, 9);
3224
3225 // Print a 9-digits subsegment, either the first or the second.
3226 auto print_subsegment = [&](uint32_t subsegment, char* buffer) {
3227 int number_of_digits_printed = 0;
3228
3229 // If we want to print an odd number of digits from the subsegment,
3230 if ((number_of_digits_to_print & 1) != 0) {
3231 // Convert to 64-bit fixed-point fractional form with 1-digit
3232 // integer part. The magic number 720575941 is a good enough
3233 // approximation of 2^(32 + 24) / 10^8; see
3234 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3235 // for details.
3236 prod = ((subsegment * static_cast<uint64_t>(720575941)) >> 24) + 1;
3237 digits = static_cast<uint32_t>(prod >> 32);
3238 *buffer = static_cast<char>('0' + digits);
3239 number_of_digits_printed++;
3240 }
3241 // If we want to print an even number of digits from the
3242 // first_subsegment,
3243 else {
3244 // Convert to 64-bit fixed-point fractional form with 2-digits
3245 // integer part. The magic number 450359963 is a good enough
3246 // approximation of 2^(32 + 20) / 10^7; see
3247 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3248 // for details.
3249 prod = ((subsegment * static_cast<uint64_t>(450359963)) >> 20) + 1;
3250 digits = static_cast<uint32_t>(prod >> 32);
3251 write2digits(buffer, digits);
3252 number_of_digits_printed += 2;
3253 }
3254
3255 // Print all digit pairs.
3256 while (number_of_digits_printed < number_of_digits_to_print) {
3257 prod = static_cast<uint32_t>(prod) * static_cast<uint64_t>(100);
3258 digits = static_cast<uint32_t>(prod >> 32);
3259 write2digits(buffer + number_of_digits_printed, digits);
3260 number_of_digits_printed += 2;
3261 }
3262 };
3263
3264 // Print first subsegment.
3265 print_subsegment(first_subsegment, buf.data());
3266
3267 // Perform rounding if the first subsegment is the last subsegment to
3268 // print.
3269 if (precision <= 9) {
3270 // Rounding inside the subsegment.
3271 // We round-up if:
3272 // - either the fractional part is strictly larger than 1/2, or
3273 // - the fractional part is exactly 1/2 and the last digit is odd.
3274 // We rely on the following observations:
3275 // - If fractional_part >= threshold, then the fractional part is
3276 // strictly larger than 1/2.
3277 // - If the MSB of fractional_part is set, then the fractional part
3278 // must be at least 1/2.
3279 // - When the MSB of fractional_part is set, either
3280 // second_third_subsegments being nonzero or has_more_segments
3281 // being true means there are further digits not printed, so the
3282 // fractional part is strictly larger than 1/2.
3283 if (precision < 9) {
3284 uint32_t fractional_part = static_cast<uint32_t>(prod);
3285 should_round_up =
3286 fractional_part >= fractional_part_rounding_thresholds(
3287 8 - number_of_digits_to_print) ||
3288 ((fractional_part >> 31) &
3289 ((digits & 1) | (second_third_subsegments != 0) |
3290 has_more_segments)) != 0;
3291 }
3292 // Rounding at the subsegment boundary.
3293 // In this case, the fractional part is at least 1/2 if and only if
3294 // second_third_subsegments >= 5000000000ULL, and is strictly larger
3295 // than 1/2 if we further have either second_third_subsegments >
3296 // 5000000000ULL or has_more_segments == true.
3297 else {
3298 should_round_up = second_third_subsegments > 5000000000ULL ||
3299 (second_third_subsegments == 5000000000ULL &&
3300 ((digits & 1) != 0 || has_more_segments));
3301 }
3302 }
3303 // Otherwise, print the second subsegment.
3304 else {
3305 // Compilers are not aware of how to leverage the maximum value of
3306 // second_third_subsegments to find out a better magic number which
3307 // allows us to eliminate an additional shift. 1844674407370955162 =
3308 // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))).
3309 const uint32_t second_subsegment =
3310 static_cast<uint32_t>(dragonbox::umul128_upper64(
3311 second_third_subsegments, 1844674407370955162ULL));
3312 const uint32_t third_subsegment =
3313 static_cast<uint32_t>(second_third_subsegments) -
3314 second_subsegment * 10;
3315
3316 number_of_digits_to_print = precision - 9;
3317 print_subsegment(second_subsegment, buf.data() + 9);
3318
3319 // Rounding inside the subsegment.
3320 if (precision < 18) {
3321 // The condition third_subsegment != 0 implies that the segment was
3322 // of 19 digits, so in this case the third segment should be
3323 // consisting of a genuine digit from the input.
3324 uint32_t fractional_part = static_cast<uint32_t>(prod);
3325 should_round_up =
3326 fractional_part >= fractional_part_rounding_thresholds(
3327 8 - number_of_digits_to_print) ||
3328 ((fractional_part >> 31) &
3329 ((digits & 1) | (third_subsegment != 0) |
3330 has_more_segments)) != 0;
3331 }
3332 // Rounding at the subsegment boundary.
3333 else {
3334 // In this case, the segment must be of 19 digits, thus
3335 // the third subsegment should be consisting of a genuine digit from
3336 // the input.
3337 should_round_up = third_subsegment > 5 ||
3338 (third_subsegment == 5 &&
3339 ((digits & 1) != 0 || has_more_segments));
3340 }
3341 }
3342
3343 // Round-up if necessary.
3344 if (should_round_up) {
3345 ++buf[precision - 1];
3346 for (int i = precision - 1; i > 0 && buf[i] > '9'; --i) {
3347 buf[i] = '0';
3348 ++buf[i - 1];
3349 }
3350 if (buf[0] > '9') {
3351 buf[0] = '1';
3352 if (fixed)
3353 buf[precision++] = '0';
3354 else
3355 ++exp;
3356 }
3357 }
3358 buf.try_resize(to_unsigned(precision));
3359 }
3360 } // if (digits_in_the_first_segment > precision)
3361 else {
3362 // Adjust the exponent for its use in Dragon4.
3363 exp += digits_in_the_first_segment - 1;
3364 }
3365 }
3366 if (use_dragon) {
3367 auto f = basic_fp<uint128_t>();
3368 bool is_predecessor_closer = binary32 ? f.assign(static_cast<float>(value))
3369 : f.assign(converted_value);
3370 if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer;
3371 if (fixed) dragon_flags |= dragon::fixed;
3372 // Limit precision to the maximum possible number of significant digits in
3373 // an IEEE754 double because we don't need to generate zeros.
3374 const int max_double_digits = 767;
3375 if (precision > max_double_digits) precision = max_double_digits;
3376 format_dragon(f, dragon_flags, precision, buf, exp);
3377 }
3378 if (!fixed && !specs.alt()) {
3379 // Remove trailing zeros.
3380 auto num_digits = buf.size();
3381 while (num_digits > 0 && buf[num_digits - 1] == '0') {
3382 --num_digits;
3383 ++exp;
3384 }
3385 buf.try_resize(num_digits);
3386 }
3387 return exp;
3388}
3389
3390template <typename Char, typename OutputIt, typename T,
3391 FMT_ENABLE_IF(is_floating_point<T>::value)>
3392FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs,
3393 locale_ref loc = {}) -> OutputIt {
3394 if (specs.localized() && write_loc(out, value, specs, loc)) return out;
3395
3396 // Use signbit because value < 0 is false for NaN.
3397 sign s = detail::signbit(value) ? sign::minus : specs.sign();
3398
3399 if (!detail::isfinite(value))
3400 return write_nonfinite<Char>(out, detail::isnan(value), specs, s);
3401
3402 if (specs.align() == align::numeric && s != sign::none) {
3403 *out++ = detail::getsign<Char>(s);
3404 s = sign::none;
3405 if (specs.width != 0) --specs.width;
3406 }
3407
3408 const int exp_upper = detail::exp_upper<T>();
3409 int precision = specs.precision;
3410 if (precision < 0) {
3411 if (specs.type() != presentation_type::none) {
3412 precision = 6;
3413 } else if (is_fast_float<T>::value && !is_constant_evaluated()) {
3414 // Use Dragonbox for the shortest format.
3415 auto dec = dragonbox::to_decimal(static_cast<fast_float_t<T>>(value));
3416 return write_float<Char>(out, dec, specs, s, exp_upper, loc);
3417 }
3418 }
3419
3420 memory_buffer buffer;
3421 if (specs.type() == presentation_type::hexfloat) {
3422 if (s != sign::none) buffer.push_back(detail::getsign<char>(s));
3423 format_hexfloat(convert_float(value), specs, buffer);
3424 return write_bytes<Char, align::right>(out, {buffer.data(), buffer.size()},
3425 specs);
3426 }
3427
3428 if (specs.type() == presentation_type::exp) {
3429 if (precision == max_value<int>())
3430 report_error("number is too big");
3431 else
3432 ++precision;
3433 if (specs.precision != 0) specs.set_alt();
3434 } else if (specs.type() == presentation_type::fixed) {
3435 if (specs.precision != 0) specs.set_alt();
3436 } else if (precision == 0) {
3437 precision = 1;
3438 }
3439 int exp = format_float(convert_float(value), precision, specs,
3440 std::is_same<T, float>(), buffer);
3441
3442 specs.precision = precision;
3443 auto f = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
3444 return write_float<Char>(out, f, specs, s, exp_upper, loc);
3445}
3446
3447template <typename Char, typename OutputIt, typename T,
3448 FMT_ENABLE_IF(is_fast_float<T>::value)>
3449FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
3450 if (is_constant_evaluated()) return write<Char>(out, value, format_specs());
3451
3453 auto mask = exponent_mask<fast_float_t<T>>();
3454 if ((bit_cast<decltype(mask)>(value) & mask) == mask)
3455 return write_nonfinite<Char>(out, std::isnan(value), {}, s);
3456
3457 auto dec = dragonbox::to_decimal(static_cast<fast_float_t<T>>(value));
3458 int significand_size = count_digits(dec.significand);
3459 int exp = dec.exponent + significand_size - 1;
3461 return write_fixed<Char, fallback_digit_grouping<Char>>(
3462 out, dec, significand_size, Char('.'), {}, s);
3463 }
3464
3465 // Write value in the exponential format.
3466 auto has_decimal_point = significand_size != 1;
3467 size_t size =
3468 to_unsigned((s != sign::none ? 1 : 0) + significand_size +
3469 (has_decimal_point ? 1 : 0) + compute_exp_size(exp));
3470 auto it = reserve(out, size);
3471 if (s != sign::none) *it++ = Char('-');
3472 // Insert a decimal point after the first digit and add an exponent.
3473 it = write_significand(it, dec.significand, significand_size, 1,
3474 has_decimal_point ? Char('.') : Char());
3475 *it++ = Char('e');
3476 it = write_exponent<Char>(exp, it);
3477 return base_iterator(out, it);
3478}
3479
3480template <typename Char, typename OutputIt, typename T,
3481 FMT_ENABLE_IF(is_floating_point<T>::value &&
3482 !is_fast_float<T>::value)>
3483inline auto write(OutputIt out, T value) -> OutputIt {
3484 return write<Char>(out, value, {});
3485}
3486
3487template <typename Char, typename OutputIt>
3488auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {})
3489 -> OutputIt {
3490 FMT_ASSERT(false, "");
3491 return out;
3492}
3493
3494template <typename Char, typename OutputIt>
3496 -> OutputIt {
3497 return copy_noinline<Char>(value.begin(), value.end(), out);
3498}
3499
3500template <typename Char, typename OutputIt, typename T,
3501 FMT_ENABLE_IF(has_to_string_view<T>::value)>
3502constexpr auto write(OutputIt out, const T& value) -> OutputIt {
3503 return write<Char>(out, to_string_view(value));
3504}
3505
3506// FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
3507template <
3508 typename Char, typename OutputIt, typename T,
3509 bool check = std::is_enum<T>::value && !std::is_same<T, Char>::value &&
3510 mapped_type_constant<T, Char>::value != type::custom_type,
3511 FMT_ENABLE_IF(check)>
3512FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
3513 return write<Char>(out, static_cast<underlying_t<T>>(value));
3514}
3515
3516template <typename Char, typename OutputIt, typename T,
3517 FMT_ENABLE_IF(std::is_same<T, bool>::value)>
3518FMT_CONSTEXPR auto write(OutputIt out, T value, const format_specs& specs = {},
3519 locale_ref = {}) -> OutputIt {
3520 return specs.type() != presentation_type::none &&
3522 ? write<Char>(out, value ? 1 : 0, specs, {})
3523 : write_bytes<Char>(out, value ? "true" : "false", specs);
3524}
3525
3526template <typename Char, typename OutputIt>
3527FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
3528 auto it = reserve(out, 1);
3529 *it++ = value;
3530 return base_iterator(out, it);
3531}
3532
3533template <typename Char, typename OutputIt>
3534FMT_CONSTEXPR20 auto write(OutputIt out, const Char* value) -> OutputIt {
3535 if (value) return write(out, basic_string_view<Char>(value));
3536 report_error("string pointer is null");
3537 return out;
3538}
3539
3540template <typename Char, typename OutputIt, typename T,
3541 FMT_ENABLE_IF(std::is_same<T, void>::value)>
3542auto write(OutputIt out, const T* value, const format_specs& specs = {},
3543 locale_ref = {}) -> OutputIt {
3544 return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
3545}
3546
3547template <typename Char, typename OutputIt, typename T,
3548 FMT_ENABLE_IF(mapped_type_constant<T, Char>::value ==
3549 type::custom_type &&
3550 !std::is_fundamental<T>::value)>
3551FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> OutputIt {
3552 auto f = formatter<T, Char>();
3553 auto parse_ctx = parse_context<Char>({});
3554 f.parse(parse_ctx);
3555 auto ctx = basic_format_context<OutputIt, Char>(out, {}, {});
3556 return f.format(value, ctx);
3557}
3558
3559template <typename T>
3562
3563// An argument visitor that formats the argument and writes it via the output
3564// iterator. It's a class and not a generic lambda for compatibility with C++11.
3565template <typename Char> struct default_arg_formatter {
3567
3569
3570 void operator()(monostate) { report_error("argument not found"); }
3571
3572 template <typename T, FMT_ENABLE_IF(is_builtin<T>::value)>
3574 write<Char>(out, value);
3575 }
3576
3577 template <typename T, FMT_ENABLE_IF(!is_builtin<T>::value)>
3578 void operator()(T) {
3579 FMT_ASSERT(false, "");
3580 }
3581
3583 // Use a null locale since the default format must be unlocalized.
3584 auto parse_ctx = parse_context<Char>({});
3585 auto format_ctx = context(out, {}, {});
3586 h.format(parse_ctx, format_ctx);
3587 }
3588};
3589
3590template <typename Char> struct arg_formatter {
3594
3595 template <typename T, FMT_ENABLE_IF(is_builtin<T>::value)>
3599
3600 template <typename T, FMT_ENABLE_IF(!is_builtin<T>::value)>
3601 void operator()(T) {
3602 FMT_ASSERT(false, "");
3603 }
3604
3606 // User-defined types are handled separately because they require access
3607 // to the parse context.
3608 }
3609};
3610
3612 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
3613 FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
3614 return is_negative(value) ? ~0ull : static_cast<unsigned long long>(value);
3615 }
3616
3617 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
3618 FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
3619 report_error("width/precision is not integer");
3620 return 0;
3621 }
3622};
3623
3624template <typename Context, typename ID>
3626 auto arg = ctx.arg(id);
3627 if (!arg) report_error("argument not found");
3628 return arg;
3629}
3630
3631template <typename Context>
3634 Context& ctx) {
3635 FMT_ASSERT(kind != arg_id_kind::none, "");
3636 auto arg =
3637 kind == arg_id_kind::index ? ctx.arg(ref.index) : ctx.arg(ref.name);
3638 if (!arg) report_error("argument not found");
3639 unsigned long long value = arg.visit(dynamic_spec_getter());
3640 if (value > to_unsigned(max_value<int>()))
3641 report_error("width/precision is out of range");
3642 return static_cast<int>(value);
3643}
3644
3645template <typename Context>
3647 arg_id_kind kind, int& value,
3648 const arg_ref<typename Context::char_type>& ref, Context& ctx) {
3649 if (kind != arg_id_kind::none) value = get_dynamic_spec(kind, ref, ctx);
3650}
3651
3652#if FMT_USE_NONTYPE_TEMPLATE_ARGS
3653template <typename T, typename Char, size_t N,
3654 fmt::detail::fixed_string<Char, N> Str>
3655struct static_named_arg : view {
3656 static constexpr auto name = Str.data;
3657
3658 const T& value;
3659 static_named_arg(const T& v) : value(v) {}
3660};
3661
3662template <typename T, typename Char, size_t N,
3663 fmt::detail::fixed_string<Char, N> Str>
3664struct is_named_arg<static_named_arg<T, Char, N, Str>> : std::true_type {};
3665
3666template <typename T, typename Char, size_t N,
3667 fmt::detail::fixed_string<Char, N> Str>
3668struct is_static_named_arg<static_named_arg<T, Char, N, Str>> : std::true_type {
3669};
3670
3671template <typename Char, size_t N, fmt::detail::fixed_string<Char, N> Str>
3672struct udl_arg {
3673 template <typename T> auto operator=(T&& value) const {
3674 return static_named_arg<T, Char, N, Str>(std::forward<T>(value));
3675 }
3676};
3677#else
3678template <typename Char> struct udl_arg {
3679 const Char* str;
3680
3681 template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
3682 return {str, std::forward<T>(value)};
3683 }
3684};
3685#endif // FMT_USE_NONTYPE_TEMPLATE_ARGS
3686
3687template <typename Char> struct format_handler {
3690
3691 void on_text(const Char* begin, const Char* end) {
3692 copy_noinline<Char>(begin, end, ctx.out());
3693 }
3694
3695 FMT_CONSTEXPR auto on_arg_id() -> int { return parse_ctx.next_arg_id(); }
3696 FMT_CONSTEXPR auto on_arg_id(int id) -> int {
3697 parse_ctx.check_arg_id(id);
3698 return id;
3699 }
3701 parse_ctx.check_arg_id(id);
3702 int arg_id = ctx.arg_id(id);
3703 if (arg_id < 0) report_error("argument not found");
3704 return arg_id;
3705 }
3706
3707 FMT_INLINE void on_replacement_field(int id, const Char*) {
3708 ctx.arg(id).visit(default_arg_formatter<Char>{ctx.out()});
3709 }
3710
3711 auto on_format_specs(int id, const Char* begin, const Char* end)
3712 -> const Char* {
3713 auto arg = get_arg(ctx, id);
3714 // Not using a visitor for custom types gives better codegen.
3715 if (arg.format_custom(begin, parse_ctx, ctx)) return parse_ctx.begin();
3716
3717 auto specs = dynamic_format_specs<Char>();
3718 begin = parse_format_specs(begin, end, specs, parse_ctx, arg.type());
3719 if (specs.dynamic()) {
3720 handle_dynamic_spec(specs.dynamic_width(), specs.width, specs.width_ref,
3721 ctx);
3723 specs.precision_ref, ctx);
3724 }
3725
3726 arg.visit(arg_formatter<Char>{ctx.out(), specs, ctx.locale()});
3727 return begin;
3728 }
3729
3730 FMT_NORETURN void on_error(const char* message) { report_error(message); }
3731};
3732
3733using format_func = void (*)(detail::buffer<char>&, int, const char*);
3734FMT_API void do_report_error(format_func func, int error_code,
3735 const char* message) noexcept;
3736
3737FMT_API void format_error_code(buffer<char>& out, int error_code,
3738 string_view message) noexcept;
3739
3740template <typename T, typename Char, type TYPE>
3741template <typename FormatContext>
3743 const T& val, FormatContext& ctx) const -> decltype(ctx.out()) {
3744 if (!specs_.dynamic())
3745 return write<Char>(ctx.out(), val, specs_, ctx.locale());
3746 auto specs = format_specs(specs_);
3747 handle_dynamic_spec(specs.dynamic_width(), specs.width, specs_.width_ref,
3748 ctx);
3750 specs_.precision_ref, ctx);
3751 return write<Char>(ctx.out(), val, specs, ctx.locale());
3752}
3753
3754// DEPRECATED! https://github.com/fmtlib/fmt/issues/4292.
3755template <typename T, typename Enable = void>
3756struct is_locale : std::false_type {};
3757template <typename T>
3758struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
3759
3760// DEPRECATED!
3761template <typename Char = char> struct vformat_args {
3763};
3764template <> struct vformat_args<char> {
3766};
3767
3768template <typename Char>
3770 typename vformat_args<Char>::type args, locale_ref loc = {}) {
3771 auto out = basic_appender<Char>(buf);
3772 parse_format_string(
3773 fmt, format_handler<Char>{parse_context<Char>(fmt), {out, args, loc}});
3774}
3775} // namespace detail
3776
3778
3779// A generic formatting context with custom output iterator and character
3780// (code unit) support. Char is the format string code unit type which can be
3781// different from OutputIt::value_type.
3782template <typename OutputIt, typename Char> class generic_context {
3783 private:
3784 OutputIt out_;
3786 detail::locale_ref loc_;
3787
3788 public:
3789 using char_type = Char;
3790 using iterator = OutputIt;
3791 using parse_context_type FMT_DEPRECATED = parse_context<Char>;
3792 template <typename T>
3793 using formatter_type FMT_DEPRECATED = formatter<T, Char>;
3795
3796 constexpr generic_context(OutputIt out,
3798 detail::locale_ref loc = {})
3799 : out_(out), args_(args), loc_(loc) {}
3802 void operator=(const generic_context&) = delete;
3803
3804 constexpr auto arg(int id) const -> basic_format_arg<generic_context> {
3805 return args_.get(id);
3806 }
3809 return args_.get(name);
3810 }
3811 constexpr auto arg_id(basic_string_view<Char> name) const -> int {
3812 return args_.get_id(name);
3813 }
3814
3815 constexpr auto out() const -> iterator { return out_; }
3816
3819 }
3820
3821 constexpr auto locale() const -> detail::locale_ref { return loc_; }
3822};
3823
3825 private:
3827
3828 public:
3829 template <typename T, FMT_ENABLE_IF(!detail::is_float128<T>::value)>
3830 loc_value(T value) : value_(value) {}
3831
3832 template <typename T, FMT_ENABLE_IF(detail::is_float128<T>::value)>
3834
3835 template <typename Visitor> auto visit(Visitor&& vis) -> decltype(vis(0)) {
3836 return value_.visit(vis);
3837 }
3838};
3839
3840// A locale facet that formats values in UTF-8.
3841// It is parameterized on the locale to avoid the heavy <locale> include.
3842template <typename Locale> class format_facet : public Locale::facet {
3843 private:
3844 std::string separator_;
3845 std::string grouping_;
3846 std::string decimal_point_;
3847
3848 protected:
3849 virtual auto do_put(appender out, loc_value val,
3850 const format_specs& specs) const -> bool;
3851
3852 public:
3853 static FMT_API typename Locale::id id;
3854
3855 explicit format_facet(Locale& loc);
3856 explicit format_facet(string_view sep = "", std::string grouping = "\3",
3857 std::string decimal_point = ".")
3858 : separator_(sep.data(), sep.size()),
3859 grouping_(grouping),
3860 decimal_point_(decimal_point) {}
3861
3862 auto put(appender out, loc_value val, const format_specs& specs) const
3863 -> bool {
3864 return do_put(out, val, specs);
3865 }
3866};
3867
3868#define FMT_FORMAT_AS(Type, Base) \
3869 template <typename Char> \
3870 struct formatter<Type, Char> : formatter<Base, Char> { \
3871 template <typename FormatContext> \
3872 FMT_CONSTEXPR auto format(Type value, FormatContext& ctx) const \
3873 -> decltype(ctx.out()) { \
3874 return formatter<Base, Char>::format(value, ctx); \
3875 } \
3876 }
3877
3878FMT_FORMAT_AS(signed char, int);
3879FMT_FORMAT_AS(unsigned char, unsigned);
3880FMT_FORMAT_AS(short, int);
3881FMT_FORMAT_AS(unsigned short, unsigned);
3884FMT_FORMAT_AS(Char*, const Char*);
3886FMT_FORMAT_AS(std::nullptr_t, const void*);
3887FMT_FORMAT_AS(void*, const void*);
3888
3889template <typename Char, size_t N>
3890struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {};
3891
3892template <typename Char, typename Traits, typename Allocator>
3893class formatter<std::basic_string<Char, Traits, Allocator>, Char>
3894 : public formatter<basic_string_view<Char>, Char> {};
3895
3896template <int N, typename Char>
3897struct formatter<detail::bitint<N>, Char> : formatter<long long, Char> {};
3898template <int N, typename Char>
3899struct formatter<detail::ubitint<N>, Char>
3900 : formatter<unsigned long long, Char> {};
3901
3902template <typename Char>
3903struct formatter<detail::float128, Char>
3904 : detail::native_formatter<detail::float128, Char,
3905 detail::type::float_type> {};
3906
3907template <typename T, typename Char>
3908struct formatter<T, Char, void_t<detail::format_as_result<T>>>
3909 : formatter<detail::format_as_result<T>, Char> {
3910 template <typename FormatContext>
3911 FMT_CONSTEXPR auto format(const T& value, FormatContext& ctx) const
3912 -> decltype(ctx.out()) {
3913 auto&& val = format_as(value); // Make an lvalue reference for format.
3914 return formatter<detail::format_as_result<T>, Char>::format(val, ctx);
3915 }
3916};
3917
3918/**
3919 * Converts `p` to `const void*` for pointer formatting.
3920 *
3921 * **Example**:
3922 *
3923 * auto s = fmt::format("{}", fmt::ptr(p));
3924 */
3925template <typename T> auto ptr(T p) -> const void* {
3926 static_assert(std::is_pointer<T>::value, "fmt::ptr used with non-pointer");
3928}
3929
3930/**
3931 * Converts `e` to the underlying type.
3932 *
3933 * **Example**:
3934 *
3935 * enum class color { red, green, blue };
3936 * auto s = fmt::format("{}", fmt::underlying(color::red)); // s == "0"
3937 */
3938template <typename Enum>
3939constexpr auto underlying(Enum e) noexcept -> underlying_t<Enum> {
3940 return static_cast<underlying_t<Enum>>(e);
3941}
3942
3943namespace enums {
3944template <typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)>
3945constexpr auto format_as(Enum e) noexcept -> underlying_t<Enum> {
3946 return static_cast<underlying_t<Enum>>(e);
3947}
3948} // namespace enums
3949
3950#ifdef __cpp_lib_byte
3951template <typename Char>
3952struct formatter<std::byte, Char> : formatter<unsigned, Char> {
3953 static auto format_as(std::byte b) -> unsigned char {
3954 return static_cast<unsigned char>(b);
3955 }
3956 template <typename Context>
3957 auto format(std::byte b, Context& ctx) const -> decltype(ctx.out()) {
3959 }
3960};
3961#endif
3962
3963struct bytes {
3965
3966 inline explicit bytes(string_view s) : data(s) {}
3967};
3968
3969template <> struct formatter<bytes> {
3970 private:
3972
3973 public:
3974 FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* {
3975 return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
3977 }
3978
3979 template <typename FormatContext>
3980 auto format(bytes b, FormatContext& ctx) const -> decltype(ctx.out()) {
3981 auto specs = specs_;
3983 specs.width_ref, ctx);
3985 specs.precision_ref, ctx);
3986 return detail::write_bytes<char>(ctx.out(), b.data, specs);
3987 }
3988};
3989
3990// group_digits_view is not derived from view because it copies the argument.
3991template <typename T> struct group_digits_view {
3993};
3994
3995/**
3996 * Returns a view that formats an integer value using ',' as a
3997 * locale-independent thousands separator.
3998 *
3999 * **Example**:
4000 *
4001 * fmt::print("{}", fmt::group_digits(12345));
4002 * // Output: "12,345"
4003 */
4004template <typename T> auto group_digits(T value) -> group_digits_view<T> {
4005 return {value};
4006}
4007
4008template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
4009 private:
4011
4012 public:
4013 FMT_CONSTEXPR auto parse(parse_context<>& ctx) -> const char* {
4014 return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4016 }
4017
4018 template <typename FormatContext>
4019 auto format(group_digits_view<T> view, FormatContext& ctx) const
4020 -> decltype(ctx.out()) {
4021 auto specs = specs_;
4023 specs.width_ref, ctx);
4025 specs.precision_ref, ctx);
4026 auto arg = detail::make_write_int_arg(view.value, specs.sign());
4027 return detail::write_int(
4028 ctx.out(), static_cast<detail::uint64_or_128_t<T>>(arg.abs_value),
4029 arg.prefix, specs, detail::digit_grouping<char>("\3", ","));
4030 }
4031};
4032
4033template <typename T, typename Char> struct nested_view {
4035 const T* value;
4036};
4037
4038template <typename T, typename Char>
4039struct formatter<nested_view<T, Char>, Char> {
4040 FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
4041 return ctx.begin();
4042 }
4043 template <typename FormatContext>
4044 auto format(nested_view<T, Char> view, FormatContext& ctx) const
4045 -> decltype(ctx.out()) {
4046 return view.fmt->format(*view.value, ctx);
4047 }
4048};
4049
4050template <typename T, typename Char = char> struct nested_formatter {
4051 private:
4052 basic_specs specs_;
4053 int width_;
4054 formatter<T, Char> formatter_;
4055
4056 public:
4057 constexpr nested_formatter() : width_(0) {}
4058
4059 FMT_CONSTEXPR auto parse(parse_context<Char>& ctx) -> const Char* {
4060 auto it = ctx.begin(), end = ctx.end();
4061 if (it == end) return it;
4062 auto specs = format_specs();
4063 it = detail::parse_align(it, end, specs);
4064 specs_ = specs;
4065 Char c = *it;
4066 auto width_ref = detail::arg_ref<Char>();
4067 if ((c >= '0' && c <= '9') || c == '{') {
4068 it = detail::parse_width(it, end, specs, width_ref, ctx);
4069 width_ = specs.width;
4070 }
4071 ctx.advance_to(it);
4072 return formatter_.parse(ctx);
4073 }
4074
4075 template <typename FormatContext, typename F>
4076 auto write_padded(FormatContext& ctx, F write) const -> decltype(ctx.out()) {
4077 if (width_ == 0) return write(ctx.out());
4078 auto buf = basic_memory_buffer<Char>();
4079 write(basic_appender<Char>(buf));
4080 auto specs = format_specs();
4081 specs.width = width_;
4082 specs.copy_fill_from(specs_);
4083 specs.set_align(specs_.align());
4084 return detail::write<Char>(
4085 ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs);
4086 }
4087
4088 auto nested(const T& value) const -> nested_view<T, Char> {
4089 return nested_view<T, Char>{&formatter_, &value};
4090 }
4091};
4092
4093inline namespace literals {
4094#if FMT_USE_NONTYPE_TEMPLATE_ARGS
4095template <detail::fixed_string S> constexpr auto operator""_a() {
4096 using char_t = remove_cvref_t<decltype(*S.data)>;
4097 return detail::udl_arg<char_t, sizeof(S.data) / sizeof(char_t), S>();
4098}
4099#else
4100/**
4101 * User-defined literal equivalent of `fmt::arg`.
4102 *
4103 * **Example**:
4104 *
4105 * using namespace fmt::literals;
4106 * fmt::print("The answer is {answer}.", "answer"_a=42);
4107 */
4108constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg<char> {
4109 return {s};
4110}
4111#endif // FMT_USE_NONTYPE_TEMPLATE_ARGS
4112} // namespace literals
4113
4114/// A fast integer formatter.
4116 private:
4117 // Buffer should be large enough to hold all digits (digits10 + 1),
4118 // a sign and a null character.
4119 enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
4120 mutable char buffer_[buffer_size];
4121 char* str_;
4122
4123 template <typename UInt>
4124 FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* {
4125 auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
4126 return detail::do_format_decimal(buffer_, n, buffer_size - 1);
4127 }
4128
4129 template <typename Int>
4130 FMT_CONSTEXPR20 auto format_signed(Int value) -> char* {
4131 auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
4132 bool negative = value < 0;
4133 if (negative) abs_value = 0 - abs_value;
4134 auto begin = format_unsigned(abs_value);
4135 if (negative) *--begin = '-';
4136 return begin;
4137 }
4138
4139 public:
4140 FMT_CONSTEXPR20 explicit format_int(int value) : str_(format_signed(value)) {}
4141 FMT_CONSTEXPR20 explicit format_int(long value)
4142 : str_(format_signed(value)) {}
4143 FMT_CONSTEXPR20 explicit format_int(long long value)
4144 : str_(format_signed(value)) {}
4145 FMT_CONSTEXPR20 explicit format_int(unsigned value)
4146 : str_(format_unsigned(value)) {}
4147 FMT_CONSTEXPR20 explicit format_int(unsigned long value)
4148 : str_(format_unsigned(value)) {}
4149 FMT_CONSTEXPR20 explicit format_int(unsigned long long value)
4150 : str_(format_unsigned(value)) {}
4151
4152 /// Returns the number of characters written to the output buffer.
4153 FMT_CONSTEXPR20 auto size() const -> size_t {
4154 return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
4155 }
4156
4157 /// Returns a pointer to the output buffer content. No terminating null
4158 /// character is appended.
4159 FMT_CONSTEXPR20 auto data() const -> const char* { return str_; }
4160
4161 /// Returns a pointer to the output buffer content with terminating null
4162 /// character appended.
4163 FMT_CONSTEXPR20 auto c_str() const -> const char* {
4164 buffer_[buffer_size - 1] = '\0';
4165 return str_;
4166 }
4167
4168 /// Returns the content of the output buffer as an `std::string`.
4169 inline auto str() const -> std::string { return {str_, size()}; }
4170};
4171
4172#define FMT_STRING_IMPL(s, base) \
4173 [] { \
4174 /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
4175 /* Use a macro-like name to avoid shadowing warnings. */ \
4176 struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
4177 using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
4178 constexpr explicit operator fmt::basic_string_view<char_type>() const { \
4179 return fmt::detail::compile_string_to_view<char_type>(s); \
4180 } \
4181 }; \
4182 using FMT_STRING_VIEW = \
4183 fmt::basic_string_view<typename FMT_COMPILE_STRING::char_type>; \
4184 fmt::detail::ignore_unused(FMT_STRING_VIEW(FMT_COMPILE_STRING())); \
4185 return FMT_COMPILE_STRING(); \
4186 }()
4187
4188/**
4189 * Constructs a legacy compile-time format string from a string literal `s`.
4190 *
4191 * **Example**:
4192 *
4193 * // A compile-time error because 'd' is an invalid specifier for strings.
4194 * std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
4195 */
4196#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string)
4197
4198FMT_API auto vsystem_error(int error_code, string_view fmt, format_args args)
4199 -> std::system_error;
4200
4201/**
4202 * Constructs `std::system_error` with a message formatted with
4203 * `fmt::format(fmt, args...)`.
4204 * `error_code` is a system error code as given by `errno`.
4205 *
4206 * **Example**:
4207 *
4208 * // This throws std::system_error with the description
4209 * // cannot open file 'madeup': No such file or directory
4210 * // or similar (system message may vary).
4211 * const char* filename = "madeup";
4212 * FILE* file = fopen(filename, "r");
4213 * if (!file)
4214 * throw fmt::system_error(errno, "cannot open file '{}'", filename);
4215 */
4216template <typename... T>
4217auto system_error(int error_code, format_string<T...> fmt, T&&... args)
4218 -> std::system_error {
4219 return vsystem_error(error_code, fmt.str, vargs<T...>{{args...}});
4220}
4221
4222/**
4223 * Formats an error message for an error returned by an operating system or a
4224 * language runtime, for example a file opening error, and writes it to `out`.
4225 * The format is the same as the one used by `std::system_error(ec, message)`
4226 * where `ec` is `std::error_code(error_code, std::generic_category())`.
4227 * It is implementation-defined but normally looks like:
4228 *
4229 * <message>: <system-message>
4230 *
4231 * where `<message>` is the passed message and `<system-message>` is the system
4232 * message corresponding to the error code.
4233 * `error_code` is a system error code as given by `errno`.
4234 */
4235FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
4236 const char* message) noexcept;
4237
4238// Reports a system error without throwing an exception.
4239// Can be used to report errors from destructors.
4240FMT_API void report_system_error(int error_code, const char* message) noexcept;
4241
4242template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4243inline auto vformat(const Locale& loc, string_view fmt, format_args args)
4244 -> std::string {
4245 auto buf = memory_buffer();
4246 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
4247 return {buf.data(), buf.size()};
4248}
4249
4250template <typename Locale, typename... T,
4252FMT_INLINE auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
4253 -> std::string {
4254 return vformat(loc, fmt.str, vargs<T...>{{args...}});
4255}
4256
4257template <typename OutputIt, typename Locale,
4259auto vformat_to(OutputIt out, const Locale& loc, string_view fmt,
4260 format_args args) -> OutputIt {
4261 auto&& buf = detail::get_buffer<char>(out);
4262 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
4263 return detail::get_iterator(buf, out);
4264}
4265
4266template <typename OutputIt, typename Locale, typename... T,
4269FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
4270 format_string<T...> fmt, T&&... args) -> OutputIt {
4271 return fmt::vformat_to(out, loc, fmt.str, vargs<T...>{{args...}});
4272}
4273
4274template <typename Locale, typename... T,
4278 T&&... args) -> size_t {
4279 auto buf = detail::counting_buffer<>();
4280 detail::vformat_to(buf, fmt.str, vargs<T...>{{args...}},
4281 detail::locale_ref(loc));
4282 return buf.count();
4283}
4284
4285FMT_API auto vformat(string_view fmt, format_args args) -> std::string;
4286
4287/**
4288 * Formats `args` according to specifications in `fmt` and returns the result
4289 * as a string.
4290 *
4291 * **Example**:
4292 *
4293 * #include <fmt/format.h>
4294 * std::string message = fmt::format("The answer is {}.", 42);
4295 */
4296template <typename... T>
4298 -> std::string {
4299 return vformat(fmt.str, vargs<T...>{{args...}});
4300}
4301
4302/**
4303 * Converts `value` to `std::string` using the default format for type `T`.
4304 *
4305 * **Example**:
4306 *
4307 * std::string answer = fmt::to_string(42);
4308 */
4309template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
4310FMT_NODISCARD FMT_CONSTEXPR_STRING auto to_string(T value) -> std::string {
4311 // The buffer should be large enough to store the number including the sign
4312 // or "false" for bool.
4313 char buffer[max_of(detail::digits10<T>() + 2, 5)];
4314 return {buffer, detail::write<char>(buffer, value)};
4315}
4316
4317template <typename T, FMT_ENABLE_IF(detail::use_format_as<T>::value)>
4319 -> std::string {
4320 return to_string(format_as(value));
4321}
4322
4323template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
4324 !detail::use_format_as<T>::value)>
4325FMT_NODISCARD FMT_CONSTEXPR_STRING auto to_string(const T& value)
4326 -> std::string {
4327 auto buffer = memory_buffer();
4328 detail::write<char>(appender(buffer), value);
4329 return {buffer.data(), buffer.size()};
4330}
4331
4334
4335#ifdef FMT_HEADER_ONLY
4336# define FMT_FUNC inline
4337# include "format-inl.h"
4338#endif
4339
4340// Restore _LIBCPP_REMOVE_TRANSITIVE_INCLUDES.
4341#ifdef FMT_REMOVE_TRANSITIVE_INCLUDES
4342# undef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
4343#endif
4344
4345#endif // FMT_FORMAT_H_
constexpr auto format_as(HAL_AddressableLEDColorOrder order)
Definition AddressableLEDTypes.h:33
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or glfw and nanopb were modified for use in Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
Definition ThirdPartyNotices.txt:140
Definition base.h:2474
Definition base.h:2504
void format(parse_context< char_type > &parse_ctx, Context &ctx) const
Definition base.h:2511
Definition base.h:2494
FMT_CONSTEXPR FMT_INLINE auto visit(Visitor &&vis) const -> decltype(vis(0))
Visits an argument dispatching to the appropriate visit method based on the argument type.
Definition base.h:2534
A view of a collection of formatting arguments.
Definition base.h:2575
FMT_CONSTEXPR auto get(int id) const -> format_arg
Returns the argument with the specified id.
Definition base.h:2636
FMT_CONSTEXPR auto get_id(basic_string_view< Char > name) const -> int
Definition base.h:2655
A dynamically growing memory buffer for trivially copyable/constructible types with the first SIZE el...
Definition format.h:774
const T & const_reference
Definition format.h:813
FMT_CONSTEXPR20 ~basic_memory_buffer()
Definition format.h:821
auto operator=(basic_memory_buffer &&other) noexcept -> basic_memory_buffer &
Moves the content of the other basic_memory_buffer object to this one.
Definition format.h:851
void reserve(size_t new_capacity)
Increases the buffer capacity to new_capacity.
Definition format.h:866
auto get_allocator() const -> Allocator
Definition format.h:859
FMT_CONSTEXPR20 void append(const ContiguousRange &range)
Definition format.h:870
FMT_CONSTEXPR basic_memory_buffer(const Allocator &alloc=Allocator())
Definition format.h:815
FMT_CONSTEXPR void resize(size_t count)
Resizes the buffer to contain count elements.
Definition format.h:863
FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer &&other) noexcept
Constructs a basic_memory_buffer object moving the content of the other object to it.
Definition format.h:845
T value_type
Definition format.h:812
Definition base.h:702
constexpr bool dynamic() const
Definition base.h:783
FMT_CONSTEXPR void copy_fill_from(const basic_specs &specs)
Definition base.h:847
FMT_CONSTEXPR void set_fill(char c)
Definition base.h:826
constexpr auto align() const -> align
Definition base.h:760
FMT_CONSTEXPR auto dynamic_precision() const -> arg_id_kind
Definition base.h:774
constexpr auto sign() const -> sign
Definition base.h:787
FMT_CONSTEXPR void set_alt()
Definition base.h:798
constexpr auto localized() const -> bool
Definition base.h:801
constexpr auto upper() const -> bool
Definition base.h:794
constexpr auto type() const -> presentation_type
Definition base.h:753
constexpr auto alt() const -> bool
Definition base.h:797
constexpr auto dynamic_width() const -> arg_id_kind
Definition base.h:767
constexpr auto fill_unit() const -> Char
Definition base.h:819
FMT_CONSTEXPR void set_align(fmt::align a)
Definition base.h:763
constexpr auto fill_size() const -> size_t
Definition base.h:806
An implementation of std::basic_string_view for pre-C++17.
Definition base.h:518
constexpr auto end() const noexcept -> iterator
Definition base.h:566
constexpr auto size() const noexcept -> size_t
Returns the string size.
Definition base.h:563
constexpr auto data() const noexcept -> const Char *
Returns a pointer to the string data.
Definition base.h:560
constexpr auto begin() const noexcept -> iterator
Definition base.h:565
Definition base.h:2673
Definition format.h:2609
FMT_CONSTEXPR void align(const bigint &other)
Definition format.h:2822
FMT_CONSTEXPR auto operator<<=(int shift) -> bigint &
Definition format.h:2718
FMT_CONSTEXPR20 void square()
Definition format.h:2792
FMT_CONSTEXPR bigint()
Definition format.h:2695
FMT_CONSTEXPR auto operator*=(Int value) -> bigint &
Definition format.h:2733
FMT_CONSTEXPR void operator=(Int n)
Definition format.h:2709
FMT_CONSTEXPR void assign(const bigint &other)
Definition format.h:2701
void operator=(const bigint &)=delete
bigint(uint64_t n)
Definition format.h:2696
FMT_CONSTEXPR20 void assign_pow10(int exp)
Definition format.h:2775
friend FMT_CONSTEXPR auto compare(const bigint &b1, const bigint &b2) -> int
Definition format.h:2739
FMT_CONSTEXPR auto num_bigits() const -> int
Definition format.h:2714
friend FMT_CONSTEXPR auto add_compare(const bigint &lhs1, const bigint &lhs2, const bigint &rhs) -> int
Definition format.h:2755
FMT_CONSTEXPR auto divmod_assign(const bigint &divisor) -> int
Definition format.h:2835
bigint(const bigint &)=delete
A contiguous memory buffer with an optional growing ability.
Definition base.h:1746
FMT_CONSTEXPR20 void append(const U *begin, const U *end)
Appends data to the end of the buffer.
Definition base.h:1828
FMT_CONSTEXPR void push_back(const T &value)
Definition base.h:1815
constexpr auto size() const noexcept -> size_t
Returns the size of this buffer.
Definition base.h:1788
FMT_CONSTEXPR void try_reserve(size_t new_capacity)
Definition base.h:1811
auto end() noexcept -> T *
Definition base.h:1782
FMT_CONSTEXPR void try_resize(size_t count)
Definition base.h:1802
constexpr auto capacity() const noexcept -> size_t
Returns the capacity of this buffer.
Definition base.h:1791
FMT_CONSTEXPR auto data() noexcept -> T *
Returns a pointer to the buffer data (not null-terminated).
Definition base.h:1794
Definition base.h:1966
Definition base.h:2003
constexpr auto count() const noexcept -> size_t
Definition base.h:2018
Definition format.h:1825
auto apply(Out out, basic_string_view< C > digits) const -> Out
Definition format.h:1869
digit_grouping(std::string grouping, std::basic_string< Char > sep)
Definition format.h:1855
auto has_separator() const -> bool
Definition format.h:1858
digit_grouping(Locale loc, bool localized=true)
Definition format.h:1849
auto count_separators(int num_digits) const -> int
Definition format.h:1860
Definition format.h:2429
constexpr auto has_separator() const -> bool
Definition format.h:2433
constexpr auto count_separators(int) const -> int
Definition format.h:2435
constexpr fallback_digit_grouping(locale_ref, bool)
Definition format.h:2431
constexpr auto apply(Out out, basic_string_view< C >) const -> Out
Definition format.h:2438
Definition base.h:2318
Definition format.h:1273
static auto convert(Buffer &buf, basic_string_view< WChar > s, to_utf8_error_policy policy=to_utf8_error_policy::abort) -> bool
Definition format.h:1302
auto convert(basic_string_view< WChar > s, to_utf8_error_policy policy=to_utf8_error_policy::abort) -> bool
Definition format.h:1295
to_utf8(basic_string_view< WChar > s, to_utf8_error_policy policy=to_utf8_error_policy::abort)
Definition format.h:1279
to_utf8()
Definition format.h:1278
auto c_str() const -> const char *
Definition format.h:1289
auto size() const -> size_t
Definition format.h:1288
auto str() const -> std::string
Definition format.h:1290
Definition format.h:302
FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback &
Definition format.h:373
constexpr uint128_fallback(uint64_t hi, uint64_t lo)
Definition format.h:307
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback
Definition format.h:363
friend constexpr auto operator==(const uint128_fallback &lhs, const uint128_fallback &rhs) -> bool
Definition format.h:318
friend FMT_CONSTEXPR auto operator*(const uint128_fallback &lhs, uint32_t rhs) -> uint128_fallback
Definition format.h:351
friend constexpr auto operator|(const uint128_fallback &lhs, const uint128_fallback &rhs) -> uint128_fallback
Definition format.h:330
friend constexpr auto operator-(const uint128_fallback &lhs, uint64_t rhs) -> uint128_fallback
Definition format.h:359
FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback
Definition format.h:368
friend constexpr auto operator!=(const uint128_fallback &lhs, const uint128_fallback &rhs) -> bool
Definition format.h:322
friend constexpr auto operator~(const uint128_fallback &n) -> uint128_fallback
Definition format.h:340
friend FMT_CONSTEXPR auto operator+(const uint128_fallback &lhs, const uint128_fallback &rhs) -> uint128_fallback
Definition format.h:344
friend constexpr auto operator>(const uint128_fallback &lhs, const uint128_fallback &rhs) -> bool
Definition format.h:326
constexpr uint128_fallback(uint64_t value=0)
Definition format.h:308
constexpr auto high() const noexcept -> uint64_t
Definition format.h:310
FMT_CONSTEXPR void operator+=(uint128_fallback n)
Definition format.h:376
friend constexpr auto operator&(const uint128_fallback &lhs, const uint128_fallback &rhs) -> uint128_fallback
Definition format.h:335
FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback &
Definition format.h:388
FMT_CONSTEXPR void operator&=(uint128_fallback n)
Definition format.h:383
constexpr auto low() const noexcept -> uint64_t
Definition format.h:311
Definition format.h:1256
FMT_API utf8_to_utf16(string_view s)
Definition format-inl.h:1411
auto size() const -> size_t
Definition format.h:1265
auto c_str() const -> const wchar_t *
Definition format.h:1266
auto str() const -> std::wstring
Definition format.h:1267
Definition base.h:2146
Definition format.h:3842
static FMT_API Locale::id id
Definition format.h:3853
auto put(appender out, loc_value val, const format_specs &specs) const -> bool
Definition format.h:3862
format_facet(string_view sep="", std::string grouping="\3", std::string decimal_point=".")
Definition format.h:3856
format_facet(Locale &loc)
Definition format-inl.h:148
virtual auto do_put(appender out, loc_value val, const format_specs &specs) const -> bool
A fast integer formatter.
Definition format.h:4115
FMT_CONSTEXPR20 format_int(long long value)
Definition format.h:4143
FMT_CONSTEXPR20 format_int(int value)
Definition format.h:4140
auto str() const -> std::string
Returns the content of the output buffer as an std::string.
Definition format.h:4169
FMT_CONSTEXPR20 format_int(unsigned long value)
Definition format.h:4147
FMT_CONSTEXPR20 auto data() const -> const char *
Returns a pointer to the output buffer content.
Definition format.h:4159
FMT_CONSTEXPR20 format_int(unsigned long long value)
Definition format.h:4149
FMT_CONSTEXPR20 auto size() const -> size_t
Returns the number of characters written to the output buffer.
Definition format.h:4153
FMT_CONSTEXPR20 format_int(long value)
Definition format.h:4141
FMT_CONSTEXPR20 format_int(unsigned value)
Definition format.h:4145
FMT_CONSTEXPR20 auto c_str() const -> const char *
Returns a pointer to the output buffer content with terminating null character appended.
Definition format.h:4163
Definition format.h:3782
generic_context(const generic_context &)=delete
void operator=(const generic_context &)=delete
constexpr auto locale() const -> detail::locale_ref
Definition format.h:3821
constexpr auto out() const -> iterator
Definition format.h:3815
generic_context(generic_context &&)=default
void advance_to(iterator it)
Definition format.h:3817
@ builtin_types
Definition format.h:3794
auto arg(basic_string_view< Char > name) const -> basic_format_arg< generic_context >
Definition format.h:3807
OutputIt iterator
Definition format.h:3790
constexpr auto arg_id(basic_string_view< Char > name) const -> int
Definition format.h:3811
constexpr auto arg(int id) const -> basic_format_arg< generic_context >
Definition format.h:3804
Char char_type
Definition format.h:3789
constexpr generic_context(OutputIt out, basic_format_args< generic_context > args, detail::locale_ref loc={})
Definition format.h:3796
Definition format.h:3824
loc_value(T)
Definition format.h:3833
loc_value(T value)
Definition format.h:3830
auto visit(Visitor &&vis) -> decltype(vis(0))
Definition format.h:3835
Parsing context consisting of a format string range being parsed and an argument counter for automati...
Definition base.h:866
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the beginning of the format string range being parsed.
Definition base.h:885
FMT_CONSTEXPR void check_arg_id(int id)
Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing.
Definition base.h:909
FMT_CONSTEXPR auto next_arg_id() -> int
Reports an error if using the manual argument indexing; otherwise returns the next argument index and...
Definition base.h:897
Definition format.h:908
std::string & str()
Definition format.h:917
string_buffer()
Definition format.h:914
Definition format.h:886
void print(format_string< T... > fmt, T &&... args)
Formats args according to specifications in fmt and writes the output to the file.
Definition format.h:900
writer(detail::buffer< char > &buf)
Definition format.h:896
writer(FILE *f)
Definition format.h:895
FMT_FUNC void report_error(const char *message)
Reports a format error at compile time or, via a format_error exception, at runtime.
Definition format-inl.h:135
FMT_API auto vsystem_error(int error_code, string_view fmt, format_args args) -> std::system_error
Definition format-inl.h:163
auto system_error(int error_code, format_string< T... > fmt, T &&... args) -> std::system_error
Constructs std::system_error with a message formatted with fmt::format(fmt, args.....
Definition format.h:4217
FMT_API void report_system_error(int error_code, const char *message) noexcept
Definition format-inl.h:1437
#define FMT_FORMAT_AS(Type, Base)
Definition format.h:3868
FMT_INLINE auto format_to(OutputIt out, const Locale &loc, format_string< T... > fmt, T &&... args) -> OutputIt
Definition format.h:4269
#define FMT_CONSTEXPR_STRING
Definition format.h:145
#define FMT_SO_VISIBILITY(value)
Definition format.h:112
FMT_API void format_system_error(detail::buffer< char > &out, int error_code, const char *message) noexcept
Formats an error message for an error returned by an operating system or a language runtime,...
Definition format-inl.h:1426
FMT_NODISCARD auto to_string(const basic_memory_buffer< char, SIZE > &buf) -> std::string
Definition format.h:878
auto vformat(const Locale &loc, string_view fmt, format_args args) -> std::string
Definition format.h:4243
auto vformat_to(OutputIt out, const Locale &loc, string_view fmt, format_args args) -> OutputIt
Definition format.h:4259
basic_memory_buffer< char > memory_buffer
Definition format.h:875
FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale &loc, format_string< T... > fmt, T &&... args) -> size_t
Definition format.h:4276
#define FMT_NOINLINE
Definition format.h:118
auto group_digits(T value) -> group_digits_view< T >
Returns a view that formats an integer value using ',' as a locale-independent thousands separator.
Definition format.h:4004
#define FMT_INLINE_VARIABLE
Definition format.h:94
constexpr auto underlying(Enum e) noexcept -> underlying_t< Enum >
Converts e to the underlying type.
Definition format.h:3939
#define FMT_THROW(x)
Definition format.h:178
auto ptr(T p) -> const void *
Converts p to const void* for pointer formatting.
Definition format.h:3925
FMT_INLINE auto format(const Locale &loc, format_string< T... > fmt, T &&... args) -> std::string
Definition format.h:4252
#define FMT_REDUCE_INT_INSTANTIATIONS
Definition format.h:188
#define FMT_POWERS_OF_10(factor)
Definition format.h:985
FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback
Definition format-inl.h:1139
auto floor_log10_pow2(int e) noexcept -> int
Definition format.h:1373
auto floor_log2_pow10(int e) noexcept -> int
Definition format.h:1379
FMT_API auto to_decimal(T x) noexcept -> decimal_fp< T >
Definition format-inl.h:1259
auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t
Definition format.h:1385
auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept -> uint128_fallback
Definition format.h:1398
detail namespace with internal helper functions
Definition input_adapters.h:32
conditional_t< num_bits< T >()<=32 &&!FMT_REDUCE_INT_INSTANTIATIONS, uint32_t, conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > > uint32_or_64_or_128_t
Definition format.h:978
FMT_CONSTEXPR auto display_width_of(uint32_t cp) noexcept -> size_t
Definition format.h:662
uint128_t uintptr_t
Definition format.h:419
FMT_CONSTEXPR auto code_point_length(const Char *begin) -> int
Definition base.h:1286
auto get_iterator(Buf &buf, OutputIt) -> decltype(buf.out())
Definition base.h:2109
constexpr auto digits10< int128_opt >() noexcept -> int
Definition format.h:1112
FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(OutputIt out, write_int_arg< T > arg, const format_specs &specs) -> OutputIt
Definition format.h:2083
FMT_CONSTEXPR20 auto isfinite(T value) -> bool
Definition format.h:2575
FMT_CONSTEXPR auto do_format_base2e(int base_bits, Char *out, UInt value, int size, bool upper=false) -> Char *
Definition format.h:1219
FMT_CONSTEXPR auto compare(const Char *s1, const Char *s2, size_t n) -> int
Definition base.h:470
conditional_t< long_short, int, long long > long_type
Definition base.h:1109
FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs &specs, size_t size, size_t width, F &&f) -> OutputIt
Definition format.h:1634
constexpr auto to_ascii(Char c) -> char
Definition base.h:1280
constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t
Definition format.h:3080
FMT_CONSTEXPR20 auto bit_cast(const From &from) -> To
Definition format.h:277
FMT_CONSTEXPR FMT_NOINLINE auto fill(OutputIt it, size_t n, const basic_specs &specs) -> OutputIt
Definition format.h:1619
FMT_CONSTEXPR auto operator*(fp x, fp y) -> fp
Definition format.h:1605
FMT_CONSTEXPR int get_dynamic_spec(arg_id_kind kind, const arg_ref< typename Context::char_type > &ref, Context &ctx)
Definition format.h:3632
FMT_CONSTEXPR void ignore_unused(const T &...)
Definition base.h:363
auto decimal_point(locale_ref loc) -> Char
Definition format.h:1134
FMT_INLINE void assume(bool condition)
Definition format.h:476
constexpr auto num_bits< uint128_fallback >() -> int
Definition format.h:433
constexpr auto use_fixed(int exp, int exp_upper) -> bool
Definition format.h:2425
bool_constant< is_integral< T >::value &&!std::is_same< T, bool >::value && !std::is_same< T, char >::value && !std::is_same< T, wchar_t >::value > is_integer
Definition format.h:694
void(*)(detail::buffer< char > &, int, const char *) format_func
Definition format.h:3733
constexpr auto has_implicit_bit() -> bool
Definition format.h:1459
constexpr auto num_bits() -> int
Definition format.h:427
uint128_opt
Definition base.h:416
FMT_CONSTEXPR void prefix_append(unsigned &prefix, unsigned value)
Definition format.h:1891
auto is_big_endian() -> bool
Definition format.h:287
FMT_CONSTEXPR auto write(OutputIt out, Char value, const format_specs &specs, locale_ref loc={}) -> OutputIt
Definition format.h:1815
FMT_CONSTEXPR auto count_digits_fallback(T n) -> int
Definition format.h:1009
conditional_t< FMT_USE_INT128, uint128_opt, uint128_fallback > uint128_t
Definition format.h:414
FMT_CONSTEXPR auto get_arg(Context &ctx, ID id) -> basic_format_arg< Context >
Definition format.h:3625
FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, const format_specs &specs={}) -> OutputIt
Definition format.h:1661
constexpr auto digits10() noexcept -> int
Definition format.h:1109
dragon
Definition format.h:2850
@ fixup
Definition format.h:2852
@ predecessor_closer
Definition format.h:2851
conditional_t< long_short, unsigned, unsigned long long > ulong_type
Definition base.h:1110
FMT_API void print(FILE *, string_view)
constexpr auto digits10< uint128_t >() noexcept -> int
Definition format.h:1113
FMT_CONSTEXPR20 void adjust_precision(int &precision, int exp10)
Definition format.h:2601
constexpr auto max_value() -> T
Definition format.h:424
typename std::enable_if< B, T >::type enable_if_t
Definition cpp_future.h:38
int128_opt
Definition base.h:415
FMT_CONSTEXPR auto make_write_int_arg(T value, sign s) -> write_int_arg< uint32_or_64_or_128_t< T > >
Definition format.h:1962
@ value
the parser finished reading a JSON value
FMT_CONSTEXPR auto to_unsigned(Int value) -> make_unsigned_t< Int >
Definition base.h:437
FMT_END_EXPORT auto equal2(const Char *lhs, const char *rhs) -> bool
Definition format.h:1153
constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point
Definition format.h:623
auto write_ptr(OutputIt out, UIntPtr value, const format_specs *specs) -> OutputIt
Definition format.h:1671
@ use_utf8
Definition base.h:457
auto write_int(OutputIt out, UInt value, unsigned prefix, const format_specs &specs, const digit_grouping< Char > &grouping) -> OutputIt
Definition format.h:1898
auto base_iterator(OutputIt it, typename OutputIt::container_type::value_type *) -> OutputIt
Definition format.h:535
FMT_API auto decimal_point_impl(locale_ref loc) -> Char
Definition format-inl.h:117
FMT_CONSTEXPR auto check_char_specs(const format_specs &specs) -> bool
Definition base.h:1649
constexpr auto to_pointer(OutputIt, size_t) -> T *
Definition format.h:519
auto write_loc(OutputIt, const loc_value &, const format_specs &, locale_ref) -> bool
Definition format.h:1951
to_utf8_error_policy
Definition format.h:1270
FMT_API void format_error_code(buffer< char > &out, int error_code, string_view message) noexcept
Definition format-inl.h:43
auto digits2(size_t value) -> const char *
Definition format.h:992
FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP &f, const format_specs &specs, sign s, int exp_upper, locale_ref loc) -> OutputIt
Definition format.h:2550
conditional_t< std::is_same< T, float >::value||doublish, double, T > convert_float_result
Definition format.h:1610
FMT_CONSTEXPR auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t
Definition format.h:1588
FMT_API auto is_printable(uint32_t cp) -> bool
Definition format-inl.h:1795
FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, buffer< char > &buf)
Definition format.h:2995
FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end, OutputIt out) -> OutputIt
Definition format.h:564
constexpr auto is_constant_evaluated(bool default_value=false) noexcept -> bool
Definition base.h:365
FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result< Char >
Definition format-inl.h:110
template FMT_API auto thousands_sep_impl< wchar_t >(locale_ref) -> thousands_sep_result< wchar_t >
@ error
throw a parse_error exception in case of a tag
auto write_escaped_char(OutputIt out, Char v) -> OutputIt
Definition format.h:1789
constexpr auto num_bits< int128_opt >() -> int
Definition format.h:431
auto thousands_sep(locale_ref loc) -> thousands_sep_result< Char >
Definition format.h:1123
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T &value) -> OutputIt
Definition format.h:549
FMT_ALWAYS_INLINE constexpr auto const_check(T val) -> T
Definition base.h:382
constexpr auto exponent_bias() -> int
Definition format.h:1480
constexpr auto num_significand_bits() -> int
Definition format.h:1466
FMT_CONSTEXPR auto parse_width(const Char *begin, const Char *end, format_specs &specs, arg_ref< Char > &width_ref, parse_context< Char > &ctx) -> const Char *
Definition base.h:1416
bool_constant< std::is_same< T, int >::value||FMT_BUILTIN_TYPES > is_builtin
Definition format.h:3560
FMT_API auto write_console(int fd, string_view text) -> bool
Definition format-inl.h:1696
FMT_CONSTEXPR20 auto copy(InputIt begin, InputIt end, OutputIt out) -> OutputIt
Definition base.h:2051
remove_reference_t< decltype(reserve(std::declval< OutputIt & >(), 0))> reserve_iterator
Definition format.h:515
FMT_CONSTEXPR auto write_exponent(int exp, OutputIt out) -> OutputIt
Definition format.h:1495
FMT_CONSTEXPR auto utf8_decode(const char *s, uint32_t *c, int *e) -> const char *
Definition format.h:586
FMT_CONSTEXPR void abort_fuzzing_if(bool condition)
Definition format.h:249
constexpr auto getsign(sign s) -> Char
Definition format.h:1004
std::integral_constant< bool, std::numeric_limits< T >::is_signed|| std::is_same< T, int128_opt >::value > is_signed
Definition format.h:689
FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, format_specs specs, sign s) -> OutputIt
Definition format.h:2294
typename make_void< Ts... >::type void_t
Definition void_t.h:21
constexpr auto write_significand(OutputIt out, const char *significand, int significand_size) -> OutputIt
Definition format.h:2328
auto write_escaped_cp(OutputIt out, const find_escape_result< Char > &escape) -> OutputIt
Definition format.h:1736
FMT_CONSTEXPR auto parse_align(const Char *begin, const Char *end, format_specs &specs) -> const Char *
Definition format.h:2258
constexpr auto get_significand_size(const big_decimal_fp &f) -> int
Definition format.h:2319
FMT_CONSTEXPR auto format_base2e(int base_bits, Char *out, UInt value, int num_digits, bool upper=false) -> Char *
Definition format.h:1233
FMT_CONSTEXPR auto write_char(OutputIt out, Char value, const format_specs &specs) -> OutputIt
Definition format.h:1805
FMT_CONSTEXPR auto compute_exp_size(int exp) -> int
Definition format.h:1486
auto needs_escape(uint32_t cp) -> bool
Definition format.h:1687
constexpr auto convert_float(T value) -> convert_float_result< T >
Definition format.h:1614
auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt
Definition format.h:1726
typename V::value_type char_t
String's character (code unit) type. detail:: is intentional to prevent ADL.
Definition base.h:956
constexpr auto to_string_view(const Char *s) -> basic_string_view< Char >
Definition base.h:931
FMT_CONSTEXPR void handle_dynamic_spec(arg_id_kind kind, int &value, const arg_ref< typename Context::char_type > &ref, Context &ctx)
Definition format.h:3646
std::integral_constant< bool, Value > bool_constant
Definition type_traits.h:743
conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > uint64_or_128_t
Definition format.h:983
state
Definition base.h:1440
FMT_CONSTEXPR void for_each_codepoint(string_view s, F f)
Definition format.h:628
FMT_CONSTEVAL auto exp_upper() -> int
Definition format.h:2417
FMT_CONSTEXPR20 auto reserve(OutputIt it, size_t n) -> typename OutputIt::value_type *
Definition format.h:494
FMT_EXPORT constexpr auto compile_string_to_view(const Char(&s)[N]) -> basic_string_view< Char >
Definition format.h:952
FMT_CONSTEXPR20 auto countl_zero_fallback(UInt n) -> int
Definition format.h:455
constexpr auto is_negative(T value) -> bool
Definition format.h:967
std::is_same< T, float128 > is_float128
Definition format.h:715
FMT_API void do_report_error(format_func func, int error_code, const char *message) noexcept
Definition format-inl.h:66
auto get_buffer(OutputIt out) -> iterator_buffer< OutputIt, T >
Definition base.h:2099
auto find_escape(const Char *begin, const Char *end) -> find_escape_result< Char >
Definition format.h:1700
FMT_CONSTEXPR20 auto format_float(Float value, int precision, const format_specs &specs, bool binary32, buffer< char > &buf) -> int
Definition format.h:3092
FMT_CONSTEXPR20 FMT_INLINE void write2digits(Char *out, size_t value)
Definition format.h:1162
constexpr auto num_bits< uint128_opt >() -> int
Definition format.h:432
constexpr auto count() -> int
Definition base.h:1054
FMT_CONSTEXPR20 auto do_format_decimal(Char *out, UInt value, int size) -> Char *
Definition format.h:1175
FMT_CONSTEXPR20 auto count_digits(uint64_t n) -> int
Definition format.h:1052
void vformat_to(buffer< Char > &buf, basic_string_view< Char > fmt, typename vformat_args< Char >::type args, locale_ref loc={})
Definition format.h:3769
FMT_BEGIN_EXPORT template FMT_API auto thousands_sep_impl< char >(locale_ref) -> thousands_sep_result< char >
conditional_t< sizeof(Char)==1, unsigned char, unsigned > unsigned_char
Definition base.h:443
constexpr auto exponent_mask() -> typename dragonbox::float_info< Float >::carrier_uint
Definition format.h:1474
FMT_CONSTEXPR FMT_INLINE auto format_decimal(Char *out, UInt value, int num_digits) -> Char *
Definition format.h:1197
FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP &f, const format_specs &specs, sign s, int exp_upper, locale_ref loc) -> OutputIt
Definition format.h:2511
FMT_CONSTEXPR20 auto countl_zero(uint32_t n) -> int
Definition format.h:462
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition string_escape.h:50
FMT_CONSTEXPR20 void format_dragon(basic_fp< uint128_t > value, unsigned flags, int num_digits, buffer< char > &buf, int &exp10)
Definition format.h:2859
auto write_escaped_string(OutputIt out, basic_string_view< Char > str) -> OutputIt
Definition format.h:1773
auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback
Definition format.h:1342
FMT_CONSTEXPR20 auto get_container(OutputIt it) -> typename OutputIt::container_type &
Definition base.h:498
FMT_CONSTEXPR20 auto write_fixed(OutputIt out, const DecimalFP &f, int significand_size, Char decimal_point, const format_specs &specs, sign s, locale_ref loc={}) -> OutputIt
Definition format.h:2445
FMT_CONSTEXPR auto normalize(basic_fp< F > value) -> basic_fp< F >
Definition format.h:1571
FMT_CONSTEXPR auto parse_format_specs(const Char *begin, const Char *end, dynamic_format_specs< Char > &specs, parse_context< Char > &ctx, type arg_type) -> const Char *
Definition base.h:1444
constexpr auto isnan(T value) -> bool
Definition format.h:2562
FMT_INLINE FMT_CONSTEXPR bool signbit(T value)
Definition format.h:2589
Definition format.h:3943
constexpr auto format_as(Enum e) noexcept -> underlying_t< Enum >
Definition format.h:3945
Definition json.h:5183
Definition PointerIntPair.h:280
b
Definition data.h:44
Definition format.h:3963
bytes(string_view s)
Definition format.h:3966
string_view data
Definition format.h:3964
Definition format.h:3590
const format_specs & specs
Definition format.h:3592
basic_appender< Char > out
Definition format.h:3591
void operator()(T)
Definition format.h:3601
FMT_CONSTEXPR FMT_INLINE void operator()(T value)
Definition format.h:3596
void operator()(typename basic_format_arg< buffered_context< Char > >::handle)
Definition format.h:3605
FMT_NO_UNIQUE_ADDRESS locale_ref locale
Definition format.h:3593
Definition format.h:1521
FMT_CONSTEXPR basic_fp(Float n)
Definition format.h:1532
constexpr basic_fp(uint64_t f_val, int e_val)
Definition format.h:1529
FMT_CONSTEXPR auto assign(Float n) -> bool
Definition format.h:1536
constexpr basic_fp()
Definition format.h:1528
int e
Definition format.h:1523
static constexpr int num_significand_bits
Definition format.h:1525
F f
Definition format.h:1522
Definition format.h:2313
const char * significand
Definition format.h:2314
int significand_size
Definition format.h:2315
int exponent
Definition format.h:2316
Definition format.h:3565
void operator()(monostate)
Definition format.h:3570
void operator()(T value)
Definition format.h:3573
void operator()(T)
Definition format.h:3578
void operator()(typename basic_format_arg< context >::handle h)
Definition format.h:3582
basic_appender< Char > out
Definition format.h:3568
Definition format.h:1449
int exponent
Definition format.h:1452
significand_type significand
Definition format.h:1451
typename float_info< T >::carrier_uint significand_type
Definition format.h:1450
uint64_t carrier_uint
Definition format.h:1423
uint32_t carrier_uint
Definition format.h:1411
Definition format.h:1408
Definition base.h:1273
Definition format.h:3611
FMT_CONSTEXPR auto operator()(T) -> unsigned long long
Definition format.h:3618
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long
Definition format.h:3613
Definition format.h:1693
const Char * end
Definition format.h:1695
const Char * begin
Definition format.h:1694
uint32_t cp
Definition format.h:1696
Definition format.h:942
Char data[N]
Definition format.h:947
FMT_CONSTEXPR20 fixed_string(const Char(&s)[N])
Definition format.h:943
Definition format.h:712
Definition base.h:2389
Definition format.h:3687
auto on_format_specs(int id, const Char *begin, const Char *end) -> const Char *
Definition format.h:3711
buffered_context< Char > ctx
Definition format.h:3689
FMT_CONSTEXPR auto on_arg_id() -> int
Definition format.h:3695
void on_text(const Char *begin, const Char *end)
Definition format.h:3691
FMT_NORETURN void on_error(const char *message)
Definition format.h:3730
FMT_CONSTEXPR auto on_arg_id(int id) -> int
Definition format.h:3696
FMT_INLINE void on_replacement_field(int id, const Char *)
Definition format.h:3707
FMT_CONSTEXPR auto on_arg_id(basic_string_view< Char > id) -> int
Definition format.h:3700
parse_context< Char > parse_ctx
Definition format.h:3688
Definition format.h:2567
Definition base.h:488
Definition format.h:717
Definition format.h:684
Definition format.h:3756
Definition base.h:2303
Definition format.h:1976
std::string grouping
Definition format.h:1980
auto operator()(T value) -> bool
Definition format.h:1984
auto operator()(T) -> bool
Definition format.h:1992
std::basic_string< Char > decimal_point
Definition format.h:1981
const format_specs & specs
Definition format.h:1978
std::basic_string< Char > sep
Definition format.h:1979
basic_appender< Char > out
Definition format.h:1977
Definition format-inl.h:92
Definition base.h:1046
Definition base.h:2399
Definition format.h:1998
FMT_CONSTEXPR size_padding(int num_digits, unsigned prefix, const format_specs &specs)
Definition format.h:2002
unsigned padding
Definition format.h:2000
unsigned size
Definition format.h:1999
Definition format.h:259
Definition format.h:264
static constexpr Char value[sizeof...(C)]
Definition format.h:265
Definition format.h:1115
Char thousands_sep
Definition format.h:1117
std::string grouping
Definition format.h:1116
Definition format.h:3678
const Char * str
Definition format.h:3679
auto operator=(T &&value) const -> named_arg< Char, T >
Definition format.h:3681
Definition format.h:3761
Definition format.h:1956
unsigned prefix
Definition format.h:1958
UInt abs_value
Definition format.h:1957
Definition base.h:855
int width
Definition base.h:856
int precision
Definition base.h:857
FMT_CONSTEXPR auto format(const T &value, FormatContext &ctx) const -> decltype(ctx.out())
Definition format.h:3911
auto format(bytes b, FormatContext &ctx) const -> decltype(ctx.out())
Definition format.h:3980
FMT_CONSTEXPR auto parse(parse_context<> &ctx) -> const char *
Definition format.h:3974
FMT_CONSTEXPR auto parse(parse_context<> &ctx) -> const char *
Definition format.h:4013
auto format(group_digits_view< T > view, FormatContext &ctx) const -> decltype(ctx.out())
Definition format.h:4019
auto format(nested_view< T, Char > view, FormatContext &ctx) const -> decltype(ctx.out())
Definition format.h:4044
FMT_CONSTEXPR auto parse(parse_context< Char > &ctx) -> const Char *
Definition format.h:4040
Definition base.h:664
Definition format.h:3991
T value
Definition format.h:3992
Definition base.h:635
Definition base.h:339
Definition format.h:4050
constexpr nested_formatter()
Definition format.h:4057
auto write_padded(FormatContext &ctx, F write) const -> decltype(ctx.out())
Definition format.h:4076
FMT_CONSTEXPR auto parse(parse_context< Char > &ctx) -> const Char *
Definition format.h:4059
auto nested(const T &value) const -> nested_view< T, Char >
Definition format.h:4088
Definition format.h:4033
const T * value
Definition format.h:4035
const formatter< T, Char > * fmt
Definition format.h:4034
output_iterator_tag iterator_category
Definition format.h:151
decltype(static_cast< int * >(nullptr) - static_cast< int * >(nullptr)) difference_type
Definition format.h:153
Definition base.h:1262
int index
Definition base.h:1266
basic_string_view< Char > name
Definition base.h:1267
#define S(label, offset, message)
Definition Errors.h:113
#define FMT_ASSERT(condition, message)
Definition base.h:396
#define FMT_END_EXPORT
Definition base.h:272
#define FMT_BUILTIN_TYPES
Definition base.h:301
#define FMT_PRAGMA_CLANG(x)
Definition base.h:230
#define FMT_CONSTEVAL
Definition base.h:140
basic_string_view< char > string_view
Definition base.h:616
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Returns a named argument to be used in a formatting function.
Definition base.h:2844
constexpr auto min_of(T a, T b) -> T
Definition base.h:352
#define FMT_FALLTHROUGH
Definition base.h:186
#define FMT_NODISCARD
Definition base.h:201
typename std::remove_reference< T >::type remove_reference_t
Definition base.h:317
typename fstring< T... >::t format_string
Definition base.h:2789
#define FMT_GCC_VERSION
Definition base.h:35
#define FMT_OPTIMIZE_SIZE
Definition base.h:295
basic_appender< char > appender
Definition base.h:632
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
Definition base.h:321
constexpr auto max_of(T a, T b) -> T
Definition base.h:355
#define FMT_CONSTEXPR
Definition base.h:113
align
Definition base.h:697
arg_id_kind
Definition base.h:699
#define FMT_BEGIN_NAMESPACE
Definition base.h:261
sign
Definition base.h:698
conditional_t< std::is_same< OutputIt, appender >::value, context, generic_context< OutputIt, Char > > basic_format_context
Definition base.h:645
#define FMT_API
Definition base.h:291
#define FMT_ENABLE_IF(...)
Definition base.h:349
#define FMT_BEGIN_EXPORT
Definition base.h:271
void void_t
Definition base.h:336
#define FMT_INLINE
Definition base.h:255
#define FMT_NO_UNIQUE_ADDRESS
Definition base.h:175
basic_format_args< context > format_args
Definition base.h:660
#define FMT_NORETURN
Definition base.h:193
#define FMT_MSC_WARNING(...)
Definition base.h:235
typename std::conditional< B, T, F >::type conditional_t
Definition base.h:314
#define FMT_CONSTEXPR20
Definition base.h:141
typename std::underlying_type< T >::type underlying_t
Definition base.h:325
#define FMT_END_NAMESPACE
Definition base.h:264
conditional_t< std::is_same< Char, char >::value, context, generic_context< basic_appender< Char >, Char > > buffered_context
Definition base.h:651
#define FMT_EXPORT
Definition base.h:270