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