|
Loading...
Searching...
No Matches
Go to the documentation of this file.
46#ifdef __INTEL_COMPILER
47# define FMT_ICC_VERSION __INTEL_COMPILER
49# define FMT_ICC_VERSION __ICL
51# define FMT_ICC_VERSION 0
55# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
57# define FMT_CUDA_VERSION 0
61# define FMT_HAS_BUILTIN(x) __has_builtin(x)
63# define FMT_HAS_BUILTIN(x) 0
66#if FMT_GCC_VERSION || FMT_CLANG_VERSION
67# define FMT_NOINLINE __attribute__((noinline))
72#if __cplusplus == 201103L || __cplusplus == 201402L
73# if defined(__INTEL_COMPILER) || defined(__PGI)
74# define FMT_FALLTHROUGH
75# elif defined(__clang__)
76# define FMT_FALLTHROUGH [[clang::fallthrough]]
77# elif FMT_GCC_VERSION >= 700 && \
78 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
79# define FMT_FALLTHROUGH [[gnu::fallthrough]]
81# define FMT_FALLTHROUGH
83#elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough) || \
84 (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
85# define FMT_FALLTHROUGH [[fallthrough]]
87# define FMT_FALLTHROUGH
90#ifndef FMT_MAYBE_UNUSED
91# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
92# define FMT_MAYBE_UNUSED [[maybe_unused]]
94# define FMT_MAYBE_UNUSED
100# if FMT_MSC_VER || FMT_NVCC
103template < typename Exception> inline void do_throw( const Exception& x) {
106 volatile bool b = true;
111# define FMT_THROW(x) detail::do_throw(x)
113# define FMT_THROW(x) throw x
116# define FMT_THROW(x) \
118 static_cast<void>(sizeof(x)); \
119 FMT_ASSERT(false, ""); \
126# define FMT_CATCH(x) catch (x)
128# define FMT_TRY if (true)
129# define FMT_CATCH(x) if (false)
132#ifndef FMT_USE_USER_DEFINED_LITERALS
134# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
135 FMT_MSC_VER >= 1900) && \
136 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 480)
137# define FMT_USE_USER_DEFINED_LITERALS 1
139# define FMT_USE_USER_DEFINED_LITERALS 0
143#ifndef FMT_USE_UDL_TEMPLATE
146# if FMT_USE_USER_DEFINED_LITERALS && \
147 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 501) && \
148 ((FMT_GCC_VERSION >= 604 && __cplusplus >= 201402L) || \
149 FMT_CLANG_VERSION >= 304) && \
150 !defined(__PGI) && !defined(__NVCC__)
151# define FMT_USE_UDL_TEMPLATE 1
153# define FMT_USE_UDL_TEMPLATE 0
158# define FMT_USE_FLOAT 1
161#ifndef FMT_USE_DOUBLE
162# define FMT_USE_DOUBLE 1
165#ifndef FMT_USE_LONG_DOUBLE
166# define FMT_USE_LONG_DOUBLE 1
173#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
174# define FMT_REDUCE_INT_INSTANTIATIONS 0
179#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clz)) && !FMT_MSC_VER
180# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
182#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clzll)) && !FMT_MSC_VER
183# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
185#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctz))
186# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
188#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctzll))
189# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
199#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && \
200 !defined(FMT_BUILTIN_CTZLL) && !defined(_MANAGED)
205# pragma intrinsic(_BitScanForward)
206# pragma intrinsic(_BitScanReverse)
208# if defined(_WIN64) && !defined(__clang__)
209# pragma intrinsic(_BitScanForward64)
210# pragma intrinsic(_BitScanReverse64)
213inline int clz(uint32_t x) {
215 _BitScanReverse(&r, x);
221 return 31 ^ static_cast<int>(r);
223# define FMT_BUILTIN_CLZ(n) detail::clz(n)
225inline int clzll(uint64_t x) {
228 _BitScanReverse64(&r, x);
231 if (_BitScanReverse(&r, static_cast<uint32_t >(x >> 32))) return 63 ^ (r + 32);
233 _BitScanReverse(&r, static_cast<uint32_t >(x));
237 return 63 ^ static_cast<int>(r);
239# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
241inline int ctz(uint32_t x) {
243 _BitScanForward(&r, x);
246 return static_cast<int>(r);
248# define FMT_BUILTIN_CTZ(n) detail::ctz(n)
250inline int ctzll(uint64_t x) {
255 _BitScanForward64(&r, x);
258 if (_BitScanForward(&r, static_cast<uint32_t >(x))) return static_cast<int>(r);
260 _BitScanForward(&r, static_cast<uint32_t >(x >> 32));
263 return static_cast<int>(r);
265# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
271#ifndef FMT_DEPRECATED_NUMERIC_ALIGN
272# define FMT_DEPRECATED_NUMERIC_ALIGN 0
281template < typename Dest, typename Source>
283 static_assert( sizeof(Dest) == sizeof(Source), "size mismatch");
285 std::memcpy(&dest, &source, sizeof(dest));
292 char data[ sizeof(u)];
305 for ( size_t i = 0, j = sizeof( void*) - 1; i < j; ++i, --j)
323 return (std::numeric_limits<T>::max)();
326 return std::numeric_limits<T>::digits;
332 return static_cast<int>( sizeof( void*) *
333 std::numeric_limits<unsigned char>::digits);
338#if FMT_HAS_BUILTIN(__builtin_assume)
339 __builtin_assume(condition);
346template < typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
349template < typename Char> inline Char* get_data(std::basic_string<Char>& s) {
352template < typename Container>
353inline typename Container::value_type* get_data(Container& c) {
357#if defined(_SECURE_SCL) && _SECURE_SCL
359template < typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
365template < typename T> inline T* make_checked(T* p, size_t) { return p; }
368template < typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
370__attribute__((no_sanitize( "undefined")))
373reserve(std::back_insert_iterator<Container> it, size_t n) {
375 size_t size = c.size();
387template < typename Iterator> inline Iterator& reserve(Iterator& it, size_t) {
391template < typename T, typename OutputIt>
397 auto size = buf. size();
398 if (buf. capacity() < size + n) return nullptr;
400 return buf. data() + size;
403template < typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
405 std::back_insert_iterator<Container>& it,
410template < typename Iterator>
447 it. count_ += static_cast<size_t>(n);
465 using value_type = typename std::iterator_traits<OutputIt>::value_type;
478template < typename OutputIt,
479 typename Enable = typename std::is_void<
480 typename std::iterator_traits<OutputIt>::value_type> ::type>
483template < typename OutputIt>
495 if (this->count_++ < this->limit_) ++this->out_;
506 return this->count_ < this->limit_ ? *this->out_ : blackhole_;
510template < typename OutputIt>
518 if (this->count_++ < this->limit_) *this->out_++ = val;
527template < typename Char>
535 size_t num_code_points = 0;
536 for ( size_t i = 0, size = s. size(); i != size; ++i) {
537 if (( data[i] & 0xc0) != 0x80) ++num_code_points;
539 return num_code_points;
544 reinterpret_cast<const char* >(s. data()), s. size()));
547template < typename Char>
549 size_t size = s. size();
550 return n < size ? n : size;
556 size_t num_code_points = 0;
557 for ( size_t i = 0, size = s. size(); i != size; ++i) {
558 if (( data[i] & 0xc0) != 0x80 && ++num_code_points > n) {
565template < typename InputIt, typename OutChar>
567 std::is_same<typename std::iterator_traits<InputIt>::value_type,
569 std::is_same<OutChar, char8_type>::value>;
571template < typename OutChar, typename InputIt, typename OutputIt,
573OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
574 return std::copy(begin, end, it);
577template < typename OutChar, typename InputIt, typename OutputIt,
579OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
580 return std::transform(begin, end, it,
581 []( char c) { return static_cast<char8_type>(c); });
584template < typename Char, typename InputIt>
587 return it + (end - begin);
592 sizeof(T) <= sizeof( double)>;
594#ifndef FMT_USE_FULL_CACHE_DRAGONBOX
595# define FMT_USE_FULL_CACHE_DRAGONBOX 0
603 try_reserve(size_ + count);
604 auto free_cap = capacity_ - size_;
609 } while (begin != end);
612template < typename OutputIt, typename T, typename Traits>
614 out_ = std::copy_n(data_, this->limit(this->size()), out_);
653 typename Allocator = std::allocator<T>>
676 this-> set(store_, SIZE);
734 template < typename ContiguousRange>
735 void append( const ContiguousRange& range) {
736 append(range.data(), range.data() + range.size());
740template < typename T, size_t SIZE, typename Allocator>
743 if (size > 5000) throw std::runtime_error( "fuzz mode - won't grow that much");
745 size_t old_capacity = this->capacity();
746 size_t new_capacity = old_capacity + old_capacity / 2;
747 if (size > new_capacity) new_capacity = size;
748 T* old_data = this-> data();
750 std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
752 std::uninitialized_copy(old_data, old_data + this->size(),
754 this->set(new_data, new_capacity);
758 if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
764template < typename T, size_t SIZE, typename Allocator>
772 explicit format_error( const char* message) : std::runtime_error(message) {}
774 : std::runtime_error(message) {}
786 std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
787 std::is_same<T, int128_t>::value>;
791template < typename T, FMT_ENABLE_IF(is_ signed<T>::value)>
795template < typename T, FMT_ENABLE_IF(!is_ signed<T>::value)>
800template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
823 : internal_{ static_cast<uint128_t>(low) |
826 uint128_wrapper(uint128_t u) : internal_{u} {}
828 uint64_t high() const FMT_NOEXCEPT { return uint64_t(internal_ >> 64); }
829 uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); }
846# if defined(_MSC_VER) && defined(_M_X64)
847 unsigned char carry = _addcarry_u64(0, low_, n, &low_);
848 _addcarry_u64(carry, high_, 0, &high_);
851 uint64_t sum = low_ + n;
852 high_ += (sum < low_ ? 1 : 0);
868 static const uint64_t powers_of_10_64[];
869 static const uint32_t zero_or_powers_of_10_32_new[];
870 static const uint64_t zero_or_powers_of_10_64_new[];
871 static const uint64_t grisu_pow10_significands[];
872 static const int16_t grisu_pow10_exponents[];
875 static const uint64_t dragonbox_pow10_significands_64[];
878 static const uint64_t log10_2_significand = 0x4d104d427de7fbcc;
879#if !FMT_USE_FULL_CACHE_DRAGONBOX
880 static const uint64_t powers_of_5_64[];
881 static const uint32_t dragonbox_pow10_recovery_errors[];
886 static const char hex_digits[];
887 static const char foreground_color[];
888 static const char background_color[];
890 static const wchar_t wreset_color[5];
891 static const char signs[];
892 static const char left_padding_shifts[5];
893 static const char right_padding_shifts[5];
896 static const uint32_t zero_or_powers_of_10_32[];
897 static const uint64_t zero_or_powers_of_10_64[];
903 static constexpr uint16_t data[] = {
904 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
905 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
906 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
907 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
918#ifdef FMT_BUILTIN_CLZLL
923 auto t = bsr2log10(FMT_BUILTIN_CLZLL(n | 1) ^ 63);
924 return t - (n < data::zero_or_powers_of_10_64_new[t]);
934 if (n < 10) return count;
935 if (n < 100) return count + 1;
936 if (n < 1000) return count + 2;
937 if (n < 10000) return count + 3;
945inline int count_digits(uint128_t n) {
951 if (n < 10) return count;
952 if (n < 100) return count + 1;
953 if (n < 1000) return count + 2;
954 if (n < 10000) return count + 3;
962template < unsigned BITS, typename UInt> inline int count_digits(UInt n) {
966 } while ((n >>= BITS) != 0);
972#if FMT_GCC_VERSION || FMT_CLANG_VERSION
973# define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
975# define FMT_ALWAYS_INLINE __forceinline
977# define FMT_ALWAYS_INLINE inline
981#if FMT_MSC_VER && !FMT_CLANG_VERSION
982# define FMT_SAFEBUFFERS __declspec(safebuffers)
984# define FMT_SAFEBUFFERS
987#ifdef FMT_BUILTIN_CLZ
989inline int count_digits(uint32_t n) {
990 auto t = bsr2log10(FMT_BUILTIN_CLZ(n | 1) ^ 31);
991 return t - (n < data::zero_or_powers_of_10_32_new[t]);
996 return std::numeric_limits<Int>::digits10;
998template <> constexpr int digits10<int128_t>() FMT_NOEXCEPT { return 38; }
999template <> constexpr int digits10<uint128_t>() FMT_NOEXCEPT { return 38; }
1001template < typename Char> FMT_API std::string grouping_impl(locale_ref loc);
1003 return grouping_impl<char>(loc);
1005template <> inline std::string grouping<wchar_t>( locale_ref loc) {
1006 return grouping_impl<wchar_t>(loc);
1009template < typename Char> FMT_API Char thousands_sep_impl(locale_ref loc);
1011 return Char(thousands_sep_impl<char>(loc));
1014 return thousands_sep_impl<wchar_t>(loc);
1017template < typename Char> FMT_API Char decimal_point_impl(locale_ref loc);
1019 return Char(decimal_point_impl<char>(loc));
1022 return decimal_point_impl<wchar_t>(loc);
1026template < typename Char> bool equal2( const Char* lhs, const char* rhs) {
1027 return lhs[0] == rhs[0] && lhs[1] == rhs[1];
1029inline bool equal2( const char* lhs, const char* rhs) {
1030 return memcmp(lhs, rhs, 2) == 0;
1034template < typename Char> void copy2(Char* dst, const char* src) {
1035 *dst++ = static_cast<Char >(*src++);
1036 *dst = static_cast<Char >(*src);
1048template < typename Char, typename UInt>
1054 while ( value >= 100) {
1063 *--out = static_cast<Char >( '0' + value);
1071template < typename Char, typename UInt, typename Iterator,
1076 Char buffer[digits10<UInt>() + 1];
1081template < unsigned BASE_BITS, typename Char, typename UInt>
1083 bool upper = false) {
1087 const char* digits = upper ? "0123456789ABCDEF" : data::hex_digits;
1088 unsigned digit = ( value & ((1 << BASE_BITS) - 1));
1089 *-- buffer = static_cast<Char >(BASE_BITS < 4 ? static_cast<char>( '0' + digit)
1091 } while (( value >>= BASE_BITS) != 0);
1095template < unsigned BASE_BITS, typename Char>
1098 auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
1099 int start = (num_digits + char_digits - 1) / char_digits - 1;
1100 if ( int start_digits = num_digits % char_digits) {
1104 for (; start >= 0; --start) {
1108 for ( int i = 0; i < char_digits; ++i) {
1109 unsigned digit = ( value & ((1 << BASE_BITS) - 1));
1110 *--p = static_cast<Char >(data::hex_digits[digit]);
1111 value >>= BASE_BITS;
1117template < unsigned BASE_BITS, typename Char, typename It, typename UInt>
1120 format_uint<BASE_BITS>( ptr, value, num_digits, upper);
1124 char buffer[num_bits<UInt>() / BASE_BITS + 1];
1125 format_uint<BASE_BITS>( buffer, value, num_digits, upper);
1138 const wchar_t* c_str() const { return &buffer_[0]; }
1139 std::wstring str() const { return {&buffer_[0], size()}; }
1142template < typename T = void> struct null {};
1147 enum { max_size = 4 };
1148 Char data_[max_size] = {Char( ' '), Char(0), Char(0), Char(0)};
1149 unsigned char size_ = 1;
1153 auto size = s. size();
1154 if (size > max_size) {
1158 for ( size_t i = 0; i < size; ++i) data_[i] = s[i];
1159 size_ = static_cast<unsigned char>(size);
1162 size_t size() const { return size_; }
1163 const Char* data() const { return data_; }
1167 return data_[ index];
1206namespace dragonbox {
1213 static const int significand_bits = 23;
1214 static const int exponent_bits = 8;
1215 static const int min_exponent = -126;
1216 static const int max_exponent = 127;
1217 static const int exponent_bias = -127;
1218 static const int decimal_digits = 9;
1219 static const int kappa = 1;
1220 static const int big_divisor = 100;
1221 static const int small_divisor = 10;
1222 static const int min_k = -31;
1223 static const int max_k = 46;
1224 static const int cache_bits = 64;
1225 static const int divisibility_check_by_5_threshold = 39;
1226 static const int case_fc_pm_half_lower_threshold = -1;
1227 static const int case_fc_pm_half_upper_threshold = 6;
1228 static const int case_fc_lower_threshold = -2;
1229 static const int case_fc_upper_threshold = 6;
1230 static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1231 static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1232 static const int shorter_interval_tie_lower_threshold = -35;
1233 static const int shorter_interval_tie_upper_threshold = -35;
1234 static const int max_trailing_zeros = 7;
1239 static const int significand_bits = 52;
1240 static const int exponent_bits = 11;
1241 static const int min_exponent = -1022;
1242 static const int max_exponent = 1023;
1243 static const int exponent_bias = -1023;
1244 static const int decimal_digits = 17;
1245 static const int kappa = 2;
1246 static const int big_divisor = 1000;
1247 static const int small_divisor = 100;
1248 static const int min_k = -292;
1249 static const int max_k = 326;
1250 static const int cache_bits = 128;
1251 static const int divisibility_check_by_5_threshold = 86;
1252 static const int case_fc_pm_half_lower_threshold = -2;
1253 static const int case_fc_pm_half_upper_threshold = 9;
1254 static const int case_fc_lower_threshold = -4;
1255 static const int case_fc_upper_threshold = 9;
1256 static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1257 static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1258 static const int shorter_interval_tie_lower_threshold = -77;
1259 static const int shorter_interval_tie_upper_threshold = -77;
1260 static const int max_trailing_zeros = 16;
1272template < typename T>
1302 *it++ = static_cast<Char >( '-');
1305 *it++ = static_cast<Char >( '+');
1308 const char* top = data::digits[ exp / 100];
1309 if ( exp >= 1000) *it++ = static_cast<Char >(top[0]);
1310 *it++ = static_cast<Char >(top[1]);
1313 const char* d = data::digits[ exp];
1314 *it++ = static_cast<Char >(d[0]);
1315 *it++ = static_cast<Char >(d[1]);
1319template < typename T>
1320int format_float(T value, int precision, float_specs specs, buffer<char>& buf);
1323template < typename T>
1324int snprintf_float(T value, int precision, float_specs specs,
1330template < typename Handler>
1348#ifdef FMT_DEPRECATED_N_SPECIFIER
1362template < typename ErrorHandler = error_handler, typename Char>
1365 auto result = float_specs();
1366 result.showpoint = specs. alt;
1367 switch (specs. type) {
1369 result.format = float_format::general;
1370 result.showpoint |= specs. precision > 0;
1373 result.upper = true;
1376 result.format = float_format::general;
1379 result.upper = true;
1382 result.format = float_format::exp;
1383 result.showpoint |= specs. precision != 0;
1386 result.upper = true;
1389 result.format = float_format::fixed;
1390 result.showpoint |= specs. precision != 0;
1393 result.upper = true;
1396 result.format = float_format::hex;
1398#ifdef FMT_DEPRECATED_N_SPECIFIER
1402 result.locale = true;
1405 eh.on_error( "invalid type specifier");
1411template < typename Char, typename Handler>
1413 Handler&& handler) {
1414 if (!specs) return handler.on_char();
1415 if (specs-> type && specs-> type != 'c') return handler.on_int();
1417 handler.on_error( "invalid format specifier for char");
1421template < typename Char, typename Handler>
1423 if (spec == 0 || spec == 's')
1424 handler.on_string();
1425 else if (spec == 'p')
1426 handler.on_pointer();
1428 handler.on_error( "invalid type specifier");
1431template < typename Char, typename ErrorHandler>
1433 if (spec != 0 && spec != 's') eh.on_error( "invalid type specifier");
1436template < typename Char, typename ErrorHandler>
1438 if (spec != 0 && spec != 'p') eh.on_error( "invalid type specifier");
1453 ErrorHandler::on_error( "invalid type specifier");
1457template < typename ErrorHandler>
1464 : ErrorHandler(eh), type_( type) {}
1472template < typename ErrorHandler>
1476 : ErrorHandler(eh) {}
1482template < typename OutputIt, typename Char>
1484 auto fill_size = fill.size();
1485 if (fill_size == 1) return std::fill_n(it, n, fill[0]);
1486 for ( size_t i = 0; i < n; ++i) it = std::copy_n( fill.data(), fill_size, it);
1497 size_t width, F&& f) {
1500 size_t padding = spec_width > width ? spec_width - width : 0;
1502 : data::right_padding_shifts;
1503 size_t left_padding = padding >> shifts[specs. align];
1504 auto it = reserve(out, size + padding * specs. fill.size());
1505 it = fill(it, left_padding, specs. fill);
1507 it = fill(it, padding - left_padding, specs. fill);
1516 return write_padded<align>(out, specs, size, size, f);
1519template < typename Char, typename OutputIt>
1524 const char* data = bytes.data();
1525 return copy_str<Char>(data, data + bytes.size(), it);
1537 : size(prefix.size() + to_unsigned(num_digits)), padding(0) {
1541 padding = width - size;
1544 } else if (specs. precision > num_digits) {
1554template < typename OutputIt, typename Char, typename F>
1559 return write_padded<align::right>(out, specs, data.size, [=](iterator it) {
1560 if (prefix.size() != 0)
1561 it = copy_str<Char>(prefix.begin(), prefix.end(), it);
1562 it = std::fill_n(it, data.padding, static_cast<Char>( '0'));
1567template < typename StrChar, typename Char, typename OutputIt>
1571 auto size = s. size();
1574 auto width = specs. width != 0
1578 return write_padded(out, specs, size, width, [=](iterator it) {
1579 return copy_str<Char>( data, data + size, it);
1584template < typename OutputIt, typename Char, typename UInt> struct int_writer {
1597 template < typename Int>
1603 abs_value(static_cast<UInt>( value)),
1605 static_assert(std::is_same<uint32_or_64_or_128_t<Int>, UInt>::value, "");
1609 abs_value = 0 - abs_value;
1619 out, num_digits, get_prefix(), specs, [ this, num_digits]( iterator it) {
1620 return format_decimal<Char>(it, abs_value, num_digits).end;
1626 prefix[prefix_size++] = '0';
1627 prefix[prefix_size++] = specs. type;
1629 int num_digits = count_digits<4>(abs_value);
1630 out = write_int(out, num_digits, get_prefix(), specs,
1632 return format_uint<4, Char>(it, abs_value, num_digits,
1639 prefix[prefix_size++] = '0';
1640 prefix[prefix_size++] = static_cast<char>(specs. type);
1642 int num_digits = count_digits<1>(abs_value);
1643 out = write_int(out, num_digits, get_prefix(), specs,
1645 return format_uint<1, Char>(it, abs_value, num_digits);
1650 int num_digits = count_digits<3>(abs_value);
1651 if (specs. alt && specs. precision <= num_digits && abs_value != 0) {
1654 prefix[prefix_size++] = '0';
1656 out = write_int(out, num_digits, get_prefix(), specs,
1658 return format_uint<3, Char>(it, abs_value, num_digits);
1662 enum { sep_size = 1 };
1665 std::string groups = grouping<Char>(locale);
1666 if (groups.empty()) return on_dec();
1667 auto sep = thousands_sep<Char>(locale);
1668 if (!sep) return on_dec();
1670 int size = num_digits, n = num_digits;
1671 std::string::const_iterator group = groups.cbegin();
1672 while (group != groups.cend() && n > *group && *group > 0 &&
1673 *group != max_value<char>()) {
1678 if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back());
1682 size += static_cast<int>(prefix_size);
1687 int digit_index = 0;
1688 group = groups.cbegin();
1690 for ( int i = num_digits - 1; i > 0; --i) {
1691 *p-- = static_cast<Char >(digits[i]);
1692 if (*group <= 0 || ++digit_index % *group != 0 ||
1693 *group == max_value<char>())
1695 if (group + 1 != groups.cend()) {
1703 *p-- = static_cast<Char >(*digits);
1704 if (prefix_size != 0) *p = static_cast<Char >( '-');
1706 out = write_padded<align::right>(
1707 out, specs, usize, usize,
1711 void on_chr() { *out++ = static_cast<Char >(abs_value); }
1718template < typename Char, typename OutputIt>
1723 isinf ? (fspecs. upper ? "INF" : "inf") : (fspecs. upper ? "NAN" : "nan");
1724 constexpr size_t str_size = 3;
1726 auto size = str_size + ( sign ? 1 : 0);
1728 return write_padded(out, specs, size, [=](iterator it) {
1729 if ( sign) *it++ = static_cast<Char >(data::signs[ sign]);
1730 return copy_str<Char>(str, str + str_size, it);
1744template < typename T>
1749template < typename Char, typename OutputIt>
1751 int& significand_size) {
1752 return copy_str<Char>(significand, significand + significand_size, out);
1754template < typename Char, typename OutputIt, typename UInt>
1756 int significand_size) {
1757 return format_decimal<Char>(out, significand, significand_size).end;
1760template < typename Char, typename UInt,
1763 int significand_size, int integral_size,
1764 Char decimal_point) {
1767 auto end = format_decimal(out + 1, significand, significand_size).end;
1768 if (integral_size == 1)
1771 std::copy_n(out + 1, integral_size, out);
1776template < typename OutputIt, typename UInt, typename Char,
1779 int significand_size, int integral_size,
1780 Char decimal_point) {
1782 Char buffer[digits10<UInt>() + 2];
1788template < typename OutputIt, typename Char>
1790 int significand_size, int integral_size,
1791 Char decimal_point) {
1796 significand + significand_size, out);
1799template < typename OutputIt, typename DecimalFP, typename Char>
1802 Char decimal_point) {
1803 auto significand = fp.significand;
1805 static const Char zero = static_cast<Char >( '0');
1810 int output_exp = fp.exponent + significand_size - 1;
1811 auto use_exp_format = [=]() {
1812 if (fspecs. format == float_format::exp) return true;
1813 if (fspecs. format != float_format::general) return false;
1816 const int exp_lower = -4, exp_upper = 16;
1817 return output_exp < exp_lower ||
1820 if (use_exp_format()) {
1823 num_zeros = (std::max)(fspecs. precision - significand_size, 0);
1825 } else if (significand_size == 1) {
1828 auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
1830 if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
1833 char exp_char = fspecs. upper ? 'E' : 'e';
1834 auto write = [=](iterator it) {
1835 if ( sign) *it++ = static_cast<Char >(data::signs[ sign]);
1839 if (num_zeros > 0) it = std::fill_n(it, num_zeros, zero);
1840 *it++ = static_cast<Char >(exp_char);
1841 return write_exponent<Char>(output_exp, it);
1843 return specs. width > 0 ? write_padded<align::right>(out, specs, size, write)
1847 int exp = fp.exponent + significand_size;
1848 if ( fp.exponent >= 0) {
1853 if (num_zeros > 5000)
1854 throw std::runtime_error( "fuzz mode - avoiding excessive cpu use");
1857 if (num_zeros <= 0 && fspecs. format != float_format::fixed) num_zeros = 1;
1858 if (num_zeros > 0) size += to_unsigned(num_zeros);
1860 return write_padded<align::right>(out, specs, size, [&](iterator it) {
1861 if ( sign) *it++ = static_cast<Char >(data::signs[ sign]);
1862 it = write_significand<Char>(it, significand, significand_size);
1863 it = std::fill_n(it, fp.exponent, zero);
1866 return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it;
1868 } else if ( exp > 0) {
1871 size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
1872 return write_padded<align::right>(out, specs, size, [&](iterator it) {
1873 if ( sign) *it++ = static_cast<Char >(data::signs[ sign]);
1876 return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it;
1880 int num_zeros = - exp;
1881 if (significand_size == 0 && fspecs. precision >= 0 &&
1886 return write_padded<align::right>(out, specs, size, [&](iterator it) {
1887 if ( sign) *it++ = static_cast<Char >(data::signs[ sign]);
1889 if (num_zeros == 0 && significand_size == 0 && !fspecs. showpoint) return it;
1891 it = std::fill_n(it, num_zeros, zero);
1892 return write_significand<Char>(it, significand, significand_size);
1896template < typename Char, typename OutputIt, typename T,
1900 if (const_check(!is_supported_floating_point(value))) return out;
1901 float_specs fspecs = parse_float_type_spec(specs);
1902 fspecs.sign = specs. sign;
1903 if (std::signbit(value)) {
1910 if (!std::isfinite(value))
1915 *it++ = static_cast<Char >(data::signs[fspecs.sign]);
1922 if (fspecs.format == float_format::hex) {
1923 if (fspecs.sign) buffer. push_back(data::signs[fspecs.sign]);
1928 if (fspecs.format == float_format::exp) {
1929 if (precision == max_value<int>())
1934 if ( const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1935 fspecs.use_grisu = is_fast_float<T>();
1937 fspecs.precision = precision;
1939 fspecs.locale ? decimal_point<Char>(loc) : static_cast<Char>( '.');
1940 auto fp = big_decimal_fp{buffer. data(), static_cast<int>(buffer. size()), exp};
1941 return write_float(out, fp, specs, fspecs, point);
1944template < typename Char, typename OutputIt, typename T,
1954 auto sign_bit = bits & (uint(1) << (num_bits<uint>() - 1));
1955 if (sign_bit != 0) {
1961 uint mask = exponent_mask<floaty>();
1962 if (( bits & mask) == mask)
1965 auto dec = dragonbox::to_decimal( static_cast<floaty >( value));
1966 return write_float(out, dec, specs, fspecs, static_cast<Char >( '.'));
1969template < typename Char, typename OutputIt, typename T,
1971 !is_fast_float<T>::value)>
1972inline OutputIt write(OutputIt out, T value) {
1976template < typename Char, typename OutputIt>
1986template < typename Char, typename OutputIt, typename UIntPtr>
1989 int num_digits = count_digits<4>( value);
1992 auto write = [=](iterator it) {
1993 *it++ = static_cast<Char >( '0');
1994 *it++ = static_cast<Char >( 'x');
1995 return format_uint<4, Char>(it, value, num_digits);
1997 return specs ? write_padded<align::right>(out, *specs, size, write)
2005template < typename Char, typename OutputIt>
2011template < typename Char, typename OutputIt,
2015 it = copy_str<Char>( value.begin(), value.end(), it);
2019template < typename Char, typename OutputIt>
2022 it = std::copy( value.begin(), value.end(), it);
2026template < typename Char>
2033template < typename Char, typename OutputIt, typename T,
2035 !std::is_same<T, bool>::value &&
2036 !std::is_same<T, Char>::value)>
2037OutputIt write(OutputIt out, T value) {
2038 auto abs_value = static_cast<uint32_or_64_or_128_t<T> >(value);
2039 bool negative = is_negative(value);
2041 if (negative) abs_value = ~abs_value + 1;
2042 int num_digits = count_digits(abs_value);
2043 auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
2044 auto it = reserve(out, size);
2045 if ( auto ptr = to_pointer<Char>(it, size)) {
2046 if (negative) * ptr++ = static_cast<Char >( '-');
2047 format_decimal<Char>( ptr, abs_value, num_digits);
2050 if (negative) *it++ = static_cast<Char >( '-');
2051 it = format_decimal<Char>(it, abs_value, num_digits).end;
2055template < typename Char, typename OutputIt>
2060template < typename Char, typename OutputIt>
2067template < typename Char, typename OutputIt>
2072 auto length = std::char_traits<Char>::length( value);
2078template < typename Char, typename OutputIt>
2083template < typename Char, typename OutputIt, typename T>
2084auto write(OutputIt out, const T& value) -> typename std::enable_if<
2089 using formatter_type =
2091 typename context_type::template formatter_type<T>,
2093 context_type ctx(out, {}, {});
2094 return formatter_type().format( value, ctx);
2107 return write<Char>(out, value);
2113 handle. format(parse_ctx, format_ctx);
2114 return format_ctx.out();
2118template < typename OutputIt, typename Char,
2119 typename ErrorHandler = error_handler>
2152 template < typename Ch, FMT_ENABLE_IF(std::is_same<Ch, Char>::value)>
2159 it = copy_str<Char>( value.begin(), value.end(), it);
2162 static_assert(std::is_same<Char, wchar_t>::value, "");
2164 it = std::copy( value.begin(), value.end(), it);
2167 template < typename Ch>
2169 auto width = specs. width != 0
2173 return copy_str<Char>(s, s + size, it);
2177 template < typename Ch>
2183 out_ = write_ptr<char_type>(out_, to_uintptr(p), specs_);
2231 auto length = std::char_traits<char_type>::length( value);
2239 : out_(out), locale_(loc), specs_(s) {}
2246 template < typename T, FMT_ENABLE_IF(is_ integral<T>::value)>
2262 if (specs_ && specs_-> type) return (* this)( value ? 1 : 0);
2267 template < typename T, FMT_ENABLE_IF(std::is_ floating_po int<T>::value)>
2273 FMT_ASSERT( false, "unsupported float argument type");
2295 write_pointer( value);
2301template < typename OutputIt, typename Char>
2327 : base(ctx.out(), specs, ctx.locale()),
2329 parse_ctx_(parse_ctx),
2332 using base::operator();
2337 handle. format(*parse_ctx_, ctx_);
2343 return ( 'a' <= c && c <= 'z') || ( 'A' <= c && c <= 'Z') || '_' == c;
2348template < typename Char, typename ErrorHandler>
2350 ErrorHandler&& eh) {
2351 FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
2354 constexpr unsigned max_int = max_value<int>();
2355 unsigned big = max_int / 10;
2359 value = max_int + 1;
2364 } while (begin != end && '0' <= *begin && *begin <= '9');
2365 if ( value > max_int) eh.on_error( "number is too big");
2366 return static_cast<int>( value);
2379 : parse_ctx_(parse_ctx), ctx_(ctx) {}
2382 h. format(parse_ctx_, ctx_);
2388template < typename T>
2391 !std::is_same<T, char>::value &&
2392 !std::is_same<T, wchar_t>::value>;
2398 template < typename T, FMT_ENABLE_IF(is_ integer<T>::value)>
2401 return static_cast<unsigned long long>( value);
2404 template < typename T, FMT_ENABLE_IF(!is_ integer<T>::value)>
2406 handler_.on_error( "width is not integer");
2418 template < typename T, FMT_ENABLE_IF(is_ integer<T>::value)>
2421 return static_cast<unsigned long long>( value);
2424 template < typename T, FMT_ENABLE_IF(!is_ integer<T>::value)>
2426 handler_.on_error( "precision is not integer");
2441 : specs_(other.specs_) {}
2454 specs_. fill[0] = Char( '0');
2464 specs_. type = static_cast<char>( type);
2474 : error_handler_(eh), arg_type_(arg_type) {}
2478 error_handler_.on_error( "format specifier requires numeric argument");
2482 require_numeric_argument();
2484 arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
2485 error_handler_.on_error( "format specifier requires signed argument");
2491 error_handler_.on_error( "precision not allowed for this argument type");
2513 : Handler(other), checker_( error_handler(), other.arg_type_) {}
2517 Handler::on_align( align);
2527 Handler::on_minus();
2532 Handler::on_space();
2548template < template < typename> class Handler, typename FormatArg,
2549 typename ErrorHandler>
2552 if ( value > to_unsigned(max_value<int>())) eh.on_error( "number is too big");
2553 return static_cast<int>( value);
2558template < typename Context, typename ID>
2560 auto arg = ctx.arg( id);
2561 if (! arg) ctx.on_error( "argument not found");
2566template < typename ParseContext, typename Context>
2572 ParseContext& parse_ctx, Context& ctx)
2574 parse_context_(parse_ctx),
2578 this->specs_. width = get_dynamic_spec<width_checker>(
2579 get_arg(arg_id), context_.error_handler());
2583 this->specs_. precision = get_dynamic_spec<precision_checker>(
2584 get_arg(arg_id), context_.error_handler());
2587 void on_error( const char* message) { context_.on_error(message); }
2598 parse_context_.check_arg_id(arg_id);
2603 parse_context_.check_arg_id(arg_id);
2623 kind = arg_id_kind::index;
2641template < typename Char>
2649template < typename ParseContext>
2651 : public specs_setter<typename ParseContext::char_type> {
2661 specs_(other.specs_),
2662 context_(other.context_) {}
2665 specs_.width_ref = make_arg_ref(arg_id);
2669 specs_.precision_ref = make_arg_ref(arg_id);
2673 context_.on_error(message);
2680 context_.check_arg_id(arg_id);
2689 context_.check_arg_id(arg_id);
2691 context_.begin(), to_unsigned(context_.end() - context_.begin()));
2699template < typename Char, typename IDHandler>
2701 IDHandler&& handler) {
2704 if (c == '}' || c == ':') {
2708 if (c >= '0' && c <= '9') {
2714 if (begin == end || (*begin != '}' && *begin != ':'))
2715 handler.on_error( "invalid format string");
2721 handler.on_error( "invalid format string");
2727 } while (it != end && ( is_name_start(c = *it) || ( '0' <= c && c <= '9')));
2739 handler.on_dynamic_width( id);
2743 handler.on_error(message);
2756 handler.on_dynamic_precision( id);
2760 handler.on_error(message);
2766template < typename Char>
2769 constexpr char lengths[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2770 0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0};
2771 int len = lengths[ static_cast<unsigned char>(*begin) >> 3];
2780 return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
2784template < typename Char, FMT_ENABLE_IF(std::is_ integral<Char>::value)>
2788template < typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
2794template < typename Char, typename Handler>
2796 Handler&& handler) {
2800 if (p >= end) p = begin;
2809#if FMT_DEPRECATED_NUMERIC_ALIGN
2822 return handler.on_error( "invalid fill character '{'"), begin;
2827 handler.on_align( align);
2829 } else if (p == begin) {
2837template < typename Char, typename Handler>
2839 Handler&& handler) {
2841 if ( '0' <= *begin && *begin <= '9') {
2843 } else if (*begin == '{') {
2847 if (begin == end || *begin != '}')
2848 return handler.on_error( "invalid format string"), begin;
2854template < typename Char, typename Handler>
2856 Handler&& handler) {
2858 auto c = begin != end ? *begin : Char();
2859 if ( '0' <= c && c <= '9') {
2861 } else if (c == '{') {
2867 if (begin == end || *begin++ != '}')
2868 return handler.on_error( "invalid format string"), begin;
2870 return handler.on_error( "missing precision specifier"), begin;
2872 handler.end_precision();
2878template < typename Char, typename SpecHandler>
2880 SpecHandler&& handler) {
2881 if (begin == end) return begin;
2884 if (begin == end) return begin;
2901 if (begin == end) return begin;
2903 if (*begin == '#') {
2905 if (++begin == end) return begin;
2909 if (*begin == '0') {
2911 if (++begin == end) return begin;
2915 if (begin == end) return begin;
2918 if (*begin == '.') {
2923 if (begin != end && *begin != '}') handler.on_type(*begin++);
2928template < bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
2930 for (out = first; out != last; ++out) {
2931 if (*out == value) return true;
2937inline bool find<false, char>( const char* first, const char* last, char value,
2939 out = static_cast<const char* >(
2941 return out != nullptr;
2951 arg_id = handler.on_arg_id( id);
2954 handler.on_error(message);
2958template < typename Char, typename Handler>
2961 Handler&& handler) {
2963 if (begin == end) return handler.on_error( "invalid format string"), end;
2964 if (*begin == '}') {
2965 handler.on_replacement_field(handler.on_arg_id(), begin);
2966 } else if (*begin == '{') {
2967 handler.on_text(begin, begin + 1);
2971 Char c = begin != end ? *begin : Char();
2973 handler.on_replacement_field(adapter.arg_id, begin);
2974 } else if (c == ':') {
2975 begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
2976 if (begin == end || *begin != '}')
2977 return handler.on_error( "unknown format specifier"), end;
2979 return handler.on_error( "missing '}' in format string"), end;
2985template < bool IS_CONSTEXPR, typename Char, typename Handler>
2988 auto begin = format_str. data();
2989 auto end = begin + format_str. size();
2990 if (end - begin < 32) {
2992 const Char* p = begin;
2996 handler.on_text(begin, p - 1);
2998 } else if (c == '}') {
2999 if (p == end || *p != '}')
3000 return handler.on_error( "unmatched '}' in format string");
3001 handler.on_text(begin, p);
3005 handler.on_text(begin, end);
3009 FMT_CONSTEXPR void operator()( const Char* pbegin, const Char* pend) {
3010 if (pbegin == pend) return;
3012 const Char* p = nullptr;
3013 if (!find<IS_CONSTEXPR>(pbegin, pend, '}', p))
3014 return handler_.on_text(pbegin, pend);
3016 if (p == pend || *p != '}')
3017 return handler_.on_error( "unmatched '}' in format string");
3018 handler_.on_text(pbegin, p);
3024 while (begin != end) {
3027 const Char* p = begin;
3028 if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, '{', p))
3029 return write(begin, end);
3035template < typename T, typename ParseContext>
3037 ParseContext& ctx) {
3038 using char_type = typename ParseContext::char_type;
3047 return f.parse(ctx);
3050template < typename OutputIt, typename Char, typename Context>
3057 : parse_context(str), context(out, format_args, loc) {}
3059 void on_text( const Char* begin, const Char* end) {
3061 auto out = context.out();
3062 auto&& it = reserve(out, size);
3063 it = std::copy_n(begin, size, it);
3064 context.advance_to(out);
3070 int arg_id = context.arg_id( id);
3071 if (arg_id < 0) on_error( "argument not found");
3085 if ( arg.type() == type::custom_type) {
3088 return parse_context. begin();
3092 specs. type = static_cast<char>(*begin++);
3100 if (begin == end || *begin != '}')
3101 on_error( "missing '}' in format string");
3113template < typename Char, typename ErrorHandler = error_handler>
3123 ErrorHandler eh = {})
3124 : base(format_str, eh), num_args_(num_args) {}
3127 int id = base::next_arg_id();
3128 if ( id >= num_args_) this->on_error( "argument not found");
3133 base::check_arg_id( id);
3134 if ( id >= num_args_) this->on_error( "argument not found");
3136 using base::check_arg_id;
3139template < typename Char, typename ErrorHandler, typename... Args>
3144 : context_(format_str, num_args, eh),
3152 on_error( "compile-time checks don't support named arguments");
3161 return id < num_args ? parse_funcs_[id](context_) : begin;
3165 context_.on_error(message);
3170 enum { num_args = sizeof...(Args) };
3180template < typename Char, size_t N>
3182 const Char (&s)[N]) {
3186 N - ((std::char_traits<Char>::to_int_type(s[N - 1]) == 0) ? 1 : 0)};
3190template < typename Char>
3193 return {s.data(), s.size()};
3196#define FMT_STRING_IMPL(s, base) \
3199 struct FMT_COMPILE_STRING : base { \
3200 using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
3201 FMT_MAYBE_UNUSED FMT_CONSTEXPR \
3202 operator fmt::basic_string_view<char_type>() const { \
3203 return fmt::detail::compile_string_to_view<char_type>(s); \
3206 return FMT_COMPILE_STRING(); \
3219#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string)
3221template < typename... Args, typename S,
3228 (parse_format_string<true>(s, checker(s, {})), true);
3229 (void)invalid_format;
3232template < template < typename> class Handler, typename Context>
3236 case arg_id_kind::none:
3238 case arg_id_kind::index:
3240 ctx.error_handler());
3242 case arg_id_kind::name:
3244 ctx.error_handler());
3258template < typename OutputIt, typename Char>
3295 template < typename... Args>
3297 : std::runtime_error( "") {
3338 enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
3339 mutable char buffer_[buffer_size];
3349 bool negative = value < 0;
3350 if (negative) abs_value = 0 - abs_value;
3351 auto begin = format_unsigned(abs_value);
3352 if (negative) *--begin = '-';
3359 explicit format_int( long long value) : str_(format_signed(value)) {}
3360 explicit format_int( unsigned value) : str_(format_unsigned(value)) {}
3361 explicit format_int( unsigned long value) : str_(format_unsigned(value)) {}
3363 : str_(format_unsigned(value)) {}
3374 const char* data() const { return str_; }
3381 buffer_[buffer_size - 1] = '\0';
3390 std::string str() const { return std::string(str_, size()); }
3395template < typename T, typename Char>
3403 template < typename ParseContext>
3409 auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
3410 auto eh = ctx.error_handler();
3422 handle_int_type_spec(specs_. type,
3439 FMT_ASSERT( false, "double support disabled");
3445 FMT_ASSERT( false, "long double support disabled");
3465 template < typename FormatContext>
3466 auto format( const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3468 specs_.width_ref, ctx);
3470 specs_. precision, specs_.precision_ref, ctx);
3472 typename FormatContext::char_type>;
3481#define FMT_FORMAT_AS(Type, Base) \
3482 template <typename Char> \
3483 struct formatter<Type, Char> : formatter<Base, Char> { \
3484 template <typename FormatContext> \
3485 auto format(Type const& val, FormatContext& ctx) -> decltype(ctx.out()) { \
3486 return formatter<Base, Char>::format(val, ctx); \
3501template < typename Char>
3503 template < typename FormatContext>
3504 auto format( void* val, FormatContext& ctx) -> decltype(ctx.out()) {
3509template < typename Char, size_t N>
3511 template < typename FormatContext>
3512 auto format( const Char* val, FormatContext& ctx) -> decltype(ctx.out()) {
3540 template < typename ParseContext>
3541 auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3542 format_str_ = ctx.begin();
3545 return parse_format_specs(ctx.begin(), ctx.end(), handler);
3548 template < typename T, typename FormatContext>
3549 auto format( const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3554 switch (specs_. sign) {
3570 typename FormatContext::char_type>;
3579 specs_.width_ref, ctx);
3581 specs_. precision, specs_.precision_ref, ctx);
3588template < typename Char, typename ErrorHandler>
3603template < typename T> inline const void* ptr( const T* p) { return p; }
3604template < typename T> inline const void* ptr( const std::unique_ptr<T>& p) {
3607template < typename T> inline const void* ptr( const std::shared_ptr<T>& p) {
3625 template < typename ParseContext>
3630 auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
3635 template < typename FormatContext>
3645template < typename It, typename Sentinel, typename Char>
3652 : begin(b), end(e), sep(s) {}
3655template < typename It, typename Sentinel, typename Char>
3657 : formatter<typename std::iterator_traits<It>::value_type, Char> {
3658 template < typename FormatContext>
3660 -> decltype(ctx.out()) {
3662 auto it = value.begin;
3663 auto out = ctx.out();
3664 if (it != value.end) {
3665 out = base::format(*it++, ctx);
3666 while (it != value.end) {
3667 out = std::copy(value.sep.begin(), value.sep.end(), out);
3668 ctx.advance_to(out);
3669 out = base::format(*it++, ctx);
3680template < typename It, typename Sentinel>
3682 return {begin, end, sep};
3685template < typename It, typename Sentinel>
3687 return {begin, end, sep};
3706template < typename Range>
3709 return join(std::begin(range), std::end(range), sep);
3712template < typename Range>
3715 return join(std::begin(range), std::end(range), sep);
3729template < typename T, FMT_ENABLE_IF(!std::is_ integral<T>::value)>
3736template < typename T, FMT_ENABLE_IF(std::is_ integral<T>::value)>
3741 char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
3742 char* begin = buffer;
3749template < typename T> inline std::wstring to_wstring( const T& value) {
3750 return format(L "{}", value);
3753template < typename Char, size_t SIZE>
3755 auto size = buf. size();
3757 return std::basic_string<Char>(buf. data(), size);
3760template < typename Char>
3766 auto out = buffer_appender<Char>(buf);
3768 auto arg = args.get(0);
3769 if (! arg) error_handler().on_error( "argument not found");
3774 format_handler<iterator, Char, buffer_context<Char>> h(out, format_str, args,
3776 parse_format_string<false>(format_str, h);
3779#ifndef FMT_HEADER_ONLY
3785extern template FMT_API std::string grouping_impl<char>(locale_ref loc);
3786extern template FMT_API std::string grouping_impl<wchar_t>(locale_ref loc);
3787extern template FMT_API char thousands_sep_impl<char>(locale_ref loc);
3788extern template FMT_API wchar_t thousands_sep_impl<wchar_t>(locale_ref loc);
3791extern template int format_float<double>( double value, int precision,
3792 float_specs specs, buffer<char>& buf);
3793extern template int format_float<long double>( long double value, int precision,
3797 buffer<char>& buf) = delete;
3798extern template int snprintf_float<double>( double value, int precision,
3801extern template int snprintf_float<long double>( long double value,
3808template < typename S, typename Char = char_t<S>,
3809 FMT_ENABLE_IF(detail::is_ string<S>::value)>
3820 const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
3825template < typename OutputIt, typename Char = char>
3828template < typename OutputIt, typename Char = char>
3831template < typename OutputIt, typename Char = typename OutputIt::value_type>
3834template < typename OutputIt, typename Char = typename OutputIt::value_type>
3838template < typename OutputIt, typename Char, typename... Args>
3844template < typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
3853template < typename Char, FMT_ENABLE_IF(std::is_same<Char, wchar_t>::value)>
3859 if (std::fputws(buffer. data(), f) == -1)
3863template < typename Char, FMT_ENABLE_IF(std::is_same<Char, wchar_t>::value)>
3865 vprint(stdout, format_str, args);
3868#if FMT_USE_USER_DEFINED_LITERALS
3871# if FMT_USE_UDL_TEMPLATE
3872template < typename Char, Char... CHARS> class udl_formatter {
3874 template < typename... Args>
3875 std::basic_string<Char> operator()(Args&&... args) const {
3881template < typename Char> struct udl_formatter {
3884 template < typename... Args>
3885 std::basic_string<Char> operator()(Args&&... args) const {
3886 return format(str, std::forward<Args>(args)...);
3891template < typename Char> struct udl_arg {
3894 template < typename T> named_arg<Char, T> operator=(T&& value) const {
3895 return {str, std::forward<T>(value)};
3900inline namespace literals {
3901# if FMT_USE_UDL_TEMPLATE
3902# pragma GCC diagnostic push
3903# pragma GCC diagnostic ignored "-Wpedantic"
3904# if FMT_CLANG_VERSION
3905# pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
3907template < typename Char, Char... CHARS>
3908FMT_CONSTEXPR detail::udl_formatter<Char, CHARS...> operator""_format() {
3911# pragma GCC diagnostic pop
3923FMT_CONSTEXPR detail::udl_formatter<char> operator"" _format( const char* s,
3927FMT_CONSTEXPR detail::udl_formatter<wchar_t> operator"" _format(
3928 const wchar_t* s, size_t n) {
3943FMT_CONSTEXPR detail::udl_arg<char> operator"" _a( const char* s, size_t) {
3946FMT_CONSTEXPR detail::udl_arg<wchar_t> operator"" _a( const wchar_t* s, size_t) {
3953#ifdef FMT_HEADER_ONLY
3954# define FMT_FUNC inline
FMT_CONSTEXPR void advance_to(iterator it)
FMT_CONSTEXPR void check_arg_id(int)
constexpr iterator begin() const FMT_NOEXCEPT
FMT_CONSTEXPR int next_arg_id()
basic_memory_buffer & operator=(basic_memory_buffer &&other) FMT_NOEXCEPT
void resize(size_t count)
void move(basic_memory_buffer &other)
Allocator get_allocator() const
void reserve(size_t new_capacity)
basic_memory_buffer(const Allocator &alloc=Allocator())
void append(const ContiguousRange &range)
const T & const_reference
basic_memory_buffer(basic_memory_buffer &&other) FMT_NOEXCEPT
void grow(size_t size) final FMT_OVERRIDE
constexpr size_t size() const
constexpr const Char * data() const
void try_reserve(size_t new_capacity)
void append(const U *begin, const U *end)
void try_resize(size_t count)
void push_back(const T &value)
void set(T *buf_data, size_t buf_capacity) FMT_NOEXCEPT
size_t size() const FMT_NOEXCEPT
size_t capacity() const FMT_NOEXCEPT
FMT_CONSTEXPR void on_char()
FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
FMT_CONSTEXPR void on_int()
FMT_CONSTEXPR void check_arg_id(int id)
FMT_CONSTEXPR int next_arg_id()
FMT_CONSTEXPR compile_parse_context(basic_string_view< Char > format_str, int num_args=max_value< int >(), ErrorHandler eh={})
counting_iterator & operator++()
std::output_iterator_tag iterator_category
counting_iterator operator++(int)
value_type operator*() const
std::ptrdiff_t difference_type
friend counting_iterator operator+(counting_iterator it, difference_type n)
FMT_CONSTEXPR cstring_type_checker(ErrorHandler eh)
FMT_CONSTEXPR void on_string()
FMT_CONSTEXPR void on_pointer()
FMT_CONSTEXPR void on_error(const char *message)
FMT_CONSTEXPR arg_ref_type make_arg_ref(auto_id)
dynamic_format_specs< char_type > & specs_
FMT_CONSTEXPR arg_ref_type make_arg_ref(int arg_id)
FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs< char_type > &specs, ParseContext &ctx)
FMT_CONSTEXPR void on_dynamic_width(Id arg_id)
FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view< char_type > arg_id)
typename ParseContext::char_type char_type
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id)
FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler &other)
static FMT_CONSTEXPR_DECL const int significand_size
FMT_CONSTEXPR void on_hex()
FMT_CONSTEXPR void on_num()
FMT_CONSTEXPR int_type_checker(ErrorHandler eh)
FMT_CONSTEXPR void on_dec()
FMT_CONSTEXPR void on_chr()
FMT_CONSTEXPR void on_oct()
FMT_CONSTEXPR void on_bin()
FMT_CONSTEXPR void on_error()
FMT_CONSTEXPR void require_numeric_argument()
FMT_CONSTEXPR void check_sign()
FMT_CONSTEXPR numeric_specs_checker(ErrorHandler &eh, detail::type arg_type)
FMT_CONSTEXPR void check_precision()
ErrorHandler & error_handler_
FMT_CONSTEXPR precision_checker(ErrorHandler &eh)
FMT_CONSTEXPR unsigned long long operator()(T)
FMT_CONSTEXPR unsigned long long operator()(T value)
numeric_specs_checker< Handler > checker_
FMT_CONSTEXPR Handler & error_handler()
FMT_CONSTEXPR specs_checker(const specs_checker &other)
FMT_CONSTEXPR void on_space()
FMT_CONSTEXPR void on_minus()
FMT_CONSTEXPR void on_zero()
FMT_CONSTEXPR void on_plus()
FMT_CONSTEXPR void end_precision()
FMT_CONSTEXPR void on_hash()
FMT_CONSTEXPR specs_checker(const Handler &handler, detail::type arg_type)
FMT_CONSTEXPR void on_align(align_t align)
typename Context::format_arg format_arg
FMT_CONSTEXPR format_arg get_arg(basic_string_view< char_type > arg_id)
FMT_CONSTEXPR format_arg get_arg(auto_id)
void on_error(const char *message)
ParseContext & parse_context_
FMT_CONSTEXPR format_arg get_arg(int arg_id)
FMT_CONSTEXPR specs_handler(basic_format_specs< char_type > &specs, ParseContext &parse_ctx, Context &ctx)
FMT_CONSTEXPR void on_dynamic_width(Id arg_id)
typename Context::char_type char_type
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id)
FMT_CONSTEXPR void on_fill(basic_string_view< Char > fill)
FMT_CONSTEXPR specs_setter(const specs_setter &other)
FMT_CONSTEXPR void on_type(Char type)
FMT_CONSTEXPR specs_setter(basic_format_specs< Char > &specs)
FMT_CONSTEXPR void on_width(int width)
FMT_CONSTEXPR void on_space()
FMT_CONSTEXPR void on_minus()
basic_format_specs< Char > & specs_
FMT_CONSTEXPR void on_zero()
FMT_CONSTEXPR void on_plus()
FMT_CONSTEXPR void end_precision()
FMT_CONSTEXPR void on_precision(int precision)
FMT_CONSTEXPR void on_hash()
FMT_CONSTEXPR void on_align(align_t align)
truncating_iterator & operator++()
value_type & operator*() const
truncating_iterator operator++(int)
typename truncating_iterator_base< OutputIt >::value_type value_type
truncating_iterator_base< OutputIt >::value_type blackhole_
truncating_iterator(OutputIt out, size_t limit)
truncating_iterator & operator++()
truncating_iterator & operator*()
truncating_iterator & operator++(int)
truncating_iterator & operator=(T val)
truncating_iterator(OutputIt out, size_t limit)
std::output_iterator_tag iterator_category
typename std::iterator_traits< OutputIt >::value_type value_type
truncating_iterator_base(OutputIt out, size_t limit)
const wchar_t * c_str() const
FMT_CONSTEXPR unsigned long long operator()(T)
FMT_CONSTEXPR unsigned long long operator()(T value)
FMT_CONSTEXPR width_checker(ErrorHandler &eh)
system_error(int error_code, string_view message, const Args &... args)
~system_error() FMT_NOEXCEPT FMT_OVERRIDE
system_error & operator=(const system_error &)=default
system_error(const system_error &)=default
system_error & operator=(system_error &&)=default
system_error(system_error &&)=default
OutputIt vformat_to(OutputIt out, const text_style &ts, basic_string_view< Char > format_str, basic_format_args< buffer_context< type_identity_t< Char > > > args)
auto format_to(OutputIt out, const text_style &ts, const S &format_str, Args &&... args) -> typename std::enable_if< enable, OutputIt >::type
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
void vprint(std::FILE *f, const text_style &ts, const S &format, basic_format_args< buffer_context< type_identity_t< Char > > > args)
typename std::enable_if< B, T >::type enable_if_t
#define FMT_ASSERT(condition, message)
std::integral_constant< bool, B > bool_constant
basic_string_view< char > string_view
typename std::remove_reference< T >::type remove_reference_t
typename detail::char_t_impl< S >::type char_t
basic_string_view< wchar_t > wstring_view
detail::named_arg< Char, T > arg(const Char *name, const T &arg)
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
format_arg_store< Context, Args... > make_format_args(const Args &... args)
#define FMT_SUPPRESS_MSC_WARNING(n)
#define FMT_BEGIN_NAMESPACE
#define FMT_BUFFER_CONTEXT(Char)
basic_string_view< Char > to_string_view(const Char *s)
#define FMT_ENABLE_IF(...)
#define FMT_EXTERN_TEMPLATE_API
typename type_identity< T >::type type_identity_t
FMT_CONSTEXPR_DECL FMT_INLINE auto visit_format_arg(Visitor &&vis, const basic_format_arg< Context > &arg) -> decltype(vis(0))
typename std::conditional< B, T, F >::type conditional_t
#define FMT_END_NAMESPACE
#define FMT_CONSTEXPR_DECL
FMT_SAFEBUFFERS decimal_fp< T > to_decimal(T x) FMT_NOEXCEPT
FMT_CONSTEXPR bool is_name_start(Char c)
void copy2(Char *dst, const char *src)
FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler &&handler)
int snprintf_float(T value, int precision, float_specs specs, buffer< char > &buf)
FMT_CONSTEXPR const Char * parse_align(const Char *begin, const Char *end, Handler &&handler)
Container & get_container(std::back_insert_iterator< Container > it)
OutputIt write_significand(OutputIt out, const char *significand, int &significand_size)
T * make_checked(T *p, size_t)
FMT_CONSTEXPR const Char * parse_replacement_field(const Char *begin, const Char *end, Handler &&handler)
FMT_CONSTEXPR const Char * parse_precision(const Char *begin, const Char *end, Handler &&handler)
checked_ptr< typename Container::value_type > reserve(std::back_insert_iterator< Container > it, size_t n)
constexpr int num_bits< fallback_uintptr >()
FMT_CONSTEXPR_DECL FMT_INLINE void parse_format_string(basic_string_view< Char > format_str, Handler &&handler)
constexpr bool is_ascii_letter(Char c)
FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler &&eh)
Char * format_uint(Char *buffer, UInt value, int num_digits, bool upper=false)
FMT_CONSTEXPR float_specs parse_float_type_spec(const basic_format_specs< Char > &specs, ErrorHandler &&eh={})
bool equal2(const Char *lhs, const char *rhs)
constexpr Char to_ascii(Char value)
FMT_CONSTEXPR const Char * parse_format_specs(const Char *begin, const Char *end, SpecHandler &&handler)
const T & first(const T &value, const Tail &...)
FMT_FUNC void format_error_code(detail::buffer< char > &out, int error_code, string_view message) FMT_NOEXCEPT
OutputIt write_float(OutputIt out, const DecimalFP &fp, const basic_format_specs< Char > &specs, float_specs fspecs, Char decimal_point)
decltype(std::begin(std::declval< T & >())) iterator_t
OutputIt write_bytes(OutputIt out, string_view bytes, const basic_format_specs< Char > &specs)
FMT_CONSTEXPR int get_dynamic_spec(FormatArg arg, ErrorHandler eh)
FMT_CONSTEXPR basic_format_arg< Context > make_arg(const T &value)
FMT_INLINE void assume(bool condition)
FMT_INLINE uint16_t bsr2log10(int bsr)
OutputIt write_char(OutputIt out, Char value, const basic_format_specs< Char > &specs)
bool_constant< std::numeric_limits< T >::is_iec559 && sizeof(T)<=sizeof(double)> is_fast_float
FMT_CONSTEXPR std::make_unsigned< Int >::type to_unsigned(Int value)
Char * get_data(std::basic_string< Char > &s)
Char decimal_point(locale_ref loc)
conditional_t< num_bits< T >()<=32 &&!FMT_REDUCE_INT_INSTANTIATIONS, uint32_t, conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > > uint32_or_64_or_128_t
size_t code_point_index(basic_string_view< Char > s, size_t n)
void reset_color(FILE *stream) FMT_NOEXCEPT
bool_constant< is_integral< T >::value &&!std::is_same< T, bool >::value && !std::is_same< T, char >::value && !std::is_same< T, wchar_t >::value > is_integer
void(*)(detail::buffer< char > &, int, string_view) format_func
OutputIt write_int(OutputIt out, int num_digits, string_view prefix, const basic_format_specs< Char > &specs, F f)
OutputIt copy_str(InputIt begin, InputIt end, OutputIt it)
FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t< Char > &fill)
std::back_insert_iterator< Container > base_iterator(std::back_insert_iterator< Container > &it, checked_ptr< typename Container::value_type >)
int get_significand_size(const big_decimal_fp &fp)
int count_digits(uint64_t n)
FMT_CONSTEXPR bool is_supported_floating_point(T)
OutputIt write_nonfinite(OutputIt out, bool isinf, const basic_format_specs< Char > &specs, const float_specs &fspecs)
fallback_uintptr to_uintptr(const void *p)
FMT_CONSTEXPR const Char * parse_width(const Char *begin, const Char *end, Handler &&handler)
void vformat_to(buffer< Char > &buf, const text_style &ts, basic_string_view< Char > format_str, basic_format_args< buffer_context< type_identity_t< Char > > > args)
decltype(std::end(std::declval< T & >())) sentinel_t
format_decimal_result< Char * > format_decimal(Char *out, UInt value, int size)
constexpr int num_bits< int128_t >()
OutputIt write(OutputIt out, basic_string_view< StrChar > s, const basic_format_specs< Char > &specs)
std::integral_constant< bool, std::numeric_limits< T >::is_signed|| std::is_same< T, int128_t >::value > is_signed
constexpr bool is_integral_type(type t)
std::string grouping(locale_ref loc)
FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler &&eh)
FMT_CONSTEXPR bool is_negative(T value)
OutputIt write_padded(OutputIt out, const basic_format_specs< Char > &specs, size_t size, size_t width, F &&f)
FMT_FUNC Char decimal_point_impl(locale_ref loc)
FMT_FUNC void report_error(format_func func, int error_code, string_view message) FMT_NOEXCEPT
void handle_dynamic_spec(int &value, arg_ref< typename Context::char_type > ref, Context &ctx)
std::basic_string< Char > vformat(basic_string_view< Char > format_str, basic_format_args< buffer_context< type_identity_t< Char > > > args)
FMT_CONSTEXPR void handle_cstring_type_spec(Char spec, Handler &&handler)
Dest bit_cast(const Source &source)
FMT_INLINE void check_format_string(const S &)
size_t count_code_points(basic_string_view< Char > s)
fallback_uintptr uintptr_t
constexpr T const_check(T value)
It write_exponent(int exp, It it)
constexpr int digits10() FMT_NOEXCEPT
FMT_CONSTEXPR Context::format_arg get_arg(Context &ctx, ID id)
FMT_CONSTEXPR const Char * parse_arg_id(const Char *begin, const Char *end, IDHandler &&handler)
constexpr dragonbox::float_info< T >::carrier_uint exponent_mask()
constexpr T * to_pointer(OutputIt, size_t)
FMT_CONSTEXPR basic_string_view< Char > compile_string_to_view(const Char(&s)[N])
FMT_CONSTEXPR void handle_char_specs(const basic_format_specs< Char > *specs, Handler &&handler)
FMT_CONSTEXPR int code_point_length(const Char *begin)
int format_float(T value, int precision, float_specs specs, buffer< char > &buf)
FMT_CONSTEXPR int parse_nonnegative_int(const Char *&begin, const Char *end, ErrorHandler &&eh)
constexpr bool is_arithmetic_type(type t)
constexpr int num_bits< uint128_t >()
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
bool_constant< std::is_same< typename std::iterator_traits< InputIt >::value_type, char >::value && std::is_same< OutChar, char8_type >::value > needs_conversion
OutputIt write_ptr(OutputIt out, UIntPtr value, const basic_format_specs< Char > *specs)
Char thousands_sep(locale_ref loc)
basic_string_view< Char > sep
arg_join(It b, Sentinel e, basic_string_view< Char > s)
FMT_CONSTEXPR int map(signed char val)
union detail::arg_ref::value val
FMT_CONSTEXPR arg_ref & operator=(int idx)
FMT_CONSTEXPR arg_ref(int index)
FMT_CONSTEXPR arg_ref(basic_string_view< Char > name)
void operator=(const T &)
significand_type significand
typename float_info< T >::carrier_uint significand_type
unsigned char value[sizeof(void *)]
fallback_uintptr(const void *p)
fallback_uintptr()=default
FMT_CONSTEXPR const Char & operator[](size_t index) const
FMT_CONSTEXPR Char & operator[](size_t index)
FMT_CONSTEXPR void operator=(basic_string_view< Char > s)
const Char * data() const
FMT_CONSTEXPR void operator()(basic_string_view< Char > id)
FMT_CONSTEXPR void on_error(const char *message)
FMT_CONSTEXPR void operator()()
FMT_CONSTEXPR void operator()(int id)
FMT_NORETURN void on_error()
int_writer(OutputIt output, locale_ref loc, Int value, const basic_format_specs< Char > &s)
const basic_format_specs< Char > & specs
remove_reference_t< decltype(reserve(std::declval< OutputIt & >(), 0))> iterator
string_view get_prefix() const
FMT_CONSTEXPR void operator()(basic_string_view< Char > id)
FMT_CONSTEXPR void on_error(const char *message)
FMT_CONSTEXPR precision_adapter(SpecHandler &h)
FMT_CONSTEXPR void operator()()
FMT_CONSTEXPR void operator()(int id)
uint128_wrapper()=default
uint128_wrapper & operator+=(uint64_t n) FMT_NOEXCEPT
uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT
uint64_t high() const FMT_NOEXCEPT
uint64_t low() const FMT_NOEXCEPT
FMT_CONSTEXPR width_adapter(SpecHandler &h)
FMT_CONSTEXPR void operator()(basic_string_view< Char > id)
FMT_CONSTEXPR void on_error(const char *message)
FMT_CONSTEXPR void operator()()
FMT_CONSTEXPR void operator()(int id)
write_int_data(int num_digits, string_view prefix, const basic_format_specs< Char > &specs)
basic_string_view< Char > name
FMT_CONSTEXPR value(int id=0)
FMT_CONSTEXPR value(basic_string_view< Char > n)
|