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