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