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