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