2 Formatting library for C++
4 Copyright (c) 2012 - present, Victor Zverovich
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 --- Optional exception to the license ---
27 As an exception, if, as a result of your compiling your source code, portions
28 of this Software are embedded into a machine-executable object form of such
29 source code, you may redistribute such embedded portions in such object form
30 without including the above copyright and permission notices.
36 #include <cmath> // std::signbit
37 #include <cstdint> // uint32_t
38 #include <cstring> // std::memcpy
39 #include <initializer_list> // std::initializer_list
40 #include <limits> // std::numeric_limits
41 #include <memory> // std::uninitialized_copy
42 #include <stdexcept> // std::runtime_error
43 #include <system_error> // std::system_error
45 #ifdef __cpp_lib_bit_cast
46 # include <bit> // std::bitcast
51 #if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
52 # define FMT_INLINE_VARIABLE inline
54 # define FMT_INLINE_VARIABLE
57 #if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
58 # define FMT_FALLTHROUGH [[fallthrough]]
59 #elif defined(__clang__)
60 # define FMT_FALLTHROUGH [[clang::fallthrough]]
61 #elif FMT_GCC_VERSION >= 700 && \
62 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
63 # define FMT_FALLTHROUGH [[gnu::fallthrough]]
65 # define FMT_FALLTHROUGH
68 #ifndef FMT_DEPRECATED
69 # if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900
70 # define FMT_DEPRECATED [[deprecated]]
72 # if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
73 # define FMT_DEPRECATED __attribute__((deprecated))
74 # elif FMT_MSC_VERSION
75 # define FMT_DEPRECATED __declspec(deprecated)
77 # define FMT_DEPRECATED /* deprecated */
82 #ifndef FMT_NO_UNIQUE_ADDRESS
83 # if FMT_CPLUSPLUS >= 202002L
84 # if FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
85 # define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
86 // VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485)
87 # elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION
88 # define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
92 #ifndef FMT_NO_UNIQUE_ADDRESS
93 # define FMT_NO_UNIQUE_ADDRESS
96 #if FMT_GCC_VERSION || defined(__clang__)
97 # define FMT_VISIBILITY(value) __attribute__((visibility(value)))
99 # define FMT_VISIBILITY(value)
103 # define FMT_HAS_BUILTIN(x) __has_builtin(x)
105 # define FMT_HAS_BUILTIN(x) 0
108 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
109 # define FMT_NOINLINE __attribute__((noinline))
111 # define FMT_NOINLINE
116 # if FMT_MSC_VERSION || defined(__NVCC__)
119 template <typename Exception
> inline void do_throw(const Exception
& x
) {
120 // Silence unreachable code warnings in MSVC and NVCC because these
121 // are nearly impossible to fix in a generic code.
122 volatile bool b
= true;
125 } // namespace detail
127 # define FMT_THROW(x) detail::do_throw(x)
129 # define FMT_THROW(x) throw x
132 # define FMT_THROW(x) \
133 ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
139 # define FMT_CATCH(x) catch (x)
141 # define FMT_TRY if (true)
142 # define FMT_CATCH(x) if (false)
145 #ifndef FMT_MAYBE_UNUSED
146 # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
147 # define FMT_MAYBE_UNUSED [[maybe_unused]]
149 # define FMT_MAYBE_UNUSED
153 #ifndef FMT_USE_USER_DEFINED_LITERALS
154 // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
155 # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
156 FMT_MSC_VERSION >= 1900) && \
157 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
158 # define FMT_USE_USER_DEFINED_LITERALS 1
160 # define FMT_USE_USER_DEFINED_LITERALS 0
164 // Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
165 // integer formatter template instantiations to just one by only using the
166 // largest integer type. This results in a reduction in binary size but will
167 // cause a decrease in integer formatting performance.
168 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
169 # define FMT_REDUCE_INT_INSTANTIATIONS 0
172 // __builtin_clz is broken in clang with Microsoft CodeGen:
173 // https://github.com/fmtlib/fmt/issues/519.
175 # if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
176 # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
178 # if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
179 # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
183 // __builtin_ctz is broken in Intel Compiler Classic on Windows:
184 // https://github.com/fmtlib/fmt/issues/2510.
186 # if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
187 defined(__NVCOMPILER)
188 # define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
190 # if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
191 FMT_ICC_VERSION || defined(__NVCOMPILER)
192 # define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
197 # include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
200 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
201 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
202 // MSVC intrinsics if the clz and clzll builtins are not available.
203 #if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
204 !defined(FMT_BUILTIN_CTZLL)
207 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
208 # if !defined(__clang__)
209 # pragma intrinsic(_BitScanForward)
210 # pragma intrinsic(_BitScanReverse)
212 # pragma intrinsic(_BitScanForward64)
213 # pragma intrinsic(_BitScanReverse64)
217 inline auto clz(uint32_t x
) -> int {
219 _BitScanReverse(&r
, x
);
220 FMT_ASSERT(x
!= 0, "");
221 // Static analysis complains about using uninitialized data
222 // "r", but the only way that can happen is if "x" is 0,
223 // which the callers guarantee to not happen.
224 FMT_MSC_WARNING(suppress
: 6102)
225 return 31 ^ static_cast<int>(r
);
227 # define FMT_BUILTIN_CLZ(n) detail::clz(n)
229 inline auto clzll(uint64_t x
) -> int {
232 _BitScanReverse64(&r
, x
);
234 // Scan the high 32 bits.
235 if (_BitScanReverse(&r
, static_cast<uint32_t>(x
>> 32)))
236 return 63 ^ static_cast<int>(r
+ 32);
237 // Scan the low 32 bits.
238 _BitScanReverse(&r
, static_cast<uint32_t>(x
));
240 FMT_ASSERT(x
!= 0, "");
241 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
242 return 63 ^ static_cast<int>(r
);
244 # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
246 inline auto ctz(uint32_t x
) -> int {
248 _BitScanForward(&r
, x
);
249 FMT_ASSERT(x
!= 0, "");
250 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
251 return static_cast<int>(r
);
253 # define FMT_BUILTIN_CTZ(n) detail::ctz(n)
255 inline auto ctzll(uint64_t x
) -> int {
257 FMT_ASSERT(x
!= 0, "");
258 FMT_MSC_WARNING(suppress
: 6102) // Suppress a bogus static analysis warning.
260 _BitScanForward64(&r
, x
);
262 // Scan the low 32 bits.
263 if (_BitScanForward(&r
, static_cast<uint32_t>(x
))) return static_cast<int>(r
);
264 // Scan the high 32 bits.
265 _BitScanForward(&r
, static_cast<uint32_t>(x
>> 32));
268 return static_cast<int>(r
);
270 # define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
271 } // namespace detail
277 template <typename
...> struct disjunction
: std::false_type
{};
278 template <typename P
> struct disjunction
<P
> : P
{};
279 template <typename P1
, typename
... Pn
>
280 struct disjunction
<P1
, Pn
...>
281 : conditional_t
<bool(P1::value
), P1
, disjunction
<Pn
...>> {};
283 template <typename
...> struct conjunction
: std::true_type
{};
284 template <typename P
> struct conjunction
<P
> : P
{};
285 template <typename P1
, typename
... Pn
>
286 struct conjunction
<P1
, Pn
...>
287 : conditional_t
<bool(P1::value
), conjunction
<Pn
...>, P1
> {};
291 FMT_CONSTEXPR
inline void abort_fuzzing_if(bool condition
) {
292 ignore_unused(condition
);
294 if (condition
) throw std::runtime_error("fuzzing limit reached");
298 template <typename CharT
, CharT
... C
> struct string_literal
{
299 static constexpr CharT value
[sizeof...(C
)] = {C
...};
300 constexpr operator basic_string_view
<CharT
>() const {
301 return {value
, sizeof...(C
)};
305 #if FMT_CPLUSPLUS < 201703L
306 template <typename CharT
, CharT
... C
>
307 constexpr CharT string_literal
<CharT
, C
...>::value
[sizeof...(C
)];
310 template <typename Streambuf
> class formatbuf
: public Streambuf
{
312 using char_type
= typename
Streambuf::char_type
;
313 using streamsize
= decltype(std::declval
<Streambuf
>().sputn(nullptr, 0));
314 using int_type
= typename
Streambuf::int_type
;
315 using traits_type
= typename
Streambuf::traits_type
;
317 buffer
<char_type
>& buffer_
;
320 explicit formatbuf(buffer
<char_type
>& buf
) : buffer_(buf
) {}
323 // The put area is always empty. This makes the implementation simpler and has
324 // the advantage that the streambuf and the buffer are always in sync and
325 // sputc never writes into uninitialized memory. A disadvantage is that each
326 // call to sputc always results in a (virtual) call to overflow. There is no
327 // disadvantage here for sputn since this always results in a call to xsputn.
329 auto overflow(int_type ch
) -> int_type override
{
330 if (!traits_type::eq_int_type(ch
, traits_type::eof()))
331 buffer_
.push_back(static_cast<char_type
>(ch
));
335 auto xsputn(const char_type
* s
, streamsize count
) -> streamsize override
{
336 buffer_
.append(s
, s
+ count
);
341 // Implementation of std::bit_cast for pre-C++20.
342 template <typename To
, typename From
, FMT_ENABLE_IF(sizeof(To
) == sizeof(From
))>
343 FMT_CONSTEXPR20
auto bit_cast(const From
& from
) -> To
{
344 #ifdef __cpp_lib_bit_cast
345 if (is_constant_evaluated()) return std::bit_cast
<To
>(from
);
348 // The cast suppresses a bogus -Wclass-memaccess on GCC.
349 std::memcpy(static_cast<void*>(&to
), &from
, sizeof(to
));
353 inline auto is_big_endian() -> bool {
356 #elif defined(__BIG_ENDIAN__)
358 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
359 return __BYTE_ORDER__
== __ORDER_BIG_ENDIAN__
;
362 char data
[sizeof(int)];
364 return bit_cast
<bytes
>(1).data
[0] == 0;
368 class uint128_fallback
{
373 constexpr uint128_fallback(uint64_t hi
, uint64_t lo
) : lo_(lo
), hi_(hi
) {}
374 constexpr uint128_fallback(uint64_t value
= 0) : lo_(value
), hi_(0) {}
376 constexpr uint64_t high() const noexcept
{ return hi_
; }
377 constexpr uint64_t low() const noexcept
{ return lo_
; }
379 template <typename T
, FMT_ENABLE_IF(std::is_integral
<T
>::value
)>
380 constexpr explicit operator T() const {
381 return static_cast<T
>(lo_
);
384 friend constexpr auto operator==(const uint128_fallback
& lhs
,
385 const uint128_fallback
& rhs
) -> bool {
386 return lhs
.hi_
== rhs
.hi_
&& lhs
.lo_
== rhs
.lo_
;
388 friend constexpr auto operator!=(const uint128_fallback
& lhs
,
389 const uint128_fallback
& rhs
) -> bool {
390 return !(lhs
== rhs
);
392 friend constexpr auto operator>(const uint128_fallback
& lhs
,
393 const uint128_fallback
& rhs
) -> bool {
394 return lhs
.hi_
!= rhs
.hi_
? lhs
.hi_
> rhs
.hi_
: lhs
.lo_
> rhs
.lo_
;
396 friend constexpr auto operator|(const uint128_fallback
& lhs
,
397 const uint128_fallback
& rhs
)
398 -> uint128_fallback
{
399 return {lhs
.hi_
| rhs
.hi_
, lhs
.lo_
| rhs
.lo_
};
401 friend constexpr auto operator&(const uint128_fallback
& lhs
,
402 const uint128_fallback
& rhs
)
403 -> uint128_fallback
{
404 return {lhs
.hi_
& rhs
.hi_
, lhs
.lo_
& rhs
.lo_
};
406 friend constexpr auto operator~(const uint128_fallback
& n
)
407 -> uint128_fallback
{
408 return {~n
.hi_
, ~n
.lo_
};
410 friend auto operator+(const uint128_fallback
& lhs
,
411 const uint128_fallback
& rhs
) -> uint128_fallback
{
412 auto result
= uint128_fallback(lhs
);
416 friend auto operator*(const uint128_fallback
& lhs
, uint32_t rhs
)
417 -> uint128_fallback
{
418 FMT_ASSERT(lhs
.hi_
== 0, "");
419 uint64_t hi
= (lhs
.lo_
>> 32) * rhs
;
420 uint64_t lo
= (lhs
.lo_
& ~uint32_t()) * rhs
;
421 uint64_t new_lo
= (hi
<< 32) + lo
;
422 return {(hi
>> 32) + (new_lo
< lo
? 1 : 0), new_lo
};
424 friend auto operator-(const uint128_fallback
& lhs
, uint64_t rhs
)
425 -> uint128_fallback
{
426 return {lhs
.hi_
- (lhs
.lo_
< rhs
? 1 : 0), lhs
.lo_
- rhs
};
428 FMT_CONSTEXPR
auto operator>>(int shift
) const -> uint128_fallback
{
429 if (shift
== 64) return {0, hi_
};
430 if (shift
> 64) return uint128_fallback(0, hi_
) >> (shift
- 64);
431 return {hi_
>> shift
, (hi_
<< (64 - shift
)) | (lo_
>> shift
)};
433 FMT_CONSTEXPR
auto operator<<(int shift
) const -> uint128_fallback
{
434 if (shift
== 64) return {lo_
, 0};
435 if (shift
> 64) return uint128_fallback(lo_
, 0) << (shift
- 64);
436 return {hi_
<< shift
| (lo_
>> (64 - shift
)), (lo_
<< shift
)};
438 FMT_CONSTEXPR
auto operator>>=(int shift
) -> uint128_fallback
& {
439 return *this = *this >> shift
;
441 FMT_CONSTEXPR
void operator+=(uint128_fallback n
) {
442 uint64_t new_lo
= lo_
+ n
.lo_
;
443 uint64_t new_hi
= hi_
+ n
.hi_
+ (new_lo
< lo_
? 1 : 0);
444 FMT_ASSERT(new_hi
>= hi_
, "");
448 FMT_CONSTEXPR
void operator&=(uint128_fallback n
) {
453 FMT_CONSTEXPR20 uint128_fallback
& operator+=(uint64_t n
) noexcept
{
454 if (is_constant_evaluated()) {
456 hi_
+= (lo_
< n
? 1 : 0);
459 #if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
460 unsigned long long carry
;
461 lo_
= __builtin_addcll(lo_
, n
, 0, &carry
);
463 #elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
464 unsigned long long result
;
465 auto carry
= __builtin_ia32_addcarryx_u64(0, lo_
, n
, &result
);
468 #elif defined(_MSC_VER) && defined(_M_X64)
469 auto carry
= _addcarry_u64(0, lo_
, n
, &lo_
);
470 _addcarry_u64(carry
, hi_
, 0, &hi_
);
473 hi_
+= (lo_
< n
? 1 : 0);
479 using uint128_t
= conditional_t
<FMT_USE_INT128
, uint128_opt
, uint128_fallback
>;
482 using uintptr_t = ::uintptr_t;
484 using uintptr_t = uint128_t
;
487 // Returns the largest possible value for type T. Same as
488 // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
489 template <typename T
> constexpr auto max_value() -> T
{
490 return (std::numeric_limits
<T
>::max
)();
492 template <typename T
> constexpr auto num_bits() -> int {
493 return std::numeric_limits
<T
>::digits
;
495 // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
496 template <> constexpr auto num_bits
<int128_opt
>() -> int { return 128; }
497 template <> constexpr auto num_bits
<uint128_t
>() -> int { return 128; }
499 // A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
500 // and 128-bit pointers to uint128_fallback.
501 template <typename To
, typename From
, FMT_ENABLE_IF(sizeof(To
) > sizeof(From
))>
502 inline auto bit_cast(const From
& from
) -> To
{
503 constexpr auto size
= static_cast<int>(sizeof(From
) / sizeof(unsigned));
505 unsigned value
[static_cast<unsigned>(size
)];
506 } data
= bit_cast
<data_t
>(from
);
508 if (const_check(is_big_endian())) {
509 for (int i
= 0; i
< size
; ++i
)
510 result
= (result
<< num_bits
<unsigned>()) | data
.value
[i
];
512 for (int i
= size
- 1; i
>= 0; --i
)
513 result
= (result
<< num_bits
<unsigned>()) | data
.value
[i
];
518 template <typename UInt
>
519 FMT_CONSTEXPR20
inline auto countl_zero_fallback(UInt n
) -> int {
521 constexpr UInt msb_mask
= static_cast<UInt
>(1) << (num_bits
<UInt
>() - 1);
522 for (; (n
& msb_mask
) == 0; n
<<= 1) lz
++;
526 FMT_CONSTEXPR20
inline auto countl_zero(uint32_t n
) -> int {
527 #ifdef FMT_BUILTIN_CLZ
528 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n
);
530 return countl_zero_fallback(n
);
533 FMT_CONSTEXPR20
inline auto countl_zero(uint64_t n
) -> int {
534 #ifdef FMT_BUILTIN_CLZLL
535 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n
);
537 return countl_zero_fallback(n
);
540 FMT_INLINE
void assume(bool condition
) {
542 #if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
543 __builtin_assume(condition
);
544 #elif FMT_GCC_VERSION
545 if (!condition
) __builtin_unreachable();
549 // An approximation of iterator_t for pre-C++20 systems.
550 template <typename T
>
551 using iterator_t
= decltype(std::begin(std::declval
<T
&>()));
552 template <typename T
> using sentinel_t
= decltype(std::end(std::declval
<T
&>()));
554 // A workaround for std::string not having mutable data() until C++17.
555 template <typename Char
>
556 inline auto get_data(std::basic_string
<Char
>& s
) -> Char
* {
559 template <typename Container
>
560 inline auto get_data(Container
& c
) -> typename
Container::value_type
* {
564 // Attempts to reserve space for n extra characters in the output range.
565 // Returns a pointer to the reserved range or a reference to it.
566 template <typename Container
, FMT_ENABLE_IF(is_contiguous
<Container
>::value
)>
567 #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
568 __attribute__((no_sanitize("undefined")))
571 reserve(std::back_insert_iterator
<Container
> it
, size_t n
) ->
572 typename
Container::value_type
* {
573 Container
& c
= get_container(it
);
574 size_t size
= c
.size();
576 return get_data(c
) + size
;
579 template <typename T
>
580 inline auto reserve(buffer_appender
<T
> it
, size_t n
) -> buffer_appender
<T
> {
581 buffer
<T
>& buf
= get_container(it
);
582 buf
.try_reserve(buf
.size() + n
);
586 template <typename Iterator
>
587 constexpr auto reserve(Iterator
& it
, size_t) -> Iterator
& {
591 template <typename OutputIt
>
592 using reserve_iterator
=
593 remove_reference_t
<decltype(reserve(std::declval
<OutputIt
&>(), 0))>;
595 template <typename T
, typename OutputIt
>
596 constexpr auto to_pointer(OutputIt
, size_t) -> T
* {
599 template <typename T
> auto to_pointer(buffer_appender
<T
> it
, size_t n
) -> T
* {
600 buffer
<T
>& buf
= get_container(it
);
601 auto size
= buf
.size();
602 if (buf
.capacity() < size
+ n
) return nullptr;
603 buf
.try_resize(size
+ n
);
604 return buf
.data() + size
;
607 template <typename Container
, FMT_ENABLE_IF(is_contiguous
<Container
>::value
)>
608 inline auto base_iterator(std::back_insert_iterator
<Container
> it
,
609 typename
Container::value_type
*)
610 -> std::back_insert_iterator
<Container
> {
614 template <typename Iterator
>
615 constexpr auto base_iterator(Iterator
, Iterator it
) -> Iterator
{
619 // <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
621 template <typename OutputIt
, typename Size
, typename T
>
622 FMT_CONSTEXPR
auto fill_n(OutputIt out
, Size count
, const T
& value
)
624 for (Size i
= 0; i
< count
; ++i
) *out
++ = value
;
627 template <typename T
, typename Size
>
628 FMT_CONSTEXPR20
auto fill_n(T
* out
, Size count
, char value
) -> T
* {
629 if (is_constant_evaluated()) {
630 return fill_n
<T
*, Size
, T
>(out
, count
, value
);
632 std::memset(out
, value
, to_unsigned(count
));
637 using char8_type
= char8_t
;
639 enum char8_type
: unsigned char {};
642 template <typename OutChar
, typename InputIt
, typename OutputIt
>
643 FMT_CONSTEXPR FMT_NOINLINE
auto copy_str_noinline(InputIt begin
, InputIt end
,
644 OutputIt out
) -> OutputIt
{
645 return copy_str
<OutChar
>(begin
, end
, out
);
648 // A public domain branchless UTF-8 decoder by Christopher Wellons:
649 // https://github.com/skeeto/branchless-utf8
650 /* Decode the next character, c, from s, reporting errors in e.
652 * Since this is a branchless decoder, four bytes will be read from the
653 * buffer regardless of the actual length of the next character. This
654 * means the buffer _must_ have at least three bytes of zero padding
655 * following the end of the data stream.
657 * Errors are reported in e, which will be non-zero if the parsed
658 * character was somehow invalid: invalid byte sequence, non-canonical
659 * encoding, or a surrogate half.
661 * The function returns a pointer to the next character. When an error
662 * occurs, this pointer will be a guess that depends on the particular
663 * error, but it will always advance at least one byte.
665 FMT_CONSTEXPR
inline auto utf8_decode(const char* s
, uint32_t* c
, int* e
)
667 constexpr const int masks
[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
668 constexpr const uint32_t mins
[] = {4194304, 0, 128, 2048, 65536};
669 constexpr const int shiftc
[] = {0, 18, 12, 6, 0};
670 constexpr const int shifte
[] = {0, 6, 4, 2, 0};
672 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"
673 [static_cast<unsigned char>(*s
) >> 3];
674 // Compute the pointer to the next character early so that the next
675 // iteration can start working on the next character. Neither Clang
676 // nor GCC figure out this reordering on their own.
677 const char* next
= s
+ len
+ !len
;
679 using uchar
= unsigned char;
681 // Assume a four-byte character and load four bytes. Unused bits are
683 *c
= uint32_t(uchar(s
[0]) & masks
[len
]) << 18;
684 *c
|= uint32_t(uchar(s
[1]) & 0x3f) << 12;
685 *c
|= uint32_t(uchar(s
[2]) & 0x3f) << 6;
686 *c
|= uint32_t(uchar(s
[3]) & 0x3f) << 0;
689 // Accumulate the various error conditions.
690 *e
= (*c
< mins
[len
]) << 6; // non-canonical encoding
691 *e
|= ((*c
>> 11) == 0x1b) << 7; // surrogate half?
692 *e
|= (*c
> 0x10FFFF) << 8; // out of range?
693 *e
|= (uchar(s
[1]) & 0xc0) >> 2;
694 *e
|= (uchar(s
[2]) & 0xc0) >> 4;
695 *e
|= uchar(s
[3]) >> 6;
696 *e
^= 0x2a; // top two bits of each tail byte correct?
702 constexpr FMT_INLINE_VARIABLE
uint32_t invalid_code_point
= ~uint32_t();
704 // Invokes f(cp, sv) for every code point cp in s with sv being the string view
705 // corresponding to the code point. cp is invalid_code_point on error.
706 template <typename F
>
707 FMT_CONSTEXPR
void for_each_codepoint(string_view s
, F f
) {
708 auto decode
= [f
](const char* buf_ptr
, const char* ptr
) {
709 auto cp
= uint32_t();
711 auto end
= utf8_decode(buf_ptr
, &cp
, &error
);
712 bool result
= f(error
? invalid_code_point
: cp
,
713 string_view(ptr
, error
? 1 : to_unsigned(end
- buf_ptr
)));
714 return result
? (error
? buf_ptr
+ 1 : end
) : nullptr;
717 const size_t block_size
= 4; // utf8_decode always reads blocks of 4 chars.
718 if (s
.size() >= block_size
) {
719 for (auto end
= p
+ s
.size() - block_size
+ 1; p
< end
;) {
724 if (auto num_chars_left
= s
.data() + s
.size() - p
) {
725 char buf
[2 * block_size
- 1] = {};
726 copy_str
<char>(p
, p
+ num_chars_left
, buf
);
727 const char* buf_ptr
= buf
;
729 auto end
= decode(buf_ptr
, p
);
733 } while (buf_ptr
- buf
< num_chars_left
);
737 template <typename Char
>
738 inline auto compute_width(basic_string_view
<Char
> s
) -> size_t {
742 // Computes approximate display width of a UTF-8 string.
743 FMT_CONSTEXPR
inline size_t compute_width(string_view s
) {
744 size_t num_code_points
= 0;
745 // It is not a lambda for compatibility with C++14.
746 struct count_code_points
{
748 FMT_CONSTEXPR
auto operator()(uint32_t cp
, string_view
) const -> bool {
749 *count
+= detail::to_unsigned(
752 (cp
<= 0x115f || // Hangul Jamo init. consonants
753 cp
== 0x2329 || // LEFT-POINTING ANGLE BRACKET
754 cp
== 0x232a || // RIGHT-POINTING ANGLE BRACKET
755 // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
756 (cp
>= 0x2e80 && cp
<= 0xa4cf && cp
!= 0x303f) ||
757 (cp
>= 0xac00 && cp
<= 0xd7a3) || // Hangul Syllables
758 (cp
>= 0xf900 && cp
<= 0xfaff) || // CJK Compatibility Ideographs
759 (cp
>= 0xfe10 && cp
<= 0xfe19) || // Vertical Forms
760 (cp
>= 0xfe30 && cp
<= 0xfe6f) || // CJK Compatibility Forms
761 (cp
>= 0xff00 && cp
<= 0xff60) || // Fullwidth Forms
762 (cp
>= 0xffe0 && cp
<= 0xffe6) || // Fullwidth Forms
763 (cp
>= 0x20000 && cp
<= 0x2fffd) || // CJK
764 (cp
>= 0x30000 && cp
<= 0x3fffd) ||
765 // Miscellaneous Symbols and Pictographs + Emoticons:
766 (cp
>= 0x1f300 && cp
<= 0x1f64f) ||
767 // Supplemental Symbols and Pictographs:
768 (cp
>= 0x1f900 && cp
<= 0x1f9ff))));
772 // We could avoid branches by using utf8_decode directly.
773 for_each_codepoint(s
, count_code_points
{&num_code_points
});
774 return num_code_points
;
777 inline auto compute_width(basic_string_view
<char8_type
> s
) -> size_t {
778 return compute_width(
779 string_view(reinterpret_cast<const char*>(s
.data()), s
.size()));
782 template <typename Char
>
783 inline auto code_point_index(basic_string_view
<Char
> s
, size_t n
) -> size_t {
784 size_t size
= s
.size();
785 return n
< size
? n
: size
;
788 // Calculates the index of the nth code point in a UTF-8 string.
789 inline auto code_point_index(string_view s
, size_t n
) -> size_t {
790 const char* data
= s
.data();
791 size_t num_code_points
= 0;
792 for (size_t i
= 0, size
= s
.size(); i
!= size
; ++i
) {
793 if ((data
[i
] & 0xc0) != 0x80 && ++num_code_points
> n
) return i
;
798 inline auto code_point_index(basic_string_view
<char8_type
> s
, size_t n
)
800 return code_point_index(
801 string_view(reinterpret_cast<const char*>(s
.data()), s
.size()), n
);
804 template <typename T
> struct is_integral
: std::is_integral
<T
> {};
805 template <> struct is_integral
<int128_opt
> : std::true_type
{};
806 template <> struct is_integral
<uint128_t
> : std::true_type
{};
808 template <typename T
>
810 std::integral_constant
<bool, std::numeric_limits
<T
>::is_signed
||
811 std::is_same
<T
, int128_opt
>::value
>;
813 template <typename T
>
815 bool_constant
<is_integral
<T
>::value
&& !std::is_same
<T
, bool>::value
&&
816 !std::is_same
<T
, char>::value
&&
817 !std::is_same
<T
, wchar_t>::value
>;
819 #ifndef FMT_USE_FLOAT
820 # define FMT_USE_FLOAT 1
822 #ifndef FMT_USE_DOUBLE
823 # define FMT_USE_DOUBLE 1
825 #ifndef FMT_USE_LONG_DOUBLE
826 # define FMT_USE_LONG_DOUBLE 1
829 #ifndef FMT_USE_FLOAT128
831 // Clang emulates GCC, so it has to appear early.
832 # if FMT_HAS_INCLUDE(<quadmath.h>)
833 # define FMT_USE_FLOAT128 1
835 # elif defined(__GNUC__)
837 # if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
838 # define FMT_USE_FLOAT128 1
841 # ifndef FMT_USE_FLOAT128
842 # define FMT_USE_FLOAT128 0
847 using float128
= __float128
;
849 using float128
= void;
851 template <typename T
> using is_float128
= std::is_same
<T
, float128
>;
853 template <typename T
>
854 using is_floating_point
=
855 bool_constant
<std::is_floating_point
<T
>::value
|| is_float128
<T
>::value
>;
857 template <typename T
, bool = std::is_floating_point
<T
>::value
>
858 struct is_fast_float
: bool_constant
<std::numeric_limits
<T
>::is_iec559
&&
859 sizeof(T
) <= sizeof(double)> {};
860 template <typename T
> struct is_fast_float
<T
, false> : std::false_type
{};
862 template <typename T
>
863 using is_double_double
= bool_constant
<std::numeric_limits
<T
>::digits
== 106>;
865 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
866 # define FMT_USE_FULL_CACHE_DRAGONBOX 0
869 template <typename T
>
870 template <typename U
>
871 void buffer
<T
>::append(const U
* begin
, const U
* end
) {
872 while (begin
!= end
) {
873 auto count
= to_unsigned(end
- begin
);
874 try_reserve(size_
+ count
);
875 auto free_cap
= capacity_
- size_
;
876 if (free_cap
< count
) count
= free_cap
;
877 std::uninitialized_copy_n(begin
, count
, ptr_
+ size_
);
883 template <typename T
, typename Enable
= void>
884 struct is_locale
: std::false_type
{};
885 template <typename T
>
886 struct is_locale
<T
, void_t
<decltype(T::classic())>> : std::true_type
{};
887 } // namespace detail
891 // The number of characters to store in the basic_memory_buffer object itself
892 // to avoid dynamic memory allocation.
893 enum { inline_buffer_size
= 500 };
897 A dynamically growing memory buffer for trivially copyable/constructible types
898 with the first ``SIZE`` elements stored in the object itself.
900 You can use the ``memory_buffer`` type alias for ``char`` instead.
904 auto out = fmt::memory_buffer();
905 format_to(std::back_inserter(out), "The answer is {}.", 42);
907 This will append the following output to the ``out`` object:
913 The output can be converted to an ``std::string`` with ``to_string(out)``.
916 template <typename T
, size_t SIZE
= inline_buffer_size
,
917 typename Allocator
= std::allocator
<T
>>
918 class basic_memory_buffer final
: public detail::buffer
<T
> {
922 // Don't inherit from Allocator to avoid generating type_info for it.
923 FMT_NO_UNIQUE_ADDRESS Allocator alloc_
;
925 // Deallocate memory allocated by the buffer.
926 FMT_CONSTEXPR20
void deallocate() {
927 T
* data
= this->data();
928 if (data
!= store_
) alloc_
.deallocate(data
, this->capacity());
932 FMT_CONSTEXPR20
void grow(size_t size
) override
{
933 detail::abort_fuzzing_if(size
> 5000);
934 const size_t max_size
= std::allocator_traits
<Allocator
>::max_size(alloc_
);
935 size_t old_capacity
= this->capacity();
936 size_t new_capacity
= old_capacity
+ old_capacity
/ 2;
937 if (size
> new_capacity
)
939 else if (new_capacity
> max_size
)
940 new_capacity
= size
> max_size
? size
: max_size
;
941 T
* old_data
= this->data();
943 std::allocator_traits
<Allocator
>::allocate(alloc_
, new_capacity
);
944 // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
945 detail::assume(this->size() <= new_capacity
);
946 // The following code doesn't throw, so the raw pointer above doesn't leak.
947 std::uninitialized_copy_n(old_data
, this->size(), new_data
);
948 this->set(new_data
, new_capacity
);
949 // deallocate must not throw according to the standard, but even if it does,
950 // the buffer already uses the new storage and will deallocate it in
952 if (old_data
!= store_
) alloc_
.deallocate(old_data
, old_capacity
);
956 using value_type
= T
;
957 using const_reference
= const T
&;
959 FMT_CONSTEXPR20
explicit basic_memory_buffer(
960 const Allocator
& alloc
= Allocator())
962 this->set(store_
, SIZE
);
963 if (detail::is_constant_evaluated()) detail::fill_n(store_
, SIZE
, T());
965 FMT_CONSTEXPR20
~basic_memory_buffer() { deallocate(); }
968 // Move data from other to this buffer.
969 FMT_CONSTEXPR20
void move(basic_memory_buffer
& other
) {
970 alloc_
= std::move(other
.alloc_
);
971 T
* data
= other
.data();
972 size_t size
= other
.size(), capacity
= other
.capacity();
973 if (data
== other
.store_
) {
974 this->set(store_
, capacity
);
975 detail::copy_str
<T
>(other
.store_
, other
.store_
+ size
, store_
);
977 this->set(data
, capacity
);
978 // Set pointer to the inline array so that delete is not called
979 // when deallocating.
980 other
.set(other
.store_
, 0);
989 Constructs a :class:`fmt::basic_memory_buffer` object moving the content
990 of the other object to it.
993 FMT_CONSTEXPR20
basic_memory_buffer(basic_memory_buffer
&& other
) noexcept
{
999 Moves the content of the other ``basic_memory_buffer`` object to this one.
1002 auto operator=(basic_memory_buffer
&& other
) noexcept
-> basic_memory_buffer
& {
1003 FMT_ASSERT(this != &other
, "");
1009 // Returns a copy of the allocator associated with this buffer.
1010 auto get_allocator() const -> Allocator
{ return alloc_
; }
1013 Resizes the buffer to contain *count* elements. If T is a POD type new
1014 elements may not be initialized.
1016 FMT_CONSTEXPR20
void resize(size_t count
) { this->try_resize(count
); }
1018 /** Increases the buffer capacity to *new_capacity*. */
1019 void reserve(size_t new_capacity
) { this->try_reserve(new_capacity
); }
1021 // Directly append data into the buffer
1022 using detail::buffer
<T
>::append
;
1023 template <typename ContiguousRange
>
1024 void append(const ContiguousRange
& range
) {
1025 append(range
.data(), range
.data() + range
.size());
1029 using memory_buffer
= basic_memory_buffer
<char>;
1031 template <typename T
, size_t SIZE
, typename Allocator
>
1032 struct is_contiguous
<basic_memory_buffer
<T
, SIZE
, Allocator
>> : std::true_type
{
1037 FMT_API
bool write_console(std::FILE* f
, string_view text
);
1038 FMT_API
void print(std::FILE*, string_view
);
1039 } // namespace detail
1043 // Suppress a misleading warning in older versions of clang.
1044 #if FMT_CLANG_VERSION
1045 # pragma clang diagnostic ignored "-Wweak-vtables"
1048 /** An error reported from a formatting function. */
1049 class FMT_VISIBILITY("default") format_error
: public std::runtime_error
{
1051 using std::runtime_error::runtime_error
;
1054 namespace detail_exported
{
1055 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
1056 template <typename Char
, size_t N
> struct fixed_string
{
1057 constexpr fixed_string(const Char (&str
)[N
]) {
1058 detail::copy_str
<Char
, const Char
*, Char
*>(static_cast<const Char
*>(str
),
1065 // Converts a compile-time string to basic_string_view.
1066 template <typename Char
, size_t N
>
1067 constexpr auto compile_string_to_view(const Char (&s
)[N
])
1068 -> basic_string_view
<Char
> {
1069 // Remove trailing NUL character if needed. Won't be present if this is used
1070 // with a raw character array (i.e. not defined as a string).
1071 return {s
, N
- (std::char_traits
<Char
>::to_int_type(s
[N
- 1]) == 0 ? 1 : 0)};
1073 template <typename Char
>
1074 constexpr auto compile_string_to_view(detail::std_string_view
<Char
> s
)
1075 -> basic_string_view
<Char
> {
1076 return {s
.data(), s
.size()};
1078 } // namespace detail_exported
1082 basic_format_arg
<format_context
> value_
;
1085 template <typename T
, FMT_ENABLE_IF(!detail::is_float128
<T
>::value
)>
1086 loc_value(T value
) : value_(detail::make_arg
<format_context
>(value
)) {}
1088 template <typename T
, FMT_ENABLE_IF(detail::is_float128
<T
>::value
)>
1091 template <typename Visitor
> auto visit(Visitor
&& vis
) -> decltype(vis(0)) {
1092 return visit_format_arg(vis
, value_
);
1096 // A locale facet that formats values in UTF-8.
1097 // It is parameterized on the locale to avoid the heavy <locale> include.
1098 template <typename Locale
> class format_facet
: public Locale::facet
{
1100 std::string separator_
;
1101 std::string grouping_
;
1102 std::string decimal_point_
;
1105 virtual auto do_put(appender out
, loc_value val
,
1106 const format_specs
<>& specs
) const -> bool;
1109 static FMT_API typename
Locale::id id
;
1111 explicit format_facet(Locale
& loc
);
1112 explicit format_facet(string_view sep
= "",
1113 std::initializer_list
<unsigned char> g
= {3},
1114 std::string decimal_point
= ".")
1115 : separator_(sep
.data(), sep
.size()),
1116 grouping_(g
.begin(), g
.end()),
1117 decimal_point_(decimal_point
) {}
1119 auto put(appender out
, loc_value val
, const format_specs
<>& specs
) const
1121 return do_put(out
, val
, specs
);
1127 // Returns true if value is negative, false otherwise.
1128 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
1129 template <typename T
, FMT_ENABLE_IF(is_signed
<T
>::value
)>
1130 constexpr auto is_negative(T value
) -> bool {
1133 template <typename T
, FMT_ENABLE_IF(!is_signed
<T
>::value
)>
1134 constexpr auto is_negative(T
) -> bool {
1138 template <typename T
>
1139 FMT_CONSTEXPR
auto is_supported_floating_point(T
) -> bool {
1140 if (std::is_same
<T
, float>()) return FMT_USE_FLOAT
;
1141 if (std::is_same
<T
, double>()) return FMT_USE_DOUBLE
;
1142 if (std::is_same
<T
, long double>()) return FMT_USE_LONG_DOUBLE
;
1146 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
1147 // represent all values of an integral type T.
1148 template <typename T
>
1149 using uint32_or_64_or_128_t
=
1150 conditional_t
<num_bits
<T
>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS
,
1152 conditional_t
<num_bits
<T
>() <= 64, uint64_t, uint128_t
>>;
1153 template <typename T
>
1154 using uint64_or_128_t
= conditional_t
<num_bits
<T
>() <= 64, uint64_t, uint128_t
>;
1156 #define FMT_POWERS_OF_10(factor) \
1157 factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
1158 (factor)*1000000, (factor)*10000000, (factor)*100000000, \
1161 // Converts value in the range [0, 100) to a string.
1162 constexpr const char* digits2(size_t value
) {
1163 // GCC generates slightly better code when value is pointer-size.
1164 return &"0001020304050607080910111213141516171819"
1165 "2021222324252627282930313233343536373839"
1166 "4041424344454647484950515253545556575859"
1167 "6061626364656667686970717273747576777879"
1168 "8081828384858687888990919293949596979899"[value
* 2];
1171 // Sign is a template parameter to workaround a bug in gcc 4.8.
1172 template <typename Char
, typename Sign
> constexpr Char
sign(Sign s
) {
1173 #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1174 static_assert(std::is_same
<Sign
, sign_t
>::value
, "");
1176 return static_cast<Char
>("\0-+ "[s
]);
1179 template <typename T
> FMT_CONSTEXPR
auto count_digits_fallback(T n
) -> int {
1182 // Integer division is slow so do it for a group of four digits instead
1183 // of for every digit. The idea comes from the talk by Alexandrescu
1184 // "Three Optimization Tips for C++". See speed-test for a comparison.
1185 if (n
< 10) return count
;
1186 if (n
< 100) return count
+ 1;
1187 if (n
< 1000) return count
+ 2;
1188 if (n
< 10000) return count
+ 3;
1194 FMT_CONSTEXPR
inline auto count_digits(uint128_opt n
) -> int {
1195 return count_digits_fallback(n
);
1199 #ifdef FMT_BUILTIN_CLZLL
1200 // It is a separate function rather than a part of count_digits to workaround
1201 // the lack of static constexpr in constexpr functions.
1202 inline auto do_count_digits(uint64_t n
) -> int {
1203 // This has comparable performance to the version by Kendall Willets
1204 // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
1205 // but uses smaller tables.
1206 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
1207 static constexpr uint8_t bsr2log10
[] = {
1208 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1209 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1210 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1211 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1212 auto t
= bsr2log10
[FMT_BUILTIN_CLZLL(n
| 1) ^ 63];
1213 static constexpr const uint64_t zero_or_powers_of_10
[] = {
1214 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1215 10000000000000000000ULL};
1216 return t
- (n
< zero_or_powers_of_10
[t
]);
1220 // Returns the number of decimal digits in n. Leading zeros are not counted
1221 // except for n == 0 in which case count_digits returns 1.
1222 FMT_CONSTEXPR20
inline auto count_digits(uint64_t n
) -> int {
1223 #ifdef FMT_BUILTIN_CLZLL
1224 if (!is_constant_evaluated()) {
1225 return do_count_digits(n
);
1228 return count_digits_fallback(n
);
1231 // Counts the number of digits in n. BITS = log2(radix).
1232 template <int BITS
, typename UInt
>
1233 FMT_CONSTEXPR
auto count_digits(UInt n
) -> int {
1234 #ifdef FMT_BUILTIN_CLZ
1235 if (!is_constant_evaluated() && num_bits
<UInt
>() == 32)
1236 return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n
) | 1) ^ 31) / BITS
+ 1;
1238 // Lambda avoids unreachable code warnings from NVHPC.
1243 } while ((m
>>= BITS
) != 0);
1248 #ifdef FMT_BUILTIN_CLZ
1249 // It is a separate function rather than a part of count_digits to workaround
1250 // the lack of static constexpr in constexpr functions.
1251 FMT_INLINE
auto do_count_digits(uint32_t n
) -> int {
1252 // An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1253 // This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1254 # define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1255 static constexpr uint64_t table
[] = {
1256 FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1257 FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1258 FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1259 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1260 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1261 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1262 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1263 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1264 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1265 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1266 FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1268 auto inc
= table
[FMT_BUILTIN_CLZ(n
| 1) ^ 31];
1269 return static_cast<int>((n
+ inc
) >> 32);
1273 // Optional version of count_digits for better performance on 32-bit platforms.
1274 FMT_CONSTEXPR20
inline auto count_digits(uint32_t n
) -> int {
1275 #ifdef FMT_BUILTIN_CLZ
1276 if (!is_constant_evaluated()) {
1277 return do_count_digits(n
);
1280 return count_digits_fallback(n
);
1283 template <typename Int
> constexpr auto digits10() noexcept
-> int {
1284 return std::numeric_limits
<Int
>::digits10
;
1286 template <> constexpr auto digits10
<int128_opt
>() noexcept
-> int { return 38; }
1287 template <> constexpr auto digits10
<uint128_t
>() noexcept
-> int { return 38; }
1289 template <typename Char
> struct thousands_sep_result
{
1290 std::string grouping
;
1294 template <typename Char
>
1295 FMT_API
auto thousands_sep_impl(locale_ref loc
) -> thousands_sep_result
<Char
>;
1296 template <typename Char
>
1297 inline auto thousands_sep(locale_ref loc
) -> thousands_sep_result
<Char
> {
1298 auto result
= thousands_sep_impl
<char>(loc
);
1299 return {result
.grouping
, Char(result
.thousands_sep
)};
1302 inline auto thousands_sep(locale_ref loc
) -> thousands_sep_result
<wchar_t> {
1303 return thousands_sep_impl
<wchar_t>(loc
);
1306 template <typename Char
>
1307 FMT_API
auto decimal_point_impl(locale_ref loc
) -> Char
;
1308 template <typename Char
> inline auto decimal_point(locale_ref loc
) -> Char
{
1309 return Char(decimal_point_impl
<char>(loc
));
1311 template <> inline auto decimal_point(locale_ref loc
) -> wchar_t {
1312 return decimal_point_impl
<wchar_t>(loc
);
1315 // Compares two characters for equality.
1316 template <typename Char
> auto equal2(const Char
* lhs
, const char* rhs
) -> bool {
1317 return lhs
[0] == Char(rhs
[0]) && lhs
[1] == Char(rhs
[1]);
1319 inline auto equal2(const char* lhs
, const char* rhs
) -> bool {
1320 return memcmp(lhs
, rhs
, 2) == 0;
1323 // Copies two characters from src to dst.
1324 template <typename Char
>
1325 FMT_CONSTEXPR20 FMT_INLINE
void copy2(Char
* dst
, const char* src
) {
1326 if (!is_constant_evaluated() && sizeof(Char
) == sizeof(char)) {
1327 memcpy(dst
, src
, 2);
1330 *dst
++ = static_cast<Char
>(*src
++);
1331 *dst
= static_cast<Char
>(*src
);
1334 template <typename Iterator
> struct format_decimal_result
{
1339 // Formats a decimal unsigned integer value writing into out pointing to a
1340 // buffer of specified size. The caller must ensure that the buffer is large
1342 template <typename Char
, typename UInt
>
1343 FMT_CONSTEXPR20
auto format_decimal(Char
* out
, UInt value
, int size
)
1344 -> format_decimal_result
<Char
*> {
1345 FMT_ASSERT(size
>= count_digits(value
), "invalid digit count");
1348 while (value
>= 100) {
1349 // Integer division is slow so do it for a group of two digits instead
1350 // of for every digit. The idea comes from the talk by Alexandrescu
1351 // "Three Optimization Tips for C++". See speed-test for a comparison.
1353 copy2(out
, digits2(static_cast<size_t>(value
% 100)));
1357 *--out
= static_cast<Char
>('0' + value
);
1361 copy2(out
, digits2(static_cast<size_t>(value
)));
1365 template <typename Char
, typename UInt
, typename Iterator
,
1366 FMT_ENABLE_IF(!std::is_pointer
<remove_cvref_t
<Iterator
>>::value
)>
1367 FMT_CONSTEXPR
inline auto format_decimal(Iterator out
, UInt value
, int size
)
1368 -> format_decimal_result
<Iterator
> {
1369 // Buffer is large enough to hold all digits (digits10 + 1).
1370 Char buffer
[digits10
<UInt
>() + 1] = {};
1371 auto end
= format_decimal(buffer
, value
, size
).end
;
1372 return {out
, detail::copy_str_noinline
<Char
>(buffer
, end
, out
)};
1375 template <unsigned BASE_BITS
, typename Char
, typename UInt
>
1376 FMT_CONSTEXPR
auto format_uint(Char
* buffer
, UInt value
, int num_digits
,
1377 bool upper
= false) -> Char
* {
1378 buffer
+= num_digits
;
1381 const char* digits
= upper
? "0123456789ABCDEF" : "0123456789abcdef";
1382 unsigned digit
= static_cast<unsigned>(value
& ((1 << BASE_BITS
) - 1));
1383 *--buffer
= static_cast<Char
>(BASE_BITS
< 4 ? static_cast<char>('0' + digit
)
1385 } while ((value
>>= BASE_BITS
) != 0);
1389 template <unsigned BASE_BITS
, typename Char
, typename It
, typename UInt
>
1390 FMT_CONSTEXPR
inline auto format_uint(It out
, UInt value
, int num_digits
,
1391 bool upper
= false) -> It
{
1392 if (auto ptr
= to_pointer
<Char
>(out
, to_unsigned(num_digits
))) {
1393 format_uint
<BASE_BITS
>(ptr
, value
, num_digits
, upper
);
1396 // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1397 char buffer
[num_bits
<UInt
>() / BASE_BITS
+ 1];
1398 format_uint
<BASE_BITS
>(buffer
, value
, num_digits
, upper
);
1399 return detail::copy_str_noinline
<Char
>(buffer
, buffer
+ num_digits
, out
);
1402 // A converter from UTF-8 to UTF-16.
1403 class utf8_to_utf16
{
1405 basic_memory_buffer
<wchar_t> buffer_
;
1408 FMT_API
explicit utf8_to_utf16(string_view s
);
1409 operator basic_string_view
<wchar_t>() const { return {&buffer_
[0], size()}; }
1410 auto size() const -> size_t { return buffer_
.size() - 1; }
1411 auto c_str() const -> const wchar_t* { return &buffer_
[0]; }
1412 auto str() const -> std::wstring
{ return {&buffer_
[0], size()}; }
1415 enum class to_utf8_error_policy
{ abort
, replace
};
1417 // A converter from UTF-16/UTF-32 (host endian) to UTF-8.
1418 template <typename WChar
, typename Buffer
= memory_buffer
> class to_utf8
{
1424 explicit to_utf8(basic_string_view
<WChar
> s
,
1425 to_utf8_error_policy policy
= to_utf8_error_policy::abort
) {
1426 static_assert(sizeof(WChar
) == 2 || sizeof(WChar
) == 4,
1427 "Expect utf16 or utf32");
1428 if (!convert(s
, policy
))
1429 FMT_THROW(std::runtime_error(sizeof(WChar
) == 2 ? "invalid utf16"
1430 : "invalid utf32"));
1432 operator string_view() const { return string_view(&buffer_
[0], size()); }
1433 size_t size() const { return buffer_
.size() - 1; }
1434 const char* c_str() const { return &buffer_
[0]; }
1435 std::string
str() const { return std::string(&buffer_
[0], size()); }
1437 // Performs conversion returning a bool instead of throwing exception on
1438 // conversion error. This method may still throw in case of memory allocation
1440 bool convert(basic_string_view
<WChar
> s
,
1441 to_utf8_error_policy policy
= to_utf8_error_policy::abort
) {
1442 if (!convert(buffer_
, s
, policy
)) return false;
1443 buffer_
.push_back(0);
1446 static bool convert(
1447 Buffer
& buf
, basic_string_view
<WChar
> s
,
1448 to_utf8_error_policy policy
= to_utf8_error_policy::abort
) {
1449 for (auto p
= s
.begin(); p
!= s
.end(); ++p
) {
1450 uint32_t c
= static_cast<uint32_t>(*p
);
1451 if (sizeof(WChar
) == 2 && c
>= 0xd800 && c
<= 0xdfff) {
1452 // Handle a surrogate pair.
1454 if (p
== s
.end() || (c
& 0xfc00) != 0xd800 || (*p
& 0xfc00) != 0xdc00) {
1455 if (policy
== to_utf8_error_policy::abort
) return false;
1456 buf
.append(string_view("\xEF\xBF\xBD"));
1459 c
= (c
<< 10) + static_cast<uint32_t>(*p
) - 0x35fdc00;
1461 } else if (c
< 0x80) {
1462 buf
.push_back(static_cast<char>(c
));
1463 } else if (c
< 0x800) {
1464 buf
.push_back(static_cast<char>(0xc0 | (c
>> 6)));
1465 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1466 } else if ((c
>= 0x800 && c
<= 0xd7ff) || (c
>= 0xe000 && c
<= 0xffff)) {
1467 buf
.push_back(static_cast<char>(0xe0 | (c
>> 12)));
1468 buf
.push_back(static_cast<char>(0x80 | ((c
& 0xfff) >> 6)));
1469 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1470 } else if (c
>= 0x10000 && c
<= 0x10ffff) {
1471 buf
.push_back(static_cast<char>(0xf0 | (c
>> 18)));
1472 buf
.push_back(static_cast<char>(0x80 | ((c
& 0x3ffff) >> 12)));
1473 buf
.push_back(static_cast<char>(0x80 | ((c
& 0xfff) >> 6)));
1474 buf
.push_back(static_cast<char>(0x80 | (c
& 0x3f)));
1483 // Computes 128-bit result of multiplication of two 64-bit unsigned integers.
1484 inline uint128_fallback
umul128(uint64_t x
, uint64_t y
) noexcept
{
1486 auto p
= static_cast<uint128_opt
>(x
) * static_cast<uint128_opt
>(y
);
1487 return {static_cast<uint64_t>(p
>> 64), static_cast<uint64_t>(p
)};
1488 #elif defined(_MSC_VER) && defined(_M_X64)
1489 auto hi
= uint64_t();
1490 auto lo
= _umul128(x
, y
, &hi
);
1493 const uint64_t mask
= static_cast<uint64_t>(max_value
<uint32_t>());
1495 uint64_t a
= x
>> 32;
1496 uint64_t b
= x
& mask
;
1497 uint64_t c
= y
>> 32;
1498 uint64_t d
= y
& mask
;
1500 uint64_t ac
= a
* c
;
1501 uint64_t bc
= b
* c
;
1502 uint64_t ad
= a
* d
;
1503 uint64_t bd
= b
* d
;
1505 uint64_t intermediate
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
);
1507 return {ac
+ (intermediate
>> 32) + (ad
>> 32) + (bc
>> 32),
1508 (intermediate
<< 32) + (bd
& mask
)};
1512 namespace dragonbox
{
1513 // Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
1514 // https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
1515 inline int floor_log10_pow2(int e
) noexcept
{
1516 FMT_ASSERT(e
<= 2620 && e
>= -2620, "too large exponent");
1517 static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
1518 return (e
* 315653) >> 20;
1521 inline int floor_log2_pow10(int e
) noexcept
{
1522 FMT_ASSERT(e
<= 1233 && e
>= -1233, "too large exponent");
1523 return (e
* 1741647) >> 19;
1526 // Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
1527 inline uint64_t umul128_upper64(uint64_t x
, uint64_t y
) noexcept
{
1529 auto p
= static_cast<uint128_opt
>(x
) * static_cast<uint128_opt
>(y
);
1530 return static_cast<uint64_t>(p
>> 64);
1531 #elif defined(_MSC_VER) && defined(_M_X64)
1532 return __umulh(x
, y
);
1534 return umul128(x
, y
).high();
1538 // Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
1539 // 128-bit unsigned integer.
1540 inline uint128_fallback
umul192_upper128(uint64_t x
,
1541 uint128_fallback y
) noexcept
{
1542 uint128_fallback r
= umul128(x
, y
.high());
1543 r
+= umul128_upper64(x
, y
.low());
1547 FMT_API uint128_fallback
get_cached_power(int k
) noexcept
;
1549 // Type-specific information that Dragonbox uses.
1550 template <typename T
, typename Enable
= void> struct float_info
;
1552 template <> struct float_info
<float> {
1553 using carrier_uint
= uint32_t;
1554 static const int exponent_bits
= 8;
1555 static const int kappa
= 1;
1556 static const int big_divisor
= 100;
1557 static const int small_divisor
= 10;
1558 static const int min_k
= -31;
1559 static const int max_k
= 46;
1560 static const int shorter_interval_tie_lower_threshold
= -35;
1561 static const int shorter_interval_tie_upper_threshold
= -35;
1564 template <> struct float_info
<double> {
1565 using carrier_uint
= uint64_t;
1566 static const int exponent_bits
= 11;
1567 static const int kappa
= 2;
1568 static const int big_divisor
= 1000;
1569 static const int small_divisor
= 100;
1570 static const int min_k
= -292;
1571 static const int max_k
= 341;
1572 static const int shorter_interval_tie_lower_threshold
= -77;
1573 static const int shorter_interval_tie_upper_threshold
= -77;
1576 // An 80- or 128-bit floating point number.
1577 template <typename T
>
1578 struct float_info
<T
, enable_if_t
<std::numeric_limits
<T
>::digits
== 64 ||
1579 std::numeric_limits
<T
>::digits
== 113 ||
1580 is_float128
<T
>::value
>> {
1581 using carrier_uint
= detail::uint128_t
;
1582 static const int exponent_bits
= 15;
1585 // A double-double floating point number.
1586 template <typename T
>
1587 struct float_info
<T
, enable_if_t
<is_double_double
<T
>::value
>> {
1588 using carrier_uint
= detail::uint128_t
;
1591 template <typename T
> struct decimal_fp
{
1592 using significand_type
= typename float_info
<T
>::carrier_uint
;
1593 significand_type significand
;
1597 template <typename T
> FMT_API
auto to_decimal(T x
) noexcept
-> decimal_fp
<T
>;
1598 } // namespace dragonbox
1600 // Returns true iff Float has the implicit bit which is not stored.
1601 template <typename Float
> constexpr bool has_implicit_bit() {
1602 // An 80-bit FP number has a 64-bit significand an no implicit bit.
1603 return std::numeric_limits
<Float
>::digits
!= 64;
1606 // Returns the number of significand bits stored in Float. The implicit bit is
1607 // not counted since it is not stored.
1608 template <typename Float
> constexpr int num_significand_bits() {
1609 // std::numeric_limits may not support __float128.
1610 return is_float128
<Float
>() ? 112
1611 : (std::numeric_limits
<Float
>::digits
-
1612 (has_implicit_bit
<Float
>() ? 1 : 0));
1615 template <typename Float
>
1616 constexpr auto exponent_mask() ->
1617 typename
dragonbox::float_info
<Float
>::carrier_uint
{
1618 using float_uint
= typename
dragonbox::float_info
<Float
>::carrier_uint
;
1619 return ((float_uint(1) << dragonbox::float_info
<Float
>::exponent_bits
) - 1)
1620 << num_significand_bits
<Float
>();
1622 template <typename Float
> constexpr auto exponent_bias() -> int {
1623 // std::numeric_limits may not support __float128.
1624 return is_float128
<Float
>() ? 16383
1625 : std::numeric_limits
<Float
>::max_exponent
- 1;
1628 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1629 template <typename Char
, typename It
>
1630 FMT_CONSTEXPR
auto write_exponent(int exp
, It it
) -> It
{
1631 FMT_ASSERT(-10000 < exp
&& exp
< 10000, "exponent out of range");
1633 *it
++ = static_cast<Char
>('-');
1636 *it
++ = static_cast<Char
>('+');
1639 const char* top
= digits2(to_unsigned(exp
/ 100));
1640 if (exp
>= 1000) *it
++ = static_cast<Char
>(top
[0]);
1641 *it
++ = static_cast<Char
>(top
[1]);
1644 const char* d
= digits2(to_unsigned(exp
));
1645 *it
++ = static_cast<Char
>(d
[0]);
1646 *it
++ = static_cast<Char
>(d
[1]);
1650 // A floating-point number f * pow(2, e) where F is an unsigned type.
1651 template <typename F
> struct basic_fp
{
1655 static constexpr const int num_significand_bits
=
1656 static_cast<int>(sizeof(F
) * num_bits
<unsigned char>());
1658 constexpr basic_fp() : f(0), e(0) {}
1659 constexpr basic_fp(uint64_t f_val
, int e_val
) : f(f_val
), e(e_val
) {}
1661 // Constructs fp from an IEEE754 floating-point number.
1662 template <typename Float
> FMT_CONSTEXPR
basic_fp(Float n
) { assign(n
); }
1664 // Assigns n to this and return true iff predecessor is closer than successor.
1665 template <typename Float
, FMT_ENABLE_IF(!is_double_double
<Float
>::value
)>
1666 FMT_CONSTEXPR
auto assign(Float n
) -> bool {
1667 static_assert(std::numeric_limits
<Float
>::digits
<= 113, "unsupported FP");
1668 // Assume Float is in the format [sign][exponent][significand].
1669 using carrier_uint
= typename
dragonbox::float_info
<Float
>::carrier_uint
;
1670 const auto num_float_significand_bits
=
1671 detail::num_significand_bits
<Float
>();
1672 const auto implicit_bit
= carrier_uint(1) << num_float_significand_bits
;
1673 const auto significand_mask
= implicit_bit
- 1;
1674 auto u
= bit_cast
<carrier_uint
>(n
);
1675 f
= static_cast<F
>(u
& significand_mask
);
1676 auto biased_e
= static_cast<int>((u
& exponent_mask
<Float
>()) >>
1677 num_float_significand_bits
);
1678 // The predecessor is closer if n is a normalized power of 2 (f == 0)
1679 // other than the smallest normalized number (biased_e > 1).
1680 auto is_predecessor_closer
= f
== 0 && biased_e
> 1;
1682 biased_e
= 1; // Subnormals use biased exponent 1 (min exponent).
1683 else if (has_implicit_bit
<Float
>())
1684 f
+= static_cast<F
>(implicit_bit
);
1685 e
= biased_e
- exponent_bias
<Float
>() - num_float_significand_bits
;
1686 if (!has_implicit_bit
<Float
>()) ++e
;
1687 return is_predecessor_closer
;
1690 template <typename Float
, FMT_ENABLE_IF(is_double_double
<Float
>::value
)>
1691 FMT_CONSTEXPR
auto assign(Float n
) -> bool {
1692 static_assert(std::numeric_limits
<double>::is_iec559
, "unsupported FP");
1693 return assign(static_cast<double>(n
));
1697 using fp
= basic_fp
<unsigned long long>;
1699 // Normalizes the value converted from double and multiplied by (1 << SHIFT).
1700 template <int SHIFT
= 0, typename F
>
1701 FMT_CONSTEXPR basic_fp
<F
> normalize(basic_fp
<F
> value
) {
1702 // Handle subnormals.
1703 const auto implicit_bit
= F(1) << num_significand_bits
<double>();
1704 const auto shifted_implicit_bit
= implicit_bit
<< SHIFT
;
1705 while ((value
.f
& shifted_implicit_bit
) == 0) {
1709 // Subtract 1 to account for hidden bit.
1710 const auto offset
= basic_fp
<F
>::num_significand_bits
-
1711 num_significand_bits
<double>() - SHIFT
- 1;
1717 // Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
1718 FMT_CONSTEXPR
inline uint64_t multiply(uint64_t lhs
, uint64_t rhs
) {
1720 auto product
= static_cast<__uint128_t
>(lhs
) * rhs
;
1721 auto f
= static_cast<uint64_t>(product
>> 64);
1722 return (static_cast<uint64_t>(product
) & (1ULL << 63)) != 0 ? f
+ 1 : f
;
1724 // Multiply 32-bit parts of significands.
1725 uint64_t mask
= (1ULL << 32) - 1;
1726 uint64_t a
= lhs
>> 32, b
= lhs
& mask
;
1727 uint64_t c
= rhs
>> 32, d
= rhs
& mask
;
1728 uint64_t ac
= a
* c
, bc
= b
* c
, ad
= a
* d
, bd
= b
* d
;
1729 // Compute mid 64-bit of result and round.
1730 uint64_t mid
= (bd
>> 32) + (ad
& mask
) + (bc
& mask
) + (1U << 31);
1731 return ac
+ (ad
>> 32) + (bc
>> 32) + (mid
>> 32);
1735 FMT_CONSTEXPR
inline fp
operator*(fp x
, fp y
) {
1736 return {multiply(x
.f
, y
.f
), x
.e
+ y
.e
+ 64};
1739 template <typename T
= void> struct basic_data
{
1740 // For checking rounding thresholds.
1741 // The kth entry is chosen to be the smallest integer such that the
1742 // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k.
1743 static constexpr uint32_t fractional_part_rounding_thresholds
[8] = {
1744 2576980378U, // ceil(2^31 + 2^32/10^1)
1745 2190433321U, // ceil(2^31 + 2^32/10^2)
1746 2151778616U, // ceil(2^31 + 2^32/10^3)
1747 2147913145U, // ceil(2^31 + 2^32/10^4)
1748 2147526598U, // ceil(2^31 + 2^32/10^5)
1749 2147487943U, // ceil(2^31 + 2^32/10^6)
1750 2147484078U, // ceil(2^31 + 2^32/10^7)
1751 2147483691U // ceil(2^31 + 2^32/10^8)
1754 // This is a struct rather than an alias to avoid shadowing warnings in gcc.
1755 struct data
: basic_data
<> {};
1757 #if FMT_CPLUSPLUS < 201703L
1758 template <typename T
>
1759 constexpr uint32_t basic_data
<T
>::fractional_part_rounding_thresholds
[];
1762 template <typename T
, bool doublish
= num_bits
<T
>() == num_bits
<double>()>
1763 using convert_float_result
=
1764 conditional_t
<std::is_same
<T
, float>::value
|| doublish
, double, T
>;
1766 template <typename T
>
1767 constexpr auto convert_float(T value
) -> convert_float_result
<T
> {
1768 return static_cast<convert_float_result
<T
>>(value
);
1771 template <typename OutputIt
, typename Char
>
1772 FMT_NOINLINE FMT_CONSTEXPR
auto fill(OutputIt it
, size_t n
,
1773 const fill_t
<Char
>& fill
) -> OutputIt
{
1774 auto fill_size
= fill
.size();
1775 if (fill_size
== 1) return detail::fill_n(it
, n
, fill
[0]);
1776 auto data
= fill
.data();
1777 for (size_t i
= 0; i
< n
; ++i
)
1778 it
= copy_str
<Char
>(data
, data
+ fill_size
, it
);
1782 // Writes the output of f, padded according to format specifications in specs.
1783 // size: output size in code units.
1784 // width: output display width in (terminal) column positions.
1785 template <align::type align
= align::left
, typename OutputIt
, typename Char
,
1787 FMT_CONSTEXPR
auto write_padded(OutputIt out
, const format_specs
<Char
>& specs
,
1788 size_t size
, size_t width
, F
&& f
) -> OutputIt
{
1789 static_assert(align
== align::left
|| align
== align::right
, "");
1790 unsigned spec_width
= to_unsigned(specs
.width
);
1791 size_t padding
= spec_width
> width
? spec_width
- width
: 0;
1792 // Shifts are encoded as string literals because static constexpr is not
1793 // supported in constexpr functions.
1794 auto* shifts
= align
== align::left
? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1795 size_t left_padding
= padding
>> shifts
[specs
.align
];
1796 size_t right_padding
= padding
- left_padding
;
1797 auto it
= reserve(out
, size
+ padding
* specs
.fill
.size());
1798 if (left_padding
!= 0) it
= fill(it
, left_padding
, specs
.fill
);
1800 if (right_padding
!= 0) it
= fill(it
, right_padding
, specs
.fill
);
1801 return base_iterator(out
, it
);
1804 template <align::type align
= align::left
, typename OutputIt
, typename Char
,
1806 constexpr auto write_padded(OutputIt out
, const format_specs
<Char
>& specs
,
1807 size_t size
, F
&& f
) -> OutputIt
{
1808 return write_padded
<align
>(out
, specs
, size
, size
, f
);
1811 template <align::type align
= align::left
, typename Char
, typename OutputIt
>
1812 FMT_CONSTEXPR
auto write_bytes(OutputIt out
, string_view bytes
,
1813 const format_specs
<Char
>& specs
) -> OutputIt
{
1814 return write_padded
<align
>(
1815 out
, specs
, bytes
.size(), [bytes
](reserve_iterator
<OutputIt
> it
) {
1816 const char* data
= bytes
.data();
1817 return copy_str
<Char
>(data
, data
+ bytes
.size(), it
);
1821 template <typename Char
, typename OutputIt
, typename UIntPtr
>
1822 auto write_ptr(OutputIt out
, UIntPtr value
, const format_specs
<Char
>* specs
)
1824 int num_digits
= count_digits
<4>(value
);
1825 auto size
= to_unsigned(num_digits
) + size_t(2);
1826 auto write
= [=](reserve_iterator
<OutputIt
> it
) {
1827 *it
++ = static_cast<Char
>('0');
1828 *it
++ = static_cast<Char
>('x');
1829 return format_uint
<4, Char
>(it
, value
, num_digits
);
1831 return specs
? write_padded
<align::right
>(out
, *specs
, size
, write
)
1832 : base_iterator(out
, write(reserve(out
, size
)));
1835 // Returns true iff the code point cp is printable.
1836 FMT_API
auto is_printable(uint32_t cp
) -> bool;
1838 inline auto needs_escape(uint32_t cp
) -> bool {
1839 return cp
< 0x20 || cp
== 0x7f || cp
== '"' || cp
== '\\' ||
1843 template <typename Char
> struct find_escape_result
{
1849 template <typename Char
>
1850 using make_unsigned_char
=
1851 typename conditional_t
<std::is_integral
<Char
>::value
,
1852 std::make_unsigned
<Char
>,
1853 type_identity
<uint32_t>>::type
;
1855 template <typename Char
>
1856 auto find_escape(const Char
* begin
, const Char
* end
)
1857 -> find_escape_result
<Char
> {
1858 for (; begin
!= end
; ++begin
) {
1859 uint32_t cp
= static_cast<make_unsigned_char
<Char
>>(*begin
);
1860 if (const_check(sizeof(Char
) == 1) && cp
>= 0x80) continue;
1861 if (needs_escape(cp
)) return {begin
, begin
+ 1, cp
};
1863 return {begin
, nullptr, 0};
1866 inline auto find_escape(const char* begin
, const char* end
)
1867 -> find_escape_result
<char> {
1868 if (!is_utf8()) return find_escape
<char>(begin
, end
);
1869 auto result
= find_escape_result
<char>{end
, nullptr, 0};
1870 for_each_codepoint(string_view(begin
, to_unsigned(end
- begin
)),
1871 [&](uint32_t cp
, string_view sv
) {
1872 if (needs_escape(cp
)) {
1873 result
= {sv
.begin(), sv
.end(), cp
};
1881 #define FMT_STRING_IMPL(s, base, explicit) \
1883 /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
1884 /* Use a macro-like name to avoid shadowing warnings. */ \
1885 struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
1886 using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1887 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1888 operator fmt::basic_string_view<char_type>() const { \
1889 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1892 return FMT_COMPILE_STRING(); \
1897 Constructs a compile-time format string from a string literal *s*.
1901 // A compile-time error because 'd' is an invalid specifier for strings.
1902 std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
1905 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1907 template <size_t width
, typename Char
, typename OutputIt
>
1908 auto write_codepoint(OutputIt out
, char prefix
, uint32_t cp
) -> OutputIt
{
1909 *out
++ = static_cast<Char
>('\\');
1910 *out
++ = static_cast<Char
>(prefix
);
1912 fill_n(buf
, width
, static_cast<Char
>('0'));
1913 format_uint
<4>(buf
, cp
, width
);
1914 return copy_str
<Char
>(buf
, buf
+ width
, out
);
1917 template <typename OutputIt
, typename Char
>
1918 auto write_escaped_cp(OutputIt out
, const find_escape_result
<Char
>& escape
)
1920 auto c
= static_cast<Char
>(escape
.cp
);
1921 switch (escape
.cp
) {
1923 *out
++ = static_cast<Char
>('\\');
1924 c
= static_cast<Char
>('n');
1927 *out
++ = static_cast<Char
>('\\');
1928 c
= static_cast<Char
>('r');
1931 *out
++ = static_cast<Char
>('\\');
1932 c
= static_cast<Char
>('t');
1939 *out
++ = static_cast<Char
>('\\');
1942 if (escape
.cp
< 0x100) {
1943 return write_codepoint
<2, Char
>(out
, 'x', escape
.cp
);
1945 if (escape
.cp
< 0x10000) {
1946 return write_codepoint
<4, Char
>(out
, 'u', escape
.cp
);
1948 if (escape
.cp
< 0x110000) {
1949 return write_codepoint
<8, Char
>(out
, 'U', escape
.cp
);
1951 for (Char escape_char
: basic_string_view
<Char
>(
1952 escape
.begin
, to_unsigned(escape
.end
- escape
.begin
))) {
1953 out
= write_codepoint
<2, Char
>(out
, 'x',
1954 static_cast<uint32_t>(escape_char
) & 0xFF);
1962 template <typename Char
, typename OutputIt
>
1963 auto write_escaped_string(OutputIt out
, basic_string_view
<Char
> str
)
1965 *out
++ = static_cast<Char
>('"');
1966 auto begin
= str
.begin(), end
= str
.end();
1968 auto escape
= find_escape(begin
, end
);
1969 out
= copy_str
<Char
>(begin
, escape
.begin
, out
);
1972 out
= write_escaped_cp
<OutputIt
, Char
>(out
, escape
);
1973 } while (begin
!= end
);
1974 *out
++ = static_cast<Char
>('"');
1978 template <typename Char
, typename OutputIt
>
1979 auto write_escaped_char(OutputIt out
, Char v
) -> OutputIt
{
1980 *out
++ = static_cast<Char
>('\'');
1981 if ((needs_escape(static_cast<uint32_t>(v
)) && v
!= static_cast<Char
>('"')) ||
1982 v
== static_cast<Char
>('\'')) {
1983 out
= write_escaped_cp(
1984 out
, find_escape_result
<Char
>{&v
, &v
+ 1, static_cast<uint32_t>(v
)});
1988 *out
++ = static_cast<Char
>('\'');
1992 template <typename Char
, typename OutputIt
>
1993 FMT_CONSTEXPR
auto write_char(OutputIt out
, Char value
,
1994 const format_specs
<Char
>& specs
) -> OutputIt
{
1995 bool is_debug
= specs
.type
== presentation_type::debug
;
1996 return write_padded(out
, specs
, 1, [=](reserve_iterator
<OutputIt
> it
) {
1997 if (is_debug
) return write_escaped_char(it
, value
);
2002 template <typename Char
, typename OutputIt
>
2003 FMT_CONSTEXPR
auto write(OutputIt out
, Char value
,
2004 const format_specs
<Char
>& specs
, locale_ref loc
= {})
2006 // char is formatted as unsigned char for consistency across platforms.
2007 using unsigned_type
=
2008 conditional_t
<std::is_same
<Char
, char>::value
, unsigned char, unsigned>;
2009 return check_char_specs(specs
)
2010 ? write_char(out
, value
, specs
)
2011 : write(out
, static_cast<unsigned_type
>(value
), specs
, loc
);
2014 // Data for write_int that doesn't depend on output iterator type. It is used to
2015 // avoid template code bloat.
2016 template <typename Char
> struct write_int_data
{
2020 FMT_CONSTEXPR
write_int_data(int num_digits
, unsigned prefix
,
2021 const format_specs
<Char
>& specs
)
2022 : size((prefix
>> 24) + to_unsigned(num_digits
)), padding(0) {
2023 if (specs
.align
== align::numeric
) {
2024 auto width
= to_unsigned(specs
.width
);
2026 padding
= width
- size
;
2029 } else if (specs
.precision
> num_digits
) {
2030 size
= (prefix
>> 24) + to_unsigned(specs
.precision
);
2031 padding
= to_unsigned(specs
.precision
- num_digits
);
2036 // Writes an integer in the format
2037 // <left-padding><prefix><numeric-padding><digits><right-padding>
2038 // where <digits> are written by write_digits(it).
2039 // prefix contains chars in three lower bytes and the size in the fourth byte.
2040 template <typename OutputIt
, typename Char
, typename W
>
2041 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out
, int num_digits
,
2043 const format_specs
<Char
>& specs
,
2044 W write_digits
) -> OutputIt
{
2045 // Slightly faster check for specs.width == 0 && specs.precision == -1.
2046 if ((specs
.width
| (specs
.precision
+ 1)) == 0) {
2047 auto it
= reserve(out
, to_unsigned(num_digits
) + (prefix
>> 24));
2049 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
2050 *it
++ = static_cast<Char
>(p
& 0xff);
2052 return base_iterator(out
, write_digits(it
));
2054 auto data
= write_int_data
<Char
>(num_digits
, prefix
, specs
);
2055 return write_padded
<align::right
>(
2056 out
, specs
, data
.size
, [=](reserve_iterator
<OutputIt
> it
) {
2057 for (unsigned p
= prefix
& 0xffffff; p
!= 0; p
>>= 8)
2058 *it
++ = static_cast<Char
>(p
& 0xff);
2059 it
= detail::fill_n(it
, data
.padding
, static_cast<Char
>('0'));
2060 return write_digits(it
);
2064 template <typename Char
> class digit_grouping
{
2066 std::string grouping_
;
2067 std::basic_string
<Char
> thousands_sep_
;
2070 std::string::const_iterator group
;
2073 next_state
initial_state() const { return {grouping_
.begin(), 0}; }
2075 // Returns the next digit group separator position.
2076 int next(next_state
& state
) const {
2077 if (thousands_sep_
.empty()) return max_value
<int>();
2078 if (state
.group
== grouping_
.end()) return state
.pos
+= grouping_
.back();
2079 if (*state
.group
<= 0 || *state
.group
== max_value
<char>())
2080 return max_value
<int>();
2081 state
.pos
+= *state
.group
++;
2086 explicit digit_grouping(locale_ref loc
, bool localized
= true) {
2087 if (!localized
) return;
2088 auto sep
= thousands_sep
<Char
>(loc
);
2089 grouping_
= sep
.grouping
;
2090 if (sep
.thousands_sep
) thousands_sep_
.assign(1, sep
.thousands_sep
);
2092 digit_grouping(std::string grouping
, std::basic_string
<Char
> sep
)
2093 : grouping_(std::move(grouping
)), thousands_sep_(std::move(sep
)) {}
2095 bool has_separator() const { return !thousands_sep_
.empty(); }
2097 int count_separators(int num_digits
) const {
2099 auto state
= initial_state();
2100 while (num_digits
> next(state
)) ++count
;
2104 // Applies grouping to digits and write the output to out.
2105 template <typename Out
, typename C
>
2106 Out
apply(Out out
, basic_string_view
<C
> digits
) const {
2107 auto num_digits
= static_cast<int>(digits
.size());
2108 auto separators
= basic_memory_buffer
<int>();
2109 separators
.push_back(0);
2110 auto state
= initial_state();
2111 while (int i
= next(state
)) {
2112 if (i
>= num_digits
) break;
2113 separators
.push_back(i
);
2115 for (int i
= 0, sep_index
= static_cast<int>(separators
.size() - 1);
2116 i
< num_digits
; ++i
) {
2117 if (num_digits
- i
== separators
[sep_index
]) {
2119 copy_str
<Char
>(thousands_sep_
.data(),
2120 thousands_sep_
.data() + thousands_sep_
.size(), out
);
2123 *out
++ = static_cast<Char
>(digits
[to_unsigned(i
)]);
2129 // Writes a decimal integer with digit grouping.
2130 template <typename OutputIt
, typename UInt
, typename Char
>
2131 auto write_int(OutputIt out
, UInt value
, unsigned prefix
,
2132 const format_specs
<Char
>& specs
,
2133 const digit_grouping
<Char
>& grouping
) -> OutputIt
{
2134 static_assert(std::is_same
<uint64_or_128_t
<UInt
>, UInt
>::value
, "");
2135 int num_digits
= count_digits(value
);
2137 format_decimal(digits
, value
, num_digits
);
2138 unsigned size
= to_unsigned((prefix
!= 0 ? 1 : 0) + num_digits
+
2139 grouping
.count_separators(num_digits
));
2140 return write_padded
<align::right
>(
2141 out
, specs
, size
, size
, [&](reserve_iterator
<OutputIt
> it
) {
2143 char sign
= static_cast<char>(prefix
);
2144 *it
++ = static_cast<Char
>(sign
);
2146 return grouping
.apply(it
, string_view(digits
, to_unsigned(num_digits
)));
2150 // Writes a localized value.
2151 FMT_API
auto write_loc(appender out
, loc_value value
,
2152 const format_specs
<>& specs
, locale_ref loc
) -> bool;
2153 template <typename OutputIt
, typename Char
>
2154 inline auto write_loc(OutputIt
, loc_value
, const format_specs
<Char
>&,
2155 locale_ref
) -> bool {
2159 FMT_CONSTEXPR
inline void prefix_append(unsigned& prefix
, unsigned value
) {
2160 prefix
|= prefix
!= 0 ? value
<< 8 : value
;
2161 prefix
+= (1u + (value
> 0xff ? 1 : 0)) << 24;
2164 template <typename UInt
> struct write_int_arg
{
2169 template <typename T
>
2170 FMT_CONSTEXPR
auto make_write_int_arg(T value
, sign_t sign
)
2171 -> write_int_arg
<uint32_or_64_or_128_t
<T
>> {
2173 auto abs_value
= static_cast<uint32_or_64_or_128_t
<T
>>(value
);
2174 if (is_negative(value
)) {
2175 prefix
= 0x01000000 | '-';
2176 abs_value
= 0 - abs_value
;
2178 constexpr const unsigned prefixes
[4] = {0, 0, 0x1000000u
| '+',
2180 prefix
= prefixes
[sign
];
2182 return {abs_value
, prefix
};
2185 template <typename Char
= char> struct loc_writer
{
2186 buffer_appender
<Char
> out
;
2187 const format_specs
<Char
>& specs
;
2188 std::basic_string
<Char
> sep
;
2189 std::string grouping
;
2190 std::basic_string
<Char
> decimal_point
;
2192 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
2193 auto operator()(T value
) -> bool {
2194 auto arg
= make_write_int_arg(value
, specs
.sign
);
2195 write_int(out
, static_cast<uint64_or_128_t
<T
>>(arg
.abs_value
), arg
.prefix
,
2196 specs
, digit_grouping
<Char
>(grouping
, sep
));
2200 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
2201 auto operator()(T
) -> bool {
2206 template <typename Char
, typename OutputIt
, typename T
>
2207 FMT_CONSTEXPR FMT_INLINE
auto write_int(OutputIt out
, write_int_arg
<T
> arg
,
2208 const format_specs
<Char
>& specs
,
2209 locale_ref
) -> OutputIt
{
2210 static_assert(std::is_same
<T
, uint32_or_64_or_128_t
<T
>>::value
, "");
2211 auto abs_value
= arg
.abs_value
;
2212 auto prefix
= arg
.prefix
;
2213 switch (specs
.type
) {
2214 case presentation_type::none
:
2215 case presentation_type::dec
: {
2216 auto num_digits
= count_digits(abs_value
);
2218 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2219 return format_decimal
<Char
>(it
, abs_value
, num_digits
).end
;
2222 case presentation_type::hex_lower
:
2223 case presentation_type::hex_upper
: {
2224 bool upper
= specs
.type
== presentation_type::hex_upper
;
2226 prefix_append(prefix
, unsigned(upper
? 'X' : 'x') << 8 | '0');
2227 int num_digits
= count_digits
<4>(abs_value
);
2229 out
, num_digits
, prefix
, specs
, [=](reserve_iterator
<OutputIt
> it
) {
2230 return format_uint
<4, Char
>(it
, abs_value
, num_digits
, upper
);
2233 case presentation_type::bin_lower
:
2234 case presentation_type::bin_upper
: {
2235 bool upper
= specs
.type
== presentation_type::bin_upper
;
2237 prefix_append(prefix
, unsigned(upper
? 'B' : 'b') << 8 | '0');
2238 int num_digits
= count_digits
<1>(abs_value
);
2239 return write_int(out
, num_digits
, prefix
, specs
,
2240 [=](reserve_iterator
<OutputIt
> it
) {
2241 return format_uint
<1, Char
>(it
, abs_value
, num_digits
);
2244 case presentation_type::oct
: {
2245 int num_digits
= count_digits
<3>(abs_value
);
2246 // Octal prefix '0' is counted as a digit, so only add it if precision
2247 // is not greater than the number of digits.
2248 if (specs
.alt
&& specs
.precision
<= num_digits
&& abs_value
!= 0)
2249 prefix_append(prefix
, '0');
2250 return write_int(out
, num_digits
, prefix
, specs
,
2251 [=](reserve_iterator
<OutputIt
> it
) {
2252 return format_uint
<3, Char
>(it
, abs_value
, num_digits
);
2255 case presentation_type::chr
:
2256 return write_char(out
, static_cast<Char
>(abs_value
), specs
);
2258 throw_format_error("invalid format specifier");
2262 template <typename Char
, typename OutputIt
, typename T
>
2263 FMT_CONSTEXPR FMT_NOINLINE
auto write_int_noinline(
2264 OutputIt out
, write_int_arg
<T
> arg
, const format_specs
<Char
>& specs
,
2265 locale_ref loc
) -> OutputIt
{
2266 return write_int(out
, arg
, specs
, loc
);
2268 template <typename Char
, typename OutputIt
, typename T
,
2269 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2270 !std::is_same
<T
, bool>::value
&&
2271 std::is_same
<OutputIt
, buffer_appender
<Char
>>::value
)>
2272 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out
, T value
,
2273 const format_specs
<Char
>& specs
,
2274 locale_ref loc
) -> OutputIt
{
2275 if (specs
.localized
&& write_loc(out
, value
, specs
, loc
)) return out
;
2276 return write_int_noinline(out
, make_write_int_arg(value
, specs
.sign
), specs
,
2279 // An inlined version of write used in format string compilation.
2280 template <typename Char
, typename OutputIt
, typename T
,
2281 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2282 !std::is_same
<T
, bool>::value
&&
2283 !std::is_same
<OutputIt
, buffer_appender
<Char
>>::value
)>
2284 FMT_CONSTEXPR FMT_INLINE
auto write(OutputIt out
, T value
,
2285 const format_specs
<Char
>& specs
,
2286 locale_ref loc
) -> OutputIt
{
2287 if (specs
.localized
&& write_loc(out
, value
, specs
, loc
)) return out
;
2288 return write_int(out
, make_write_int_arg(value
, specs
.sign
), specs
, loc
);
2291 // An output iterator that counts the number of objects written to it and
2293 class counting_iterator
{
2298 using iterator_category
= std::output_iterator_tag
;
2299 using difference_type
= std::ptrdiff_t;
2300 using pointer
= void;
2301 using reference
= void;
2302 FMT_UNCHECKED_ITERATOR(counting_iterator
);
2305 template <typename T
> FMT_CONSTEXPR
void operator=(const T
&) {}
2308 FMT_CONSTEXPR
counting_iterator() : count_(0) {}
2310 FMT_CONSTEXPR
size_t count() const { return count_
; }
2312 FMT_CONSTEXPR counting_iterator
& operator++() {
2316 FMT_CONSTEXPR counting_iterator
operator++(int) {
2322 FMT_CONSTEXPR
friend counting_iterator
operator+(counting_iterator it
,
2323 difference_type n
) {
2324 it
.count_
+= static_cast<size_t>(n
);
2328 FMT_CONSTEXPR value_type
operator*() const { return {}; }
2331 template <typename Char
, typename OutputIt
>
2332 FMT_CONSTEXPR
auto write(OutputIt out
, basic_string_view
<Char
> s
,
2333 const format_specs
<Char
>& specs
) -> OutputIt
{
2334 auto data
= s
.data();
2335 auto size
= s
.size();
2336 if (specs
.precision
>= 0 && to_unsigned(specs
.precision
) < size
)
2337 size
= code_point_index(s
, to_unsigned(specs
.precision
));
2338 bool is_debug
= specs
.type
== presentation_type::debug
;
2340 if (specs
.width
!= 0) {
2342 width
= write_escaped_string(counting_iterator
{}, s
).count();
2344 width
= compute_width(basic_string_view
<Char
>(data
, size
));
2346 return write_padded(out
, specs
, size
, width
,
2347 [=](reserve_iterator
<OutputIt
> it
) {
2348 if (is_debug
) return write_escaped_string(it
, s
);
2349 return copy_str
<Char
>(data
, data
+ size
, it
);
2352 template <typename Char
, typename OutputIt
>
2353 FMT_CONSTEXPR
auto write(OutputIt out
,
2354 basic_string_view
<type_identity_t
<Char
>> s
,
2355 const format_specs
<Char
>& specs
, locale_ref
)
2357 return write(out
, s
, specs
);
2359 template <typename Char
, typename OutputIt
>
2360 FMT_CONSTEXPR
auto write(OutputIt out
, const Char
* s
,
2361 const format_specs
<Char
>& specs
, locale_ref
)
2363 return specs
.type
!= presentation_type::pointer
2364 ? write(out
, basic_string_view
<Char
>(s
), specs
, {})
2365 : write_ptr
<Char
>(out
, bit_cast
<uintptr_t>(s
), &specs
);
2368 template <typename Char
, typename OutputIt
, typename T
,
2369 FMT_ENABLE_IF(is_integral
<T
>::value
&&
2370 !std::is_same
<T
, bool>::value
&&
2371 !std::is_same
<T
, Char
>::value
)>
2372 FMT_CONSTEXPR
auto write(OutputIt out
, T value
) -> OutputIt
{
2373 auto abs_value
= static_cast<uint32_or_64_or_128_t
<T
>>(value
);
2374 bool negative
= is_negative(value
);
2375 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2376 if (negative
) abs_value
= ~abs_value
+ 1;
2377 int num_digits
= count_digits(abs_value
);
2378 auto size
= (negative
? 1 : 0) + static_cast<size_t>(num_digits
);
2379 auto it
= reserve(out
, size
);
2380 if (auto ptr
= to_pointer
<Char
>(it
, size
)) {
2381 if (negative
) *ptr
++ = static_cast<Char
>('-');
2382 format_decimal
<Char
>(ptr
, abs_value
, num_digits
);
2385 if (negative
) *it
++ = static_cast<Char
>('-');
2386 it
= format_decimal
<Char
>(it
, abs_value
, num_digits
).end
;
2387 return base_iterator(out
, it
);
2391 template <typename Char
>
2392 FMT_CONSTEXPR
auto parse_align(const Char
* begin
, const Char
* end
,
2393 format_specs
<Char
>& specs
) -> const Char
* {
2394 FMT_ASSERT(begin
!= end
, "");
2395 auto align
= align::none
;
2396 auto p
= begin
+ code_point_length(begin
);
2397 if (end
- p
<= 0) p
= begin
;
2399 switch (to_ascii(*p
)) {
2401 align
= align::left
;
2404 align
= align::right
;
2407 align
= align::center
;
2410 if (align
!= align::none
) {
2413 if (c
== '}') return begin
;
2415 throw_format_error("invalid fill character '{'");
2418 specs
.fill
= {begin
, to_unsigned(p
- begin
)};
2424 } else if (p
== begin
) {
2429 specs
.align
= align
;
2433 // A floating-point presentation format.
2434 enum class float_format
: unsigned char {
2435 general
, // General: exponent notation or fixed point based on magnitude.
2436 exp
, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
2437 fixed
, // Fixed point with the default precision of 6, e.g. 0.0012.
2441 struct float_specs
{
2443 float_format format
: 8;
2451 template <typename ErrorHandler
= error_handler
, typename Char
>
2452 FMT_CONSTEXPR
auto parse_float_type_spec(const format_specs
<Char
>& specs
,
2453 ErrorHandler
&& eh
= {})
2455 auto result
= float_specs();
2456 result
.showpoint
= specs
.alt
;
2457 result
.locale
= specs
.localized
;
2458 switch (specs
.type
) {
2459 case presentation_type::none
:
2460 result
.format
= float_format::general
;
2462 case presentation_type::general_upper
:
2463 result
.upper
= true;
2465 case presentation_type::general_lower
:
2466 result
.format
= float_format::general
;
2468 case presentation_type::exp_upper
:
2469 result
.upper
= true;
2471 case presentation_type::exp_lower
:
2472 result
.format
= float_format::exp
;
2473 result
.showpoint
|= specs
.precision
!= 0;
2475 case presentation_type::fixed_upper
:
2476 result
.upper
= true;
2478 case presentation_type::fixed_lower
:
2479 result
.format
= float_format::fixed
;
2480 result
.showpoint
|= specs
.precision
!= 0;
2482 case presentation_type::hexfloat_upper
:
2483 result
.upper
= true;
2485 case presentation_type::hexfloat_lower
:
2486 result
.format
= float_format::hex
;
2489 eh
.on_error("invalid format specifier");
2495 template <typename Char
, typename OutputIt
>
2496 FMT_CONSTEXPR20
auto write_nonfinite(OutputIt out
, bool isnan
,
2497 format_specs
<Char
> specs
,
2498 const float_specs
& fspecs
) -> OutputIt
{
2500 isnan
? (fspecs
.upper
? "NAN" : "nan") : (fspecs
.upper
? "INF" : "inf");
2501 constexpr size_t str_size
= 3;
2502 auto sign
= fspecs
.sign
;
2503 auto size
= str_size
+ (sign
? 1 : 0);
2504 // Replace '0'-padding with space for non-finite values.
2505 const bool is_zero_fill
=
2506 specs
.fill
.size() == 1 && *specs
.fill
.data() == static_cast<Char
>('0');
2507 if (is_zero_fill
) specs
.fill
[0] = static_cast<Char
>(' ');
2508 return write_padded(out
, specs
, size
, [=](reserve_iterator
<OutputIt
> it
) {
2509 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2510 return copy_str
<Char
>(str
, str
+ str_size
, it
);
2514 // A decimal floating-point number significand * pow(10, exp).
2515 struct big_decimal_fp
{
2516 const char* significand
;
2517 int significand_size
;
2521 constexpr auto get_significand_size(const big_decimal_fp
& f
) -> int {
2522 return f
.significand_size
;
2524 template <typename T
>
2525 inline auto get_significand_size(const dragonbox::decimal_fp
<T
>& f
) -> int {
2526 return count_digits(f
.significand
);
2529 template <typename Char
, typename OutputIt
>
2530 constexpr auto write_significand(OutputIt out
, const char* significand
,
2531 int significand_size
) -> OutputIt
{
2532 return copy_str
<Char
>(significand
, significand
+ significand_size
, out
);
2534 template <typename Char
, typename OutputIt
, typename UInt
>
2535 inline auto write_significand(OutputIt out
, UInt significand
,
2536 int significand_size
) -> OutputIt
{
2537 return format_decimal
<Char
>(out
, significand
, significand_size
).end
;
2539 template <typename Char
, typename OutputIt
, typename T
, typename Grouping
>
2540 FMT_CONSTEXPR20
auto write_significand(OutputIt out
, T significand
,
2541 int significand_size
, int exponent
,
2542 const Grouping
& grouping
) -> OutputIt
{
2543 if (!grouping
.has_separator()) {
2544 out
= write_significand
<Char
>(out
, significand
, significand_size
);
2545 return detail::fill_n(out
, exponent
, static_cast<Char
>('0'));
2547 auto buffer
= memory_buffer();
2548 write_significand
<char>(appender(buffer
), significand
, significand_size
);
2549 detail::fill_n(appender(buffer
), exponent
, '0');
2550 return grouping
.apply(out
, string_view(buffer
.data(), buffer
.size()));
2553 template <typename Char
, typename UInt
,
2554 FMT_ENABLE_IF(std::is_integral
<UInt
>::value
)>
2555 inline auto write_significand(Char
* out
, UInt significand
, int significand_size
,
2556 int integral_size
, Char decimal_point
) -> Char
* {
2558 return format_decimal(out
, significand
, significand_size
).end
;
2559 out
+= significand_size
+ 1;
2561 int floating_size
= significand_size
- integral_size
;
2562 for (int i
= floating_size
/ 2; i
> 0; --i
) {
2564 copy2(out
, digits2(static_cast<std::size_t>(significand
% 100)));
2567 if (floating_size
% 2 != 0) {
2568 *--out
= static_cast<Char
>('0' + significand
% 10);
2571 *--out
= decimal_point
;
2572 format_decimal(out
- integral_size
, significand
, integral_size
);
2576 template <typename OutputIt
, typename UInt
, typename Char
,
2577 FMT_ENABLE_IF(!std::is_pointer
<remove_cvref_t
<OutputIt
>>::value
)>
2578 inline auto write_significand(OutputIt out
, UInt significand
,
2579 int significand_size
, int integral_size
,
2580 Char decimal_point
) -> OutputIt
{
2581 // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
2582 Char buffer
[digits10
<UInt
>() + 2];
2583 auto end
= write_significand(buffer
, significand
, significand_size
,
2584 integral_size
, decimal_point
);
2585 return detail::copy_str_noinline
<Char
>(buffer
, end
, out
);
2588 template <typename OutputIt
, typename Char
>
2589 FMT_CONSTEXPR
auto write_significand(OutputIt out
, const char* significand
,
2590 int significand_size
, int integral_size
,
2591 Char decimal_point
) -> OutputIt
{
2592 out
= detail::copy_str_noinline
<Char
>(significand
,
2593 significand
+ integral_size
, out
);
2594 if (!decimal_point
) return out
;
2595 *out
++ = decimal_point
;
2596 return detail::copy_str_noinline
<Char
>(significand
+ integral_size
,
2597 significand
+ significand_size
, out
);
2600 template <typename OutputIt
, typename Char
, typename T
, typename Grouping
>
2601 FMT_CONSTEXPR20
auto write_significand(OutputIt out
, T significand
,
2602 int significand_size
, int integral_size
,
2604 const Grouping
& grouping
) -> OutputIt
{
2605 if (!grouping
.has_separator()) {
2606 return write_significand(out
, significand
, significand_size
, integral_size
,
2609 auto buffer
= basic_memory_buffer
<Char
>();
2610 write_significand(buffer_appender
<Char
>(buffer
), significand
,
2611 significand_size
, integral_size
, decimal_point
);
2613 out
, basic_string_view
<Char
>(buffer
.data(), to_unsigned(integral_size
)));
2614 return detail::copy_str_noinline
<Char
>(buffer
.data() + integral_size
,
2618 template <typename OutputIt
, typename DecimalFP
, typename Char
,
2619 typename Grouping
= digit_grouping
<Char
>>
2620 FMT_CONSTEXPR20
auto do_write_float(OutputIt out
, const DecimalFP
& f
,
2621 const format_specs
<Char
>& specs
,
2622 float_specs fspecs
, locale_ref loc
)
2624 auto significand
= f
.significand
;
2625 int significand_size
= get_significand_size(f
);
2626 const Char zero
= static_cast<Char
>('0');
2627 auto sign
= fspecs
.sign
;
2628 size_t size
= to_unsigned(significand_size
) + (sign
? 1 : 0);
2629 using iterator
= reserve_iterator
<OutputIt
>;
2631 Char decimal_point
=
2632 fspecs
.locale
? detail::decimal_point
<Char
>(loc
) : static_cast<Char
>('.');
2634 int output_exp
= f
.exponent
+ significand_size
- 1;
2635 auto use_exp_format
= [=]() {
2636 if (fspecs
.format
== float_format::exp
) return true;
2637 if (fspecs
.format
!= float_format::general
) return false;
2638 // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
2639 // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
2640 const int exp_lower
= -4, exp_upper
= 16;
2641 return output_exp
< exp_lower
||
2642 output_exp
>= (fspecs
.precision
> 0 ? fspecs
.precision
: exp_upper
);
2644 if (use_exp_format()) {
2646 if (fspecs
.showpoint
) {
2647 num_zeros
= fspecs
.precision
- significand_size
;
2648 if (num_zeros
< 0) num_zeros
= 0;
2649 size
+= to_unsigned(num_zeros
);
2650 } else if (significand_size
== 1) {
2651 decimal_point
= Char();
2653 auto abs_output_exp
= output_exp
>= 0 ? output_exp
: -output_exp
;
2655 if (abs_output_exp
>= 100) exp_digits
= abs_output_exp
>= 1000 ? 4 : 3;
2657 size
+= to_unsigned((decimal_point
? 1 : 0) + 2 + exp_digits
);
2658 char exp_char
= fspecs
.upper
? 'E' : 'e';
2659 auto write
= [=](iterator it
) {
2660 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2661 // Insert a decimal point after the first digit and add an exponent.
2662 it
= write_significand(it
, significand
, significand_size
, 1,
2664 if (num_zeros
> 0) it
= detail::fill_n(it
, num_zeros
, zero
);
2665 *it
++ = static_cast<Char
>(exp_char
);
2666 return write_exponent
<Char
>(output_exp
, it
);
2668 return specs
.width
> 0 ? write_padded
<align::right
>(out
, specs
, size
, write
)
2669 : base_iterator(out
, write(reserve(out
, size
)));
2672 int exp
= f
.exponent
+ significand_size
;
2673 if (f
.exponent
>= 0) {
2674 // 1234e5 -> 123400000[.0+]
2675 size
+= to_unsigned(f
.exponent
);
2676 int num_zeros
= fspecs
.precision
- exp
;
2677 abort_fuzzing_if(num_zeros
> 5000);
2678 if (fspecs
.showpoint
) {
2680 if (num_zeros
<= 0 && fspecs
.format
!= float_format::fixed
) num_zeros
= 0;
2681 if (num_zeros
> 0) size
+= to_unsigned(num_zeros
);
2683 auto grouping
= Grouping(loc
, fspecs
.locale
);
2684 size
+= to_unsigned(grouping
.count_separators(exp
));
2685 return write_padded
<align::right
>(out
, specs
, size
, [&](iterator it
) {
2686 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2687 it
= write_significand
<Char
>(it
, significand
, significand_size
,
2688 f
.exponent
, grouping
);
2689 if (!fspecs
.showpoint
) return it
;
2690 *it
++ = decimal_point
;
2691 return num_zeros
> 0 ? detail::fill_n(it
, num_zeros
, zero
) : it
;
2693 } else if (exp
> 0) {
2694 // 1234e-2 -> 12.34[0+]
2695 int num_zeros
= fspecs
.showpoint
? fspecs
.precision
- significand_size
: 0;
2696 size
+= 1 + to_unsigned(num_zeros
> 0 ? num_zeros
: 0);
2697 auto grouping
= Grouping(loc
, fspecs
.locale
);
2698 size
+= to_unsigned(grouping
.count_separators(exp
));
2699 return write_padded
<align::right
>(out
, specs
, size
, [&](iterator it
) {
2700 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2701 it
= write_significand(it
, significand
, significand_size
, exp
,
2702 decimal_point
, grouping
);
2703 return num_zeros
> 0 ? detail::fill_n(it
, num_zeros
, zero
) : it
;
2706 // 1234e-6 -> 0.001234
2707 int num_zeros
= -exp
;
2708 if (significand_size
== 0 && fspecs
.precision
>= 0 &&
2709 fspecs
.precision
< num_zeros
) {
2710 num_zeros
= fspecs
.precision
;
2712 bool pointy
= num_zeros
!= 0 || significand_size
!= 0 || fspecs
.showpoint
;
2713 size
+= 1 + (pointy
? 1 : 0) + to_unsigned(num_zeros
);
2714 return write_padded
<align::right
>(out
, specs
, size
, [&](iterator it
) {
2715 if (sign
) *it
++ = detail::sign
<Char
>(sign
);
2717 if (!pointy
) return it
;
2718 *it
++ = decimal_point
;
2719 it
= detail::fill_n(it
, num_zeros
, zero
);
2720 return write_significand
<Char
>(it
, significand
, significand_size
);
2724 template <typename Char
> class fallback_digit_grouping
{
2726 constexpr fallback_digit_grouping(locale_ref
, bool) {}
2728 constexpr bool has_separator() const { return false; }
2730 constexpr int count_separators(int) const { return 0; }
2732 template <typename Out
, typename C
>
2733 constexpr Out
apply(Out out
, basic_string_view
<C
>) const {
2738 template <typename OutputIt
, typename DecimalFP
, typename Char
>
2739 FMT_CONSTEXPR20
auto write_float(OutputIt out
, const DecimalFP
& f
,
2740 const format_specs
<Char
>& specs
,
2741 float_specs fspecs
, locale_ref loc
)
2743 if (is_constant_evaluated()) {
2744 return do_write_float
<OutputIt
, DecimalFP
, Char
,
2745 fallback_digit_grouping
<Char
>>(out
, f
, specs
, fspecs
,
2748 return do_write_float(out
, f
, specs
, fspecs
, loc
);
2752 template <typename T
> constexpr bool isnan(T value
) {
2753 return !(value
>= value
); // std::isnan doesn't support __float128.
2756 template <typename T
, typename Enable
= void>
2757 struct has_isfinite
: std::false_type
{};
2759 template <typename T
>
2760 struct has_isfinite
<T
, enable_if_t
<sizeof(std::isfinite(T())) != 0>>
2761 : std::true_type
{};
2763 template <typename T
, FMT_ENABLE_IF(std::is_floating_point
<T
>::value
&&
2764 has_isfinite
<T
>::value
)>
2765 FMT_CONSTEXPR20
bool isfinite(T value
) {
2766 constexpr T inf
= T(std::numeric_limits
<double>::infinity());
2767 if (is_constant_evaluated())
2768 return !detail::isnan(value
) && value
< inf
&& value
> -inf
;
2769 return std::isfinite(value
);
2771 template <typename T
, FMT_ENABLE_IF(!has_isfinite
<T
>::value
)>
2772 FMT_CONSTEXPR
bool isfinite(T value
) {
2773 T inf
= T(std::numeric_limits
<double>::infinity());
2774 // std::isfinite doesn't support __float128.
2775 return !detail::isnan(value
) && value
< inf
&& value
> -inf
;
2778 template <typename T
, FMT_ENABLE_IF(is_floating_point
<T
>::value
)>
2779 FMT_INLINE FMT_CONSTEXPR
bool signbit(T value
) {
2780 if (is_constant_evaluated()) {
2781 #ifdef __cpp_if_constexpr
2782 if constexpr (std::numeric_limits
<double>::is_iec559
) {
2783 auto bits
= detail::bit_cast
<uint64_t>(static_cast<double>(value
));
2784 return (bits
>> (num_bits
<uint64_t>() - 1)) != 0;
2788 return std::signbit(static_cast<double>(value
));
2791 inline FMT_CONSTEXPR20
void adjust_precision(int& precision
, int exp10
) {
2792 // Adjust fixed precision by exponent because it is relative to decimal
2794 if (exp10
> 0 && precision
> max_value
<int>() - exp10
)
2795 FMT_THROW(format_error("number is too big"));
2801 // A bigint is stored as an array of bigits (big digits), with bigit at index
2802 // 0 being the least significant one.
2803 using bigit
= uint32_t;
2804 using double_bigit
= uint64_t;
2805 enum { bigits_capacity
= 32 };
2806 basic_memory_buffer
<bigit
, bigits_capacity
> bigits_
;
2809 FMT_CONSTEXPR20 bigit
operator[](int index
) const {
2810 return bigits_
[to_unsigned(index
)];
2812 FMT_CONSTEXPR20 bigit
& operator[](int index
) {
2813 return bigits_
[to_unsigned(index
)];
2816 static constexpr const int bigit_bits
= num_bits
<bigit
>();
2818 friend struct formatter
<bigint
>;
2820 FMT_CONSTEXPR20
void subtract_bigits(int index
, bigit other
, bigit
& borrow
) {
2821 auto result
= static_cast<double_bigit
>((*this)[index
]) - other
- borrow
;
2822 (*this)[index
] = static_cast<bigit
>(result
);
2823 borrow
= static_cast<bigit
>(result
>> (bigit_bits
* 2 - 1));
2826 FMT_CONSTEXPR20
void remove_leading_zeros() {
2827 int num_bigits
= static_cast<int>(bigits_
.size()) - 1;
2828 while (num_bigits
> 0 && (*this)[num_bigits
] == 0) --num_bigits
;
2829 bigits_
.resize(to_unsigned(num_bigits
+ 1));
2832 // Computes *this -= other assuming aligned bigints and *this >= other.
2833 FMT_CONSTEXPR20
void subtract_aligned(const bigint
& other
) {
2834 FMT_ASSERT(other
.exp_
>= exp_
, "unaligned bigints");
2835 FMT_ASSERT(compare(*this, other
) >= 0, "");
2837 int i
= other
.exp_
- exp_
;
2838 for (size_t j
= 0, n
= other
.bigits_
.size(); j
!= n
; ++i
, ++j
)
2839 subtract_bigits(i
, other
.bigits_
[j
], borrow
);
2840 while (borrow
> 0) subtract_bigits(i
, 0, borrow
);
2841 remove_leading_zeros();
2844 FMT_CONSTEXPR20
void multiply(uint32_t value
) {
2845 const double_bigit wide_value
= value
;
2847 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2848 double_bigit result
= bigits_
[i
] * wide_value
+ carry
;
2849 bigits_
[i
] = static_cast<bigit
>(result
);
2850 carry
= static_cast<bigit
>(result
>> bigit_bits
);
2852 if (carry
!= 0) bigits_
.push_back(carry
);
2855 template <typename UInt
, FMT_ENABLE_IF(std::is_same
<UInt
, uint64_t>::value
||
2856 std::is_same
<UInt
, uint128_t
>::value
)>
2857 FMT_CONSTEXPR20
void multiply(UInt value
) {
2859 conditional_t
<std::is_same
<UInt
, uint128_t
>::value
, uint64_t, uint32_t>;
2860 const int shift
= num_bits
<half_uint
>() - bigit_bits
;
2861 const UInt lower
= static_cast<half_uint
>(value
);
2862 const UInt upper
= value
>> num_bits
<half_uint
>();
2864 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2865 UInt result
= lower
* bigits_
[i
] + static_cast<bigit
>(carry
);
2866 carry
= (upper
* bigits_
[i
] << shift
) + (result
>> bigit_bits
) +
2867 (carry
>> bigit_bits
);
2868 bigits_
[i
] = static_cast<bigit
>(result
);
2870 while (carry
!= 0) {
2871 bigits_
.push_back(static_cast<bigit
>(carry
));
2872 carry
>>= bigit_bits
;
2876 template <typename UInt
, FMT_ENABLE_IF(std::is_same
<UInt
, uint64_t>::value
||
2877 std::is_same
<UInt
, uint128_t
>::value
)>
2878 FMT_CONSTEXPR20
void assign(UInt n
) {
2879 size_t num_bigits
= 0;
2881 bigits_
[num_bigits
++] = static_cast<bigit
>(n
);
2884 bigits_
.resize(num_bigits
);
2889 FMT_CONSTEXPR20
bigint() : exp_(0) {}
2890 explicit bigint(uint64_t n
) { assign(n
); }
2892 bigint(const bigint
&) = delete;
2893 void operator=(const bigint
&) = delete;
2895 FMT_CONSTEXPR20
void assign(const bigint
& other
) {
2896 auto size
= other
.bigits_
.size();
2897 bigits_
.resize(size
);
2898 auto data
= other
.bigits_
.data();
2899 copy_str
<bigit
>(data
, data
+ size
, bigits_
.data());
2903 template <typename Int
> FMT_CONSTEXPR20
void operator=(Int n
) {
2904 FMT_ASSERT(n
> 0, "");
2905 assign(uint64_or_128_t
<Int
>(n
));
2908 FMT_CONSTEXPR20
int num_bigits() const {
2909 return static_cast<int>(bigits_
.size()) + exp_
;
2912 FMT_NOINLINE FMT_CONSTEXPR20 bigint
& operator<<=(int shift
) {
2913 FMT_ASSERT(shift
>= 0, "");
2914 exp_
+= shift
/ bigit_bits
;
2915 shift
%= bigit_bits
;
2916 if (shift
== 0) return *this;
2918 for (size_t i
= 0, n
= bigits_
.size(); i
< n
; ++i
) {
2919 bigit c
= bigits_
[i
] >> (bigit_bits
- shift
);
2920 bigits_
[i
] = (bigits_
[i
] << shift
) + carry
;
2923 if (carry
!= 0) bigits_
.push_back(carry
);
2927 template <typename Int
> FMT_CONSTEXPR20 bigint
& operator*=(Int value
) {
2928 FMT_ASSERT(value
> 0, "");
2929 multiply(uint32_or_64_or_128_t
<Int
>(value
));
2933 friend FMT_CONSTEXPR20
int compare(const bigint
& lhs
, const bigint
& rhs
) {
2934 int num_lhs_bigits
= lhs
.num_bigits(), num_rhs_bigits
= rhs
.num_bigits();
2935 if (num_lhs_bigits
!= num_rhs_bigits
)
2936 return num_lhs_bigits
> num_rhs_bigits
? 1 : -1;
2937 int i
= static_cast<int>(lhs
.bigits_
.size()) - 1;
2938 int j
= static_cast<int>(rhs
.bigits_
.size()) - 1;
2940 if (end
< 0) end
= 0;
2941 for (; i
>= end
; --i
, --j
) {
2942 bigit lhs_bigit
= lhs
[i
], rhs_bigit
= rhs
[j
];
2943 if (lhs_bigit
!= rhs_bigit
) return lhs_bigit
> rhs_bigit
? 1 : -1;
2945 if (i
!= j
) return i
> j
? 1 : -1;
2949 // Returns compare(lhs1 + lhs2, rhs).
2950 friend FMT_CONSTEXPR20
int add_compare(const bigint
& lhs1
, const bigint
& lhs2
,
2951 const bigint
& rhs
) {
2952 auto minimum
= [](int a
, int b
) { return a
< b
? a
: b
; };
2953 auto maximum
= [](int a
, int b
) { return a
> b
? a
: b
; };
2954 int max_lhs_bigits
= maximum(lhs1
.num_bigits(), lhs2
.num_bigits());
2955 int num_rhs_bigits
= rhs
.num_bigits();
2956 if (max_lhs_bigits
+ 1 < num_rhs_bigits
) return -1;
2957 if (max_lhs_bigits
> num_rhs_bigits
) return 1;
2958 auto get_bigit
= [](const bigint
& n
, int i
) -> bigit
{
2959 return i
>= n
.exp_
&& i
< n
.num_bigits() ? n
[i
- n
.exp_
] : 0;
2961 double_bigit borrow
= 0;
2962 int min_exp
= minimum(minimum(lhs1
.exp_
, lhs2
.exp_
), rhs
.exp_
);
2963 for (int i
= num_rhs_bigits
- 1; i
>= min_exp
; --i
) {
2965 static_cast<double_bigit
>(get_bigit(lhs1
, i
)) + get_bigit(lhs2
, i
);
2966 bigit rhs_bigit
= get_bigit(rhs
, i
);
2967 if (sum
> rhs_bigit
+ borrow
) return 1;
2968 borrow
= rhs_bigit
+ borrow
- sum
;
2969 if (borrow
> 1) return -1;
2970 borrow
<<= bigit_bits
;
2972 return borrow
!= 0 ? -1 : 0;
2975 // Assigns pow(10, exp) to this bigint.
2976 FMT_CONSTEXPR20
void assign_pow10(int exp
) {
2977 FMT_ASSERT(exp
>= 0, "");
2978 if (exp
== 0) return *this = 1;
2979 // Find the top bit.
2981 while (exp
>= bitmask
) bitmask
<<= 1;
2983 // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
2984 // repeated squaring and multiplication.
2987 while (bitmask
!= 0) {
2989 if ((exp
& bitmask
) != 0) *this *= 5;
2992 *this <<= exp
; // Multiply by pow(2, exp) by shifting.
2995 FMT_CONSTEXPR20
void square() {
2996 int num_bigits
= static_cast<int>(bigits_
.size());
2997 int num_result_bigits
= 2 * num_bigits
;
2998 basic_memory_buffer
<bigit
, bigits_capacity
> n(std::move(bigits_
));
2999 bigits_
.resize(to_unsigned(num_result_bigits
));
3000 auto sum
= uint128_t();
3001 for (int bigit_index
= 0; bigit_index
< num_bigits
; ++bigit_index
) {
3002 // Compute bigit at position bigit_index of the result by adding
3003 // cross-product terms n[i] * n[j] such that i + j == bigit_index.
3004 for (int i
= 0, j
= bigit_index
; j
>= 0; ++i
, --j
) {
3005 // Most terms are multiplied twice which can be optimized in the future.
3006 sum
+= static_cast<double_bigit
>(n
[i
]) * n
[j
];
3008 (*this)[bigit_index
] = static_cast<bigit
>(sum
);
3009 sum
>>= num_bits
<bigit
>(); // Compute the carry.
3011 // Do the same for the top half.
3012 for (int bigit_index
= num_bigits
; bigit_index
< num_result_bigits
;
3014 for (int j
= num_bigits
- 1, i
= bigit_index
- j
; i
< num_bigits
;)
3015 sum
+= static_cast<double_bigit
>(n
[i
++]) * n
[j
--];
3016 (*this)[bigit_index
] = static_cast<bigit
>(sum
);
3017 sum
>>= num_bits
<bigit
>();
3019 remove_leading_zeros();
3023 // If this bigint has a bigger exponent than other, adds trailing zero to make
3024 // exponents equal. This simplifies some operations such as subtraction.
3025 FMT_CONSTEXPR20
void align(const bigint
& other
) {
3026 int exp_difference
= exp_
- other
.exp_
;
3027 if (exp_difference
<= 0) return;
3028 int num_bigits
= static_cast<int>(bigits_
.size());
3029 bigits_
.resize(to_unsigned(num_bigits
+ exp_difference
));
3030 for (int i
= num_bigits
- 1, j
= i
+ exp_difference
; i
>= 0; --i
, --j
)
3031 bigits_
[j
] = bigits_
[i
];
3032 std::uninitialized_fill_n(bigits_
.data(), exp_difference
, 0);
3033 exp_
-= exp_difference
;
3036 // Divides this bignum by divisor, assigning the remainder to this and
3037 // returning the quotient.
3038 FMT_CONSTEXPR20
int divmod_assign(const bigint
& divisor
) {
3039 FMT_ASSERT(this != &divisor
, "");
3040 if (compare(*this, divisor
) < 0) return 0;
3041 FMT_ASSERT(divisor
.bigits_
[divisor
.bigits_
.size() - 1u] != 0, "");
3045 subtract_aligned(divisor
);
3047 } while (compare(*this, divisor
) >= 0);
3052 // format_dragon flags.
3054 predecessor_closer
= 1,
3055 fixup
= 2, // Run fixup to correct exp10 which can be off by one.
3059 // Formats a floating-point number using a variation of the Fixed-Precision
3060 // Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
3061 // https://fmt.dev/papers/p372-steele.pdf.
3062 FMT_CONSTEXPR20
inline void format_dragon(basic_fp
<uint128_t
> value
,
3063 unsigned flags
, int num_digits
,
3064 buffer
<char>& buf
, int& exp10
) {
3065 bigint numerator
; // 2 * R in (FPP)^2.
3066 bigint denominator
; // 2 * S in (FPP)^2.
3067 // lower and upper are differences between value and corresponding boundaries.
3068 bigint lower
; // (M^- in (FPP)^2).
3069 bigint upper_store
; // upper's value if different from lower.
3070 bigint
* upper
= nullptr; // (M^+ in (FPP)^2).
3071 // Shift numerator and denominator by an extra bit or two (if lower boundary
3072 // is closer) to make lower and upper integers. This eliminates multiplication
3073 // by 2 during later computations.
3074 bool is_predecessor_closer
= (flags
& dragon::predecessor_closer
) != 0;
3075 int shift
= is_predecessor_closer
? 2 : 1;
3077 numerator
= value
.f
;
3078 numerator
<<= value
.e
+ shift
;
3081 if (is_predecessor_closer
) {
3083 upper_store
<<= value
.e
+ 1;
3084 upper
= &upper_store
;
3086 denominator
.assign_pow10(exp10
);
3087 denominator
<<= shift
;
3088 } else if (exp10
< 0) {
3089 numerator
.assign_pow10(-exp10
);
3090 lower
.assign(numerator
);
3091 if (is_predecessor_closer
) {
3092 upper_store
.assign(numerator
);
3094 upper
= &upper_store
;
3096 numerator
*= value
.f
;
3097 numerator
<<= shift
;
3099 denominator
<<= shift
- value
.e
;
3101 numerator
= value
.f
;
3102 numerator
<<= shift
;
3103 denominator
.assign_pow10(exp10
);
3104 denominator
<<= shift
- value
.e
;
3106 if (is_predecessor_closer
) {
3107 upper_store
= 1ULL << 1;
3108 upper
= &upper_store
;
3111 int even
= static_cast<int>((value
.f
& 1) == 0);
3112 if (!upper
) upper
= &lower
;
3113 bool shortest
= num_digits
< 0;
3114 if ((flags
& dragon::fixup
) != 0) {
3115 if (add_compare(numerator
, *upper
, denominator
) + even
<= 0) {
3118 if (num_digits
< 0) {
3120 if (upper
!= &lower
) *upper
*= 10;
3123 if ((flags
& dragon::fixed
) != 0) adjust_precision(num_digits
, exp10
+ 1);
3125 // Invariant: value == (numerator / denominator) * pow(10, exp10).
3127 // Generate the shortest representation.
3129 char* data
= buf
.data();
3131 int digit
= numerator
.divmod_assign(denominator
);
3132 bool low
= compare(numerator
, lower
) - even
< 0; // numerator <[=] lower.
3133 // numerator + upper >[=] pow10:
3134 bool high
= add_compare(numerator
, *upper
, denominator
) + even
> 0;
3135 data
[num_digits
++] = static_cast<char>('0' + digit
);
3138 ++data
[num_digits
- 1];
3140 int result
= add_compare(numerator
, numerator
, denominator
);
3141 // Round half to even.
3142 if (result
> 0 || (result
== 0 && (digit
% 2) != 0))
3143 ++data
[num_digits
- 1];
3145 buf
.try_resize(to_unsigned(num_digits
));
3146 exp10
-= num_digits
- 1;
3151 if (upper
!= &lower
) *upper
*= 10;
3154 // Generate the given number of digits.
3155 exp10
-= num_digits
- 1;
3156 if (num_digits
<= 0) {
3158 auto digit
= add_compare(numerator
, numerator
, denominator
) > 0 ? '1' : '0';
3159 buf
.push_back(digit
);
3162 buf
.try_resize(to_unsigned(num_digits
));
3163 for (int i
= 0; i
< num_digits
- 1; ++i
) {
3164 int digit
= numerator
.divmod_assign(denominator
);
3165 buf
[i
] = static_cast<char>('0' + digit
);
3168 int digit
= numerator
.divmod_assign(denominator
);
3169 auto result
= add_compare(numerator
, numerator
, denominator
);
3170 if (result
> 0 || (result
== 0 && (digit
% 2) != 0)) {
3172 const auto overflow
= '0' + 10;
3173 buf
[num_digits
- 1] = overflow
;
3174 // Propagate the carry.
3175 for (int i
= num_digits
- 1; i
> 0 && buf
[i
] == overflow
; --i
) {
3179 if (buf
[0] == overflow
) {
3181 if ((flags
& dragon::fixed
) != 0) buf
.push_back('0');
3188 buf
[num_digits
- 1] = static_cast<char>('0' + digit
);
3191 // Formats a floating-point number using the hexfloat format.
3192 template <typename Float
, FMT_ENABLE_IF(!is_double_double
<Float
>::value
)>
3193 FMT_CONSTEXPR20
void format_hexfloat(Float value
, int precision
,
3194 float_specs specs
, buffer
<char>& buf
) {
3195 // float is passed as double to reduce the number of instantiations and to
3196 // simplify implementation.
3197 static_assert(!std::is_same
<Float
, float>::value
, "");
3199 using info
= dragonbox::float_info
<Float
>;
3201 // Assume Float is in the format [sign][exponent][significand].
3202 using carrier_uint
= typename
info::carrier_uint
;
3204 constexpr auto num_float_significand_bits
=
3205 detail::num_significand_bits
<Float
>();
3207 basic_fp
<carrier_uint
> f(value
);
3208 f
.e
+= num_float_significand_bits
;
3209 if (!has_implicit_bit
<Float
>()) --f
.e
;
3211 constexpr auto num_fraction_bits
=
3212 num_float_significand_bits
+ (has_implicit_bit
<Float
>() ? 1 : 0);
3213 constexpr auto num_xdigits
= (num_fraction_bits
+ 3) / 4;
3215 constexpr auto leading_shift
= ((num_xdigits
- 1) * 4);
3216 const auto leading_mask
= carrier_uint(0xF) << leading_shift
;
3217 const auto leading_xdigit
=
3218 static_cast<uint32_t>((f
.f
& leading_mask
) >> leading_shift
);
3219 if (leading_xdigit
> 1) f
.e
-= (32 - countl_zero(leading_xdigit
) - 1);
3221 int print_xdigits
= num_xdigits
- 1;
3222 if (precision
>= 0 && print_xdigits
> precision
) {
3223 const int shift
= ((print_xdigits
- precision
- 1) * 4);
3224 const auto mask
= carrier_uint(0xF) << shift
;
3225 const auto v
= static_cast<uint32_t>((f
.f
& mask
) >> shift
);
3228 const auto inc
= carrier_uint(1) << (shift
+ 4);
3233 // Check long double overflow
3234 if (!has_implicit_bit
<Float
>()) {
3235 const auto implicit_bit
= carrier_uint(1) << num_float_significand_bits
;
3236 if ((f
.f
& implicit_bit
) == implicit_bit
) {
3242 print_xdigits
= precision
;
3245 char xdigits
[num_bits
<carrier_uint
>() / 4];
3246 detail::fill_n(xdigits
, sizeof(xdigits
), '0');
3247 format_uint
<4>(xdigits
, f
.f
, num_xdigits
, specs
.upper
);
3250 while (print_xdigits
> 0 && xdigits
[print_xdigits
] == '0') --print_xdigits
;
3253 buf
.push_back(specs
.upper
? 'X' : 'x');
3254 buf
.push_back(xdigits
[0]);
3255 if (specs
.showpoint
|| print_xdigits
> 0 || print_xdigits
< precision
)
3257 buf
.append(xdigits
+ 1, xdigits
+ 1 + print_xdigits
);
3258 for (; print_xdigits
< precision
; ++print_xdigits
) buf
.push_back('0');
3260 buf
.push_back(specs
.upper
? 'P' : 'p');
3265 abs_e
= static_cast<uint32_t>(-f
.e
);
3268 abs_e
= static_cast<uint32_t>(f
.e
);
3270 format_decimal
<char>(appender(buf
), abs_e
, detail::count_digits(abs_e
));
3273 template <typename Float
, FMT_ENABLE_IF(is_double_double
<Float
>::value
)>
3274 FMT_CONSTEXPR20
void format_hexfloat(Float value
, int precision
,
3275 float_specs specs
, buffer
<char>& buf
) {
3276 format_hexfloat(static_cast<double>(value
), precision
, specs
, buf
);
3279 template <typename Float
>
3280 FMT_CONSTEXPR20
auto format_float(Float value
, int precision
, float_specs specs
,
3281 buffer
<char>& buf
) -> int {
3282 // float is passed as double to reduce the number of instantiations.
3283 static_assert(!std::is_same
<Float
, float>::value
, "");
3284 FMT_ASSERT(value
>= 0, "value is negative");
3285 auto converted_value
= convert_float(value
);
3287 const bool fixed
= specs
.format
== float_format::fixed
;
3288 if (value
<= 0) { // <= instead of == to silence a warning.
3289 if (precision
<= 0 || !fixed
) {
3293 buf
.try_resize(to_unsigned(precision
));
3294 fill_n(buf
.data(), precision
, '0');
3299 bool use_dragon
= true;
3300 unsigned dragon_flags
= 0;
3301 if (!is_fast_float
<Float
>() || is_constant_evaluated()) {
3302 const auto inv_log2_10
= 0.3010299956639812; // 1 / log2(10)
3303 using info
= dragonbox::float_info
<decltype(converted_value
)>;
3304 const auto f
= basic_fp
<typename
info::carrier_uint
>(converted_value
);
3305 // Compute exp, an approximate power of 10, such that
3306 // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
3307 // This is based on log10(value) == log2(value) / log2(10) and approximation
3308 // of log2(value) by e + num_fraction_bits idea from double-conversion.
3309 auto e
= (f
.e
+ count_digits
<1>(f
.f
) - 1) * inv_log2_10
- 1e-10;
3310 exp
= static_cast<int>(e
);
3311 if (e
> exp
) ++exp
; // Compute ceil.
3312 dragon_flags
= dragon::fixup
;
3313 } else if (precision
< 0) {
3314 // Use Dragonbox for the shortest format.
3315 if (specs
.binary32
) {
3316 auto dec
= dragonbox::to_decimal(static_cast<float>(value
));
3317 write
<char>(buffer_appender
<char>(buf
), dec
.significand
);
3318 return dec
.exponent
;
3320 auto dec
= dragonbox::to_decimal(static_cast<double>(value
));
3321 write
<char>(buffer_appender
<char>(buf
), dec
.significand
);
3322 return dec
.exponent
;
3324 // Extract significand bits and exponent bits.
3325 using info
= dragonbox::float_info
<double>;
3326 auto br
= bit_cast
<uint64_t>(static_cast<double>(value
));
3328 const uint64_t significand_mask
=
3329 (static_cast<uint64_t>(1) << num_significand_bits
<double>()) - 1;
3330 uint64_t significand
= (br
& significand_mask
);
3331 int exponent
= static_cast<int>((br
& exponent_mask
<double>()) >>
3332 num_significand_bits
<double>());
3334 if (exponent
!= 0) { // Check if normal.
3335 exponent
-= exponent_bias
<double>() + num_significand_bits
<double>();
3337 (static_cast<uint64_t>(1) << num_significand_bits
<double>());
3340 // Normalize subnormal inputs.
3341 FMT_ASSERT(significand
!= 0, "zeros should not appear here");
3342 int shift
= countl_zero(significand
);
3343 FMT_ASSERT(shift
>= num_bits
<uint64_t>() - num_significand_bits
<double>(),
3345 shift
-= (num_bits
<uint64_t>() - num_significand_bits
<double>() - 2);
3346 exponent
= (std::numeric_limits
<double>::min_exponent
-
3347 num_significand_bits
<double>()) -
3349 significand
<<= shift
;
3352 // Compute the first several nonzero decimal significand digits.
3353 // We call the number we get the first segment.
3354 const int k
= info::kappa
- dragonbox::floor_log10_pow2(exponent
);
3356 const int beta
= exponent
+ dragonbox::floor_log2_pow10(k
);
3357 uint64_t first_segment
;
3358 bool has_more_segments
;
3359 int digits_in_the_first_segment
;
3361 const auto r
= dragonbox::umul192_upper128(
3362 significand
<< beta
, dragonbox::get_cached_power(k
));
3363 first_segment
= r
.high();
3364 has_more_segments
= r
.low() != 0;
3366 // The first segment can have 18 ~ 19 digits.
3367 if (first_segment
>= 1000000000000000000ULL) {
3368 digits_in_the_first_segment
= 19;
3370 // When it is of 18-digits, we align it to 19-digits by adding a bogus
3372 digits_in_the_first_segment
= 18;
3373 first_segment
*= 10;
3377 // Compute the actual number of decimal digits to print.
3378 if (fixed
) adjust_precision(precision
, exp
+ digits_in_the_first_segment
);
3380 // Use Dragon4 only when there might be not enough digits in the first
3382 if (digits_in_the_first_segment
> precision
) {
3385 if (precision
<= 0) {
3386 exp
+= digits_in_the_first_segment
;
3388 if (precision
< 0) {
3389 // Nothing to do, since all we have are just leading zeros.
3392 // We may need to round-up.
3394 if ((first_segment
| static_cast<uint64_t>(has_more_segments
)) >
3395 5000000000000000000ULL) {
3403 exp
+= digits_in_the_first_segment
- precision
;
3405 // When precision > 0, we divide the first segment into three
3406 // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits
3407 // in 32-bits which usually allows faster calculation than in
3408 // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize
3409 // division-by-constant for large 64-bit divisors, we do it here
3410 // manually. The magic number 7922816251426433760 below is equal to
3411 // ceil(2^(64+32) / 10^10).
3412 const uint32_t first_subsegment
= static_cast<uint32_t>(
3413 dragonbox::umul128_upper64(first_segment
, 7922816251426433760ULL) >>
3415 const uint64_t second_third_subsegments
=
3416 first_segment
- first_subsegment
* 10000000000ULL;
3420 bool should_round_up
;
3421 int number_of_digits_to_print
= precision
> 9 ? 9 : precision
;
3423 // Print a 9-digits subsegment, either the first or the second.
3424 auto print_subsegment
= [&](uint32_t subsegment
, char* buffer
) {
3425 int number_of_digits_printed
= 0;
3427 // If we want to print an odd number of digits from the subsegment,
3428 if ((number_of_digits_to_print
& 1) != 0) {
3429 // Convert to 64-bit fixed-point fractional form with 1-digit
3430 // integer part. The magic number 720575941 is a good enough
3431 // approximation of 2^(32 + 24) / 10^8; see
3432 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3434 prod
= ((subsegment
* static_cast<uint64_t>(720575941)) >> 24) + 1;
3435 digits
= static_cast<uint32_t>(prod
>> 32);
3436 *buffer
= static_cast<char>('0' + digits
);
3437 number_of_digits_printed
++;
3439 // If we want to print an even number of digits from the
3440 // first_subsegment,
3442 // Convert to 64-bit fixed-point fractional form with 2-digits
3443 // integer part. The magic number 450359963 is a good enough
3444 // approximation of 2^(32 + 20) / 10^7; see
3445 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3447 prod
= ((subsegment
* static_cast<uint64_t>(450359963)) >> 20) + 1;
3448 digits
= static_cast<uint32_t>(prod
>> 32);
3449 copy2(buffer
, digits2(digits
));
3450 number_of_digits_printed
+= 2;
3453 // Print all digit pairs.
3454 while (number_of_digits_printed
< number_of_digits_to_print
) {
3455 prod
= static_cast<uint32_t>(prod
) * static_cast<uint64_t>(100);
3456 digits
= static_cast<uint32_t>(prod
>> 32);
3457 copy2(buffer
+ number_of_digits_printed
, digits2(digits
));
3458 number_of_digits_printed
+= 2;
3462 // Print first subsegment.
3463 print_subsegment(first_subsegment
, buf
.data());
3465 // Perform rounding if the first subsegment is the last subsegment to
3467 if (precision
<= 9) {
3468 // Rounding inside the subsegment.
3470 // - either the fractional part is strictly larger than 1/2, or
3471 // - the fractional part is exactly 1/2 and the last digit is odd.
3472 // We rely on the following observations:
3473 // - If fractional_part >= threshold, then the fractional part is
3474 // strictly larger than 1/2.
3475 // - If the MSB of fractional_part is set, then the fractional part
3476 // must be at least 1/2.
3477 // - When the MSB of fractional_part is set, either
3478 // second_third_subsegments being nonzero or has_more_segments
3479 // being true means there are further digits not printed, so the
3480 // fractional part is strictly larger than 1/2.
3481 if (precision
< 9) {
3482 uint32_t fractional_part
= static_cast<uint32_t>(prod
);
3483 should_round_up
= fractional_part
>=
3484 data::fractional_part_rounding_thresholds
3485 [8 - number_of_digits_to_print
] ||
3486 ((fractional_part
>> 31) &
3487 ((digits
& 1) | (second_third_subsegments
!= 0) |
3488 has_more_segments
)) != 0;
3490 // Rounding at the subsegment boundary.
3491 // In this case, the fractional part is at least 1/2 if and only if
3492 // second_third_subsegments >= 5000000000ULL, and is strictly larger
3493 // than 1/2 if we further have either second_third_subsegments >
3494 // 5000000000ULL or has_more_segments == true.
3496 should_round_up
= second_third_subsegments
> 5000000000ULL ||
3497 (second_third_subsegments
== 5000000000ULL &&
3498 ((digits
& 1) != 0 || has_more_segments
));
3501 // Otherwise, print the second subsegment.
3503 // Compilers are not aware of how to leverage the maximum value of
3504 // second_third_subsegments to find out a better magic number which
3505 // allows us to eliminate an additional shift. 1844674407370955162 =
3506 // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))).
3507 const uint32_t second_subsegment
=
3508 static_cast<uint32_t>(dragonbox::umul128_upper64(
3509 second_third_subsegments
, 1844674407370955162ULL));
3510 const uint32_t third_subsegment
=
3511 static_cast<uint32_t>(second_third_subsegments
) -
3512 second_subsegment
* 10;
3514 number_of_digits_to_print
= precision
- 9;
3515 print_subsegment(second_subsegment
, buf
.data() + 9);
3517 // Rounding inside the subsegment.
3518 if (precision
< 18) {
3519 // The condition third_subsegment != 0 implies that the segment was
3520 // of 19 digits, so in this case the third segment should be
3521 // consisting of a genuine digit from the input.
3522 uint32_t fractional_part
= static_cast<uint32_t>(prod
);
3523 should_round_up
= fractional_part
>=
3524 data::fractional_part_rounding_thresholds
3525 [8 - number_of_digits_to_print
] ||
3526 ((fractional_part
>> 31) &
3527 ((digits
& 1) | (third_subsegment
!= 0) |
3528 has_more_segments
)) != 0;
3530 // Rounding at the subsegment boundary.
3532 // In this case, the segment must be of 19 digits, thus
3533 // the third subsegment should be consisting of a genuine digit from
3535 should_round_up
= third_subsegment
> 5 ||
3536 (third_subsegment
== 5 &&
3537 ((digits
& 1) != 0 || has_more_segments
));
3541 // Round-up if necessary.
3542 if (should_round_up
) {
3543 ++buf
[precision
- 1];
3544 for (int i
= precision
- 1; i
> 0 && buf
[i
] > '9'; --i
) {
3551 buf
[precision
++] = '0';
3556 buf
.try_resize(to_unsigned(precision
));
3558 } // if (digits_in_the_first_segment > precision)
3560 // Adjust the exponent for its use in Dragon4.
3561 exp
+= digits_in_the_first_segment
- 1;
3565 auto f
= basic_fp
<uint128_t
>();
3566 bool is_predecessor_closer
= specs
.binary32
3567 ? f
.assign(static_cast<float>(value
))
3568 : f
.assign(converted_value
);
3569 if (is_predecessor_closer
) dragon_flags
|= dragon::predecessor_closer
;
3570 if (fixed
) dragon_flags
|= dragon::fixed
;
3571 // Limit precision to the maximum possible number of significant digits in
3572 // an IEEE754 double because we don't need to generate zeros.
3573 const int max_double_digits
= 767;
3574 if (precision
> max_double_digits
) precision
= max_double_digits
;
3575 format_dragon(f
, dragon_flags
, precision
, buf
, exp
);
3577 if (!fixed
&& !specs
.showpoint
) {
3578 // Remove trailing zeros.
3579 auto num_digits
= buf
.size();
3580 while (num_digits
> 0 && buf
[num_digits
- 1] == '0') {
3584 buf
.try_resize(num_digits
);
3588 template <typename Char
, typename OutputIt
, typename T
>
3589 FMT_CONSTEXPR20
auto write_float(OutputIt out
, T value
,
3590 format_specs
<Char
> specs
, locale_ref loc
)
3592 float_specs fspecs
= parse_float_type_spec(specs
);
3593 fspecs
.sign
= specs
.sign
;
3594 if (detail::signbit(value
)) { // value < 0 is false for NaN so use signbit.
3595 fspecs
.sign
= sign::minus
;
3597 } else if (fspecs
.sign
== sign::minus
) {
3598 fspecs
.sign
= sign::none
;
3601 if (!detail::isfinite(value
))
3602 return write_nonfinite(out
, detail::isnan(value
), specs
, fspecs
);
3604 if (specs
.align
== align::numeric
&& fspecs
.sign
) {
3605 auto it
= reserve(out
, 1);
3606 *it
++ = detail::sign
<Char
>(fspecs
.sign
);
3607 out
= base_iterator(out
, it
);
3608 fspecs
.sign
= sign::none
;
3609 if (specs
.width
!= 0) --specs
.width
;
3612 memory_buffer buffer
;
3613 if (fspecs
.format
== float_format::hex
) {
3614 if (fspecs
.sign
) buffer
.push_back(detail::sign
<char>(fspecs
.sign
));
3615 format_hexfloat(convert_float(value
), specs
.precision
, fspecs
, buffer
);
3616 return write_bytes
<align::right
>(out
, {buffer
.data(), buffer
.size()},
3619 int precision
= specs
.precision
>= 0 || specs
.type
== presentation_type::none
3622 if (fspecs
.format
== float_format::exp
) {
3623 if (precision
== max_value
<int>())
3624 throw_format_error("number is too big");
3627 } else if (fspecs
.format
!= float_format::fixed
&& precision
== 0) {
3630 if (const_check(std::is_same
<T
, float>())) fspecs
.binary32
= true;
3631 int exp
= format_float(convert_float(value
), precision
, fspecs
, buffer
);
3632 fspecs
.precision
= precision
;
3633 auto f
= big_decimal_fp
{buffer
.data(), static_cast<int>(buffer
.size()), exp
};
3634 return write_float(out
, f
, specs
, fspecs
, loc
);
3637 template <typename Char
, typename OutputIt
, typename T
,
3638 FMT_ENABLE_IF(is_floating_point
<T
>::value
)>
3639 FMT_CONSTEXPR20
auto write(OutputIt out
, T value
, format_specs
<Char
> specs
,
3640 locale_ref loc
= {}) -> OutputIt
{
3641 if (const_check(!is_supported_floating_point(value
))) return out
;
3642 return specs
.localized
&& write_loc(out
, value
, specs
, loc
)
3644 : write_float(out
, value
, specs
, loc
);
3647 template <typename Char
, typename OutputIt
, typename T
,
3648 FMT_ENABLE_IF(is_fast_float
<T
>::value
)>
3649 FMT_CONSTEXPR20
auto write(OutputIt out
, T value
) -> OutputIt
{
3650 if (is_constant_evaluated()) return write(out
, value
, format_specs
<Char
>());
3651 if (const_check(!is_supported_floating_point(value
))) return out
;
3653 auto fspecs
= float_specs();
3654 if (detail::signbit(value
)) {
3655 fspecs
.sign
= sign::minus
;
3659 constexpr auto specs
= format_specs
<Char
>();
3660 using floaty
= conditional_t
<std::is_same
<T
, long double>::value
, double, T
>;
3661 using floaty_uint
= typename
dragonbox::float_info
<floaty
>::carrier_uint
;
3662 floaty_uint mask
= exponent_mask
<floaty
>();
3663 if ((bit_cast
<floaty_uint
>(value
) & mask
) == mask
)
3664 return write_nonfinite(out
, std::isnan(value
), specs
, fspecs
);
3666 auto dec
= dragonbox::to_decimal(static_cast<floaty
>(value
));
3667 return write_float(out
, dec
, specs
, fspecs
, {});
3670 template <typename Char
, typename OutputIt
, typename T
,
3671 FMT_ENABLE_IF(is_floating_point
<T
>::value
&&
3672 !is_fast_float
<T
>::value
)>
3673 inline auto write(OutputIt out
, T value
) -> OutputIt
{
3674 return write(out
, value
, format_specs
<Char
>());
3677 template <typename Char
, typename OutputIt
>
3678 auto write(OutputIt out
, monostate
, format_specs
<Char
> = {}, locale_ref
= {})
3680 FMT_ASSERT(false, "");
3684 template <typename Char
, typename OutputIt
>
3685 FMT_CONSTEXPR
auto write(OutputIt out
, basic_string_view
<Char
> value
)
3687 auto it
= reserve(out
, value
.size());
3688 it
= copy_str_noinline
<Char
>(value
.begin(), value
.end(), it
);
3689 return base_iterator(out
, it
);
3692 template <typename Char
, typename OutputIt
, typename T
,
3693 FMT_ENABLE_IF(is_string
<T
>::value
)>
3694 constexpr auto write(OutputIt out
, const T
& value
) -> OutputIt
{
3695 return write
<Char
>(out
, to_string_view(value
));
3698 // FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
3700 typename Char
, typename OutputIt
, typename T
,
3702 std::is_enum
<T
>::value
&& !std::is_same
<T
, Char
>::value
&&
3703 mapped_type_constant
<T
, basic_format_context
<OutputIt
, Char
>>::value
!=
3705 FMT_ENABLE_IF(check
)>
3706 FMT_CONSTEXPR
auto write(OutputIt out
, T value
) -> OutputIt
{
3707 return write
<Char
>(out
, static_cast<underlying_t
<T
>>(value
));
3710 template <typename Char
, typename OutputIt
, typename T
,
3711 FMT_ENABLE_IF(std::is_same
<T
, bool>::value
)>
3712 FMT_CONSTEXPR
auto write(OutputIt out
, T value
,
3713 const format_specs
<Char
>& specs
= {}, locale_ref
= {})
3715 return specs
.type
!= presentation_type::none
&&
3716 specs
.type
!= presentation_type::string
3717 ? write(out
, value
? 1 : 0, specs
, {})
3718 : write_bytes(out
, value
? "true" : "false", specs
);
3721 template <typename Char
, typename OutputIt
>
3722 FMT_CONSTEXPR
auto write(OutputIt out
, Char value
) -> OutputIt
{
3723 auto it
= reserve(out
, 1);
3725 return base_iterator(out
, it
);
3728 template <typename Char
, typename OutputIt
>
3729 FMT_CONSTEXPR_CHAR_TRAITS
auto write(OutputIt out
, const Char
* value
)
3731 if (value
) return write(out
, basic_string_view
<Char
>(value
));
3732 throw_format_error("string pointer is null");
3736 template <typename Char
, typename OutputIt
, typename T
,
3737 FMT_ENABLE_IF(std::is_same
<T
, void>::value
)>
3738 auto write(OutputIt out
, const T
* value
, const format_specs
<Char
>& specs
= {},
3739 locale_ref
= {}) -> OutputIt
{
3740 return write_ptr
<Char
>(out
, bit_cast
<uintptr_t>(value
), &specs
);
3743 // A write overload that handles implicit conversions.
3744 template <typename Char
, typename OutputIt
, typename T
,
3745 typename Context
= basic_format_context
<OutputIt
, Char
>>
3746 FMT_CONSTEXPR
auto write(OutputIt out
, const T
& value
) -> enable_if_t
<
3747 std::is_class
<T
>::value
&& !is_string
<T
>::value
&&
3748 !is_floating_point
<T
>::value
&& !std::is_same
<T
, Char
>::value
&&
3749 !std::is_same
<T
, remove_cvref_t
<decltype(arg_mapper
<Context
>().map(
3752 return write
<Char
>(out
, arg_mapper
<Context
>().map(value
));
3755 template <typename Char
, typename OutputIt
, typename T
,
3756 typename Context
= basic_format_context
<OutputIt
, Char
>>
3757 FMT_CONSTEXPR
auto write(OutputIt out
, const T
& value
)
3758 -> enable_if_t
<mapped_type_constant
<T
, Context
>::value
== type::custom_type
,
3760 auto ctx
= Context(out
, {}, {});
3761 return typename
Context::template formatter_type
<T
>().format(value
, ctx
);
3764 // An argument visitor that formats the argument and writes it via the output
3765 // iterator. It's a class and not a generic lambda for compatibility with C++11.
3766 template <typename Char
> struct default_arg_formatter
{
3767 using iterator
= buffer_appender
<Char
>;
3768 using context
= buffer_context
<Char
>;
3771 basic_format_args
<context
> args
;
3774 template <typename T
> auto operator()(T value
) -> iterator
{
3775 return write
<Char
>(out
, value
);
3777 auto operator()(typename basic_format_arg
<context
>::handle h
) -> iterator
{
3778 basic_format_parse_context
<Char
> parse_ctx({});
3779 context
format_ctx(out
, args
, loc
);
3780 h
.format(parse_ctx
, format_ctx
);
3781 return format_ctx
.out();
3785 template <typename Char
> struct arg_formatter
{
3786 using iterator
= buffer_appender
<Char
>;
3787 using context
= buffer_context
<Char
>;
3790 const format_specs
<Char
>& specs
;
3793 template <typename T
>
3794 FMT_CONSTEXPR FMT_INLINE
auto operator()(T value
) -> iterator
{
3795 return detail::write(out
, value
, specs
, locale
);
3797 auto operator()(typename basic_format_arg
<context
>::handle
) -> iterator
{
3798 // User-defined types are handled separately because they require access
3799 // to the parse context.
3804 template <typename Char
> struct custom_formatter
{
3805 basic_format_parse_context
<Char
>& parse_ctx
;
3806 buffer_context
<Char
>& ctx
;
3809 typename basic_format_arg
<buffer_context
<Char
>>::handle h
) const {
3810 h
.format(parse_ctx
, ctx
);
3812 template <typename T
> void operator()(T
) const {}
3815 template <typename ErrorHandler
> class width_checker
{
3817 explicit FMT_CONSTEXPR
width_checker(ErrorHandler
& eh
) : handler_(eh
) {}
3819 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
3820 FMT_CONSTEXPR
auto operator()(T value
) -> unsigned long long {
3821 if (is_negative(value
)) handler_
.on_error("negative width");
3822 return static_cast<unsigned long long>(value
);
3825 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
3826 FMT_CONSTEXPR
auto operator()(T
) -> unsigned long long {
3827 handler_
.on_error("width is not integer");
3832 ErrorHandler
& handler_
;
3835 template <typename ErrorHandler
> class precision_checker
{
3837 explicit FMT_CONSTEXPR
precision_checker(ErrorHandler
& eh
) : handler_(eh
) {}
3839 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
3840 FMT_CONSTEXPR
auto operator()(T value
) -> unsigned long long {
3841 if (is_negative(value
)) handler_
.on_error("negative precision");
3842 return static_cast<unsigned long long>(value
);
3845 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
3846 FMT_CONSTEXPR
auto operator()(T
) -> unsigned long long {
3847 handler_
.on_error("precision is not integer");
3852 ErrorHandler
& handler_
;
3855 template <template <typename
> class Handler
, typename FormatArg
,
3856 typename ErrorHandler
>
3857 FMT_CONSTEXPR
auto get_dynamic_spec(FormatArg arg
, ErrorHandler eh
) -> int {
3858 unsigned long long value
= visit_format_arg(Handler
<ErrorHandler
>(eh
), arg
);
3859 if (value
> to_unsigned(max_value
<int>())) eh
.on_error("number is too big");
3860 return static_cast<int>(value
);
3863 template <typename Context
, typename ID
>
3864 FMT_CONSTEXPR
auto get_arg(Context
& ctx
, ID id
) -> decltype(ctx
.arg(id
)) {
3865 auto arg
= ctx
.arg(id
);
3866 if (!arg
) ctx
.on_error("argument not found");
3870 template <template <typename
> class Handler
, typename Context
>
3871 FMT_CONSTEXPR
void handle_dynamic_spec(int& value
,
3872 arg_ref
<typename
Context::char_type
> ref
,
3875 case arg_id_kind::none
:
3877 case arg_id_kind::index
:
3878 value
= detail::get_dynamic_spec
<Handler
>(get_arg(ctx
, ref
.val
.index
),
3879 ctx
.error_handler());
3881 case arg_id_kind::name
:
3882 value
= detail::get_dynamic_spec
<Handler
>(get_arg(ctx
, ref
.val
.name
),
3883 ctx
.error_handler());
3888 #if FMT_USE_USER_DEFINED_LITERALS
3889 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
3890 template <typename T
, typename Char
, size_t N
,
3891 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3892 struct statically_named_arg
: view
{
3893 static constexpr auto name
= Str
.data
;
3896 statically_named_arg(const T
& v
) : value(v
) {}
3899 template <typename T
, typename Char
, size_t N
,
3900 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3901 struct is_named_arg
<statically_named_arg
<T
, Char
, N
, Str
>> : std::true_type
{};
3903 template <typename T
, typename Char
, size_t N
,
3904 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3905 struct is_statically_named_arg
<statically_named_arg
<T
, Char
, N
, Str
>>
3906 : std::true_type
{};
3908 template <typename Char
, size_t N
,
3909 fmt::detail_exported::fixed_string
<Char
, N
> Str
>
3911 template <typename T
> auto operator=(T
&& value
) const {
3912 return statically_named_arg
<T
, Char
, N
, Str
>(std::forward
<T
>(value
));
3916 template <typename Char
> struct udl_arg
{
3919 template <typename T
> auto operator=(T
&& value
) const -> named_arg
<Char
, T
> {
3920 return {str
, std::forward
<T
>(value
)};
3924 #endif // FMT_USE_USER_DEFINED_LITERALS
3926 template <typename Locale
, typename Char
>
3927 auto vformat(const Locale
& loc
, basic_string_view
<Char
> fmt
,
3928 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
)
3929 -> std::basic_string
<Char
> {
3930 auto buf
= basic_memory_buffer
<Char
>();
3931 detail::vformat_to(buf
, fmt
, args
, detail::locale_ref(loc
));
3932 return {buf
.data(), buf
.size()};
3935 using format_func
= void (*)(detail::buffer
<char>&, int, const char*);
3937 FMT_API
void format_error_code(buffer
<char>& out
, int error_code
,
3938 string_view message
) noexcept
;
3940 FMT_API
void report_error(format_func func
, int error_code
,
3941 const char* message
) noexcept
;
3942 } // namespace detail
3944 FMT_API
auto vsystem_error(int error_code
, string_view format_str
,
3945 format_args args
) -> std::system_error
;
3949 Constructs :class:`std::system_error` with a message formatted with
3950 ``fmt::format(fmt, args...)``.
3951 *error_code* is a system error code as given by ``errno``.
3955 // This throws std::system_error with the description
3956 // cannot open file 'madeup': No such file or directory
3957 // or similar (system message may vary).
3958 const char* filename = "madeup";
3959 std::FILE* file = std::fopen(filename, "r");
3961 throw fmt::system_error(errno, "cannot open file '{}'", filename);
3964 template <typename
... T
>
3965 auto system_error(int error_code
, format_string
<T
...> fmt
, T
&&... args
)
3966 -> std::system_error
{
3967 return vsystem_error(error_code
, fmt
, fmt::make_format_args(args
...));
3972 Formats an error message for an error returned by an operating system or a
3973 language runtime, for example a file opening error, and writes it to *out*.
3974 The format is the same as the one used by ``std::system_error(ec, message)``
3975 where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.
3976 It is implementation-defined but normally looks like:
3979 *<message>*: *<system-message>*
3981 where *<message>* is the passed message and *<system-message>* is the system
3982 message corresponding to the error code.
3983 *error_code* is a system error code as given by ``errno``.
3986 FMT_API
void format_system_error(detail::buffer
<char>& out
, int error_code
,
3987 const char* message
) noexcept
;
3989 // Reports a system error without throwing an exception.
3990 // Can be used to report errors from destructors.
3991 FMT_API
void report_system_error(int error_code
, const char* message
) noexcept
;
3993 /** Fast integer formatter. */
3996 // Buffer should be large enough to hold all digits (digits10 + 1),
3997 // a sign and a null character.
3998 enum { buffer_size
= std::numeric_limits
<unsigned long long>::digits10
+ 3 };
3999 mutable char buffer_
[buffer_size
];
4002 template <typename UInt
> auto format_unsigned(UInt value
) -> char* {
4003 auto n
= static_cast<detail::uint32_or_64_or_128_t
<UInt
>>(value
);
4004 return detail::format_decimal(buffer_
, n
, buffer_size
- 1).begin
;
4007 template <typename Int
> auto format_signed(Int value
) -> char* {
4008 auto abs_value
= static_cast<detail::uint32_or_64_or_128_t
<Int
>>(value
);
4009 bool negative
= value
< 0;
4010 if (negative
) abs_value
= 0 - abs_value
;
4011 auto begin
= format_unsigned(abs_value
);
4012 if (negative
) *--begin
= '-';
4017 explicit format_int(int value
) : str_(format_signed(value
)) {}
4018 explicit format_int(long value
) : str_(format_signed(value
)) {}
4019 explicit format_int(long long value
) : str_(format_signed(value
)) {}
4020 explicit format_int(unsigned value
) : str_(format_unsigned(value
)) {}
4021 explicit format_int(unsigned long value
) : str_(format_unsigned(value
)) {}
4022 explicit format_int(unsigned long long value
)
4023 : str_(format_unsigned(value
)) {}
4025 /** Returns the number of characters written to the output buffer. */
4026 auto size() const -> size_t {
4027 return detail::to_unsigned(buffer_
- str_
+ buffer_size
- 1);
4031 Returns a pointer to the output buffer content. No terminating null
4032 character is appended.
4034 auto data() const -> const char* { return str_
; }
4037 Returns a pointer to the output buffer content with terminating null
4040 auto c_str() const -> const char* {
4041 buffer_
[buffer_size
- 1] = '\0';
4047 Returns the content of the output buffer as an ``std::string``.
4050 auto str() const -> std::string
{ return std::string(str_
, size()); }
4053 template <typename T
, typename Char
>
4054 struct formatter
<T
, Char
, enable_if_t
<detail::has_format_as
<T
>::value
>>
4055 : private formatter
<detail::format_as_t
<T
>, Char
> {
4056 using base
= formatter
<detail::format_as_t
<T
>, Char
>;
4059 template <typename FormatContext
>
4060 auto format(const T
& value
, FormatContext
& ctx
) const -> decltype(ctx
.out()) {
4061 return base::format(format_as(value
), ctx
);
4065 #define FMT_FORMAT_AS(Type, Base) \
4066 template <typename Char> \
4067 struct formatter<Type, Char> : formatter<Base, Char> {}
4069 FMT_FORMAT_AS(signed char, int);
4070 FMT_FORMAT_AS(unsigned char, unsigned);
4071 FMT_FORMAT_AS(short, int);
4072 FMT_FORMAT_AS(unsigned short, unsigned);
4073 FMT_FORMAT_AS(long, detail::long_type
);
4074 FMT_FORMAT_AS(unsigned long, detail::ulong_type
);
4075 FMT_FORMAT_AS(Char
*, const Char
*);
4076 FMT_FORMAT_AS(std::basic_string
<Char
>, basic_string_view
<Char
>);
4077 FMT_FORMAT_AS(std::nullptr_t
, const void*);
4078 FMT_FORMAT_AS(detail::std_string_view
<Char
>, basic_string_view
<Char
>);
4079 FMT_FORMAT_AS(void*, const void*);
4081 template <typename Char
, size_t N
>
4082 struct formatter
<Char
[N
], Char
> : formatter
<basic_string_view
<Char
>, Char
> {};
4086 Converts ``p`` to ``const void*`` for pointer formatting.
4090 auto s = fmt::format("{}", fmt::ptr(p));
4093 template <typename T
> auto ptr(T p
) -> const void* {
4094 static_assert(std::is_pointer
<T
>::value
, "");
4095 return detail::bit_cast
<const void*>(p
);
4097 template <typename T
, typename Deleter
>
4098 auto ptr(const std::unique_ptr
<T
, Deleter
>& p
) -> const void* {
4101 template <typename T
> auto ptr(const std::shared_ptr
<T
>& p
) -> const void* {
4107 Converts ``e`` to the underlying type.
4111 enum class color { red, green, blue };
4112 auto s = fmt::format("{}", fmt::underlying(color::red));
4115 template <typename Enum
>
4116 constexpr auto underlying(Enum e
) noexcept
-> underlying_t
<Enum
> {
4117 return static_cast<underlying_t
<Enum
>>(e
);
4121 template <typename Enum
, FMT_ENABLE_IF(std::is_enum
<Enum
>::value
)>
4122 constexpr auto format_as(Enum e
) noexcept
-> underlying_t
<Enum
> {
4123 return static_cast<underlying_t
<Enum
>>(e
);
4125 } // namespace enums
4130 friend struct formatter
<bytes
>;
4133 explicit bytes(string_view data
) : data_(data
) {}
4136 template <> struct formatter
<bytes
> {
4138 detail::dynamic_format_specs
<> specs_
;
4141 template <typename ParseContext
>
4142 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const char* {
4143 return parse_format_specs(ctx
.begin(), ctx
.end(), specs_
, ctx
,
4144 detail::type::string_type
);
4147 template <typename FormatContext
>
4148 auto format(bytes b
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
4149 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
4150 specs_
.width_ref
, ctx
);
4151 detail::handle_dynamic_spec
<detail::precision_checker
>(
4152 specs_
.precision
, specs_
.precision_ref
, ctx
);
4153 return detail::write_bytes(ctx
.out(), b
.data_
, specs_
);
4157 // group_digits_view is not derived from view because it copies the argument.
4158 template <typename T
> struct group_digits_view
{
4164 Returns a view that formats an integer value using ',' as a locale-independent
4165 thousands separator.
4169 fmt::print("{}", fmt::group_digits(12345));
4173 template <typename T
> auto group_digits(T value
) -> group_digits_view
<T
> {
4177 template <typename T
> struct formatter
<group_digits_view
<T
>> : formatter
<T
> {
4179 detail::dynamic_format_specs
<> specs_
;
4182 template <typename ParseContext
>
4183 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const char* {
4184 return parse_format_specs(ctx
.begin(), ctx
.end(), specs_
, ctx
,
4185 detail::type::int_type
);
4188 template <typename FormatContext
>
4189 auto format(group_digits_view
<T
> t
, FormatContext
& ctx
)
4190 -> decltype(ctx
.out()) {
4191 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
4192 specs_
.width_ref
, ctx
);
4193 detail::handle_dynamic_spec
<detail::precision_checker
>(
4194 specs_
.precision
, specs_
.precision_ref
, ctx
);
4195 return detail::write_int(
4196 ctx
.out(), static_cast<detail::uint64_or_128_t
<T
>>(t
.value
), 0, specs_
,
4197 detail::digit_grouping
<char>("\3", ","));
4201 // DEPRECATED! join_view will be moved to ranges.h.
4202 template <typename It
, typename Sentinel
, typename Char
= char>
4203 struct join_view
: detail::view
{
4206 basic_string_view
<Char
> sep
;
4208 join_view(It b
, Sentinel e
, basic_string_view
<Char
> s
)
4209 : begin(b
), end(e
), sep(s
) {}
4212 template <typename It
, typename Sentinel
, typename Char
>
4213 struct formatter
<join_view
<It
, Sentinel
, Char
>, Char
> {
4216 #ifdef __cpp_lib_ranges
4217 std::iter_value_t
<It
>;
4219 typename
std::iterator_traits
<It
>::value_type
;
4221 formatter
<remove_cvref_t
<value_type
>, Char
> value_formatter_
;
4224 template <typename ParseContext
>
4225 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> const Char
* {
4226 return value_formatter_
.parse(ctx
);
4229 template <typename FormatContext
>
4230 auto format(const join_view
<It
, Sentinel
, Char
>& value
,
4231 FormatContext
& ctx
) const -> decltype(ctx
.out()) {
4232 auto it
= value
.begin
;
4233 auto out
= ctx
.out();
4234 if (it
!= value
.end
) {
4235 out
= value_formatter_
.format(*it
, ctx
);
4237 while (it
!= value
.end
) {
4238 out
= detail::copy_str
<Char
>(value
.sep
.begin(), value
.sep
.end(), out
);
4239 ctx
.advance_to(out
);
4240 out
= value_formatter_
.format(*it
, ctx
);
4249 Returns a view that formats the iterator range `[begin, end)` with elements
4252 template <typename It
, typename Sentinel
>
4253 auto join(It begin
, Sentinel end
, string_view sep
) -> join_view
<It
, Sentinel
> {
4254 return {begin
, end
, sep
};
4259 Returns a view that formats `range` with elements separated by `sep`.
4263 std::vector<int> v = {1, 2, 3};
4264 fmt::print("{}", fmt::join(v, ", "));
4265 // Output: "1, 2, 3"
4267 ``fmt::join`` applies passed format specifiers to the range elements::
4269 fmt::print("{:02}", fmt::join(v, ", "));
4270 // Output: "01, 02, 03"
4273 template <typename Range
>
4274 auto join(Range
&& range
, string_view sep
)
4275 -> join_view
<detail::iterator_t
<Range
>, detail::sentinel_t
<Range
>> {
4276 return join(std::begin(range
), std::end(range
), sep
);
4281 Converts *value* to ``std::string`` using the default format for type *T*.
4285 #include <fmt/format.h>
4287 std::string answer = fmt::to_string(42);
4290 template <typename T
, FMT_ENABLE_IF(!std::is_integral
<T
>::value
&&
4291 !detail::has_format_as
<T
>::value
)>
4292 inline auto to_string(const T
& value
) -> std::string
{
4293 auto buffer
= memory_buffer();
4294 detail::write
<char>(appender(buffer
), value
);
4295 return {buffer
.data(), buffer
.size()};
4298 template <typename T
, FMT_ENABLE_IF(std::is_integral
<T
>::value
)>
4299 FMT_NODISCARD
inline auto to_string(T value
) -> std::string
{
4300 // The buffer should be large enough to store the number including the sign
4301 // or "false" for bool.
4302 constexpr int max_size
= detail::digits10
<T
>() + 2;
4303 char buffer
[max_size
> 5 ? static_cast<unsigned>(max_size
) : 5];
4304 char* begin
= buffer
;
4305 return std::string(begin
, detail::write
<char>(begin
, value
));
4308 template <typename Char
, size_t SIZE
>
4309 FMT_NODISCARD
auto to_string(const basic_memory_buffer
<Char
, SIZE
>& buf
)
4310 -> std::basic_string
<Char
> {
4311 auto size
= buf
.size();
4312 detail::assume(size
< std::basic_string
<Char
>().max_size());
4313 return std::basic_string
<Char
>(buf
.data(), size
);
4316 template <typename T
, FMT_ENABLE_IF(!std::is_integral
<T
>::value
&&
4317 detail::has_format_as
<T
>::value
)>
4318 inline auto to_string(const T
& value
) -> std::string
{
4319 return to_string(format_as(value
));
4326 template <typename Char
>
4327 void vformat_to(buffer
<Char
>& buf
, basic_string_view
<Char
> fmt
,
4328 typename vformat_args
<Char
>::type args
, locale_ref loc
) {
4329 auto out
= buffer_appender
<Char
>(buf
);
4330 if (fmt
.size() == 2 && equal2(fmt
.data(), "{}")) {
4331 auto arg
= args
.get(0);
4332 if (!arg
) error_handler().on_error("argument not found");
4333 visit_format_arg(default_arg_formatter
<Char
>{out
, args
, loc
}, arg
);
4337 struct format_handler
: error_handler
{
4338 basic_format_parse_context
<Char
> parse_context
;
4339 buffer_context
<Char
> context
;
4341 format_handler(buffer_appender
<Char
> p_out
, basic_string_view
<Char
> str
,
4342 basic_format_args
<buffer_context
<Char
>> p_args
,
4344 : parse_context(str
), context(p_out
, p_args
, p_loc
) {}
4346 void on_text(const Char
* begin
, const Char
* end
) {
4347 auto text
= basic_string_view
<Char
>(begin
, to_unsigned(end
- begin
));
4348 context
.advance_to(write
<Char
>(context
.out(), text
));
4351 FMT_CONSTEXPR
auto on_arg_id() -> int {
4352 return parse_context
.next_arg_id();
4354 FMT_CONSTEXPR
auto on_arg_id(int id
) -> int {
4355 return parse_context
.check_arg_id(id
), id
;
4357 FMT_CONSTEXPR
auto on_arg_id(basic_string_view
<Char
> id
) -> int {
4358 int arg_id
= context
.arg_id(id
);
4359 if (arg_id
< 0) on_error("argument not found");
4363 FMT_INLINE
void on_replacement_field(int id
, const Char
*) {
4364 auto arg
= get_arg(context
, id
);
4365 context
.advance_to(visit_format_arg(
4366 default_arg_formatter
<Char
>{context
.out(), context
.args(),
4371 auto on_format_specs(int id
, const Char
* begin
, const Char
* end
)
4373 auto arg
= get_arg(context
, id
);
4374 if (arg
.type() == type::custom_type
) {
4375 parse_context
.advance_to(begin
);
4376 visit_format_arg(custom_formatter
<Char
>{parse_context
, context
}, arg
);
4377 return parse_context
.begin();
4379 auto specs
= detail::dynamic_format_specs
<Char
>();
4380 begin
= parse_format_specs(begin
, end
, specs
, parse_context
, arg
.type());
4381 detail::handle_dynamic_spec
<detail::width_checker
>(
4382 specs
.width
, specs
.width_ref
, context
);
4383 detail::handle_dynamic_spec
<detail::precision_checker
>(
4384 specs
.precision
, specs
.precision_ref
, context
);
4385 if (begin
== end
|| *begin
!= '}')
4386 on_error("missing '}' in format string");
4387 auto f
= arg_formatter
<Char
>{context
.out(), specs
, context
.locale()};
4388 context
.advance_to(visit_format_arg(f
, arg
));
4392 detail::parse_format_string
<false>(fmt
, format_handler(out
, fmt
, args
, loc
));
4397 #ifndef FMT_HEADER_ONLY
4398 extern template FMT_API
void vformat_to(buffer
<char>&, string_view
,
4399 typename vformat_args
<>::type
,
4401 extern template FMT_API
auto thousands_sep_impl
<char>(locale_ref
)
4402 -> thousands_sep_result
<char>;
4403 extern template FMT_API
auto thousands_sep_impl
<wchar_t>(locale_ref
)
4404 -> thousands_sep_result
<wchar_t>;
4405 extern template FMT_API
auto decimal_point_impl(locale_ref
) -> char;
4406 extern template FMT_API
auto decimal_point_impl(locale_ref
) -> wchar_t;
4407 #endif // FMT_HEADER_ONLY
4409 } // namespace detail
4411 #if FMT_USE_USER_DEFINED_LITERALS
4412 inline namespace literals
{
4415 User-defined literal equivalent of :func:`fmt::arg`.
4419 using namespace fmt::literals;
4420 fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
4423 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
4424 template <detail_exported::fixed_string Str
> constexpr auto operator""_a() {
4425 using char_t
= remove_cvref_t
<decltype(Str
.data
[0])>;
4426 return detail::udl_arg
<char_t
, sizeof(Str
.data
) / sizeof(char_t
), Str
>();
4429 constexpr auto operator"" _a(const char* s
, size_t) -> detail::udl_arg
<char> {
4433 } // namespace literals
4434 #endif // FMT_USE_USER_DEFINED_LITERALS
4436 template <typename Locale
, FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4437 inline auto vformat(const Locale
& loc
, string_view fmt
, format_args args
)
4439 return detail::vformat(loc
, fmt
, args
);
4442 template <typename Locale
, typename
... T
,
4443 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4444 inline auto format(const Locale
& loc
, format_string
<T
...> fmt
, T
&&... args
)
4446 return fmt::vformat(loc
, string_view(fmt
), fmt::make_format_args(args
...));
4449 template <typename OutputIt
, typename Locale
,
4450 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
&&
4451 detail::is_locale
<Locale
>::value
)>
4452 auto vformat_to(OutputIt out
, const Locale
& loc
, string_view fmt
,
4453 format_args args
) -> OutputIt
{
4454 using detail::get_buffer
;
4455 auto&& buf
= get_buffer
<char>(out
);
4456 detail::vformat_to(buf
, fmt
, args
, detail::locale_ref(loc
));
4457 return detail::get_iterator(buf
, out
);
4460 template <typename OutputIt
, typename Locale
, typename
... T
,
4461 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
, char>::value
&&
4462 detail::is_locale
<Locale
>::value
)>
4463 FMT_INLINE
auto format_to(OutputIt out
, const Locale
& loc
,
4464 format_string
<T
...> fmt
, T
&&... args
) -> OutputIt
{
4465 return vformat_to(out
, loc
, fmt
, fmt::make_format_args(args
...));
4468 template <typename Locale
, typename
... T
,
4469 FMT_ENABLE_IF(detail::is_locale
<Locale
>::value
)>
4470 FMT_NODISCARD FMT_INLINE
auto formatted_size(const Locale
& loc
,
4471 format_string
<T
...> fmt
,
4472 T
&&... args
) -> size_t {
4473 auto buf
= detail::counting_buffer
<>();
4474 detail::vformat_to
<char>(buf
, fmt
, fmt::make_format_args(args
...),
4475 detail::locale_ref(loc
));
4481 template <typename T
, typename Char
>
4482 template <typename FormatContext
>
4483 FMT_CONSTEXPR FMT_INLINE
auto
4485 enable_if_t
<detail::type_constant
<T
, Char
>::value
!=
4486 detail::type::custom_type
>>::format(const T
& val
,
4488 const -> decltype(ctx
.out()) {
4489 if (specs_
.width_ref
.kind
!= detail::arg_id_kind::none
||
4490 specs_
.precision_ref
.kind
!= detail::arg_id_kind::none
) {
4491 auto specs
= specs_
;
4492 detail::handle_dynamic_spec
<detail::width_checker
>(specs
.width
,
4493 specs
.width_ref
, ctx
);
4494 detail::handle_dynamic_spec
<detail::precision_checker
>(
4495 specs
.precision
, specs
.precision_ref
, ctx
);
4496 return detail::write
<Char
>(ctx
.out(), val
, specs
, ctx
.locale());
4498 return detail::write
<Char
>(ctx
.out(), val
, specs_
, ctx
.locale());
4503 #ifdef FMT_HEADER_ONLY
4504 # define FMT_FUNC inline
4505 # include "format-inl.h"
4510 #endif // FMT_FORMAT_H_