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