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