2 Formatting library for C++
4 Copyright (c) 2012 - present, Victor Zverovich
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:
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
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.
25 --- Optional exception to the license ---
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.
36 #include <cmath> // std::signbit
37 #include <cstdint> // uint32_t
38 #include <cstring> // std::memcpy
39 #include <initializer_list> // std::initializer_list
40 #include <limits> // std::numeric_limits
41 #include <memory> // std::uninitialized_copy
42 #include <stdexcept> // std::runtime_error
43 #include <system_error> // std::system_error
45 #ifdef __cpp_lib_bit_cast
46 # include <bit> // std::bit_cast
51 #if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
52 # define FMT_INLINE_VARIABLE inline
54 # define FMT_INLINE_VARIABLE
57 #if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
58 # define FMT_FALLTHROUGH [[fallthrough]]
59 #elif defined(__clang__)
60 # define FMT_FALLTHROUGH [[clang::fallthrough]]
61 #elif FMT_GCC_VERSION >= 700 && \
62 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
63 # define FMT_FALLTHROUGH [[gnu::fallthrough]]
65 # define FMT_FALLTHROUGH
68 #ifndef FMT_DEPRECATED
69 # if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900
70 # define FMT_DEPRECATED [[deprecated]]
72 # if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
73 # define FMT_DEPRECATED __attribute__((deprecated))
74 # elif FMT_MSC_VERSION
75 # define FMT_DEPRECATED __declspec(deprecated)
77 # define FMT_DEPRECATED /* deprecated */
82 #ifndef FMT_NO_UNIQUE_ADDRESS
83 # if FMT_CPLUSPLUS >= 202002L
84 # if FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
85 # define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
86 // VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485)
87 # elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION
88 # define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
92 #ifndef FMT_NO_UNIQUE_ADDRESS
93 # define FMT_NO_UNIQUE_ADDRESS
96 // Visibility when compiled as a shared library/object.
97 #if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
98 # define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value)
100 # define FMT_SO_VISIBILITY(value)
104 # define FMT_HAS_BUILTIN(x) __has_builtin(x)
106 # define FMT_HAS_BUILTIN(x) 0
109 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
110 # define FMT_NOINLINE __attribute__((noinline))
112 # define FMT_NOINLINE
117 # if FMT_MSC_VERSION || defined(__NVCC__)
120 template <typename Exception
> inline void do_throw(const Exception
& x
) {
121 // Silence unreachable code warnings in MSVC and NVCC because these
122 // are nearly impossible to fix in a generic code.
123 volatile bool b
= true;
126 } // namespace detail
128 # define FMT_THROW(x) detail::do_throw(x)
130 # define FMT_THROW(x) throw x
133 # define FMT_THROW(x) \
134 ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
140 # define FMT_CATCH(x) catch (x)
142 # define FMT_TRY if (true)
143 # define FMT_CATCH(x) if (false)
146 #ifndef FMT_MAYBE_UNUSED
147 # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
148 # define FMT_MAYBE_UNUSED [[maybe_unused]]
150 # define FMT_MAYBE_UNUSED
154 #ifndef FMT_USE_USER_DEFINED_LITERALS
155 // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
157 // GCC before 4.9 requires a space in `operator"" _a` which is invalid in later
158 // compiler versions.
159 # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \
160 FMT_MSC_VERSION >= 1900) && \
161 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
162 # define FMT_USE_USER_DEFINED_LITERALS 1
164 # define FMT_USE_USER_DEFINED_LITERALS 0
168 // Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
169 // integer formatter template instantiations to just one by only using the
170 // largest integer type. This results in a reduction in binary size but will
171 // cause a decrease in integer formatting performance.
172 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
173 # define FMT_REDUCE_INT_INSTANTIATIONS 0
176 // __builtin_clz is broken in clang with Microsoft CodeGen:
177 // https://github.com/fmtlib/fmt/issues/519.
179 # if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
180 # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
182 # if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
183 # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
187 // __builtin_ctz is broken in Intel Compiler Classic on Windows:
188 // https://github.com/fmtlib/fmt/issues/2510.
190 # if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
191 defined(__NVCOMPILER)
192 # define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
194 # if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
195 FMT_ICC_VERSION || defined(__NVCOMPILER)
196 # define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
201 # include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
204 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
205 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
206 // MSVC intrinsics if the clz and clzll builtins are not available.
207 #if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
208 !defined(FMT_BUILTIN_CTZLL)
211 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
212 # if !defined(__clang__)
213 # pragma intrinsic(_BitScanForward)
214 # pragma intrinsic(_BitScanReverse)
216 # pragma intrinsic(_BitScanForward64)
217 # pragma intrinsic(_BitScanReverse64)
221 inline auto clz(uint32_t x
) -> int {
223 _BitScanReverse(&r
, x
);
224 FMT_ASSERT(x
!= 0, "");
225 // Static analysis complains about using uninitialized data
226 // "r", but the only way that can happen is if "x" is 0,
227 // which the callers guarantee to not happen.
228 FMT_MSC_WARNING(suppress
: 6102)
229 return 31 ^ static_cast<int>(r
);
231 # define FMT_BUILTIN_CLZ(n) detail::clz(n)
233 inline auto clzll(uint64_t x
) -> int {
236 _BitScanReverse64(&r
, x
);
238 // Scan the high 32 bits.
239 if (_BitScanReverse(&r
, static_cast<uint32_t>(x
>> 32)))
240 return 63 ^ static_cast<int>(r
+ 32);
241 // Scan the low 32 bits.
242 _BitScanReverse(&r
, static_cast<uint32_t>(x
));
244 FMT_ASSERT(x
!= 0, "");
245 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
246 return 63 ^ static_cast<int>(r
);
248 # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
250 inline auto ctz(uint32_t x
) -> int {
252 _BitScanForward(&r
, x
);
253 FMT_ASSERT(x
!= 0, "");
254 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
255 return static_cast<int>(r
);
257 # define FMT_BUILTIN_CTZ(n) detail::ctz(n)
259 inline auto ctzll(uint64_t x
) -> int {
261 FMT_ASSERT(x
!= 0, "");
262 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
264 _BitScanForward64(&r
, x
);
266 // Scan the low 32 bits.
267 if (_BitScanForward(&r
, static_cast<uint32_t>(x
))) return static_cast<int>(r
);
268 // Scan the high 32 bits.
269 _BitScanForward(&r
, static_cast<uint32_t>(x
>> 32));
272 return static_cast<int>(r
);
274 # define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
275 } // namespace detail
282 FMT_CONSTEXPR
inline void abort_fuzzing_if(bool condition
) {
283 ignore_unused(condition
);
285 if (condition
) throw std::runtime_error("fuzzing limit reached");
289 template <typename CharT
, CharT
... C
> struct string_literal
{
290 static constexpr CharT value
[sizeof...(C
)] = {C
...};
291 constexpr operator basic_string_view
<CharT
>() const {
292 return {value
, sizeof...(C
)};
296 #if FMT_CPLUSPLUS < 201703L
297 template <typename CharT
, CharT
... C
>
298 constexpr CharT string_literal
<CharT
, C
...>::value
[sizeof...(C
)];
301 // Implementation of std::bit_cast for pre-C++20.
302 template <typename To
, typename From
, FMT_ENABLE_IF(sizeof(To
) == sizeof(From
))>
303 FMT_CONSTEXPR20
auto bit_cast(const From
& from
) -> To
{
304 #ifdef __cpp_lib_bit_cast
305 if (is_constant_evaluated()) return std::bit_cast
<To
>(from
);
308 // The cast suppresses a bogus -Wclass-memaccess on GCC.
309 std::memcpy(static_cast<void*>(&to
), &from
, sizeof(to
));
313 inline auto is_big_endian() -> bool {
316 #elif defined(__BIG_ENDIAN__)
318 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
319 return __BYTE_ORDER__
== __ORDER_BIG_ENDIAN__
;
322 char data
[sizeof(int)];
324 return bit_cast
<bytes
>(1).data
[0] == 0;
328 class uint128_fallback
{
333 constexpr uint128_fallback(uint64_t hi
, uint64_t lo
) : lo_(lo
), hi_(hi
) {}
334 constexpr uint128_fallback(uint64_t value
= 0) : lo_(value
), hi_(0) {}
336 constexpr auto high() const noexcept
-> uint64_t { return hi_
; }
337 constexpr auto low() const noexcept
-> uint64_t { return lo_
; }
339 template <typename T
, FMT_ENABLE_IF(std::is_integral
<T
>::value
)>
340 constexpr explicit operator T() const {
341 return static_cast<T
>(lo_
);
344 friend constexpr auto operator==(const uint128_fallback
& lhs
,
345 const uint128_fallback
& rhs
) -> bool {
346 return lhs
.hi_
== rhs
.hi_
&& lhs
.lo_
== rhs
.lo_
;
348 friend constexpr auto operator!=(const uint128_fallback
& lhs
,
349 const uint128_fallback
& rhs
) -> bool {
350 return !(lhs
== rhs
);
352 friend constexpr auto operator>(const uint128_fallback
& lhs
,
353 const uint128_fallback
& rhs
) -> bool {
354 return lhs
.hi_
!= rhs
.hi_
? lhs
.hi_
> rhs
.hi_
: lhs
.lo_
> rhs
.lo_
;
356 friend constexpr auto operator|(const uint128_fallback
& lhs
,
357 const uint128_fallback
& rhs
)
358 -> uint128_fallback
{
359 return {lhs
.hi_
| rhs
.hi_
, lhs
.lo_
| rhs
.lo_
};
361 friend constexpr auto operator&(const uint128_fallback
& lhs
,
362 const uint128_fallback
& rhs
)
363 -> uint128_fallback
{
364 return {lhs
.hi_
& rhs
.hi_
, lhs
.lo_
& rhs
.lo_
};
366 friend constexpr auto operator~(const uint128_fallback
& n
)
367 -> uint128_fallback
{
368 return {~n
.hi_
, ~n
.lo_
};
370 friend auto operator+(const uint128_fallback
& lhs
,
371 const uint128_fallback
& rhs
) -> uint128_fallback
{
372 auto result
= uint128_fallback(lhs
);
376 friend auto operator*(const uint128_fallback
& lhs
, uint32_t rhs
)
377 -> uint128_fallback
{
378 FMT_ASSERT(lhs
.hi_
== 0, "");
379 uint64_t hi
= (lhs
.lo_
>> 32) * rhs
;
380 uint64_t lo
= (lhs
.lo_
& ~uint32_t()) * rhs
;
381 uint64_t new_lo
= (hi
<< 32) + lo
;
382 return {(hi
>> 32) + (new_lo
< lo
? 1 : 0), new_lo
};
384 friend auto operator-(const uint128_fallback
& lhs
, uint64_t rhs
)
385 -> uint128_fallback
{
386 return {lhs
.hi_
- (lhs
.lo_
< rhs
? 1 : 0), lhs
.lo_
- rhs
};
388 FMT_CONSTEXPR
auto operator>>(int shift
) const -> uint128_fallback
{
389 if (shift
== 64) return {0, hi_
};
390 if (shift
> 64) return uint128_fallback(0, hi_
) >> (shift
- 64);
391 return {hi_
>> shift
, (hi_
<< (64 - shift
)) | (lo_
>> shift
)};
393 FMT_CONSTEXPR
auto operator<<(int shift
) const -> uint128_fallback
{
394 if (shift
== 64) return {lo_
, 0};
395 if (shift
> 64) return uint128_fallback(lo_
, 0) << (shift
- 64);
396 return {hi_
<< shift
| (lo_
>> (64 - shift
)), (lo_
<< shift
)};
398 FMT_CONSTEXPR
auto operator>>=(int shift
) -> uint128_fallback
& {
399 return *this = *this >> shift
;
401 FMT_CONSTEXPR
void operator+=(uint128_fallback n
) {
402 uint64_t new_lo
= lo_
+ n
.lo_
;
403 uint64_t new_hi
= hi_
+ n
.hi_
+ (new_lo
< lo_
? 1 : 0);
404 FMT_ASSERT(new_hi
>= hi_
, "");
408 FMT_CONSTEXPR
void operator&=(uint128_fallback n
) {
413 FMT_CONSTEXPR20
auto operator+=(uint64_t n
) noexcept
-> uint128_fallback
& {
414 if (is_constant_evaluated()) {
416 hi_
+= (lo_
< n
? 1 : 0);
419 #if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
420 unsigned long long carry
;
421 lo_
= __builtin_addcll(lo_
, n
, 0, &carry
);
423 #elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
424 unsigned long long result
;
425 auto carry
= __builtin_ia32_addcarryx_u64(0, lo_
, n
, &result
);
428 #elif defined(_MSC_VER) && defined(_M_X64)
429 auto carry
= _addcarry_u64(0, lo_
, n
, &lo_
);
430 _addcarry_u64(carry
, hi_
, 0, &hi_
);
433 hi_
+= (lo_
< n
? 1 : 0);
439 using uint128_t
= conditional_t
<FMT_USE_INT128
, uint128_opt
, uint128_fallback
>;
442 using uintptr_t = ::uintptr_t;
444 using uintptr_t = uint128_t
;
447 // Returns the largest possible value for type T. Same as
448 // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
449 template <typename T
> constexpr auto max_value() -> T
{
450 return (std::numeric_limits
<T
>::max
)();
452 template <typename T
> constexpr auto num_bits() -> int {
453 return std::numeric_limits
<T
>::digits
;
455 // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
456 template <> constexpr auto num_bits
<int128_opt
>() -> int { return 128; }
457 template <> constexpr auto num_bits
<uint128_t
>() -> int { return 128; }
459 // A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
460 // and 128-bit pointers to uint128_fallback.
461 template <typename To
, typename From
, FMT_ENABLE_IF(sizeof(To
) > sizeof(From
))>
462 inline auto bit_cast(const From
& from
) -> To
{
463 constexpr auto size
= static_cast<int>(sizeof(From
) / sizeof(unsigned));
465 unsigned value
[static_cast<unsigned>(size
)];
466 } data
= bit_cast
<data_t
>(from
);
468 if (const_check(is_big_endian())) {
469 for (int i
= 0; i
< size
; ++i
)
470 result
= (result
<< num_bits
<unsigned>()) | data
.value
[i
];
472 for (int i
= size
- 1; i
>= 0; --i
)
473 result
= (result
<< num_bits
<unsigned>()) | data
.value
[i
];
478 template <typename UInt
>
479 FMT_CONSTEXPR20
inline auto countl_zero_fallback(UInt n
) -> int {
481 constexpr UInt msb_mask
= static_cast<UInt
>(1) << (num_bits
<UInt
>() - 1);
482 for (; (n
& msb_mask
) == 0; n
<<= 1) lz
++;
486 FMT_CONSTEXPR20
inline auto countl_zero(uint32_t n
) -> int {
487 #ifdef FMT_BUILTIN_CLZ
488 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n
);
490 return countl_zero_fallback(n
);
493 FMT_CONSTEXPR20
inline auto countl_zero(uint64_t n
) -> int {
494 #ifdef FMT_BUILTIN_CLZLL
495 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n
);
497 return countl_zero_fallback(n
);
500 FMT_INLINE
void assume(bool condition
) {
502 #if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
503 __builtin_assume(condition
);
504 #elif FMT_GCC_VERSION
505 if (!condition
) __builtin_unreachable();
509 // An approximation of iterator_t for pre-C++20 systems.
510 template <typename T
>
511 using iterator_t
= decltype(std::begin(std::declval
<T
&>()));
512 template <typename T
> using sentinel_t
= decltype(std::end(std::declval
<T
&>()));
514 // A workaround for std::string not having mutable data() until C++17.
515 template <typename Char
>
516 inline auto get_data(std::basic_string
<Char
>& s
) -> Char
* {
519 template <typename Container
>
520 inline auto get_data(Container
& c
) -> typename
Container::value_type
* {
524 // Attempts to reserve space for n extra characters in the output range.
525 // Returns a pointer to the reserved range or a reference to it.
526 template <typename Container
, FMT_ENABLE_IF(is_contiguous
<Container
>::value
)>
527 #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
528 __attribute__((no_sanitize("undefined")))
531 reserve(std::back_insert_iterator
<Container
> it
, size_t n
) ->
532 typename
Container::value_type
* {
533 Container
& c
= get_container(it
);
534 size_t size
= c
.size();
536 return get_data(c
) + size
;
539 template <typename T
>
540 inline auto reserve(buffer_appender
<T
> it
, size_t n
) -> buffer_appender
<T
> {
541 buffer
<T
>& buf
= get_container(it
);
542 buf
.try_reserve(buf
.size() + n
);
546 template <typename Iterator
>
547 constexpr auto reserve(Iterator
& it
, size_t) -> Iterator
& {
551 template <typename OutputIt
>
552 using reserve_iterator
=
553 remove_reference_t
<decltype(reserve(std::declval
<OutputIt
&>(), 0))>;
555 template <typename T
, typename OutputIt
>
556 constexpr auto to_pointer(OutputIt
, size_t) -> T
* {
559 template <typename T
> auto to_pointer(buffer_appender
<T
> it
, size_t n
) -> T
* {
560 buffer
<T
>& buf
= get_container(it
);
561 auto size
= buf
.size();
562 if (buf
.capacity() < size
+ n
) return nullptr;
563 buf
.try_resize(size
+ n
);
564 return buf
.data() + size
;
567 template <typename Container
, FMT_ENABLE_IF(is_contiguous
<Container
>::value
)>
568 inline auto base_iterator(std::back_insert_iterator
<Container
> it
,
569 typename
Container::value_type
*)
570 -> std::back_insert_iterator
<Container
> {
574 template <typename Iterator
>
575 constexpr auto base_iterator(Iterator
, Iterator it
) -> Iterator
{
579 // <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
581 template <typename OutputIt
, typename Size
, typename T
>
582 FMT_CONSTEXPR
auto fill_n(OutputIt out
, Size count
, const T
& value
)
584 for (Size i
= 0; i
< count
; ++i
) *out
++ = value
;
587 template <typename T
, typename Size
>
588 FMT_CONSTEXPR20
auto fill_n(T
* out
, Size count
, char value
) -> T
* {
589 if (is_constant_evaluated()) {
590 return fill_n
<T
*, Size
, T
>(out
, count
, value
);
592 std::memset(out
, value
, to_unsigned(count
));
597 using char8_type
= char8_t
;
599 enum char8_type
: unsigned char {};
602 template <typename OutChar
, typename InputIt
, typename OutputIt
>
603 FMT_CONSTEXPR FMT_NOINLINE
auto copy_str_noinline(InputIt begin
, InputIt end
,
604 OutputIt out
) -> OutputIt
{
605 return copy_str
<OutChar
>(begin
, end
, out
);
608 // A public domain branchless UTF-8 decoder by Christopher Wellons:
609 // https://github.com/skeeto/branchless-utf8
610 /* Decode the next character, c, from s, reporting errors in e.
612 * Since this is a branchless decoder, four bytes will be read from the
613 * buffer regardless of the actual length of the next character. This
614 * means the buffer _must_ have at least three bytes of zero padding
615 * following the end of the data stream.
617 * Errors are reported in e, which will be non-zero if the parsed
618 * character was somehow invalid: invalid byte sequence, non-canonical
619 * encoding, or a surrogate half.
621 * The function returns a pointer to the next character. When an error
622 * occurs, this pointer will be a guess that depends on the particular
623 * error, but it will always advance at least one byte.
625 FMT_CONSTEXPR
inline auto utf8_decode(const char* s
, uint32_t* c
, int* e
)
627 constexpr const int masks
[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
628 constexpr const uint32_t mins
[] = {4194304, 0, 128, 2048, 65536};
629 constexpr const int shiftc
[] = {0, 18, 12, 6, 0};
630 constexpr const int shifte
[] = {0, 6, 4, 2, 0};
632 int len
= "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"
633 [static_cast<unsigned char>(*s
) >> 3];
634 // Compute the pointer to the next character early so that the next
635 // iteration can start working on the next character. Neither Clang
636 // nor GCC figure out this reordering on their own.
637 const char* next
= s
+ len
+ !len
;
639 using uchar
= unsigned char;
641 // Assume a four-byte character and load four bytes. Unused bits are
643 *c
= uint32_t(uchar(s
[0]) & masks
[len
]) << 18;
644 *c
|= uint32_t(uchar(s
[1]) & 0x3f) << 12;
645 *c
|= uint32_t(uchar(s
[2]) & 0x3f) << 6;
646 *c
|= uint32_t(uchar(s
[3]) & 0x3f) << 0;
649 // Accumulate the various error conditions.
650 *e
= (*c
< mins
[len
]) << 6; // non-canonical encoding
651 *e
|= ((*c
>> 11) == 0x1b) << 7; // surrogate half?
652 *e
|= (*c
> 0x10FFFF) << 8; // out of range?
653 *e
|= (uchar(s
[1]) & 0xc0) >> 2;
654 *e
|= (uchar(s
[2]) & 0xc0) >> 4;
655 *e
|= uchar(s
[3]) >> 6;
656 *e
^= 0x2a; // top two bits of each tail byte correct?
662 constexpr FMT_INLINE_VARIABLE
uint32_t invalid_code_point
= ~uint32_t();
664 // Invokes f(cp, sv) for every code point cp in s with sv being the string view
665 // corresponding to the code point. cp is invalid_code_point on error.
666 template <typename F
>
667 FMT_CONSTEXPR
void for_each_codepoint(string_view s
, F f
) {
668 auto decode
= [f
](const char* buf_ptr
, const char* ptr
) {
669 auto cp
= uint32_t();
671 auto end
= utf8_decode(buf_ptr
, &cp
, &error
);
672 bool result
= f(error
? invalid_code_point
: cp
,
673 string_view(ptr
, error
? 1 : to_unsigned(end
- buf_ptr
)));
674 return result
? (error
? buf_ptr
+ 1 : end
) : nullptr;
677 const size_t block_size
= 4; // utf8_decode always reads blocks of 4 chars.
678 if (s
.size() >= block_size
) {
679 for (auto end
= p
+ s
.size() - block_size
+ 1; p
< end
;) {
684 if (auto num_chars_left
= s
.data() + s
.size() - p
) {
685 char buf
[2 * block_size
- 1] = {};
686 copy_str
<char>(p
, p
+ num_chars_left
, buf
);
687 const char* buf_ptr
= buf
;
689 auto end
= decode(buf_ptr
, p
);
693 } while (buf_ptr
- buf
< num_chars_left
);
697 template <typename Char
>
698 inline auto compute_width(basic_string_view
<Char
> s
) -> size_t {
702 // Computes approximate display width of a UTF-8 string.
703 FMT_CONSTEXPR
inline auto compute_width(string_view s
) -> size_t {
704 size_t num_code_points
= 0;
705 // It is not a lambda for compatibility with C++14.
706 struct count_code_points
{
708 FMT_CONSTEXPR
auto operator()(uint32_t cp
, string_view
) const -> bool {
709 *count
+= detail::to_unsigned(
712 (cp
<= 0x115f || // Hangul Jamo init. consonants
713 cp
== 0x2329 || // LEFT-POINTING ANGLE BRACKET
714 cp
== 0x232a || // RIGHT-POINTING ANGLE BRACKET
715 // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
716 (cp
>= 0x2e80 && cp
<= 0xa4cf && cp
!= 0x303f) ||
717 (cp
>= 0xac00 && cp
<= 0xd7a3) || // Hangul Syllables
718 (cp
>= 0xf900 && cp
<= 0xfaff) || // CJK Compatibility Ideographs
719 (cp
>= 0xfe10 && cp
<= 0xfe19) || // Vertical Forms
720 (cp
>= 0xfe30 && cp
<= 0xfe6f) || // CJK Compatibility Forms
721 (cp
>= 0xff00 && cp
<= 0xff60) || // Fullwidth Forms
722 (cp
>= 0xffe0 && cp
<= 0xffe6) || // Fullwidth Forms
723 (cp
>= 0x20000 && cp
<= 0x2fffd) || // CJK
724 (cp
>= 0x30000 && cp
<= 0x3fffd) ||
725 // Miscellaneous Symbols and Pictographs + Emoticons:
726 (cp
>= 0x1f300 && cp
<= 0x1f64f) ||
727 // Supplemental Symbols and Pictographs:
728 (cp
>= 0x1f900 && cp
<= 0x1f9ff))));
732 // We could avoid branches by using utf8_decode directly.
733 for_each_codepoint(s
, count_code_points
{&num_code_points
});
734 return num_code_points
;
737 inline auto compute_width(basic_string_view
<char8_type
> s
) -> size_t {
738 return compute_width(
739 string_view(reinterpret_cast<const char*>(s
.data()), s
.size()));
742 template <typename Char
>
743 inline auto code_point_index(basic_string_view
<Char
> s
, size_t n
) -> size_t {
744 size_t size
= s
.size();
745 return n
< size
? n
: size
;
748 // Calculates the index of the nth code point in a UTF-8 string.
749 inline auto code_point_index(string_view s
, size_t n
) -> size_t {
750 size_t result
= s
.size();
751 const char* begin
= s
.begin();
752 for_each_codepoint(s
, [begin
, &n
, &result
](uint32_t, string_view sv
) {
757 result
= to_unsigned(sv
.begin() - begin
);
763 inline auto code_point_index(basic_string_view
<char8_type
> s
, size_t n
)
765 return code_point_index(
766 string_view(reinterpret_cast<const char*>(s
.data()), s
.size()), n
);
769 template <typename T
> struct is_integral
: std::is_integral
<T
> {};
770 template <> struct is_integral
<int128_opt
> : std::true_type
{};
771 template <> struct is_integral
<uint128_t
> : std::true_type
{};
773 template <typename T
>
775 std::integral_constant
<bool, std::numeric_limits
<T
>::is_signed
||
776 std::is_same
<T
, int128_opt
>::value
>;
778 template <typename T
>
780 bool_constant
<is_integral
<T
>::value
&& !std::is_same
<T
, bool>::value
&&
781 !std::is_same
<T
, char>::value
&&
782 !std::is_same
<T
, wchar_t>::value
>;
784 #ifndef FMT_USE_FLOAT
785 # define FMT_USE_FLOAT 1
787 #ifndef FMT_USE_DOUBLE
788 # define FMT_USE_DOUBLE 1
790 #ifndef FMT_USE_LONG_DOUBLE
791 # define FMT_USE_LONG_DOUBLE 1
794 #ifndef FMT_USE_FLOAT128
796 // Clang emulates GCC, so it has to appear early.
797 # if FMT_HAS_INCLUDE(<quadmath.h>)
798 # define FMT_USE_FLOAT128 1
800 # elif defined(__GNUC__)
802 # if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
803 # define FMT_USE_FLOAT128 1
806 # ifndef FMT_USE_FLOAT128
807 # define FMT_USE_FLOAT128 0
812 using float128
= __float128
;
814 using float128
= void;
816 template <typename T
> using is_float128
= std::is_same
<T
, float128
>;
818 template <typename T
>
819 using is_floating_point
=
820 bool_constant
<std::is_floating_point
<T
>::value
|| is_float128
<T
>::value
>;
822 template <typename T
, bool = std::is_floating_point
<T
>::value
>
823 struct is_fast_float
: bool_constant
<std::numeric_limits
<T
>::is_iec559
&&
824 sizeof(T
) <= sizeof(double)> {};
825 template <typename T
> struct is_fast_float
<T
, false> : std::false_type
{};
827 template <typename T
>
828 using is_double_double
= bool_constant
<std::numeric_limits
<T
>::digits
== 106>;
830 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
831 # define FMT_USE_FULL_CACHE_DRAGONBOX 0
834 template <typename T
>
835 template <typename U
>
836 void buffer
<T
>::append(const U
* begin
, const U
* end
) {
837 while (begin
!= end
) {
838 auto count
= to_unsigned(end
- begin
);
839 try_reserve(size_
+ count
);
840 auto free_cap
= capacity_
- size_
;
841 if (free_cap
< count
) count
= free_cap
;
842 std::uninitialized_copy_n(begin
, count
, ptr_
+ size_
);
848 template <typename T
, typename Enable
= void>
849 struct is_locale
: std::false_type
{};
850 template <typename T
>
851 struct is_locale
<T
, void_t
<decltype(T::classic())>> : std::true_type
{};
852 } // namespace detail
856 // The number of characters to store in the basic_memory_buffer object itself
857 // to avoid dynamic memory allocation.
858 enum { inline_buffer_size
= 500 };
862 A dynamically growing memory buffer for trivially copyable/constructible types
863 with the first ``SIZE`` elements stored in the object itself.
865 You can use the ``memory_buffer`` type alias for ``char`` instead.
869 auto out = fmt::memory_buffer();
870 fmt::format_to(std::back_inserter(out), "The answer is {}.", 42);
872 This will append the following output to the ``out`` object:
878 The output can be converted to an ``std::string`` with ``to_string(out)``.
881 template <typename T
, size_t SIZE
= inline_buffer_size
,
882 typename Allocator
= std::allocator
<T
>>
883 class basic_memory_buffer final
: public detail::buffer
<T
> {
887 // Don't inherit from Allocator to avoid generating type_info for it.
888 FMT_NO_UNIQUE_ADDRESS Allocator alloc_
;
890 // Deallocate memory allocated by the buffer.
891 FMT_CONSTEXPR20
void deallocate() {
892 T
* data
= this->data();
893 if (data
!= store_
) alloc_
.deallocate(data
, this->capacity());
897 FMT_CONSTEXPR20
void grow(size_t size
) override
{
898 detail::abort_fuzzing_if(size
> 5000);
899 const size_t max_size
= std::allocator_traits
<Allocator
>::max_size(alloc_
);
900 size_t old_capacity
= this->capacity();
901 size_t new_capacity
= old_capacity
+ old_capacity
/ 2;
902 if (size
> new_capacity
)
904 else if (new_capacity
> max_size
)
905 new_capacity
= size
> max_size
? size
: max_size
;
906 T
* old_data
= this->data();
908 std::allocator_traits
<Allocator
>::allocate(alloc_
, new_capacity
);
909 // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
910 detail::assume(this->size() <= new_capacity
);
911 // The following code doesn't throw, so the raw pointer above doesn't leak.
912 std::uninitialized_copy_n(old_data
, this->size(), new_data
);
913 this->set(new_data
, new_capacity
);
914 // deallocate must not throw according to the standard, but even if it does,
915 // the buffer already uses the new storage and will deallocate it in
917 if (old_data
!= store_
) alloc_
.deallocate(old_data
, old_capacity
);
921 using value_type
= T
;
922 using const_reference
= const T
&;
924 FMT_CONSTEXPR20
explicit basic_memory_buffer(
925 const Allocator
& alloc
= Allocator())
927 this->set(store_
, SIZE
);
928 if (detail::is_constant_evaluated()) detail::fill_n(store_
, SIZE
, T());
930 FMT_CONSTEXPR20
~basic_memory_buffer() { deallocate(); }
933 // Move data from other to this buffer.
934 FMT_CONSTEXPR20
void move(basic_memory_buffer
& other
) {
935 alloc_
= std::move(other
.alloc_
);
936 T
* data
= other
.data();
937 size_t size
= other
.size(), capacity
= other
.capacity();
938 if (data
== other
.store_
) {
939 this->set(store_
, capacity
);
940 detail::copy_str
<T
>(other
.store_
, other
.store_
+ size
, store_
);
942 this->set(data
, capacity
);
943 // Set pointer to the inline array so that delete is not called
944 // when deallocating.
945 other
.set(other
.store_
, 0);
954 Constructs a :class:`fmt::basic_memory_buffer` object moving the content
955 of the other object to it.
958 FMT_CONSTEXPR20
basic_memory_buffer(basic_memory_buffer
&& other
) noexcept
{
964 Moves the content of the other ``basic_memory_buffer`` object to this one.
967 auto operator=(basic_memory_buffer
&& other
) noexcept
-> basic_memory_buffer
& {
968 FMT_ASSERT(this != &other
, "");
974 // Returns a copy of the allocator associated with this buffer.
975 auto get_allocator() const -> Allocator
{ return alloc_
; }
978 Resizes the buffer to contain *count* elements. If T is a POD type new
979 elements may not be initialized.
981 FMT_CONSTEXPR20
void resize(size_t count
) { this->try_resize(count
); }
983 /** Increases the buffer capacity to *new_capacity*. */
984 void reserve(size_t new_capacity
) { this->try_reserve(new_capacity
); }
986 using detail::buffer
<T
>::append
;
987 template <typename ContiguousRange
>
988 void append(const ContiguousRange
& range
) {
989 append(range
.data(), range
.data() + range
.size());
993 using memory_buffer
= basic_memory_buffer
<char>;
995 template <typename T
, size_t SIZE
, typename Allocator
>
996 struct is_contiguous
<basic_memory_buffer
<T
, SIZE
, Allocator
>> : std::true_type
{
1001 FMT_API
auto write_console(int fd
, string_view text
) -> bool;
1002 FMT_API
void print(std::FILE*, string_view
);
1003 } // namespace detail
1007 // Suppress a misleading warning in older versions of clang.
1008 #if FMT_CLANG_VERSION
1009 # pragma clang diagnostic ignored "-Wweak-vtables"
1012 /** An error reported from a formatting function. */
1013 class FMT_SO_VISIBILITY("default") format_error
: public std::runtime_error
{
1015 using std::runtime_error::runtime_error
;
1018 namespace detail_exported
{
1019 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
1020 template <typename Char
, size_t N
> struct fixed_string
{
1021 constexpr fixed_string(const Char (&str
)[N
]) {
1022 detail::copy_str
<Char
, const Char
*, Char
*>(static_cast<const Char
*>(str
),
1029 // Converts a compile-time string to basic_string_view.
1030 template <typename Char
, size_t N
>
1031 constexpr auto compile_string_to_view(const Char (&s
)[N
])
1032 -> basic_string_view
<Char
> {
1033 // Remove trailing NUL character if needed. Won't be present if this is used
1034 // with a raw character array (i.e. not defined as a string).
1035 return {s
, N
- (std::char_traits
<Char
>::to_int_type(s
[N
- 1]) == 0 ? 1 : 0)};
1037 template <typename Char
>
1038 constexpr auto compile_string_to_view(detail::std_string_view
<Char
> s
)
1039 -> basic_string_view
<Char
> {
1040 return {s
.data(), s
.size()};
1042 } // namespace detail_exported
1046 basic_format_arg
<format_context
> value_
;
1049 template <typename T
, FMT_ENABLE_IF(!detail::is_float128
<T
>::value
)>
1050 loc_value(T value
) : value_(detail::make_arg
<format_context
>(value
)) {}
1052 template <typename T
, FMT_ENABLE_IF(detail::is_float128
<T
>::value
)>
1055 template <typename Visitor
> auto visit(Visitor
&& vis
) -> decltype(vis(0)) {
1056 return visit_format_arg(vis
, value_
);
1060 // A locale facet that formats values in UTF-8.
1061 // It is parameterized on the locale to avoid the heavy <locale> include.
1062 template <typename Locale
> class format_facet
: public Locale::facet
{
1064 std::string separator_
;
1065 std::string grouping_
;
1066 std::string decimal_point_
;
1069 virtual auto do_put(appender out
, loc_value val
,
1070 const format_specs
<>& specs
) const -> bool;
1073 static FMT_API typename
Locale::id id
;
1075 explicit format_facet(Locale
& loc
);
1076 explicit format_facet(string_view sep
= "",
1077 std::initializer_list
<unsigned char> g
= {3},
1078 std::string decimal_point
= ".")
1079 : separator_(sep
.data(), sep
.size()),
1080 grouping_(g
.begin(), g
.end()),
1081 decimal_point_(decimal_point
) {}
1083 auto put(appender out
, loc_value val
, const format_specs
<>& specs
) const
1085 return do_put(out
, val
, specs
);
1091 // Returns true if value is negative, false otherwise.
1092 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
1093 template <typename T
, FMT_ENABLE_IF(is_signed
<T
>::value
)>
1094 constexpr auto is_negative(T value
) -> bool {
1097 template <typename T
, FMT_ENABLE_IF(!is_signed
<T
>::value
)>
1098 constexpr auto is_negative(T
) -> bool {
1102 template <typename T
>
1103 FMT_CONSTEXPR
auto is_supported_floating_point(T
) -> bool {
1104 if (std::is_same
<T
, float>()) return FMT_USE_FLOAT
;
1105 if (std::is_same
<T
, double>()) return FMT_USE_DOUBLE
;
1106 if (std::is_same
<T
, long double>()) return FMT_USE_LONG_DOUBLE
;
1110 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
1111 // represent all values of an integral type T.
1112 template <typename T
>
1113 using uint32_or_64_or_128_t
=
1114 conditional_t
<num_bits
<T
>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS
,
1116 conditional_t
<num_bits
<T
>() <= 64, uint64_t, uint128_t
>>;
1117 template <typename T
>
1118 using uint64_or_128_t
= conditional_t
<num_bits
<T
>() <= 64, uint64_t, uint128_t
>;
1120 #define FMT_POWERS_OF_10(factor) \
1121 factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \
1122 (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \
1123 (factor) * 100000000, (factor) * 1000000000
1125 // Converts value in the range [0, 100) to a string.
1126 constexpr auto digits2(size_t value
) -> const char* {
1127 // GCC generates slightly better code when value is pointer-size.
1128 return &"0001020304050607080910111213141516171819"
1129 "2021222324252627282930313233343536373839"
1130 "4041424344454647484950515253545556575859"
1131 "6061626364656667686970717273747576777879"
1132 "8081828384858687888990919293949596979899"[value
* 2];
1135 // Sign is a template parameter to workaround a bug in gcc 4.8.
1136 template <typename Char
, typename Sign
> constexpr auto sign(Sign s
) -> Char
{
1137 #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1138 static_assert(std::is_same
<Sign
, sign_t
>::value
, "");
1140 return static_cast<Char
>("\0-+ "[s
]);
1143 template <typename T
> FMT_CONSTEXPR
auto count_digits_fallback(T n
) -> int {
1146 // Integer division is slow so do it for a group of four digits instead
1147 // of for every digit. The idea comes from the talk by Alexandrescu
1148 // "Three Optimization Tips for C++". See speed-test for a comparison.
1149 if (n
< 10) return count
;
1150 if (n
< 100) return count
+ 1;
1151 if (n
< 1000) return count
+ 2;
1152 if (n
< 10000) return count
+ 3;
1158 FMT_CONSTEXPR
inline auto count_digits(uint128_opt n
) -> int {
1159 return count_digits_fallback(n
);
1163 #ifdef FMT_BUILTIN_CLZLL
1164 // It is a separate function rather than a part of count_digits to workaround
1165 // the lack of static constexpr in constexpr functions.
1166 inline auto do_count_digits(uint64_t n
) -> int {
1167 // This has comparable performance to the version by Kendall Willets
1168 // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
1169 // but uses smaller tables.
1170 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
1171 static constexpr uint8_t bsr2log10
[] = {
1172 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1173 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1174 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1175 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1176 auto t
= bsr2log10
[FMT_BUILTIN_CLZLL(n
| 1) ^ 63];
1177 static constexpr const uint64_t zero_or_powers_of_10
[] = {
1178 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1179 10000000000000000000ULL};
1180 return t
- (n
< zero_or_powers_of_10
[t
]);
1184 // Returns the number of decimal digits in n. Leading zeros are not counted
1185 // except for n == 0 in which case count_digits returns 1.
1186 FMT_CONSTEXPR20
inline auto count_digits(uint64_t n
) -> int {
1187 #ifdef FMT_BUILTIN_CLZLL
1188 if (!is_constant_evaluated()) {
1189 return do_count_digits(n
);
1192 return count_digits_fallback(n
);
1195 // Counts the number of digits in n. BITS = log2(radix).
1196 template <int BITS
, typename UInt
>
1197 FMT_CONSTEXPR
auto count_digits(UInt n
) -> int {
1198 #ifdef FMT_BUILTIN_CLZ
1199 if (!is_constant_evaluated() && num_bits
<UInt
>() == 32)
1200 return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n
) | 1) ^ 31) / BITS
+ 1;
1202 // Lambda avoids unreachable code warnings from NVHPC.
1207 } while ((m
>>= BITS
) != 0);
1212 #ifdef FMT_BUILTIN_CLZ
1213 // It is a separate function rather than a part of count_digits to workaround
1214 // the lack of static constexpr in constexpr functions.
1215 FMT_INLINE
auto do_count_digits(uint32_t n
) -> int {
1216 // An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1217 // This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1218 # define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1219 static constexpr uint64_t table
[] = {
1220 FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1221 FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1222 FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1223 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1224 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1225 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1226 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1227 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1228 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1229 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1230 FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1232 auto inc
= table
[FMT_BUILTIN_CLZ(n
| 1) ^ 31];
1233 return static_cast<int>((n
+ inc
) >> 32);
1237 // Optional version of count_digits for better performance on 32-bit platforms.
1238 FMT_CONSTEXPR20
inline auto count_digits(uint32_t n
) -> int {
1239 #ifdef FMT_BUILTIN_CLZ
1240 if (!is_constant_evaluated()) {
1241 return do_count_digits(n
);
1244 return count_digits_fallback(n
);
1247 template <typename Int
> constexpr auto digits10() noexcept
-> int {
1248 return std::numeric_limits
<Int
>::digits10
;
1250 template <> constexpr auto digits10
<int128_opt
>() noexcept
-> int { return 38; }
1251 template <> constexpr auto digits10
<uint128_t
>() noexcept
-> int { return 38; }
1253 template <typename Char
> struct thousands_sep_result
{
1254 std::string grouping
;
1258 template <typename Char
>
1259 FMT_API
auto thousands_sep_impl(locale_ref loc
) -> thousands_sep_result
<Char
>;
1260 template <typename Char
>
1261 inline auto thousands_sep(locale_ref loc
) -> thousands_sep_result
<Char
> {
1262 auto result
= thousands_sep_impl
<char>(loc
);
1263 return {result
.grouping
, Char(result
.thousands_sep
)};
1266 inline auto thousands_sep(locale_ref loc
) -> thousands_sep_result
<wchar_t> {
1267 return thousands_sep_impl
<wchar_t>(loc
);
1270 template <typename Char
>
1271 FMT_API
auto decimal_point_impl(locale_ref loc
) -> Char
;
1272 template <typename Char
> inline auto decimal_point(locale_ref loc
) -> Char
{
1273 return Char(decimal_point_impl
<char>(loc
));
1275 template <> inline auto decimal_point(locale_ref loc
) -> wchar_t {
1276 return decimal_point_impl
<wchar_t>(loc
);
1279 // Compares two characters for equality.
1280 template <typename Char
> auto equal2(const Char
* lhs
, const char* rhs
) -> bool {
1281 return lhs
[0] == Char(rhs
[0]) && lhs
[1] == Char(rhs
[1]);
1283 inline auto equal2(const char* lhs
, const char* rhs
) -> bool {
1284 return memcmp(lhs
, rhs
, 2) == 0;
1287 // Copies two characters from src to dst.
1288 template <typename Char
>
1289 FMT_CONSTEXPR20 FMT_INLINE
void copy2(Char
* dst
, const char* src
) {
1290 if (!is_constant_evaluated() && sizeof(Char
) == sizeof(char)) {
1291 memcpy(dst
, src
, 2);
1294 *dst
++ = static_cast<Char
>(*src
++);
1295 *dst
= static_cast<Char
>(*src
);
1298 template <typename Iterator
> struct format_decimal_result
{
1303 // Formats a decimal unsigned integer value writing into out pointing to a
1304 // buffer of specified size. The caller must ensure that the buffer is large
1306 template <typename Char
, typename UInt
>
1307 FMT_CONSTEXPR20
auto format_decimal(Char
* out
, UInt value
, int size
)
1308 -> format_decimal_result
<Char
*> {
1309 FMT_ASSERT(size
>= count_digits(value
), "invalid digit count");
1312 while (value
>= 100) {
1313 // Integer division is slow so do it for a group of two digits instead
1314 // of for every digit. The idea comes from the talk by Alexandrescu
1315 // "Three Optimization Tips for C++". See speed-test for a comparison.
1317 copy2(out
, digits2(static_cast<size_t>(value
% 100)));
1321 *--out
= static_cast<Char
>('0' + value
);
1325 copy2(out
, digits2(static_cast<size_t>(value
)));
1329 template <typename Char
, typename UInt
, typename Iterator
,
1330 FMT_ENABLE_IF(!std::is_pointer
<remove_cvref_t
<Iterator
>>::value
)>
1331 FMT_CONSTEXPR
inline auto format_decimal(Iterator out
, UInt value
, int size
)
1332 -> format_decimal_result
<Iterator
> {
1333 // Buffer is large enough to hold all digits (digits10 + 1).
1334 Char buffer
[digits10
<UInt
>() + 1] = {};
1335 auto end
= format_decimal(buffer
, value
, size
).end
;
1336 return {out
, detail::copy_str_noinline
<Char
>(buffer
, end
, out
)};
1339 template <unsigned BASE_BITS
, typename Char
, typename UInt
>
1340 FMT_CONSTEXPR
auto format_uint(Char
* buffer
, UInt value
, int num_digits
,
1341 bool upper
= false) -> Char
* {
1342 buffer
+= num_digits
;
1345 const char* digits
= upper
? "0123456789ABCDEF" : "0123456789abcdef";
1346 unsigned digit
= static_cast<unsigned>(value
& ((1 << BASE_BITS
) - 1));
1347 *--buffer
= static_cast<Char
>(BASE_BITS
< 4 ? static_cast<char>('0' + digit
)
1349 } while ((value
>>= BASE_BITS
) != 0);
1353 template <unsigned BASE_BITS
, typename Char
, typename It
, typename UInt
>
1354 FMT_CONSTEXPR
inline auto format_uint(It out
, UInt value
, int num_digits
,
1355 bool upper
= false) -> It
{
1356 if (auto ptr
= to_pointer
<Char
>(out
, to_unsigned(num_digits
))) {
1357 format_uint
<BASE_BITS
>(ptr
, value
, num_digits
, upper
);
1360 // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1361 char buffer
[num_bits
<UInt
>() / BASE_BITS
+ 1] = {};
1362 format_uint
<BASE_BITS
>(buffer
, value
, num_digits
, upper
);
1363 return detail::copy_str_noinline
<Char
>(buffer
, buffer
+ num_digits
, out
);
1366 // A converter from UTF-8 to UTF-16.
1367 class utf8_to_utf16
{
1369 basic_memory_buffer
<wchar_t> buffer_
;
1372 FMT_API
explicit utf8_to_utf16(string_view s
);
1373 operator basic_string_view
<wchar_t>() const { return {&buffer_
[0], size()}; }
1374 auto size() const -> size_t { return buffer_
.size() - 1; }
1375 auto c_str() const -> const wchar_t* { return &buffer_
[0]; }
1376 auto str() const -> std::wstring
{ return {&buffer_
[0], size()}; }
1379 enum class to_utf8_error_policy
{ abort
, replace
};
1381 // A converter from UTF-16/UTF-32 (host endian) to UTF-8.
1382 template <typename WChar
, typename Buffer
= memory_buffer
> class to_utf8
{
1388 explicit to_utf8(basic_string_view
<WChar
> s
,
1389 to_utf8_error_policy policy
= to_utf8_error_policy::abort
) {
1390 static_assert(sizeof(WChar
) == 2 || sizeof(WChar
) == 4,
1391 "Expect utf16 or utf32");
1392 if (!convert(s
, policy
))
1393 FMT_THROW(std::runtime_error(sizeof(WChar
) == 2 ? "invalid utf16"
1394 : "invalid utf32"));
1396 operator string_view() const { return string_view(&buffer_
[0], size()); }
1397 auto size() const -> size_t { return buffer_
.size() - 1; }
1398 auto c_str() const -> const char* { return &buffer_
[0]; }
1399 auto str() const -> std::string
{ return std::string(&buffer_
[0], size()); }
1401 // Performs conversion returning a bool instead of throwing exception on
1402 // conversion error. This method may still throw in case of memory allocation
1404 auto convert(basic_string_view
<WChar
> s
,
1405 to_utf8_error_policy policy
= to_utf8_error_policy::abort
)
1407 if (!convert(buffer_
, s
, policy
)) return false;
1408 buffer_
.push_back(0);
1411 static auto convert(Buffer
& buf
, basic_string_view
<WChar
> s
,
1412 to_utf8_error_policy policy
= to_utf8_error_policy::abort
)
1414 for (auto p
= s
.begin(); p
!= s
.end(); ++p
) {
1415 uint32_t c
= static_cast<uint32_t>(*p
);
1416 if (sizeof(WChar
) == 2 && c
>= 0xd800 && c
<= 0xdfff) {
1417 // Handle a surrogate pair.
1419 if (p
== s
.end() || (c
& 0xfc00) != 0xd800 || (*p
& 0xfc00) != 0xdc00) {
1420 if (policy
== to_utf8_error_policy::abort
) return false;
1421 buf
.append(string_view("\xEF\xBF\xBD"));
1424 c
= (c
<< 10) + static_cast<uint32_t>(*p
) - 0x35fdc00;
1426 } else if (c
< 0x80) {
1427 buf
.push_back(static_cast<char>(c
));
1428 } else if (c
< 0x800) {
1429 buf
.push_back(static_cast<char>(0xc0 | (c
>> 6)));
1430 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1431 } else if ((c
>= 0x800 && c
<= 0xd7ff) || (c
>= 0xe000 && c
<= 0xffff)) {
1432 buf
.push_back(static_cast<char>(0xe0 | (c
>> 12)));
1433 buf
.push_back(static_cast<char>(0x80 | ((c
& 0xfff) >> 6)));
1434 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1435 } else if (c
>= 0x10000 && c
<= 0x10ffff) {
1436 buf
.push_back(static_cast<char>(0xf0 | (c
>> 18)));
1437 buf
.push_back(static_cast<char>(0x80 | ((c
& 0x3ffff) >> 12)));
1438 buf
.push_back(static_cast<char>(0x80 | ((c
& 0xfff) >> 6)));
1439 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1448 // Computes 128-bit result of multiplication of two 64-bit unsigned integers.
1449 inline auto umul128(uint64_t x
, uint64_t y
) noexcept
-> uint128_fallback
{
1451 auto p
= static_cast<uint128_opt
>(x
) * static_cast<uint128_opt
>(y
);
1452 return {static_cast<uint64_t>(p
>> 64), static_cast<uint64_t>(p
)};
1453 #elif defined(_MSC_VER) && defined(_M_X64)
1454 auto hi
= uint64_t();
1455 auto lo
= _umul128(x
, y
, &hi
);
1458 const uint64_t mask
= static_cast<uint64_t>(max_value
<uint32_t>());
1460 uint64_t a
= x
>> 32;
1461 uint64_t b
= x
& mask
;
1462 uint64_t c
= y
>> 32;
1463 uint64_t d
= y
& mask
;
1465 uint64_t ac
= a
* c
;
1466 uint64_t bc
= b
* c
;
1467 uint64_t ad
= a
* d
;
1468 uint64_t bd
= b
* d
;
1470 uint64_t intermediate
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
);
1472 return {ac
+ (intermediate
>> 32) + (ad
>> 32) + (bc
>> 32),
1473 (intermediate
<< 32) + (bd
& mask
)};
1477 namespace dragonbox
{
1478 // Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
1479 // https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
1480 inline auto floor_log10_pow2(int e
) noexcept
-> int {
1481 FMT_ASSERT(e
<= 2620 && e
>= -2620, "too large exponent");
1482 static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
1483 return (e
* 315653) >> 20;
1486 inline auto floor_log2_pow10(int e
) noexcept
-> int {
1487 FMT_ASSERT(e
<= 1233 && e
>= -1233, "too large exponent");
1488 return (e
* 1741647) >> 19;
1491 // Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
1492 inline auto umul128_upper64(uint64_t x
, uint64_t y
) noexcept
-> uint64_t {
1494 auto p
= static_cast<uint128_opt
>(x
) * static_cast<uint128_opt
>(y
);
1495 return static_cast<uint64_t>(p
>> 64);
1496 #elif defined(_MSC_VER) && defined(_M_X64)
1497 return __umulh(x
, y
);
1499 return umul128(x
, y
).high();
1503 // Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
1504 // 128-bit unsigned integer.
1505 inline auto umul192_upper128(uint64_t x
, uint128_fallback y
) noexcept
1506 -> uint128_fallback
{
1507 uint128_fallback r
= umul128(x
, y
.high());
1508 r
+= umul128_upper64(x
, y
.low());
1512 FMT_API
auto get_cached_power(int k
) noexcept
-> uint128_fallback
;
1514 // Type-specific information that Dragonbox uses.
1515 template <typename T
, typename Enable
= void> struct float_info
;
1517 template <> struct float_info
<float> {
1518 using carrier_uint
= uint32_t;
1519 static const int exponent_bits
= 8;
1520 static const int kappa
= 1;
1521 static const int big_divisor
= 100;
1522 static const int small_divisor
= 10;
1523 static const int min_k
= -31;
1524 static const int max_k
= 46;
1525 static const int shorter_interval_tie_lower_threshold
= -35;
1526 static const int shorter_interval_tie_upper_threshold
= -35;
1529 template <> struct float_info
<double> {
1530 using carrier_uint
= uint64_t;
1531 static const int exponent_bits
= 11;
1532 static const int kappa
= 2;
1533 static const int big_divisor
= 1000;
1534 static const int small_divisor
= 100;
1535 static const int min_k
= -292;
1536 static const int max_k
= 341;
1537 static const int shorter_interval_tie_lower_threshold
= -77;
1538 static const int shorter_interval_tie_upper_threshold
= -77;
1541 // An 80- or 128-bit floating point number.
1542 template <typename T
>
1543 struct float_info
<T
, enable_if_t
<std::numeric_limits
<T
>::digits
== 64 ||
1544 std::numeric_limits
<T
>::digits
== 113 ||
1545 is_float128
<T
>::value
>> {
1546 using carrier_uint
= detail::uint128_t
;
1547 static const int exponent_bits
= 15;
1550 // A double-double floating point number.
1551 template <typename T
>
1552 struct float_info
<T
, enable_if_t
<is_double_double
<T
>::value
>> {
1553 using carrier_uint
= detail::uint128_t
;
1556 template <typename T
> struct decimal_fp
{
1557 using significand_type
= typename float_info
<T
>::carrier_uint
;
1558 significand_type significand
;
1562 template <typename T
> FMT_API
auto to_decimal(T x
) noexcept
-> decimal_fp
<T
>;
1563 } // namespace dragonbox
1565 // Returns true iff Float has the implicit bit which is not stored.
1566 template <typename Float
> constexpr auto has_implicit_bit() -> bool {
1567 // An 80-bit FP number has a 64-bit significand an no implicit bit.
1568 return std::numeric_limits
<Float
>::digits
!= 64;
1571 // Returns the number of significand bits stored in Float. The implicit bit is
1572 // not counted since it is not stored.
1573 template <typename Float
> constexpr auto num_significand_bits() -> int {
1574 // std::numeric_limits may not support __float128.
1575 return is_float128
<Float
>() ? 112
1576 : (std::numeric_limits
<Float
>::digits
-
1577 (has_implicit_bit
<Float
>() ? 1 : 0));
1580 template <typename Float
>
1581 constexpr auto exponent_mask() ->
1582 typename
dragonbox::float_info
<Float
>::carrier_uint
{
1583 using float_uint
= typename
dragonbox::float_info
<Float
>::carrier_uint
;
1584 return ((float_uint(1) << dragonbox::float_info
<Float
>::exponent_bits
) - 1)
1585 << num_significand_bits
<Float
>();
1587 template <typename Float
> constexpr auto exponent_bias() -> int {
1588 // std::numeric_limits may not support __float128.
1589 return is_float128
<Float
>() ? 16383
1590 : std::numeric_limits
<Float
>::max_exponent
- 1;
1593 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1594 template <typename Char
, typename It
>
1595 FMT_CONSTEXPR
auto write_exponent(int exp
, It it
) -> It
{
1596 FMT_ASSERT(-10000 < exp
&& exp
< 10000, "exponent out of range");
1598 *it
++ = static_cast<Char
>('-');
1601 *it
++ = static_cast<Char
>('+');
1604 const char* top
= digits2(to_unsigned(exp
/ 100));
1605 if (exp
>= 1000) *it
++ = static_cast<Char
>(top
[0]);
1606 *it
++ = static_cast<Char
>(top
[1]);
1609 const char* d
= digits2(to_unsigned(exp
));
1610 *it
++ = static_cast<Char
>(d
[0]);
1611 *it
++ = static_cast<Char
>(d
[1]);
1615 // A floating-point number f * pow(2, e) where F is an unsigned type.
1616 template <typename F
> struct basic_fp
{
1620 static constexpr const int num_significand_bits
=
1621 static_cast<int>(sizeof(F
) * num_bits
<unsigned char>());
1623 constexpr basic_fp() : f(0), e(0) {}
1624 constexpr basic_fp(uint64_t f_val
, int e_val
) : f(f_val
), e(e_val
) {}
1626 // Constructs fp from an IEEE754 floating-point number.
1627 template <typename Float
> FMT_CONSTEXPR
basic_fp(Float n
) { assign(n
); }
1629 // Assigns n to this and return true iff predecessor is closer than successor.
1630 template <typename Float
, FMT_ENABLE_IF(!is_double_double
<Float
>::value
)>
1631 FMT_CONSTEXPR
auto assign(Float n
) -> bool {
1632 static_assert(std::numeric_limits
<Float
>::digits
<= 113, "unsupported FP");
1633 // Assume Float is in the format [sign][exponent][significand].
1634 using carrier_uint
= typename
dragonbox::float_info
<Float
>::carrier_uint
;
1635 const auto num_float_significand_bits
=
1636 detail::num_significand_bits
<Float
>();
1637 const auto implicit_bit
= carrier_uint(1) << num_float_significand_bits
;
1638 const auto significand_mask
= implicit_bit
- 1;
1639 auto u
= bit_cast
<carrier_uint
>(n
);
1640 f
= static_cast<F
>(u
& significand_mask
);
1641 auto biased_e
= static_cast<int>((u
& exponent_mask
<Float
>()) >>
1642 num_float_significand_bits
);
1643 // The predecessor is closer if n is a normalized power of 2 (f == 0)
1644 // other than the smallest normalized number (biased_e > 1).
1645 auto is_predecessor_closer
= f
== 0 && biased_e
> 1;
1647 biased_e
= 1; // Subnormals use biased exponent 1 (min exponent).
1648 else if (has_implicit_bit
<Float
>())
1649 f
+= static_cast<F
>(implicit_bit
);
1650 e
= biased_e
- exponent_bias
<Float
>() - num_float_significand_bits
;
1651 if (!has_implicit_bit
<Float
>()) ++e
;
1652 return is_predecessor_closer
;
1655 template <typename Float
, FMT_ENABLE_IF(is_double_double
<Float
>::value
)>
1656 FMT_CONSTEXPR
auto assign(Float n
) -> bool {
1657 static_assert(std::numeric_limits
<double>::is_iec559
, "unsupported FP");
1658 return assign(static_cast<double>(n
));
1662 using fp
= basic_fp
<unsigned long long>;
1664 // Normalizes the value converted from double and multiplied by (1 << SHIFT).
1665 template <int SHIFT
= 0, typename F
>
1666 FMT_CONSTEXPR
auto normalize(basic_fp
<F
> value
) -> basic_fp
<F
> {
1667 // Handle subnormals.
1668 const auto implicit_bit
= F(1) << num_significand_bits
<double>();
1669 const auto shifted_implicit_bit
= implicit_bit
<< SHIFT
;
1670 while ((value
.f
& shifted_implicit_bit
) == 0) {
1674 // Subtract 1 to account for hidden bit.
1675 const auto offset
= basic_fp
<F
>::num_significand_bits
-
1676 num_significand_bits
<double>() - SHIFT
- 1;
1682 // Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
1683 FMT_CONSTEXPR
inline auto multiply(uint64_t lhs
, uint64_t rhs
) -> uint64_t {
1685 auto product
= static_cast<__uint128_t
>(lhs
) * rhs
;
1686 auto f
= static_cast<uint64_t>(product
>> 64);
1687 return (static_cast<uint64_t>(product
) & (1ULL << 63)) != 0 ? f
+ 1 : f
;
1689 // Multiply 32-bit parts of significands.
1690 uint64_t mask
= (1ULL << 32) - 1;
1691 uint64_t a
= lhs
>> 32, b
= lhs
& mask
;
1692 uint64_t c
= rhs
>> 32, d
= rhs
& mask
;
1693 uint64_t ac
= a
* c
, bc
= b
* c
, ad
= a
* d
, bd
= b
* d
;
1694 // Compute mid 64-bit of result and round.
1695 uint64_t mid
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
) + (1U << 31);
1696 return ac
+ (ad
>> 32) + (bc
>> 32) + (mid
>> 32);
1700 FMT_CONSTEXPR
inline auto operator*(fp x
, fp y
) -> fp
{
1701 return {multiply(x
.f
, y
.f
), x
.e
+ y
.e
+ 64};
1704 template <typename T
, bool doublish
= num_bits
<T
>() == num_bits
<double>()>
1705 using convert_float_result
=
1706 conditional_t
<std::is_same
<T
, float>::value
|| doublish
, double, T
>;
1708 template <typename T
>
1709 constexpr auto convert_float(T value
) -> convert_float_result
<T
> {
1710 return static_cast<convert_float_result
<T
>>(value
);
1713 template <typename OutputIt
, typename Char
>
1714 FMT_NOINLINE FMT_CONSTEXPR
auto fill(OutputIt it
, size_t n
,
1715 const fill_t
<Char
>& fill
) -> OutputIt
{
1716 auto fill_size
= fill
.size();
1717 if (fill_size
== 1) return detail::fill_n(it
, n
, fill
[0]);
1718 auto data
= fill
.data();
1719 for (size_t i
= 0; i
< n
; ++i
)
1720 it
= copy_str
<Char
>(data
, data
+ fill_size
, it
);
1724 // Writes the output of f, padded according to format specifications in specs.
1725 // size: output size in code units.
1726 // width: output display width in (terminal) column positions.
1727 template <align::type align
= align::left
, typename OutputIt
, typename Char
,
1729 FMT_CONSTEXPR
auto write_padded(OutputIt out
, const format_specs
<Char
>& specs
,
1730 size_t size
, size_t width
, F
&& f
) -> OutputIt
{
1731 static_assert(align
== align::left
|| align
== align::right
, "");
1732 unsigned spec_width
= to_unsigned(specs
.width
);
1733 size_t padding
= spec_width
> width
? spec_width
- width
: 0;
1734 // Shifts are encoded as string literals because static constexpr is not
1735 // supported in constexpr functions.
1736 auto* shifts
= align
== align::left
? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1737 size_t left_padding
= padding
>> shifts
[specs
.align
];
1738 size_t right_padding
= padding
- left_padding
;
1739 auto it
= reserve(out
, size
+ padding
* specs
.fill
.size());
1740 if (left_padding
!= 0) it
= fill(it
, left_padding
, specs
.fill
);
1742 if (right_padding
!= 0) it
= fill(it
, right_padding
, specs
.fill
);
1743 return base_iterator(out
, it
);
1746 template <align::type align
= align::left
, typename OutputIt
, typename Char
,
1748 constexpr auto write_padded(OutputIt out
, const format_specs
<Char
>& specs
,
1749 size_t size
, F
&& f
) -> OutputIt
{
1750 return write_padded
<align
>(out
, specs
, size
, size
, f
);
1753 template <align::type align
= align::left
, typename Char
, typename OutputIt
>
1754 FMT_CONSTEXPR
auto write_bytes(OutputIt out
, string_view bytes
,
1755 const format_specs
<Char
>& specs
) -> OutputIt
{
1756 return write_padded
<align
>(
1757 out
, specs
, bytes
.size(), [bytes
](reserve_iterator
<OutputIt
> it
) {
1758 const char* data
= bytes
.data();
1759 return copy_str
<Char
>(data
, data
+ bytes
.size(), it
);
1763 template <typename Char
, typename OutputIt
, typename UIntPtr
>
1764 auto write_ptr(OutputIt out
, UIntPtr value
, const format_specs
<Char
>* specs
)
1766 int num_digits
= count_digits
<4>(value
);
1767 auto size
= to_unsigned(num_digits
) + size_t(2);
1768 auto write
= [=](reserve_iterator
<OutputIt
> it
) {
1769 *it
++ = static_cast<Char
>('0');
1770 *it
++ = static_cast<Char
>('x');
1771 return format_uint
<4, Char
>(it
, value
, num_digits
);
1773 return specs
? write_padded
<align::right
>(out
, *specs
, size
, write
)
1774 : base_iterator(out
, write(reserve(out
, size
)));
1777 // Returns true iff the code point cp is printable.
1778 FMT_API
auto is_printable(uint32_t cp
) -> bool;
1780 inline auto needs_escape(uint32_t cp
) -> bool {
1781 return cp
< 0x20 || cp
== 0x7f || cp
== '"' || cp
== '\\' ||
1785 template <typename Char
> struct find_escape_result
{
1791 template <typename Char
>
1792 using make_unsigned_char
=
1793 typename conditional_t
<std::is_integral
<Char
>::value
,
1794 std::make_unsigned
<Char
>,
1795 type_identity
<uint32_t>>::type
;
1797 template <typename Char
>
1798 auto find_escape(const Char
* begin
, const Char
* end
)
1799 -> find_escape_result
<Char
> {
1800 for (; begin
!= end
; ++begin
) {
1801 uint32_t cp
= static_cast<make_unsigned_char
<Char
>>(*begin
);
1802 if (const_check(sizeof(Char
) == 1) && cp
>= 0x80) continue;
1803 if (needs_escape(cp
)) return {begin
, begin
+ 1, cp
};
1805 return {begin
, nullptr, 0};
1808 inline auto find_escape(const char* begin
, const char* end
)
1809 -> find_escape_result
<char> {
1810 if (!is_utf8()) return find_escape
<char>(begin
, end
);
1811 auto result
= find_escape_result
<char>{end
, nullptr, 0};
1812 for_each_codepoint(string_view(begin
, to_unsigned(end
- begin
)),
1813 [&](uint32_t cp
, string_view sv
) {
1814 if (needs_escape(cp
)) {
1815 result
= {sv
.begin(), sv
.end(), cp
};
1823 #define FMT_STRING_IMPL(s, base, explicit) \
1825 /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
1826 /* Use a macro-like name to avoid shadowing warnings. */ \
1827 struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
1828 using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1829 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1830 operator fmt::basic_string_view<char_type>() const { \
1831 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1834 return FMT_COMPILE_STRING(); \
1839 Constructs a compile-time format string from a string literal *s*.
1843 // A compile-time error because 'd' is an invalid specifier for strings.
1844 std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
1847 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1849 template <size_t width
, typename Char
, typename OutputIt
>
1850 auto write_codepoint(OutputIt out
, char prefix
, uint32_t cp
) -> OutputIt
{
1851 *out
++ = static_cast<Char
>('\\');
1852 *out
++ = static_cast<Char
>(prefix
);
1854 fill_n(buf
, width
, static_cast<Char
>('0'));
1855 format_uint
<4>(buf
, cp
, width
);
1856 return copy_str
<Char
>(buf
, buf
+ width
, out
);
1859 template <typename OutputIt
, typename Char
>
1860 auto write_escaped_cp(OutputIt out
, const find_escape_result
<Char
>& escape
)
1862 auto c
= static_cast<Char
>(escape
.cp
);
1863 switch (escape
.cp
) {
1865 *out
++ = static_cast<Char
>('\\');
1866 c
= static_cast<Char
>('n');
1869 *out
++ = static_cast<Char
>('\\');
1870 c
= static_cast<Char
>('r');
1873 *out
++ = static_cast<Char
>('\\');
1874 c
= static_cast<Char
>('t');
1881 *out
++ = static_cast<Char
>('\\');
1884 if (escape
.cp
< 0x100) {
1885 return write_codepoint
<2, Char
>(out
, 'x', escape
.cp
);
1887 if (escape
.cp
< 0x10000) {
1888 return write_codepoint
<4, Char
>(out
, 'u', escape
.cp
);
1890 if (escape
.cp
< 0x110000) {
1891 return write_codepoint
<8, Char
>(out
, 'U', escape
.cp
);
1893 for (Char escape_char
: basic_string_view
<Char
>(
1894 escape
.begin
, to_unsigned(escape
.end
- escape
.begin
))) {
1895 out
= write_codepoint
<2, Char
>(out
, 'x',
1896 static_cast<uint32_t>(escape_char
) & 0xFF);
1904 template <typename Char
, typename OutputIt
>
1905 auto write_escaped_string(OutputIt out
, basic_string_view
<Char
> str
)
1907 *out
++ = static_cast<Char
>('"');
1908 auto begin
= str
.begin(), end
= str
.end();
1910 auto escape
= find_escape(begin
, end
);
1911 out
= copy_str
<Char
>(begin
, escape
.begin
, out
);
1914 out
= write_escaped_cp
<OutputIt
, Char
>(out
, escape
);
1915 } while (begin
!= end
);
1916 *out
++ = static_cast<Char
>('"');
1920 template <typename Char
, typename OutputIt
>
1921 auto write_escaped_char(OutputIt out
, Char v
) -> OutputIt
{
1922 Char v_array
[1] = {v
};
1923 *out
++ = static_cast<Char
>('\'');
1924 if ((needs_escape(static_cast<uint32_t>(v
)) && v
!= static_cast<Char
>('"')) ||
1925 v
== static_cast<Char
>('\'')) {
1926 out
= write_escaped_cp(out
,
1927 find_escape_result
<Char
>{v_array
, v_array
+ 1,
1928 static_cast<uint32_t>(v
)});
1932 *out
++ = static_cast<Char
>('\'');
1936 template <typename Char
, typename OutputIt
>
1937 FMT_CONSTEXPR
auto write_char(OutputIt out
, Char value
,
1938 const format_specs
<Char
>& specs
) -> OutputIt
{
1939 bool is_debug
= specs
.type
== presentation_type::debug
;
1940 return write_padded(out
, specs
, 1, [=](reserve_iterator
<OutputIt
> it
) {
1941 if (is_debug
) return write_escaped_char(it
, value
);
1946 template <typename Char
, typename OutputIt
>
1947 FMT_CONSTEXPR
auto write(OutputIt out
, Char value
,
1948 const format_specs
<Char
>& specs
, locale_ref loc
= {})
1950 // char is formatted as unsigned char for consistency across platforms.
1951 using unsigned_type
=
1952 conditional_t
<std::is_same
<Char
, char>::value
, unsigned char, unsigned>;
1953 return check_char_specs(specs
)
1954 ? write_char(out
, value
, specs
)
1955 : write(out
, static_cast<unsigned_type
>(value
), specs
, loc
);
1958 // Data for write_int that doesn't depend on output iterator type. It is used to
1959 // avoid template code bloat.
1960 template <typename Char
> struct write_int_data
{
1964 FMT_CONSTEXPR
write_int_data(int num_digits
, unsigned prefix
,
1965 const format_specs
<Char
>& specs
)
1966 : size((prefix
>> 24) + to_unsigned(num_digits
)), padding(0) {
1967 if (specs
.align
== align::numeric
) {
1968 auto width
= to_unsigned(specs
.width
);
1970 padding
= width
- size
;
1973 } else if (specs
.precision
> num_digits
) {
1974 size
= (prefix
>> 24) + to_unsigned(specs
.precision
);
1975 padding
= to_unsigned(specs
.precision
- num_digits
);
1980 // Writes an integer in the format
1981 // <left-padding><prefix><numeric-padding><digits><right-padding>
1982 // where <digits> are written by write_digits(it).
1983 // prefix contains chars in three lower bytes and the size in the fourth byte.
1984 template <typename OutputIt
, typename Char
, typename W
>
1985 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out
, int num_digits
,
1987 const format_specs
<Char
>& specs
,
1988 W write_digits
) -> OutputIt
{
1989 // Slightly faster check for specs.width == 0 && specs.precision == -1.
1990 if ((specs
.width
| (specs
.precision
+ 1)) == 0) {
1991 auto it
= reserve(out
, to_unsigned(num_digits
) + (prefix
>> 24));
1993 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
1994 *it
++ = static_cast<Char
>(p
& 0xff);
1996 return base_iterator(out
, write_digits(it
));
1998 auto data
= write_int_data
<Char
>(num_digits
, prefix
, specs
);
1999 return write_padded
<align::right
>(
2000 out
, specs
, data
.size
, [=](reserve_iterator
<OutputIt
> it
) {
2001 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
2002 *it
++ = static_cast<Char
>(p
& 0xff);
2003 it
= detail::fill_n(it
, data
.padding
, static_cast<Char
>('0'));
2004 return write_digits(it
);
2008 template <typename Char
> class digit_grouping
{
2010 std::string grouping_
;
2011 std::basic_string
<Char
> thousands_sep_
;
2014 std::string::const_iterator group
;
2017 auto initial_state() const -> next_state
{ return {grouping_
.begin(), 0}; }
2019 // Returns the next digit group separator position.
2020 auto next(next_state
& state
) const -> int {
2021 if (thousands_sep_
.empty()) return max_value
<int>();
2022 if (state
.group
== grouping_
.end()) return state
.pos
+= grouping_
.back();
2023 if (*state
.group
<= 0 || *state
.group
== max_value
<char>())
2024 return max_value
<int>();
2025 state
.pos
+= *state
.group
++;
2030 explicit digit_grouping(locale_ref loc
, bool localized
= true) {
2031 if (!localized
) return;
2032 auto sep
= thousands_sep
<Char
>(loc
);
2033 grouping_
= sep
.grouping
;
2034 if (sep
.thousands_sep
) thousands_sep_
.assign(1, sep
.thousands_sep
);
2036 digit_grouping(std::string grouping
, std::basic_string
<Char
> sep
)
2037 : grouping_(std::move(grouping
)), thousands_sep_(std::move(sep
)) {}
2039 auto has_separator() const -> bool { return !thousands_sep_
.empty(); }
2041 auto count_separators(int num_digits
) const -> int {
2043 auto state
= initial_state();
2044 while (num_digits
> next(state
)) ++count
;
2048 // Applies grouping to digits and write the output to out.
2049 template <typename Out
, typename C
>
2050 auto apply(Out out
, basic_string_view
<C
> digits
) const -> Out
{
2051 auto num_digits
= static_cast<int>(digits
.size());
2052 auto separators
= basic_memory_buffer
<int>();
2053 separators
.push_back(0);
2054 auto state
= initial_state();
2055 while (int i
= next(state
)) {
2056 if (i
>= num_digits
) break;
2057 separators
.push_back(i
);
2059 for (int i
= 0, sep_index
= static_cast<int>(separators
.size() - 1);
2060 i
< num_digits
; ++i
) {
2061 if (num_digits
- i
== separators
[sep_index
]) {
2063 copy_str
<Char
>(thousands_sep_
.data(),
2064 thousands_sep_
.data() + thousands_sep_
.size(), out
);
2067 *out
++ = static_cast<Char
>(digits
[to_unsigned(i
)]);
2073 FMT_CONSTEXPR
inline void prefix_append(unsigned& prefix
, unsigned value
) {
2074 prefix
|= prefix
!= 0 ? value
<< 8 : value
;
2075 prefix
+= (1u + (value
> 0xff ? 1 : 0)) << 24;
2078 // Writes a decimal integer with digit grouping.
2079 template <typename OutputIt
, typename UInt
, typename Char
>
2080 auto write_int(OutputIt out
, UInt value
, unsigned prefix
,
2081 const format_specs
<Char
>& specs
,
2082 const digit_grouping
<Char
>& grouping
) -> OutputIt
{
2083 static_assert(std::is_same
<uint64_or_128_t
<UInt
>, UInt
>::value
, "");
2085 auto buffer
= memory_buffer();
2086 switch (specs
.type
) {
2087 case presentation_type::none
:
2088 case presentation_type::dec
: {
2089 num_digits
= count_digits(value
);
2090 format_decimal
<char>(appender(buffer
), value
, num_digits
);
2093 case presentation_type::hex_lower
:
2094 case presentation_type::hex_upper
: {
2095 bool upper
= specs
.type
== presentation_type::hex_upper
;
2097 prefix_append(prefix
, unsigned(upper
? 'X' : 'x') << 8 | '0');
2098 num_digits
= count_digits
<4>(value
);
2099 format_uint
<4, char>(appender(buffer
), value
, num_digits
, upper
);
2102 case presentation_type::bin_lower
:
2103 case presentation_type::bin_upper
: {
2104 bool upper
= specs
.type
== presentation_type::bin_upper
;
2106 prefix_append(prefix
, unsigned(upper
? 'B' : 'b') << 8 | '0');
2107 num_digits
= count_digits
<1>(value
);
2108 format_uint
<1, char>(appender(buffer
), value
, num_digits
);
2111 case presentation_type::oct
: {
2112 num_digits
= count_digits
<3>(value
);
2113 // Octal prefix '0' is counted as a digit, so only add it if precision
2114 // is not greater than the number of digits.
2115 if (specs
.alt
&& specs
.precision
<= num_digits
&& value
!= 0)
2116 prefix_append(prefix
, '0');
2117 format_uint
<3, char>(appender(buffer
), value
, num_digits
);
2120 case presentation_type::chr
:
2121 return write_char(out
, static_cast<Char
>(value
), specs
);
2123 throw_format_error("invalid format specifier");
2126 unsigned size
= (prefix
!= 0 ? prefix
>> 24 : 0) + to_unsigned(num_digits
) +
2127 to_unsigned(grouping
.count_separators(num_digits
));
2128 return write_padded
<align::right
>(
2129 out
, specs
, size
, size
, [&](reserve_iterator
<OutputIt
> it
) {
2130 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
2131 *it
++ = static_cast<Char
>(p
& 0xff);
2132 return grouping
.apply(it
, string_view(buffer
.data(), buffer
.size()));
2136 // Writes a localized value.
2137 FMT_API
auto write_loc(appender out
, loc_value value
,
2138 const format_specs
<>& specs
, locale_ref loc
) -> bool;
2139 template <typename OutputIt
, typename Char
>
2140 inline auto write_loc(OutputIt
, loc_value
, const format_specs
<Char
>&,
2141 locale_ref
) -> bool {
2145 template <typename UInt
> struct write_int_arg
{
2150 template <typename T
>
2151 FMT_CONSTEXPR
auto make_write_int_arg(T value
, sign_t sign
)
2152 -> write_int_arg
<uint32_or_64_or_128_t
<T
>> {
2154 auto abs_value
= static_cast<uint32_or_64_or_128_t
<T
>>(value
);
2155 if (is_negative(value
)) {
2156 prefix
= 0x01000000 | '-';
2157 abs_value
= 0 - abs_value
;
2159 constexpr const unsigned prefixes
[4] = {0, 0, 0x1000000u
| '+',
2161 prefix
= prefixes
[sign
];
2163 return {abs_value
, prefix
};
2166 template <typename Char
= char> struct loc_writer
{
2167 buffer_appender
<Char
> out
;
2168 const format_specs
<Char
>& specs
;
2169 std::basic_string
<Char
> sep
;
2170 std::string grouping
;
2171 std::basic_string
<Char
> decimal_point
;
2173 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
2174 auto operator()(T value
) -> bool {
2175 auto arg
= make_write_int_arg(value
, specs
.sign
);
2176 write_int(out
, static_cast<uint64_or_128_t
<T
>>(arg
.abs_value
), arg
.prefix
,
2177 specs
, digit_grouping
<Char
>(grouping
, sep
));
2181 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
2182 auto operator()(T
) -> bool {
2187 template <typename Char
, typename OutputIt
, typename T
>
2188 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out
, write_int_arg
<T
> arg
,
2189 const format_specs
<Char
>& specs
,
2190 locale_ref
) -> OutputIt
{
2191 static_assert(std::is_same
<T
, uint32_or_64_or_128_t
<T
>>::value
, "");
2192 auto abs_value
= arg
.abs_value
;
2193 auto prefix
= arg
.prefix
;
2194 switch (specs
.type
) {
2195 case presentation_type::none
:
2196 case presentation_type::dec
: {
2197 auto num_digits
= count_digits(abs_value
);
2199 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2200 return format_decimal
<Char
>(it
, abs_value
, num_digits
).end
;
2203 case presentation_type::hex_lower
:
2204 case presentation_type::hex_upper
: {
2205 bool upper
= specs
.type
== presentation_type::hex_upper
;
2207 prefix_append(prefix
, unsigned(upper
? 'X' : 'x') << 8 | '0');
2208 int num_digits
= count_digits
<4>(abs_value
);
2210 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2211 return format_uint
<4, Char
>(it
, abs_value
, num_digits
, upper
);
2214 case presentation_type::bin_lower
:
2215 case presentation_type::bin_upper
: {
2216 bool upper
= specs
.type
== presentation_type::bin_upper
;
2218 prefix_append(prefix
, unsigned(upper
? 'B' : 'b') << 8 | '0');
2219 int num_digits
= count_digits
<1>(abs_value
);
2220 return write_int(out
, num_digits
, prefix
, specs
,
2221 [=](reserve_iterator
<OutputIt
> it
) {
2222 return format_uint
<1, Char
>(it
, abs_value
, num_digits
);
2225 case presentation_type::oct
: {
2226 int num_digits
= count_digits
<3>(abs_value
);
2227 // Octal prefix '0' is counted as a digit, so only add it if precision
2228 // is not greater than the number of digits.
2229 if (specs
.alt
&& specs
.precision
<= num_digits
&& abs_value
!= 0)
2230 prefix_append(prefix
, '0');
2231 return write_int(out
, num_digits
, prefix
, specs
,
2232 [=](reserve_iterator
<OutputIt
> it
) {
2233 return format_uint
<3, Char
>(it
, abs_value
, num_digits
);
2236 case presentation_type::chr
:
2237 return write_char(out
, static_cast<Char
>(abs_value
), specs
);
2239 throw_format_error("invalid format specifier");
2243 template <typename Char
, typename OutputIt
, typename T
>
2244 FMT_CONSTEXPR FMT_NOINLINE
auto write_int_noinline(
2245 OutputIt out
, write_int_arg
<T
> arg
, const format_specs
<Char
>& specs
,
2246 locale_ref loc
) -> OutputIt
{
2247 return write_int(out
, arg
, specs
, loc
);
2249 template <typename Char
, typename OutputIt
, typename T
,
2250 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2251 !std::is_same
<T
, bool>::value
&&
2252 std::is_same
<OutputIt
, buffer_appender
<Char
>>::value
)>
2253 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out
, T value
,
2254 const format_specs
<Char
>& specs
,
2255 locale_ref loc
) -> OutputIt
{
2256 if (specs
.localized
&& write_loc(out
, value
, specs
, loc
)) return out
;
2257 return write_int_noinline(out
, make_write_int_arg(value
, specs
.sign
), specs
,
2260 // An inlined version of write used in format string compilation.
2261 template <typename Char
, typename OutputIt
, typename T
,
2262 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2263 !std::is_same
<T
, bool>::value
&&
2264 !std::is_same
<OutputIt
, buffer_appender
<Char
>>::value
)>
2265 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out
, T value
,
2266 const format_specs
<Char
>& specs
,
2267 locale_ref loc
) -> OutputIt
{
2268 if (specs
.localized
&& write_loc(out
, value
, specs
, loc
)) return out
;
2269 return write_int(out
, make_write_int_arg(value
, specs
.sign
), specs
, loc
);
2272 // An output iterator that counts the number of objects written to it and
2274 class counting_iterator
{
2279 using iterator_category
= std::output_iterator_tag
;
2280 using difference_type
= std::ptrdiff_t;
2281 using pointer
= void;
2282 using reference
= void;
2283 FMT_UNCHECKED_ITERATOR(counting_iterator
);
2286 template <typename T
> FMT_CONSTEXPR
void operator=(const T
&) {}
2289 FMT_CONSTEXPR
counting_iterator() : count_(0) {}
2291 FMT_CONSTEXPR
auto count() const -> size_t { return count_
; }
2293 FMT_CONSTEXPR
auto operator++() -> counting_iterator
& {
2297 FMT_CONSTEXPR
auto operator++(int) -> counting_iterator
{
2303 FMT_CONSTEXPR
friend auto operator+(counting_iterator it
, difference_type n
)
2304 -> counting_iterator
{
2305 it
.count_
+= static_cast<size_t>(n
);
2309 FMT_CONSTEXPR
auto operator*() const -> value_type
{ return {}; }
2312 template <typename Char
, typename OutputIt
>
2313 FMT_CONSTEXPR
auto write(OutputIt out
, basic_string_view
<Char
> s
,
2314 const format_specs
<Char
>& specs
) -> OutputIt
{
2315 auto data
= s
.data();
2316 auto size
= s
.size();
2317 if (specs
.precision
>= 0 && to_unsigned(specs
.precision
) < size
)
2318 size
= code_point_index(s
, to_unsigned(specs
.precision
));
2319 bool is_debug
= specs
.type
== presentation_type::debug
;
2321 if (specs
.width
!= 0) {
2323 width
= write_escaped_string(counting_iterator
{}, s
).count();
2325 width
= compute_width(basic_string_view
<Char
>(data
, size
));
2327 return write_padded(out
, specs
, size
, width
,
2328 [=](reserve_iterator
<OutputIt
> it
) {
2329 if (is_debug
) return write_escaped_string(it
, s
);
2330 return copy_str
<Char
>(data
, data
+ size
, it
);
2333 template <typename Char
, typename OutputIt
>
2334 FMT_CONSTEXPR
auto write(OutputIt out
,
2335 basic_string_view
<type_identity_t
<Char
>> s
,
2336 const format_specs
<Char
>& specs
, locale_ref
)
2338 return write(out
, s
, specs
);
2340 template <typename Char
, typename OutputIt
>
2341 FMT_CONSTEXPR
auto write(OutputIt out
, const Char
* s
,
2342 const format_specs
<Char
>& specs
, locale_ref
)
2344 if (specs
.type
== presentation_type::pointer
)
2345 return write_ptr
<Char
>(out
, bit_cast
<uintptr_t>(s
), &specs
);
2346 if (!s
) throw_format_error("string pointer is null");
2347 return write(out
, basic_string_view
<Char
>(s
), specs
, {});
2350 template <typename Char
, typename OutputIt
, typename T
,
2351 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2352 !std::is_same
<T
, bool>::value
&&
2353 !std::is_same
<T
, Char
>::value
)>
2354 FMT_CONSTEXPR
auto write(OutputIt out
, T value
) -> OutputIt
{
2355 auto abs_value
= static_cast<uint32_or_64_or_128_t
<T
>>(value
);
2356 bool negative
= is_negative(value
);
2357 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2358 if (negative
) abs_value
= ~abs_value
+ 1;
2359 int num_digits
= count_digits(abs_value
);
2360 auto size
= (negative
? 1 : 0) + static_cast<size_t>(num_digits
);
2361 auto it
= reserve(out
, size
);
2362 if (auto ptr
= to_pointer
<Char
>(it
, size
)) {
2363 if (negative
) *ptr
++ = static_cast<Char
>('-');
2364 format_decimal
<Char
>(ptr
, abs_value
, num_digits
);
2367 if (negative
) *it
++ = static_cast<Char
>('-');
2368 it
= format_decimal
<Char
>(it
, abs_value
, num_digits
).end
;
2369 return base_iterator(out
, it
);
2373 template <typename Char
>
2374 FMT_CONSTEXPR
auto parse_align(const Char
* begin
, const Char
* end
,
2375 format_specs
<Char
>& specs
) -> const Char
* {
2376 FMT_ASSERT(begin
!= end
, "");
2377 auto align
= align::none
;
2378 auto p
= begin
+ code_point_length(begin
);
2379 if (end
- p
<= 0) p
= begin
;
2381 switch (to_ascii(*p
)) {
2383 align
= align::left
;
2386 align
= align::right
;
2389 align
= align::center
;
2392 if (align
!= align::none
) {
2395 if (c
== '}') return begin
;
2397 throw_format_error("invalid fill character '{'");
2400 specs
.fill
= {begin
, to_unsigned(p
- begin
)};
2406 } else if (p
== begin
) {
2411 specs
.align
= align
;
2415 // A floating-point presentation format.
2416 enum class float_format
: unsigned char {
2417 general
, // General: exponent notation or fixed point based on magnitude.
2418 exp
, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
2419 fixed
, // Fixed point with the default precision of 6, e.g. 0.0012.
2423 struct float_specs
{
2425 float_format format
: 8;
2433 template <typename Char
>
2434 FMT_CONSTEXPR
auto parse_float_type_spec(const format_specs
<Char
>& specs
)
2436 auto result
= float_specs();
2437 result
.showpoint
= specs
.alt
;
2438 result
.locale
= specs
.localized
;
2439 switch (specs
.type
) {
2440 case presentation_type::none
:
2441 result
.format
= float_format::general
;
2443 case presentation_type::general_upper
:
2444 result
.upper
= true;
2446 case presentation_type::general_lower
:
2447 result
.format
= float_format::general
;
2449 case presentation_type::exp_upper
:
2450 result
.upper
= true;
2452 case presentation_type::exp_lower
:
2453 result
.format
= float_format::exp
;
2454 result
.showpoint
|= specs
.precision
!= 0;
2456 case presentation_type::fixed_upper
:
2457 result
.upper
= true;
2459 case presentation_type::fixed_lower
:
2460 result
.format
= float_format::fixed
;
2461 result
.showpoint
|= specs
.precision
!= 0;
2463 case presentation_type::hexfloat_upper
:
2464 result
.upper
= true;
2466 case presentation_type::hexfloat_lower
:
2467 result
.format
= float_format::hex
;
2470 throw_format_error("invalid format specifier");
2476 template <typename Char
, typename OutputIt
>
2477 FMT_CONSTEXPR20
auto write_nonfinite(OutputIt out
, bool isnan
,
2478 format_specs
<Char
> specs
,
2479 const float_specs
& fspecs
) -> OutputIt
{
2481 isnan
? (fspecs
.upper
? "NAN" : "nan") : (fspecs
.upper
? "INF" : "inf");
2482 constexpr size_t str_size
= 3;
2483 auto sign
= fspecs
.sign
;
2484 auto size
= str_size
+ (sign
? 1 : 0);
2485 // Replace '0'-padding with space for non-finite values.
2486 const bool is_zero_fill
=
2487 specs
.fill
.size() == 1 && *specs
.fill
.data() == static_cast<Char
>('0');
2488 if (is_zero_fill
) specs
.fill
[0] = static_cast<Char
>(' ');
2489 return write_padded(out
, specs
, size
, [=](reserve_iterator
<OutputIt
> it
) {
2490 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2491 return copy_str
<Char
>(str
, str
+ str_size
, it
);
2495 // A decimal floating-point number significand * pow(10, exp).
2496 struct big_decimal_fp
{
2497 const char* significand
;
2498 int significand_size
;
2502 constexpr auto get_significand_size(const big_decimal_fp
& f
) -> int {
2503 return f
.significand_size
;
2505 template <typename T
>
2506 inline auto get_significand_size(const dragonbox::decimal_fp
<T
>& f
) -> int {
2507 return count_digits(f
.significand
);
2510 template <typename Char
, typename OutputIt
>
2511 constexpr auto write_significand(OutputIt out
, const char* significand
,
2512 int significand_size
) -> OutputIt
{
2513 return copy_str
<Char
>(significand
, significand
+ significand_size
, out
);
2515 template <typename Char
, typename OutputIt
, typename UInt
>
2516 inline auto write_significand(OutputIt out
, UInt significand
,
2517 int significand_size
) -> OutputIt
{
2518 return format_decimal
<Char
>(out
, significand
, significand_size
).end
;
2520 template <typename Char
, typename OutputIt
, typename T
, typename Grouping
>
2521 FMT_CONSTEXPR20
auto write_significand(OutputIt out
, T significand
,
2522 int significand_size
, int exponent
,
2523 const Grouping
& grouping
) -> OutputIt
{
2524 if (!grouping
.has_separator()) {
2525 out
= write_significand
<Char
>(out
, significand
, significand_size
);
2526 return detail::fill_n(out
, exponent
, static_cast<Char
>('0'));
2528 auto buffer
= memory_buffer();
2529 write_significand
<char>(appender(buffer
), significand
, significand_size
);
2530 detail::fill_n(appender(buffer
), exponent
, '0');
2531 return grouping
.apply(out
, string_view(buffer
.data(), buffer
.size()));
2534 template <typename Char
, typename UInt
,
2535 FMT_ENABLE_IF(std::is_integral
<UInt
>::value
)>
2536 inline auto write_significand(Char
* out
, UInt significand
, int significand_size
,
2537 int integral_size
, Char decimal_point
) -> Char
* {
2539 return format_decimal(out
, significand
, significand_size
).end
;
2540 out
+= significand_size
+ 1;
2542 int floating_size
= significand_size
- integral_size
;
2543 for (int i
= floating_size
/ 2; i
> 0; --i
) {
2545 copy2(out
, digits2(static_cast<std::size_t>(significand
% 100)));
2548 if (floating_size
% 2 != 0) {
2549 *--out
= static_cast<Char
>('0' + significand
% 10);
2552 *--out
= decimal_point
;
2553 format_decimal(out
- integral_size
, significand
, integral_size
);
2557 template <typename OutputIt
, typename UInt
, typename Char
,
2558 FMT_ENABLE_IF(!std::is_pointer
<remove_cvref_t
<OutputIt
>>::value
)>
2559 inline auto write_significand(OutputIt out
, UInt significand
,
2560 int significand_size
, int integral_size
,
2561 Char decimal_point
) -> OutputIt
{
2562 // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
2563 Char buffer
[digits10
<UInt
>() + 2];
2564 auto end
= write_significand(buffer
, significand
, significand_size
,
2565 integral_size
, decimal_point
);
2566 return detail::copy_str_noinline
<Char
>(buffer
, end
, out
);
2569 template <typename OutputIt
, typename Char
>
2570 FMT_CONSTEXPR
auto write_significand(OutputIt out
, const char* significand
,
2571 int significand_size
, int integral_size
,
2572 Char decimal_point
) -> OutputIt
{
2573 out
= detail::copy_str_noinline
<Char
>(significand
,
2574 significand
+ integral_size
, out
);
2575 if (!decimal_point
) return out
;
2576 *out
++ = decimal_point
;
2577 return detail::copy_str_noinline
<Char
>(significand
+ integral_size
,
2578 significand
+ significand_size
, out
);
2581 template <typename OutputIt
, typename Char
, typename T
, typename Grouping
>
2582 FMT_CONSTEXPR20
auto write_significand(OutputIt out
, T significand
,
2583 int significand_size
, int integral_size
,
2585 const Grouping
& grouping
) -> OutputIt
{
2586 if (!grouping
.has_separator()) {
2587 return write_significand(out
, significand
, significand_size
, integral_size
,
2590 auto buffer
= basic_memory_buffer
<Char
>();
2591 write_significand(buffer_appender
<Char
>(buffer
), significand
,
2592 significand_size
, integral_size
, decimal_point
);
2594 out
, basic_string_view
<Char
>(buffer
.data(), to_unsigned(integral_size
)));
2595 return detail::copy_str_noinline
<Char
>(buffer
.data() + integral_size
,
2599 template <typename OutputIt
, typename DecimalFP
, typename Char
,
2600 typename Grouping
= digit_grouping
<Char
>>
2601 FMT_CONSTEXPR20
auto do_write_float(OutputIt out
, const DecimalFP
& f
,
2602 const format_specs
<Char
>& specs
,
2603 float_specs fspecs
, locale_ref loc
)
2605 auto significand
= f
.significand
;
2606 int significand_size
= get_significand_size(f
);
2607 const Char zero
= static_cast<Char
>('0');
2608 auto sign
= fspecs
.sign
;
2609 size_t size
= to_unsigned(significand_size
) + (sign
? 1 : 0);
2610 using iterator
= reserve_iterator
<OutputIt
>;
2612 Char decimal_point
=
2613 fspecs
.locale
? detail::decimal_point
<Char
>(loc
) : static_cast<Char
>('.');
2615 int output_exp
= f
.exponent
+ significand_size
- 1;
2616 auto use_exp_format
= [=]() {
2617 if (fspecs
.format
== float_format::exp
) return true;
2618 if (fspecs
.format
!= float_format::general
) return false;
2619 // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
2620 // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
2621 const int exp_lower
= -4, exp_upper
= 16;
2622 return output_exp
< exp_lower
||
2623 output_exp
>= (fspecs
.precision
> 0 ? fspecs
.precision
: exp_upper
);
2625 if (use_exp_format()) {
2627 if (fspecs
.showpoint
) {
2628 num_zeros
= fspecs
.precision
- significand_size
;
2629 if (num_zeros
< 0) num_zeros
= 0;
2630 size
+= to_unsigned(num_zeros
);
2631 } else if (significand_size
== 1) {
2632 decimal_point
= Char();
2634 auto abs_output_exp
= output_exp
>= 0 ? output_exp
: -output_exp
;
2636 if (abs_output_exp
>= 100) exp_digits
= abs_output_exp
>= 1000 ? 4 : 3;
2638 size
+= to_unsigned((decimal_point
? 1 : 0) + 2 + exp_digits
);
2639 char exp_char
= fspecs
.upper
? 'E' : 'e';
2640 auto write
= [=](iterator it
) {
2641 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2642 // Insert a decimal point after the first digit and add an exponent.
2643 it
= write_significand(it
, significand
, significand_size
, 1,
2645 if (num_zeros
> 0) it
= detail::fill_n(it
, num_zeros
, zero
);
2646 *it
++ = static_cast<Char
>(exp_char
);
2647 return write_exponent
<Char
>(output_exp
, it
);
2649 return specs
.width
> 0 ? write_padded
<align::right
>(out
, specs
, size
, write
)
2650 : base_iterator(out
, write(reserve(out
, size
)));
2653 int exp
= f
.exponent
+ significand_size
;
2654 if (f
.exponent
>= 0) {
2655 // 1234e5 -> 123400000[.0+]
2656 size
+= to_unsigned(f
.exponent
);
2657 int num_zeros
= fspecs
.precision
- exp
;
2658 abort_fuzzing_if(num_zeros
> 5000);
2659 if (fspecs
.showpoint
) {
2661 if (num_zeros
<= 0 && fspecs
.format
!= float_format::fixed
) num_zeros
= 0;
2662 if (num_zeros
> 0) size
+= to_unsigned(num_zeros
);
2664 auto grouping
= Grouping(loc
, fspecs
.locale
);
2665 size
+= to_unsigned(grouping
.count_separators(exp
));
2666 return write_padded
<align::right
>(out
, specs
, size
, [&](iterator it
) {
2667 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2668 it
= write_significand
<Char
>(it
, significand
, significand_size
,
2669 f
.exponent
, grouping
);
2670 if (!fspecs
.showpoint
) return it
;
2671 *it
++ = decimal_point
;
2672 return num_zeros
> 0 ? detail::fill_n(it
, num_zeros
, zero
) : it
;
2674 } else if (exp
> 0) {
2675 // 1234e-2 -> 12.34[0+]
2676 int num_zeros
= fspecs
.showpoint
? fspecs
.precision
- significand_size
: 0;
2677 size
+= 1 + to_unsigned(num_zeros
> 0 ? num_zeros
: 0);
2678 auto grouping
= Grouping(loc
, fspecs
.locale
);
2679 size
+= to_unsigned(grouping
.count_separators(exp
));
2680 return write_padded
<align::right
>(out
, specs
, size
, [&](iterator it
) {
2681 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2682 it
= write_significand(it
, significand
, significand_size
, exp
,
2683 decimal_point
, grouping
);
2684 return num_zeros
> 0 ? detail::fill_n(it
, num_zeros
, zero
) : it
;
2687 // 1234e-6 -> 0.001234
2688 int num_zeros
= -exp
;
2689 if (significand_size
== 0 && fspecs
.precision
>= 0 &&
2690 fspecs
.precision
< num_zeros
) {
2691 num_zeros
= fspecs
.precision
;
2693 bool pointy
= num_zeros
!= 0 || significand_size
!= 0 || fspecs
.showpoint
;
2694 size
+= 1 + (pointy
? 1 : 0) + to_unsigned(num_zeros
);
2695 return write_padded
<align::right
>(out
, specs
, size
, [&](iterator it
) {
2696 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2698 if (!pointy
) return it
;
2699 *it
++ = decimal_point
;
2700 it
= detail::fill_n(it
, num_zeros
, zero
);
2701 return write_significand
<Char
>(it
, significand
, significand_size
);
2705 template <typename Char
> class fallback_digit_grouping
{
2707 constexpr fallback_digit_grouping(locale_ref
, bool) {}
2709 constexpr auto has_separator() const -> bool { return false; }
2711 constexpr auto count_separators(int) const -> int { return 0; }
2713 template <typename Out
, typename C
>
2714 constexpr auto apply(Out out
, basic_string_view
<C
>) const -> Out
{
2719 template <typename OutputIt
, typename DecimalFP
, typename Char
>
2720 FMT_CONSTEXPR20
auto write_float(OutputIt out
, const DecimalFP
& f
,
2721 const format_specs
<Char
>& specs
,
2722 float_specs fspecs
, locale_ref loc
)
2724 if (is_constant_evaluated()) {
2725 return do_write_float
<OutputIt
, DecimalFP
, Char
,
2726 fallback_digit_grouping
<Char
>>(out
, f
, specs
, fspecs
,
2729 return do_write_float(out
, f
, specs
, fspecs
, loc
);
2733 template <typename T
> constexpr auto isnan(T value
) -> bool {
2734 return !(value
>= value
); // std::isnan doesn't support __float128.
2737 template <typename T
, typename Enable
= void>
2738 struct has_isfinite
: std::false_type
{};
2740 template <typename T
>
2741 struct has_isfinite
<T
, enable_if_t
<sizeof(std::isfinite(T())) != 0>>
2742 : std::true_type
{};
2744 template <typename T
, FMT_ENABLE_IF(std::is_floating_point
<T
>::value
&&
2745 has_isfinite
<T
>::value
)>
2746 FMT_CONSTEXPR20
auto isfinite(T value
) -> bool {
2747 constexpr T inf
= T(std::numeric_limits
<double>::infinity());
2748 if (is_constant_evaluated())
2749 return !detail::isnan(value
) && value
< inf
&& value
> -inf
;
2750 return std::isfinite(value
);
2752 template <typename T
, FMT_ENABLE_IF(!has_isfinite
<T
>::value
)>
2753 FMT_CONSTEXPR
auto isfinite(T value
) -> bool {
2754 T inf
= T(std::numeric_limits
<double>::infinity());
2755 // std::isfinite doesn't support __float128.
2756 return !detail::isnan(value
) && value
< inf
&& value
> -inf
;
2759 template <typename T
, FMT_ENABLE_IF(is_floating_point
<T
>::value
)>
2760 FMT_INLINE FMT_CONSTEXPR
bool signbit(T value
) {
2761 if (is_constant_evaluated()) {
2762 #ifdef __cpp_if_constexpr
2763 if constexpr (std::numeric_limits
<double>::is_iec559
) {
2764 auto bits
= detail::bit_cast
<uint64_t>(static_cast<double>(value
));
2765 return (bits
>> (num_bits
<uint64_t>() - 1)) != 0;
2769 return std::signbit(static_cast<double>(value
));
2772 inline FMT_CONSTEXPR20
void adjust_precision(int& precision
, int exp10
) {
2773 // Adjust fixed precision by exponent because it is relative to decimal
2775 if (exp10
> 0 && precision
> max_value
<int>() - exp10
)
2776 FMT_THROW(format_error("number is too big"));
2782 // A bigint is stored as an array of bigits (big digits), with bigit at index
2783 // 0 being the least significant one.
2784 using bigit
= uint32_t;
2785 using double_bigit
= uint64_t;
2786 enum { bigits_capacity
= 32 };
2787 basic_memory_buffer
<bigit
, bigits_capacity
> bigits_
;
2790 FMT_CONSTEXPR20
auto operator[](int index
) const -> bigit
{
2791 return bigits_
[to_unsigned(index
)];
2793 FMT_CONSTEXPR20
auto operator[](int index
) -> bigit
& {
2794 return bigits_
[to_unsigned(index
)];
2797 static constexpr const int bigit_bits
= num_bits
<bigit
>();
2799 friend struct formatter
<bigint
>;
2801 FMT_CONSTEXPR20
void subtract_bigits(int index
, bigit other
, bigit
& borrow
) {
2802 auto result
= static_cast<double_bigit
>((*this)[index
]) - other
- borrow
;
2803 (*this)[index
] = static_cast<bigit
>(result
);
2804 borrow
= static_cast<bigit
>(result
>> (bigit_bits
* 2 - 1));
2807 FMT_CONSTEXPR20
void remove_leading_zeros() {
2808 int num_bigits
= static_cast<int>(bigits_
.size()) - 1;
2809 while (num_bigits
> 0 && (*this)[num_bigits
] == 0) --num_bigits
;
2810 bigits_
.resize(to_unsigned(num_bigits
+ 1));
2813 // Computes *this -= other assuming aligned bigints and *this >= other.
2814 FMT_CONSTEXPR20
void subtract_aligned(const bigint
& other
) {
2815 FMT_ASSERT(other
.exp_
>= exp_
, "unaligned bigints");
2816 FMT_ASSERT(compare(*this, other
) >= 0, "");
2818 int i
= other
.exp_
- exp_
;
2819 for (size_t j
= 0, n
= other
.bigits_
.size(); j
!= n
; ++i
, ++j
)
2820 subtract_bigits(i
, other
.bigits_
[j
], borrow
);
2821 while (borrow
> 0) subtract_bigits(i
, 0, borrow
);
2822 remove_leading_zeros();
2825 FMT_CONSTEXPR20
void multiply(uint32_t value
) {
2826 const double_bigit wide_value
= value
;
2828 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2829 double_bigit result
= bigits_
[i
] * wide_value
+ carry
;
2830 bigits_
[i
] = static_cast<bigit
>(result
);
2831 carry
= static_cast<bigit
>(result
>> bigit_bits
);
2833 if (carry
!= 0) bigits_
.push_back(carry
);
2836 template <typename UInt
, FMT_ENABLE_IF(std::is_same
<UInt
, uint64_t>::value
||
2837 std::is_same
<UInt
, uint128_t
>::value
)>
2838 FMT_CONSTEXPR20
void multiply(UInt value
) {
2840 conditional_t
<std::is_same
<UInt
, uint128_t
>::value
, uint64_t, uint32_t>;
2841 const int shift
= num_bits
<half_uint
>() - bigit_bits
;
2842 const UInt lower
= static_cast<half_uint
>(value
);
2843 const UInt upper
= value
>> num_bits
<half_uint
>();
2845 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2846 UInt result
= lower
* bigits_
[i
] + static_cast<bigit
>(carry
);
2847 carry
= (upper
* bigits_
[i
] << shift
) + (result
>> bigit_bits
) +
2848 (carry
>> bigit_bits
);
2849 bigits_
[i
] = static_cast<bigit
>(result
);
2851 while (carry
!= 0) {
2852 bigits_
.push_back(static_cast<bigit
>(carry
));
2853 carry
>>= bigit_bits
;
2857 template <typename UInt
, FMT_ENABLE_IF(std::is_same
<UInt
, uint64_t>::value
||
2858 std::is_same
<UInt
, uint128_t
>::value
)>
2859 FMT_CONSTEXPR20
void assign(UInt n
) {
2860 size_t num_bigits
= 0;
2862 bigits_
[num_bigits
++] = static_cast<bigit
>(n
);
2865 bigits_
.resize(num_bigits
);
2870 FMT_CONSTEXPR20
bigint() : exp_(0) {}
2871 explicit bigint(uint64_t n
) { assign(n
); }
2873 bigint(const bigint
&) = delete;
2874 void operator=(const bigint
&) = delete;
2876 FMT_CONSTEXPR20
void assign(const bigint
& other
) {
2877 auto size
= other
.bigits_
.size();
2878 bigits_
.resize(size
);
2879 auto data
= other
.bigits_
.data();
2880 copy_str
<bigit
>(data
, data
+ size
, bigits_
.data());
2884 template <typename Int
> FMT_CONSTEXPR20
void operator=(Int n
) {
2885 FMT_ASSERT(n
> 0, "");
2886 assign(uint64_or_128_t
<Int
>(n
));
2889 FMT_CONSTEXPR20
auto num_bigits() const -> int {
2890 return static_cast<int>(bigits_
.size()) + exp_
;
2893 FMT_NOINLINE FMT_CONSTEXPR20
auto operator<<=(int shift
) -> bigint
& {
2894 FMT_ASSERT(shift
>= 0, "");
2895 exp_
+= shift
/ bigit_bits
;
2896 shift
%= bigit_bits
;
2897 if (shift
== 0) return *this;
2899 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2900 bigit c
= bigits_
[i
] >> (bigit_bits
- shift
);
2901 bigits_
[i
] = (bigits_
[i
] << shift
) + carry
;
2904 if (carry
!= 0) bigits_
.push_back(carry
);
2908 template <typename Int
>
2909 FMT_CONSTEXPR20
auto operator*=(Int value
) -> bigint
& {
2910 FMT_ASSERT(value
> 0, "");
2911 multiply(uint32_or_64_or_128_t
<Int
>(value
));
2915 friend FMT_CONSTEXPR20
auto compare(const bigint
& lhs
, const bigint
& rhs
)
2917 int num_lhs_bigits
= lhs
.num_bigits(), num_rhs_bigits
= rhs
.num_bigits();
2918 if (num_lhs_bigits
!= num_rhs_bigits
)
2919 return num_lhs_bigits
> num_rhs_bigits
? 1 : -1;
2920 int i
= static_cast<int>(lhs
.bigits_
.size()) - 1;
2921 int j
= static_cast<int>(rhs
.bigits_
.size()) - 1;
2923 if (end
< 0) end
= 0;
2924 for (; i
>= end
; --i
, --j
) {
2925 bigit lhs_bigit
= lhs
[i
], rhs_bigit
= rhs
[j
];
2926 if (lhs_bigit
!= rhs_bigit
) return lhs_bigit
> rhs_bigit
? 1 : -1;
2928 if (i
!= j
) return i
> j
? 1 : -1;
2932 // Returns compare(lhs1 + lhs2, rhs).
2933 friend FMT_CONSTEXPR20
auto add_compare(const bigint
& lhs1
,
2934 const bigint
& lhs2
, const bigint
& rhs
)
2936 auto minimum
= [](int a
, int b
) { return a
< b
? a
: b
; };
2937 auto maximum
= [](int a
, int b
) { return a
> b
? a
: b
; };
2938 int max_lhs_bigits
= maximum(lhs1
.num_bigits(), lhs2
.num_bigits());
2939 int num_rhs_bigits
= rhs
.num_bigits();
2940 if (max_lhs_bigits
+ 1 < num_rhs_bigits
) return -1;
2941 if (max_lhs_bigits
> num_rhs_bigits
) return 1;
2942 auto get_bigit
= [](const bigint
& n
, int i
) -> bigit
{
2943 return i
>= n
.exp_
&& i
< n
.num_bigits() ? n
[i
- n
.exp_
] : 0;
2945 double_bigit borrow
= 0;
2946 int min_exp
= minimum(minimum(lhs1
.exp_
, lhs2
.exp_
), rhs
.exp_
);
2947 for (int i
= num_rhs_bigits
- 1; i
>= min_exp
; --i
) {
2949 static_cast<double_bigit
>(get_bigit(lhs1
, i
)) + get_bigit(lhs2
, i
);
2950 bigit rhs_bigit
= get_bigit(rhs
, i
);
2951 if (sum
> rhs_bigit
+ borrow
) return 1;
2952 borrow
= rhs_bigit
+ borrow
- sum
;
2953 if (borrow
> 1) return -1;
2954 borrow
<<= bigit_bits
;
2956 return borrow
!= 0 ? -1 : 0;
2959 // Assigns pow(10, exp) to this bigint.
2960 FMT_CONSTEXPR20
void assign_pow10(int exp
) {
2961 FMT_ASSERT(exp
>= 0, "");
2962 if (exp
== 0) return *this = 1;
2963 // Find the top bit.
2965 while (exp
>= bitmask
) bitmask
<<= 1;
2967 // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
2968 // repeated squaring and multiplication.
2971 while (bitmask
!= 0) {
2973 if ((exp
& bitmask
) != 0) *this *= 5;
2976 *this <<= exp
; // Multiply by pow(2, exp) by shifting.
2979 FMT_CONSTEXPR20
void square() {
2980 int num_bigits
= static_cast<int>(bigits_
.size());
2981 int num_result_bigits
= 2 * num_bigits
;
2982 basic_memory_buffer
<bigit
, bigits_capacity
> n(std::move(bigits_
));
2983 bigits_
.resize(to_unsigned(num_result_bigits
));
2984 auto sum
= uint128_t();
2985 for (int bigit_index
= 0; bigit_index
< num_bigits
; ++bigit_index
) {
2986 // Compute bigit at position bigit_index of the result by adding
2987 // cross-product terms n[i] * n[j] such that i + j == bigit_index.
2988 for (int i
= 0, j
= bigit_index
; j
>= 0; ++i
, --j
) {
2989 // Most terms are multiplied twice which can be optimized in the future.
2990 sum
+= static_cast<double_bigit
>(n
[i
]) * n
[j
];
2992 (*this)[bigit_index
] = static_cast<bigit
>(sum
);
2993 sum
>>= num_bits
<bigit
>(); // Compute the carry.
2995 // Do the same for the top half.
2996 for (int bigit_index
= num_bigits
; bigit_index
< num_result_bigits
;
2998 for (int j
= num_bigits
- 1, i
= bigit_index
- j
; i
< num_bigits
;)
2999 sum
+= static_cast<double_bigit
>(n
[i
++]) * n
[j
--];
3000 (*this)[bigit_index
] = static_cast<bigit
>(sum
);
3001 sum
>>= num_bits
<bigit
>();
3003 remove_leading_zeros();
3007 // If this bigint has a bigger exponent than other, adds trailing zero to make
3008 // exponents equal. This simplifies some operations such as subtraction.
3009 FMT_CONSTEXPR20
void align(const bigint
& other
) {
3010 int exp_difference
= exp_
- other
.exp_
;
3011 if (exp_difference
<= 0) return;
3012 int num_bigits
= static_cast<int>(bigits_
.size());
3013 bigits_
.resize(to_unsigned(num_bigits
+ exp_difference
));
3014 for (int i
= num_bigits
- 1, j
= i
+ exp_difference
; i
>= 0; --i
, --j
)
3015 bigits_
[j
] = bigits_
[i
];
3016 std::uninitialized_fill_n(bigits_
.data(), exp_difference
, 0u);
3017 exp_
-= exp_difference
;
3020 // Divides this bignum by divisor, assigning the remainder to this and
3021 // returning the quotient.
3022 FMT_CONSTEXPR20
auto divmod_assign(const bigint
& divisor
) -> int {
3023 FMT_ASSERT(this != &divisor
, "");
3024 if (compare(*this, divisor
) < 0) return 0;
3025 FMT_ASSERT(divisor
.bigits_
[divisor
.bigits_
.size() - 1u] != 0, "");
3029 subtract_aligned(divisor
);
3031 } while (compare(*this, divisor
) >= 0);
3036 // format_dragon flags.
3038 predecessor_closer
= 1,
3039 fixup
= 2, // Run fixup to correct exp10 which can be off by one.
3043 // Formats a floating-point number using a variation of the Fixed-Precision
3044 // Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
3045 // https://fmt.dev/papers/p372-steele.pdf.
3046 FMT_CONSTEXPR20
inline void format_dragon(basic_fp
<uint128_t
> value
,
3047 unsigned flags
, int num_digits
,
3048 buffer
<char>& buf
, int& exp10
) {
3049 bigint numerator
; // 2 * R in (FPP)^2.
3050 bigint denominator
; // 2 * S in (FPP)^2.
3051 // lower and upper are differences between value and corresponding boundaries.
3052 bigint lower
; // (M^- in (FPP)^2).
3053 bigint upper_store
; // upper's value if different from lower.
3054 bigint
* upper
= nullptr; // (M^+ in (FPP)^2).
3055 // Shift numerator and denominator by an extra bit or two (if lower boundary
3056 // is closer) to make lower and upper integers. This eliminates multiplication
3057 // by 2 during later computations.
3058 bool is_predecessor_closer
= (flags
& dragon::predecessor_closer
) != 0;
3059 int shift
= is_predecessor_closer
? 2 : 1;
3061 numerator
= value
.f
;
3062 numerator
<<= value
.e
+ shift
;
3065 if (is_predecessor_closer
) {
3067 upper_store
<<= value
.e
+ 1;
3068 upper
= &upper_store
;
3070 denominator
.assign_pow10(exp10
);
3071 denominator
<<= shift
;
3072 } else if (exp10
< 0) {
3073 numerator
.assign_pow10(-exp10
);
3074 lower
.assign(numerator
);
3075 if (is_predecessor_closer
) {
3076 upper_store
.assign(numerator
);
3078 upper
= &upper_store
;
3080 numerator
*= value
.f
;
3081 numerator
<<= shift
;
3083 denominator
<<= shift
- value
.e
;
3085 numerator
= value
.f
;
3086 numerator
<<= shift
;
3087 denominator
.assign_pow10(exp10
);
3088 denominator
<<= shift
- value
.e
;
3090 if (is_predecessor_closer
) {
3091 upper_store
= 1ULL << 1;
3092 upper
= &upper_store
;
3095 int even
= static_cast<int>((value
.f
& 1) == 0);
3096 if (!upper
) upper
= &lower
;
3097 bool shortest
= num_digits
< 0;
3098 if ((flags
& dragon::fixup
) != 0) {
3099 if (add_compare(numerator
, *upper
, denominator
) + even
<= 0) {
3102 if (num_digits
< 0) {
3104 if (upper
!= &lower
) *upper
*= 10;
3107 if ((flags
& dragon::fixed
) != 0) adjust_precision(num_digits
, exp10
+ 1);
3109 // Invariant: value == (numerator / denominator) * pow(10, exp10).
3111 // Generate the shortest representation.
3113 char* data
= buf
.data();
3115 int digit
= numerator
.divmod_assign(denominator
);
3116 bool low
= compare(numerator
, lower
) - even
< 0; // numerator <[=] lower.
3117 // numerator + upper >[=] pow10:
3118 bool high
= add_compare(numerator
, *upper
, denominator
) + even
> 0;
3119 data
[num_digits
++] = static_cast<char>('0' + digit
);
3122 ++data
[num_digits
- 1];
3124 int result
= add_compare(numerator
, numerator
, denominator
);
3125 // Round half to even.
3126 if (result
> 0 || (result
== 0 && (digit
% 2) != 0))
3127 ++data
[num_digits
- 1];
3129 buf
.try_resize(to_unsigned(num_digits
));
3130 exp10
-= num_digits
- 1;
3135 if (upper
!= &lower
) *upper
*= 10;
3138 // Generate the given number of digits.
3139 exp10
-= num_digits
- 1;
3140 if (num_digits
<= 0) {
3142 auto digit
= add_compare(numerator
, numerator
, denominator
) > 0 ? '1' : '0';
3143 buf
.push_back(digit
);
3146 buf
.try_resize(to_unsigned(num_digits
));
3147 for (int i
= 0; i
< num_digits
- 1; ++i
) {
3148 int digit
= numerator
.divmod_assign(denominator
);
3149 buf
[i
] = static_cast<char>('0' + digit
);
3152 int digit
= numerator
.divmod_assign(denominator
);
3153 auto result
= add_compare(numerator
, numerator
, denominator
);
3154 if (result
> 0 || (result
== 0 && (digit
% 2) != 0)) {
3156 const auto overflow
= '0' + 10;
3157 buf
[num_digits
- 1] = overflow
;
3158 // Propagate the carry.
3159 for (int i
= num_digits
- 1; i
> 0 && buf
[i
] == overflow
; --i
) {
3163 if (buf
[0] == overflow
) {
3165 if ((flags
& dragon::fixed
) != 0)
3174 buf
[num_digits
- 1] = static_cast<char>('0' + digit
);
3177 // Formats a floating-point number using the hexfloat format.
3178 template <typename Float
, FMT_ENABLE_IF(!is_double_double
<Float
>::value
)>
3179 FMT_CONSTEXPR20
void format_hexfloat(Float value
, int precision
,
3180 float_specs specs
, buffer
<char>& buf
) {
3181 // float is passed as double to reduce the number of instantiations and to
3182 // simplify implementation.
3183 static_assert(!std::is_same
<Float
, float>::value
, "");
3185 using info
= dragonbox::float_info
<Float
>;
3187 // Assume Float is in the format [sign][exponent][significand].
3188 using carrier_uint
= typename
info::carrier_uint
;
3190 constexpr auto num_float_significand_bits
=
3191 detail::num_significand_bits
<Float
>();
3193 basic_fp
<carrier_uint
> f(value
);
3194 f
.e
+= num_float_significand_bits
;
3195 if (!has_implicit_bit
<Float
>()) --f
.e
;
3197 constexpr auto num_fraction_bits
=
3198 num_float_significand_bits
+ (has_implicit_bit
<Float
>() ? 1 : 0);
3199 constexpr auto num_xdigits
= (num_fraction_bits
+ 3) / 4;
3201 constexpr auto leading_shift
= ((num_xdigits
- 1) * 4);
3202 const auto leading_mask
= carrier_uint(0xF) << leading_shift
;
3203 const auto leading_xdigit
=
3204 static_cast<uint32_t>((f
.f
& leading_mask
) >> leading_shift
);
3205 if (leading_xdigit
> 1) f
.e
-= (32 - countl_zero(leading_xdigit
) - 1);
3207 int print_xdigits
= num_xdigits
- 1;
3208 if (precision
>= 0 && print_xdigits
> precision
) {
3209 const int shift
= ((print_xdigits
- precision
- 1) * 4);
3210 const auto mask
= carrier_uint(0xF) << shift
;
3211 const auto v
= static_cast<uint32_t>((f
.f
& mask
) >> shift
);
3214 const auto inc
= carrier_uint(1) << (shift
+ 4);
3219 // Check long double overflow
3220 if (!has_implicit_bit
<Float
>()) {
3221 const auto implicit_bit
= carrier_uint(1) << num_float_significand_bits
;
3222 if ((f
.f
& implicit_bit
) == implicit_bit
) {
3228 print_xdigits
= precision
;
3231 char xdigits
[num_bits
<carrier_uint
>() / 4];
3232 detail::fill_n(xdigits
, sizeof(xdigits
), '0');
3233 format_uint
<4>(xdigits
, f
.f
, num_xdigits
, specs
.upper
);
3236 while (print_xdigits
> 0 && xdigits
[print_xdigits
] == '0') --print_xdigits
;
3239 buf
.push_back(specs
.upper
? 'X' : 'x');
3240 buf
.push_back(xdigits
[0]);
3241 if (specs
.showpoint
|| print_xdigits
> 0 || print_xdigits
< precision
)
3243 buf
.append(xdigits
+ 1, xdigits
+ 1 + print_xdigits
);
3244 for (; print_xdigits
< precision
; ++print_xdigits
) buf
.push_back('0');
3246 buf
.push_back(specs
.upper
? 'P' : 'p');
3251 abs_e
= static_cast<uint32_t>(-f
.e
);
3254 abs_e
= static_cast<uint32_t>(f
.e
);
3256 format_decimal
<char>(appender(buf
), abs_e
, detail::count_digits(abs_e
));
3259 template <typename Float
, FMT_ENABLE_IF(is_double_double
<Float
>::value
)>
3260 FMT_CONSTEXPR20
void format_hexfloat(Float value
, int precision
,
3261 float_specs specs
, buffer
<char>& buf
) {
3262 format_hexfloat(static_cast<double>(value
), precision
, specs
, buf
);
3265 constexpr auto fractional_part_rounding_thresholds(int index
) -> uint32_t {
3266 // For checking rounding thresholds.
3267 // The kth entry is chosen to be the smallest integer such that the
3268 // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k.
3269 // It is equal to ceil(2^31 + 2^32/10^(k + 1)).
3270 // These are stored in a string literal because we cannot have static arrays
3271 // in constexpr functions and non-static ones are poorly optimized.
3272 return U
"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
3273 U
"\x800001ae\x8000002b"[index
];
3276 template <typename Float
>
3277 FMT_CONSTEXPR20
auto format_float(Float value
, int precision
, float_specs specs
,
3278 buffer
<char>& buf
) -> int {
3279 // float is passed as double to reduce the number of instantiations.
3280 static_assert(!std::is_same
<Float
, float>::value
, "");
3281 FMT_ASSERT(value
>= 0, "value is negative");
3282 auto converted_value
= convert_float(value
);
3284 const bool fixed
= specs
.format
== float_format::fixed
;
3285 if (value
<= 0) { // <= instead of == to silence a warning.
3286 if (precision
<= 0 || !fixed
) {
3290 buf
.try_resize(to_unsigned(precision
));
3291 fill_n(buf
.data(), precision
, '0');
3296 bool use_dragon
= true;
3297 unsigned dragon_flags
= 0;
3298 if (!is_fast_float
<Float
>() || is_constant_evaluated()) {
3299 const auto inv_log2_10
= 0.3010299956639812; // 1 / log2(10)
3300 using info
= dragonbox::float_info
<decltype(converted_value
)>;
3301 const auto f
= basic_fp
<typename
info::carrier_uint
>(converted_value
);
3302 // Compute exp, an approximate power of 10, such that
3303 // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
3304 // This is based on log10(value) == log2(value) / log2(10) and approximation
3305 // of log2(value) by e + num_fraction_bits idea from double-conversion.
3306 auto e
= (f
.e
+ count_digits
<1>(f
.f
) - 1) * inv_log2_10
- 1e-10;
3307 exp
= static_cast<int>(e
);
3308 if (e
> exp
) ++exp
; // Compute ceil.
3309 dragon_flags
= dragon::fixup
;
3310 } else if (precision
< 0) {
3311 // Use Dragonbox for the shortest format.
3312 if (specs
.binary32
) {
3313 auto dec
= dragonbox::to_decimal(static_cast<float>(value
));
3314 write
<char>(buffer_appender
<char>(buf
), dec
.significand
);
3315 return dec
.exponent
;
3317 auto dec
= dragonbox::to_decimal(static_cast<double>(value
));
3318 write
<char>(buffer_appender
<char>(buf
), dec
.significand
);
3319 return dec
.exponent
;
3321 // Extract significand bits and exponent bits.
3322 using info
= dragonbox::float_info
<double>;
3323 auto br
= bit_cast
<uint64_t>(static_cast<double>(value
));
3325 const uint64_t significand_mask
=
3326 (static_cast<uint64_t>(1) << num_significand_bits
<double>()) - 1;
3327 uint64_t significand
= (br
& significand_mask
);
3328 int exponent
= static_cast<int>((br
& exponent_mask
<double>()) >>
3329 num_significand_bits
<double>());
3331 if (exponent
!= 0) { // Check if normal.
3332 exponent
-= exponent_bias
<double>() + num_significand_bits
<double>();
3334 (static_cast<uint64_t>(1) << num_significand_bits
<double>());
3337 // Normalize subnormal inputs.
3338 FMT_ASSERT(significand
!= 0, "zeros should not appear here");
3339 int shift
= countl_zero(significand
);
3340 FMT_ASSERT(shift
>= num_bits
<uint64_t>() - num_significand_bits
<double>(),
3342 shift
-= (num_bits
<uint64_t>() - num_significand_bits
<double>() - 2);
3343 exponent
= (std::numeric_limits
<double>::min_exponent
-
3344 num_significand_bits
<double>()) -
3346 significand
<<= shift
;
3349 // Compute the first several nonzero decimal significand digits.
3350 // We call the number we get the first segment.
3351 const int k
= info::kappa
- dragonbox::floor_log10_pow2(exponent
);
3353 const int beta
= exponent
+ dragonbox::floor_log2_pow10(k
);
3354 uint64_t first_segment
;
3355 bool has_more_segments
;
3356 int digits_in_the_first_segment
;
3358 const auto r
= dragonbox::umul192_upper128(
3359 significand
<< beta
, dragonbox::get_cached_power(k
));
3360 first_segment
= r
.high();
3361 has_more_segments
= r
.low() != 0;
3363 // The first segment can have 18 ~ 19 digits.
3364 if (first_segment
>= 1000000000000000000ULL) {
3365 digits_in_the_first_segment
= 19;
3367 // When it is of 18-digits, we align it to 19-digits by adding a bogus
3369 digits_in_the_first_segment
= 18;
3370 first_segment
*= 10;
3374 // Compute the actual number of decimal digits to print.
3375 if (fixed
) adjust_precision(precision
, exp
+ digits_in_the_first_segment
);
3377 // Use Dragon4 only when there might be not enough digits in the first
3379 if (digits_in_the_first_segment
> precision
) {
3382 if (precision
<= 0) {
3383 exp
+= digits_in_the_first_segment
;
3385 if (precision
< 0) {
3386 // Nothing to do, since all we have are just leading zeros.
3389 // We may need to round-up.
3391 if ((first_segment
| static_cast<uint64_t>(has_more_segments
)) >
3392 5000000000000000000ULL) {
3400 exp
+= digits_in_the_first_segment
- precision
;
3402 // When precision > 0, we divide the first segment into three
3403 // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits
3404 // in 32-bits which usually allows faster calculation than in
3405 // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize
3406 // division-by-constant for large 64-bit divisors, we do it here
3407 // manually. The magic number 7922816251426433760 below is equal to
3408 // ceil(2^(64+32) / 10^10).
3409 const uint32_t first_subsegment
= static_cast<uint32_t>(
3410 dragonbox::umul128_upper64(first_segment
, 7922816251426433760ULL) >>
3412 const uint64_t second_third_subsegments
=
3413 first_segment
- first_subsegment
* 10000000000ULL;
3417 bool should_round_up
;
3418 int number_of_digits_to_print
= precision
> 9 ? 9 : precision
;
3420 // Print a 9-digits subsegment, either the first or the second.
3421 auto print_subsegment
= [&](uint32_t subsegment
, char* buffer
) {
3422 int number_of_digits_printed
= 0;
3424 // If we want to print an odd number of digits from the subsegment,
3425 if ((number_of_digits_to_print
& 1) != 0) {
3426 // Convert to 64-bit fixed-point fractional form with 1-digit
3427 // integer part. The magic number 720575941 is a good enough
3428 // approximation of 2^(32 + 24) / 10^8; see
3429 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3431 prod
= ((subsegment
* static_cast<uint64_t>(720575941)) >> 24) + 1;
3432 digits
= static_cast<uint32_t>(prod
>> 32);
3433 *buffer
= static_cast<char>('0' + digits
);
3434 number_of_digits_printed
++;
3436 // If we want to print an even number of digits from the
3437 // first_subsegment,
3439 // Convert to 64-bit fixed-point fractional form with 2-digits
3440 // integer part. The magic number 450359963 is a good enough
3441 // approximation of 2^(32 + 20) / 10^7; see
3442 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3444 prod
= ((subsegment
* static_cast<uint64_t>(450359963)) >> 20) + 1;
3445 digits
= static_cast<uint32_t>(prod
>> 32);
3446 copy2(buffer
, digits2(digits
));
3447 number_of_digits_printed
+= 2;
3450 // Print all digit pairs.
3451 while (number_of_digits_printed
< number_of_digits_to_print
) {
3452 prod
= static_cast<uint32_t>(prod
) * static_cast<uint64_t>(100);
3453 digits
= static_cast<uint32_t>(prod
>> 32);
3454 copy2(buffer
+ number_of_digits_printed
, digits2(digits
));
3455 number_of_digits_printed
+= 2;
3459 // Print first subsegment.
3460 print_subsegment(first_subsegment
, buf
.data());
3462 // Perform rounding if the first subsegment is the last subsegment to
3464 if (precision
<= 9) {
3465 // Rounding inside the subsegment.
3467 // - either the fractional part is strictly larger than 1/2, or
3468 // - the fractional part is exactly 1/2 and the last digit is odd.
3469 // We rely on the following observations:
3470 // - If fractional_part >= threshold, then the fractional part is
3471 // strictly larger than 1/2.
3472 // - If the MSB of fractional_part is set, then the fractional part
3473 // must be at least 1/2.
3474 // - When the MSB of fractional_part is set, either
3475 // second_third_subsegments being nonzero or has_more_segments
3476 // being true means there are further digits not printed, so the
3477 // fractional part is strictly larger than 1/2.
3478 if (precision
< 9) {
3479 uint32_t fractional_part
= static_cast<uint32_t>(prod
);
3481 fractional_part
>= fractional_part_rounding_thresholds(
3482 8 - number_of_digits_to_print
) ||
3483 ((fractional_part
>> 31) &
3484 ((digits
& 1) | (second_third_subsegments
!= 0) |
3485 has_more_segments
)) != 0;
3487 // Rounding at the subsegment boundary.
3488 // In this case, the fractional part is at least 1/2 if and only if
3489 // second_third_subsegments >= 5000000000ULL, and is strictly larger
3490 // than 1/2 if we further have either second_third_subsegments >
3491 // 5000000000ULL or has_more_segments == true.
3493 should_round_up
= second_third_subsegments
> 5000000000ULL ||
3494 (second_third_subsegments
== 5000000000ULL &&
3495 ((digits
& 1) != 0 || has_more_segments
));
3498 // Otherwise, print the second subsegment.
3500 // Compilers are not aware of how to leverage the maximum value of
3501 // second_third_subsegments to find out a better magic number which
3502 // allows us to eliminate an additional shift. 1844674407370955162 =
3503 // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))).
3504 const uint32_t second_subsegment
=
3505 static_cast<uint32_t>(dragonbox::umul128_upper64(
3506 second_third_subsegments
, 1844674407370955162ULL));
3507 const uint32_t third_subsegment
=
3508 static_cast<uint32_t>(second_third_subsegments
) -
3509 second_subsegment
* 10;
3511 number_of_digits_to_print
= precision
- 9;
3512 print_subsegment(second_subsegment
, buf
.data() + 9);
3514 // Rounding inside the subsegment.
3515 if (precision
< 18) {
3516 // The condition third_subsegment != 0 implies that the segment was
3517 // of 19 digits, so in this case the third segment should be
3518 // consisting of a genuine digit from the input.
3519 uint32_t fractional_part
= static_cast<uint32_t>(prod
);
3521 fractional_part
>= fractional_part_rounding_thresholds(
3522 8 - number_of_digits_to_print
) ||
3523 ((fractional_part
>> 31) &
3524 ((digits
& 1) | (third_subsegment
!= 0) |
3525 has_more_segments
)) != 0;
3527 // Rounding at the subsegment boundary.
3529 // In this case, the segment must be of 19 digits, thus
3530 // the third subsegment should be consisting of a genuine digit from
3532 should_round_up
= third_subsegment
> 5 ||
3533 (third_subsegment
== 5 &&
3534 ((digits
& 1) != 0 || has_more_segments
));
3538 // Round-up if necessary.
3539 if (should_round_up
) {
3540 ++buf
[precision
- 1];
3541 for (int i
= precision
- 1; i
> 0 && buf
[i
] > '9'; --i
) {
3548 buf
[precision
++] = '0';
3553 buf
.try_resize(to_unsigned(precision
));
3555 } // if (digits_in_the_first_segment > precision)
3557 // Adjust the exponent for its use in Dragon4.
3558 exp
+= digits_in_the_first_segment
- 1;
3562 auto f
= basic_fp
<uint128_t
>();
3563 bool is_predecessor_closer
= specs
.binary32
3564 ? f
.assign(static_cast<float>(value
))
3565 : f
.assign(converted_value
);
3566 if (is_predecessor_closer
) dragon_flags
|= dragon::predecessor_closer
;
3567 if (fixed
) dragon_flags
|= dragon::fixed
;
3568 // Limit precision to the maximum possible number of significant digits in
3569 // an IEEE754 double because we don't need to generate zeros.
3570 const int max_double_digits
= 767;
3571 if (precision
> max_double_digits
) precision
= max_double_digits
;
3572 format_dragon(f
, dragon_flags
, precision
, buf
, exp
);
3574 if (!fixed
&& !specs
.showpoint
) {
3575 // Remove trailing zeros.
3576 auto num_digits
= buf
.size();
3577 while (num_digits
> 0 && buf
[num_digits
- 1] == '0') {
3581 buf
.try_resize(num_digits
);
3585 template <typename Char
, typename OutputIt
, typename T
>
3586 FMT_CONSTEXPR20
auto write_float(OutputIt out
, T value
,
3587 format_specs
<Char
> specs
, locale_ref loc
)
3589 float_specs fspecs
= parse_float_type_spec(specs
);
3590 fspecs
.sign
= specs
.sign
;
3591 if (detail::signbit(value
)) { // value < 0 is false for NaN so use signbit.
3592 fspecs
.sign
= sign::minus
;
3594 } else if (fspecs
.sign
== sign::minus
) {
3595 fspecs
.sign
= sign::none
;
3598 if (!detail::isfinite(value
))
3599 return write_nonfinite(out
, detail::isnan(value
), specs
, fspecs
);
3601 if (specs
.align
== align::numeric
&& fspecs
.sign
) {
3602 auto it
= reserve(out
, 1);
3603 *it
++ = detail::sign
<Char
>(fspecs
.sign
);
3604 out
= base_iterator(out
, it
);
3605 fspecs
.sign
= sign::none
;
3606 if (specs
.width
!= 0) --specs
.width
;
3609 memory_buffer buffer
;
3610 if (fspecs
.format
== float_format::hex
) {
3611 if (fspecs
.sign
) buffer
.push_back(detail::sign
<char>(fspecs
.sign
));
3612 format_hexfloat(convert_float(value
), specs
.precision
, fspecs
, buffer
);
3613 return write_bytes
<align::right
>(out
, {buffer
.data(), buffer
.size()},
3616 int precision
= specs
.precision
>= 0 || specs
.type
== presentation_type::none
3619 if (fspecs
.format
== float_format::exp
) {
3620 if (precision
== max_value
<int>())
3621 throw_format_error("number is too big");
3624 } else if (fspecs
.format
!= float_format::fixed
&& precision
== 0) {
3627 if (const_check(std::is_same
<T
, float>())) fspecs
.binary32
= true;
3628 int exp
= format_float(convert_float(value
), precision
, fspecs
, buffer
);
3629 fspecs
.precision
= precision
;
3630 auto f
= big_decimal_fp
{buffer
.data(), static_cast<int>(buffer
.size()), exp
};
3631 return write_float(out
, f
, specs
, fspecs
, loc
);
3634 template <typename Char
, typename OutputIt
, typename T
,
3635 FMT_ENABLE_IF(is_floating_point
<T
>::value
)>
3636 FMT_CONSTEXPR20
auto write(OutputIt out
, T value
, format_specs
<Char
> specs
,
3637 locale_ref loc
= {}) -> OutputIt
{
3638 if (const_check(!is_supported_floating_point(value
))) return out
;
3639 return specs
.localized
&& write_loc(out
, value
, specs
, loc
)
3641 : write_float(out
, value
, specs
, loc
);
3644 template <typename Char
, typename OutputIt
, typename T
,
3645 FMT_ENABLE_IF(is_fast_float
<T
>::value
)>
3646 FMT_CONSTEXPR20
auto write(OutputIt out
, T value
) -> OutputIt
{
3647 if (is_constant_evaluated()) return write(out
, value
, format_specs
<Char
>());
3648 if (const_check(!is_supported_floating_point(value
))) return out
;
3650 auto fspecs
= float_specs();
3651 if (detail::signbit(value
)) {
3652 fspecs
.sign
= sign::minus
;
3656 constexpr auto specs
= format_specs
<Char
>();
3657 using floaty
= conditional_t
<std::is_same
<T
, long double>::value
, double, T
>;
3658 using floaty_uint
= typename
dragonbox::float_info
<floaty
>::carrier_uint
;
3659 floaty_uint mask
= exponent_mask
<floaty
>();
3660 if ((bit_cast
<floaty_uint
>(value
) & mask
) == mask
)
3661 return write_nonfinite(out
, std::isnan(value
), specs
, fspecs
);
3663 auto dec
= dragonbox::to_decimal(static_cast<floaty
>(value
));
3664 return write_float(out
, dec
, specs
, fspecs
, {});
3667 template <typename Char
, typename OutputIt
, typename T
,
3668 FMT_ENABLE_IF(is_floating_point
<T
>::value
&&
3669 !is_fast_float
<T
>::value
)>
3670 inline auto write(OutputIt out
, T value
) -> OutputIt
{
3671 return write(out
, value
, format_specs
<Char
>());
3674 template <typename Char
, typename OutputIt
>
3675 auto write(OutputIt out
, monostate
, format_specs
<Char
> = {}, locale_ref
= {})
3677 FMT_ASSERT(false, "");
3681 template <typename Char
, typename OutputIt
>
3682 FMT_CONSTEXPR
auto write(OutputIt out
, basic_string_view
<Char
> value
)
3684 auto it
= reserve(out
, value
.size());
3685 it
= copy_str_noinline
<Char
>(value
.begin(), value
.end(), it
);
3686 return base_iterator(out
, it
);
3689 template <typename Char
, typename OutputIt
, typename T
,
3690 FMT_ENABLE_IF(is_string
<T
>::value
)>
3691 constexpr auto write(OutputIt out
, const T
& value
) -> OutputIt
{
3692 return write
<Char
>(out
, to_string_view(value
));
3695 // FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
3697 typename Char
, typename OutputIt
, typename T
,
3699 std::is_enum
<T
>::value
&& !std::is_same
<T
, Char
>::value
&&
3700 mapped_type_constant
<T
, basic_format_context
<OutputIt
, Char
>>::value
!=
3702 FMT_ENABLE_IF(check
)>
3703 FMT_CONSTEXPR
auto write(OutputIt out
, T value
) -> OutputIt
{
3704 return write
<Char
>(out
, static_cast<underlying_t
<T
>>(value
));
3707 template <typename Char
, typename OutputIt
, typename T
,
3708 FMT_ENABLE_IF(std::is_same
<T
, bool>::value
)>
3709 FMT_CONSTEXPR
auto write(OutputIt out
, T value
,
3710 const format_specs
<Char
>& specs
= {}, locale_ref
= {})
3712 return specs
.type
!= presentation_type::none
&&
3713 specs
.type
!= presentation_type::string
3714 ? write(out
, value
? 1 : 0, specs
, {})
3715 : write_bytes(out
, value
? "true" : "false", specs
);
3718 template <typename Char
, typename OutputIt
>
3719 FMT_CONSTEXPR
auto write(OutputIt out
, Char value
) -> OutputIt
{
3720 auto it
= reserve(out
, 1);
3722 return base_iterator(out
, it
);
3725 template <typename Char
, typename OutputIt
>
3726 FMT_CONSTEXPR_CHAR_TRAITS
auto write(OutputIt out
, const Char
* value
)
3728 if (value
) return write(out
, basic_string_view
<Char
>(value
));
3729 throw_format_error("string pointer is null");
3733 template <typename Char
, typename OutputIt
, typename T
,
3734 FMT_ENABLE_IF(std::is_same
<T
, void>::value
)>
3735 auto write(OutputIt out
, const T
* value
, const format_specs
<Char
>& specs
= {},
3736 locale_ref
= {}) -> OutputIt
{
3737 return write_ptr
<Char
>(out
, bit_cast
<uintptr_t>(value
), &specs
);
3740 // A write overload that handles implicit conversions.
3741 template <typename Char
, typename OutputIt
, typename T
,
3742 typename Context
= basic_format_context
<OutputIt
, Char
>>
3743 FMT_CONSTEXPR
auto write(OutputIt out
, const T
& value
) -> enable_if_t
<
3744 std::is_class
<T
>::value
&& !is_string
<T
>::value
&&
3745 !is_floating_point
<T
>::value
&& !std::is_same
<T
, Char
>::value
&&
3746 !std::is_same
<T
, remove_cvref_t
<decltype(arg_mapper
<Context
>().map(
3749 return write
<Char
>(out
, arg_mapper
<Context
>().map(value
));
3752 template <typename Char
, typename OutputIt
, typename T
,
3753 typename Context
= basic_format_context
<OutputIt
, Char
>>
3754 FMT_CONSTEXPR
auto write(OutputIt out
, const T
& value
)
3755 -> enable_if_t
<mapped_type_constant
<T
, Context
>::value
== type::custom_type
,
3757 auto formatter
= typename
Context::template formatter_type
<T
>();
3758 auto parse_ctx
= typename
Context::parse_context_type({});
3759 formatter
.parse(parse_ctx
);
3760 auto ctx
= Context(out
, {}, {});
3761 return formatter
.format(value
, ctx
);
3764 // An argument visitor that formats the argument and writes it via the output
3765 // iterator. It's a class and not a generic lambda for compatibility with C++11.
3766 template <typename Char
> struct default_arg_formatter
{
3767 using iterator
= buffer_appender
<Char
>;
3768 using context
= buffer_context
<Char
>;
3771 basic_format_args
<context
> args
;
3774 template <typename T
> auto operator()(T value
) -> iterator
{
3775 return write
<Char
>(out
, value
);
3777 auto operator()(typename basic_format_arg
<context
>::handle h
) -> iterator
{
3778 basic_format_parse_context
<Char
> parse_ctx({});
3779 context
format_ctx(out
, args
, loc
);
3780 h
.format(parse_ctx
, format_ctx
);
3781 return format_ctx
.out();
3785 template <typename Char
> struct arg_formatter
{
3786 using iterator
= buffer_appender
<Char
>;
3787 using context
= buffer_context
<Char
>;
3790 const format_specs
<Char
>& specs
;
3793 template <typename T
>
3794 FMT_CONSTEXPR FMT_INLINE
auto operator()(T value
) -> iterator
{
3795 return detail::write(out
, value
, specs
, locale
);
3797 auto operator()(typename basic_format_arg
<context
>::handle
) -> iterator
{
3798 // User-defined types are handled separately because they require access
3799 // to the parse context.
3804 struct width_checker
{
3805 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
3806 FMT_CONSTEXPR
auto operator()(T value
) -> unsigned long long {
3807 if (is_negative(value
)) throw_format_error("negative width");
3808 return static_cast<unsigned long long>(value
);
3811 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
3812 FMT_CONSTEXPR
auto operator()(T
) -> unsigned long long {
3813 throw_format_error("width is not integer");
3818 struct precision_checker
{
3819 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
3820 FMT_CONSTEXPR
auto operator()(T value
) -> unsigned long long {
3821 if (is_negative(value
)) throw_format_error("negative precision");
3822 return static_cast<unsigned long long>(value
);
3825 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
3826 FMT_CONSTEXPR
auto operator()(T
) -> unsigned long long {
3827 throw_format_error("precision is not integer");
3832 template <typename Handler
, typename FormatArg
>
3833 FMT_CONSTEXPR
auto get_dynamic_spec(FormatArg arg
) -> int {
3834 unsigned long long value
= visit_format_arg(Handler(), arg
);
3835 if (value
> to_unsigned(max_value
<int>()))
3836 throw_format_error("number is too big");
3837 return static_cast<int>(value
);
3840 template <typename Context
, typename ID
>
3841 FMT_CONSTEXPR
auto get_arg(Context
& ctx
, ID id
) -> decltype(ctx
.arg(id
)) {
3842 auto arg
= ctx
.arg(id
);
3843 if (!arg
) ctx
.on_error("argument not found");
3847 template <typename Handler
, typename Context
>
3848 FMT_CONSTEXPR
void handle_dynamic_spec(int& value
,
3849 arg_ref
<typename
Context::char_type
> ref
,
3852 case arg_id_kind::none
:
3854 case arg_id_kind::index
:
3855 value
= detail::get_dynamic_spec
<Handler
>(get_arg(ctx
, ref
.val
.index
));
3857 case arg_id_kind::name
:
3858 value
= detail::get_dynamic_spec
<Handler
>(get_arg(ctx
, ref
.val
.name
));
3863 #if FMT_USE_USER_DEFINED_LITERALS
3864 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
3865 template <typename T
, typename Char
, size_t N
,
3866 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3867 struct statically_named_arg
: view
{
3868 static constexpr auto name
= Str
.data
;
3871 statically_named_arg(const T
& v
) : value(v
) {}
3874 template <typename T
, typename Char
, size_t N
,
3875 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3876 struct is_named_arg
<statically_named_arg
<T
, Char
, N
, Str
>> : std::true_type
{};
3878 template <typename T
, typename Char
, size_t N
,
3879 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3880 struct is_statically_named_arg
<statically_named_arg
<T
, Char
, N
, Str
>>
3881 : std::true_type
{};
3883 template <typename Char
, size_t N
,
3884 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3886 template <typename T
> auto operator=(T
&& value
) const {
3887 return statically_named_arg
<T
, Char
, N
, Str
>(std::forward
<T
>(value
));
3891 template <typename Char
> struct udl_arg
{
3894 template <typename T
> auto operator=(T
&& value
) const -> named_arg
<Char
, T
> {
3895 return {str
, std::forward
<T
>(value
)};
3899 #endif // FMT_USE_USER_DEFINED_LITERALS
3901 template <typename Locale
, typename Char
>
3902 auto vformat(const Locale
& loc
, basic_string_view
<Char
> fmt
,
3903 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
3904 -> std::basic_string
<Char
> {
3905 auto buf
= basic_memory_buffer
<Char
>();
3906 detail::vformat_to(buf
, fmt
, args
, detail::locale_ref(loc
));
3907 return {buf
.data(), buf
.size()};
3910 using format_func
= void (*)(detail::buffer
<char>&, int, const char*);
3912 FMT_API
void format_error_code(buffer
<char>& out
, int error_code
,
3913 string_view message
) noexcept
;
3915 FMT_API
void report_error(format_func func
, int error_code
,
3916 const char* message
) noexcept
;
3917 } // namespace detail
3919 FMT_API
auto vsystem_error(int error_code
, string_view format_str
,
3920 format_args args
) -> std::system_error
;
3924 Constructs :class:`std::system_error` with a message formatted with
3925 ``fmt::format(fmt, args...)``.
3926 *error_code* is a system error code as given by ``errno``.
3930 // This throws std::system_error with the description
3931 // cannot open file 'madeup': No such file or directory
3932 // or similar (system message may vary).
3933 const char* filename = "madeup";
3934 std::FILE* file = std::fopen(filename, "r");
3936 throw fmt::system_error(errno, "cannot open file '{}'", filename);
3939 template <typename
... T
>
3940 auto system_error(int error_code
, format_string
<T
...> fmt
, T
&&... args
)
3941 -> std::system_error
{
3942 return vsystem_error(error_code
, fmt
, fmt::make_format_args(args
...));
3947 Formats an error message for an error returned by an operating system or a
3948 language runtime, for example a file opening error, and writes it to *out*.
3949 The format is the same as the one used by ``std::system_error(ec, message)``
3950 where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.
3951 It is implementation-defined but normally looks like:
3954 *<message>*: *<system-message>*
3956 where *<message>* is the passed message and *<system-message>* is the system
3957 message corresponding to the error code.
3958 *error_code* is a system error code as given by ``errno``.
3961 FMT_API
void format_system_error(detail::buffer
<char>& out
, int error_code
,
3962 const char* message
) noexcept
;
3964 // Reports a system error without throwing an exception.
3965 // Can be used to report errors from destructors.
3966 FMT_API
void report_system_error(int error_code
, const char* message
) noexcept
;
3968 /** Fast integer formatter. */
3971 // Buffer should be large enough to hold all digits (digits10 + 1),
3972 // a sign and a null character.
3973 enum { buffer_size
= std::numeric_limits
<unsigned long long>::digits10
+ 3 };
3974 mutable char buffer_
[buffer_size
];
3977 template <typename UInt
> auto format_unsigned(UInt value
) -> char* {
3978 auto n
= static_cast<detail::uint32_or_64_or_128_t
<UInt
>>(value
);
3979 return detail::format_decimal(buffer_
, n
, buffer_size
- 1).begin
;
3982 template <typename Int
> auto format_signed(Int value
) -> char* {
3983 auto abs_value
= static_cast<detail::uint32_or_64_or_128_t
<Int
>>(value
);
3984 bool negative
= value
< 0;
3985 if (negative
) abs_value
= 0 - abs_value
;
3986 auto begin
= format_unsigned(abs_value
);
3987 if (negative
) *--begin
= '-';
3992 explicit format_int(int value
) : str_(format_signed(value
)) {}
3993 explicit format_int(long value
) : str_(format_signed(value
)) {}
3994 explicit format_int(long long value
) : str_(format_signed(value
)) {}
3995 explicit format_int(unsigned value
) : str_(format_unsigned(value
)) {}
3996 explicit format_int(unsigned long value
) : str_(format_unsigned(value
)) {}
3997 explicit format_int(unsigned long long value
)
3998 : str_(format_unsigned(value
)) {}
4000 /** Returns the number of characters written to the output buffer. */
4001 auto size() const -> size_t {
4002 return detail::to_unsigned(buffer_
- str_
+ buffer_size
- 1);
4006 Returns a pointer to the output buffer content. No terminating null
4007 character is appended.
4009 auto data() const -> const char* { return str_
; }
4012 Returns a pointer to the output buffer content with terminating null
4015 auto c_str() const -> const char* {
4016 buffer_
[buffer_size
- 1] = '\0';
4022 Returns the content of the output buffer as an ``std::string``.
4025 auto str() const -> std::string
{ return std::string(str_
, size()); }
4028 template <typename T
, typename Char
>
4029 struct formatter
<T
, Char
, enable_if_t
<detail::has_format_as
<T
>::value
>>
4030 : formatter
<detail::format_as_t
<T
>, Char
> {
4031 template <typename FormatContext
>
4032 auto format(const T
& value
, FormatContext
& ctx
) const -> decltype(ctx
.out()) {
4033 using base
= formatter
<detail::format_as_t
<T
>, Char
>;
4034 return base::format(format_as(value
), ctx
);
4038 #define FMT_FORMAT_AS(Type, Base) \
4039 template <typename Char> \
4040 struct formatter<Type, Char> : formatter<Base, Char> {}
4042 FMT_FORMAT_AS(signed char, int);
4043 FMT_FORMAT_AS(unsigned char, unsigned);
4044 FMT_FORMAT_AS(short, int);
4045 FMT_FORMAT_AS(unsigned short, unsigned);
4046 FMT_FORMAT_AS(long, detail::long_type
);
4047 FMT_FORMAT_AS(unsigned long, detail::ulong_type
);
4048 FMT_FORMAT_AS(Char
*, const Char
*);
4049 FMT_FORMAT_AS(std::basic_string
<Char
>, basic_string_view
<Char
>);
4050 FMT_FORMAT_AS(std::nullptr_t
, const void*);
4051 FMT_FORMAT_AS(detail::std_string_view
<Char
>, basic_string_view
<Char
>);
4052 FMT_FORMAT_AS(void*, const void*);
4054 template <typename Char
, size_t N
>
4055 struct formatter
<Char
[N
], Char
> : formatter
<basic_string_view
<Char
>, Char
> {};
4059 Converts ``p`` to ``const void*`` for pointer formatting.
4063 auto s = fmt::format("{}", fmt::ptr(p));
4066 template <typename T
> auto ptr(T p
) -> const void* {
4067 static_assert(std::is_pointer
<T
>::value
, "");
4068 return detail::bit_cast
<const void*>(p
);
4070 template <typename T
, typename Deleter
>
4071 auto ptr(const std::unique_ptr
<T
, Deleter
>& p
) -> const void* {
4074 template <typename T
> auto ptr(const std::shared_ptr
<T
>& p
) -> const void* {
4080 Converts ``e`` to the underlying type.
4084 enum class color { red, green, blue };
4085 auto s = fmt::format("{}", fmt::underlying(color::red));
4088 template <typename Enum
>
4089 constexpr auto underlying(Enum e
) noexcept
-> underlying_t
<Enum
> {
4090 return static_cast<underlying_t
<Enum
>>(e
);
4094 template <typename Enum
, FMT_ENABLE_IF(std::is_enum
<Enum
>::value
)>
4095 constexpr auto format_as(Enum e
) noexcept
-> underlying_t
<Enum
> {
4096 return static_cast<underlying_t
<Enum
>>(e
);
4098 } // namespace enums
4103 friend struct formatter
<bytes
>;
4106 explicit bytes(string_view data
) : data_(data
) {}
4109 template <> struct formatter
<bytes
> {
4111 detail::dynamic_format_specs
<> specs_
;
4114 template <typename ParseContext
>
4115 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const char* {
4116 return parse_format_specs(ctx
.begin(), ctx
.end(), specs_
, ctx
,
4117 detail::type::string_type
);
4120 template <typename FormatContext
>
4121 auto format(bytes b
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
4122 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
4123 specs_
.width_ref
, ctx
);
4124 detail::handle_dynamic_spec
<detail::precision_checker
>(
4125 specs_
.precision
, specs_
.precision_ref
, ctx
);
4126 return detail::write_bytes(ctx
.out(), b
.data_
, specs_
);
4130 // group_digits_view is not derived from view because it copies the argument.
4131 template <typename T
> struct group_digits_view
{
4137 Returns a view that formats an integer value using ',' as a locale-independent
4138 thousands separator.
4142 fmt::print("{}", fmt::group_digits(12345));
4146 template <typename T
> auto group_digits(T value
) -> group_digits_view
<T
> {
4150 template <typename T
> struct formatter
<group_digits_view
<T
>> : formatter
<T
> {
4152 detail::dynamic_format_specs
<> specs_
;
4155 template <typename ParseContext
>
4156 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const char* {
4157 return parse_format_specs(ctx
.begin(), ctx
.end(), specs_
, ctx
,
4158 detail::type::int_type
);
4161 template <typename FormatContext
>
4162 auto format(group_digits_view
<T
> t
, FormatContext
& ctx
)
4163 -> decltype(ctx
.out()) {
4164 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
4165 specs_
.width_ref
, ctx
);
4166 detail::handle_dynamic_spec
<detail::precision_checker
>(
4167 specs_
.precision
, specs_
.precision_ref
, ctx
);
4168 return detail::write_int(
4169 ctx
.out(), static_cast<detail::uint64_or_128_t
<T
>>(t
.value
), 0, specs_
,
4170 detail::digit_grouping
<char>("\3", ","));
4174 template <typename T
> struct nested_view
{
4175 const formatter
<T
>* fmt
;
4179 template <typename T
> struct formatter
<nested_view
<T
>> {
4180 FMT_CONSTEXPR
auto parse(format_parse_context
& ctx
) -> const char* {
4183 auto format(nested_view
<T
> view
, format_context
& ctx
) const
4184 -> decltype(ctx
.out()) {
4185 return view
.fmt
->format(*view
.value
, ctx
);
4189 template <typename T
> struct nested_formatter
{
4192 detail::fill_t
<char> fill_
;
4194 formatter
<T
> formatter_
;
4197 constexpr nested_formatter() : width_(0), align_(align_t::none
) {}
4199 FMT_CONSTEXPR
auto parse(format_parse_context
& ctx
) -> const char* {
4200 auto specs
= detail::dynamic_format_specs
<char>();
4201 auto it
= parse_format_specs(ctx
.begin(), ctx
.end(), specs
, ctx
,
4202 detail::type::none_type
);
4203 width_
= specs
.width
;
4205 align_
= specs
.align
;
4207 return formatter_
.parse(ctx
);
4210 template <typename F
>
4211 auto write_padded(format_context
& ctx
, F write
) const -> decltype(ctx
.out()) {
4212 if (width_
== 0) return write(ctx
.out());
4213 auto buf
= memory_buffer();
4214 write(std::back_inserter(buf
));
4215 auto specs
= format_specs
<>();
4216 specs
.width
= width_
;
4218 specs
.align
= align_
;
4219 return detail::write(ctx
.out(), string_view(buf
.data(), buf
.size()), specs
);
4222 auto nested(const T
& value
) const -> nested_view
<T
> {
4223 return nested_view
<T
>{&formatter_
, &value
};
4227 // DEPRECATED! join_view will be moved to ranges.h.
4228 template <typename It
, typename Sentinel
, typename Char
= char>
4229 struct join_view
: detail::view
{
4232 basic_string_view
<Char
> sep
;
4234 join_view(It b
, Sentinel e
, basic_string_view
<Char
> s
)
4235 : begin(b
), end(e
), sep(s
) {}
4238 template <typename It
, typename Sentinel
, typename Char
>
4239 struct formatter
<join_view
<It
, Sentinel
, Char
>, Char
> {
4242 #ifdef __cpp_lib_ranges
4243 std::iter_value_t
<It
>;
4245 typename
std::iterator_traits
<It
>::value_type
;
4247 formatter
<remove_cvref_t
<value_type
>, Char
> value_formatter_
;
4250 template <typename ParseContext
>
4251 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const Char
* {
4252 return value_formatter_
.parse(ctx
);
4255 template <typename FormatContext
>
4256 auto format(const join_view
<It
, Sentinel
, Char
>& value
,
4257 FormatContext
& ctx
) const -> decltype(ctx
.out()) {
4258 auto it
= value
.begin
;
4259 auto out
= ctx
.out();
4260 if (it
!= value
.end
) {
4261 out
= value_formatter_
.format(*it
, ctx
);
4263 while (it
!= value
.end
) {
4264 out
= detail::copy_str
<Char
>(value
.sep
.begin(), value
.sep
.end(), out
);
4265 ctx
.advance_to(out
);
4266 out
= value_formatter_
.format(*it
, ctx
);
4275 Returns a view that formats the iterator range `[begin, end)` with elements
4278 template <typename It
, typename Sentinel
>
4279 auto join(It begin
, Sentinel end
, string_view sep
) -> join_view
<It
, Sentinel
> {
4280 return {begin
, end
, sep
};
4285 Returns a view that formats `range` with elements separated by `sep`.
4289 std::vector<int> v = {1, 2, 3};
4290 fmt::print("{}", fmt::join(v, ", "));
4291 // Output: "1, 2, 3"
4293 ``fmt::join`` applies passed format specifiers to the range elements::
4295 fmt::print("{:02}", fmt::join(v, ", "));
4296 // Output: "01, 02, 03"
4299 template <typename Range
>
4300 auto join(Range
&& range
, string_view sep
)
4301 -> join_view
<detail::iterator_t
<Range
>, detail::sentinel_t
<Range
>> {
4302 return join(std::begin(range
), std::end(range
), sep
);
4307 Converts *value* to ``std::string`` using the default format for type *T*.
4311 #include <fmt/format.h>
4313 std::string answer = fmt::to_string(42);
4316 template <typename T
, FMT_ENABLE_IF(!std::is_integral
<T
>::value
&&
4317 !detail::has_format_as
<T
>::value
)>
4318 inline auto to_string(const T
& value
) -> std::string
{
4319 auto buffer
= memory_buffer();
4320 detail::write
<char>(appender(buffer
), value
);
4321 return {buffer
.data(), buffer
.size()};
4324 template <typename T
, FMT_ENABLE_IF(std::is_integral
<T
>::value
)>
4325 FMT_NODISCARD
inline auto to_string(T value
) -> std::string
{
4326 // The buffer should be large enough to store the number including the sign
4327 // or "false" for bool.
4328 constexpr int max_size
= detail::digits10
<T
>() + 2;
4329 char buffer
[max_size
> 5 ? static_cast<unsigned>(max_size
) : 5];
4330 char* begin
= buffer
;
4331 return std::string(begin
, detail::write
<char>(begin
, value
));
4334 template <typename Char
, size_t SIZE
>
4335 FMT_NODISCARD
auto to_string(const basic_memory_buffer
<Char
, SIZE
>& buf
)
4336 -> std::basic_string
<Char
> {
4337 auto size
= buf
.size();
4338 detail::assume(size
< std::basic_string
<Char
>().max_size());
4339 return std::basic_string
<Char
>(buf
.data(), size
);
4342 template <typename T
, FMT_ENABLE_IF(!std::is_integral
<T
>::value
&&
4343 detail::has_format_as
<T
>::value
)>
4344 inline auto to_string(const T
& value
) -> std::string
{
4345 return to_string(format_as(value
));
4352 template <typename Char
>
4353 void vformat_to(buffer
<Char
>& buf
, basic_string_view
<Char
> fmt
,
4354 typename vformat_args
<Char
>::type args
, locale_ref loc
) {
4355 auto out
= buffer_appender
<Char
>(buf
);
4356 if (fmt
.size() == 2 && equal2(fmt
.data(), "{}")) {
4357 auto arg
= args
.get(0);
4358 if (!arg
) throw_format_error("argument not found");
4359 visit_format_arg(default_arg_formatter
<Char
>{out
, args
, loc
}, arg
);
4363 struct format_handler
: error_handler
{
4364 basic_format_parse_context
<Char
> parse_context
;
4365 buffer_context
<Char
> context
;
4367 format_handler(buffer_appender
<Char
> p_out
, basic_string_view
<Char
> str
,
4368 basic_format_args
<buffer_context
<Char
>> p_args
,
4370 : parse_context(str
), context(p_out
, p_args
, p_loc
) {}
4372 void on_text(const Char
* begin
, const Char
* end
) {
4373 auto text
= basic_string_view
<Char
>(begin
, to_unsigned(end
- begin
));
4374 context
.advance_to(write
<Char
>(context
.out(), text
));
4377 FMT_CONSTEXPR
auto on_arg_id() -> int {
4378 return parse_context
.next_arg_id();
4380 FMT_CONSTEXPR
auto on_arg_id(int id
) -> int {
4381 return parse_context
.check_arg_id(id
), id
;
4383 FMT_CONSTEXPR
auto on_arg_id(basic_string_view
<Char
> id
) -> int {
4384 int arg_id
= context
.arg_id(id
);
4385 if (arg_id
< 0) throw_format_error("argument not found");
4389 FMT_INLINE
void on_replacement_field(int id
, const Char
*) {
4390 auto arg
= get_arg(context
, id
);
4391 context
.advance_to(visit_format_arg(
4392 default_arg_formatter
<Char
>{context
.out(), context
.args(),
4397 auto on_format_specs(int id
, const Char
* begin
, const Char
* end
)
4399 auto arg
= get_arg(context
, id
);
4400 // Not using a visitor for custom types gives better codegen.
4401 if (arg
.format_custom(begin
, parse_context
, context
))
4402 return parse_context
.begin();
4403 auto specs
= detail::dynamic_format_specs
<Char
>();
4404 begin
= parse_format_specs(begin
, end
, specs
, parse_context
, arg
.type());
4405 detail::handle_dynamic_spec
<detail::width_checker
>(
4406 specs
.width
, specs
.width_ref
, context
);
4407 detail::handle_dynamic_spec
<detail::precision_checker
>(
4408 specs
.precision
, specs
.precision_ref
, context
);
4409 if (begin
== end
|| *begin
!= '}')
4410 throw_format_error("missing '}' in format string");
4411 auto f
= arg_formatter
<Char
>{context
.out(), specs
, context
.locale()};
4412 context
.advance_to(visit_format_arg(f
, arg
));
4416 detail::parse_format_string
<false>(fmt
, format_handler(out
, fmt
, args
, loc
));
4421 #ifndef FMT_HEADER_ONLY
4422 extern template FMT_API
void vformat_to(buffer
<char>&, string_view
,
4423 typename vformat_args
<>::type
,
4425 extern template FMT_API
auto thousands_sep_impl
<char>(locale_ref
)
4426 -> thousands_sep_result
<char>;
4427 extern template FMT_API
auto thousands_sep_impl
<wchar_t>(locale_ref
)
4428 -> thousands_sep_result
<wchar_t>;
4429 extern template FMT_API
auto decimal_point_impl(locale_ref
) -> char;
4430 extern template FMT_API
auto decimal_point_impl(locale_ref
) -> wchar_t;
4431 #endif // FMT_HEADER_ONLY
4433 } // namespace detail
4435 #if FMT_USE_USER_DEFINED_LITERALS
4436 inline namespace literals
{
4439 User-defined literal equivalent of :func:`fmt::arg`.
4443 using namespace fmt::literals;
4444 fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
4447 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
4448 template <detail_exported::fixed_string Str
> constexpr auto operator""_a() {
4449 using char_t
= remove_cvref_t
<decltype(Str
.data
[0])>;
4450 return detail::udl_arg
<char_t
, sizeof(Str
.data
) / sizeof(char_t
), Str
>();
4453 constexpr auto operator""_a(const char* s
, size_t) -> detail::udl_arg
<char> {
4457 } // namespace literals
4458 #endif // FMT_USE_USER_DEFINED_LITERALS
4460 template <typename Locale
, FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4461 inline auto vformat(const Locale
& loc
, string_view fmt
, format_args args
)
4463 return detail::vformat(loc
, fmt
, args
);
4466 template <typename Locale
, typename
... T
,
4467 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4468 inline auto format(const Locale
& loc
, format_string
<T
...> fmt
, T
&&... args
)
4470 return fmt::vformat(loc
, string_view(fmt
), fmt::make_format_args(args
...));
4473 template <typename OutputIt
, typename Locale
,
4474 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
&&
4475 detail::is_locale
<Locale
>::value
)>
4476 auto vformat_to(OutputIt out
, const Locale
& loc
, string_view fmt
,
4477 format_args args
) -> OutputIt
{
4478 using detail::get_buffer
;
4479 auto&& buf
= get_buffer
<char>(out
);
4480 detail::vformat_to(buf
, fmt
, args
, detail::locale_ref(loc
));
4481 return detail::get_iterator(buf
, out
);
4484 template <typename OutputIt
, typename Locale
, typename
... T
,
4485 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
&&
4486 detail::is_locale
<Locale
>::value
)>
4487 FMT_INLINE
auto format_to(OutputIt out
, const Locale
& loc
,
4488 format_string
<T
...> fmt
, T
&&... args
) -> OutputIt
{
4489 return vformat_to(out
, loc
, fmt
, fmt::make_format_args(args
...));
4492 template <typename Locale
, typename
... T
,
4493 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4494 FMT_NODISCARD FMT_INLINE
auto formatted_size(const Locale
& loc
,
4495 format_string
<T
...> fmt
,
4496 T
&&... args
) -> size_t {
4497 auto buf
= detail::counting_buffer
<>();
4498 detail::vformat_to
<char>(buf
, fmt
, fmt::make_format_args(args
...),
4499 detail::locale_ref(loc
));
4505 template <typename T
, typename Char
>
4506 template <typename FormatContext
>
4507 FMT_CONSTEXPR FMT_INLINE
auto
4509 enable_if_t
<detail::type_constant
<T
, Char
>::value
!=
4510 detail::type::custom_type
>>::format(const T
& val
,
4512 const -> decltype(ctx
.out()) {
4513 if (specs_
.width_ref
.kind
== detail::arg_id_kind::none
&&
4514 specs_
.precision_ref
.kind
== detail::arg_id_kind::none
) {
4515 return detail::write
<Char
>(ctx
.out(), val
, specs_
, ctx
.locale());
4517 auto specs
= specs_
;
4518 detail::handle_dynamic_spec
<detail::width_checker
>(specs
.width
,
4519 specs
.width_ref
, ctx
);
4520 detail::handle_dynamic_spec
<detail::precision_checker
>(
4521 specs
.precision
, specs
.precision_ref
, ctx
);
4522 return detail::write
<Char
>(ctx
.out(), val
, specs
, ctx
.locale());
4527 #ifdef FMT_HEADER_ONLY
4528 # define FMT_FUNC inline
4529 # include "format-inl.h"
4534 #endif // FMT_FORMAT_H_