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