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