39 #include <initializer_list>
43 #include <system_error>
45 #ifdef __cpp_lib_bit_cast
51 #if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
52 # define FMT_INLINE_VARIABLE inline
54 # define FMT_INLINE_VARIABLE
57 #if FMT_HAS_CPP17_ATTRIBUTE(fallthrough)
58 # define FMT_FALLTHROUGH [[fallthrough]]
59 #elif defined(__clang__)
60 # define FMT_FALLTHROUGH [[clang::fallthrough]]
61 #elif FMT_GCC_VERSION >= 700 && \
62 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
63 # define FMT_FALLTHROUGH [[gnu::fallthrough]]
65 # define FMT_FALLTHROUGH
68 #ifndef FMT_DEPRECATED
69 # if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900
70 # define FMT_DEPRECATED [[deprecated]]
72 # if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
73 # define FMT_DEPRECATED __attribute__((deprecated))
74 # elif FMT_MSC_VERSION
75 # define FMT_DEPRECATED __declspec(deprecated)
77 # define FMT_DEPRECATED
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]]
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
97 #if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED)
98 # define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value)
100 # define FMT_SO_VISIBILITY(value)
104 # define FMT_HAS_BUILTIN(x) __has_builtin(x)
106 # define FMT_HAS_BUILTIN(x) 0
109 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
110 # define FMT_NOINLINE __attribute__((noinline))
112 # define FMT_NOINLINE
117 # if FMT_MSC_VERSION || defined(__NVCC__)
120 template <
typename Exception>
inline void do_throw(
const Exception&
x) {
123 volatile bool b =
true;
128 # define FMT_THROW(x) detail::do_throw(x)
130 # define FMT_THROW(x) throw x
133 # define FMT_THROW(x) \
134 ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
140 # define FMT_CATCH(x) catch (x)
142 # define FMT_TRY if (true)
143 # define FMT_CATCH(x) if (false)
146 #ifndef FMT_MAYBE_UNUSED
147 # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
148 # define FMT_MAYBE_UNUSED [[maybe_unused]]
150 # define FMT_MAYBE_UNUSED
154 #ifndef FMT_USE_USER_DEFINED_LITERALS
159 # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \
160 FMT_MSC_VERSION >= 1900) && \
161 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 480)
162 # define FMT_USE_USER_DEFINED_LITERALS 1
164 # define FMT_USE_USER_DEFINED_LITERALS 0
172 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
173 # define FMT_REDUCE_INT_INSTANTIATIONS 0
179 # if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
180 # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
182 # if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
183 # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
190 # if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
191 defined(__NVCOMPILER)
192 # define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
194 # if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
195 FMT_ICC_VERSION || defined(__NVCOMPILER)
196 # define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
207 #if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
208 !defined(FMT_BUILTIN_CTZLL)
212 # if !defined(__clang__)
213 # pragma intrinsic(_BitScanForward)
214 # pragma intrinsic(_BitScanReverse)
216 # pragma intrinsic(_BitScanForward64)
217 # pragma intrinsic(_BitScanReverse64)
221 inline auto clz(uint32_t
x) ->
int {
223 _BitScanReverse(&r,
x);
229 return 31 ^
static_cast<int>(r);
231 # define FMT_BUILTIN_CLZ(n) detail::clz(n)
233 inline auto clzll(uint64_t
x) ->
int {
236 _BitScanReverse64(&r,
x);
239 if (_BitScanReverse(&r,
static_cast<uint32_t
>(
x >> 32)))
240 return 63 ^
static_cast<int>(r + 32);
242 _BitScanReverse(&r,
static_cast<uint32_t
>(
x));
246 return 63 ^
static_cast<int>(r);
248 # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
250 inline auto ctz(uint32_t
x) ->
int {
252 _BitScanForward(&r,
x);
255 return static_cast<int>(r);
257 # define FMT_BUILTIN_CTZ(n) detail::ctz(n)
259 inline auto ctzll(uint64_t
x) ->
int {
264 _BitScanForward64(&r,
x);
267 if (_BitScanForward(&r,
static_cast<uint32_t
>(
x)))
return static_cast<int>(r);
269 _BitScanForward(&r,
static_cast<uint32_t
>(
x >> 32));
272 return static_cast<int>(r);
274 # define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
285 if (condition)
throw std::runtime_error(
"fuzzing limit reached");
290 static constexpr CharT
value[
sizeof...(C)] = {
C...};
292 return {
value,
sizeof...(C)};
296 #if FMT_CPLUSPLUS < 201703L
297 template <
typename CharT, CharT...
C>
298 constexpr CharT string_literal<CharT,
C...>::value[
sizeof...(C)];
302 template <
typename To,
typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))>
304 #ifdef __cpp_lib_bit_cast
309 std::memcpy(
static_cast<void*
>(&to), &from,
sizeof(to));
316 #elif defined(__BIG_ENDIAN__)
318 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
319 return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
324 return bit_cast<bytes>(1).data[0] == 0;
336 constexpr
auto high() const noexcept -> uint64_t {
return hi_; }
337 constexpr
auto low() const noexcept -> uint64_t {
return lo_; }
339 template <
typename T, FMT_ENABLE_IF(std::is_
integral<T>::value)>
340 constexpr
explicit operator T()
const {
341 return static_cast<T
>(
lo_);
346 return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
350 return !(lhs == rhs);
354 return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
359 return {lhs.
hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
364 return {lhs.
hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
368 return {~n.
hi_, ~n.lo_};
379 uint64_t hi = (lhs.lo_ >> 32) * rhs;
380 uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
381 uint64_t new_lo = (hi << 32) + lo;
382 return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
386 return {lhs.
hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
389 if (shift == 64)
return {0,
hi_};
391 return {
hi_ >> shift, (
hi_ << (64 - shift)) | (
lo_ >> shift)};
394 if (shift == 64)
return {
lo_, 0};
396 return {
hi_ << shift | (
lo_ >> (64 - shift)), (
lo_ << shift)};
399 return *
this = *
this >> shift;
402 uint64_t new_lo =
lo_ + n.
lo_;
403 uint64_t new_hi =
hi_ + n.
hi_ + (new_lo <
lo_ ? 1 : 0);
419 #if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
420 unsigned long long carry;
421 lo_ = __builtin_addcll(
lo_, n, 0, &carry);
423 #elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
424 unsigned long long result;
425 auto carry = __builtin_ia32_addcarryx_u64(0,
lo_, n, &result);
428 #elif defined(_MSC_VER) && defined(_M_X64)
429 auto carry = _addcarry_u64(0,
lo_, n, &
lo_);
430 _addcarry_u64(carry,
hi_, 0, &
hi_);
450 return (std::numeric_limits<T>::max)();
452 template <
typename T> constexpr
auto num_bits() ->
int {
453 return std::numeric_limits<T>::digits;
461 template <
typename To,
typename From, FMT_ENABLE_IF(sizeof(To) >
sizeof(From))>
463 constexpr
auto size =
static_cast<int>(
sizeof(From) /
sizeof(
unsigned));
465 unsigned value[
static_cast<unsigned>(
size)];
466 }
data = bit_cast<data_t>(from);
469 for (
int i = 0; i <
size; ++i)
470 result = (result << num_bits<unsigned>()) |
data.value[i];
472 for (
int i =
size - 1; i >= 0; --i)
473 result = (result << num_bits<unsigned>()) |
data.value[i];
478 template <
typename UInt>
481 constexpr UInt msb_mask =
static_cast<UInt
>(1) << (num_bits<UInt>() - 1);
482 for (; (n & msb_mask) == 0; n <<= 1) lz++;
487 #ifdef FMT_BUILTIN_CLZ
494 #ifdef FMT_BUILTIN_CLZLL
502 #if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
503 __builtin_assume(condition);
504 #elif FMT_GCC_VERSION
505 if (!condition) __builtin_unreachable();
510 template <
typename T>
512 template <
typename T>
using sentinel_t = decltype(std::end(std::declval<T&>()));
515 template <
typename Char>
516 inline auto get_data(std::basic_string<Char>& s) -> Char* {
519 template <
typename Container>
520 inline auto get_data(Container& c) ->
typename Container::value_type* {
526 template <
typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
527 #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
528 __attribute__((no_sanitize(
"undefined")))
531 reserve(std::back_insert_iterator<Container> it,
size_t n) ->
532 typename Container::value_type* {
534 size_t size = c.size();
539 template <
typename T>
546 template <
typename Iterator>
547 constexpr
auto reserve(Iterator& it,
size_t) -> Iterator& {
551 template <
typename OutputIt>
555 template <
typename T,
typename OutputIt>
567 template <
typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
569 typename Container::value_type*)
570 -> std::back_insert_iterator<Container> {
574 template <
typename Iterator>
581 template <
typename OutputIt,
typename Size,
typename T>
584 for (Size i = 0; i <
count; ++i) *out++ =
value;
587 template <
typename T,
typename Size>
590 return fill_n<T*, Size, T>(out,
count,
value);
602 template <
typename OutChar,
typename InputIt,
typename OutputIt>
604 OutputIt out) -> OutputIt {
605 return copy_str<OutChar>(begin, end, out);
627 constexpr
const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
628 constexpr
const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
629 constexpr
const int shiftc[] = {0, 18, 12, 6, 0};
630 constexpr
const int shifte[] = {0, 6, 4, 2, 0};
632 int len =
"\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"
633 [
static_cast<unsigned char>(*s) >> 3];
637 const char*
next =
s + len + !len;
639 using uchar =
unsigned char;
643 *c = uint32_t(
uchar(
s[0]) & masks[len]) << 18;
644 *c |= uint32_t(
uchar(
s[1]) & 0x3f) << 12;
645 *c |= uint32_t(
uchar(
s[2]) & 0x3f) << 6;
646 *c |= uint32_t(
uchar(
s[3]) & 0x3f) << 0;
650 *e = (*c < mins[len]) << 6;
651 *e |= ((*c >> 11) == 0x1b) << 7;
652 *e |= (*c > 0x10FFFF) << 8;
653 *e |= (
uchar(
s[1]) & 0xc0) >> 2;
654 *e |= (
uchar(
s[2]) & 0xc0) >> 4;
666 template <
typename F>
668 auto decode = [
f](
const char* buf_ptr,
const char*
ptr) {
669 auto cp = uint32_t();
674 return result ? (error ? buf_ptr + 1 : end) :
nullptr;
677 const size_t block_size = 4;
678 if (
s.size() >= block_size) {
679 for (
auto end = p +
s.size() - block_size + 1; p < end;) {
684 if (
auto num_chars_left =
s.data() +
s.size() - p) {
685 char buf[2 * block_size - 1] = {};
686 copy_str<char>(p, p + num_chars_left, buf);
687 const char* buf_ptr = buf;
689 auto end = decode(buf_ptr, p);
693 }
while (buf_ptr - buf < num_chars_left);
697 template <
typename Char>
704 size_t num_code_points = 0;
706 struct count_code_points {
716 (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
717 (cp >= 0xac00 && cp <= 0xd7a3) ||
718 (cp >= 0xf900 && cp <= 0xfaff) ||
719 (cp >= 0xfe10 && cp <= 0xfe19) ||
720 (cp >= 0xfe30 && cp <= 0xfe6f) ||
721 (cp >= 0xff00 && cp <= 0xff60) ||
722 (cp >= 0xffe0 && cp <= 0xffe6) ||
723 (cp >= 0x20000 && cp <= 0x2fffd) ||
724 (cp >= 0x30000 && cp <= 0x3fffd) ||
726 (cp >= 0x1f300 && cp <= 0x1f64f) ||
728 (cp >= 0x1f900 && cp <= 0x1f9ff))));
734 return num_code_points;
739 string_view(
reinterpret_cast<const char*
>(
s.data()),
s.size()));
742 template <
typename Char>
744 size_t size =
s.size();
750 size_t result =
s.size();
751 const char* begin =
s.begin();
766 string_view(
reinterpret_cast<const char*
>(
s.data()),
s.size()), n);
769 template <
typename T>
struct is_integral : std::is_integral<T> {};
773 template <
typename T>
776 std::is_same<T, int128_opt>::value>;
778 template <
typename T>
781 !std::is_same<T, char>::value &&
782 !std::is_same<T, wchar_t>::value>;
784 #ifndef FMT_USE_FLOAT
785 # define FMT_USE_FLOAT 1
787 #ifndef FMT_USE_DOUBLE
788 # define FMT_USE_DOUBLE 1
790 #ifndef FMT_USE_LONG_DOUBLE
791 # define FMT_USE_LONG_DOUBLE 1
794 #ifndef FMT_USE_FLOAT128
797 # if FMT_HAS_INCLUDE(<quadmath.h>)
798 # define FMT_USE_FLOAT128 1
800 # elif defined(__GNUC__)
802 # if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
803 # define FMT_USE_FLOAT128 1
806 # ifndef FMT_USE_FLOAT128
807 # define FMT_USE_FLOAT128 0
816 template <
typename T>
using is_float128 = std::is_same<T, float128>;
818 template <
typename T>
822 template <typename T, bool = std::is_floating_point<T>::value>
823 struct is_fast_float :
bool_constant<std::numeric_limits<T>::is_iec559 &&
824 sizeof(T) <= sizeof(double)> {};
825 template <typename T> struct is_fast_float<T, false> : std::false_type {};
827 template <typename T>
828 using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
830 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
831 # define FMT_USE_FULL_CACHE_DRAGONBOX 0
834 template <typename T>
835 template <typename U>
836 void buffer<T>::append(const U* begin, const U* end) {
837 while (begin != end) {
838 auto count = to_unsigned(end - begin);
839 try_reserve(size_ + count);
840 auto free_cap = capacity_ - size_;
841 if (free_cap < count) count = free_cap;
842 std::uninitialized_copy_n(begin, count, ptr_ + size_);
848 template <typename T, typename Enable = void>
849 struct is_locale : std::false_type {};
850 template <typename T>
851 struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
858 enum { inline_buffer_size = 500 };
881 template <typename T, size_t SIZE = inline_buffer_size,
882 typename Allocator = std::allocator<T>>
883 class basic_memory_buffer final : public detail::buffer<T> {
888 FMT_NO_UNIQUE_ADDRESS Allocator alloc_;
891 FMT_CONSTEXPR20 void deallocate() {
892 T* data = this->data();
893 if (data != store_) alloc_.deallocate(data, this->capacity());
899 const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
900 size_t old_capacity = this->capacity();
901 size_t new_capacity = old_capacity + old_capacity / 2;
902 if (
size > new_capacity)
904 else if (new_capacity > max_size)
905 new_capacity =
size > max_size ?
size : max_size;
906 T* old_data = this->
data();
908 std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
912 std::uninitialized_copy_n(old_data, this->
size(), new_data);
913 this->
set(new_data, new_capacity);
917 if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
925 const Allocator& alloc = Allocator())
927 this->
set(store_, SIZE);
939 this->
set(store_, capacity);
942 this->
set(data, capacity);
984 void reserve(
size_t new_capacity) { this->try_reserve(new_capacity); }
987 template <
typename ContiguousRange>
988 void append(
const ContiguousRange& range) {
989 append(range.data(), range.data() + range.size());
995 template <
typename T,
size_t SIZE,
typename Allocator>
1009 #if FMT_CLANG_VERSION
1010 # pragma clang diagnostic ignored "-Wweak-vtables"
1016 using std::runtime_error::runtime_error;
1020 #if FMT_USE_NONTYPE_TEMPLATE_ARGS
1021 template <
typename Char,
size_t N>
struct fixed_string {
1022 constexpr fixed_string(
const Char (&str)[N]) {
1023 detail::copy_str<Char, const Char*, Char*>(
static_cast<const Char*
>(str),
1031 template <
typename Char,
size_t N>
1036 return {
s, N - (std::char_traits<Char>::to_int_type(
s[N - 1]) == 0 ? 1 : 0)};
1038 template <
typename Char>
1041 return {
s.data(),
s.size()};
1050 template <
typename T, FMT_ENABLE_IF(!detail::is_
float128<T>::value)>
1053 template <
typename T, FMT_ENABLE_IF(detail::is_
float128<T>::value)>
1056 template <
typename Visitor>
auto visit(Visitor&& vis) -> decltype(vis(0)) {
1078 std::initializer_list<unsigned char> g = {3},
1086 return do_put(out, val, specs);
1094 template <
typename T, FMT_ENABLE_IF(is_
signed<T>::value)>
1098 template <
typename T, FMT_ENABLE_IF(!is_
signed<T>::value)>
1103 template <
typename T>
1113 template <
typename T>
1118 template <
typename T>
1121 #define FMT_POWERS_OF_10(factor) \
1122 factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \
1123 (factor) * 100000, (factor) * 1000000, (factor) * 10000000, \
1124 (factor) * 100000000, (factor) * 1000000000
1129 return &
"0001020304050607080910111213141516171819"
1130 "2021222324252627282930313233343536373839"
1131 "4041424344454647484950515253545556575859"
1132 "6061626364656667686970717273747576777879"
1133 "8081828384858687888990919293949596979899"[
value * 2];
1137 template <
typename Char,
typename Sign> constexpr
auto sign(Sign s) -> Char {
1138 #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1139 static_assert(std::is_same<Sign, sign_t>::value,
"");
1141 return static_cast<Char
>(
"\0-+ "[
s]);
1150 if (n < 10)
return count;
1151 if (n < 100)
return count + 1;
1152 if (n < 1000)
return count + 2;
1153 if (n < 10000)
return count + 3;
1164 #ifdef FMT_BUILTIN_CLZLL
1167 inline auto do_count_digits(uint64_t n) ->
int {
1172 static constexpr uint8_t bsr2log10[] = {
1173 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1174 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1175 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1176 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1177 auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
1178 static constexpr
const uint64_t zero_or_powers_of_10[] = {
1180 10000000000000000000ULL};
1181 return t - (n < zero_or_powers_of_10[t]);
1188 #ifdef FMT_BUILTIN_CLZLL
1190 return do_count_digits(n);
1197 template <
int BITS,
typename UInt>
1199 #ifdef FMT_BUILTIN_CLZ
1201 return (FMT_BUILTIN_CLZ(
static_cast<uint32_t
>(n) | 1) ^ 31) / BITS + 1;
1208 }
while ((m >>= BITS) != 0);
1213 #ifdef FMT_BUILTIN_CLZ
1216 FMT_INLINE auto do_count_digits(uint32_t n) ->
int {
1219 # define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1220 static constexpr uint64_t table[] = {
1221 FMT_INC(0), FMT_INC(0), FMT_INC(0),
1222 FMT_INC(10), FMT_INC(10), FMT_INC(10),
1223 FMT_INC(100), FMT_INC(100), FMT_INC(100),
1224 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000),
1225 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000),
1226 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000),
1227 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000),
1228 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000),
1229 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000),
1230 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000),
1231 FMT_INC(1000000000), FMT_INC(1000000000)
1233 auto inc =
table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
1234 return static_cast<int>((n + inc) >> 32);
1240 #ifdef FMT_BUILTIN_CLZ
1242 return do_count_digits(n);
1248 template <
typename Int> constexpr
auto digits10() noexcept ->
int {
1259 template <
typename Char>
1261 template <
typename Char>
1264 return {result.grouping, Char(result.thousands_sep)};
1271 template <
typename Char>
1274 return Char(decimal_point_impl<char>(loc));
1277 return decimal_point_impl<wchar_t>(loc);
1281 template <
typename Char>
auto equal2(
const Char* lhs,
const char* rhs) ->
bool {
1282 return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1284 inline auto equal2(
const char* lhs,
const char* rhs) ->
bool {
1285 return memcmp(lhs, rhs, 2) == 0;
1289 template <
typename Char>
1292 memcpy(
dst, src, 2);
1295 *
dst++ =
static_cast<Char
>(*src++);
1296 *
dst =
static_cast<Char
>(*src);
1307 template <
typename Char,
typename UInt>
1313 while (
value >= 100) {
1322 *--out =
static_cast<Char
>(
'0' +
value);
1330 template <
typename Char,
typename UInt,
typename Iterator,
1335 Char
buffer[digits10<UInt>() + 1] = {};
1337 return {out, detail::copy_str_noinline<Char>(
buffer, end, out)};
1340 template <
unsigned BASE_BITS,
typename Char,
typename UInt>
1342 bool upper =
false) -> Char* {
1346 const char* digits = upper ?
"0123456789ABCDEF" :
"0123456789abcdef";
1347 unsigned digit =
static_cast<unsigned>(
value & ((1 << BASE_BITS) - 1));
1348 *--
buffer =
static_cast<Char
>(BASE_BITS < 4 ? static_cast<char>(
'0' +
digit)
1350 }
while ((
value >>= BASE_BITS) != 0);
1354 template <
unsigned BASE_BITS,
typename Char,
typename It,
typename UInt>
1356 bool upper =
false) -> It {
1358 format_uint<BASE_BITS>(
ptr,
value, num_digits, upper);
1362 char buffer[num_bits<UInt>() / BASE_BITS + 1] = {};
1363 format_uint<BASE_BITS>(
buffer,
value, num_digits, upper);
1364 return detail::copy_str_noinline<Char>(
buffer,
buffer + num_digits, out);
1383 template <
typename WChar,
typename Buffer = memory_buffer>
class to_utf8 {
1391 static_assert(
sizeof(WChar) == 2 ||
sizeof(WChar) == 4,
1392 "Expect utf16 or utf32");
1394 FMT_THROW(std::runtime_error(
sizeof(WChar) == 2 ?
"invalid utf16"
1395 :
"invalid utf32"));
1415 for (
auto p =
s.begin(); p !=
s.end(); ++p) {
1416 uint32_t c =
static_cast<uint32_t
>(*p);
1417 if (
sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) {
1420 if (p ==
s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
1425 c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
1427 }
else if (c < 0x80) {
1428 buf.push_back(
static_cast<char>(c));
1429 }
else if (c < 0x800) {
1430 buf.push_back(
static_cast<char>(0xc0 | (c >> 6)));
1431 buf.push_back(
static_cast<char>(0x80 | (c & 0x3f)));
1432 }
else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
1433 buf.push_back(
static_cast<char>(0xe0 | (c >> 12)));
1434 buf.push_back(
static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1435 buf.push_back(
static_cast<char>(0x80 | (c & 0x3f)));
1436 }
else if (c >= 0x10000 && c <= 0x10ffff) {
1437 buf.push_back(
static_cast<char>(0xf0 | (c >> 18)));
1438 buf.push_back(
static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
1439 buf.push_back(
static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1440 buf.push_back(
static_cast<char>(0x80 | (c & 0x3f)));
1453 return {
static_cast<uint64_t
>(p >> 64),
static_cast<uint64_t
>(p)};
1454 #elif defined(_MSC_VER) && defined(_M_X64)
1455 auto hi = uint64_t();
1456 auto lo = _umul128(
x,
y, &hi);
1459 const uint64_t mask =
static_cast<uint64_t
>(max_value<uint32_t>());
1461 uint64_t a =
x >> 32;
1462 uint64_t b =
x & mask;
1463 uint64_t c =
y >> 32;
1464 uint64_t
d =
y & mask;
1466 uint64_t ac = a * c;
1467 uint64_t bc = b * c;
1468 uint64_t ad = a *
d;
1469 uint64_t bd = b *
d;
1471 uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
1473 return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
1474 (intermediate << 32) + (bd & mask)};
1478 namespace dragonbox {
1482 FMT_ASSERT(e <= 2620 && e >= -2620,
"too large exponent");
1483 static_assert((-1 >> 1) == -1,
"right shift is not arithmetic");
1484 return (e * 315653) >> 20;
1488 FMT_ASSERT(e <= 1233 && e >= -1233,
"too large exponent");
1489 return (e * 1741647) >> 19;
1496 return static_cast<uint64_t
>(p >> 64);
1497 #elif defined(_MSC_VER) && defined(_M_X64)
1498 return __umulh(
x,
y);
1520 static const int exponent_bits = 8;
1521 static const int kappa = 1;
1522 static const int big_divisor = 100;
1523 static const int small_divisor = 10;
1524 static const int min_k = -31;
1525 static const int max_k = 46;
1526 static const int shorter_interval_tie_lower_threshold = -35;
1527 static const int shorter_interval_tie_upper_threshold = -35;
1532 static const int exponent_bits = 11;
1533 static const int kappa = 2;
1534 static const int big_divisor = 1000;
1535 static const int small_divisor = 100;
1536 static const int min_k = -292;
1537 static const int max_k = 341;
1538 static const int shorter_interval_tie_lower_threshold = -77;
1539 static const int shorter_interval_tie_upper_threshold = -77;
1543 template <
typename T>
1545 std::numeric_limits<T>::digits == 113 ||
1548 static const int exponent_bits = 15;
1552 template <
typename T>
1569 return std::numeric_limits<Float>::digits != 64;
1577 : (std::numeric_limits<Float>::digits -
1578 (has_implicit_bit<Float>() ? 1 : 0));
1581 template <
typename Float>
1586 << num_significand_bits<Float>();
1591 : std::numeric_limits<Float>::max_exponent - 1;
1595 template <
typename Char,
typename It>
1599 *it++ =
static_cast<Char
>(
'-');
1602 *it++ =
static_cast<Char
>(
'+');
1606 if (
exp >= 1000) *it++ =
static_cast<Char
>(
top[0]);
1607 *it++ =
static_cast<Char
>(
top[1]);
1611 *it++ =
static_cast<Char
>(
d[0]);
1612 *it++ =
static_cast<Char
>(
d[1]);
1622 static_cast<int>(
sizeof(F) * num_bits<unsigned char>());
1625 constexpr
basic_fp(uint64_t f_val,
int e_val) :
f(f_val),
e(e_val) {}
1631 template <
typename Float, FMT_ENABLE_IF(!is_
double_
double<Float>::value)>
1633 static_assert(std::numeric_limits<Float>::digits <= 113,
"unsupported FP");
1636 const auto num_float_significand_bits =
1637 detail::num_significand_bits<Float>();
1638 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
1639 const auto significand_mask = implicit_bit - 1;
1640 auto u = bit_cast<carrier_uint>(n);
1641 f =
static_cast<F
>(u & significand_mask);
1642 auto biased_e =
static_cast<int>((u & exponent_mask<Float>()) >>
1643 num_float_significand_bits);
1646 auto is_predecessor_closer =
f == 0 && biased_e > 1;
1649 else if (has_implicit_bit<Float>())
1650 f +=
static_cast<F
>(implicit_bit);
1651 e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
1652 if (!has_implicit_bit<Float>()) ++
e;
1653 return is_predecessor_closer;
1656 template <
typename Float, FMT_ENABLE_IF(is_
double_
double<Float>::value)>
1658 static_assert(std::numeric_limits<double>::is_iec559,
"unsupported FP");
1659 return assign(
static_cast<double>(n));
1666 template <
int SHIFT = 0,
typename F>
1669 const auto implicit_bit = F(1) << num_significand_bits<double>();
1670 const auto shifted_implicit_bit = implicit_bit << SHIFT;
1671 while ((
value.f & shifted_implicit_bit) == 0) {
1677 num_significand_bits<double>() - SHIFT - 1;
1686 auto product =
static_cast<__uint128_t
>(lhs) * rhs;
1687 auto f =
static_cast<uint64_t
>(product >> 64);
1688 return (
static_cast<uint64_t
>(product) & (1ULL << 63)) != 0 ?
f + 1 :
f;
1691 uint64_t mask = (1ULL << 32) - 1;
1692 uint64_t a = lhs >> 32, b = lhs & mask;
1693 uint64_t c = rhs >> 32,
d = rhs & mask;
1694 uint64_t ac = a * c, bc = b * c, ad = a *
d, bd = b *
d;
1696 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
1697 return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
1705 template <typename T, bool doublish = num_bits<T>() == num_bits<double>()>
1709 template <
typename T>
1714 template <
typename OutputIt,
typename Char>
1717 auto fill_size =
fill.size();
1720 for (
size_t i = 0; i < n; ++i)
1721 it = copy_str<Char>(
data,
data + fill_size, it);
1728 template <align::type
align =
align::left,
typename OutputIt,
typename Char,
1731 size_t size,
size_t width, F&& f) -> OutputIt {
1734 size_t padding = spec_width >
width ? spec_width -
width : 0;
1737 auto* shifts =
align ==
align::left ?
"\x1f\x1f\x00\x01" :
"\x00\x1f\x00\x01";
1738 size_t left_padding = padding >> shifts[specs.align];
1739 size_t right_padding = padding - left_padding;
1740 auto it =
reserve(out,
size + padding * specs.fill.size());
1741 if (left_padding != 0) it =
fill(it, left_padding, specs.fill);
1743 if (right_padding != 0) it =
fill(it, right_padding, specs.fill);
1747 template <align::type
align =
align::left,
typename OutputIt,
typename Char,
1750 size_t size, F&& f) -> OutputIt {
1751 return write_padded<align>(out, specs,
size,
size,
f);
1754 template <align::type align = align::left,
typename Char,
typename OutputIt>
1757 return write_padded<align>(
1759 const char* data = bytes.data();
1760 return copy_str<Char>(data, data + bytes.size(), it);
1764 template <
typename Char,
typename OutputIt,
typename UIntPtr>
1767 int num_digits = count_digits<4>(
value);
1770 *it++ =
static_cast<Char
>(
'0');
1771 *it++ =
static_cast<Char
>(
'x');
1772 return format_uint<4, Char>(it,
value, num_digits);
1774 return specs ? write_padded<align::right>(out, *specs,
size,
write)
1782 return cp < 0x20 || cp == 0x7f || cp ==
'"' || cp ==
'\\' ||
1792 template <
typename Char>
1795 std::make_unsigned<Char>,
1798 template <
typename Char>
1801 for (; begin != end; ++begin) {
1803 if (
const_check(
sizeof(Char) == 1) && cp >= 0x80)
continue;
1806 return {begin,
nullptr, 0};
1811 if (!
is_utf8())
return find_escape<char>(begin, end);
1816 result = {sv.
begin(), sv.
end(), cp};
1824 #define FMT_STRING_IMPL(s, base, explicit) \
1828 struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
1829 using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1830 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1831 operator fmt::basic_string_view<char_type>() const { \
1832 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1835 return FMT_COMPILE_STRING(); \
1848 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1850 template <
size_t w
idth,
typename Char,
typename OutputIt>
1852 *out++ =
static_cast<Char
>(
'\\');
1853 *out++ =
static_cast<Char
>(prefix);
1856 format_uint<4>(buf, cp,
width);
1857 return copy_str<Char>(buf, buf +
width, out);
1860 template <
typename OutputIt,
typename Char>
1863 auto c =
static_cast<Char
>(
escape.cp);
1866 *out++ =
static_cast<Char
>(
'\\');
1867 c =
static_cast<Char
>(
'n');
1870 *out++ =
static_cast<Char
>(
'\\');
1871 c =
static_cast<Char
>(
'r');
1874 *out++ =
static_cast<Char
>(
'\\');
1875 c =
static_cast<Char
>(
't');
1882 *out++ =
static_cast<Char
>(
'\\');
1886 return write_codepoint<2, Char>(out,
'x',
escape.cp);
1888 if (
escape.cp < 0x10000) {
1889 return write_codepoint<4, Char>(out,
'u',
escape.cp);
1891 if (
escape.cp < 0x110000) {
1892 return write_codepoint<8, Char>(out,
'U',
escape.cp);
1896 out = write_codepoint<2, Char>(out,
'x',
1897 static_cast<uint32_t
>(escape_char) & 0xFF);
1905 template <
typename Char,
typename OutputIt>
1908 *out++ =
static_cast<Char
>(
'"');
1909 auto begin = str.begin(), end = str.end();
1912 out = copy_str<Char>(begin,
escape.begin, out);
1915 out = write_escaped_cp<OutputIt, Char>(out,
escape);
1916 }
while (begin != end);
1917 *out++ =
static_cast<Char
>(
'"');
1921 template <
typename Char,
typename OutputIt>
1923 Char v_array[1] = {v};
1924 *out++ =
static_cast<Char
>(
'\'');
1925 if ((
needs_escape(
static_cast<uint32_t
>(v)) && v !=
static_cast<Char
>(
'"')) ||
1926 v ==
static_cast<Char
>(
'\'')) {
1929 static_cast<uint32_t
>(v)});
1933 *out++ =
static_cast<Char
>(
'\'');
1937 template <
typename Char,
typename OutputIt>
1947 template <
typename Char,
typename OutputIt>
1952 using unsigned_type =
1956 :
write(out, static_cast<unsigned_type>(value), specs, loc);
1968 if (specs.
align == align::numeric) {
1974 }
else if (specs.
precision > num_digits) {
1985 template <
typename OutputIt,
typename Char,
typename W>
1989 W write_digits) -> OutputIt {
1994 for (
unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1995 *it++ =
static_cast<Char
>(p & 0xff);
2000 return write_padded<align::right>(
2002 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2003 *it++ = static_cast<Char>(p & 0xff);
2004 it = detail::fill_n(it, data.padding, static_cast<Char>(
'0'));
2005 return write_digits(it);
2024 if (*
state.group <= 0 || *
state.group == max_value<char>())
2025 return max_value<int>();
2032 if (!localized)
return;
2033 auto sep = thousands_sep<Char>(loc);
2035 if (sep.thousands_sep)
thousands_sep_.assign(1, sep.thousands_sep);
2050 template <
typename Out,
typename C>
2052 auto num_digits =
static_cast<int>(digits.size());
2054 separators.push_back(0);
2057 if (i >= num_digits)
break;
2058 separators.push_back(i);
2060 for (
int i = 0, sep_index =
static_cast<int>(separators.size() - 1);
2061 i < num_digits; ++i) {
2062 if (num_digits - i == separators[sep_index]) {
2068 *out++ =
static_cast<Char
>(digits[
to_unsigned(i)]);
2076 prefix += (1u + (
value > 0xff ? 1 : 0)) << 24;
2080 template <
typename OutputIt,
typename UInt,
typename Char>
2087 switch (specs.
type) {
2098 prefix_append(prefix,
unsigned(upper ?
'X' :
'x') << 8 |
'0');
2099 num_digits = count_digits<4>(
value);
2107 prefix_append(prefix,
unsigned(upper ?
'B' :
'b') << 8 |
'0');
2108 num_digits = count_digits<1>(
value);
2113 num_digits = count_digits<3>(
value);
2127 unsigned size = (prefix != 0 ? prefix >> 24 : 0) +
to_unsigned(num_digits) +
2128 to_unsigned(grouping.count_separators(num_digits));
2129 return write_padded<align::right>(
2131 for (
unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2132 *it++ =
static_cast<Char
>(p & 0xff);
2140 template <
typename OutputIt,
typename Char>
2151 template <
typename T>
2157 prefix = 0x01000000 |
'-';
2158 abs_value = 0 - abs_value;
2160 constexpr
const unsigned prefixes[4] = {0, 0, 0x1000000u |
'+',
2162 prefix = prefixes[
sign];
2164 return {abs_value, prefix};
2174 template <
typename T, FMT_ENABLE_IF(is_
integer<T>::value)>
2182 template <
typename T, FMT_ENABLE_IF(!is_
integer<T>::value)>
2188 template <
typename Char,
typename OutputIt,
typename T>
2193 auto abs_value =
arg.abs_value;
2194 auto prefix =
arg.prefix;
2195 switch (specs.
type) {
2201 return format_decimal<Char>(it, abs_value, num_digits).end;
2208 prefix_append(prefix,
unsigned(upper ?
'X' :
'x') << 8 |
'0');
2209 int num_digits = count_digits<4>(abs_value);
2212 return format_uint<4, Char>(it, abs_value, num_digits, upper);
2219 prefix_append(prefix,
unsigned(upper ?
'B' :
'b') << 8 |
'0');
2220 int num_digits = count_digits<1>(abs_value);
2221 return write_int(out, num_digits, prefix, specs,
2223 return format_uint<1, Char>(it, abs_value, num_digits);
2227 int num_digits = count_digits<3>(abs_value);
2230 if (specs.
alt && specs.
precision <= num_digits && abs_value != 0)
2232 return write_int(out, num_digits, prefix, specs,
2234 return format_uint<3, Char>(it, abs_value, num_digits);
2238 return write_char(out,
static_cast<Char
>(abs_value), specs);
2244 template <
typename Char,
typename OutputIt,
typename T>
2250 template <
typename Char,
typename OutputIt,
typename T,
2252 !std::is_same<T, bool>::value &&
2253 std::is_same<OutputIt, buffer_appender<Char>>::value)>
2262 template <
typename Char,
typename OutputIt,
typename T,
2264 !std::is_same<T, bool>::value &&
2265 !std::is_same<OutputIt, buffer_appender<Char>>::value)>
2268 locale_ref loc) -> OutputIt {
2306 it.
count_ +=
static_cast<size_t>(n);
2313 template <
typename Char,
typename OutputIt>
2316 auto data =
s.data();
2317 auto size =
s.size();
2322 if (specs.
width != 0) {
2334 template <
typename Char,
typename OutputIt>
2339 return write(out,
s, specs);
2341 template <
typename Char,
typename OutputIt>
2346 return write_ptr<Char>(out, bit_cast<uintptr_t>(
s), &specs);
2351 template <
typename Char,
typename OutputIt,
typename T,
2353 !std::is_same<T, bool>::value &&
2354 !std::is_same<T, Char>::value)>
2359 if (negative) abs_value = ~abs_value + 1;
2361 auto size = (negative ? 1 : 0) +
static_cast<size_t>(num_digits);
2363 if (
auto ptr = to_pointer<Char>(it,
size)) {
2364 if (negative) *
ptr++ =
static_cast<Char
>(
'-');
2365 format_decimal<Char>(
ptr, abs_value, num_digits);
2368 if (negative) *it++ =
static_cast<Char
>(
'-');
2369 it = format_decimal<Char>(it, abs_value, num_digits).end;
2374 template <
typename Char>
2378 auto align = align::none;
2380 if (end - p <= 0) p = begin;
2390 align = align::center;
2393 if (
align != align::none) {
2396 if (c ==
'}')
return begin;
2407 }
else if (p == begin) {
2434 template <
typename Char>
2438 result.showpoint = specs.
alt;
2440 switch (specs.
type) {
2445 result.upper =
true;
2451 result.upper =
true;
2455 result.showpoint |= specs.
precision != 0;
2458 result.upper =
true;
2462 result.showpoint |= specs.
precision != 0;
2465 result.upper =
true;
2477 template <
typename Char,
typename OutputIt>
2482 isnan ? (fspecs.upper ?
"NAN" :
"nan") : (fspecs.upper ?
"INF" :
"inf");
2483 constexpr
size_t str_size = 3;
2484 auto sign = fspecs.sign;
2485 auto size = str_size + (
sign ? 1 : 0);
2487 const bool is_zero_fill =
2488 specs.
fill.size() == 1 && *specs.
fill.data() ==
static_cast<Char
>(
'0');
2489 if (is_zero_fill) specs.
fill[0] =
static_cast<Char
>(
' ');
2491 if (
sign) *it++ = detail::sign<Char>(
sign);
2492 return copy_str<Char>(str, str + str_size, it);
2504 return f.significand_size;
2506 template <
typename T>
2511 template <
typename Char,
typename OutputIt>
2513 int significand_size) -> OutputIt {
2514 return copy_str<Char>(significand, significand + significand_size, out);
2516 template <
typename Char,
typename OutputIt,
typename UInt>
2518 int significand_size) -> OutputIt {
2519 return format_decimal<Char>(out, significand, significand_size).end;
2521 template <
typename Char,
typename OutputIt,
typename T,
typename Grouping>
2523 int significand_size,
int exponent,
2524 const Grouping& grouping) -> OutputIt {
2525 if (!grouping.has_separator()) {
2526 out = write_significand<Char>(out, significand, significand_size);
2530 write_significand<char>(
appender(
buffer), significand, significand_size);
2535 template <
typename Char,
typename UInt,
2541 out += significand_size + 1;
2543 int floating_size = significand_size - integral_size;
2544 for (
int i = floating_size / 2; i > 0; --i) {
2549 if (floating_size % 2 != 0) {
2550 *--out =
static_cast<Char
>(
'0' + significand % 10);
2558 template <
typename OutputIt,
typename UInt,
typename Char,
2561 int significand_size,
int integral_size,
2564 Char
buffer[digits10<UInt>() + 2];
2567 return detail::copy_str_noinline<Char>(
buffer, end, out);
2570 template <
typename OutputIt,
typename Char>
2572 int significand_size,
int integral_size,
2574 out = detail::copy_str_noinline<Char>(significand,
2575 significand + integral_size, out);
2578 return detail::copy_str_noinline<Char>(significand + integral_size,
2579 significand + significand_size, out);
2582 template <
typename OutputIt,
typename Char,
typename T,
typename Grouping>
2584 int significand_size,
int integral_size,
2586 const Grouping& grouping) -> OutputIt {
2587 if (!grouping.has_separator()) {
2596 return detail::copy_str_noinline<Char>(
buffer.
data() + integral_size,
2600 template <
typename OutputIt,
typename DecimalFP,
typename Char,
2601 typename Grouping = digit_grouping<Char>>
2606 auto significand =
f.significand;
2608 const Char
zero =
static_cast<Char
>(
'0');
2609 auto sign = fspecs.sign;
2614 fspecs.locale ? detail::decimal_point<Char>(loc) :
static_cast<Char
>(
'.');
2616 int output_exp =
f.exponent + significand_size - 1;
2617 auto use_exp_format = [=]() {
2624 output_exp >= (fspecs.precision > 0 ? fspecs.precision :
exp_upper);
2626 if (use_exp_format()) {
2628 if (fspecs.showpoint) {
2629 num_zeros = fspecs.precision - significand_size;
2630 if (num_zeros < 0) num_zeros = 0;
2632 }
else if (significand_size == 1) {
2635 auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
2637 if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
2640 char exp_char = fspecs.upper ?
'E' :
'e';
2641 auto write = [=](iterator it) {
2642 if (
sign) *it++ = detail::sign<Char>(
sign);
2647 *it++ =
static_cast<Char
>(exp_char);
2648 return write_exponent<Char>(output_exp, it);
2650 return specs.
width > 0 ? write_padded<align::right>(out, specs,
size,
write)
2654 int exp =
f.exponent + significand_size;
2655 if (
f.exponent >= 0) {
2658 int num_zeros = fspecs.precision -
exp;
2660 if (fspecs.showpoint) {
2665 auto grouping = Grouping(loc, fspecs.locale);
2667 return write_padded<align::right>(out, specs,
size, [&](iterator it) {
2668 if (
sign) *it++ = detail::sign<Char>(
sign);
2669 it = write_significand<Char>(it, significand, significand_size,
2670 f.exponent, grouping);
2671 if (!fspecs.showpoint)
return it;
2675 }
else if (
exp > 0) {
2677 int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
2679 auto grouping = Grouping(loc, fspecs.locale);
2681 return write_padded<align::right>(out, specs,
size, [&](iterator it) {
2682 if (
sign) *it++ = detail::sign<Char>(
sign);
2689 int num_zeros = -
exp;
2690 if (significand_size == 0 && fspecs.precision >= 0 &&
2691 fspecs.precision < num_zeros) {
2692 num_zeros = fspecs.precision;
2694 bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
2696 return write_padded<align::right>(out, specs,
size, [&](iterator it) {
2697 if (
sign) *it++ = detail::sign<Char>(
sign);
2699 if (!pointy)
return it;
2702 return write_significand<Char>(it, significand, significand_size);
2714 template <
typename Out,
typename C>
2720 template <
typename OutputIt,
typename DecimalFP,
typename Char>
2738 template <
typename T,
typename Enable =
void>
2741 template <
typename T>
2745 template <
typename T, FMT_ENABLE_IF(std::is_
floating_po
int<T>::value&&
2746 has_isfinite<T>::value)>
2748 constexpr T inf = T(std::numeric_limits<double>::infinity());
2753 template <
typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)>
2755 T inf = T(std::numeric_limits<double>::infinity());
2760 template <
typename T, FMT_ENABLE_IF(is_
floating_po
int<T>::value)>
2763 #ifdef __cpp_if_constexpr
2764 if constexpr (std::numeric_limits<double>::is_iec559) {
2765 auto bits = detail::bit_cast<uint64_t>(
static_cast<double>(
value));
2766 return (bits >> (num_bits<uint64_t>() - 1)) != 0;
2776 if (exp10 > 0 &&
precision > max_value<int>() - exp10)
2777 FMT_THROW(format_error(
"number is too big"));
2803 auto result =
static_cast<double_bigit>((*this)[index]) - other - borrow;
2804 (*this)[index] =
static_cast<bigit>(result);
2820 for (
size_t j = 0, n = other.
bigits_.
size(); j != n; ++i, ++j)
2829 for (
size_t i = 0, n =
bigits_.
size(); i < n; ++i) {
2837 template <
typename UInt, FMT_ENABLE_IF(std::is_same<UInt, u
int64_t>::value ||
2838 std::is_same<UInt, u
int128_t>::value)>
2842 const int shift = num_bits<half_uint>() -
bigit_bits;
2843 const UInt lower =
static_cast<half_uint
>(
value);
2844 const UInt upper =
value >> num_bits<half_uint>();
2846 for (
size_t i = 0, n =
bigits_.
size(); i < n; ++i) {
2847 UInt result = lower *
bigits_[i] +
static_cast<bigit>(carry);
2852 while (carry != 0) {
2858 template <
typename UInt, FMT_ENABLE_IF(std::is_same<UInt, u
int64_t>::value ||
2859 std::is_same<UInt, u
int128_t>::value)>
2898 if (shift == 0)
return *
this;
2900 for (
size_t i = 0, n =
bigits_.
size(); i < n; ++i) {
2909 template <
typename Int>
2918 int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
2919 if (num_lhs_bigits != num_rhs_bigits)
2920 return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
2921 int i =
static_cast<int>(lhs.bigits_.size()) - 1;
2922 int j =
static_cast<int>(rhs.bigits_.size()) - 1;
2924 if (end < 0) end = 0;
2925 for (; i >= end; --i, --j) {
2926 bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
2927 if (lhs_bigit != rhs_bigit)
return lhs_bigit > rhs_bigit ? 1 : -1;
2929 if (i != j)
return i > j ? 1 : -1;
2937 auto minimum = [](
int a,
int b) {
return a < b ? a : b; };
2938 auto maximum = [](
int a,
int b) {
return a > b ? a : b; };
2939 int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits());
2940 int num_rhs_bigits = rhs.num_bigits();
2941 if (max_lhs_bigits + 1 < num_rhs_bigits)
return -1;
2942 if (max_lhs_bigits > num_rhs_bigits)
return 1;
2943 auto get_bigit = [](
const bigint& n,
int i) ->
bigit {
2947 int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_);
2948 for (
int i = num_rhs_bigits - 1; i >= min_exp; --i) {
2950 static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
2951 bigit rhs_bigit = get_bigit(rhs, i);
2952 if (sum > rhs_bigit + borrow)
return 1;
2953 borrow = rhs_bigit + borrow - sum;
2954 if (borrow > 1)
return -1;
2957 return borrow != 0 ? -1 : 0;
2963 if (
exp == 0)
return *
this = 1;
2986 for (
int bigit_index = 0; bigit_index <
num_bigits; ++bigit_index) {
2989 for (
int i = 0, j = bigit_index; j >= 0; ++i, --j) {
2993 (*this)[bigit_index] =
static_cast<bigit>(sum);
2994 sum >>= num_bits<bigit>();
2997 for (
int bigit_index =
num_bigits; bigit_index < num_result_bigits;
3001 (*this)[bigit_index] =
static_cast<bigit>(sum);
3002 sum >>= num_bits<bigit>();
3011 int exp_difference =
exp_ - other.
exp_;
3012 if (exp_difference <= 0)
return;
3015 for (
int i =
num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
3017 std::uninitialized_fill_n(
bigits_.
data(), exp_difference, 0u);
3018 exp_ -= exp_difference;
3048 unsigned flags,
int num_digits,
3060 int shift = is_predecessor_closer ? 2 : 1;
3062 numerator =
value.f;
3063 numerator <<=
value.e + shift;
3066 if (is_predecessor_closer) {
3068 upper_store <<=
value.e + 1;
3069 upper = &upper_store;
3072 denominator <<= shift;
3073 }
else if (exp10 < 0) {
3076 if (is_predecessor_closer) {
3077 upper_store.
assign(numerator);
3079 upper = &upper_store;
3081 numerator *=
value.f;
3082 numerator <<= shift;
3084 denominator <<= shift -
value.e;
3086 numerator =
value.f;
3087 numerator <<= shift;
3089 denominator <<= shift -
value.e;
3091 if (is_predecessor_closer) {
3092 upper_store = 1ULL << 1;
3093 upper = &upper_store;
3096 int even =
static_cast<int>((
value.f & 1) == 0);
3097 if (!upper) upper = &lower;
3098 bool shortest = num_digits < 0;
3100 if (add_compare(numerator, *upper, denominator) + even <= 0) {
3103 if (num_digits < 0) {
3105 if (upper != &lower) *upper *= 10;
3117 bool low = compare(numerator, lower) - even < 0;
3119 bool high = add_compare(numerator, *upper, denominator) + even > 0;
3120 data[num_digits++] =
static_cast<char>(
'0' +
digit);
3123 ++
data[num_digits - 1];
3125 int result = add_compare(numerator, numerator, denominator);
3127 if (result > 0 || (result == 0 && (
digit % 2) != 0))
3128 ++
data[num_digits - 1];
3131 exp10 -= num_digits - 1;
3136 if (upper != &lower) *upper *= 10;
3140 exp10 -= num_digits - 1;
3141 if (num_digits <= 0) {
3143 auto digit = add_compare(numerator, numerator, denominator) > 0 ?
'1' :
'0';
3148 for (
int i = 0; i < num_digits - 1; ++i) {
3150 buf[i] =
static_cast<char>(
'0' +
digit);
3154 auto result = add_compare(numerator, numerator, denominator);
3155 if (result > 0 || (result == 0 && (
digit % 2) != 0)) {
3157 const auto overflow =
'0' + 10;
3158 buf[num_digits - 1] = overflow;
3160 for (
int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
3164 if (buf[0] == overflow) {
3175 buf[num_digits - 1] =
static_cast<char>(
'0' +
digit);
3179 template <
typename Float, FMT_ENABLE_IF(!is_
double_
double<Float>::value)>
3184 static_assert(!std::is_same<Float, float>::value,
"");
3189 using carrier_uint =
typename info::carrier_uint;
3191 constexpr
auto num_float_significand_bits =
3192 detail::num_significand_bits<Float>();
3195 f.e += num_float_significand_bits;
3196 if (!has_implicit_bit<Float>()) --
f.e;
3198 constexpr
auto num_fraction_bits =
3199 num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0);
3200 constexpr
auto num_xdigits = (num_fraction_bits + 3) / 4;
3202 constexpr
auto leading_shift = ((num_xdigits - 1) * 4);
3203 const auto leading_mask = carrier_uint(0xF) << leading_shift;
3204 const auto leading_xdigit =
3205 static_cast<uint32_t
>((
f.f & leading_mask) >> leading_shift);
3206 if (leading_xdigit > 1)
f.e -= (32 -
countl_zero(leading_xdigit) - 1);
3208 int print_xdigits = num_xdigits - 1;
3210 const int shift = ((print_xdigits -
precision - 1) * 4);
3211 const auto mask = carrier_uint(0xF) << shift;
3212 const auto v =
static_cast<uint32_t
>((
f.f & mask) >> shift);
3215 const auto inc = carrier_uint(1) << (shift + 4);
3221 if (!has_implicit_bit<Float>()) {
3222 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
3223 if ((
f.f & implicit_bit) == implicit_bit) {
3232 char xdigits[num_bits<carrier_uint>() / 4];
3234 format_uint<4>(xdigits,
f.f, num_xdigits, specs.
upper);
3237 while (print_xdigits > 0 && xdigits[print_xdigits] ==
'0') --print_xdigits;
3244 buf.
append(xdigits + 1, xdigits + 1 + print_xdigits);
3252 abs_e =
static_cast<uint32_t
>(-
f.e);
3255 abs_e =
static_cast<uint32_t
>(
f.e);
3260 template <
typename Float, FMT_ENABLE_IF(is_
double_
double<Float>::value)>
3262 float_specs specs, buffer<char>& buf) {
3273 return U
"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7"
3274 U
"\x800001ae\x8000002b"[index];
3277 template <
typename Float>
3281 static_assert(!std::is_same<Float, float>::value,
"");
3297 bool use_dragon =
true;
3298 unsigned dragon_flags = 0;
3300 const auto inv_log2_10 = 0.3010299956639812;
3307 auto e = (
f.e + count_digits<1>(
f.f) - 1) * inv_log2_10 - 1e-10;
3308 exp =
static_cast<int>(e);
3313 if (specs.binary32) {
3316 return dec.exponent;
3320 return dec.exponent;
3324 auto br = bit_cast<uint64_t>(
static_cast<double>(
value));
3326 const uint64_t significand_mask =
3327 (
static_cast<uint64_t
>(1) << num_significand_bits<double>()) - 1;
3328 uint64_t significand = (br & significand_mask);
3329 int exponent =
static_cast<int>((br & exponent_mask<double>()) >>
3330 num_significand_bits<double>());
3332 if (exponent != 0) {
3333 exponent -= exponent_bias<double>() + num_significand_bits<double>();
3335 (
static_cast<uint64_t
>(1) << num_significand_bits<double>());
3339 FMT_ASSERT(significand != 0,
"zeros should not appear here");
3341 FMT_ASSERT(shift >= num_bits<uint64_t>() - num_significand_bits<double>(),
3343 shift -= (num_bits<uint64_t>() - num_significand_bits<double>() - 2);
3344 exponent = (std::numeric_limits<double>::min_exponent -
3345 num_significand_bits<double>()) -
3347 significand <<= shift;
3355 uint64_t first_segment;
3356 bool has_more_segments;
3357 int digits_in_the_first_segment;
3361 first_segment = r.high();
3362 has_more_segments = r.low() != 0;
3365 if (first_segment >= 1000000000000000000ULL) {
3366 digits_in_the_first_segment = 19;
3370 digits_in_the_first_segment = 18;
3371 first_segment *= 10;
3380 if (digits_in_the_first_segment >
precision) {
3384 exp += digits_in_the_first_segment;
3392 if ((first_segment |
static_cast<uint64_t
>(has_more_segments)) >
3393 5000000000000000000ULL) {
3410 const uint32_t first_subsegment =
static_cast<uint32_t
>(
3413 const uint64_t second_third_subsegments =
3414 first_segment - first_subsegment * 10000000000ULL;
3418 bool should_round_up;
3422 auto print_subsegment = [&](uint32_t subsegment,
char*
buffer) {
3423 int number_of_digits_printed = 0;
3426 if ((number_of_digits_to_print & 1) != 0) {
3432 prod = ((subsegment *
static_cast<uint64_t
>(720575941)) >> 24) + 1;
3433 digits =
static_cast<uint32_t
>(
prod >> 32);
3434 *
buffer =
static_cast<char>(
'0' + digits);
3435 number_of_digits_printed++;
3445 prod = ((subsegment *
static_cast<uint64_t
>(450359963)) >> 20) + 1;
3446 digits =
static_cast<uint32_t
>(
prod >> 32);
3448 number_of_digits_printed += 2;
3452 while (number_of_digits_printed < number_of_digits_to_print) {
3453 prod =
static_cast<uint32_t
>(
prod) *
static_cast<uint64_t
>(100);
3454 digits =
static_cast<uint32_t
>(
prod >> 32);
3456 number_of_digits_printed += 2;
3461 print_subsegment(first_subsegment, buf.data());
3480 uint32_t fractional_part =
static_cast<uint32_t
>(
prod);
3483 8 - number_of_digits_to_print) ||
3484 ((fractional_part >> 31) &
3485 ((digits & 1) | (second_third_subsegments != 0) |
3486 has_more_segments)) != 0;
3494 should_round_up = second_third_subsegments > 5000000000ULL ||
3495 (second_third_subsegments == 5000000000ULL &&
3496 ((digits & 1) != 0 || has_more_segments));
3505 const uint32_t second_subsegment =
3507 second_third_subsegments, 1844674407370955162ULL));
3508 const uint32_t third_subsegment =
3509 static_cast<uint32_t
>(second_third_subsegments) -
3510 second_subsegment * 10;
3512 number_of_digits_to_print =
precision - 9;
3513 print_subsegment(second_subsegment, buf.data() + 9);
3520 uint32_t fractional_part =
static_cast<uint32_t
>(
prod);
3523 8 - number_of_digits_to_print) ||
3524 ((fractional_part >> 31) &
3525 ((digits & 1) | (third_subsegment != 0) |
3526 has_more_segments)) != 0;
3533 should_round_up = third_subsegment > 5 ||
3534 (third_subsegment == 5 &&
3535 ((digits & 1) != 0 || has_more_segments));
3540 if (should_round_up) {
3542 for (
int i =
precision - 1; i > 0 && buf[i] >
'9'; --i) {
3559 exp += digits_in_the_first_segment - 1;
3564 bool is_predecessor_closer = specs.binary32
3565 ?
f.assign(
static_cast<float>(
value))
3566 :
f.assign(converted_value);
3571 const int max_double_digits = 767;
3575 if (!
fixed && !specs.showpoint) {
3577 auto num_digits = buf.size();
3578 while (num_digits > 0 && buf[num_digits - 1] ==
'0') {
3582 buf.try_resize(num_digits);
3586 template <
typename Char,
typename OutputIt,
typename T>
3591 fspecs.
sign = specs.sign;
3593 fspecs.
sign = sign::minus;
3595 }
else if (fspecs.
sign == sign::minus) {
3596 fspecs.
sign = sign::none;
3602 if (specs.align == align::numeric && fspecs.
sign) {
3604 *it++ = detail::sign<Char>(fspecs.
sign);
3606 fspecs.
sign = sign::none;
3607 if (specs.width != 0) --specs.width;
3635 template <
typename Char,
typename OutputIt,
typename T,
3645 template <
typename Char,
typename OutputIt,
typename T,
3653 fspecs.sign = sign::minus;
3660 floaty_uint mask = exponent_mask<floaty>();
3661 if ((bit_cast<floaty_uint>(
value) & mask) == mask)
3668 template <
typename Char,
typename OutputIt,
typename T,
3670 !is_fast_float<T>::value)>
3675 template <
typename Char,
typename OutputIt>
3682 template <
typename Char,
typename OutputIt>
3686 it = copy_str_noinline<Char>(
value.begin(),
value.end(), it);
3690 template <
typename Char,
typename OutputIt,
typename T,
3698 typename Char,
typename OutputIt,
typename T,
3700 std::is_enum<T>::value && !std::is_same<T, Char>::value &&
3701 mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value !=
3708 template <
typename Char,
typename OutputIt,
typename T,
3715 ?
write(out, value ? 1 : 0, specs, {})
3716 :
write_bytes(out, value ?
"true" :
"false", specs);
3719 template <
typename Char,
typename OutputIt>
3726 template <
typename Char,
typename OutputIt>
3734 template <
typename Char,
typename OutputIt,
typename T,
3737 locale_ref = {}) -> OutputIt {
3738 return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
3742 template <
typename Char,
typename OutputIt,
typename T,
3747 !std::is_same<T, remove_cvref_t<decltype(arg_mapper<Context>().map(
3753 template <
typename Char,
typename OutputIt,
typename T,
3758 auto formatter =
typename Context::template formatter_type<T>();
3759 auto parse_ctx =
typename Context::parse_context_type({});
3761 auto ctx = Context(out, {}, {});
3781 h.format(parse_ctx, format_ctx);
3782 return format_ctx.out();
3794 template <
typename T>
3806 template <
typename T, FMT_ENABLE_IF(is_
integer<T>::value)>
3809 return static_cast<unsigned long long>(
value);
3812 template <
typename T, FMT_ENABLE_IF(!is_
integer<T>::value)>
3820 template <
typename T, FMT_ENABLE_IF(is_
integer<T>::value)>
3823 return static_cast<unsigned long long>(
value);
3826 template <
typename T, FMT_ENABLE_IF(!is_
integer<T>::value)>
3833 template <
typename Handler,
typename FormatArg>
3838 return static_cast<int>(
value);
3841 template <
typename Context,
typename ID>
3843 auto arg = ctx.arg(
id);
3844 if (!
arg) ctx.on_error(
"argument not found");
3848 template <
typename Handler,
typename Context>
3864 #if FMT_USE_USER_DEFINED_LITERALS
3865 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
3866 template <
typename T,
typename Char,
size_t N,
3867 fmt::detail_exported::fixed_string<Char, N> Str>
3868 struct statically_named_arg : view {
3869 static constexpr
auto name = Str.data;
3872 statically_named_arg(
const T& v) : value(v) {}
3875 template <
typename T,
typename Char,
size_t N,
3876 fmt::detail_exported::fixed_string<Char, N> Str>
3877 struct is_named_arg<statically_named_arg<T, Char, N, Str>> :
std::true_type {};
3879 template <
typename T,
typename Char,
size_t N,
3880 fmt::detail_exported::fixed_string<Char, N> Str>
3881 struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
3884 template <
typename Char,
size_t N,
3885 fmt::detail_exported::fixed_string<Char, N> Str>
3887 template <
typename T>
auto operator=(T&& value)
const {
3888 return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
3892 template <
typename Char>
struct udl_arg {
3895 template <
typename T>
auto operator=(T&& value)
const -> named_arg<Char, T> {
3896 return {str, std::forward<T>(value)};
3900 #endif // FMT_USE_USER_DEFINED_LITERALS
3902 template <
typename Locale,
typename Char>
3905 -> std::basic_string<Char> {
3908 return {buf.data(), buf.size()};
3917 const char* message) noexcept;
3940 template <
typename... T>
3963 const char* message) noexcept;
3985 bool negative = value < 0;
3986 if (negative) abs_value = 0 - abs_value;
3988 if (negative) *--begin =
'-';
4029 template <
typename T,
typename Char>
4031 :
formatter<detail::format_as_t<T>, Char> {
4032 template <
typename FormatContext>
4033 auto format(
const T& value, FormatContext& ctx)
const -> decltype(ctx.out()) {
4039 #define FMT_FORMAT_AS(Type, Base) \
4040 template <typename Char> \
4041 struct formatter<Type, Char> : formatter<Base, Char> {}
4055 template <
typename Char,
size_t N>
4067 template <
typename T>
auto ptr(T p) ->
const void* {
4068 static_assert(std::is_pointer<T>::value,
"");
4069 return detail::bit_cast<const void*>(p);
4071 template <
typename T,
typename Deleter>
4072 auto ptr(
const std::unique_ptr<T, Deleter>& p) ->
const void* {
4075 template <
typename T>
auto ptr(
const std::shared_ptr<T>& p) ->
const void* {
4089 template <
typename Enum>
4095 template <
typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)>
4115 template <
typename ParseContext>
4121 template <
typename FormatContext>
4123 detail::handle_dynamic_spec<detail::width_checker>(specs_.
width,
4125 detail::handle_dynamic_spec<detail::precision_checker>(
4156 template <
typename ParseContext>
4162 template <
typename FormatContext>
4164 -> decltype(ctx.out()) {
4165 detail::handle_dynamic_spec<detail::width_checker>(specs_.
width,
4167 detail::handle_dynamic_spec<detail::precision_checker>(
4185 -> decltype(ctx.out()) {
4186 return view.fmt->format(*view.value, ctx);
4211 template <
typename F>
4215 write(std::back_inserter(buf));
4229 template <
typename It,
typename Sentinel,
typename Char =
char>
4239 template <
typename It,
typename Sentinel,
typename Char>
4243 #ifdef __cpp_lib_ranges
4244 std::iter_value_t<It>;
4246 typename std::iterator_traits<It>::value_type;
4251 template <
typename ParseContext>
4253 return value_formatter_.parse(ctx);
4256 template <
typename FormatContext>
4258 FormatContext& ctx)
const -> decltype(ctx.out()) {
4259 auto it = value.begin;
4260 auto out = ctx.out();
4261 if (it != value.end) {
4262 out = value_formatter_.format(*it, ctx);
4264 while (it != value.end) {
4265 out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
4266 ctx.advance_to(out);
4267 out = value_formatter_.format(*it, ctx);
4279 template <
typename It,
typename Sentinel>
4281 return {begin, end, sep};
4300 template <
typename Range>
4303 return join(std::begin(range), std::end(range), sep);
4317 template <
typename T, FMT_ENABLE_IF(!std::is_
integral<T>::value &&
4318 !detail::has_format_as<T>::value)>
4321 detail::write<char>(
appender(buffer), value);
4322 return {buffer.data(), buffer.size()};
4325 template <
typename T, FMT_ENABLE_IF(std::is_
integral<T>::value)>
4329 constexpr
int max_size = detail::digits10<T>() + 2;
4330 char buffer[max_size > 5 ?
static_cast<unsigned>(max_size) : 5];
4331 char* begin = buffer;
4332 return std::string(begin, detail::write<char>(begin, value));
4335 template <
typename Char,
size_t SIZE>
4337 -> std::basic_string<Char> {
4338 auto size = buf.size();
4340 return std::basic_string<Char>(buf.data(),
size);
4343 template <
typename T, FMT_ENABLE_IF(!std::is_
integral<T>::value &&
4344 detail::has_format_as<T>::value)>
4345 inline auto to_string(
const T& value) -> std::string {
4353 template <
typename Char>
4371 : parse_context(str), context(p_out, p_args, p_loc) {}
4373 void on_text(
const Char* begin,
const Char* end) {
4385 int arg_id = context.
arg_id(
id);
4390 FMT_INLINE void on_replacement_field(
int id,
const Char*) {
4398 auto on_format_specs(
int id,
const Char* begin,
const Char* end)
4402 if (
arg.format_custom(begin, parse_context, context))
4403 return parse_context.
begin();
4406 detail::handle_dynamic_spec<detail::width_checker>(
4407 specs.
width, specs.width_ref, context);
4408 detail::handle_dynamic_spec<detail::precision_checker>(
4409 specs.
precision, specs.precision_ref, context);
4410 if (begin == end || *begin !=
'}')
4417 detail::parse_format_string<false>(fmt, format_handler(out, fmt,
args, loc));
4422 #ifndef FMT_HEADER_ONLY
4427 -> thousands_sep_result<char>;
4429 -> thousands_sep_result<wchar_t>;
4432 #endif // FMT_HEADER_ONLY
4436 #if FMT_USE_USER_DEFINED_LITERALS
4448 # if FMT_USE_NONTYPE_TEMPLATE_ARGS
4449 template <detail_exported::fixed_
string Str> constexpr
auto operator""_a() {
4451 return detail::udl_arg<
char_t,
sizeof(Str.data) /
sizeof(
char_t), Str>();
4454 constexpr
auto operator""_a(
const char* s,
size_t) -> detail::udl_arg<char> {
4459 #endif // FMT_USE_USER_DEFINED_LITERALS
4461 template <
typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4467 template <
typename Locale,
typename... T,
4474 template <
typename OutputIt,
typename Locale,
4476 detail::is_locale<Locale>::value)>
4480 auto&& buf = get_buffer<char>(out);
4485 template <
typename OutputIt,
typename Locale,
typename... T,
4487 detail::is_locale<Locale>::value)>
4493 template <
typename Locale,
typename... T,
4497 T&&...
args) ->
size_t {
4506 template <
typename T,
typename Char>
4507 template <
typename FormatContext>
4513 const -> decltype(ctx.out()) {
4516 return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
4518 auto specs = specs_;
4519 detail::handle_dynamic_spec<detail::width_checker>(specs.
width,
4520 specs.width_ref, ctx);
4521 detail::handle_dynamic_spec<detail::precision_checker>(
4522 specs.
precision, specs.precision_ref, ctx);
4523 return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
4528 #ifdef FMT_HEADER_ONLY
4529 # define FMT_FUNC inline
4535 #endif // FMT_FORMAT_H_