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 #ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
37 # define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
38 # define FMT_REMOVE_TRANSITIVE_INCLUDES
44 # include <cmath> // std::signbit
45 # include <cstdint> // uint32_t
46 # include <cstring> // std::memcpy
47 # include <initializer_list> // std::initializer_list
48 # include <limits> // std::numeric_limits
49 # if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI)
50 // Workaround for pre gcc 5 libstdc++.
51 # include <memory> // std::allocator_traits
53 # include <stdexcept> // std::runtime_error
54 # include <string> // std::string
55 # include <system_error> // std::system_error
57 // Checking FMT_CPLUSPLUS for warning suppression in MSVC.
58 # if FMT_HAS_INCLUDE(<bit>) && FMT_CPLUSPLUS > 201703L
59 # include <bit> // std::bit_cast
62 // libc++ supports string_view in pre-c++17.
63 # if FMT_HAS_INCLUDE(<string_view>) && \
64 (FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION))
65 # include <string_view>
66 # define FMT_USE_STRING_VIEW
70 #if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
71 # define FMT_INLINE_VARIABLE inline
73 # define FMT_INLINE_VARIABLE
76 #ifndef FMT_NO_UNIQUE_ADDRESS
77 # if FMT_CPLUSPLUS >= 202002L
78 # if FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
79 # define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
80 // VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485).
81 # elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION
82 # define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
86 #ifndef FMT_NO_UNIQUE_ADDRESS
87 # define FMT_NO_UNIQUE_ADDRESS
90 // Visibility when compiled as a shared library/object.
91 #if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
92 # define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value)
94 # define FMT_SO_VISIBILITY(value)
98 # define FMT_HAS_BUILTIN(x) __has_builtin(x)
100 # define FMT_HAS_BUILTIN(x) 0
103 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
104 # define FMT_NOINLINE __attribute__((noinline))
106 # define FMT_NOINLINE
110 template <> struct iterator_traits
<fmt::appender
> {
111 using iterator_category
= output_iterator_tag
;
112 using value_type
= char;
118 # if FMT_MSC_VERSION || defined(__NVCC__)
121 template <typename Exception
> inline void do_throw(const Exception
& x
) {
122 // Silence unreachable code warnings in MSVC and NVCC because these
123 // are nearly impossible to fix in a generic code.
124 volatile bool b
= true;
127 } // namespace detail
129 # define FMT_THROW(x) detail::do_throw(x)
131 # define FMT_THROW(x) throw x
134 # define FMT_THROW(x) \
135 ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
139 #ifndef FMT_MAYBE_UNUSED
140 # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
141 # define FMT_MAYBE_UNUSED [[maybe_unused]]
143 # define FMT_MAYBE_UNUSED
147 #ifndef FMT_USE_USER_DEFINED_LITERALS
148 // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
150 // GCC before 4.9 requires a space in `operator"" _a` which is invalid in later
151 // compiler versions.
152 # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \
153 FMT_MSC_VERSION >= 1900) && \
154 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
155 # define FMT_USE_USER_DEFINED_LITERALS 1
157 # define FMT_USE_USER_DEFINED_LITERALS 0
161 // Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
162 // integer formatter template instantiations to just one by only using the
163 // largest integer type. This results in a reduction in binary size but will
164 // cause a decrease in integer formatting performance.
165 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
166 # define FMT_REDUCE_INT_INSTANTIATIONS 0
169 // __builtin_clz is broken in clang with Microsoft CodeGen:
170 // https://github.com/fmtlib/fmt/issues/519.
172 # if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
173 # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
175 # if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
176 # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
180 // __builtin_ctz is broken in Intel Compiler Classic on Windows:
181 // https://github.com/fmtlib/fmt/issues/2510.
183 # if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
184 defined(__NVCOMPILER)
185 # define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
187 # if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
188 FMT_ICC_VERSION || defined(__NVCOMPILER)
189 # define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
194 # include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
197 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
198 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
199 // MSVC intrinsics if the clz and clzll builtins are not available.
200 #if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
201 !defined(FMT_BUILTIN_CTZLL)
204 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
205 # if !defined(__clang__)
206 # pragma intrinsic(_BitScanForward)
207 # pragma intrinsic(_BitScanReverse)
209 # pragma intrinsic(_BitScanForward64)
210 # pragma intrinsic(_BitScanReverse64)
214 inline auto clz(uint32_t x
) -> int {
216 _BitScanReverse(&r
, x
);
217 FMT_ASSERT(x
!= 0, "");
218 // Static analysis complains about using uninitialized data
219 // "r", but the only way that can happen is if "x" is 0,
220 // which the callers guarantee to not happen.
221 FMT_MSC_WARNING(suppress
: 6102)
222 return 31 ^ static_cast<int>(r
);
224 # define FMT_BUILTIN_CLZ(n) detail::clz(n)
226 inline auto clzll(uint64_t x
) -> int {
229 _BitScanReverse64(&r
, x
);
231 // Scan the high 32 bits.
232 if (_BitScanReverse(&r
, static_cast<uint32_t>(x
>> 32)))
233 return 63 ^ static_cast<int>(r
+ 32);
234 // Scan the low 32 bits.
235 _BitScanReverse(&r
, static_cast<uint32_t>(x
));
237 FMT_ASSERT(x
!= 0, "");
238 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
239 return 63 ^ static_cast<int>(r
);
241 # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
243 inline auto ctz(uint32_t x
) -> int {
245 _BitScanForward(&r
, x
);
246 FMT_ASSERT(x
!= 0, "");
247 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
248 return static_cast<int>(r
);
250 # define FMT_BUILTIN_CTZ(n) detail::ctz(n)
252 inline auto ctzll(uint64_t x
) -> int {
254 FMT_ASSERT(x
!= 0, "");
255 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
257 _BitScanForward64(&r
, x
);
259 // Scan the low 32 bits.
260 if (_BitScanForward(&r
, static_cast<uint32_t>(x
))) return static_cast<int>(r
);
261 // Scan the high 32 bits.
262 _BitScanForward(&r
, static_cast<uint32_t>(x
>> 32));
265 return static_cast<int>(r
);
267 # define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
268 } // namespace detail
274 template <typename Char
, typename Traits
, typename Allocator
>
275 struct is_contiguous
<std::basic_string
<Char
, Traits
, Allocator
>>
280 FMT_CONSTEXPR
inline void abort_fuzzing_if(bool condition
) {
281 ignore_unused(condition
);
283 if (condition
) throw std::runtime_error("fuzzing limit reached");
287 #if defined(FMT_USE_STRING_VIEW)
288 template <typename Char
> using std_string_view
= std::basic_string_view
<Char
>;
290 template <typename T
> struct std_string_view
{};
293 // Implementation of std::bit_cast for pre-C++20.
294 template <typename To
, typename From
, FMT_ENABLE_IF(sizeof(To
) == sizeof(From
))>
295 FMT_CONSTEXPR20
auto bit_cast(const From
& from
) -> To
{
296 #ifdef __cpp_lib_bit_cast
297 if (is_constant_evaluated()) return std::bit_cast
<To
>(from
);
300 // The cast suppresses a bogus -Wclass-memaccess on GCC.
301 std::memcpy(static_cast<void*>(&to
), &from
, sizeof(to
));
305 inline auto is_big_endian() -> bool {
308 #elif defined(__BIG_ENDIAN__)
310 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
311 return __BYTE_ORDER__
== __ORDER_BIG_ENDIAN__
;
314 char data
[sizeof(int)];
316 return bit_cast
<bytes
>(1).data
[0] == 0;
320 class uint128_fallback
{
325 constexpr uint128_fallback(uint64_t hi
, uint64_t lo
) : lo_(lo
), hi_(hi
) {}
326 constexpr uint128_fallback(uint64_t value
= 0) : lo_(value
), hi_(0) {}
328 constexpr auto high() const noexcept
-> uint64_t { return hi_
; }
329 constexpr auto low() const noexcept
-> uint64_t { return lo_
; }
331 template <typename T
, FMT_ENABLE_IF(std::is_integral
<T
>::value
)>
332 constexpr explicit operator T() const {
333 return static_cast<T
>(lo_
);
336 friend constexpr auto operator==(const uint128_fallback
& lhs
,
337 const uint128_fallback
& rhs
) -> bool {
338 return lhs
.hi_
== rhs
.hi_
&& lhs
.lo_
== rhs
.lo_
;
340 friend constexpr auto operator!=(const uint128_fallback
& lhs
,
341 const uint128_fallback
& rhs
) -> bool {
342 return !(lhs
== rhs
);
344 friend constexpr auto operator>(const uint128_fallback
& lhs
,
345 const uint128_fallback
& rhs
) -> bool {
346 return lhs
.hi_
!= rhs
.hi_
? lhs
.hi_
> rhs
.hi_
: lhs
.lo_
> rhs
.lo_
;
348 friend constexpr auto operator|(const uint128_fallback
& lhs
,
349 const uint128_fallback
& rhs
)
350 -> uint128_fallback
{
351 return {lhs
.hi_
| rhs
.hi_
, lhs
.lo_
| rhs
.lo_
};
353 friend constexpr auto operator&(const uint128_fallback
& lhs
,
354 const uint128_fallback
& rhs
)
355 -> uint128_fallback
{
356 return {lhs
.hi_
& rhs
.hi_
, lhs
.lo_
& rhs
.lo_
};
358 friend constexpr auto operator~(const uint128_fallback
& n
)
359 -> uint128_fallback
{
360 return {~n
.hi_
, ~n
.lo_
};
362 friend auto operator+(const uint128_fallback
& lhs
,
363 const uint128_fallback
& rhs
) -> uint128_fallback
{
364 auto result
= uint128_fallback(lhs
);
368 friend auto operator*(const uint128_fallback
& lhs
, uint32_t rhs
)
369 -> uint128_fallback
{
370 FMT_ASSERT(lhs
.hi_
== 0, "");
371 uint64_t hi
= (lhs
.lo_
>> 32) * rhs
;
372 uint64_t lo
= (lhs
.lo_
& ~uint32_t()) * rhs
;
373 uint64_t new_lo
= (hi
<< 32) + lo
;
374 return {(hi
>> 32) + (new_lo
< lo
? 1 : 0), new_lo
};
376 friend auto operator-(const uint128_fallback
& lhs
, uint64_t rhs
)
377 -> uint128_fallback
{
378 return {lhs
.hi_
- (lhs
.lo_
< rhs
? 1 : 0), lhs
.lo_
- rhs
};
380 FMT_CONSTEXPR
auto operator>>(int shift
) const -> uint128_fallback
{
381 if (shift
== 64) return {0, hi_
};
382 if (shift
> 64) return uint128_fallback(0, hi_
) >> (shift
- 64);
383 return {hi_
>> shift
, (hi_
<< (64 - shift
)) | (lo_
>> shift
)};
385 FMT_CONSTEXPR
auto operator<<(int shift
) const -> uint128_fallback
{
386 if (shift
== 64) return {lo_
, 0};
387 if (shift
> 64) return uint128_fallback(lo_
, 0) << (shift
- 64);
388 return {hi_
<< shift
| (lo_
>> (64 - shift
)), (lo_
<< shift
)};
390 FMT_CONSTEXPR
auto operator>>=(int shift
) -> uint128_fallback
& {
391 return *this = *this >> shift
;
393 FMT_CONSTEXPR
void operator+=(uint128_fallback n
) {
394 uint64_t new_lo
= lo_
+ n
.lo_
;
395 uint64_t new_hi
= hi_
+ n
.hi_
+ (new_lo
< lo_
? 1 : 0);
396 FMT_ASSERT(new_hi
>= hi_
, "");
400 FMT_CONSTEXPR
void operator&=(uint128_fallback n
) {
405 FMT_CONSTEXPR20
auto operator+=(uint64_t n
) noexcept
-> uint128_fallback
& {
406 if (is_constant_evaluated()) {
408 hi_
+= (lo_
< n
? 1 : 0);
411 #if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
412 unsigned long long carry
;
413 lo_
= __builtin_addcll(lo_
, n
, 0, &carry
);
415 #elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
416 unsigned long long result
;
417 auto carry
= __builtin_ia32_addcarryx_u64(0, lo_
, n
, &result
);
420 #elif defined(_MSC_VER) && defined(_M_X64)
421 auto carry
= _addcarry_u64(0, lo_
, n
, &lo_
);
422 _addcarry_u64(carry
, hi_
, 0, &hi_
);
425 hi_
+= (lo_
< n
? 1 : 0);
431 using uint128_t
= conditional_t
<FMT_USE_INT128
, uint128_opt
, uint128_fallback
>;
434 using uintptr_t = ::uintptr_t;
436 using uintptr_t = uint128_t
;
439 // Returns the largest possible value for type T. Same as
440 // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
441 template <typename T
> constexpr auto max_value() -> T
{
442 return (std::numeric_limits
<T
>::max
)();
444 template <typename T
> constexpr auto num_bits() -> int {
445 return std::numeric_limits
<T
>::digits
;
447 // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
448 template <> constexpr auto num_bits
<int128_opt
>() -> int { return 128; }
449 template <> constexpr auto num_bits
<uint128_opt
>() -> int { return 128; }
450 template <> constexpr auto num_bits
<uint128_fallback
>() -> int { return 128; }
452 // A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
453 // and 128-bit pointers to uint128_fallback.
454 template <typename To
, typename From
, FMT_ENABLE_IF(sizeof(To
) > sizeof(From
))>
455 inline auto bit_cast(const From
& from
) -> To
{
456 constexpr auto size
= static_cast<int>(sizeof(From
) / sizeof(unsigned));
458 unsigned value
[static_cast<unsigned>(size
)];
459 } data
= bit_cast
<data_t
>(from
);
461 if (const_check(is_big_endian())) {
462 for (int i
= 0; i
< size
; ++i
)
463 result
= (result
<< num_bits
<unsigned>()) | data
.value
[i
];
465 for (int i
= size
- 1; i
>= 0; --i
)
466 result
= (result
<< num_bits
<unsigned>()) | data
.value
[i
];
471 template <typename UInt
>
472 FMT_CONSTEXPR20
inline auto countl_zero_fallback(UInt n
) -> int {
474 constexpr UInt msb_mask
= static_cast<UInt
>(1) << (num_bits
<UInt
>() - 1);
475 for (; (n
& msb_mask
) == 0; n
<<= 1) lz
++;
479 FMT_CONSTEXPR20
inline auto countl_zero(uint32_t n
) -> int {
480 #ifdef FMT_BUILTIN_CLZ
481 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n
);
483 return countl_zero_fallback(n
);
486 FMT_CONSTEXPR20
inline auto countl_zero(uint64_t n
) -> int {
487 #ifdef FMT_BUILTIN_CLZLL
488 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n
);
490 return countl_zero_fallback(n
);
493 FMT_INLINE
void assume(bool condition
) {
495 #if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
496 __builtin_assume(condition
);
497 #elif FMT_GCC_VERSION
498 if (!condition
) __builtin_unreachable();
502 // An approximation of iterator_t for pre-C++20 systems.
503 template <typename T
>
504 using iterator_t
= decltype(std::begin(std::declval
<T
&>()));
505 template <typename T
> using sentinel_t
= decltype(std::end(std::declval
<T
&>()));
507 // A workaround for std::string not having mutable data() until C++17.
508 template <typename Char
>
509 inline auto get_data(std::basic_string
<Char
>& s
) -> Char
* {
512 template <typename Container
>
513 inline auto get_data(Container
& c
) -> typename
Container::value_type
* {
517 // Attempts to reserve space for n extra characters in the output range.
518 // Returns a pointer to the reserved range or a reference to it.
519 template <typename OutputIt
,
520 FMT_ENABLE_IF(is_back_insert_iterator
<OutputIt
>::value
&&
521 is_contiguous
<typename
OutputIt::container
>::value
)>
522 #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
523 __attribute__((no_sanitize("undefined")))
526 reserve(OutputIt it
, size_t n
) -> typename
OutputIt::value_type
* {
527 auto& c
= get_container(it
);
528 size_t size
= c
.size();
530 return get_data(c
) + size
;
533 template <typename T
>
534 inline auto reserve(basic_appender
<T
> it
, size_t n
) -> basic_appender
<T
> {
535 buffer
<T
>& buf
= get_container(it
);
536 buf
.try_reserve(buf
.size() + n
);
540 template <typename Iterator
>
541 constexpr auto reserve(Iterator
& it
, size_t) -> Iterator
& {
545 template <typename OutputIt
>
546 using reserve_iterator
=
547 remove_reference_t
<decltype(reserve(std::declval
<OutputIt
&>(), 0))>;
549 template <typename T
, typename OutputIt
>
550 constexpr auto to_pointer(OutputIt
, size_t) -> T
* {
553 template <typename T
> auto to_pointer(basic_appender
<T
> it
, size_t n
) -> T
* {
554 buffer
<T
>& buf
= get_container(it
);
555 auto size
= buf
.size();
556 buf
.try_reserve(size
+ n
);
557 if (buf
.capacity() < size
+ n
) return nullptr;
558 buf
.try_resize(size
+ n
);
559 return buf
.data() + size
;
562 template <typename OutputIt
,
563 FMT_ENABLE_IF(is_back_insert_iterator
<OutputIt
>::value
&&
564 is_contiguous
<typename
OutputIt::container
>::value
)>
565 inline auto base_iterator(OutputIt it
,
566 typename
OutputIt::container_type::value_type
*)
571 template <typename Iterator
>
572 constexpr auto base_iterator(Iterator
, Iterator it
) -> Iterator
{
576 // <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
578 template <typename OutputIt
, typename Size
, typename T
>
579 FMT_CONSTEXPR
auto fill_n(OutputIt out
, Size count
, const T
& value
)
581 for (Size i
= 0; i
< count
; ++i
) *out
++ = value
;
584 template <typename T
, typename Size
>
585 FMT_CONSTEXPR20
auto fill_n(T
* out
, Size count
, char value
) -> T
* {
586 if (is_constant_evaluated()) {
587 return fill_n
<T
*, Size
, T
>(out
, count
, value
);
589 std::memset(out
, value
, to_unsigned(count
));
593 template <typename OutChar
, typename InputIt
, typename OutputIt
>
594 FMT_CONSTEXPR FMT_NOINLINE
auto copy_noinline(InputIt begin
, InputIt end
,
595 OutputIt out
) -> OutputIt
{
596 return copy
<OutChar
>(begin
, end
, out
);
599 // A public domain branchless UTF-8 decoder by Christopher Wellons:
600 // https://github.com/skeeto/branchless-utf8
601 /* Decode the next character, c, from s, reporting errors in e.
603 * Since this is a branchless decoder, four bytes will be read from the
604 * buffer regardless of the actual length of the next character. This
605 * means the buffer _must_ have at least three bytes of zero padding
606 * following the end of the data stream.
608 * Errors are reported in e, which will be non-zero if the parsed
609 * character was somehow invalid: invalid byte sequence, non-canonical
610 * encoding, or a surrogate half.
612 * The function returns a pointer to the next character. When an error
613 * occurs, this pointer will be a guess that depends on the particular
614 * error, but it will always advance at least one byte.
616 FMT_CONSTEXPR
inline auto utf8_decode(const char* s
, uint32_t* c
, int* e
)
618 constexpr const int masks
[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
619 constexpr const uint32_t mins
[] = {4194304, 0, 128, 2048, 65536};
620 constexpr const int shiftc
[] = {0, 18, 12, 6, 0};
621 constexpr const int shifte
[] = {0, 6, 4, 2, 0};
623 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"
624 [static_cast<unsigned char>(*s
) >> 3];
625 // Compute the pointer to the next character early so that the next
626 // iteration can start working on the next character. Neither Clang
627 // nor GCC figure out this reordering on their own.
628 const char* next
= s
+ len
+ !len
;
630 using uchar
= unsigned char;
632 // Assume a four-byte character and load four bytes. Unused bits are
634 *c
= uint32_t(uchar(s
[0]) & masks
[len
]) << 18;
635 *c
|= uint32_t(uchar(s
[1]) & 0x3f) << 12;
636 *c
|= uint32_t(uchar(s
[2]) & 0x3f) << 6;
637 *c
|= uint32_t(uchar(s
[3]) & 0x3f) << 0;
640 // Accumulate the various error conditions.
641 *e
= (*c
< mins
[len
]) << 6; // non-canonical encoding
642 *e
|= ((*c
>> 11) == 0x1b) << 7; // surrogate half?
643 *e
|= (*c
> 0x10FFFF) << 8; // out of range?
644 *e
|= (uchar(s
[1]) & 0xc0) >> 2;
645 *e
|= (uchar(s
[2]) & 0xc0) >> 4;
646 *e
|= uchar(s
[3]) >> 6;
647 *e
^= 0x2a; // top two bits of each tail byte correct?
653 constexpr FMT_INLINE_VARIABLE
uint32_t invalid_code_point
= ~uint32_t();
655 // Invokes f(cp, sv) for every code point cp in s with sv being the string view
656 // corresponding to the code point. cp is invalid_code_point on error.
657 template <typename F
>
658 FMT_CONSTEXPR
void for_each_codepoint(string_view s
, F f
) {
659 auto decode
= [f
](const char* buf_ptr
, const char* ptr
) {
660 auto cp
= uint32_t();
662 auto end
= utf8_decode(buf_ptr
, &cp
, &error
);
663 bool result
= f(error
? invalid_code_point
: cp
,
664 string_view(ptr
, error
? 1 : to_unsigned(end
- buf_ptr
)));
665 return result
? (error
? buf_ptr
+ 1 : end
) : nullptr;
668 const size_t block_size
= 4; // utf8_decode always reads blocks of 4 chars.
669 if (s
.size() >= block_size
) {
670 for (auto end
= p
+ s
.size() - block_size
+ 1; p
< end
;) {
675 if (auto num_chars_left
= s
.data() + s
.size() - p
) {
676 char buf
[2 * block_size
- 1] = {};
677 copy
<char>(p
, p
+ num_chars_left
, buf
);
678 const char* buf_ptr
= buf
;
680 auto end
= decode(buf_ptr
, p
);
684 } while (buf_ptr
- buf
< num_chars_left
);
688 template <typename Char
>
689 inline auto compute_width(basic_string_view
<Char
> s
) -> size_t {
693 // Computes approximate display width of a UTF-8 string.
694 FMT_CONSTEXPR
inline auto compute_width(string_view s
) -> size_t {
695 size_t num_code_points
= 0;
696 // It is not a lambda for compatibility with C++14.
697 struct count_code_points
{
699 FMT_CONSTEXPR
auto operator()(uint32_t cp
, string_view
) const -> bool {
700 *count
+= detail::to_unsigned(
703 (cp
<= 0x115f || // Hangul Jamo init. consonants
704 cp
== 0x2329 || // LEFT-POINTING ANGLE BRACKET
705 cp
== 0x232a || // RIGHT-POINTING ANGLE BRACKET
706 // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
707 (cp
>= 0x2e80 && cp
<= 0xa4cf && cp
!= 0x303f) ||
708 (cp
>= 0xac00 && cp
<= 0xd7a3) || // Hangul Syllables
709 (cp
>= 0xf900 && cp
<= 0xfaff) || // CJK Compatibility Ideographs
710 (cp
>= 0xfe10 && cp
<= 0xfe19) || // Vertical Forms
711 (cp
>= 0xfe30 && cp
<= 0xfe6f) || // CJK Compatibility Forms
712 (cp
>= 0xff00 && cp
<= 0xff60) || // Fullwidth Forms
713 (cp
>= 0xffe0 && cp
<= 0xffe6) || // Fullwidth Forms
714 (cp
>= 0x20000 && cp
<= 0x2fffd) || // CJK
715 (cp
>= 0x30000 && cp
<= 0x3fffd) ||
716 // Miscellaneous Symbols and Pictographs + Emoticons:
717 (cp
>= 0x1f300 && cp
<= 0x1f64f) ||
718 // Supplemental Symbols and Pictographs:
719 (cp
>= 0x1f900 && cp
<= 0x1f9ff))));
723 // We could avoid branches by using utf8_decode directly.
724 for_each_codepoint(s
, count_code_points
{&num_code_points
});
725 return num_code_points
;
728 template <typename Char
>
729 inline auto code_point_index(basic_string_view
<Char
> s
, size_t n
) -> size_t {
730 size_t size
= s
.size();
731 return n
< size
? n
: size
;
734 // Calculates the index of the nth code point in a UTF-8 string.
735 inline auto code_point_index(string_view s
, size_t n
) -> size_t {
736 size_t result
= s
.size();
737 const char* begin
= s
.begin();
738 for_each_codepoint(s
, [begin
, &n
, &result
](uint32_t, string_view sv
) {
743 result
= to_unsigned(sv
.begin() - begin
);
749 template <typename T
> struct is_integral
: std::is_integral
<T
> {};
750 template <> struct is_integral
<int128_opt
> : std::true_type
{};
751 template <> struct is_integral
<uint128_t
> : std::true_type
{};
753 template <typename T
>
755 std::integral_constant
<bool, std::numeric_limits
<T
>::is_signed
||
756 std::is_same
<T
, int128_opt
>::value
>;
758 template <typename T
>
760 bool_constant
<is_integral
<T
>::value
&& !std::is_same
<T
, bool>::value
&&
761 !std::is_same
<T
, char>::value
&&
762 !std::is_same
<T
, wchar_t>::value
>;
764 #ifndef FMT_USE_FLOAT
765 # define FMT_USE_FLOAT 1
767 #ifndef FMT_USE_DOUBLE
768 # define FMT_USE_DOUBLE 1
770 #ifndef FMT_USE_LONG_DOUBLE
771 # define FMT_USE_LONG_DOUBLE 1
774 #if defined(FMT_USE_FLOAT128)
775 // Use the provided definition.
776 #elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE(<quadmath.h>)
777 # define FMT_USE_FLOAT128 1
778 #elif FMT_GCC_VERSION && defined(_GLIBCXX_USE_FLOAT128) && \
779 !defined(__STRICT_ANSI__)
780 # define FMT_USE_FLOAT128 1
782 # define FMT_USE_FLOAT128 0
785 using float128
= __float128
;
787 using float128
= void;
790 template <typename T
> using is_float128
= std::is_same
<T
, float128
>;
792 template <typename T
>
793 using is_floating_point
=
794 bool_constant
<std::is_floating_point
<T
>::value
|| is_float128
<T
>::value
>;
796 template <typename T
, bool = std::is_floating_point
<T
>::value
>
797 struct is_fast_float
: bool_constant
<std::numeric_limits
<T
>::is_iec559
&&
798 sizeof(T
) <= sizeof(double)> {};
799 template <typename T
> struct is_fast_float
<T
, false> : std::false_type
{};
801 template <typename T
>
802 using is_double_double
= bool_constant
<std::numeric_limits
<T
>::digits
== 106>;
804 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
805 # define FMT_USE_FULL_CACHE_DRAGONBOX 0
808 template <typename T
, typename Enable
= void>
809 struct is_locale
: std::false_type
{};
810 template <typename T
>
811 struct is_locale
<T
, void_t
<decltype(T::classic())>> : std::true_type
{};
812 } // namespace detail
816 // The number of characters to store in the basic_memory_buffer object itself
817 // to avoid dynamic memory allocation.
818 enum { inline_buffer_size
= 500 };
821 * A dynamically growing memory buffer for trivially copyable/constructible
822 * types with the first `SIZE` elements stored in the object itself. Most
823 * commonly used via the `memory_buffer` alias for `char`.
827 * auto out = fmt::memory_buffer();
828 * fmt::format_to(std::back_inserter(out), "The answer is {}.", 42);
830 * This will append "The answer is 42." to `out`. The buffer content can be
831 * converted to `std::string` with `to_string(out)`.
833 template <typename T
, size_t SIZE
= inline_buffer_size
,
834 typename Allocator
= std::allocator
<T
>>
835 class basic_memory_buffer
: public detail::buffer
<T
> {
839 // Don't inherit from Allocator to avoid generating type_info for it.
840 FMT_NO_UNIQUE_ADDRESS Allocator alloc_
;
842 // Deallocate memory allocated by the buffer.
843 FMT_CONSTEXPR20
void deallocate() {
844 T
* data
= this->data();
845 if (data
!= store_
) alloc_
.deallocate(data
, this->capacity());
848 static FMT_CONSTEXPR20
void grow(detail::buffer
<T
>& buf
, size_t size
) {
849 detail::abort_fuzzing_if(size
> 5000);
850 auto& self
= static_cast<basic_memory_buffer
&>(buf
);
851 const size_t max_size
=
852 std::allocator_traits
<Allocator
>::max_size(self
.alloc_
);
853 size_t old_capacity
= buf
.capacity();
854 size_t new_capacity
= old_capacity
+ old_capacity
/ 2;
855 if (size
> new_capacity
)
857 else if (new_capacity
> max_size
)
858 new_capacity
= size
> max_size
? size
: max_size
;
859 T
* old_data
= buf
.data();
860 T
* new_data
= self
.alloc_
.allocate(new_capacity
);
861 // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
862 detail::assume(buf
.size() <= new_capacity
);
863 // The following code doesn't throw, so the raw pointer above doesn't leak.
864 memcpy(new_data
, old_data
, buf
.size() * sizeof(T
));
865 self
.set(new_data
, new_capacity
);
866 // deallocate must not throw according to the standard, but even if it does,
867 // the buffer already uses the new storage and will deallocate it in
869 if (old_data
!= self
.store_
) self
.alloc_
.deallocate(old_data
, old_capacity
);
873 using value_type
= T
;
874 using const_reference
= const T
&;
876 FMT_CONSTEXPR20
explicit basic_memory_buffer(
877 const Allocator
& alloc
= Allocator())
878 : detail::buffer
<T
>(grow
), alloc_(alloc
) {
879 this->set(store_
, SIZE
);
880 if (detail::is_constant_evaluated()) detail::fill_n(store_
, SIZE
, T());
882 FMT_CONSTEXPR20
~basic_memory_buffer() { deallocate(); }
885 // Move data from other to this buffer.
886 FMT_CONSTEXPR20
void move(basic_memory_buffer
& other
) {
887 alloc_
= std::move(other
.alloc_
);
888 T
* data
= other
.data();
889 size_t size
= other
.size(), capacity
= other
.capacity();
890 if (data
== other
.store_
) {
891 this->set(store_
, capacity
);
892 detail::copy
<T
>(other
.store_
, other
.store_
+ size
, store_
);
894 this->set(data
, capacity
);
895 // Set pointer to the inline array so that delete is not called
896 // when deallocating.
897 other
.set(other
.store_
, 0);
904 /// Constructs a `basic_memory_buffer` object moving the content of the other
906 FMT_CONSTEXPR20
basic_memory_buffer(basic_memory_buffer
&& other
) noexcept
907 : detail::buffer
<T
>(grow
) {
911 /// Moves the content of the other `basic_memory_buffer` object to this one.
912 auto operator=(basic_memory_buffer
&& other
) noexcept
-> basic_memory_buffer
& {
913 FMT_ASSERT(this != &other
, "");
919 // Returns a copy of the allocator associated with this buffer.
920 auto get_allocator() const -> Allocator
{ return alloc_
; }
922 /// Resizes the buffer to contain `count` elements. If T is a POD type new
923 /// elements may not be initialized.
924 FMT_CONSTEXPR20
void resize(size_t count
) { this->try_resize(count
); }
926 /// Increases the buffer capacity to `new_capacity`.
927 void reserve(size_t new_capacity
) { this->try_reserve(new_capacity
); }
929 using detail::buffer
<T
>::append
;
930 template <typename ContiguousRange
>
931 void append(const ContiguousRange
& range
) {
932 append(range
.data(), range
.data() + range
.size());
936 using memory_buffer
= basic_memory_buffer
<char>;
938 template <typename T
, size_t SIZE
, typename Allocator
>
939 struct is_contiguous
<basic_memory_buffer
<T
, SIZE
, Allocator
>> : std::true_type
{
944 FMT_API
auto write_console(int fd
, string_view text
) -> bool;
945 FMT_API
void print(std::FILE*, string_view
);
946 } // namespace detail
950 // Suppress a misleading warning in older versions of clang.
951 #if FMT_CLANG_VERSION
952 # pragma clang diagnostic ignored "-Wweak-vtables"
955 /// An error reported from a formatting function.
956 class FMT_SO_VISIBILITY("default") format_error
: public std::runtime_error
{
958 using std::runtime_error::runtime_error
;
961 namespace detail_exported
{
962 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
963 template <typename Char
, size_t N
> struct fixed_string
{
964 constexpr fixed_string(const Char (&str
)[N
]) {
965 detail::copy
<Char
, const Char
*, Char
*>(static_cast<const Char
*>(str
),
972 // Converts a compile-time string to basic_string_view.
973 template <typename Char
, size_t N
>
974 constexpr auto compile_string_to_view(const Char (&s
)[N
])
975 -> basic_string_view
<Char
> {
976 // Remove trailing NUL character if needed. Won't be present if this is used
977 // with a raw character array (i.e. not defined as a string).
978 return {s
, N
- (std::char_traits
<Char
>::to_int_type(s
[N
- 1]) == 0 ? 1 : 0)};
980 template <typename Char
>
981 constexpr auto compile_string_to_view(basic_string_view
<Char
> s
)
982 -> basic_string_view
<Char
> {
985 } // namespace detail_exported
987 // A generic formatting context with custom output iterator and character
988 // (code unit) support. Char is the format string code unit type which can be
989 // different from OutputIt::value_type.
990 template <typename OutputIt
, typename Char
> class generic_context
{
993 basic_format_args
<generic_context
> args_
;
994 detail::locale_ref loc_
;
997 using char_type
= Char
;
998 using iterator
= OutputIt
;
999 using parse_context_type
= basic_format_parse_context
<Char
>;
1000 template <typename T
> using formatter_type
= formatter
<T
, Char
>;
1002 constexpr generic_context(OutputIt out
,
1003 basic_format_args
<generic_context
> ctx_args
,
1004 detail::locale_ref loc
= {})
1005 : out_(out
), args_(ctx_args
), loc_(loc
) {}
1006 generic_context(generic_context
&&) = default;
1007 generic_context(const generic_context
&) = delete;
1008 void operator=(const generic_context
&) = delete;
1010 constexpr auto arg(int id
) const -> basic_format_arg
<generic_context
> {
1011 return args_
.get(id
);
1013 auto arg(basic_string_view
<Char
> name
) -> basic_format_arg
<generic_context
> {
1014 return args_
.get(name
);
1016 FMT_CONSTEXPR
auto arg_id(basic_string_view
<Char
> name
) -> int {
1017 return args_
.get_id(name
);
1019 auto args() const -> const basic_format_args
<generic_context
>& {
1023 FMT_CONSTEXPR
auto out() -> iterator
{ return out_
; }
1025 void advance_to(iterator it
) {
1026 if (!detail::is_back_insert_iterator
<iterator
>()) out_
= it
;
1029 FMT_CONSTEXPR
auto locale() -> detail::locale_ref
{ return loc_
; }
1034 basic_format_arg
<format_context
> value_
;
1037 template <typename T
, FMT_ENABLE_IF(!detail::is_float128
<T
>::value
)>
1038 loc_value(T value
) : value_(detail::make_arg
<format_context
>(value
)) {}
1040 template <typename T
, FMT_ENABLE_IF(detail::is_float128
<T
>::value
)>
1043 template <typename Visitor
> auto visit(Visitor
&& vis
) -> decltype(vis(0)) {
1044 return value_
.visit(vis
);
1048 // A locale facet that formats values in UTF-8.
1049 // It is parameterized on the locale to avoid the heavy <locale> include.
1050 template <typename Locale
> class format_facet
: public Locale::facet
{
1052 std::string separator_
;
1053 std::string grouping_
;
1054 std::string decimal_point_
;
1057 virtual auto do_put(appender out
, loc_value val
,
1058 const format_specs
& specs
) const -> bool;
1061 static FMT_API typename
Locale::id id
;
1063 explicit format_facet(Locale
& loc
);
1064 explicit format_facet(string_view sep
= "",
1065 std::initializer_list
<unsigned char> g
= {3},
1066 std::string decimal_point
= ".")
1067 : separator_(sep
.data(), sep
.size()),
1068 grouping_(g
.begin(), g
.end()),
1069 decimal_point_(decimal_point
) {}
1071 auto put(appender out
, loc_value val
, const format_specs
& specs
) const
1073 return do_put(out
, val
, specs
);
1081 // Returns true if value is negative, false otherwise.
1082 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
1083 template <typename T
, FMT_ENABLE_IF(is_signed
<T
>::value
)>
1084 constexpr auto is_negative(T value
) -> bool {
1087 template <typename T
, FMT_ENABLE_IF(!is_signed
<T
>::value
)>
1088 constexpr auto is_negative(T
) -> bool {
1092 template <typename T
>
1093 FMT_CONSTEXPR
auto is_supported_floating_point(T
) -> bool {
1094 if (std::is_same
<T
, float>()) return FMT_USE_FLOAT
;
1095 if (std::is_same
<T
, double>()) return FMT_USE_DOUBLE
;
1096 if (std::is_same
<T
, long double>()) return FMT_USE_LONG_DOUBLE
;
1100 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
1101 // represent all values of an integral type T.
1102 template <typename T
>
1103 using uint32_or_64_or_128_t
=
1104 conditional_t
<num_bits
<T
>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS
,
1106 conditional_t
<num_bits
<T
>() <= 64, uint64_t, uint128_t
>>;
1107 template <typename T
>
1108 using uint64_or_128_t
= conditional_t
<num_bits
<T
>() <= 64, uint64_t, uint128_t
>;
1110 #define FMT_POWERS_OF_10(factor) \
1111 factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \
1112 (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \
1113 (factor) * 100000000, (factor) * 1000000000
1115 // Converts value in the range [0, 100) to a string.
1116 constexpr auto digits2(size_t value
) -> const char* {
1117 // GCC generates slightly better code when value is pointer-size.
1118 return &"0001020304050607080910111213141516171819"
1119 "2021222324252627282930313233343536373839"
1120 "4041424344454647484950515253545556575859"
1121 "6061626364656667686970717273747576777879"
1122 "8081828384858687888990919293949596979899"[value
* 2];
1125 // Sign is a template parameter to workaround a bug in gcc 4.8.
1126 template <typename Char
, typename Sign
> constexpr auto sign(Sign s
) -> Char
{
1127 #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1128 static_assert(std::is_same
<Sign
, sign_t
>::value
, "");
1130 return static_cast<char>(((' ' << 24) | ('+' << 16) | ('-' << 8)) >> (s
* 8));
1133 template <typename T
> FMT_CONSTEXPR
auto count_digits_fallback(T n
) -> int {
1136 // Integer division is slow so do it for a group of four digits instead
1137 // of for every digit. The idea comes from the talk by Alexandrescu
1138 // "Three Optimization Tips for C++". See speed-test for a comparison.
1139 if (n
< 10) return count
;
1140 if (n
< 100) return count
+ 1;
1141 if (n
< 1000) return count
+ 2;
1142 if (n
< 10000) return count
+ 3;
1148 FMT_CONSTEXPR
inline auto count_digits(uint128_opt n
) -> int {
1149 return count_digits_fallback(n
);
1153 #ifdef FMT_BUILTIN_CLZLL
1154 // It is a separate function rather than a part of count_digits to workaround
1155 // the lack of static constexpr in constexpr functions.
1156 inline auto do_count_digits(uint64_t n
) -> int {
1157 // This has comparable performance to the version by Kendall Willets
1158 // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
1159 // but uses smaller tables.
1160 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
1161 static constexpr uint8_t bsr2log10
[] = {
1162 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1163 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1164 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1165 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1166 auto t
= bsr2log10
[FMT_BUILTIN_CLZLL(n
| 1) ^ 63];
1167 static constexpr const uint64_t zero_or_powers_of_10
[] = {
1168 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1169 10000000000000000000ULL};
1170 return t
- (n
< zero_or_powers_of_10
[t
]);
1174 // Returns the number of decimal digits in n. Leading zeros are not counted
1175 // except for n == 0 in which case count_digits returns 1.
1176 FMT_CONSTEXPR20
inline auto count_digits(uint64_t n
) -> int {
1177 #ifdef FMT_BUILTIN_CLZLL
1178 if (!is_constant_evaluated()) return do_count_digits(n
);
1180 return count_digits_fallback(n
);
1183 // Counts the number of digits in n. BITS = log2(radix).
1184 template <int BITS
, typename UInt
>
1185 FMT_CONSTEXPR
auto count_digits(UInt n
) -> int {
1186 #ifdef FMT_BUILTIN_CLZ
1187 if (!is_constant_evaluated() && num_bits
<UInt
>() == 32)
1188 return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n
) | 1) ^ 31) / BITS
+ 1;
1190 // Lambda avoids unreachable code warnings from NVHPC.
1195 } while ((m
>>= BITS
) != 0);
1200 #ifdef FMT_BUILTIN_CLZ
1201 // It is a separate function rather than a part of count_digits to workaround
1202 // the lack of static constexpr in constexpr functions.
1203 FMT_INLINE
auto do_count_digits(uint32_t n
) -> int {
1204 // An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1205 // This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1206 # define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1207 static constexpr uint64_t table
[] = {
1208 FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1209 FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1210 FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1211 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1212 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1213 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1214 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1215 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1216 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1217 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1218 FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1220 auto inc
= table
[FMT_BUILTIN_CLZ(n
| 1) ^ 31];
1221 return static_cast<int>((n
+ inc
) >> 32);
1225 // Optional version of count_digits for better performance on 32-bit platforms.
1226 FMT_CONSTEXPR20
inline auto count_digits(uint32_t n
) -> int {
1227 #ifdef FMT_BUILTIN_CLZ
1228 if (!is_constant_evaluated()) {
1229 return do_count_digits(n
);
1232 return count_digits_fallback(n
);
1235 template <typename Int
> constexpr auto digits10() noexcept
-> int {
1236 return std::numeric_limits
<Int
>::digits10
;
1238 template <> constexpr auto digits10
<int128_opt
>() noexcept
-> int { return 38; }
1239 template <> constexpr auto digits10
<uint128_t
>() noexcept
-> int { return 38; }
1241 template <typename Char
> struct thousands_sep_result
{
1242 std::string grouping
;
1246 template <typename Char
>
1247 FMT_API
auto thousands_sep_impl(locale_ref loc
) -> thousands_sep_result
<Char
>;
1248 template <typename Char
>
1249 inline auto thousands_sep(locale_ref loc
) -> thousands_sep_result
<Char
> {
1250 auto result
= thousands_sep_impl
<char>(loc
);
1251 return {result
.grouping
, Char(result
.thousands_sep
)};
1254 inline auto thousands_sep(locale_ref loc
) -> thousands_sep_result
<wchar_t> {
1255 return thousands_sep_impl
<wchar_t>(loc
);
1258 template <typename Char
>
1259 FMT_API
auto decimal_point_impl(locale_ref loc
) -> Char
;
1260 template <typename Char
> inline auto decimal_point(locale_ref loc
) -> Char
{
1261 return Char(decimal_point_impl
<char>(loc
));
1263 template <> inline auto decimal_point(locale_ref loc
) -> wchar_t {
1264 return decimal_point_impl
<wchar_t>(loc
);
1267 // Compares two characters for equality.
1268 template <typename Char
> auto equal2(const Char
* lhs
, const char* rhs
) -> bool {
1269 return lhs
[0] == Char(rhs
[0]) && lhs
[1] == Char(rhs
[1]);
1271 inline auto equal2(const char* lhs
, const char* rhs
) -> bool {
1272 return memcmp(lhs
, rhs
, 2) == 0;
1275 // Copies two characters from src to dst.
1276 template <typename Char
>
1277 FMT_CONSTEXPR20 FMT_INLINE
void copy2(Char
* dst
, const char* src
) {
1278 if (!is_constant_evaluated() && sizeof(Char
) == sizeof(char)) {
1279 memcpy(dst
, src
, 2);
1282 *dst
++ = static_cast<Char
>(*src
++);
1283 *dst
= static_cast<Char
>(*src
);
1286 template <typename Iterator
> struct format_decimal_result
{
1291 // Formats a decimal unsigned integer value writing into out pointing to a
1292 // buffer of specified size. The caller must ensure that the buffer is large
1294 template <typename Char
, typename UInt
>
1295 FMT_CONSTEXPR20
auto format_decimal(Char
* out
, UInt value
, int size
)
1296 -> format_decimal_result
<Char
*> {
1297 FMT_ASSERT(size
>= count_digits(value
), "invalid digit count");
1300 while (value
>= 100) {
1301 // Integer division is slow so do it for a group of two digits instead
1302 // of for every digit. The idea comes from the talk by Alexandrescu
1303 // "Three Optimization Tips for C++". See speed-test for a comparison.
1305 copy2(out
, digits2(static_cast<size_t>(value
% 100)));
1309 *--out
= static_cast<Char
>('0' + value
);
1313 copy2(out
, digits2(static_cast<size_t>(value
)));
1317 template <typename Char
, typename UInt
, typename Iterator
,
1318 FMT_ENABLE_IF(!std::is_pointer
<remove_cvref_t
<Iterator
>>::value
)>
1319 FMT_CONSTEXPR
inline auto format_decimal(Iterator out
, UInt value
, int size
)
1320 -> format_decimal_result
<Iterator
> {
1321 // Buffer is large enough to hold all digits (digits10 + 1).
1322 Char buffer
[digits10
<UInt
>() + 1] = {};
1323 auto end
= format_decimal(buffer
, value
, size
).end
;
1324 return {out
, detail::copy_noinline
<Char
>(buffer
, end
, out
)};
1327 template <unsigned BASE_BITS
, typename Char
, typename UInt
>
1328 FMT_CONSTEXPR
auto format_uint(Char
* buffer
, UInt value
, int num_digits
,
1329 bool upper
= false) -> Char
* {
1330 buffer
+= num_digits
;
1333 const char* digits
= upper
? "0123456789ABCDEF" : "0123456789abcdef";
1334 unsigned digit
= static_cast<unsigned>(value
& ((1 << BASE_BITS
) - 1));
1335 *--buffer
= static_cast<Char
>(BASE_BITS
< 4 ? static_cast<char>('0' + digit
)
1337 } while ((value
>>= BASE_BITS
) != 0);
1341 template <unsigned BASE_BITS
, typename Char
, typename It
, typename UInt
>
1342 FMT_CONSTEXPR
inline auto format_uint(It out
, UInt value
, int num_digits
,
1343 bool upper
= false) -> It
{
1344 if (auto ptr
= to_pointer
<Char
>(out
, to_unsigned(num_digits
))) {
1345 format_uint
<BASE_BITS
>(ptr
, value
, num_digits
, upper
);
1348 // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1349 char buffer
[num_bits
<UInt
>() / BASE_BITS
+ 1] = {};
1350 format_uint
<BASE_BITS
>(buffer
, value
, num_digits
, upper
);
1351 return detail::copy_noinline
<Char
>(buffer
, buffer
+ num_digits
, out
);
1354 // A converter from UTF-8 to UTF-16.
1355 class utf8_to_utf16
{
1357 basic_memory_buffer
<wchar_t> buffer_
;
1360 FMT_API
explicit utf8_to_utf16(string_view s
);
1361 operator basic_string_view
<wchar_t>() const { return {&buffer_
[0], size()}; }
1362 auto size() const -> size_t { return buffer_
.size() - 1; }
1363 auto c_str() const -> const wchar_t* { return &buffer_
[0]; }
1364 auto str() const -> std::wstring
{ return {&buffer_
[0], size()}; }
1367 enum class to_utf8_error_policy
{ abort
, replace
};
1369 // A converter from UTF-16/UTF-32 (host endian) to UTF-8.
1370 template <typename WChar
, typename Buffer
= memory_buffer
> class to_utf8
{
1376 explicit to_utf8(basic_string_view
<WChar
> s
,
1377 to_utf8_error_policy policy
= to_utf8_error_policy::abort
) {
1378 static_assert(sizeof(WChar
) == 2 || sizeof(WChar
) == 4,
1379 "Expect utf16 or utf32");
1380 if (!convert(s
, policy
))
1381 FMT_THROW(std::runtime_error(sizeof(WChar
) == 2 ? "invalid utf16"
1382 : "invalid utf32"));
1384 operator string_view() const { return string_view(&buffer_
[0], size()); }
1385 auto size() const -> size_t { return buffer_
.size() - 1; }
1386 auto c_str() const -> const char* { return &buffer_
[0]; }
1387 auto str() const -> std::string
{ return std::string(&buffer_
[0], size()); }
1389 // Performs conversion returning a bool instead of throwing exception on
1390 // conversion error. This method may still throw in case of memory allocation
1392 auto convert(basic_string_view
<WChar
> s
,
1393 to_utf8_error_policy policy
= to_utf8_error_policy::abort
)
1395 if (!convert(buffer_
, s
, policy
)) return false;
1396 buffer_
.push_back(0);
1399 static auto convert(Buffer
& buf
, basic_string_view
<WChar
> s
,
1400 to_utf8_error_policy policy
= to_utf8_error_policy::abort
)
1402 for (auto p
= s
.begin(); p
!= s
.end(); ++p
) {
1403 uint32_t c
= static_cast<uint32_t>(*p
);
1404 if (sizeof(WChar
) == 2 && c
>= 0xd800 && c
<= 0xdfff) {
1405 // Handle a surrogate pair.
1407 if (p
== s
.end() || (c
& 0xfc00) != 0xd800 || (*p
& 0xfc00) != 0xdc00) {
1408 if (policy
== to_utf8_error_policy::abort
) return false;
1409 buf
.append(string_view("\xEF\xBF\xBD"));
1412 c
= (c
<< 10) + static_cast<uint32_t>(*p
) - 0x35fdc00;
1414 } else if (c
< 0x80) {
1415 buf
.push_back(static_cast<char>(c
));
1416 } else if (c
< 0x800) {
1417 buf
.push_back(static_cast<char>(0xc0 | (c
>> 6)));
1418 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1419 } else if ((c
>= 0x800 && c
<= 0xd7ff) || (c
>= 0xe000 && c
<= 0xffff)) {
1420 buf
.push_back(static_cast<char>(0xe0 | (c
>> 12)));
1421 buf
.push_back(static_cast<char>(0x80 | ((c
& 0xfff) >> 6)));
1422 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1423 } else if (c
>= 0x10000 && c
<= 0x10ffff) {
1424 buf
.push_back(static_cast<char>(0xf0 | (c
>> 18)));
1425 buf
.push_back(static_cast<char>(0x80 | ((c
& 0x3ffff) >> 12)));
1426 buf
.push_back(static_cast<char>(0x80 | ((c
& 0xfff) >> 6)));
1427 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1436 // Computes 128-bit result of multiplication of two 64-bit unsigned integers.
1437 inline auto umul128(uint64_t x
, uint64_t y
) noexcept
-> uint128_fallback
{
1439 auto p
= static_cast<uint128_opt
>(x
) * static_cast<uint128_opt
>(y
);
1440 return {static_cast<uint64_t>(p
>> 64), static_cast<uint64_t>(p
)};
1441 #elif defined(_MSC_VER) && defined(_M_X64)
1442 auto hi
= uint64_t();
1443 auto lo
= _umul128(x
, y
, &hi
);
1446 const uint64_t mask
= static_cast<uint64_t>(max_value
<uint32_t>());
1448 uint64_t a
= x
>> 32;
1449 uint64_t b
= x
& mask
;
1450 uint64_t c
= y
>> 32;
1451 uint64_t d
= y
& mask
;
1453 uint64_t ac
= a
* c
;
1454 uint64_t bc
= b
* c
;
1455 uint64_t ad
= a
* d
;
1456 uint64_t bd
= b
* d
;
1458 uint64_t intermediate
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
);
1460 return {ac
+ (intermediate
>> 32) + (ad
>> 32) + (bc
>> 32),
1461 (intermediate
<< 32) + (bd
& mask
)};
1465 namespace dragonbox
{
1466 // Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
1467 // https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
1468 inline auto floor_log10_pow2(int e
) noexcept
-> int {
1469 FMT_ASSERT(e
<= 2620 && e
>= -2620, "too large exponent");
1470 static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
1471 return (e
* 315653) >> 20;
1474 inline auto floor_log2_pow10(int e
) noexcept
-> int {
1475 FMT_ASSERT(e
<= 1233 && e
>= -1233, "too large exponent");
1476 return (e
* 1741647) >> 19;
1479 // Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
1480 inline auto umul128_upper64(uint64_t x
, uint64_t y
) noexcept
-> uint64_t {
1482 auto p
= static_cast<uint128_opt
>(x
) * static_cast<uint128_opt
>(y
);
1483 return static_cast<uint64_t>(p
>> 64);
1484 #elif defined(_MSC_VER) && defined(_M_X64)
1485 return __umulh(x
, y
);
1487 return umul128(x
, y
).high();
1491 // Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
1492 // 128-bit unsigned integer.
1493 inline auto umul192_upper128(uint64_t x
, uint128_fallback y
) noexcept
1494 -> uint128_fallback
{
1495 uint128_fallback r
= umul128(x
, y
.high());
1496 r
+= umul128_upper64(x
, y
.low());
1500 FMT_API
auto get_cached_power(int k
) noexcept
-> uint128_fallback
;
1502 // Type-specific information that Dragonbox uses.
1503 template <typename T
, typename Enable
= void> struct float_info
;
1505 template <> struct float_info
<float> {
1506 using carrier_uint
= uint32_t;
1507 static const int exponent_bits
= 8;
1508 static const int kappa
= 1;
1509 static const int big_divisor
= 100;
1510 static const int small_divisor
= 10;
1511 static const int min_k
= -31;
1512 static const int max_k
= 46;
1513 static const int shorter_interval_tie_lower_threshold
= -35;
1514 static const int shorter_interval_tie_upper_threshold
= -35;
1517 template <> struct float_info
<double> {
1518 using carrier_uint
= uint64_t;
1519 static const int exponent_bits
= 11;
1520 static const int kappa
= 2;
1521 static const int big_divisor
= 1000;
1522 static const int small_divisor
= 100;
1523 static const int min_k
= -292;
1524 static const int max_k
= 341;
1525 static const int shorter_interval_tie_lower_threshold
= -77;
1526 static const int shorter_interval_tie_upper_threshold
= -77;
1529 // An 80- or 128-bit floating point number.
1530 template <typename T
>
1531 struct float_info
<T
, enable_if_t
<std::numeric_limits
<T
>::digits
== 64 ||
1532 std::numeric_limits
<T
>::digits
== 113 ||
1533 is_float128
<T
>::value
>> {
1534 using carrier_uint
= detail::uint128_t
;
1535 static const int exponent_bits
= 15;
1538 // A double-double floating point number.
1539 template <typename T
>
1540 struct float_info
<T
, enable_if_t
<is_double_double
<T
>::value
>> {
1541 using carrier_uint
= detail::uint128_t
;
1544 template <typename T
> struct decimal_fp
{
1545 using significand_type
= typename float_info
<T
>::carrier_uint
;
1546 significand_type significand
;
1550 template <typename T
> FMT_API
auto to_decimal(T x
) noexcept
-> decimal_fp
<T
>;
1551 } // namespace dragonbox
1553 // Returns true iff Float has the implicit bit which is not stored.
1554 template <typename Float
> constexpr auto has_implicit_bit() -> bool {
1555 // An 80-bit FP number has a 64-bit significand an no implicit bit.
1556 return std::numeric_limits
<Float
>::digits
!= 64;
1559 // Returns the number of significand bits stored in Float. The implicit bit is
1560 // not counted since it is not stored.
1561 template <typename Float
> constexpr auto num_significand_bits() -> int {
1562 // std::numeric_limits may not support __float128.
1563 return is_float128
<Float
>() ? 112
1564 : (std::numeric_limits
<Float
>::digits
-
1565 (has_implicit_bit
<Float
>() ? 1 : 0));
1568 template <typename Float
>
1569 constexpr auto exponent_mask() ->
1570 typename
dragonbox::float_info
<Float
>::carrier_uint
{
1571 using float_uint
= typename
dragonbox::float_info
<Float
>::carrier_uint
;
1572 return ((float_uint(1) << dragonbox::float_info
<Float
>::exponent_bits
) - 1)
1573 << num_significand_bits
<Float
>();
1575 template <typename Float
> constexpr auto exponent_bias() -> int {
1576 // std::numeric_limits may not support __float128.
1577 return is_float128
<Float
>() ? 16383
1578 : std::numeric_limits
<Float
>::max_exponent
- 1;
1581 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1582 template <typename Char
, typename It
>
1583 FMT_CONSTEXPR
auto write_exponent(int exp
, It it
) -> It
{
1584 FMT_ASSERT(-10000 < exp
&& exp
< 10000, "exponent out of range");
1586 *it
++ = static_cast<Char
>('-');
1589 *it
++ = static_cast<Char
>('+');
1592 const char* top
= digits2(to_unsigned(exp
/ 100));
1593 if (exp
>= 1000) *it
++ = static_cast<Char
>(top
[0]);
1594 *it
++ = static_cast<Char
>(top
[1]);
1597 const char* d
= digits2(to_unsigned(exp
));
1598 *it
++ = static_cast<Char
>(d
[0]);
1599 *it
++ = static_cast<Char
>(d
[1]);
1603 // A floating-point number f * pow(2, e) where F is an unsigned type.
1604 template <typename F
> struct basic_fp
{
1608 static constexpr const int num_significand_bits
=
1609 static_cast<int>(sizeof(F
) * num_bits
<unsigned char>());
1611 constexpr basic_fp() : f(0), e(0) {}
1612 constexpr basic_fp(uint64_t f_val
, int e_val
) : f(f_val
), e(e_val
) {}
1614 // Constructs fp from an IEEE754 floating-point number.
1615 template <typename Float
> FMT_CONSTEXPR
basic_fp(Float n
) { assign(n
); }
1617 // Assigns n to this and return true iff predecessor is closer than successor.
1618 template <typename Float
, FMT_ENABLE_IF(!is_double_double
<Float
>::value
)>
1619 FMT_CONSTEXPR
auto assign(Float n
) -> bool {
1620 static_assert(std::numeric_limits
<Float
>::digits
<= 113, "unsupported FP");
1621 // Assume Float is in the format [sign][exponent][significand].
1622 using carrier_uint
= typename
dragonbox::float_info
<Float
>::carrier_uint
;
1623 const auto num_float_significand_bits
=
1624 detail::num_significand_bits
<Float
>();
1625 const auto implicit_bit
= carrier_uint(1) << num_float_significand_bits
;
1626 const auto significand_mask
= implicit_bit
- 1;
1627 auto u
= bit_cast
<carrier_uint
>(n
);
1628 f
= static_cast<F
>(u
& significand_mask
);
1629 auto biased_e
= static_cast<int>((u
& exponent_mask
<Float
>()) >>
1630 num_float_significand_bits
);
1631 // The predecessor is closer if n is a normalized power of 2 (f == 0)
1632 // other than the smallest normalized number (biased_e > 1).
1633 auto is_predecessor_closer
= f
== 0 && biased_e
> 1;
1635 biased_e
= 1; // Subnormals use biased exponent 1 (min exponent).
1636 else if (has_implicit_bit
<Float
>())
1637 f
+= static_cast<F
>(implicit_bit
);
1638 e
= biased_e
- exponent_bias
<Float
>() - num_float_significand_bits
;
1639 if (!has_implicit_bit
<Float
>()) ++e
;
1640 return is_predecessor_closer
;
1643 template <typename Float
, FMT_ENABLE_IF(is_double_double
<Float
>::value
)>
1644 FMT_CONSTEXPR
auto assign(Float n
) -> bool {
1645 static_assert(std::numeric_limits
<double>::is_iec559
, "unsupported FP");
1646 return assign(static_cast<double>(n
));
1650 using fp
= basic_fp
<unsigned long long>;
1652 // Normalizes the value converted from double and multiplied by (1 << SHIFT).
1653 template <int SHIFT
= 0, typename F
>
1654 FMT_CONSTEXPR
auto normalize(basic_fp
<F
> value
) -> basic_fp
<F
> {
1655 // Handle subnormals.
1656 const auto implicit_bit
= F(1) << num_significand_bits
<double>();
1657 const auto shifted_implicit_bit
= implicit_bit
<< SHIFT
;
1658 while ((value
.f
& shifted_implicit_bit
) == 0) {
1662 // Subtract 1 to account for hidden bit.
1663 const auto offset
= basic_fp
<F
>::num_significand_bits
-
1664 num_significand_bits
<double>() - SHIFT
- 1;
1670 // Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
1671 FMT_CONSTEXPR
inline auto multiply(uint64_t lhs
, uint64_t rhs
) -> uint64_t {
1673 auto product
= static_cast<__uint128_t
>(lhs
) * rhs
;
1674 auto f
= static_cast<uint64_t>(product
>> 64);
1675 return (static_cast<uint64_t>(product
) & (1ULL << 63)) != 0 ? f
+ 1 : f
;
1677 // Multiply 32-bit parts of significands.
1678 uint64_t mask
= (1ULL << 32) - 1;
1679 uint64_t a
= lhs
>> 32, b
= lhs
& mask
;
1680 uint64_t c
= rhs
>> 32, d
= rhs
& mask
;
1681 uint64_t ac
= a
* c
, bc
= b
* c
, ad
= a
* d
, bd
= b
* d
;
1682 // Compute mid 64-bit of result and round.
1683 uint64_t mid
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
) + (1U << 31);
1684 return ac
+ (ad
>> 32) + (bc
>> 32) + (mid
>> 32);
1688 FMT_CONSTEXPR
inline auto operator*(fp x
, fp y
) -> fp
{
1689 return {multiply(x
.f
, y
.f
), x
.e
+ y
.e
+ 64};
1692 template <typename T
, bool doublish
= num_bits
<T
>() == num_bits
<double>()>
1693 using convert_float_result
=
1694 conditional_t
<std::is_same
<T
, float>::value
|| doublish
, double, T
>;
1696 template <typename T
>
1697 constexpr auto convert_float(T value
) -> convert_float_result
<T
> {
1698 return static_cast<convert_float_result
<T
>>(value
);
1701 template <typename Char
, typename OutputIt
>
1702 FMT_NOINLINE FMT_CONSTEXPR
auto fill(OutputIt it
, size_t n
, const fill_t
& fill
)
1704 auto fill_size
= fill
.size();
1705 if (fill_size
== 1) return detail::fill_n(it
, n
, fill
.template get
<Char
>());
1706 if (const Char
* data
= fill
.template data
<Char
>()) {
1707 for (size_t i
= 0; i
< n
; ++i
) it
= copy
<Char
>(data
, data
+ fill_size
, it
);
1712 // Writes the output of f, padded according to format specifications in specs.
1713 // size: output size in code units.
1714 // width: output display width in (terminal) column positions.
1715 template <typename Char
, align::type align
= align::left
, typename OutputIt
,
1717 FMT_CONSTEXPR
auto write_padded(OutputIt out
, const format_specs
& specs
,
1718 size_t size
, size_t width
, F
&& f
) -> OutputIt
{
1719 static_assert(align
== align::left
|| align
== align::right
, "");
1720 unsigned spec_width
= to_unsigned(specs
.width
);
1721 size_t padding
= spec_width
> width
? spec_width
- width
: 0;
1722 // Shifts are encoded as string literals because static constexpr is not
1723 // supported in constexpr functions.
1724 auto* shifts
= align
== align::left
? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1725 size_t left_padding
= padding
>> shifts
[specs
.align
];
1726 size_t right_padding
= padding
- left_padding
;
1727 auto it
= reserve(out
, size
+ padding
* specs
.fill
.size());
1728 if (left_padding
!= 0) it
= fill
<Char
>(it
, left_padding
, specs
.fill
);
1730 if (right_padding
!= 0) it
= fill
<Char
>(it
, right_padding
, specs
.fill
);
1731 return base_iterator(out
, it
);
1734 template <typename Char
, align::type align
= align::left
, typename OutputIt
,
1736 constexpr auto write_padded(OutputIt out
, const format_specs
& specs
,
1737 size_t size
, F
&& f
) -> OutputIt
{
1738 return write_padded
<Char
, align
>(out
, specs
, size
, size
, f
);
1741 template <typename Char
, align::type align
= align::left
, typename OutputIt
>
1742 FMT_CONSTEXPR
auto write_bytes(OutputIt out
, string_view bytes
,
1743 const format_specs
& specs
= {}) -> OutputIt
{
1744 return write_padded
<Char
, align
>(
1745 out
, specs
, bytes
.size(), [bytes
](reserve_iterator
<OutputIt
> it
) {
1746 const char* data
= bytes
.data();
1747 return copy
<Char
>(data
, data
+ bytes
.size(), it
);
1751 template <typename Char
, typename OutputIt
, typename UIntPtr
>
1752 auto write_ptr(OutputIt out
, UIntPtr value
, const format_specs
* specs
)
1754 int num_digits
= count_digits
<4>(value
);
1755 auto size
= to_unsigned(num_digits
) + size_t(2);
1756 auto write
= [=](reserve_iterator
<OutputIt
> it
) {
1757 *it
++ = static_cast<Char
>('0');
1758 *it
++ = static_cast<Char
>('x');
1759 return format_uint
<4, Char
>(it
, value
, num_digits
);
1761 return specs
? write_padded
<Char
, align::right
>(out
, *specs
, size
, write
)
1762 : base_iterator(out
, write(reserve(out
, size
)));
1765 // Returns true iff the code point cp is printable.
1766 FMT_API
auto is_printable(uint32_t cp
) -> bool;
1768 inline auto needs_escape(uint32_t cp
) -> bool {
1769 return cp
< 0x20 || cp
== 0x7f || cp
== '"' || cp
== '\\' ||
1773 template <typename Char
> struct find_escape_result
{
1779 template <typename Char
>
1780 auto find_escape(const Char
* begin
, const Char
* end
)
1781 -> find_escape_result
<Char
> {
1782 for (; begin
!= end
; ++begin
) {
1783 uint32_t cp
= static_cast<unsigned_char
<Char
>>(*begin
);
1784 if (const_check(sizeof(Char
) == 1) && cp
>= 0x80) continue;
1785 if (needs_escape(cp
)) return {begin
, begin
+ 1, cp
};
1787 return {begin
, nullptr, 0};
1790 inline auto find_escape(const char* begin
, const char* end
)
1791 -> find_escape_result
<char> {
1792 if (!use_utf8()) return find_escape
<char>(begin
, end
);
1793 auto result
= find_escape_result
<char>{end
, nullptr, 0};
1794 for_each_codepoint(string_view(begin
, to_unsigned(end
- begin
)),
1795 [&](uint32_t cp
, string_view sv
) {
1796 if (needs_escape(cp
)) {
1797 result
= {sv
.begin(), sv
.end(), cp
};
1805 #define FMT_STRING_IMPL(s, base, explicit) \
1807 /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
1808 /* Use a macro-like name to avoid shadowing warnings. */ \
1809 struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
1810 using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1811 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1812 operator fmt::basic_string_view<char_type>() const { \
1813 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1816 return FMT_COMPILE_STRING(); \
1820 * Constructs a compile-time format string from a string literal `s`.
1824 * // A compile-time error because 'd' is an invalid specifier for strings.
1825 * std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
1827 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1829 template <size_t width
, typename Char
, typename OutputIt
>
1830 auto write_codepoint(OutputIt out
, char prefix
, uint32_t cp
) -> OutputIt
{
1831 *out
++ = static_cast<Char
>('\\');
1832 *out
++ = static_cast<Char
>(prefix
);
1834 fill_n(buf
, width
, static_cast<Char
>('0'));
1835 format_uint
<4>(buf
, cp
, width
);
1836 return copy
<Char
>(buf
, buf
+ width
, out
);
1839 template <typename OutputIt
, typename Char
>
1840 auto write_escaped_cp(OutputIt out
, const find_escape_result
<Char
>& escape
)
1842 auto c
= static_cast<Char
>(escape
.cp
);
1843 switch (escape
.cp
) {
1845 *out
++ = static_cast<Char
>('\\');
1846 c
= static_cast<Char
>('n');
1849 *out
++ = static_cast<Char
>('\\');
1850 c
= static_cast<Char
>('r');
1853 *out
++ = static_cast<Char
>('\\');
1854 c
= static_cast<Char
>('t');
1861 *out
++ = static_cast<Char
>('\\');
1864 if (escape
.cp
< 0x100) return write_codepoint
<2, Char
>(out
, 'x', escape
.cp
);
1865 if (escape
.cp
< 0x10000)
1866 return write_codepoint
<4, Char
>(out
, 'u', escape
.cp
);
1867 if (escape
.cp
< 0x110000)
1868 return write_codepoint
<8, Char
>(out
, 'U', escape
.cp
);
1869 for (Char escape_char
: basic_string_view
<Char
>(
1870 escape
.begin
, to_unsigned(escape
.end
- escape
.begin
))) {
1871 out
= write_codepoint
<2, Char
>(out
, 'x',
1872 static_cast<uint32_t>(escape_char
) & 0xFF);
1880 template <typename Char
, typename OutputIt
>
1881 auto write_escaped_string(OutputIt out
, basic_string_view
<Char
> str
)
1883 *out
++ = static_cast<Char
>('"');
1884 auto begin
= str
.begin(), end
= str
.end();
1886 auto escape
= find_escape(begin
, end
);
1887 out
= copy
<Char
>(begin
, escape
.begin
, out
);
1890 out
= write_escaped_cp
<OutputIt
, Char
>(out
, escape
);
1891 } while (begin
!= end
);
1892 *out
++ = static_cast<Char
>('"');
1896 template <typename Char
, typename OutputIt
>
1897 auto write_escaped_char(OutputIt out
, Char v
) -> OutputIt
{
1898 Char v_array
[1] = {v
};
1899 *out
++ = static_cast<Char
>('\'');
1900 if ((needs_escape(static_cast<uint32_t>(v
)) && v
!= static_cast<Char
>('"')) ||
1901 v
== static_cast<Char
>('\'')) {
1902 out
= write_escaped_cp(out
,
1903 find_escape_result
<Char
>{v_array
, v_array
+ 1,
1904 static_cast<uint32_t>(v
)});
1908 *out
++ = static_cast<Char
>('\'');
1912 template <typename Char
, typename OutputIt
>
1913 FMT_CONSTEXPR
auto write_char(OutputIt out
, Char value
,
1914 const format_specs
& specs
) -> OutputIt
{
1915 bool is_debug
= specs
.type
== presentation_type::debug
;
1916 return write_padded
<Char
>(out
, specs
, 1, [=](reserve_iterator
<OutputIt
> it
) {
1917 if (is_debug
) return write_escaped_char(it
, value
);
1922 template <typename Char
, typename OutputIt
>
1923 FMT_CONSTEXPR
auto write(OutputIt out
, Char value
, const format_specs
& specs
,
1924 locale_ref loc
= {}) -> OutputIt
{
1925 // char is formatted as unsigned char for consistency across platforms.
1926 using unsigned_type
=
1927 conditional_t
<std::is_same
<Char
, char>::value
, unsigned char, unsigned>;
1928 return check_char_specs(specs
)
1929 ? write_char
<Char
>(out
, value
, specs
)
1930 : write
<Char
>(out
, static_cast<unsigned_type
>(value
), specs
, loc
);
1933 // Data for write_int that doesn't depend on output iterator type. It is used to
1934 // avoid template code bloat.
1935 template <typename Char
> struct write_int_data
{
1939 FMT_CONSTEXPR
write_int_data(int num_digits
, unsigned prefix
,
1940 const format_specs
& specs
)
1941 : size((prefix
>> 24) + to_unsigned(num_digits
)), padding(0) {
1942 if (specs
.align
== align::numeric
) {
1943 auto width
= to_unsigned(specs
.width
);
1945 padding
= width
- size
;
1948 } else if (specs
.precision
> num_digits
) {
1949 size
= (prefix
>> 24) + to_unsigned(specs
.precision
);
1950 padding
= to_unsigned(specs
.precision
- num_digits
);
1955 // Writes an integer in the format
1956 // <left-padding><prefix><numeric-padding><digits><right-padding>
1957 // where <digits> are written by write_digits(it).
1958 // prefix contains chars in three lower bytes and the size in the fourth byte.
1959 template <typename Char
, typename OutputIt
, typename W
>
1960 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out
, int num_digits
,
1962 const format_specs
& specs
,
1963 W write_digits
) -> OutputIt
{
1964 // Slightly faster check for specs.width == 0 && specs.precision == -1.
1965 if ((specs
.width
| (specs
.precision
+ 1)) == 0) {
1966 auto it
= reserve(out
, to_unsigned(num_digits
) + (prefix
>> 24));
1968 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
1969 *it
++ = static_cast<Char
>(p
& 0xff);
1971 return base_iterator(out
, write_digits(it
));
1973 auto data
= write_int_data
<Char
>(num_digits
, prefix
, specs
);
1974 return write_padded
<Char
, align::right
>(
1975 out
, specs
, data
.size
, [=](reserve_iterator
<OutputIt
> it
) {
1976 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
1977 *it
++ = static_cast<Char
>(p
& 0xff);
1978 it
= detail::fill_n(it
, data
.padding
, static_cast<Char
>('0'));
1979 return write_digits(it
);
1983 template <typename Char
> class digit_grouping
{
1985 std::string grouping_
;
1986 std::basic_string
<Char
> thousands_sep_
;
1989 std::string::const_iterator group
;
1992 auto initial_state() const -> next_state
{ return {grouping_
.begin(), 0}; }
1994 // Returns the next digit group separator position.
1995 auto next(next_state
& state
) const -> int {
1996 if (thousands_sep_
.empty()) return max_value
<int>();
1997 if (state
.group
== grouping_
.end()) return state
.pos
+= grouping_
.back();
1998 if (*state
.group
<= 0 || *state
.group
== max_value
<char>())
1999 return max_value
<int>();
2000 state
.pos
+= *state
.group
++;
2005 explicit digit_grouping(locale_ref loc
, bool localized
= true) {
2006 if (!localized
) return;
2007 auto sep
= thousands_sep
<Char
>(loc
);
2008 grouping_
= sep
.grouping
;
2009 if (sep
.thousands_sep
) thousands_sep_
.assign(1, sep
.thousands_sep
);
2011 digit_grouping(std::string grouping
, std::basic_string
<Char
> sep
)
2012 : grouping_(std::move(grouping
)), thousands_sep_(std::move(sep
)) {}
2014 auto has_separator() const -> bool { return !thousands_sep_
.empty(); }
2016 auto count_separators(int num_digits
) const -> int {
2018 auto state
= initial_state();
2019 while (num_digits
> next(state
)) ++count
;
2023 // Applies grouping to digits and write the output to out.
2024 template <typename Out
, typename C
>
2025 auto apply(Out out
, basic_string_view
<C
> digits
) const -> Out
{
2026 auto num_digits
= static_cast<int>(digits
.size());
2027 auto separators
= basic_memory_buffer
<int>();
2028 separators
.push_back(0);
2029 auto state
= initial_state();
2030 while (int i
= next(state
)) {
2031 if (i
>= num_digits
) break;
2032 separators
.push_back(i
);
2034 for (int i
= 0, sep_index
= static_cast<int>(separators
.size() - 1);
2035 i
< num_digits
; ++i
) {
2036 if (num_digits
- i
== separators
[sep_index
]) {
2037 out
= copy
<Char
>(thousands_sep_
.data(),
2038 thousands_sep_
.data() + thousands_sep_
.size(), out
);
2041 *out
++ = static_cast<Char
>(digits
[to_unsigned(i
)]);
2047 FMT_CONSTEXPR
inline void prefix_append(unsigned& prefix
, unsigned value
) {
2048 prefix
|= prefix
!= 0 ? value
<< 8 : value
;
2049 prefix
+= (1u + (value
> 0xff ? 1 : 0)) << 24;
2052 // Writes a decimal integer with digit grouping.
2053 template <typename OutputIt
, typename UInt
, typename Char
>
2054 auto write_int(OutputIt out
, UInt value
, unsigned prefix
,
2055 const format_specs
& specs
, const digit_grouping
<Char
>& grouping
)
2057 static_assert(std::is_same
<uint64_or_128_t
<UInt
>, UInt
>::value
, "");
2059 auto buffer
= memory_buffer();
2060 switch (specs
.type
) {
2062 FMT_ASSERT(false, "");
2064 case presentation_type::none
:
2065 case presentation_type::dec
:
2066 num_digits
= count_digits(value
);
2067 format_decimal
<char>(appender(buffer
), value
, num_digits
);
2069 case presentation_type::hex
:
2071 prefix_append(prefix
, unsigned(specs
.upper
? 'X' : 'x') << 8 | '0');
2072 num_digits
= count_digits
<4>(value
);
2073 format_uint
<4, char>(appender(buffer
), value
, num_digits
, specs
.upper
);
2075 case presentation_type::oct
:
2076 num_digits
= count_digits
<3>(value
);
2077 // Octal prefix '0' is counted as a digit, so only add it if precision
2078 // is not greater than the number of digits.
2079 if (specs
.alt
&& specs
.precision
<= num_digits
&& value
!= 0)
2080 prefix_append(prefix
, '0');
2081 format_uint
<3, char>(appender(buffer
), value
, num_digits
);
2083 case presentation_type::bin
:
2085 prefix_append(prefix
, unsigned(specs
.upper
? 'B' : 'b') << 8 | '0');
2086 num_digits
= count_digits
<1>(value
);
2087 format_uint
<1, char>(appender(buffer
), value
, num_digits
);
2089 case presentation_type::chr
:
2090 return write_char
<Char
>(out
, static_cast<Char
>(value
), specs
);
2093 unsigned size
= (prefix
!= 0 ? prefix
>> 24 : 0) + to_unsigned(num_digits
) +
2094 to_unsigned(grouping
.count_separators(num_digits
));
2095 return write_padded
<Char
, align::right
>(
2096 out
, specs
, size
, size
, [&](reserve_iterator
<OutputIt
> it
) {
2097 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
2098 *it
++ = static_cast<Char
>(p
& 0xff);
2099 return grouping
.apply(it
, string_view(buffer
.data(), buffer
.size()));
2103 // Writes a localized value.
2104 FMT_API
auto write_loc(appender out
, loc_value value
, const format_specs
& specs
,
2105 locale_ref loc
) -> bool;
2106 template <typename OutputIt
>
2107 inline auto write_loc(OutputIt
, loc_value
, const format_specs
&, locale_ref
)
2112 template <typename UInt
> struct write_int_arg
{
2117 template <typename T
>
2118 FMT_CONSTEXPR
auto make_write_int_arg(T value
, sign_t sign
)
2119 -> write_int_arg
<uint32_or_64_or_128_t
<T
>> {
2121 auto abs_value
= static_cast<uint32_or_64_or_128_t
<T
>>(value
);
2122 if (is_negative(value
)) {
2123 prefix
= 0x01000000 | '-';
2124 abs_value
= 0 - abs_value
;
2126 constexpr const unsigned prefixes
[4] = {0, 0, 0x1000000u
| '+',
2128 prefix
= prefixes
[sign
];
2130 return {abs_value
, prefix
};
2133 template <typename Char
= char> struct loc_writer
{
2134 basic_appender
<Char
> out
;
2135 const format_specs
& specs
;
2136 std::basic_string
<Char
> sep
;
2137 std::string grouping
;
2138 std::basic_string
<Char
> decimal_point
;
2140 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
2141 auto operator()(T value
) -> bool {
2142 auto arg
= make_write_int_arg(value
, specs
.sign
);
2143 write_int(out
, static_cast<uint64_or_128_t
<T
>>(arg
.abs_value
), arg
.prefix
,
2144 specs
, digit_grouping
<Char
>(grouping
, sep
));
2148 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
2149 auto operator()(T
) -> bool {
2154 template <typename Char
, typename OutputIt
, typename T
>
2155 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out
, write_int_arg
<T
> arg
,
2156 const format_specs
& specs
, locale_ref
)
2158 static_assert(std::is_same
<T
, uint32_or_64_or_128_t
<T
>>::value
, "");
2159 auto abs_value
= arg
.abs_value
;
2160 auto prefix
= arg
.prefix
;
2161 switch (specs
.type
) {
2163 FMT_ASSERT(false, "");
2165 case presentation_type::none
:
2166 case presentation_type::dec
: {
2167 int num_digits
= count_digits(abs_value
);
2168 return write_int
<Char
>(
2169 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2170 return format_decimal
<Char
>(it
, abs_value
, num_digits
).end
;
2173 case presentation_type::hex
: {
2175 prefix_append(prefix
, unsigned(specs
.upper
? 'X' : 'x') << 8 | '0');
2176 int num_digits
= count_digits
<4>(abs_value
);
2177 return write_int
<Char
>(
2178 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2179 return format_uint
<4, Char
>(it
, abs_value
, num_digits
, specs
.upper
);
2182 case presentation_type::oct
: {
2183 int num_digits
= count_digits
<3>(abs_value
);
2184 // Octal prefix '0' is counted as a digit, so only add it if precision
2185 // is not greater than the number of digits.
2186 if (specs
.alt
&& specs
.precision
<= num_digits
&& abs_value
!= 0)
2187 prefix_append(prefix
, '0');
2188 return write_int
<Char
>(
2189 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2190 return format_uint
<3, Char
>(it
, abs_value
, num_digits
);
2193 case presentation_type::bin
: {
2195 prefix_append(prefix
, unsigned(specs
.upper
? 'B' : 'b') << 8 | '0');
2196 int num_digits
= count_digits
<1>(abs_value
);
2197 return write_int
<Char
>(
2198 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2199 return format_uint
<1, Char
>(it
, abs_value
, num_digits
);
2202 case presentation_type::chr
:
2203 return write_char
<Char
>(out
, static_cast<Char
>(abs_value
), specs
);
2206 template <typename Char
, typename OutputIt
, typename T
>
2207 FMT_CONSTEXPR FMT_NOINLINE
auto write_int_noinline(OutputIt out
,
2208 write_int_arg
<T
> arg
,
2209 const format_specs
& specs
,
2210 locale_ref loc
) -> OutputIt
{
2211 return write_int
<Char
>(out
, arg
, specs
, loc
);
2213 template <typename Char
, typename T
,
2214 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2215 !std::is_same
<T
, bool>::value
&&
2216 !std::is_same
<T
, Char
>::value
)>
2217 FMT_CONSTEXPR FMT_INLINE
auto write(basic_appender
<Char
> out
, T value
,
2218 const format_specs
& specs
, locale_ref loc
)
2219 -> basic_appender
<Char
> {
2220 if (specs
.localized
&& write_loc(out
, value
, specs
, loc
)) return out
;
2221 return write_int_noinline
<Char
>(out
, make_write_int_arg(value
, specs
.sign
),
2224 // An inlined version of write used in format string compilation.
2225 template <typename Char
, typename OutputIt
, typename T
,
2226 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2227 !std::is_same
<T
, bool>::value
&&
2228 !std::is_same
<T
, Char
>::value
&&
2229 !std::is_same
<OutputIt
, basic_appender
<Char
>>::value
)>
2230 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out
, T value
,
2231 const format_specs
& specs
, locale_ref loc
)
2233 if (specs
.localized
&& write_loc(out
, value
, specs
, loc
)) return out
;
2234 return write_int
<Char
>(out
, make_write_int_arg(value
, specs
.sign
), specs
,
2238 // An output iterator that counts the number of objects written to it and
2240 class counting_iterator
{
2245 using iterator_category
= std::output_iterator_tag
;
2246 using difference_type
= std::ptrdiff_t;
2247 using pointer
= void;
2248 using reference
= void;
2249 FMT_UNCHECKED_ITERATOR(counting_iterator
);
2252 template <typename T
> FMT_CONSTEXPR
void operator=(const T
&) {}
2255 FMT_CONSTEXPR
counting_iterator() : count_(0) {}
2257 FMT_CONSTEXPR
auto count() const -> size_t { return count_
; }
2259 FMT_CONSTEXPR
auto operator++() -> counting_iterator
& {
2263 FMT_CONSTEXPR
auto operator++(int) -> counting_iterator
{
2269 FMT_CONSTEXPR
friend auto operator+(counting_iterator it
, difference_type n
)
2270 -> counting_iterator
{
2271 it
.count_
+= static_cast<size_t>(n
);
2275 FMT_CONSTEXPR
auto operator*() const -> value_type
{ return {}; }
2278 template <typename Char
, typename OutputIt
>
2279 FMT_CONSTEXPR
auto write(OutputIt out
, basic_string_view
<Char
> s
,
2280 const format_specs
& specs
) -> OutputIt
{
2281 auto data
= s
.data();
2282 auto size
= s
.size();
2283 if (specs
.precision
>= 0 && to_unsigned(specs
.precision
) < size
)
2284 size
= code_point_index(s
, to_unsigned(specs
.precision
));
2285 bool is_debug
= specs
.type
== presentation_type::debug
;
2288 if (is_debug
) size
= write_escaped_string(counting_iterator
{}, s
).count();
2290 if (specs
.width
!= 0) {
2294 width
= compute_width(basic_string_view
<Char
>(data
, size
));
2296 return write_padded
<Char
>(out
, specs
, size
, width
,
2297 [=](reserve_iterator
<OutputIt
> it
) {
2298 if (is_debug
) return write_escaped_string(it
, s
);
2299 return copy
<Char
>(data
, data
+ size
, it
);
2302 template <typename Char
, typename OutputIt
>
2303 FMT_CONSTEXPR
auto write(OutputIt out
,
2304 basic_string_view
<type_identity_t
<Char
>> s
,
2305 const format_specs
& specs
, locale_ref
) -> OutputIt
{
2306 return write
<Char
>(out
, s
, specs
);
2308 template <typename Char
, typename OutputIt
>
2309 FMT_CONSTEXPR
auto write(OutputIt out
, const Char
* s
, const format_specs
& specs
,
2310 locale_ref
) -> OutputIt
{
2311 if (specs
.type
== presentation_type::pointer
)
2312 return write_ptr
<Char
>(out
, bit_cast
<uintptr_t>(s
), &specs
);
2313 if (!s
) report_error("string pointer is null");
2314 return write
<Char
>(out
, basic_string_view
<Char
>(s
), specs
, {});
2317 template <typename Char
, typename OutputIt
, typename T
,
2318 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2319 !std::is_same
<T
, bool>::value
&&
2320 !std::is_same
<T
, Char
>::value
)>
2321 FMT_CONSTEXPR
auto write(OutputIt out
, T value
) -> OutputIt
{
2322 auto abs_value
= static_cast<uint32_or_64_or_128_t
<T
>>(value
);
2323 bool negative
= is_negative(value
);
2324 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2325 if (negative
) abs_value
= ~abs_value
+ 1;
2326 int num_digits
= count_digits(abs_value
);
2327 auto size
= (negative
? 1 : 0) + static_cast<size_t>(num_digits
);
2328 if (auto ptr
= to_pointer
<Char
>(out
, size
)) {
2329 if (negative
) *ptr
++ = static_cast<Char
>('-');
2330 format_decimal
<Char
>(ptr
, abs_value
, num_digits
);
2333 if (negative
) *out
++ = static_cast<Char
>('-');
2334 return format_decimal
<Char
>(out
, abs_value
, num_digits
).end
;
2338 template <typename Char
>
2339 FMT_CONSTEXPR
auto parse_align(const Char
* begin
, const Char
* end
,
2340 format_specs
& specs
) -> const Char
* {
2341 FMT_ASSERT(begin
!= end
, "");
2342 auto align
= align::none
;
2343 auto p
= begin
+ code_point_length(begin
);
2344 if (end
- p
<= 0) p
= begin
;
2346 switch (to_ascii(*p
)) {
2348 align
= align::left
;
2351 align
= align::right
;
2354 align
= align::center
;
2357 if (align
!= align::none
) {
2360 if (c
== '}') return begin
;
2362 report_error("invalid fill character '{'");
2365 specs
.fill
= basic_string_view
<Char
>(begin
, to_unsigned(p
- begin
));
2371 } else if (p
== begin
) {
2376 specs
.align
= align
;
2380 // A floating-point presentation format.
2381 enum class float_format
: unsigned char {
2382 general
, // General: exponent notation or fixed point based on magnitude.
2383 exp
, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
2384 fixed
// Fixed point with the default precision of 6, e.g. 0.0012.
2387 struct float_specs
{
2389 float_format format
: 8;
2397 FMT_CONSTEXPR
inline auto parse_float_type_spec(const format_specs
& specs
)
2399 auto result
= float_specs();
2400 result
.showpoint
= specs
.alt
;
2401 result
.locale
= specs
.localized
;
2402 switch (specs
.type
) {
2405 case presentation_type::none
:
2406 result
.format
= float_format::general
;
2408 case presentation_type::exp
:
2409 result
.format
= float_format::exp
;
2410 result
.showpoint
|= specs
.precision
!= 0;
2412 case presentation_type::fixed
:
2413 result
.format
= float_format::fixed
;
2414 result
.showpoint
|= specs
.precision
!= 0;
2416 case presentation_type::general
:
2417 result
.format
= float_format::general
;
2423 template <typename Char
, typename OutputIt
>
2424 FMT_CONSTEXPR20
auto write_nonfinite(OutputIt out
, bool isnan
,
2425 format_specs specs
, sign_t sign
)
2428 isnan
? (specs
.upper
? "NAN" : "nan") : (specs
.upper
? "INF" : "inf");
2429 constexpr size_t str_size
= 3;
2430 auto size
= str_size
+ (sign
? 1 : 0);
2431 // Replace '0'-padding with space for non-finite values.
2432 const bool is_zero_fill
=
2433 specs
.fill
.size() == 1 && specs
.fill
.template get
<Char
>() == '0';
2434 if (is_zero_fill
) specs
.fill
= ' ';
2435 return write_padded
<Char
>(out
, specs
, size
,
2436 [=](reserve_iterator
<OutputIt
> it
) {
2437 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2438 return copy
<Char
>(str
, str
+ str_size
, it
);
2442 // A decimal floating-point number significand * pow(10, exp).
2443 struct big_decimal_fp
{
2444 const char* significand
;
2445 int significand_size
;
2449 constexpr auto get_significand_size(const big_decimal_fp
& f
) -> int {
2450 return f
.significand_size
;
2452 template <typename T
>
2453 inline auto get_significand_size(const dragonbox::decimal_fp
<T
>& f
) -> int {
2454 return count_digits(f
.significand
);
2457 template <typename Char
, typename OutputIt
>
2458 constexpr auto write_significand(OutputIt out
, const char* significand
,
2459 int significand_size
) -> OutputIt
{
2460 return copy
<Char
>(significand
, significand
+ significand_size
, out
);
2462 template <typename Char
, typename OutputIt
, typename UInt
>
2463 inline auto write_significand(OutputIt out
, UInt significand
,
2464 int significand_size
) -> OutputIt
{
2465 return format_decimal
<Char
>(out
, significand
, significand_size
).end
;
2467 template <typename Char
, typename OutputIt
, typename T
, typename Grouping
>
2468 FMT_CONSTEXPR20
auto write_significand(OutputIt out
, T significand
,
2469 int significand_size
, int exponent
,
2470 const Grouping
& grouping
) -> OutputIt
{
2471 if (!grouping
.has_separator()) {
2472 out
= write_significand
<Char
>(out
, significand
, significand_size
);
2473 return detail::fill_n(out
, exponent
, static_cast<Char
>('0'));
2475 auto buffer
= memory_buffer();
2476 write_significand
<char>(appender(buffer
), significand
, significand_size
);
2477 detail::fill_n(appender(buffer
), exponent
, '0');
2478 return grouping
.apply(out
, string_view(buffer
.data(), buffer
.size()));
2481 template <typename Char
, typename UInt
,
2482 FMT_ENABLE_IF(std::is_integral
<UInt
>::value
)>
2483 inline auto write_significand(Char
* out
, UInt significand
, int significand_size
,
2484 int integral_size
, Char decimal_point
) -> Char
* {
2486 return format_decimal(out
, significand
, significand_size
).end
;
2487 out
+= significand_size
+ 1;
2489 int floating_size
= significand_size
- integral_size
;
2490 for (int i
= floating_size
/ 2; i
> 0; --i
) {
2492 copy2(out
, digits2(static_cast<std::size_t>(significand
% 100)));
2495 if (floating_size
% 2 != 0) {
2496 *--out
= static_cast<Char
>('0' + significand
% 10);
2499 *--out
= decimal_point
;
2500 format_decimal(out
- integral_size
, significand
, integral_size
);
2504 template <typename OutputIt
, typename UInt
, typename Char
,
2505 FMT_ENABLE_IF(!std::is_pointer
<remove_cvref_t
<OutputIt
>>::value
)>
2506 inline auto write_significand(OutputIt out
, UInt significand
,
2507 int significand_size
, int integral_size
,
2508 Char decimal_point
) -> OutputIt
{
2509 // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
2510 Char buffer
[digits10
<UInt
>() + 2];
2511 auto end
= write_significand(buffer
, significand
, significand_size
,
2512 integral_size
, decimal_point
);
2513 return detail::copy_noinline
<Char
>(buffer
, end
, out
);
2516 template <typename OutputIt
, typename Char
>
2517 FMT_CONSTEXPR
auto write_significand(OutputIt out
, const char* significand
,
2518 int significand_size
, int integral_size
,
2519 Char decimal_point
) -> OutputIt
{
2520 out
= detail::copy_noinline
<Char
>(significand
, significand
+ integral_size
,
2522 if (!decimal_point
) return out
;
2523 *out
++ = decimal_point
;
2524 return detail::copy_noinline
<Char
>(significand
+ integral_size
,
2525 significand
+ significand_size
, out
);
2528 template <typename OutputIt
, typename Char
, typename T
, typename Grouping
>
2529 FMT_CONSTEXPR20
auto write_significand(OutputIt out
, T significand
,
2530 int significand_size
, int integral_size
,
2532 const Grouping
& grouping
) -> OutputIt
{
2533 if (!grouping
.has_separator()) {
2534 return write_significand(out
, significand
, significand_size
, integral_size
,
2537 auto buffer
= basic_memory_buffer
<Char
>();
2538 write_significand(basic_appender
<Char
>(buffer
), significand
, significand_size
,
2539 integral_size
, decimal_point
);
2541 out
, basic_string_view
<Char
>(buffer
.data(), to_unsigned(integral_size
)));
2542 return detail::copy_noinline
<Char
>(buffer
.data() + integral_size
,
2546 template <typename Char
, typename OutputIt
, typename DecimalFP
,
2547 typename Grouping
= digit_grouping
<Char
>>
2548 FMT_CONSTEXPR20
auto do_write_float(OutputIt out
, const DecimalFP
& f
,
2549 const format_specs
& specs
,
2550 float_specs fspecs
, locale_ref loc
)
2552 auto significand
= f
.significand
;
2553 int significand_size
= get_significand_size(f
);
2554 const Char zero
= static_cast<Char
>('0');
2555 auto sign
= fspecs
.sign
;
2556 size_t size
= to_unsigned(significand_size
) + (sign
? 1 : 0);
2557 using iterator
= reserve_iterator
<OutputIt
>;
2559 Char decimal_point
=
2560 fspecs
.locale
? detail::decimal_point
<Char
>(loc
) : static_cast<Char
>('.');
2562 int output_exp
= f
.exponent
+ significand_size
- 1;
2563 auto use_exp_format
= [=]() {
2564 if (fspecs
.format
== float_format::exp
) return true;
2565 if (fspecs
.format
!= float_format::general
) return false;
2566 // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
2567 // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
2568 const int exp_lower
= -4, exp_upper
= 16;
2569 return output_exp
< exp_lower
||
2570 output_exp
>= (fspecs
.precision
> 0 ? fspecs
.precision
: exp_upper
);
2572 if (use_exp_format()) {
2574 if (fspecs
.showpoint
) {
2575 num_zeros
= fspecs
.precision
- significand_size
;
2576 if (num_zeros
< 0) num_zeros
= 0;
2577 size
+= to_unsigned(num_zeros
);
2578 } else if (significand_size
== 1) {
2579 decimal_point
= Char();
2581 auto abs_output_exp
= output_exp
>= 0 ? output_exp
: -output_exp
;
2583 if (abs_output_exp
>= 100) exp_digits
= abs_output_exp
>= 1000 ? 4 : 3;
2585 size
+= to_unsigned((decimal_point
? 1 : 0) + 2 + exp_digits
);
2586 char exp_char
= specs
.upper
? 'E' : 'e';
2587 auto write
= [=](iterator it
) {
2588 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2589 // Insert a decimal point after the first digit and add an exponent.
2590 it
= write_significand(it
, significand
, significand_size
, 1,
2592 if (num_zeros
> 0) it
= detail::fill_n(it
, num_zeros
, zero
);
2593 *it
++ = static_cast<Char
>(exp_char
);
2594 return write_exponent
<Char
>(output_exp
, it
);
2596 return specs
.width
> 0
2597 ? write_padded
<Char
, align::right
>(out
, specs
, size
, write
)
2598 : base_iterator(out
, write(reserve(out
, size
)));
2601 int exp
= f
.exponent
+ significand_size
;
2602 if (f
.exponent
>= 0) {
2603 // 1234e5 -> 123400000[.0+]
2604 size
+= to_unsigned(f
.exponent
);
2605 int num_zeros
= fspecs
.precision
- exp
;
2606 abort_fuzzing_if(num_zeros
> 5000);
2607 if (fspecs
.showpoint
) {
2609 if (num_zeros
<= 0 && fspecs
.format
!= float_format::fixed
) num_zeros
= 0;
2610 if (num_zeros
> 0) size
+= to_unsigned(num_zeros
);
2612 auto grouping
= Grouping(loc
, fspecs
.locale
);
2613 size
+= to_unsigned(grouping
.count_separators(exp
));
2614 return write_padded
<Char
, align::right
>(out
, specs
, size
, [&](iterator it
) {
2615 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2616 it
= write_significand
<Char
>(it
, significand
, significand_size
,
2617 f
.exponent
, grouping
);
2618 if (!fspecs
.showpoint
) return it
;
2619 *it
++ = decimal_point
;
2620 return num_zeros
> 0 ? detail::fill_n(it
, num_zeros
, zero
) : it
;
2622 } else if (exp
> 0) {
2623 // 1234e-2 -> 12.34[0+]
2624 int num_zeros
= fspecs
.showpoint
? fspecs
.precision
- significand_size
: 0;
2625 size
+= 1 + to_unsigned(num_zeros
> 0 ? num_zeros
: 0);
2626 auto grouping
= Grouping(loc
, fspecs
.locale
);
2627 size
+= to_unsigned(grouping
.count_separators(exp
));
2628 return write_padded
<Char
, align::right
>(out
, specs
, size
, [&](iterator it
) {
2629 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2630 it
= write_significand(it
, significand
, significand_size
, exp
,
2631 decimal_point
, grouping
);
2632 return num_zeros
> 0 ? detail::fill_n(it
, num_zeros
, zero
) : it
;
2635 // 1234e-6 -> 0.001234
2636 int num_zeros
= -exp
;
2637 if (significand_size
== 0 && fspecs
.precision
>= 0 &&
2638 fspecs
.precision
< num_zeros
) {
2639 num_zeros
= fspecs
.precision
;
2641 bool pointy
= num_zeros
!= 0 || significand_size
!= 0 || fspecs
.showpoint
;
2642 size
+= 1 + (pointy
? 1 : 0) + to_unsigned(num_zeros
);
2643 return write_padded
<Char
, align::right
>(out
, specs
, size
, [&](iterator it
) {
2644 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2646 if (!pointy
) return it
;
2647 *it
++ = decimal_point
;
2648 it
= detail::fill_n(it
, num_zeros
, zero
);
2649 return write_significand
<Char
>(it
, significand
, significand_size
);
2653 template <typename Char
> class fallback_digit_grouping
{
2655 constexpr fallback_digit_grouping(locale_ref
, bool) {}
2657 constexpr auto has_separator() const -> bool { return false; }
2659 constexpr auto count_separators(int) const -> int { return 0; }
2661 template <typename Out
, typename C
>
2662 constexpr auto apply(Out out
, basic_string_view
<C
>) const -> Out
{
2667 template <typename Char
, typename OutputIt
, typename DecimalFP
>
2668 FMT_CONSTEXPR20
auto write_float(OutputIt out
, const DecimalFP
& f
,
2669 const format_specs
& specs
, float_specs fspecs
,
2670 locale_ref loc
) -> OutputIt
{
2671 if (is_constant_evaluated()) {
2672 return do_write_float
<Char
, OutputIt
, DecimalFP
,
2673 fallback_digit_grouping
<Char
>>(out
, f
, specs
, fspecs
,
2676 return do_write_float
<Char
>(out
, f
, specs
, fspecs
, loc
);
2680 template <typename T
> constexpr auto isnan(T value
) -> bool {
2681 return value
!= value
; // std::isnan doesn't support __float128.
2684 template <typename T
, typename Enable
= void>
2685 struct has_isfinite
: std::false_type
{};
2687 template <typename T
>
2688 struct has_isfinite
<T
, enable_if_t
<sizeof(std::isfinite(T())) != 0>>
2689 : std::true_type
{};
2691 template <typename T
, FMT_ENABLE_IF(std::is_floating_point
<T
>::value
&&
2692 has_isfinite
<T
>::value
)>
2693 FMT_CONSTEXPR20
auto isfinite(T value
) -> bool {
2694 constexpr T inf
= T(std::numeric_limits
<double>::infinity());
2695 if (is_constant_evaluated())
2696 return !detail::isnan(value
) && value
< inf
&& value
> -inf
;
2697 return std::isfinite(value
);
2699 template <typename T
, FMT_ENABLE_IF(!has_isfinite
<T
>::value
)>
2700 FMT_CONSTEXPR
auto isfinite(T value
) -> bool {
2701 T inf
= T(std::numeric_limits
<double>::infinity());
2702 // std::isfinite doesn't support __float128.
2703 return !detail::isnan(value
) && value
< inf
&& value
> -inf
;
2706 template <typename T
, FMT_ENABLE_IF(is_floating_point
<T
>::value
)>
2707 FMT_INLINE FMT_CONSTEXPR
bool signbit(T value
) {
2708 if (is_constant_evaluated()) {
2709 #ifdef __cpp_if_constexpr
2710 if constexpr (std::numeric_limits
<double>::is_iec559
) {
2711 auto bits
= detail::bit_cast
<uint64_t>(static_cast<double>(value
));
2712 return (bits
>> (num_bits
<uint64_t>() - 1)) != 0;
2716 return std::signbit(static_cast<double>(value
));
2719 inline FMT_CONSTEXPR20
void adjust_precision(int& precision
, int exp10
) {
2720 // Adjust fixed precision by exponent because it is relative to decimal
2722 if (exp10
> 0 && precision
> max_value
<int>() - exp10
)
2723 FMT_THROW(format_error("number is too big"));
2729 // A bigint is stored as an array of bigits (big digits), with bigit at index
2730 // 0 being the least significant one.
2731 using bigit
= uint32_t;
2732 using double_bigit
= uint64_t;
2733 enum { bigits_capacity
= 32 };
2734 basic_memory_buffer
<bigit
, bigits_capacity
> bigits_
;
2737 FMT_CONSTEXPR20
auto operator[](int index
) const -> bigit
{
2738 return bigits_
[to_unsigned(index
)];
2740 FMT_CONSTEXPR20
auto operator[](int index
) -> bigit
& {
2741 return bigits_
[to_unsigned(index
)];
2744 static constexpr const int bigit_bits
= num_bits
<bigit
>();
2746 friend struct formatter
<bigint
>;
2748 FMT_CONSTEXPR20
void subtract_bigits(int index
, bigit other
, bigit
& borrow
) {
2749 auto result
= static_cast<double_bigit
>((*this)[index
]) - other
- borrow
;
2750 (*this)[index
] = static_cast<bigit
>(result
);
2751 borrow
= static_cast<bigit
>(result
>> (bigit_bits
* 2 - 1));
2754 FMT_CONSTEXPR20
void remove_leading_zeros() {
2755 int num_bigits
= static_cast<int>(bigits_
.size()) - 1;
2756 while (num_bigits
> 0 && (*this)[num_bigits
] == 0) --num_bigits
;
2757 bigits_
.resize(to_unsigned(num_bigits
+ 1));
2760 // Computes *this -= other assuming aligned bigints and *this >= other.
2761 FMT_CONSTEXPR20
void subtract_aligned(const bigint
& other
) {
2762 FMT_ASSERT(other
.exp_
>= exp_
, "unaligned bigints");
2763 FMT_ASSERT(compare(*this, other
) >= 0, "");
2765 int i
= other
.exp_
- exp_
;
2766 for (size_t j
= 0, n
= other
.bigits_
.size(); j
!= n
; ++i
, ++j
)
2767 subtract_bigits(i
, other
.bigits_
[j
], borrow
);
2768 while (borrow
> 0) subtract_bigits(i
, 0, borrow
);
2769 remove_leading_zeros();
2772 FMT_CONSTEXPR20
void multiply(uint32_t value
) {
2773 const double_bigit wide_value
= value
;
2775 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2776 double_bigit result
= bigits_
[i
] * wide_value
+ carry
;
2777 bigits_
[i
] = static_cast<bigit
>(result
);
2778 carry
= static_cast<bigit
>(result
>> bigit_bits
);
2780 if (carry
!= 0) bigits_
.push_back(carry
);
2783 template <typename UInt
, FMT_ENABLE_IF(std::is_same
<UInt
, uint64_t>::value
||
2784 std::is_same
<UInt
, uint128_t
>::value
)>
2785 FMT_CONSTEXPR20
void multiply(UInt value
) {
2787 conditional_t
<std::is_same
<UInt
, uint128_t
>::value
, uint64_t, uint32_t>;
2788 const int shift
= num_bits
<half_uint
>() - bigit_bits
;
2789 const UInt lower
= static_cast<half_uint
>(value
);
2790 const UInt upper
= value
>> num_bits
<half_uint
>();
2792 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2793 UInt result
= lower
* bigits_
[i
] + static_cast<bigit
>(carry
);
2794 carry
= (upper
* bigits_
[i
] << shift
) + (result
>> bigit_bits
) +
2795 (carry
>> bigit_bits
);
2796 bigits_
[i
] = static_cast<bigit
>(result
);
2798 while (carry
!= 0) {
2799 bigits_
.push_back(static_cast<bigit
>(carry
));
2800 carry
>>= bigit_bits
;
2804 template <typename UInt
, FMT_ENABLE_IF(std::is_same
<UInt
, uint64_t>::value
||
2805 std::is_same
<UInt
, uint128_t
>::value
)>
2806 FMT_CONSTEXPR20
void assign(UInt n
) {
2807 size_t num_bigits
= 0;
2809 bigits_
[num_bigits
++] = static_cast<bigit
>(n
);
2812 bigits_
.resize(num_bigits
);
2817 FMT_CONSTEXPR20
bigint() : exp_(0) {}
2818 explicit bigint(uint64_t n
) { assign(n
); }
2820 bigint(const bigint
&) = delete;
2821 void operator=(const bigint
&) = delete;
2823 FMT_CONSTEXPR20
void assign(const bigint
& other
) {
2824 auto size
= other
.bigits_
.size();
2825 bigits_
.resize(size
);
2826 auto data
= other
.bigits_
.data();
2827 copy
<bigit
>(data
, data
+ size
, bigits_
.data());
2831 template <typename Int
> FMT_CONSTEXPR20
void operator=(Int n
) {
2832 FMT_ASSERT(n
> 0, "");
2833 assign(uint64_or_128_t
<Int
>(n
));
2836 FMT_CONSTEXPR20
auto num_bigits() const -> int {
2837 return static_cast<int>(bigits_
.size()) + exp_
;
2840 FMT_NOINLINE FMT_CONSTEXPR20
auto operator<<=(int shift
) -> bigint
& {
2841 FMT_ASSERT(shift
>= 0, "");
2842 exp_
+= shift
/ bigit_bits
;
2843 shift
%= bigit_bits
;
2844 if (shift
== 0) return *this;
2846 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2847 bigit c
= bigits_
[i
] >> (bigit_bits
- shift
);
2848 bigits_
[i
] = (bigits_
[i
] << shift
) + carry
;
2851 if (carry
!= 0) bigits_
.push_back(carry
);
2855 template <typename Int
>
2856 FMT_CONSTEXPR20
auto operator*=(Int value
) -> bigint
& {
2857 FMT_ASSERT(value
> 0, "");
2858 multiply(uint32_or_64_or_128_t
<Int
>(value
));
2862 friend FMT_CONSTEXPR20
auto compare(const bigint
& lhs
, const bigint
& rhs
)
2864 int num_lhs_bigits
= lhs
.num_bigits(), num_rhs_bigits
= rhs
.num_bigits();
2865 if (num_lhs_bigits
!= num_rhs_bigits
)
2866 return num_lhs_bigits
> num_rhs_bigits
? 1 : -1;
2867 int i
= static_cast<int>(lhs
.bigits_
.size()) - 1;
2868 int j
= static_cast<int>(rhs
.bigits_
.size()) - 1;
2870 if (end
< 0) end
= 0;
2871 for (; i
>= end
; --i
, --j
) {
2872 bigit lhs_bigit
= lhs
[i
], rhs_bigit
= rhs
[j
];
2873 if (lhs_bigit
!= rhs_bigit
) return lhs_bigit
> rhs_bigit
? 1 : -1;
2875 if (i
!= j
) return i
> j
? 1 : -1;
2879 // Returns compare(lhs1 + lhs2, rhs).
2880 friend FMT_CONSTEXPR20
auto add_compare(const bigint
& lhs1
,
2881 const bigint
& lhs2
, const bigint
& rhs
)
2883 auto minimum
= [](int a
, int b
) { return a
< b
? a
: b
; };
2884 auto maximum
= [](int a
, int b
) { return a
> b
? a
: b
; };
2885 int max_lhs_bigits
= maximum(lhs1
.num_bigits(), lhs2
.num_bigits());
2886 int num_rhs_bigits
= rhs
.num_bigits();
2887 if (max_lhs_bigits
+ 1 < num_rhs_bigits
) return -1;
2888 if (max_lhs_bigits
> num_rhs_bigits
) return 1;
2889 auto get_bigit
= [](const bigint
& n
, int i
) -> bigit
{
2890 return i
>= n
.exp_
&& i
< n
.num_bigits() ? n
[i
- n
.exp_
] : 0;
2892 double_bigit borrow
= 0;
2893 int min_exp
= minimum(minimum(lhs1
.exp_
, lhs2
.exp_
), rhs
.exp_
);
2894 for (int i
= num_rhs_bigits
- 1; i
>= min_exp
; --i
) {
2896 static_cast<double_bigit
>(get_bigit(lhs1
, i
)) + get_bigit(lhs2
, i
);
2897 bigit rhs_bigit
= get_bigit(rhs
, i
);
2898 if (sum
> rhs_bigit
+ borrow
) return 1;
2899 borrow
= rhs_bigit
+ borrow
- sum
;
2900 if (borrow
> 1) return -1;
2901 borrow
<<= bigit_bits
;
2903 return borrow
!= 0 ? -1 : 0;
2906 // Assigns pow(10, exp) to this bigint.
2907 FMT_CONSTEXPR20
void assign_pow10(int exp
) {
2908 FMT_ASSERT(exp
>= 0, "");
2909 if (exp
== 0) return *this = 1;
2910 // Find the top bit.
2912 while (exp
>= bitmask
) bitmask
<<= 1;
2914 // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
2915 // repeated squaring and multiplication.
2918 while (bitmask
!= 0) {
2920 if ((exp
& bitmask
) != 0) *this *= 5;
2923 *this <<= exp
; // Multiply by pow(2, exp) by shifting.
2926 FMT_CONSTEXPR20
void square() {
2927 int num_bigits
= static_cast<int>(bigits_
.size());
2928 int num_result_bigits
= 2 * num_bigits
;
2929 basic_memory_buffer
<bigit
, bigits_capacity
> n(std::move(bigits_
));
2930 bigits_
.resize(to_unsigned(num_result_bigits
));
2931 auto sum
= uint128_t();
2932 for (int bigit_index
= 0; bigit_index
< num_bigits
; ++bigit_index
) {
2933 // Compute bigit at position bigit_index of the result by adding
2934 // cross-product terms n[i] * n[j] such that i + j == bigit_index.
2935 for (int i
= 0, j
= bigit_index
; j
>= 0; ++i
, --j
) {
2936 // Most terms are multiplied twice which can be optimized in the future.
2937 sum
+= static_cast<double_bigit
>(n
[i
]) * n
[j
];
2939 (*this)[bigit_index
] = static_cast<bigit
>(sum
);
2940 sum
>>= num_bits
<bigit
>(); // Compute the carry.
2942 // Do the same for the top half.
2943 for (int bigit_index
= num_bigits
; bigit_index
< num_result_bigits
;
2945 for (int j
= num_bigits
- 1, i
= bigit_index
- j
; i
< num_bigits
;)
2946 sum
+= static_cast<double_bigit
>(n
[i
++]) * n
[j
--];
2947 (*this)[bigit_index
] = static_cast<bigit
>(sum
);
2948 sum
>>= num_bits
<bigit
>();
2950 remove_leading_zeros();
2954 // If this bigint has a bigger exponent than other, adds trailing zero to make
2955 // exponents equal. This simplifies some operations such as subtraction.
2956 FMT_CONSTEXPR20
void align(const bigint
& other
) {
2957 int exp_difference
= exp_
- other
.exp_
;
2958 if (exp_difference
<= 0) return;
2959 int num_bigits
= static_cast<int>(bigits_
.size());
2960 bigits_
.resize(to_unsigned(num_bigits
+ exp_difference
));
2961 for (int i
= num_bigits
- 1, j
= i
+ exp_difference
; i
>= 0; --i
, --j
)
2962 bigits_
[j
] = bigits_
[i
];
2963 memset(bigits_
.data(), 0, to_unsigned(exp_difference
) * sizeof(bigit
));
2964 exp_
-= exp_difference
;
2967 // Divides this bignum by divisor, assigning the remainder to this and
2968 // returning the quotient.
2969 FMT_CONSTEXPR20
auto divmod_assign(const bigint
& divisor
) -> int {
2970 FMT_ASSERT(this != &divisor
, "");
2971 if (compare(*this, divisor
) < 0) return 0;
2972 FMT_ASSERT(divisor
.bigits_
[divisor
.bigits_
.size() - 1u] != 0, "");
2976 subtract_aligned(divisor
);
2978 } while (compare(*this, divisor
) >= 0);
2983 // format_dragon flags.
2985 predecessor_closer
= 1,
2986 fixup
= 2, // Run fixup to correct exp10 which can be off by one.
2990 // Formats a floating-point number using a variation of the Fixed-Precision
2991 // Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
2992 // https://fmt.dev/papers/p372-steele.pdf.
2993 FMT_CONSTEXPR20
inline void format_dragon(basic_fp
<uint128_t
> value
,
2994 unsigned flags
, int num_digits
,
2995 buffer
<char>& buf
, int& exp10
) {
2996 bigint numerator
; // 2 * R in (FPP)^2.
2997 bigint denominator
; // 2 * S in (FPP)^2.
2998 // lower and upper are differences between value and corresponding boundaries.
2999 bigint lower
; // (M^- in (FPP)^2).
3000 bigint upper_store
; // upper's value if different from lower.
3001 bigint
* upper
= nullptr; // (M^+ in (FPP)^2).
3002 // Shift numerator and denominator by an extra bit or two (if lower boundary
3003 // is closer) to make lower and upper integers. This eliminates multiplication
3004 // by 2 during later computations.
3005 bool is_predecessor_closer
= (flags
& dragon::predecessor_closer
) != 0;
3006 int shift
= is_predecessor_closer
? 2 : 1;
3008 numerator
= value
.f
;
3009 numerator
<<= value
.e
+ shift
;
3012 if (is_predecessor_closer
) {
3014 upper_store
<<= value
.e
+ 1;
3015 upper
= &upper_store
;
3017 denominator
.assign_pow10(exp10
);
3018 denominator
<<= shift
;
3019 } else if (exp10
< 0) {
3020 numerator
.assign_pow10(-exp10
);
3021 lower
.assign(numerator
);
3022 if (is_predecessor_closer
) {
3023 upper_store
.assign(numerator
);
3025 upper
= &upper_store
;
3027 numerator
*= value
.f
;
3028 numerator
<<= shift
;
3030 denominator
<<= shift
- value
.e
;
3032 numerator
= value
.f
;
3033 numerator
<<= shift
;
3034 denominator
.assign_pow10(exp10
);
3035 denominator
<<= shift
- value
.e
;
3037 if (is_predecessor_closer
) {
3038 upper_store
= 1ULL << 1;
3039 upper
= &upper_store
;
3042 int even
= static_cast<int>((value
.f
& 1) == 0);
3043 if (!upper
) upper
= &lower
;
3044 bool shortest
= num_digits
< 0;
3045 if ((flags
& dragon::fixup
) != 0) {
3046 if (add_compare(numerator
, *upper
, denominator
) + even
<= 0) {
3049 if (num_digits
< 0) {
3051 if (upper
!= &lower
) *upper
*= 10;
3054 if ((flags
& dragon::fixed
) != 0) adjust_precision(num_digits
, exp10
+ 1);
3056 // Invariant: value == (numerator / denominator) * pow(10, exp10).
3058 // Generate the shortest representation.
3060 char* data
= buf
.data();
3062 int digit
= numerator
.divmod_assign(denominator
);
3063 bool low
= compare(numerator
, lower
) - even
< 0; // numerator <[=] lower.
3064 // numerator + upper >[=] pow10:
3065 bool high
= add_compare(numerator
, *upper
, denominator
) + even
> 0;
3066 data
[num_digits
++] = static_cast<char>('0' + digit
);
3069 ++data
[num_digits
- 1];
3071 int result
= add_compare(numerator
, numerator
, denominator
);
3072 // Round half to even.
3073 if (result
> 0 || (result
== 0 && (digit
% 2) != 0))
3074 ++data
[num_digits
- 1];
3076 buf
.try_resize(to_unsigned(num_digits
));
3077 exp10
-= num_digits
- 1;
3082 if (upper
!= &lower
) *upper
*= 10;
3085 // Generate the given number of digits.
3086 exp10
-= num_digits
- 1;
3087 if (num_digits
<= 0) {
3089 if (num_digits
== 0) {
3091 digit
= add_compare(numerator
, numerator
, denominator
) > 0 ? '1' : '0';
3093 buf
.push_back(digit
);
3096 buf
.try_resize(to_unsigned(num_digits
));
3097 for (int i
= 0; i
< num_digits
- 1; ++i
) {
3098 int digit
= numerator
.divmod_assign(denominator
);
3099 buf
[i
] = static_cast<char>('0' + digit
);
3102 int digit
= numerator
.divmod_assign(denominator
);
3103 auto result
= add_compare(numerator
, numerator
, denominator
);
3104 if (result
> 0 || (result
== 0 && (digit
% 2) != 0)) {
3106 const auto overflow
= '0' + 10;
3107 buf
[num_digits
- 1] = overflow
;
3108 // Propagate the carry.
3109 for (int i
= num_digits
- 1; i
> 0 && buf
[i
] == overflow
; --i
) {
3113 if (buf
[0] == overflow
) {
3115 if ((flags
& dragon::fixed
) != 0)
3124 buf
[num_digits
- 1] = static_cast<char>('0' + digit
);
3127 // Formats a floating-point number using the hexfloat format.
3128 template <typename Float
, FMT_ENABLE_IF(!is_double_double
<Float
>::value
)>
3129 FMT_CONSTEXPR20
void format_hexfloat(Float value
, format_specs specs
,
3130 buffer
<char>& buf
) {
3131 // float is passed as double to reduce the number of instantiations and to
3132 // simplify implementation.
3133 static_assert(!std::is_same
<Float
, float>::value
, "");
3135 using info
= dragonbox::float_info
<Float
>;
3137 // Assume Float is in the format [sign][exponent][significand].
3138 using carrier_uint
= typename
info::carrier_uint
;
3140 constexpr auto num_float_significand_bits
=
3141 detail::num_significand_bits
<Float
>();
3143 basic_fp
<carrier_uint
> f(value
);
3144 f
.e
+= num_float_significand_bits
;
3145 if (!has_implicit_bit
<Float
>()) --f
.e
;
3147 constexpr auto num_fraction_bits
=
3148 num_float_significand_bits
+ (has_implicit_bit
<Float
>() ? 1 : 0);
3149 constexpr auto num_xdigits
= (num_fraction_bits
+ 3) / 4;
3151 constexpr auto leading_shift
= ((num_xdigits
- 1) * 4);
3152 const auto leading_mask
= carrier_uint(0xF) << leading_shift
;
3153 const auto leading_xdigit
=
3154 static_cast<uint32_t>((f
.f
& leading_mask
) >> leading_shift
);
3155 if (leading_xdigit
> 1) f
.e
-= (32 - countl_zero(leading_xdigit
) - 1);
3157 int print_xdigits
= num_xdigits
- 1;
3158 if (specs
.precision
>= 0 && print_xdigits
> specs
.precision
) {
3159 const int shift
= ((print_xdigits
- specs
.precision
- 1) * 4);
3160 const auto mask
= carrier_uint(0xF) << shift
;
3161 const auto v
= static_cast<uint32_t>((f
.f
& mask
) >> shift
);
3164 const auto inc
= carrier_uint(1) << (shift
+ 4);
3169 // Check long double overflow
3170 if (!has_implicit_bit
<Float
>()) {
3171 const auto implicit_bit
= carrier_uint(1) << num_float_significand_bits
;
3172 if ((f
.f
& implicit_bit
) == implicit_bit
) {
3178 print_xdigits
= specs
.precision
;
3181 char xdigits
[num_bits
<carrier_uint
>() / 4];
3182 detail::fill_n(xdigits
, sizeof(xdigits
), '0');
3183 format_uint
<4>(xdigits
, f
.f
, num_xdigits
, specs
.upper
);
3186 while (print_xdigits
> 0 && xdigits
[print_xdigits
] == '0') --print_xdigits
;
3189 buf
.push_back(specs
.upper
? 'X' : 'x');
3190 buf
.push_back(xdigits
[0]);
3191 if (specs
.alt
|| print_xdigits
> 0 || print_xdigits
< specs
.precision
)
3193 buf
.append(xdigits
+ 1, xdigits
+ 1 + print_xdigits
);
3194 for (; print_xdigits
< specs
.precision
; ++print_xdigits
) buf
.push_back('0');
3196 buf
.push_back(specs
.upper
? 'P' : 'p');
3201 abs_e
= static_cast<uint32_t>(-f
.e
);
3204 abs_e
= static_cast<uint32_t>(f
.e
);
3206 format_decimal
<char>(appender(buf
), abs_e
, detail::count_digits(abs_e
));
3209 template <typename Float
, FMT_ENABLE_IF(is_double_double
<Float
>::value
)>
3210 FMT_CONSTEXPR20
void format_hexfloat(Float value
, format_specs specs
,
3211 buffer
<char>& buf
) {
3212 format_hexfloat(static_cast<double>(value
), specs
, buf
);
3215 constexpr auto fractional_part_rounding_thresholds(int index
) -> uint32_t {
3216 // For checking rounding thresholds.
3217 // The kth entry is chosen to be the smallest integer such that the
3218 // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k.
3219 // It is equal to ceil(2^31 + 2^32/10^(k + 1)).
3220 // These are stored in a string literal because we cannot have static arrays
3221 // in constexpr functions and non-static ones are poorly optimized.
3222 return U
"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
3223 U
"\x800001ae\x8000002b"[index
];
3226 template <typename Float
>
3227 FMT_CONSTEXPR20
auto format_float(Float value
, int precision
, float_specs specs
,
3228 buffer
<char>& buf
) -> int {
3229 // float is passed as double to reduce the number of instantiations.
3230 static_assert(!std::is_same
<Float
, float>::value
, "");
3231 FMT_ASSERT(value
>= 0, "value is negative");
3232 auto converted_value
= convert_float(value
);
3234 const bool fixed
= specs
.format
== float_format::fixed
;
3235 if (value
<= 0) { // <= instead of == to silence a warning.
3236 if (precision
<= 0 || !fixed
) {
3240 buf
.try_resize(to_unsigned(precision
));
3241 fill_n(buf
.data(), precision
, '0');
3246 bool use_dragon
= true;
3247 unsigned dragon_flags
= 0;
3248 if (!is_fast_float
<Float
>() || is_constant_evaluated()) {
3249 const auto inv_log2_10
= 0.3010299956639812; // 1 / log2(10)
3250 using info
= dragonbox::float_info
<decltype(converted_value
)>;
3251 const auto f
= basic_fp
<typename
info::carrier_uint
>(converted_value
);
3252 // Compute exp, an approximate power of 10, such that
3253 // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
3254 // This is based on log10(value) == log2(value) / log2(10) and approximation
3255 // of log2(value) by e + num_fraction_bits idea from double-conversion.
3256 auto e
= (f
.e
+ count_digits
<1>(f
.f
) - 1) * inv_log2_10
- 1e-10;
3257 exp
= static_cast<int>(e
);
3258 if (e
> exp
) ++exp
; // Compute ceil.
3259 dragon_flags
= dragon::fixup
;
3260 } else if (precision
< 0) {
3261 // Use Dragonbox for the shortest format.
3262 if (specs
.binary32
) {
3263 auto dec
= dragonbox::to_decimal(static_cast<float>(value
));
3264 write
<char>(appender(buf
), dec
.significand
);
3265 return dec
.exponent
;
3267 auto dec
= dragonbox::to_decimal(static_cast<double>(value
));
3268 write
<char>(appender(buf
), dec
.significand
);
3269 return dec
.exponent
;
3271 // Extract significand bits and exponent bits.
3272 using info
= dragonbox::float_info
<double>;
3273 auto br
= bit_cast
<uint64_t>(static_cast<double>(value
));
3275 const uint64_t significand_mask
=
3276 (static_cast<uint64_t>(1) << num_significand_bits
<double>()) - 1;
3277 uint64_t significand
= (br
& significand_mask
);
3278 int exponent
= static_cast<int>((br
& exponent_mask
<double>()) >>
3279 num_significand_bits
<double>());
3281 if (exponent
!= 0) { // Check if normal.
3282 exponent
-= exponent_bias
<double>() + num_significand_bits
<double>();
3284 (static_cast<uint64_t>(1) << num_significand_bits
<double>());
3287 // Normalize subnormal inputs.
3288 FMT_ASSERT(significand
!= 0, "zeros should not appear here");
3289 int shift
= countl_zero(significand
);
3290 FMT_ASSERT(shift
>= num_bits
<uint64_t>() - num_significand_bits
<double>(),
3292 shift
-= (num_bits
<uint64_t>() - num_significand_bits
<double>() - 2);
3293 exponent
= (std::numeric_limits
<double>::min_exponent
-
3294 num_significand_bits
<double>()) -
3296 significand
<<= shift
;
3299 // Compute the first several nonzero decimal significand digits.
3300 // We call the number we get the first segment.
3301 const int k
= info::kappa
- dragonbox::floor_log10_pow2(exponent
);
3303 const int beta
= exponent
+ dragonbox::floor_log2_pow10(k
);
3304 uint64_t first_segment
;
3305 bool has_more_segments
;
3306 int digits_in_the_first_segment
;
3308 const auto r
= dragonbox::umul192_upper128(
3309 significand
<< beta
, dragonbox::get_cached_power(k
));
3310 first_segment
= r
.high();
3311 has_more_segments
= r
.low() != 0;
3313 // The first segment can have 18 ~ 19 digits.
3314 if (first_segment
>= 1000000000000000000ULL) {
3315 digits_in_the_first_segment
= 19;
3317 // When it is of 18-digits, we align it to 19-digits by adding a bogus
3319 digits_in_the_first_segment
= 18;
3320 first_segment
*= 10;
3324 // Compute the actual number of decimal digits to print.
3325 if (fixed
) adjust_precision(precision
, exp
+ digits_in_the_first_segment
);
3327 // Use Dragon4 only when there might be not enough digits in the first
3329 if (digits_in_the_first_segment
> precision
) {
3332 if (precision
<= 0) {
3333 exp
+= digits_in_the_first_segment
;
3335 if (precision
< 0) {
3336 // Nothing to do, since all we have are just leading zeros.
3339 // We may need to round-up.
3341 if ((first_segment
| static_cast<uint64_t>(has_more_segments
)) >
3342 5000000000000000000ULL) {
3350 exp
+= digits_in_the_first_segment
- precision
;
3352 // When precision > 0, we divide the first segment into three
3353 // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits
3354 // in 32-bits which usually allows faster calculation than in
3355 // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize
3356 // division-by-constant for large 64-bit divisors, we do it here
3357 // manually. The magic number 7922816251426433760 below is equal to
3358 // ceil(2^(64+32) / 10^10).
3359 const uint32_t first_subsegment
= static_cast<uint32_t>(
3360 dragonbox::umul128_upper64(first_segment
, 7922816251426433760ULL) >>
3362 const uint64_t second_third_subsegments
=
3363 first_segment
- first_subsegment
* 10000000000ULL;
3367 bool should_round_up
;
3368 int number_of_digits_to_print
= precision
> 9 ? 9 : precision
;
3370 // Print a 9-digits subsegment, either the first or the second.
3371 auto print_subsegment
= [&](uint32_t subsegment
, char* buffer
) {
3372 int number_of_digits_printed
= 0;
3374 // If we want to print an odd number of digits from the subsegment,
3375 if ((number_of_digits_to_print
& 1) != 0) {
3376 // Convert to 64-bit fixed-point fractional form with 1-digit
3377 // integer part. The magic number 720575941 is a good enough
3378 // approximation of 2^(32 + 24) / 10^8; see
3379 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3381 prod
= ((subsegment
* static_cast<uint64_t>(720575941)) >> 24) + 1;
3382 digits
= static_cast<uint32_t>(prod
>> 32);
3383 *buffer
= static_cast<char>('0' + digits
);
3384 number_of_digits_printed
++;
3386 // If we want to print an even number of digits from the
3387 // first_subsegment,
3389 // Convert to 64-bit fixed-point fractional form with 2-digits
3390 // integer part. The magic number 450359963 is a good enough
3391 // approximation of 2^(32 + 20) / 10^7; see
3392 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3394 prod
= ((subsegment
* static_cast<uint64_t>(450359963)) >> 20) + 1;
3395 digits
= static_cast<uint32_t>(prod
>> 32);
3396 copy2(buffer
, digits2(digits
));
3397 number_of_digits_printed
+= 2;
3400 // Print all digit pairs.
3401 while (number_of_digits_printed
< number_of_digits_to_print
) {
3402 prod
= static_cast<uint32_t>(prod
) * static_cast<uint64_t>(100);
3403 digits
= static_cast<uint32_t>(prod
>> 32);
3404 copy2(buffer
+ number_of_digits_printed
, digits2(digits
));
3405 number_of_digits_printed
+= 2;
3409 // Print first subsegment.
3410 print_subsegment(first_subsegment
, buf
.data());
3412 // Perform rounding if the first subsegment is the last subsegment to
3414 if (precision
<= 9) {
3415 // Rounding inside the subsegment.
3417 // - either the fractional part is strictly larger than 1/2, or
3418 // - the fractional part is exactly 1/2 and the last digit is odd.
3419 // We rely on the following observations:
3420 // - If fractional_part >= threshold, then the fractional part is
3421 // strictly larger than 1/2.
3422 // - If the MSB of fractional_part is set, then the fractional part
3423 // must be at least 1/2.
3424 // - When the MSB of fractional_part is set, either
3425 // second_third_subsegments being nonzero or has_more_segments
3426 // being true means there are further digits not printed, so the
3427 // fractional part is strictly larger than 1/2.
3428 if (precision
< 9) {
3429 uint32_t fractional_part
= static_cast<uint32_t>(prod
);
3431 fractional_part
>= fractional_part_rounding_thresholds(
3432 8 - number_of_digits_to_print
) ||
3433 ((fractional_part
>> 31) &
3434 ((digits
& 1) | (second_third_subsegments
!= 0) |
3435 has_more_segments
)) != 0;
3437 // Rounding at the subsegment boundary.
3438 // In this case, the fractional part is at least 1/2 if and only if
3439 // second_third_subsegments >= 5000000000ULL, and is strictly larger
3440 // than 1/2 if we further have either second_third_subsegments >
3441 // 5000000000ULL or has_more_segments == true.
3443 should_round_up
= second_third_subsegments
> 5000000000ULL ||
3444 (second_third_subsegments
== 5000000000ULL &&
3445 ((digits
& 1) != 0 || has_more_segments
));
3448 // Otherwise, print the second subsegment.
3450 // Compilers are not aware of how to leverage the maximum value of
3451 // second_third_subsegments to find out a better magic number which
3452 // allows us to eliminate an additional shift. 1844674407370955162 =
3453 // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))).
3454 const uint32_t second_subsegment
=
3455 static_cast<uint32_t>(dragonbox::umul128_upper64(
3456 second_third_subsegments
, 1844674407370955162ULL));
3457 const uint32_t third_subsegment
=
3458 static_cast<uint32_t>(second_third_subsegments
) -
3459 second_subsegment
* 10;
3461 number_of_digits_to_print
= precision
- 9;
3462 print_subsegment(second_subsegment
, buf
.data() + 9);
3464 // Rounding inside the subsegment.
3465 if (precision
< 18) {
3466 // The condition third_subsegment != 0 implies that the segment was
3467 // of 19 digits, so in this case the third segment should be
3468 // consisting of a genuine digit from the input.
3469 uint32_t fractional_part
= static_cast<uint32_t>(prod
);
3471 fractional_part
>= fractional_part_rounding_thresholds(
3472 8 - number_of_digits_to_print
) ||
3473 ((fractional_part
>> 31) &
3474 ((digits
& 1) | (third_subsegment
!= 0) |
3475 has_more_segments
)) != 0;
3477 // Rounding at the subsegment boundary.
3479 // In this case, the segment must be of 19 digits, thus
3480 // the third subsegment should be consisting of a genuine digit from
3482 should_round_up
= third_subsegment
> 5 ||
3483 (third_subsegment
== 5 &&
3484 ((digits
& 1) != 0 || has_more_segments
));
3488 // Round-up if necessary.
3489 if (should_round_up
) {
3490 ++buf
[precision
- 1];
3491 for (int i
= precision
- 1; i
> 0 && buf
[i
] > '9'; --i
) {
3498 buf
[precision
++] = '0';
3503 buf
.try_resize(to_unsigned(precision
));
3505 } // if (digits_in_the_first_segment > precision)
3507 // Adjust the exponent for its use in Dragon4.
3508 exp
+= digits_in_the_first_segment
- 1;
3512 auto f
= basic_fp
<uint128_t
>();
3513 bool is_predecessor_closer
= specs
.binary32
3514 ? f
.assign(static_cast<float>(value
))
3515 : f
.assign(converted_value
);
3516 if (is_predecessor_closer
) dragon_flags
|= dragon::predecessor_closer
;
3517 if (fixed
) dragon_flags
|= dragon::fixed
;
3518 // Limit precision to the maximum possible number of significant digits in
3519 // an IEEE754 double because we don't need to generate zeros.
3520 const int max_double_digits
= 767;
3521 if (precision
> max_double_digits
) precision
= max_double_digits
;
3522 format_dragon(f
, dragon_flags
, precision
, buf
, exp
);
3524 if (!fixed
&& !specs
.showpoint
) {
3525 // Remove trailing zeros.
3526 auto num_digits
= buf
.size();
3527 while (num_digits
> 0 && buf
[num_digits
- 1] == '0') {
3531 buf
.try_resize(num_digits
);
3536 template <typename Char
, typename OutputIt
, typename T
>
3537 FMT_CONSTEXPR20
auto write_float(OutputIt out
, T value
, format_specs specs
,
3538 locale_ref loc
) -> OutputIt
{
3539 sign_t sign
= specs
.sign
;
3540 if (detail::signbit(value
)) { // value < 0 is false for NaN so use signbit.
3543 } else if (sign
== sign::minus
) {
3547 if (!detail::isfinite(value
))
3548 return write_nonfinite
<Char
>(out
, detail::isnan(value
), specs
, sign
);
3550 if (specs
.align
== align::numeric
&& sign
) {
3551 auto it
= reserve(out
, 1);
3552 *it
++ = detail::sign
<Char
>(sign
);
3553 out
= base_iterator(out
, it
);
3555 if (specs
.width
!= 0) --specs
.width
;
3558 memory_buffer buffer
;
3559 if (specs
.type
== presentation_type::hexfloat
) {
3560 if (sign
) buffer
.push_back(detail::sign
<char>(sign
));
3561 format_hexfloat(convert_float(value
), specs
, buffer
);
3562 return write_bytes
<Char
, align::right
>(out
, {buffer
.data(), buffer
.size()},
3566 int precision
= specs
.precision
>= 0 || specs
.type
== presentation_type::none
3569 if (specs
.type
== presentation_type::exp
) {
3570 if (precision
== max_value
<int>())
3571 report_error("number is too big");
3574 } else if (specs
.type
!= presentation_type::fixed
&& precision
== 0) {
3577 float_specs fspecs
= parse_float_type_spec(specs
);
3579 if (const_check(std::is_same
<T
, float>())) fspecs
.binary32
= true;
3580 int exp
= format_float(convert_float(value
), precision
, fspecs
, buffer
);
3581 fspecs
.precision
= precision
;
3582 auto f
= big_decimal_fp
{buffer
.data(), static_cast<int>(buffer
.size()), exp
};
3583 return write_float
<Char
>(out
, f
, specs
, fspecs
, loc
);
3586 template <typename Char
, typename OutputIt
, typename T
,
3587 FMT_ENABLE_IF(is_floating_point
<T
>::value
)>
3588 FMT_CONSTEXPR20
auto write(OutputIt out
, T value
, format_specs specs
,
3589 locale_ref loc
= {}) -> OutputIt
{
3590 if (const_check(!is_supported_floating_point(value
))) return out
;
3591 return specs
.localized
&& write_loc(out
, value
, specs
, loc
)
3593 : write_float
<Char
>(out
, value
, specs
, loc
);
3596 template <typename Char
, typename OutputIt
, typename T
,
3597 FMT_ENABLE_IF(is_fast_float
<T
>::value
)>
3598 FMT_CONSTEXPR20
auto write(OutputIt out
, T value
) -> OutputIt
{
3599 if (is_constant_evaluated()) return write
<Char
>(out
, value
, format_specs());
3600 if (const_check(!is_supported_floating_point(value
))) return out
;
3602 auto sign
= sign_t::none
;
3603 if (detail::signbit(value
)) {
3608 constexpr auto specs
= format_specs();
3609 using floaty
= conditional_t
<std::is_same
<T
, long double>::value
, double, T
>;
3610 using floaty_uint
= typename
dragonbox::float_info
<floaty
>::carrier_uint
;
3611 floaty_uint mask
= exponent_mask
<floaty
>();
3612 if ((bit_cast
<floaty_uint
>(value
) & mask
) == mask
)
3613 return write_nonfinite
<Char
>(out
, std::isnan(value
), specs
, sign
);
3615 auto fspecs
= float_specs();
3617 auto dec
= dragonbox::to_decimal(static_cast<floaty
>(value
));
3618 return write_float
<Char
>(out
, dec
, specs
, fspecs
, {});
3621 template <typename Char
, typename OutputIt
, typename T
,
3622 FMT_ENABLE_IF(is_floating_point
<T
>::value
&&
3623 !is_fast_float
<T
>::value
)>
3624 inline auto write(OutputIt out
, T value
) -> OutputIt
{
3625 return write
<Char
>(out
, value
, format_specs());
3628 template <typename Char
, typename OutputIt
>
3629 auto write(OutputIt out
, monostate
, format_specs
= {}, locale_ref
= {})
3631 FMT_ASSERT(false, "");
3635 template <typename Char
, typename OutputIt
>
3636 FMT_CONSTEXPR
auto write(OutputIt out
, basic_string_view
<Char
> value
)
3638 return copy_noinline
<Char
>(value
.begin(), value
.end(), out
);
3641 template <typename Char
, typename OutputIt
, typename T
,
3642 FMT_ENABLE_IF(has_to_string_view
<T
>::value
)>
3643 constexpr auto write(OutputIt out
, const T
& value
) -> OutputIt
{
3644 return write
<Char
>(out
, to_string_view(value
));
3647 // FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
3649 typename Char
, typename OutputIt
, typename T
,
3651 std::is_enum
<T
>::value
&& !std::is_same
<T
, Char
>::value
&&
3652 mapped_type_constant
<T
, basic_format_context
<OutputIt
, Char
>>::value
!=
3654 FMT_ENABLE_IF(check
)>
3655 FMT_CONSTEXPR
auto write(OutputIt out
, T value
) -> OutputIt
{
3656 return write
<Char
>(out
, static_cast<underlying_t
<T
>>(value
));
3659 template <typename Char
, typename OutputIt
, typename T
,
3660 FMT_ENABLE_IF(std::is_same
<T
, bool>::value
)>
3661 FMT_CONSTEXPR
auto write(OutputIt out
, T value
, const format_specs
& specs
= {},
3662 locale_ref
= {}) -> OutputIt
{
3663 return specs
.type
!= presentation_type::none
&&
3664 specs
.type
!= presentation_type::string
3665 ? write
<Char
>(out
, value
? 1 : 0, specs
, {})
3666 : write_bytes
<Char
>(out
, value
? "true" : "false", specs
);
3669 template <typename Char
, typename OutputIt
>
3670 FMT_CONSTEXPR
auto write(OutputIt out
, Char value
) -> OutputIt
{
3671 auto it
= reserve(out
, 1);
3673 return base_iterator(out
, it
);
3676 template <typename Char
, typename OutputIt
>
3677 FMT_CONSTEXPR20
auto write(OutputIt out
, const Char
* value
) -> OutputIt
{
3678 if (value
) return write(out
, basic_string_view
<Char
>(value
));
3679 report_error("string pointer is null");
3683 template <typename Char
, typename OutputIt
, typename T
,
3684 FMT_ENABLE_IF(std::is_same
<T
, void>::value
)>
3685 auto write(OutputIt out
, const T
* value
, const format_specs
& specs
= {},
3686 locale_ref
= {}) -> OutputIt
{
3687 return write_ptr
<Char
>(out
, bit_cast
<uintptr_t>(value
), &specs
);
3690 // A write overload that handles implicit conversions.
3691 template <typename Char
, typename OutputIt
, typename T
,
3692 typename Context
= basic_format_context
<OutputIt
, Char
>>
3693 FMT_CONSTEXPR
auto write(OutputIt out
, const T
& value
) -> enable_if_t
<
3694 std::is_class
<T
>::value
&& !has_to_string_view
<T
>::value
&&
3695 !is_floating_point
<T
>::value
&& !std::is_same
<T
, Char
>::value
&&
3696 !std::is_same
<T
, remove_cvref_t
<decltype(arg_mapper
<Context
>().map(
3699 return write
<Char
>(out
, arg_mapper
<Context
>().map(value
));
3702 template <typename Char
, typename OutputIt
, typename T
,
3703 typename Context
= basic_format_context
<OutputIt
, Char
>>
3704 FMT_CONSTEXPR
auto write(OutputIt out
, const T
& value
)
3705 -> enable_if_t
<mapped_type_constant
<T
, Context
>::value
==
3706 type::custom_type
&&
3707 !std::is_fundamental
<T
>::value
,
3709 auto formatter
= typename
Context::template formatter_type
<T
>();
3710 auto parse_ctx
= typename
Context::parse_context_type({});
3711 formatter
.parse(parse_ctx
);
3712 auto ctx
= Context(out
, {}, {});
3713 return formatter
.format(value
, ctx
);
3716 // An argument visitor that formats the argument and writes it via the output
3717 // iterator. It's a class and not a generic lambda for compatibility with C++11.
3718 template <typename Char
> struct default_arg_formatter
{
3719 using iterator
= basic_appender
<Char
>;
3720 using context
= buffered_context
<Char
>;
3723 basic_format_args
<context
> args
;
3726 template <typename T
> auto operator()(T value
) -> iterator
{
3727 return write
<Char
>(out
, value
);
3729 auto operator()(typename basic_format_arg
<context
>::handle h
) -> iterator
{
3730 basic_format_parse_context
<Char
> parse_ctx({});
3731 context
format_ctx(out
, args
, loc
);
3732 h
.format(parse_ctx
, format_ctx
);
3733 return format_ctx
.out();
3737 template <typename Char
> struct arg_formatter
{
3738 using iterator
= basic_appender
<Char
>;
3739 using context
= buffered_context
<Char
>;
3742 const format_specs
& specs
;
3745 template <typename T
>
3746 FMT_CONSTEXPR FMT_INLINE
auto operator()(T value
) -> iterator
{
3747 return detail::write
<Char
>(out
, value
, specs
, locale
);
3749 auto operator()(typename basic_format_arg
<context
>::handle
) -> iterator
{
3750 // User-defined types are handled separately because they require access
3751 // to the parse context.
3756 struct width_checker
{
3757 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
3758 FMT_CONSTEXPR
auto operator()(T value
) -> unsigned long long {
3759 if (is_negative(value
)) report_error("negative width");
3760 return static_cast<unsigned long long>(value
);
3763 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
3764 FMT_CONSTEXPR
auto operator()(T
) -> unsigned long long {
3765 report_error("width is not integer");
3770 struct precision_checker
{
3771 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
3772 FMT_CONSTEXPR
auto operator()(T value
) -> unsigned long long {
3773 if (is_negative(value
)) report_error("negative precision");
3774 return static_cast<unsigned long long>(value
);
3777 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
3778 FMT_CONSTEXPR
auto operator()(T
) -> unsigned long long {
3779 report_error("precision is not integer");
3784 template <typename Handler
, typename FormatArg
>
3785 FMT_CONSTEXPR
auto get_dynamic_spec(FormatArg arg
) -> int {
3786 unsigned long long value
= arg
.visit(Handler());
3787 if (value
> to_unsigned(max_value
<int>())) report_error("number is too big");
3788 return static_cast<int>(value
);
3791 template <typename Context
, typename ID
>
3792 FMT_CONSTEXPR
auto get_arg(Context
& ctx
, ID id
) -> decltype(ctx
.arg(id
)) {
3793 auto arg
= ctx
.arg(id
);
3794 if (!arg
) report_error("argument not found");
3798 template <typename Handler
, typename Context
>
3799 FMT_CONSTEXPR
void handle_dynamic_spec(int& value
,
3800 arg_ref
<typename
Context::char_type
> ref
,
3803 case arg_id_kind::none
:
3805 case arg_id_kind::index
:
3806 value
= detail::get_dynamic_spec
<Handler
>(get_arg(ctx
, ref
.val
.index
));
3808 case arg_id_kind::name
:
3809 value
= detail::get_dynamic_spec
<Handler
>(get_arg(ctx
, ref
.val
.name
));
3814 #if FMT_USE_USER_DEFINED_LITERALS
3815 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
3816 template <typename T
, typename Char
, size_t N
,
3817 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3818 struct statically_named_arg
: view
{
3819 static constexpr auto name
= Str
.data
;
3822 statically_named_arg(const T
& v
) : value(v
) {}
3825 template <typename T
, typename Char
, size_t N
,
3826 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3827 struct is_named_arg
<statically_named_arg
<T
, Char
, N
, Str
>> : std::true_type
{};
3829 template <typename T
, typename Char
, size_t N
,
3830 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3831 struct is_statically_named_arg
<statically_named_arg
<T
, Char
, N
, Str
>>
3832 : std::true_type
{};
3834 template <typename Char
, size_t N
,
3835 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3837 template <typename T
> auto operator=(T
&& value
) const {
3838 return statically_named_arg
<T
, Char
, N
, Str
>(std::forward
<T
>(value
));
3842 template <typename Char
> struct udl_arg
{
3845 template <typename T
> auto operator=(T
&& value
) const -> named_arg
<Char
, T
> {
3846 return {str
, std::forward
<T
>(value
)};
3850 #endif // FMT_USE_USER_DEFINED_LITERALS
3852 template <typename Locale
, typename Char
>
3853 auto vformat(const Locale
& loc
, basic_string_view
<Char
> fmt
,
3854 typename
detail::vformat_args
<Char
>::type args
)
3855 -> std::basic_string
<Char
> {
3856 auto buf
= basic_memory_buffer
<Char
>();
3857 detail::vformat_to(buf
, fmt
, args
, detail::locale_ref(loc
));
3858 return {buf
.data(), buf
.size()};
3861 using format_func
= void (*)(detail::buffer
<char>&, int, const char*);
3863 FMT_API
void format_error_code(buffer
<char>& out
, int error_code
,
3864 string_view message
) noexcept
;
3866 using fmt::report_error
;
3867 FMT_API
void report_error(format_func func
, int error_code
,
3868 const char* message
) noexcept
;
3869 } // namespace detail
3872 FMT_API
auto vsystem_error(int error_code
, string_view format_str
,
3873 format_args args
) -> std::system_error
;
3876 * Constructs `std::system_error` with a message formatted with
3877 * `fmt::format(fmt, args...)`.
3878 * `error_code` is a system error code as given by `errno`.
3882 * // This throws std::system_error with the description
3883 * // cannot open file 'madeup': No such file or directory
3884 * // or similar (system message may vary).
3885 * const char* filename = "madeup";
3886 * std::FILE* file = std::fopen(filename, "r");
3888 * throw fmt::system_error(errno, "cannot open file '{}'", filename);
3890 template <typename
... T
>
3891 auto system_error(int error_code
, format_string
<T
...> fmt
, T
&&... args
)
3892 -> std::system_error
{
3893 return vsystem_error(error_code
, fmt
, fmt::make_format_args(args
...));
3897 * Formats an error message for an error returned by an operating system or a
3898 * language runtime, for example a file opening error, and writes it to `out`.
3899 * The format is the same as the one used by `std::system_error(ec, message)`
3900 * where `ec` is `std::error_code(error_code, std::generic_category())`.
3901 * It is implementation-defined but normally looks like:
3903 * <message>: <system-message>
3905 * where `<message>` is the passed message and `<system-message>` is the system
3906 * message corresponding to the error code.
3907 * `error_code` is a system error code as given by `errno`.
3909 FMT_API
void format_system_error(detail::buffer
<char>& out
, int error_code
,
3910 const char* message
) noexcept
;
3912 // Reports a system error without throwing an exception.
3913 // Can be used to report errors from destructors.
3914 FMT_API
void report_system_error(int error_code
, const char* message
) noexcept
;
3916 /// A fast integer formatter.
3919 // Buffer should be large enough to hold all digits (digits10 + 1),
3920 // a sign and a null character.
3921 enum { buffer_size
= std::numeric_limits
<unsigned long long>::digits10
+ 3 };
3922 mutable char buffer_
[buffer_size
];
3925 template <typename UInt
>
3926 FMT_CONSTEXPR20
auto format_unsigned(UInt value
) -> char* {
3927 auto n
= static_cast<detail::uint32_or_64_or_128_t
<UInt
>>(value
);
3928 return detail::format_decimal(buffer_
, n
, buffer_size
- 1).begin
;
3931 template <typename Int
>
3932 FMT_CONSTEXPR20
auto format_signed(Int value
) -> char* {
3933 auto abs_value
= static_cast<detail::uint32_or_64_or_128_t
<Int
>>(value
);
3934 bool negative
= value
< 0;
3935 if (negative
) abs_value
= 0 - abs_value
;
3936 auto begin
= format_unsigned(abs_value
);
3937 if (negative
) *--begin
= '-';
3942 explicit FMT_CONSTEXPR20
format_int(int value
) : str_(format_signed(value
)) {}
3943 explicit FMT_CONSTEXPR20
format_int(long value
)
3944 : str_(format_signed(value
)) {}
3945 explicit FMT_CONSTEXPR20
format_int(long long value
)
3946 : str_(format_signed(value
)) {}
3947 explicit FMT_CONSTEXPR20
format_int(unsigned value
)
3948 : str_(format_unsigned(value
)) {}
3949 explicit FMT_CONSTEXPR20
format_int(unsigned long value
)
3950 : str_(format_unsigned(value
)) {}
3951 explicit FMT_CONSTEXPR20
format_int(unsigned long long value
)
3952 : str_(format_unsigned(value
)) {}
3954 /// Returns the number of characters written to the output buffer.
3955 FMT_CONSTEXPR20
auto size() const -> size_t {
3956 return detail::to_unsigned(buffer_
- str_
+ buffer_size
- 1);
3959 /// Returns a pointer to the output buffer content. No terminating null
3960 /// character is appended.
3961 FMT_CONSTEXPR20
auto data() const -> const char* { return str_
; }
3963 /// Returns a pointer to the output buffer content with terminating null
3964 /// character appended.
3965 FMT_CONSTEXPR20
auto c_str() const -> const char* {
3966 buffer_
[buffer_size
- 1] = '\0';
3970 /// Returns the content of the output buffer as an `std::string`.
3971 auto str() const -> std::string
{ return std::string(str_
, size()); }
3974 template <typename T
, typename Char
>
3975 struct formatter
<T
, Char
, enable_if_t
<detail::has_format_as
<T
>::value
>>
3976 : formatter
<detail::format_as_t
<T
>, Char
> {
3977 template <typename FormatContext
>
3978 auto format(const T
& value
, FormatContext
& ctx
) const -> decltype(ctx
.out()) {
3979 auto&& val
= format_as(value
); // Make an lvalue reference for format.
3980 return formatter
<detail::format_as_t
<T
>, Char
>::format(val
, ctx
);
3984 #define FMT_FORMAT_AS(Type, Base) \
3985 template <typename Char> \
3986 struct formatter<Type, Char> : formatter<Base, Char> { \
3987 template <typename FormatContext> \
3988 auto format(Type value, FormatContext& ctx) const -> decltype(ctx.out()) { \
3989 return formatter<Base, Char>::format(value, ctx); \
3993 FMT_FORMAT_AS(signed char, int);
3994 FMT_FORMAT_AS(unsigned char, unsigned);
3995 FMT_FORMAT_AS(short, int);
3996 FMT_FORMAT_AS(unsigned short, unsigned);
3997 FMT_FORMAT_AS(long, detail::long_type
);
3998 FMT_FORMAT_AS(unsigned long, detail::ulong_type
);
3999 FMT_FORMAT_AS(Char
*, const Char
*);
4000 FMT_FORMAT_AS(std::nullptr_t
, const void*);
4001 FMT_FORMAT_AS(detail::std_string_view
<Char
>, basic_string_view
<Char
>);
4002 FMT_FORMAT_AS(void*, const void*);
4004 template <typename Char
, typename Traits
, typename Allocator
>
4005 class formatter
<std::basic_string
<Char
, Traits
, Allocator
>, Char
>
4006 : public formatter
<basic_string_view
<Char
>, Char
> {};
4008 template <typename Char
, size_t N
>
4009 struct formatter
<Char
[N
], Char
> : formatter
<basic_string_view
<Char
>, Char
> {};
4012 * Converts `p` to `const void*` for pointer formatting.
4016 * auto s = fmt::format("{}", fmt::ptr(p));
4018 template <typename T
> auto ptr(T p
) -> const void* {
4019 static_assert(std::is_pointer
<T
>::value
, "");
4020 return detail::bit_cast
<const void*>(p
);
4024 * Converts `e` to the underlying type.
4028 * enum class color { red, green, blue };
4029 * auto s = fmt::format("{}", fmt::underlying(color::red));
4031 template <typename Enum
>
4032 constexpr auto underlying(Enum e
) noexcept
-> underlying_t
<Enum
> {
4033 return static_cast<underlying_t
<Enum
>>(e
);
4037 template <typename Enum
, FMT_ENABLE_IF(std::is_enum
<Enum
>::value
)>
4038 constexpr auto format_as(Enum e
) noexcept
-> underlying_t
<Enum
> {
4039 return static_cast<underlying_t
<Enum
>>(e
);
4041 } // namespace enums
4046 friend struct formatter
<bytes
>;
4049 explicit bytes(string_view data
) : data_(data
) {}
4052 template <> struct formatter
<bytes
> {
4054 detail::dynamic_format_specs
<> specs_
;
4057 template <typename ParseContext
>
4058 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const char* {
4059 return parse_format_specs(ctx
.begin(), ctx
.end(), specs_
, ctx
,
4060 detail::type::string_type
);
4063 template <typename FormatContext
>
4064 auto format(bytes b
, FormatContext
& ctx
) const -> decltype(ctx
.out()) {
4065 auto specs
= specs_
;
4066 detail::handle_dynamic_spec
<detail::width_checker
>(specs
.width
,
4067 specs
.width_ref
, ctx
);
4068 detail::handle_dynamic_spec
<detail::precision_checker
>(
4069 specs
.precision
, specs
.precision_ref
, ctx
);
4070 return detail::write_bytes
<char>(ctx
.out(), b
.data_
, specs
);
4074 // group_digits_view is not derived from view because it copies the argument.
4075 template <typename T
> struct group_digits_view
{
4080 * Returns a view that formats an integer value using ',' as a
4081 * locale-independent thousands separator.
4085 * fmt::print("{}", fmt::group_digits(12345));
4086 * // Output: "12,345"
4088 template <typename T
> auto group_digits(T value
) -> group_digits_view
<T
> {
4092 template <typename T
> struct formatter
<group_digits_view
<T
>> : formatter
<T
> {
4094 detail::dynamic_format_specs
<> specs_
;
4097 template <typename ParseContext
>
4098 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const char* {
4099 return parse_format_specs(ctx
.begin(), ctx
.end(), specs_
, ctx
,
4100 detail::type::int_type
);
4103 template <typename FormatContext
>
4104 auto format(group_digits_view
<T
> t
, FormatContext
& ctx
) const
4105 -> decltype(ctx
.out()) {
4106 auto specs
= specs_
;
4107 detail::handle_dynamic_spec
<detail::width_checker
>(specs
.width
,
4108 specs
.width_ref
, ctx
);
4109 detail::handle_dynamic_spec
<detail::precision_checker
>(
4110 specs
.precision
, specs
.precision_ref
, ctx
);
4111 auto arg
= detail::make_write_int_arg(t
.value
, specs
.sign
);
4112 return detail::write_int(
4113 ctx
.out(), static_cast<detail::uint64_or_128_t
<T
>>(arg
.abs_value
),
4114 arg
.prefix
, specs
, detail::digit_grouping
<char>("\3", ","));
4118 template <typename T
, typename Char
> struct nested_view
{
4119 const formatter
<T
, Char
>* fmt
;
4123 template <typename T
, typename Char
>
4124 struct formatter
<nested_view
<T
, Char
>, Char
> {
4125 template <typename ParseContext
>
4126 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> decltype(ctx
.begin()) {
4129 template <typename FormatContext
>
4130 auto format(nested_view
<T
, Char
> view
, FormatContext
& ctx
) const
4131 -> decltype(ctx
.out()) {
4132 return view
.fmt
->format(*view
.value
, ctx
);
4136 template <typename T
, typename Char
= char> struct nested_formatter
{
4139 detail::fill_t fill_
;
4141 formatter
<T
, Char
> formatter_
;
4144 constexpr nested_formatter() : width_(0), align_(align_t::none
) {}
4146 FMT_CONSTEXPR
auto parse(basic_format_parse_context
<Char
>& ctx
)
4147 -> decltype(ctx
.begin()) {
4148 auto specs
= detail::dynamic_format_specs
<Char
>();
4149 auto it
= parse_format_specs(ctx
.begin(), ctx
.end(), specs
, ctx
,
4150 detail::type::none_type
);
4151 width_
= specs
.width
;
4153 align_
= specs
.align
;
4155 return formatter_
.parse(ctx
);
4158 template <typename FormatContext
, typename F
>
4159 auto write_padded(FormatContext
& ctx
, F write
) const -> decltype(ctx
.out()) {
4160 if (width_
== 0) return write(ctx
.out());
4161 auto buf
= basic_memory_buffer
<Char
>();
4162 write(basic_appender
<Char
>(buf
));
4163 auto specs
= format_specs();
4164 specs
.width
= width_
;
4166 specs
.align
= align_
;
4167 return detail::write
<Char
>(
4168 ctx
.out(), basic_string_view
<Char
>(buf
.data(), buf
.size()), specs
);
4171 auto nested(const T
& value
) const -> nested_view
<T
, Char
> {
4172 return nested_view
<T
, Char
>{&formatter_
, &value
};
4177 * Converts `value` to `std::string` using the default format for type `T`.
4181 * std::string answer = fmt::to_string(42);
4183 template <typename T
, FMT_ENABLE_IF(!std::is_integral
<T
>::value
&&
4184 !detail::has_format_as
<T
>::value
)>
4185 inline auto to_string(const T
& value
) -> std::string
{
4186 auto buffer
= memory_buffer();
4187 detail::write
<char>(appender(buffer
), value
);
4188 return {buffer
.data(), buffer
.size()};
4191 template <typename T
, FMT_ENABLE_IF(std::is_integral
<T
>::value
)>
4192 FMT_NODISCARD
inline auto to_string(T value
) -> std::string
{
4193 // The buffer should be large enough to store the number including the sign
4194 // or "false" for bool.
4195 constexpr int max_size
= detail::digits10
<T
>() + 2;
4196 char buffer
[max_size
> 5 ? static_cast<unsigned>(max_size
) : 5];
4197 char* begin
= buffer
;
4198 return std::string(begin
, detail::write
<char>(begin
, value
));
4201 template <typename Char
, size_t SIZE
>
4202 FMT_NODISCARD
auto to_string(const basic_memory_buffer
<Char
, SIZE
>& buf
)
4203 -> std::basic_string
<Char
> {
4204 auto size
= buf
.size();
4205 detail::assume(size
< std::basic_string
<Char
>().max_size());
4206 return std::basic_string
<Char
>(buf
.data(), size
);
4209 template <typename T
, FMT_ENABLE_IF(!std::is_integral
<T
>::value
&&
4210 detail::has_format_as
<T
>::value
)>
4211 inline auto to_string(const T
& value
) -> std::string
{
4212 return to_string(format_as(value
));
4219 template <typename Char
>
4220 void vformat_to(buffer
<Char
>& buf
, basic_string_view
<Char
> fmt
,
4221 typename vformat_args
<Char
>::type args
, locale_ref loc
) {
4222 auto out
= basic_appender
<Char
>(buf
);
4223 if (fmt
.size() == 2 && equal2(fmt
.data(), "{}")) {
4224 auto arg
= args
.get(0);
4225 if (!arg
) report_error("argument not found");
4226 arg
.visit(default_arg_formatter
<Char
>{out
, args
, loc
});
4230 struct format_handler
{
4231 basic_format_parse_context
<Char
> parse_context
;
4232 buffered_context
<Char
> context
;
4234 format_handler(basic_appender
<Char
> p_out
, basic_string_view
<Char
> str
,
4235 basic_format_args
<buffered_context
<Char
>> p_args
,
4237 : parse_context(str
), context(p_out
, p_args
, p_loc
) {}
4239 void on_text(const Char
* begin
, const Char
* end
) {
4240 auto text
= basic_string_view
<Char
>(begin
, to_unsigned(end
- begin
));
4241 context
.advance_to(write
<Char
>(context
.out(), text
));
4244 FMT_CONSTEXPR
auto on_arg_id() -> int {
4245 return parse_context
.next_arg_id();
4247 FMT_CONSTEXPR
auto on_arg_id(int id
) -> int {
4248 parse_context
.check_arg_id(id
);
4251 FMT_CONSTEXPR
auto on_arg_id(basic_string_view
<Char
> id
) -> int {
4252 parse_context
.check_arg_id(id
);
4253 int arg_id
= context
.arg_id(id
);
4254 if (arg_id
< 0) report_error("argument not found");
4258 FMT_INLINE
void on_replacement_field(int id
, const Char
*) {
4259 auto arg
= get_arg(context
, id
);
4260 context
.advance_to(arg
.visit(default_arg_formatter
<Char
>{
4261 context
.out(), context
.args(), context
.locale()}));
4264 auto on_format_specs(int id
, const Char
* begin
, const Char
* end
)
4266 auto arg
= get_arg(context
, id
);
4267 // Not using a visitor for custom types gives better codegen.
4268 if (arg
.format_custom(begin
, parse_context
, context
))
4269 return parse_context
.begin();
4270 auto specs
= detail::dynamic_format_specs
<Char
>();
4271 begin
= parse_format_specs(begin
, end
, specs
, parse_context
, arg
.type());
4272 detail::handle_dynamic_spec
<detail::width_checker
>(
4273 specs
.width
, specs
.width_ref
, context
);
4274 detail::handle_dynamic_spec
<detail::precision_checker
>(
4275 specs
.precision
, specs
.precision_ref
, context
);
4276 if (begin
== end
|| *begin
!= '}')
4277 report_error("missing '}' in format string");
4278 context
.advance_to(arg
.visit(
4279 arg_formatter
<Char
>{context
.out(), specs
, context
.locale()}));
4283 FMT_NORETURN
void on_error(const char* message
) { report_error(message
); }
4285 detail::parse_format_string
<false>(fmt
, format_handler(out
, fmt
, args
, loc
));
4290 #ifndef FMT_HEADER_ONLY
4291 extern template FMT_API
void vformat_to(buffer
<char>&, string_view
,
4292 typename vformat_args
<>::type
,
4294 extern template FMT_API
auto thousands_sep_impl
<char>(locale_ref
)
4295 -> thousands_sep_result
<char>;
4296 extern template FMT_API
auto thousands_sep_impl
<wchar_t>(locale_ref
)
4297 -> thousands_sep_result
<wchar_t>;
4298 extern template FMT_API
auto decimal_point_impl(locale_ref
) -> char;
4299 extern template FMT_API
auto decimal_point_impl(locale_ref
) -> wchar_t;
4300 #endif // FMT_HEADER_ONLY
4304 template <typename T
, typename Char
, type TYPE
>
4305 template <typename FormatContext
>
4306 FMT_CONSTEXPR FMT_INLINE
auto native_formatter
<T
, Char
, TYPE
>::format(
4307 const T
& val
, FormatContext
& ctx
) const -> decltype(ctx
.out()) {
4308 if (specs_
.width_ref
.kind
== arg_id_kind::none
&&
4309 specs_
.precision_ref
.kind
== arg_id_kind::none
) {
4310 return write
<Char
>(ctx
.out(), val
, specs_
, ctx
.locale());
4312 auto specs
= specs_
;
4313 handle_dynamic_spec
<width_checker
>(specs
.width
, specs
.width_ref
, ctx
);
4314 handle_dynamic_spec
<precision_checker
>(specs
.precision
, specs
.precision_ref
,
4316 return write
<Char
>(ctx
.out(), val
, specs
, ctx
.locale());
4319 } // namespace detail
4323 template <typename Char
>
4324 struct formatter
<detail::float128
, Char
>
4325 : detail::native_formatter
<detail::float128
, Char
,
4326 detail::type::float_type
> {};
4328 #if FMT_USE_USER_DEFINED_LITERALS
4329 inline namespace literals
{
4331 * User-defined literal equivalent of `fmt::arg`.
4335 * using namespace fmt::literals;
4336 * fmt::print("The answer is {answer}.", "answer"_a=42);
4338 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
4339 template <detail_exported::fixed_string Str
> constexpr auto operator""_a() {
4340 using char_t
= remove_cvref_t
<decltype(Str
.data
[0])>;
4341 return detail::udl_arg
<char_t
, sizeof(Str
.data
) / sizeof(char_t
), Str
>();
4344 constexpr auto operator""_a(const char* s
, size_t) -> detail::udl_arg
<char> {
4348 } // namespace literals
4349 #endif // FMT_USE_USER_DEFINED_LITERALS
4351 FMT_API
auto vformat(string_view fmt
, format_args args
) -> std::string
;
4354 * Formats `args` according to specifications in `fmt` and returns the result
4359 * #include <fmt/format.h>
4360 * std::string message = fmt::format("The answer is {}.", 42);
4362 template <typename
... T
>
4363 FMT_NODISCARD FMT_INLINE
auto format(format_string
<T
...> fmt
, T
&&... args
)
4365 return vformat(fmt
, fmt::make_format_args(args
...));
4368 template <typename Locale
, FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4369 inline auto vformat(const Locale
& loc
, string_view fmt
, format_args args
)
4371 return detail::vformat(loc
, fmt
, args
);
4374 template <typename Locale
, typename
... T
,
4375 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4376 inline auto format(const Locale
& loc
, format_string
<T
...> fmt
, T
&&... args
)
4378 return fmt::vformat(loc
, string_view(fmt
), fmt::make_format_args(args
...));
4381 template <typename OutputIt
, typename Locale
,
4382 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
&&
4383 detail::is_locale
<Locale
>::value
)>
4384 auto vformat_to(OutputIt out
, const Locale
& loc
, string_view fmt
,
4385 format_args args
) -> OutputIt
{
4386 using detail::get_buffer
;
4387 auto&& buf
= get_buffer
<char>(out
);
4388 detail::vformat_to(buf
, fmt
, args
, detail::locale_ref(loc
));
4389 return detail::get_iterator(buf
, out
);
4392 template <typename OutputIt
, typename Locale
, typename
... T
,
4393 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
&&
4394 detail::is_locale
<Locale
>::value
)>
4395 FMT_INLINE
auto format_to(OutputIt out
, const Locale
& loc
,
4396 format_string
<T
...> fmt
, T
&&... args
) -> OutputIt
{
4397 return vformat_to(out
, loc
, fmt
, fmt::make_format_args(args
...));
4400 template <typename Locale
, typename
... T
,
4401 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4402 FMT_NODISCARD FMT_INLINE
auto formatted_size(const Locale
& loc
,
4403 format_string
<T
...> fmt
,
4404 T
&&... args
) -> size_t {
4405 auto buf
= detail::counting_buffer
<>();
4406 detail::vformat_to
<char>(buf
, fmt
, fmt::make_format_args(args
...),
4407 detail::locale_ref(loc
));
4415 #ifdef FMT_HEADER_ONLY
4416 # define FMT_FUNC inline
4417 # include "format-inl.h"
4422 // Restore _LIBCPP_REMOVE_TRANSITIVE_INCLUDES.
4423 #ifdef FMT_REMOVE_TRANSITIVE_INCLUDES
4424 # undef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES
4427 #endif // FMT_FORMAT_H_