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