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