WPILibC++ 2024.3.2
format.h
Go to the documentation of this file.
1/*
2 Formatting library for C++
3
4 Copyright (c) 2012 - present, Victor Zverovich
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 --- Optional exception to the license ---
26
27 As an exception, if, as a result of your compiling your source code, portions
28 of this Software are embedded into a machine-executable object form of such
29 source code, you may redistribute such embedded portions in such object form
30 without including the above copyright and permission notices.
31 */
32
33#ifndef FMT_FORMAT_H_
34#define FMT_FORMAT_H_
35
36#include <cmath> // std::signbit
37#include <cstdint> // uint32_t
38#include <cstring> // std::memcpy
39#include <initializer_list> // std::initializer_list
40#include <limits> // std::numeric_limits
41#include <memory> // std::uninitialized_copy
42#include <stdexcept> // std::runtime_error
43#include <system_error> // std::system_error
44
45#ifdef __cpp_lib_bit_cast
46# include <bit> // std::bitcast
47#endif
48
49#include "core.h"
50
51#if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L
52# define FMT_INLINE_VARIABLE inline
53#else
54# define FMT_INLINE_VARIABLE
55#endif
56
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]]
64#else
65# define FMT_FALLTHROUGH
66#endif
67
68#ifndef FMT_DEPRECATED
69# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VERSION >= 1900
70# define FMT_DEPRECATED [[deprecated]]
71# else
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)
76# else
77# define FMT_DEPRECATED /* deprecated */
78# endif
79# endif
80#endif
81
82#ifndef FMT_NO_UNIQUE_ADDRESS
83# if FMT_CPLUSPLUS >= 202002L
84# if FMT_HAS_CPP_ATTRIBUTE(no_unique_address)
85# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]]
86// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485)
87# elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION
88# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]]
89# endif
90# endif
91#endif
92#ifndef FMT_NO_UNIQUE_ADDRESS
93# define FMT_NO_UNIQUE_ADDRESS
94#endif
95
96#if FMT_GCC_VERSION || defined(__clang__)
97# define FMT_VISIBILITY(value) __attribute__((visibility(value)))
98#else
99# define FMT_VISIBILITY(value)
100#endif
101
102#ifdef __has_builtin
103# define FMT_HAS_BUILTIN(x) __has_builtin(x)
104#else
105# define FMT_HAS_BUILTIN(x) 0
106#endif
107
108#if FMT_GCC_VERSION || FMT_CLANG_VERSION
109# define FMT_NOINLINE __attribute__((noinline))
110#else
111# define FMT_NOINLINE
112#endif
113
114#ifndef FMT_THROW
115# if FMT_EXCEPTIONS
116# if FMT_MSC_VERSION || defined(__NVCC__)
118namespace detail {
119template <typename Exception> inline void do_throw(const Exception& x) {
120 // Silence unreachable code warnings in MSVC and NVCC because these
121 // are nearly impossible to fix in a generic code.
122 volatile bool b = true;
123 if (b) throw x;
124}
125} // namespace detail
127# define FMT_THROW(x) detail::do_throw(x)
128# else
129# define FMT_THROW(x) throw x
130# endif
131# else
132# define FMT_THROW(x) \
133 ::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what())
134# endif
135#endif
136
137#if FMT_EXCEPTIONS
138# define FMT_TRY try
139# define FMT_CATCH(x) catch (x)
140#else
141# define FMT_TRY if (true)
142# define FMT_CATCH(x) if (false)
143#endif
144
145#ifndef FMT_MAYBE_UNUSED
146# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
147# define FMT_MAYBE_UNUSED [[maybe_unused]]
148# else
149# define FMT_MAYBE_UNUSED
150# endif
151#endif
152
153#ifndef FMT_USE_USER_DEFINED_LITERALS
154// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
155# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
156 FMT_MSC_VERSION >= 1900) && \
157 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
158# define FMT_USE_USER_DEFINED_LITERALS 1
159# else
160# define FMT_USE_USER_DEFINED_LITERALS 0
161# endif
162#endif
163
164// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
165// integer formatter template instantiations to just one by only using the
166// largest integer type. This results in a reduction in binary size but will
167// cause a decrease in integer formatting performance.
168#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
169# define FMT_REDUCE_INT_INSTANTIATIONS 0
170#endif
171
172// __builtin_clz is broken in clang with Microsoft CodeGen:
173// https://github.com/fmtlib/fmt/issues/519.
174#if !FMT_MSC_VERSION
175# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
176# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
177# endif
178# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
179# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
180# endif
181#endif
182
183// __builtin_ctz is broken in Intel Compiler Classic on Windows:
184// https://github.com/fmtlib/fmt/issues/2510.
185#ifndef __ICL
186# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \
187 defined(__NVCOMPILER)
188# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
189# endif
190# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \
191 FMT_ICC_VERSION || defined(__NVCOMPILER)
192# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
193# endif
194#endif
195
196#if FMT_MSC_VERSION
197# include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
198#endif
199
200// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
201// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
202// MSVC intrinsics if the clz and clzll builtins are not available.
203#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \
204 !defined(FMT_BUILTIN_CTZLL)
206namespace detail {
207// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
208# if !defined(__clang__)
209# pragma intrinsic(_BitScanForward)
210# pragma intrinsic(_BitScanReverse)
211# if defined(_WIN64)
212# pragma intrinsic(_BitScanForward64)
213# pragma intrinsic(_BitScanReverse64)
214# endif
215# endif
216
217inline auto clz(uint32_t x) -> int {
218 unsigned long r = 0;
219 _BitScanReverse(&r, x);
220 FMT_ASSERT(x != 0, "");
221 // Static analysis complains about using uninitialized data
222 // "r", but the only way that can happen is if "x" is 0,
223 // which the callers guarantee to not happen.
224 FMT_MSC_WARNING(suppress : 6102)
225 return 31 ^ static_cast<int>(r);
226}
227# define FMT_BUILTIN_CLZ(n) detail::clz(n)
228
229inline auto clzll(uint64_t x) -> int {
230 unsigned long r = 0;
231# ifdef _WIN64
232 _BitScanReverse64(&r, x);
233# else
234 // Scan the high 32 bits.
235 if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32)))
236 return 63 ^ static_cast<int>(r + 32);
237 // Scan the low 32 bits.
238 _BitScanReverse(&r, static_cast<uint32_t>(x));
239# endif
240 FMT_ASSERT(x != 0, "");
241 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
242 return 63 ^ static_cast<int>(r);
243}
244# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
245
246inline auto ctz(uint32_t x) -> int {
247 unsigned long r = 0;
248 _BitScanForward(&r, x);
249 FMT_ASSERT(x != 0, "");
250 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
251 return static_cast<int>(r);
252}
253# define FMT_BUILTIN_CTZ(n) detail::ctz(n)
254
255inline auto ctzll(uint64_t x) -> int {
256 unsigned long r = 0;
257 FMT_ASSERT(x != 0, "");
258 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
259# ifdef _WIN64
260 _BitScanForward64(&r, x);
261# else
262 // Scan the low 32 bits.
263 if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);
264 // Scan the high 32 bits.
265 _BitScanForward(&r, static_cast<uint32_t>(x >> 32));
266 r += 32;
267# endif
268 return static_cast<int>(r);
269}
270# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
271} // namespace detail
273#endif
274
276
277template <typename...> struct disjunction : std::false_type {};
278template <typename P> struct disjunction<P> : P {};
279template <typename P1, typename... Pn>
280struct disjunction<P1, Pn...>
281 : conditional_t<bool(P1::value), P1, disjunction<Pn...>> {};
282
283template <typename...> struct conjunction : std::true_type {};
284template <typename P> struct conjunction<P> : P {};
285template <typename P1, typename... Pn>
286struct conjunction<P1, Pn...>
287 : conditional_t<bool(P1::value), conjunction<Pn...>, P1> {};
288
289namespace detail {
290
291FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) {
292 ignore_unused(condition);
293#ifdef FMT_FUZZ
294 if (condition) throw std::runtime_error("fuzzing limit reached");
295#endif
296}
297
298template <typename CharT, CharT... C> struct string_literal {
299 static constexpr CharT value[sizeof...(C)] = {C...};
300 constexpr operator basic_string_view<CharT>() const {
301 return {value, sizeof...(C)};
302 }
303};
304
305#if FMT_CPLUSPLUS < 201703L
306template <typename CharT, CharT... C>
307constexpr CharT string_literal<CharT, C...>::value[sizeof...(C)];
308#endif
309
310template <typename Streambuf> class formatbuf : public Streambuf {
311 private:
312 using char_type = typename Streambuf::char_type;
313 using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));
314 using int_type = typename Streambuf::int_type;
315 using traits_type = typename Streambuf::traits_type;
316
317 buffer<char_type>& buffer_;
318
319 public:
320 explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}
321
322 protected:
323 // The put area is always empty. This makes the implementation simpler and has
324 // the advantage that the streambuf and the buffer are always in sync and
325 // sputc never writes into uninitialized memory. A disadvantage is that each
326 // call to sputc always results in a (virtual) call to overflow. There is no
327 // disadvantage here for sputn since this always results in a call to xsputn.
328
329 auto overflow(int_type ch) -> int_type override {
330 if (!traits_type::eq_int_type(ch, traits_type::eof()))
331 buffer_.push_back(static_cast<char_type>(ch));
332 return ch;
333 }
334
335 auto xsputn(const char_type* s, streamsize count) -> streamsize override {
336 buffer_.append(s, s + count);
337 return count;
338 }
339};
340
341// Implementation of std::bit_cast for pre-C++20.
342template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))>
343FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
344#ifdef __cpp_lib_bit_cast
345 if (is_constant_evaluated()) return std::bit_cast<To>(from);
346#endif
347 auto to = To();
348 // The cast suppresses a bogus -Wclass-memaccess on GCC.
349 std::memcpy(static_cast<void*>(&to), &from, sizeof(to));
350 return to;
351}
352
353inline auto is_big_endian() -> bool {
354#ifdef _WIN32
355 return false;
356#elif defined(__BIG_ENDIAN__)
357 return true;
358#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
359 return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
360#else
361 struct bytes {
362 char data[sizeof(int)];
363 };
364 return bit_cast<bytes>(1).data[0] == 0;
365#endif
366}
367
369 private:
370 uint64_t lo_, hi_;
371
372 public:
373 constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {}
374 constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {}
375
376 constexpr uint64_t high() const noexcept { return hi_; }
377 constexpr uint64_t low() const noexcept { return lo_; }
378
379 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
380 constexpr explicit operator T() const {
381 return static_cast<T>(lo_);
382 }
383
384 friend constexpr auto operator==(const uint128_fallback& lhs,
385 const uint128_fallback& rhs) -> bool {
386 return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_;
387 }
388 friend constexpr auto operator!=(const uint128_fallback& lhs,
389 const uint128_fallback& rhs) -> bool {
390 return !(lhs == rhs);
391 }
392 friend constexpr auto operator>(const uint128_fallback& lhs,
393 const uint128_fallback& rhs) -> bool {
394 return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_;
395 }
396 friend constexpr auto operator|(const uint128_fallback& lhs,
397 const uint128_fallback& rhs)
399 return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_};
400 }
401 friend constexpr auto operator&(const uint128_fallback& lhs,
402 const uint128_fallback& rhs)
404 return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_};
405 }
406 friend constexpr auto operator~(const uint128_fallback& n)
408 return {~n.hi_, ~n.lo_};
409 }
410 friend auto operator+(const uint128_fallback& lhs,
411 const uint128_fallback& rhs) -> uint128_fallback {
412 auto result = uint128_fallback(lhs);
413 result += rhs;
414 return result;
415 }
416 friend auto operator*(const uint128_fallback& lhs, uint32_t rhs)
418 FMT_ASSERT(lhs.hi_ == 0, "");
419 uint64_t hi = (lhs.lo_ >> 32) * rhs;
420 uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs;
421 uint64_t new_lo = (hi << 32) + lo;
422 return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo};
423 }
424 friend auto operator-(const uint128_fallback& lhs, uint64_t rhs)
426 return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs};
427 }
428 FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback {
429 if (shift == 64) return {0, hi_};
430 if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64);
431 return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)};
432 }
433 FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback {
434 if (shift == 64) return {lo_, 0};
435 if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64);
436 return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)};
437 }
439 return *this = *this >> shift;
440 }
442 uint64_t new_lo = lo_ + n.lo_;
443 uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0);
444 FMT_ASSERT(new_hi >= hi_, "");
445 lo_ = new_lo;
446 hi_ = new_hi;
447 }
449 lo_ &= n.lo_;
450 hi_ &= n.hi_;
451 }
452
454 if (is_constant_evaluated()) {
455 lo_ += n;
456 hi_ += (lo_ < n ? 1 : 0);
457 return *this;
458 }
459#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__)
460 unsigned long long carry;
461 lo_ = __builtin_addcll(lo_, n, 0, &carry);
462 hi_ += carry;
463#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__)
464 unsigned long long result;
465 auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result);
466 lo_ = result;
467 hi_ += carry;
468#elif defined(_MSC_VER) && defined(_M_X64)
469 auto carry = _addcarry_u64(0, lo_, n, &lo_);
470 _addcarry_u64(carry, hi_, 0, &hi_);
471#else
472 lo_ += n;
473 hi_ += (lo_ < n ? 1 : 0);
474#endif
475 return *this;
476 }
477};
478
480
481#ifdef UINTPTR_MAX
482using uintptr_t = ::uintptr_t;
483#else
485#endif
486
487// Returns the largest possible value for type T. Same as
488// std::numeric_limits<T>::max() but shorter and not affected by the max macro.
489template <typename T> constexpr auto max_value() -> T {
491}
492template <typename T> constexpr auto num_bits() -> int {
493 return std::numeric_limits<T>::digits;
494}
495// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
496template <> constexpr auto num_bits<int128_opt>() -> int { return 128; }
497template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
498
499// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t
500// and 128-bit pointers to uint128_fallback.
501template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) > sizeof(From))>
502inline auto bit_cast(const From& from) -> To {
503 constexpr auto size = static_cast<int>(sizeof(From) / sizeof(unsigned));
504 struct data_t {
505 unsigned value[static_cast<unsigned>(size)];
506 } data = bit_cast<data_t>(from);
507 auto result = To();
508 if (const_check(is_big_endian())) {
509 for (int i = 0; i < size; ++i)
510 result = (result << num_bits<unsigned>()) | data.value[i];
511 } else {
512 for (int i = size - 1; i >= 0; --i)
513 result = (result << num_bits<unsigned>()) | data.value[i];
514 }
515 return result;
516}
517
518template <typename UInt>
519FMT_CONSTEXPR20 inline auto countl_zero_fallback(UInt n) -> int {
520 int lz = 0;
521 constexpr UInt msb_mask = static_cast<UInt>(1) << (num_bits<UInt>() - 1);
522 for (; (n & msb_mask) == 0; n <<= 1) lz++;
523 return lz;
524}
525
526FMT_CONSTEXPR20 inline auto countl_zero(uint32_t n) -> int {
527#ifdef FMT_BUILTIN_CLZ
528 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n);
529#endif
530 return countl_zero_fallback(n);
531}
532
533FMT_CONSTEXPR20 inline auto countl_zero(uint64_t n) -> int {
534#ifdef FMT_BUILTIN_CLZLL
535 if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n);
536#endif
537 return countl_zero_fallback(n);
538}
539
540FMT_INLINE void assume(bool condition) {
541 (void)condition;
542#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION
543 __builtin_assume(condition);
544#elif FMT_GCC_VERSION
545 if (!condition) __builtin_unreachable();
546#endif
547}
548
549// An approximation of iterator_t for pre-C++20 systems.
550template <typename T>
551using iterator_t = decltype(std::begin(std::declval<T&>()));
552template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
553
554// A workaround for std::string not having mutable data() until C++17.
555template <typename Char>
556inline auto get_data(std::basic_string<Char>& s) -> Char* {
557 return &s[0];
558}
559template <typename Container>
560inline auto get_data(Container& c) -> typename Container::value_type* {
561 return c.data();
562}
563
564// Attempts to reserve space for n extra characters in the output range.
565// Returns a pointer to the reserved range or a reference to it.
566template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
567#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
568__attribute__((no_sanitize("undefined")))
569#endif
570inline auto
571reserve(std::back_insert_iterator<Container> it, size_t n) ->
572 typename Container::value_type* {
573 Container& c = get_container(it);
574 size_t size = c.size();
575 c.resize(size + n);
576 return get_data(c) + size;
577}
578
579template <typename T>
580inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> {
581 buffer<T>& buf = get_container(it);
582 buf.try_reserve(buf.size() + n);
583 return it;
584}
585
586template <typename Iterator>
587constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
588 return it;
589}
590
591template <typename OutputIt>
594
595template <typename T, typename OutputIt>
596constexpr auto to_pointer(OutputIt, size_t) -> T* {
597 return nullptr;
598}
599template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
600 buffer<T>& buf = get_container(it);
601 auto size = buf.size();
602 if (buf.capacity() < size + n) return nullptr;
603 buf.try_resize(size + n);
604 return buf.data() + size;
605}
606
607template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
608inline auto base_iterator(std::back_insert_iterator<Container> it,
609 typename Container::value_type*)
610 -> std::back_insert_iterator<Container> {
611 return it;
612}
613
614template <typename Iterator>
615constexpr auto base_iterator(Iterator, Iterator it) -> Iterator {
616 return it;
617}
618
619// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
620// instead (#1998).
621template <typename OutputIt, typename Size, typename T>
622FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)
623 -> OutputIt {
624 for (Size i = 0; i < count; ++i) *out++ = value;
625 return out;
626}
627template <typename T, typename Size>
628FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
629 if (is_constant_evaluated()) {
630 return fill_n<T*, Size, T>(out, count, value);
631 }
632 std::memset(out, value, to_unsigned(count));
633 return out + count;
634}
635
636#ifdef __cpp_char8_t
637using char8_type = char8_t;
638#else
639enum char8_type : unsigned char {};
640#endif
641
642template <typename OutChar, typename InputIt, typename OutputIt>
643FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,
644 OutputIt out) -> OutputIt {
645 return copy_str<OutChar>(begin, end, out);
646}
647
648// A public domain branchless UTF-8 decoder by Christopher Wellons:
649// https://github.com/skeeto/branchless-utf8
650/* Decode the next character, c, from s, reporting errors in e.
651 *
652 * Since this is a branchless decoder, four bytes will be read from the
653 * buffer regardless of the actual length of the next character. This
654 * means the buffer _must_ have at least three bytes of zero padding
655 * following the end of the data stream.
656 *
657 * Errors are reported in e, which will be non-zero if the parsed
658 * character was somehow invalid: invalid byte sequence, non-canonical
659 * encoding, or a surrogate half.
660 *
661 * The function returns a pointer to the next character. When an error
662 * occurs, this pointer will be a guess that depends on the particular
663 * error, but it will always advance at least one byte.
664 */
665FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)
666 -> const char* {
667 constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
668 constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
669 constexpr const int shiftc[] = {0, 18, 12, 6, 0};
670 constexpr const int shifte[] = {0, 6, 4, 2, 0};
671
672 int len = "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4"
673 [static_cast<unsigned char>(*s) >> 3];
674 // Compute the pointer to the next character early so that the next
675 // iteration can start working on the next character. Neither Clang
676 // nor GCC figure out this reordering on their own.
677 const char* next = s + len + !len;
678
679 using uchar = unsigned char;
680
681 // Assume a four-byte character and load four bytes. Unused bits are
682 // shifted out.
683 *c = uint32_t(uchar(s[0]) & masks[len]) << 18;
684 *c |= uint32_t(uchar(s[1]) & 0x3f) << 12;
685 *c |= uint32_t(uchar(s[2]) & 0x3f) << 6;
686 *c |= uint32_t(uchar(s[3]) & 0x3f) << 0;
687 *c >>= shiftc[len];
688
689 // Accumulate the various error conditions.
690 *e = (*c < mins[len]) << 6; // non-canonical encoding
691 *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
692 *e |= (*c > 0x10FFFF) << 8; // out of range?
693 *e |= (uchar(s[1]) & 0xc0) >> 2;
694 *e |= (uchar(s[2]) & 0xc0) >> 4;
695 *e |= uchar(s[3]) >> 6;
696 *e ^= 0x2a; // top two bits of each tail byte correct?
697 *e >>= shifte[len];
698
699 return next;
700}
701
702constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point = ~uint32_t();
703
704// Invokes f(cp, sv) for every code point cp in s with sv being the string view
705// corresponding to the code point. cp is invalid_code_point on error.
706template <typename F>
708 auto decode = [f](const char* buf_ptr, const char* ptr) {
709 auto cp = uint32_t();
710 auto error = 0;
711 auto end = utf8_decode(buf_ptr, &cp, &error);
712 bool result = f(error ? invalid_code_point : cp,
713 string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr)));
714 return result ? (error ? buf_ptr + 1 : end) : nullptr;
715 };
716 auto p = s.data();
717 const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
718 if (s.size() >= block_size) {
719 for (auto end = p + s.size() - block_size + 1; p < end;) {
720 p = decode(p, p);
721 if (!p) return;
722 }
723 }
724 if (auto num_chars_left = s.data() + s.size() - p) {
725 char buf[2 * block_size - 1] = {};
726 copy_str<char>(p, p + num_chars_left, buf);
727 const char* buf_ptr = buf;
728 do {
729 auto end = decode(buf_ptr, p);
730 if (!end) return;
731 p += end - buf_ptr;
732 buf_ptr = end;
733 } while (buf_ptr - buf < num_chars_left);
734 }
735}
736
737template <typename Char>
738inline auto compute_width(basic_string_view<Char> s) -> size_t {
739 return s.size();
740}
741
742// Computes approximate display width of a UTF-8 string.
744 size_t num_code_points = 0;
745 // It is not a lambda for compatibility with C++14.
746 struct count_code_points {
747 size_t* count;
748 FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool {
750 1 +
751 (cp >= 0x1100 &&
752 (cp <= 0x115f || // Hangul Jamo init. consonants
753 cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET
754 cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET
755 // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
756 (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
757 (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables
758 (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
759 (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms
760 (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms
761 (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
762 (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms
763 (cp >= 0x20000 && cp <= 0x2fffd) || // CJK
764 (cp >= 0x30000 && cp <= 0x3fffd) ||
765 // Miscellaneous Symbols and Pictographs + Emoticons:
766 (cp >= 0x1f300 && cp <= 0x1f64f) ||
767 // Supplemental Symbols and Pictographs:
768 (cp >= 0x1f900 && cp <= 0x1f9ff))));
769 return true;
770 }
771 };
772 // We could avoid branches by using utf8_decode directly.
773 for_each_codepoint(s, count_code_points{&num_code_points});
774 return num_code_points;
775}
776
778 return compute_width(
779 string_view(reinterpret_cast<const char*>(s.data()), s.size()));
780}
781
782template <typename Char>
783inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t {
784 size_t size = s.size();
785 return n < size ? n : size;
786}
787
788// Calculates the index of the nth code point in a UTF-8 string.
789inline auto code_point_index(string_view s, size_t n) -> size_t {
790 const char* data = s.data();
791 size_t num_code_points = 0;
792 for (size_t i = 0, size = s.size(); i != size; ++i) {
793 if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i;
794 }
795 return s.size();
796}
797
799 -> size_t {
800 return code_point_index(
801 string_view(reinterpret_cast<const char*>(s.data()), s.size()), n);
802}
803
804template <typename T> struct is_integral : std::is_integral<T> {};
805template <> struct is_integral<int128_opt> : std::true_type {};
806template <> struct is_integral<uint128_t> : std::true_type {};
807
808template <typename T>
811 std::is_same<T, int128_opt>::value>;
812
813template <typename T>
815 bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
816 !std::is_same<T, char>::value &&
817 !std::is_same<T, wchar_t>::value>;
818
819#ifndef FMT_USE_FLOAT
820# define FMT_USE_FLOAT 1
821#endif
822#ifndef FMT_USE_DOUBLE
823# define FMT_USE_DOUBLE 1
824#endif
825#ifndef FMT_USE_LONG_DOUBLE
826# define FMT_USE_LONG_DOUBLE 1
827#endif
828
829#ifndef FMT_USE_FLOAT128
830# ifdef __clang__
831// Clang emulates GCC, so it has to appear early.
832# if FMT_HAS_INCLUDE(<quadmath.h>)
833# define FMT_USE_FLOAT128 1
834# endif
835# elif defined(__GNUC__)
836// GNU C++:
837# if defined(_GLIBCXX_USE_FLOAT128) && !defined(__STRICT_ANSI__)
838# define FMT_USE_FLOAT128 1
839# endif
840# endif
841# ifndef FMT_USE_FLOAT128
842# define FMT_USE_FLOAT128 0
843# endif
844#endif
845
846#if FMT_USE_FLOAT128
847using float128 = __float128;
848#else
849using float128 = void;
850#endif
851template <typename T> using is_float128 = std::is_same<T, float128>;
852
853template <typename T>
856
857template <typename T, bool = std::is_floating_point<T>::value>
858struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
859 sizeof(T) <= sizeof(double)> {};
860template <typename T> struct is_fast_float<T, false> : std::false_type {};
861
862template <typename T>
863using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>;
864
865#ifndef FMT_USE_FULL_CACHE_DRAGONBOX
866# define FMT_USE_FULL_CACHE_DRAGONBOX 0
867#endif
868
869template <typename T>
870template <typename U>
871void buffer<T>::append(const U* begin, const U* end) {
872 while (begin != end) {
873 auto count = to_unsigned(end - begin);
874 try_reserve(size_ + count);
875 auto free_cap = capacity_ - size_;
876 if (free_cap < count) count = free_cap;
877 std::uninitialized_copy_n(begin, count, ptr_ + size_);
878 size_ += count;
879 begin += count;
880 }
881}
882
883template <typename T, typename Enable = void>
884struct is_locale : std::false_type {};
885template <typename T>
886struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
887} // namespace detail
888
889FMT_BEGIN_EXPORT
890
891// The number of characters to store in the basic_memory_buffer object itself
892// to avoid dynamic memory allocation.
893enum { inline_buffer_size = 500 };
894
895/**
896 \rst
897 A dynamically growing memory buffer for trivially copyable/constructible types
898 with the first ``SIZE`` elements stored in the object itself.
899
900 You can use the ``memory_buffer`` type alias for ``char`` instead.
901
902 **Example**::
903
904 auto out = fmt::memory_buffer();
905 format_to(std::back_inserter(out), "The answer is {}.", 42);
906
907 This will append the following output to the ``out`` object:
908
909 .. code-block:: none
910
911 The answer is 42.
912
913 The output can be converted to an ``std::string`` with ``to_string(out)``.
914 \endrst
915 */
916template <typename T, size_t SIZE = inline_buffer_size,
917 typename Allocator = std::allocator<T>>
918class basic_memory_buffer final : public detail::buffer<T> {
919 private:
920 T store_[SIZE];
921
922 // Don't inherit from Allocator to avoid generating type_info for it.
923 FMT_NO_UNIQUE_ADDRESS Allocator alloc_;
924
925 // Deallocate memory allocated by the buffer.
926 FMT_CONSTEXPR20 void deallocate() {
927 T* data = this->data();
928 if (data != store_) alloc_.deallocate(data, this->capacity());
929 }
930
931 protected:
932 FMT_CONSTEXPR20 void grow(size_t size) override {
933 detail::abort_fuzzing_if(size > 5000);
934 const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
935 size_t old_capacity = this->capacity();
936 size_t new_capacity = old_capacity + old_capacity / 2;
937 if (size > new_capacity)
938 new_capacity = size;
939 else if (new_capacity > max_size)
940 new_capacity = size > max_size ? size : max_size;
941 T* old_data = this->data();
942 T* new_data =
943 std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
944 // Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481).
945 detail::assume(this->size() <= new_capacity);
946 // The following code doesn't throw, so the raw pointer above doesn't leak.
947 std::uninitialized_copy_n(old_data, this->size(), new_data);
948 this->set(new_data, new_capacity);
949 // deallocate must not throw according to the standard, but even if it does,
950 // the buffer already uses the new storage and will deallocate it in
951 // destructor.
952 if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
953 }
954
955 public:
956 using value_type = T;
957 using const_reference = const T&;
958
960 const Allocator& alloc = Allocator())
961 : alloc_(alloc) {
962 this->set(store_, SIZE);
963 if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T());
964 }
966
967 private:
968 // Move data from other to this buffer.
969 FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
970 alloc_ = std::move(other.alloc_);
971 T* data = other.data();
972 size_t size = other.size(), capacity = other.capacity();
973 if (data == other.store_) {
974 this->set(store_, capacity);
975 detail::copy_str<T>(other.store_, other.store_ + size, store_);
976 } else {
977 this->set(data, capacity);
978 // Set pointer to the inline array so that delete is not called
979 // when deallocating.
980 other.set(other.store_, 0);
981 other.clear();
982 }
983 this->resize(size);
984 }
985
986 public:
987 /**
988 \rst
989 Constructs a :class:`fmt::basic_memory_buffer` object moving the content
990 of the other object to it.
991 \endrst
992 */
994 move(other);
995 }
996
997 /**
998 \rst
999 Moves the content of the other ``basic_memory_buffer`` object to this one.
1000 \endrst
1001 */
1003 FMT_ASSERT(this != &other, "");
1004 deallocate();
1005 move(other);
1006 return *this;
1007 }
1008
1009 // Returns a copy of the allocator associated with this buffer.
1010 auto get_allocator() const -> Allocator { return alloc_; }
1011
1012 /**
1013 Resizes the buffer to contain *count* elements. If T is a POD type new
1014 elements may not be initialized.
1015 */
1016 FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }
1017
1018 /** Increases the buffer capacity to *new_capacity*. */
1019 void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
1020
1021 // Directly append data into the buffer
1022 using detail::buffer<T>::append;
1023 template <typename ContiguousRange>
1024 void append(const ContiguousRange& range) {
1025 append(range.data(), range.data() + range.size());
1026 }
1027};
1028
1030
1031template <typename T, size_t SIZE, typename Allocator>
1032struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
1033};
1034
1036namespace detail {
1037FMT_API bool write_console(std::FILE* f, string_view text);
1038FMT_API void print(std::FILE*, string_view);
1039} // namespace detail
1040
1042
1043// Suppress a misleading warning in older versions of clang.
1044#if FMT_CLANG_VERSION
1045# pragma clang diagnostic ignored "-Wweak-vtables"
1046#endif
1047
1048/** An error reported from a formatting function. */
1049class FMT_VISIBILITY("default") format_error : public std::runtime_error {
1050 public:
1051 using std::runtime_error::runtime_error;
1052};
1053
1055#if FMT_USE_NONTYPE_TEMPLATE_ARGS
1056template <typename Char, size_t N> struct fixed_string {
1057 constexpr fixed_string(const Char (&str)[N]) {
1058 detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
1059 str + N, data);
1060 }
1061 Char data[N] = {};
1062};
1063#endif
1064
1065// Converts a compile-time string to basic_string_view.
1066template <typename Char, size_t N>
1067constexpr auto compile_string_to_view(const Char (&s)[N])
1069 // Remove trailing NUL character if needed. Won't be present if this is used
1070 // with a raw character array (i.e. not defined as a string).
1071 return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
1072}
1073template <typename Char>
1076 return {s.data(), s.size()};
1077}
1078} // namespace detail_exported
1079
1081 private:
1083
1084 public:
1085 template <typename T, FMT_ENABLE_IF(!detail::is_float128<T>::value)>
1086 loc_value(T value) : value_(detail::make_arg<format_context>(value)) {}
1087
1088 template <typename T, FMT_ENABLE_IF(detail::is_float128<T>::value)>
1090
1091 template <typename Visitor> auto visit(Visitor&& vis) -> decltype(vis(0)) {
1092 return visit_format_arg(vis, value_);
1093 }
1094};
1095
1096// A locale facet that formats values in UTF-8.
1097// It is parameterized on the locale to avoid the heavy <locale> include.
1098template <typename Locale> class format_facet : public Locale::facet {
1099 private:
1100 std::string separator_;
1101 std::string grouping_;
1102 std::string decimal_point_;
1103
1104 protected:
1105 virtual auto do_put(appender out, loc_value val,
1106 const format_specs<>& specs) const -> bool;
1107
1108 public:
1109 static FMT_API typename Locale::id id;
1110
1111 explicit format_facet(Locale& loc);
1112 explicit format_facet(string_view sep = "",
1113 std::initializer_list<unsigned char> g = {3},
1114 std::string decimal_point = ".")
1115 : separator_(sep.data(), sep.size()),
1116 grouping_(g.begin(), g.end()),
1117 decimal_point_(decimal_point) {}
1118
1119 auto put(appender out, loc_value val, const format_specs<>& specs) const
1120 -> bool {
1121 return do_put(out, val, specs);
1122 }
1123};
1124
1125namespace detail {
1126
1127// Returns true if value is negative, false otherwise.
1128// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
1129template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
1130constexpr auto is_negative(T value) -> bool {
1131 return value < 0;
1132}
1133template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
1134constexpr auto is_negative(T) -> bool {
1135 return false;
1136}
1137
1138template <typename T>
1140 if (std::is_same<T, float>()) return FMT_USE_FLOAT;
1141 if (std::is_same<T, double>()) return FMT_USE_DOUBLE;
1142 if (std::is_same<T, long double>()) return FMT_USE_LONG_DOUBLE;
1143 return true;
1144}
1145
1146// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
1147// represent all values of an integral type T.
1148template <typename T>
1151 uint32_t,
1152 conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
1153template <typename T>
1155
1156#define FMT_POWERS_OF_10(factor) \
1157 factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
1158 (factor)*1000000, (factor)*10000000, (factor)*100000000, \
1159 (factor)*1000000000
1160
1161// Converts value in the range [0, 100) to a string.
1162constexpr const char* digits2(size_t value) {
1163 // GCC generates slightly better code when value is pointer-size.
1164 return &"0001020304050607080910111213141516171819"
1165 "2021222324252627282930313233343536373839"
1166 "4041424344454647484950515253545556575859"
1167 "6061626364656667686970717273747576777879"
1168 "8081828384858687888990919293949596979899"[value * 2];
1169}
1170
1171// Sign is a template parameter to workaround a bug in gcc 4.8.
1172template <typename Char, typename Sign> constexpr Char sign(Sign s) {
1173#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
1174 static_assert(std::is_same<Sign, sign_t>::value, "");
1175#endif
1176 return static_cast<Char>("\0-+ "[s]);
1177}
1178
1179template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
1180 int count = 1;
1181 for (;;) {
1182 // Integer division is slow so do it for a group of four digits instead
1183 // of for every digit. The idea comes from the talk by Alexandrescu
1184 // "Three Optimization Tips for C++". See speed-test for a comparison.
1185 if (n < 10) return count;
1186 if (n < 100) return count + 1;
1187 if (n < 1000) return count + 2;
1188 if (n < 10000) return count + 3;
1189 n /= 10000u;
1190 count += 4;
1191 }
1192}
1193#if FMT_USE_INT128
1194FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int {
1195 return count_digits_fallback(n);
1196}
1197#endif
1198
1199#ifdef FMT_BUILTIN_CLZLL
1200// It is a separate function rather than a part of count_digits to workaround
1201// the lack of static constexpr in constexpr functions.
1202inline auto do_count_digits(uint64_t n) -> int {
1203 // This has comparable performance to the version by Kendall Willets
1204 // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
1205 // but uses smaller tables.
1206 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
1207 static constexpr uint8_t bsr2log10[] = {
1208 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
1209 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
1210 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
1211 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
1212 auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
1213 static constexpr const uint64_t zero_or_powers_of_10[] = {
1214 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
1215 10000000000000000000ULL};
1216 return t - (n < zero_or_powers_of_10[t]);
1217}
1218#endif
1219
1220// Returns the number of decimal digits in n. Leading zeros are not counted
1221// except for n == 0 in which case count_digits returns 1.
1222FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
1223#ifdef FMT_BUILTIN_CLZLL
1224 if (!is_constant_evaluated()) {
1225 return do_count_digits(n);
1226 }
1227#endif
1228 return count_digits_fallback(n);
1229}
1230
1231// Counts the number of digits in n. BITS = log2(radix).
1232template <int BITS, typename UInt>
1233FMT_CONSTEXPR auto count_digits(UInt n) -> int {
1234#ifdef FMT_BUILTIN_CLZ
1235 if (!is_constant_evaluated() && num_bits<UInt>() == 32)
1236 return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
1237#endif
1238 // Lambda avoids unreachable code warnings from NVHPC.
1239 return [](UInt m) {
1240 int num_digits = 0;
1241 do {
1242 ++num_digits;
1243 } while ((m >>= BITS) != 0);
1244 return num_digits;
1245 }(n);
1246}
1247
1248#ifdef FMT_BUILTIN_CLZ
1249// It is a separate function rather than a part of count_digits to workaround
1250// the lack of static constexpr in constexpr functions.
1251FMT_INLINE auto do_count_digits(uint32_t n) -> int {
1252// An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1253// This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1254# define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
1255 static constexpr uint64_t table[] = {
1256 FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1257 FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1258 FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1259 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1260 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1261 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1262 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1263 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1264 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1265 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1266 FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1267 };
1268 auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
1269 return static_cast<int>((n + inc) >> 32);
1270}
1271#endif
1272
1273// Optional version of count_digits for better performance on 32-bit platforms.
1274FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
1275#ifdef FMT_BUILTIN_CLZ
1276 if (!is_constant_evaluated()) {
1277 return do_count_digits(n);
1278 }
1279#endif
1280 return count_digits_fallback(n);
1281}
1282
1283template <typename Int> constexpr auto digits10() noexcept -> int {
1285}
1286template <> constexpr auto digits10<int128_opt>() noexcept -> int { return 38; }
1287template <> constexpr auto digits10<uint128_t>() noexcept -> int { return 38; }
1288
1289template <typename Char> struct thousands_sep_result {
1290 std::string grouping;
1292};
1293
1294template <typename Char>
1296template <typename Char>
1298 auto result = thousands_sep_impl<char>(loc);
1299 return {result.grouping, Char(result.thousands_sep)};
1300}
1301template <>
1303 return thousands_sep_impl<wchar_t>(loc);
1304}
1305
1306template <typename Char>
1307FMT_API auto decimal_point_impl(locale_ref loc) -> Char;
1308template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
1309 return Char(decimal_point_impl<char>(loc));
1310}
1311template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
1312 return decimal_point_impl<wchar_t>(loc);
1313}
1314
1315// Compares two characters for equality.
1316template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
1317 return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1318}
1319inline auto equal2(const char* lhs, const char* rhs) -> bool {
1320 return memcmp(lhs, rhs, 2) == 0;
1321}
1322
1323// Copies two characters from src to dst.
1324template <typename Char>
1325FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) {
1326 if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) {
1327#if FMT_GCC_VERSION && FMT_GCC_VERSION >= 1000
1328# pragma GCC diagnostic push
1329# pragma GCC diagnostic ignored "-Wstringop-overflow"
1330#endif
1331 memcpy(dst, src, 2);
1332#if FMT_GCC_VERSION && FMT_GCC_VERSION >= 1000
1333# pragma GCC diagnostic pop
1334#endif
1335 return;
1336 }
1337 *dst++ = static_cast<Char>(*src++);
1338 *dst = static_cast<Char>(*src);
1339}
1340
1341template <typename Iterator> struct format_decimal_result {
1342 Iterator begin;
1343 Iterator end;
1344};
1345
1346// Formats a decimal unsigned integer value writing into out pointing to a
1347// buffer of specified size. The caller must ensure that the buffer is large
1348// enough.
1349template <typename Char, typename UInt>
1350FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)
1352 FMT_ASSERT(size >= count_digits(value), "invalid digit count");
1353 out += size;
1354 Char* end = out;
1355 while (value >= 100) {
1356 // Integer division is slow so do it for a group of two digits instead
1357 // of for every digit. The idea comes from the talk by Alexandrescu
1358 // "Three Optimization Tips for C++". See speed-test for a comparison.
1359 out -= 2;
1360 copy2(out, digits2(static_cast<size_t>(value % 100)));
1361 value /= 100;
1362 }
1363 if (value < 10) {
1364 *--out = static_cast<Char>('0' + value);
1365 return {out, end};
1366 }
1367 out -= 2;
1368 copy2(out, digits2(static_cast<size_t>(value)));
1369 return {out, end};
1370}
1371
1372template <typename Char, typename UInt, typename Iterator,
1373 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
1374FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size)
1376 // Buffer is large enough to hold all digits (digits10 + 1).
1377 Char buffer[digits10<UInt>() + 1] = {};
1378 auto end = format_decimal(buffer, value, size).end;
1379 return {out, detail::copy_str_noinline<Char>(buffer, end, out)};
1380}
1381
1382template <unsigned BASE_BITS, typename Char, typename UInt>
1383FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,
1384 bool upper = false) -> Char* {
1385 buffer += num_digits;
1386 Char* end = buffer;
1387 do {
1388 const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
1389 unsigned digit = static_cast<unsigned>(value & ((1 << BASE_BITS) - 1));
1390 *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
1391 : digits[digit]);
1392 } while ((value >>= BASE_BITS) != 0);
1393 return end;
1394}
1395
1396template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
1397FMT_CONSTEXPR inline auto format_uint(It out, UInt value, int num_digits,
1398 bool upper = false) -> It {
1399 if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1400 format_uint<BASE_BITS>(ptr, value, num_digits, upper);
1401 return out;
1402 }
1403 // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1404 char buffer[num_bits<UInt>() / BASE_BITS + 1];
1405 format_uint<BASE_BITS>(buffer, value, num_digits, upper);
1406 return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out);
1407}
1408
1409// A converter from UTF-8 to UTF-16.
1411 private:
1413
1414 public:
1415 FMT_API explicit utf8_to_utf16(string_view s);
1416 operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
1417 auto size() const -> size_t { return buffer_.size() - 1; }
1418 auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1419 auto str() const -> std::wstring { return {&buffer_[0], size()}; }
1420};
1421
1423
1424// A converter from UTF-16/UTF-32 (host endian) to UTF-8.
1425template <typename WChar, typename Buffer = memory_buffer> class to_utf8 {
1426 private:
1427 Buffer buffer_;
1428
1429 public:
1433 static_assert(sizeof(WChar) == 2 || sizeof(WChar) == 4,
1434 "Expect utf16 or utf32");
1435 if (!convert(s, policy))
1436 FMT_THROW(std::runtime_error(sizeof(WChar) == 2 ? "invalid utf16"
1437 : "invalid utf32"));
1438 }
1439 operator string_view() const { return string_view(&buffer_[0], size()); }
1440 size_t size() const { return buffer_.size() - 1; }
1441 const char* c_str() const { return &buffer_[0]; }
1442 std::string str() const { return std::string(&buffer_[0], size()); }
1443
1444 // Performs conversion returning a bool instead of throwing exception on
1445 // conversion error. This method may still throw in case of memory allocation
1446 // error.
1449 if (!convert(buffer_, s, policy)) return false;
1450 buffer_.push_back(0);
1451 return true;
1452 }
1453 static bool convert(
1454 Buffer& buf, basic_string_view<WChar> s,
1456 for (auto p = s.begin(); p != s.end(); ++p) {
1457 uint32_t c = static_cast<uint32_t>(*p);
1458 if (sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) {
1459 // Handle a surrogate pair.
1460 ++p;
1461 if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) {
1462 if (policy == to_utf8_error_policy::abort) return false;
1463 buf.append(string_view("\xEF\xBF\xBD"));
1464 --p;
1465 } else {
1466 c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00;
1467 }
1468 } else if (c < 0x80) {
1469 buf.push_back(static_cast<char>(c));
1470 } else if (c < 0x800) {
1471 buf.push_back(static_cast<char>(0xc0 | (c >> 6)));
1472 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1473 } else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) {
1474 buf.push_back(static_cast<char>(0xe0 | (c >> 12)));
1475 buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1476 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1477 } else if (c >= 0x10000 && c <= 0x10ffff) {
1478 buf.push_back(static_cast<char>(0xf0 | (c >> 18)));
1479 buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12)));
1480 buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6)));
1481 buf.push_back(static_cast<char>(0x80 | (c & 0x3f)));
1482 } else {
1483 return false;
1484 }
1485 }
1486 return true;
1487 }
1488};
1489
1490// Computes 128-bit result of multiplication of two 64-bit unsigned integers.
1491inline uint128_fallback umul128(uint64_t x, uint64_t y) noexcept {
1492#if FMT_USE_INT128
1493 auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
1494 return {static_cast<uint64_t>(p >> 64), static_cast<uint64_t>(p)};
1495#elif defined(_MSC_VER) && defined(_M_X64)
1496 auto hi = uint64_t();
1497 auto lo = _umul128(x, y, &hi);
1498 return {hi, lo};
1499#else
1500 const uint64_t mask = static_cast<uint64_t>(max_value<uint32_t>());
1501
1502 uint64_t a = x >> 32;
1503 uint64_t b = x & mask;
1504 uint64_t c = y >> 32;
1505 uint64_t d = y & mask;
1506
1507 uint64_t ac = a * c;
1508 uint64_t bc = b * c;
1509 uint64_t ad = a * d;
1510 uint64_t bd = b * d;
1511
1512 uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask);
1513
1514 return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32),
1515 (intermediate << 32) + (bd & mask)};
1516#endif
1517}
1518
1519namespace dragonbox {
1520// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from
1521// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1.
1522inline int floor_log10_pow2(int e) noexcept {
1523 FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent");
1524 static_assert((-1 >> 1) == -1, "right shift is not arithmetic");
1525 return (e * 315653) >> 20;
1526}
1527
1528inline int floor_log2_pow10(int e) noexcept {
1529 FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent");
1530 return (e * 1741647) >> 19;
1531}
1532
1533// Computes upper 64 bits of multiplication of two 64-bit unsigned integers.
1534inline uint64_t umul128_upper64(uint64_t x, uint64_t y) noexcept {
1535#if FMT_USE_INT128
1536 auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y);
1537 return static_cast<uint64_t>(p >> 64);
1538#elif defined(_MSC_VER) && defined(_M_X64)
1539 return __umulh(x, y);
1540#else
1541 return umul128(x, y).high();
1542#endif
1543}
1544
1545// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a
1546// 128-bit unsigned integer.
1548 uint128_fallback y) noexcept {
1549 uint128_fallback r = umul128(x, y.high());
1550 r += umul128_upper64(x, y.low());
1551 return r;
1552}
1553
1555
1556// Type-specific information that Dragonbox uses.
1557template <typename T, typename Enable = void> struct float_info;
1558
1559template <> struct float_info<float> {
1560 using carrier_uint = uint32_t;
1561 static const int exponent_bits = 8;
1562 static const int kappa = 1;
1563 static const int big_divisor = 100;
1564 static const int small_divisor = 10;
1565 static const int min_k = -31;
1566 static const int max_k = 46;
1567 static const int shorter_interval_tie_lower_threshold = -35;
1568 static const int shorter_interval_tie_upper_threshold = -35;
1569};
1570
1571template <> struct float_info<double> {
1572 using carrier_uint = uint64_t;
1573 static const int exponent_bits = 11;
1574 static const int kappa = 2;
1575 static const int big_divisor = 1000;
1576 static const int small_divisor = 100;
1577 static const int min_k = -292;
1578 static const int max_k = 341;
1579 static const int shorter_interval_tie_lower_threshold = -77;
1580 static const int shorter_interval_tie_upper_threshold = -77;
1581};
1582
1583// An 80- or 128-bit floating point number.
1584template <typename T>
1585struct float_info<T, enable_if_t<std::numeric_limits<T>::digits == 64 ||
1586 std::numeric_limits<T>::digits == 113 ||
1587 is_float128<T>::value>> {
1589 static const int exponent_bits = 15;
1590};
1591
1592// A double-double floating point number.
1593template <typename T>
1594struct float_info<T, enable_if_t<is_double_double<T>::value>> {
1596};
1597
1598template <typename T> struct decimal_fp {
1602};
1603
1604template <typename T> FMT_API auto to_decimal(T x) noexcept -> decimal_fp<T>;
1605} // namespace dragonbox
1606
1607// Returns true iff Float has the implicit bit which is not stored.
1608template <typename Float> constexpr bool has_implicit_bit() {
1609 // An 80-bit FP number has a 64-bit significand an no implicit bit.
1610 return std::numeric_limits<Float>::digits != 64;
1611}
1612
1613// Returns the number of significand bits stored in Float. The implicit bit is
1614// not counted since it is not stored.
1615template <typename Float> constexpr int num_significand_bits() {
1616 // std::numeric_limits may not support __float128.
1617 return is_float128<Float>() ? 112
1618 : (std::numeric_limits<Float>::digits -
1619 (has_implicit_bit<Float>() ? 1 : 0));
1620}
1621
1622template <typename Float>
1623constexpr auto exponent_mask() ->
1625 using float_uint = typename dragonbox::float_info<Float>::carrier_uint;
1626 return ((float_uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1)
1627 << num_significand_bits<Float>();
1628}
1629template <typename Float> constexpr auto exponent_bias() -> int {
1630 // std::numeric_limits may not support __float128.
1631 return is_float128<Float>() ? 16383
1632 : std::numeric_limits<Float>::max_exponent - 1;
1633}
1634
1635// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1636template <typename Char, typename It>
1637FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It {
1638 FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
1639 if (exp < 0) {
1640 *it++ = static_cast<Char>('-');
1641 exp = -exp;
1642 } else {
1643 *it++ = static_cast<Char>('+');
1644 }
1645 if (exp >= 100) {
1646 const char* top = digits2(to_unsigned(exp / 100));
1647 if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
1648 *it++ = static_cast<Char>(top[1]);
1649 exp %= 100;
1650 }
1651 const char* d = digits2(to_unsigned(exp));
1652 *it++ = static_cast<Char>(d[0]);
1653 *it++ = static_cast<Char>(d[1]);
1654 return it;
1655}
1656
1657// A floating-point number f * pow(2, e) where F is an unsigned type.
1658template <typename F> struct basic_fp {
1660 int e;
1661
1662 static constexpr const int num_significand_bits =
1663 static_cast<int>(sizeof(F) * num_bits<unsigned char>());
1664
1665 constexpr basic_fp() : f(0), e(0) {}
1666 constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {}
1667
1668 // Constructs fp from an IEEE754 floating-point number.
1669 template <typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); }
1670
1671 // Assigns n to this and return true iff predecessor is closer than successor.
1672 template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
1673 FMT_CONSTEXPR auto assign(Float n) -> bool {
1674 static_assert(std::numeric_limits<Float>::digits <= 113, "unsupported FP");
1675 // Assume Float is in the format [sign][exponent][significand].
1676 using carrier_uint = typename dragonbox::float_info<Float>::carrier_uint;
1677 const auto num_float_significand_bits =
1678 detail::num_significand_bits<Float>();
1679 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
1680 const auto significand_mask = implicit_bit - 1;
1681 auto u = bit_cast<carrier_uint>(n);
1682 f = static_cast<F>(u & significand_mask);
1683 auto biased_e = static_cast<int>((u & exponent_mask<Float>()) >>
1684 num_float_significand_bits);
1685 // The predecessor is closer if n is a normalized power of 2 (f == 0)
1686 // other than the smallest normalized number (biased_e > 1).
1687 auto is_predecessor_closer = f == 0 && biased_e > 1;
1688 if (biased_e == 0)
1689 biased_e = 1; // Subnormals use biased exponent 1 (min exponent).
1690 else if (has_implicit_bit<Float>())
1691 f += static_cast<F>(implicit_bit);
1692 e = biased_e - exponent_bias<Float>() - num_float_significand_bits;
1693 if (!has_implicit_bit<Float>()) ++e;
1694 return is_predecessor_closer;
1695 }
1696
1697 template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
1698 FMT_CONSTEXPR auto assign(Float n) -> bool {
1699 static_assert(std::numeric_limits<double>::is_iec559, "unsupported FP");
1700 return assign(static_cast<double>(n));
1701 }
1702};
1703
1705
1706// Normalizes the value converted from double and multiplied by (1 << SHIFT).
1707template <int SHIFT = 0, typename F>
1709 // Handle subnormals.
1710 const auto implicit_bit = F(1) << num_significand_bits<double>();
1711 const auto shifted_implicit_bit = implicit_bit << SHIFT;
1712 while ((value.f & shifted_implicit_bit) == 0) {
1713 value.f <<= 1;
1714 --value.e;
1715 }
1716 // Subtract 1 to account for hidden bit.
1717 const auto offset = basic_fp<F>::num_significand_bits -
1718 num_significand_bits<double>() - SHIFT - 1;
1719 value.f <<= offset;
1720 value.e -= offset;
1721 return value;
1722}
1723
1724// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking.
1725FMT_CONSTEXPR inline uint64_t multiply(uint64_t lhs, uint64_t rhs) {
1726#if FMT_USE_INT128
1727 auto product = static_cast<__uint128_t>(lhs) * rhs;
1728 auto f = static_cast<uint64_t>(product >> 64);
1729 return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f;
1730#else
1731 // Multiply 32-bit parts of significands.
1732 uint64_t mask = (1ULL << 32) - 1;
1733 uint64_t a = lhs >> 32, b = lhs & mask;
1734 uint64_t c = rhs >> 32, d = rhs & mask;
1735 uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d;
1736 // Compute mid 64-bit of result and round.
1737 uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31);
1738 return ac + (ad >> 32) + (bc >> 32) + (mid >> 32);
1739#endif
1740}
1741
1743 return {multiply(x.f, y.f), x.e + y.e + 64};
1744}
1745
1746template <typename T = void> struct basic_data {
1747 // For checking rounding thresholds.
1748 // The kth entry is chosen to be the smallest integer such that the
1749 // upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k.
1750 static constexpr uint32_t fractional_part_rounding_thresholds[8] = {
1751 2576980378U, // ceil(2^31 + 2^32/10^1)
1752 2190433321U, // ceil(2^31 + 2^32/10^2)
1753 2151778616U, // ceil(2^31 + 2^32/10^3)
1754 2147913145U, // ceil(2^31 + 2^32/10^4)
1755 2147526598U, // ceil(2^31 + 2^32/10^5)
1756 2147487943U, // ceil(2^31 + 2^32/10^6)
1757 2147484078U, // ceil(2^31 + 2^32/10^7)
1758 2147483691U // ceil(2^31 + 2^32/10^8)
1759 };
1760};
1761// This is a struct rather than an alias to avoid shadowing warnings in gcc.
1762struct data : basic_data<> {};
1763
1764#if FMT_CPLUSPLUS < 201703L
1765template <typename T>
1767#endif
1768
1769template <typename T, bool doublish = num_bits<T>() == num_bits<double>()>
1771 conditional_t<std::is_same<T, float>::value || doublish, double, T>;
1772
1773template <typename T>
1775 return static_cast<convert_float_result<T>>(value);
1776}
1777
1778template <typename OutputIt, typename Char>
1779FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,
1780 const fill_t<Char>& fill) -> OutputIt {
1781 auto fill_size = fill.size();
1782 if (fill_size == 1) return detail::fill_n(it, n, fill[0]);
1783 auto data = fill.data();
1784 for (size_t i = 0; i < n; ++i)
1785 it = copy_str<Char>(data, data + fill_size, it);
1786 return it;
1787}
1788
1789// Writes the output of f, padded according to format specifications in specs.
1790// size: output size in code units.
1791// width: output display width in (terminal) column positions.
1792template <align::type align = align::left, typename OutputIt, typename Char,
1793 typename F>
1794FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs<Char>& specs,
1795 size_t size, size_t width, F&& f) -> OutputIt {
1796 static_assert(align == align::left || align == align::right, "");
1797 unsigned spec_width = to_unsigned(specs.width);
1798 size_t padding = spec_width > width ? spec_width - width : 0;
1799 // Shifts are encoded as string literals because static constexpr is not
1800 // supported in constexpr functions.
1801 auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1802 size_t left_padding = padding >> shifts[specs.align];
1803 size_t right_padding = padding - left_padding;
1804 auto it = reserve(out, size + padding * specs.fill.size());
1805 if (left_padding != 0) it = fill(it, left_padding, specs.fill);
1806 it = f(it);
1807 if (right_padding != 0) it = fill(it, right_padding, specs.fill);
1808 return base_iterator(out, it);
1809}
1810
1811template <align::type align = align::left, typename OutputIt, typename Char,
1812 typename F>
1813constexpr auto write_padded(OutputIt out, const format_specs<Char>& specs,
1814 size_t size, F&& f) -> OutputIt {
1815 return write_padded<align>(out, specs, size, size, f);
1816}
1817
1818template <align::type align = align::left, typename Char, typename OutputIt>
1820 const format_specs<Char>& specs) -> OutputIt {
1821 return write_padded<align>(
1822 out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
1823 const char* data = bytes.data();
1824 return copy_str<Char>(data, data + bytes.size(), it);
1825 });
1826}
1827
1828template <typename Char, typename OutputIt, typename UIntPtr>
1829auto write_ptr(OutputIt out, UIntPtr value, const format_specs<Char>* specs)
1830 -> OutputIt {
1831 int num_digits = count_digits<4>(value);
1832 auto size = to_unsigned(num_digits) + size_t(2);
1833 auto write = [=](reserve_iterator<OutputIt> it) {
1834 *it++ = static_cast<Char>('0');
1835 *it++ = static_cast<Char>('x');
1836 return format_uint<4, Char>(it, value, num_digits);
1837 };
1838 return specs ? write_padded<align::right>(out, *specs, size, write)
1839 : base_iterator(out, write(reserve(out, size)));
1840}
1841
1842// Returns true iff the code point cp is printable.
1843FMT_API auto is_printable(uint32_t cp) -> bool;
1844
1845inline auto needs_escape(uint32_t cp) -> bool {
1846 return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' ||
1847 !is_printable(cp);
1848}
1849
1850template <typename Char> struct find_escape_result {
1851 const Char* begin;
1852 const Char* end;
1853 uint32_t cp;
1854};
1855
1856template <typename Char>
1859 std::make_unsigned<Char>,
1861
1862template <typename Char>
1863auto find_escape(const Char* begin, const Char* end)
1865 for (; begin != end; ++begin) {
1866 uint32_t cp = static_cast<make_unsigned_char<Char>>(*begin);
1867 if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue;
1868 if (needs_escape(cp)) return {begin, begin + 1, cp};
1869 }
1870 return {begin, nullptr, 0};
1871}
1872
1873inline auto find_escape(const char* begin, const char* end)
1875 if (!is_utf8()) return find_escape<char>(begin, end);
1876 auto result = find_escape_result<char>{end, nullptr, 0};
1877 for_each_codepoint(string_view(begin, to_unsigned(end - begin)),
1878 [&](uint32_t cp, string_view sv) {
1879 if (needs_escape(cp)) {
1880 result = {sv.begin(), sv.end(), cp};
1881 return false;
1882 }
1883 return true;
1884 });
1885 return result;
1886}
1887
1888#define FMT_STRING_IMPL(s, base, explicit) \
1889 [] { \
1890 /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
1891 /* Use a macro-like name to avoid shadowing warnings. */ \
1892 struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \
1893 using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \
1894 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
1895 operator fmt::basic_string_view<char_type>() const { \
1896 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
1897 } \
1898 }; \
1899 return FMT_COMPILE_STRING(); \
1900 }()
1901
1902/**
1903 \rst
1904 Constructs a compile-time format string from a string literal *s*.
1905
1906 **Example**::
1907
1908 // A compile-time error because 'd' is an invalid specifier for strings.
1909 std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
1910 \endrst
1911 */
1912#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, )
1913
1914template <size_t width, typename Char, typename OutputIt>
1915auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt {
1916 *out++ = static_cast<Char>('\\');
1917 *out++ = static_cast<Char>(prefix);
1918 Char buf[width];
1919 fill_n(buf, width, static_cast<Char>('0'));
1920 format_uint<4>(buf, cp, width);
1921 return copy_str<Char>(buf, buf + width, out);
1922}
1923
1924template <typename OutputIt, typename Char>
1926 -> OutputIt {
1927 auto c = static_cast<Char>(escape.cp);
1928 switch (escape.cp) {
1929 case '\n':
1930 *out++ = static_cast<Char>('\\');
1931 c = static_cast<Char>('n');
1932 break;
1933 case '\r':
1934 *out++ = static_cast<Char>('\\');
1935 c = static_cast<Char>('r');
1936 break;
1937 case '\t':
1938 *out++ = static_cast<Char>('\\');
1939 c = static_cast<Char>('t');
1940 break;
1941 case '"':
1943 case '\'':
1945 case '\\':
1946 *out++ = static_cast<Char>('\\');
1947 break;
1948 default:
1949 if (escape.cp < 0x100) {
1950 return write_codepoint<2, Char>(out, 'x', escape.cp);
1951 }
1952 if (escape.cp < 0x10000) {
1953 return write_codepoint<4, Char>(out, 'u', escape.cp);
1954 }
1955 if (escape.cp < 0x110000) {
1956 return write_codepoint<8, Char>(out, 'U', escape.cp);
1957 }
1958 for (Char escape_char : basic_string_view<Char>(
1959 escape.begin, to_unsigned(escape.end - escape.begin))) {
1960 out = write_codepoint<2, Char>(out, 'x',
1961 static_cast<uint32_t>(escape_char) & 0xFF);
1962 }
1963 return out;
1964 }
1965 *out++ = c;
1966 return out;
1967}
1968
1969template <typename Char, typename OutputIt>
1971 -> OutputIt {
1972 *out++ = static_cast<Char>('"');
1973 auto begin = str.begin(), end = str.end();
1974 do {
1975 auto escape = find_escape(begin, end);
1976 out = copy_str<Char>(begin, escape.begin, out);
1977 begin = escape.end;
1978 if (!begin) break;
1979 out = write_escaped_cp<OutputIt, Char>(out, escape);
1980 } while (begin != end);
1981 *out++ = static_cast<Char>('"');
1982 return out;
1983}
1984
1985template <typename Char, typename OutputIt>
1986auto write_escaped_char(OutputIt out, Char v) -> OutputIt {
1987 *out++ = static_cast<Char>('\'');
1988 if ((needs_escape(static_cast<uint32_t>(v)) && v != static_cast<Char>('"')) ||
1989 v == static_cast<Char>('\'')) {
1990 out = write_escaped_cp(
1991 out, find_escape_result<Char>{&v, &v + 1, static_cast<uint32_t>(v)});
1992 } else {
1993 *out++ = v;
1994 }
1995 *out++ = static_cast<Char>('\'');
1996 return out;
1997}
1998
1999template <typename Char, typename OutputIt>
2000FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
2001 const format_specs<Char>& specs) -> OutputIt {
2002 bool is_debug = specs.type == presentation_type::debug;
2003 return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
2004 if (is_debug) return write_escaped_char(it, value);
2005 *it++ = value;
2006 return it;
2007 });
2008}
2009template <typename Char, typename OutputIt>
2010FMT_CONSTEXPR auto write(OutputIt out, Char value,
2011 const format_specs<Char>& specs, locale_ref loc = {})
2012 -> OutputIt {
2013 // char is formatted as unsigned char for consistency across platforms.
2014 using unsigned_type =
2015 conditional_t<std::is_same<Char, char>::value, unsigned char, unsigned>;
2016 return check_char_specs(specs)
2017 ? write_char(out, value, specs)
2018 : write(out, static_cast<unsigned_type>(value), specs, loc);
2019}
2020
2021// Data for write_int that doesn't depend on output iterator type. It is used to
2022// avoid template code bloat.
2023template <typename Char> struct write_int_data {
2024 size_t size;
2025 size_t padding;
2026
2027 FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix,
2028 const format_specs<Char>& specs)
2029 : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
2030 if (specs.align == align::numeric) {
2031 auto width = to_unsigned(specs.width);
2032 if (width > size) {
2033 padding = width - size;
2034 size = width;
2035 }
2036 } else if (specs.precision > num_digits) {
2037 size = (prefix >> 24) + to_unsigned(specs.precision);
2038 padding = to_unsigned(specs.precision - num_digits);
2039 }
2040 }
2041};
2042
2043// Writes an integer in the format
2044// <left-padding><prefix><numeric-padding><digits><right-padding>
2045// where <digits> are written by write_digits(it).
2046// prefix contains chars in three lower bytes and the size in the fourth byte.
2047template <typename OutputIt, typename Char, typename W>
2048FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits,
2049 unsigned prefix,
2050 const format_specs<Char>& specs,
2051 W write_digits) -> OutputIt {
2052 // Slightly faster check for specs.width == 0 && specs.precision == -1.
2053 if ((specs.width | (specs.precision + 1)) == 0) {
2054 auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
2055 if (prefix != 0) {
2056 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2057 *it++ = static_cast<Char>(p & 0xff);
2058 }
2059 return base_iterator(out, write_digits(it));
2060 }
2061 auto data = write_int_data<Char>(num_digits, prefix, specs);
2062 return write_padded<align::right>(
2063 out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
2064 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
2065 *it++ = static_cast<Char>(p & 0xff);
2066 it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
2067 return write_digits(it);
2068 });
2069}
2070
2071template <typename Char> class digit_grouping {
2072 private:
2073 std::string grouping_;
2074 std::basic_string<Char> thousands_sep_;
2075
2076 struct next_state {
2077 std::string::const_iterator group;
2078 int pos;
2079 };
2080 next_state initial_state() const { return {grouping_.begin(), 0}; }
2081
2082 // Returns the next digit group separator position.
2083 int next(next_state& state) const {
2084 if (thousands_sep_.empty()) return max_value<int>();
2085 if (state.group == grouping_.end()) return state.pos += grouping_.back();
2086 if (*state.group <= 0 || *state.group == max_value<char>())
2087 return max_value<int>();
2088 state.pos += *state.group++;
2089 return state.pos;
2090 }
2091
2092 public:
2093 explicit digit_grouping(locale_ref loc, bool localized = true) {
2094 if (!localized) return;
2095 auto sep = thousands_sep<Char>(loc);
2096 grouping_ = sep.grouping;
2097 if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep);
2098 }
2099 digit_grouping(std::string grouping, std::basic_string<Char> sep)
2100 : grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {}
2101
2102 bool has_separator() const { return !thousands_sep_.empty(); }
2103
2104 int count_separators(int num_digits) const {
2105 int count = 0;
2106 auto state = initial_state();
2107 while (num_digits > next(state)) ++count;
2108 return count;
2109 }
2110
2111 // Applies grouping to digits and write the output to out.
2112 template <typename Out, typename C>
2113 Out apply(Out out, basic_string_view<C> digits) const {
2114 auto num_digits = static_cast<int>(digits.size());
2115 auto separators = basic_memory_buffer<int>();
2116 separators.push_back(0);
2117 auto state = initial_state();
2118 while (int i = next(state)) {
2119 if (i >= num_digits) break;
2120 separators.push_back(i);
2121 }
2122 for (int i = 0, sep_index = static_cast<int>(separators.size() - 1);
2123 i < num_digits; ++i) {
2124 if (num_digits - i == separators[sep_index]) {
2125 out =
2126 copy_str<Char>(thousands_sep_.data(),
2127 thousands_sep_.data() + thousands_sep_.size(), out);
2128 --sep_index;
2129 }
2130 *out++ = static_cast<Char>(digits[to_unsigned(i)]);
2131 }
2132 return out;
2133 }
2134};
2135
2136// Writes a decimal integer with digit grouping.
2137template <typename OutputIt, typename UInt, typename Char>
2138auto write_int(OutputIt out, UInt value, unsigned prefix,
2139 const format_specs<Char>& specs,
2140 const digit_grouping<Char>& grouping) -> OutputIt {
2141 static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
2142 int num_digits = count_digits(value);
2143 char digits[40];
2144 format_decimal(digits, value, num_digits);
2145 unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits +
2146 grouping.count_separators(num_digits));
2147 return write_padded<align::right>(
2148 out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
2149 if (prefix != 0) {
2150 char sign = static_cast<char>(prefix);
2151 *it++ = static_cast<Char>(sign);
2152 }
2153 return grouping.apply(it, string_view(digits, to_unsigned(num_digits)));
2154 });
2155}
2156
2157// Writes a localized value.
2158FMT_API auto write_loc(appender out, loc_value value,
2159 const format_specs<>& specs, locale_ref loc) -> bool;
2160template <typename OutputIt, typename Char>
2161inline auto write_loc(OutputIt, loc_value, const format_specs<Char>&,
2162 locale_ref) -> bool {
2163 return false;
2164}
2165
2166FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
2167 prefix |= prefix != 0 ? value << 8 : value;
2168 prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
2169}
2170
2171template <typename UInt> struct write_int_arg {
2173 unsigned prefix;
2174};
2175
2176template <typename T>
2179 auto prefix = 0u;
2180 auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2181 if (is_negative(value)) {
2182 prefix = 0x01000000 | '-';
2183 abs_value = 0 - abs_value;
2184 } else {
2185 constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
2186 0x1000000u | ' '};
2187 prefix = prefixes[sign];
2188 }
2189 return {abs_value, prefix};
2190}
2191
2192template <typename Char = char> struct loc_writer {
2195 std::basic_string<Char> sep;
2196 std::string grouping;
2197 std::basic_string<Char> decimal_point;
2198
2199 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2200 auto operator()(T value) -> bool {
2202 write_int(out, static_cast<uint64_or_128_t<T>>(arg.abs_value), arg.prefix,
2204 return true;
2205 }
2206
2207 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2208 auto operator()(T) -> bool {
2209 return false;
2210 }
2211};
2212
2213template <typename Char, typename OutputIt, typename T>
2215 const format_specs<Char>& specs,
2216 locale_ref) -> OutputIt {
2217 static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, "");
2218 auto abs_value = arg.abs_value;
2219 auto prefix = arg.prefix;
2220 switch (specs.type) {
2223 auto num_digits = count_digits(abs_value);
2224 return write_int(
2225 out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
2226 return format_decimal<Char>(it, abs_value, num_digits).end;
2227 });
2228 }
2231 bool upper = specs.type == presentation_type::hex_upper;
2232 if (specs.alt)
2233 prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0');
2234 int num_digits = count_digits<4>(abs_value);
2235 return write_int(
2236 out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
2237 return format_uint<4, Char>(it, abs_value, num_digits, upper);
2238 });
2239 }
2242 bool upper = specs.type == presentation_type::bin_upper;
2243 if (specs.alt)
2244 prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0');
2245 int num_digits = count_digits<1>(abs_value);
2246 return write_int(out, num_digits, prefix, specs,
2248 return format_uint<1, Char>(it, abs_value, num_digits);
2249 });
2250 }
2252 int num_digits = count_digits<3>(abs_value);
2253 // Octal prefix '0' is counted as a digit, so only add it if precision
2254 // is not greater than the number of digits.
2255 if (specs.alt && specs.precision <= num_digits && abs_value != 0)
2256 prefix_append(prefix, '0');
2257 return write_int(out, num_digits, prefix, specs,
2259 return format_uint<3, Char>(it, abs_value, num_digits);
2260 });
2261 }
2263 return write_char(out, static_cast<Char>(abs_value), specs);
2264 default:
2265 throw_format_error("invalid format specifier");
2266 }
2267 return out;
2268}
2269template <typename Char, typename OutputIt, typename T>
2271 OutputIt out, write_int_arg<T> arg, const format_specs<Char>& specs,
2272 locale_ref loc) -> OutputIt {
2273 return write_int(out, arg, specs, loc);
2274}
2275template <typename Char, typename OutputIt, typename T,
2276 FMT_ENABLE_IF(is_integral<T>::value &&
2277 !std::is_same<T, bool>::value &&
2278 std::is_same<OutputIt, buffer_appender<Char>>::value)>
2280 const format_specs<Char>& specs,
2281 locale_ref loc) -> OutputIt {
2282 if (specs.localized && write_loc(out, value, specs, loc)) return out;
2283 return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs,
2284 loc);
2285}
2286// An inlined version of write used in format string compilation.
2287template <typename Char, typename OutputIt, typename T,
2288 FMT_ENABLE_IF(is_integral<T>::value &&
2289 !std::is_same<T, bool>::value &&
2290 !std::is_same<OutputIt, buffer_appender<Char>>::value)>
2291FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
2292 const format_specs<Char>& specs,
2293 locale_ref loc) -> OutputIt {
2294 if (specs.localized && write_loc(out, value, specs, loc)) return out;
2295 return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
2296}
2297
2298// An output iterator that counts the number of objects written to it and
2299// discards them.
2301 private:
2302 size_t count_;
2303
2304 public:
2305 using iterator_category = std::output_iterator_tag;
2306 using difference_type = std::ptrdiff_t;
2307 using pointer = void;
2308 using reference = void;
2310
2311 struct value_type {
2312 template <typename T> FMT_CONSTEXPR void operator=(const T&) {}
2313 };
2314
2316
2317 FMT_CONSTEXPR size_t count() const { return count_; }
2318
2320 ++count_;
2321 return *this;
2322 }
2324 auto it = *this;
2325 ++*this;
2326 return it;
2327 }
2328
2330 difference_type n) {
2331 it.count_ += static_cast<size_t>(n);
2332 return it;
2333 }
2334
2335 FMT_CONSTEXPR value_type operator*() const { return {}; }
2336};
2337
2338template <typename Char, typename OutputIt>
2340 const format_specs<Char>& specs) -> OutputIt {
2341 auto data = s.data();
2342 auto size = s.size();
2343 if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
2344 size = code_point_index(s, to_unsigned(specs.precision));
2345 bool is_debug = specs.type == presentation_type::debug;
2346 size_t width = 0;
2347 if (specs.width != 0) {
2348 if (is_debug)
2350 else
2352 }
2353 return write_padded(out, specs, size, width,
2355 if (is_debug) return write_escaped_string(it, s);
2356 return copy_str<Char>(data, data + size, it);
2357 });
2358}
2359template <typename Char, typename OutputIt>
2360FMT_CONSTEXPR auto write(OutputIt out,
2362 const format_specs<Char>& specs, locale_ref)
2363 -> OutputIt {
2364 return write(out, s, specs);
2365}
2366template <typename Char, typename OutputIt>
2367FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
2368 const format_specs<Char>& specs, locale_ref)
2369 -> OutputIt {
2370 return specs.type != presentation_type::pointer
2371 ? write(out, basic_string_view<Char>(s), specs, {})
2372 : write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs);
2373}
2374
2375template <typename Char, typename OutputIt, typename T,
2376 FMT_ENABLE_IF(is_integral<T>::value &&
2377 !std::is_same<T, bool>::value &&
2378 !std::is_same<T, Char>::value)>
2379FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
2380 auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2381 bool negative = is_negative(value);
2382 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2383 if (negative) abs_value = ~abs_value + 1;
2384 int num_digits = count_digits(abs_value);
2385 auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
2386 auto it = reserve(out, size);
2387 if (auto ptr = to_pointer<Char>(it, size)) {
2388 if (negative) *ptr++ = static_cast<Char>('-');
2389 format_decimal<Char>(ptr, abs_value, num_digits);
2390 return out;
2391 }
2392 if (negative) *it++ = static_cast<Char>('-');
2393 it = format_decimal<Char>(it, abs_value, num_digits).end;
2394 return base_iterator(out, it);
2395}
2396
2397// DEPRECATED!
2398template <typename Char>
2399FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end,
2400 format_specs<Char>& specs) -> const Char* {
2401 FMT_ASSERT(begin != end, "");
2402 auto align = align::none;
2403 auto p = begin + code_point_length(begin);
2404 if (end - p <= 0) p = begin;
2405 for (;;) {
2406 switch (to_ascii(*p)) {
2407 case '<':
2408 align = align::left;
2409 break;
2410 case '>':
2411 align = align::right;
2412 break;
2413 case '^':
2414 align = align::center;
2415 break;
2416 }
2417 if (align != align::none) {
2418 if (p != begin) {
2419 auto c = *begin;
2420 if (c == '}') return begin;
2421 if (c == '{') {
2422 throw_format_error("invalid fill character '{'");
2423 return begin;
2424 }
2425 specs.fill = {begin, to_unsigned(p - begin)};
2426 begin = p + 1;
2427 } else {
2428 ++begin;
2429 }
2430 break;
2431 } else if (p == begin) {
2432 break;
2433 }
2434 p = begin;
2435 }
2436 specs.align = align;
2437 return begin;
2438}
2439
2440// A floating-point presentation format.
2441enum class float_format : unsigned char {
2442 general, // General: exponent notation or fixed point based on magnitude.
2443 exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
2444 fixed, // Fixed point with the default precision of 6, e.g. 0.0012.
2445 hex
2446};
2447
2452 bool upper : 1;
2453 bool locale : 1;
2454 bool binary32 : 1;
2455 bool showpoint : 1;
2456};
2457
2458template <typename ErrorHandler = error_handler, typename Char>
2460 ErrorHandler&& eh = {})
2461 -> float_specs {
2462 auto result = float_specs();
2463 result.showpoint = specs.alt;
2464 result.locale = specs.localized;
2465 switch (specs.type) {
2467 result.format = float_format::general;
2468 break;
2470 result.upper = true;
2473 result.format = float_format::general;
2474 break;
2476 result.upper = true;
2479 result.format = float_format::exp;
2480 result.showpoint |= specs.precision != 0;
2481 break;
2483 result.upper = true;
2486 result.format = float_format::fixed;
2487 result.showpoint |= specs.precision != 0;
2488 break;
2490 result.upper = true;
2493 result.format = float_format::hex;
2494 break;
2495 default:
2496 eh.on_error("invalid format specifier");
2497 break;
2498 }
2499 return result;
2500}
2501
2502template <typename Char, typename OutputIt>
2503FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan,
2504 format_specs<Char> specs,
2505 const float_specs& fspecs) -> OutputIt {
2506 auto str =
2507 isnan ? (fspecs.upper ? "NAN" : "nan") : (fspecs.upper ? "INF" : "inf");
2508 constexpr size_t str_size = 3;
2509 auto sign = fspecs.sign;
2510 auto size = str_size + (sign ? 1 : 0);
2511 // Replace '0'-padding with space for non-finite values.
2512 const bool is_zero_fill =
2513 specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0');
2514 if (is_zero_fill) specs.fill[0] = static_cast<Char>(' ');
2515 return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
2516 if (sign) *it++ = detail::sign<Char>(sign);
2517 return copy_str<Char>(str, str + str_size, it);
2518 });
2519}
2520
2521// A decimal floating-point number significand * pow(10, exp).
2523 const char* significand;
2526};
2527
2528constexpr auto get_significand_size(const big_decimal_fp& f) -> int {
2529 return f.significand_size;
2530}
2531template <typename T>
2533 return count_digits(f.significand);
2534}
2535
2536template <typename Char, typename OutputIt>
2537constexpr auto write_significand(OutputIt out, const char* significand,
2538 int significand_size) -> OutputIt {
2539 return copy_str<Char>(significand, significand + significand_size, out);
2540}
2541template <typename Char, typename OutputIt, typename UInt>
2542inline auto write_significand(OutputIt out, UInt significand,
2543 int significand_size) -> OutputIt {
2544 return format_decimal<Char>(out, significand, significand_size).end;
2545}
2546template <typename Char, typename OutputIt, typename T, typename Grouping>
2547FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
2548 int significand_size, int exponent,
2549 const Grouping& grouping) -> OutputIt {
2550 if (!grouping.has_separator()) {
2551 out = write_significand<Char>(out, significand, significand_size);
2552 return detail::fill_n(out, exponent, static_cast<Char>('0'));
2553 }
2554 auto buffer = memory_buffer();
2555 write_significand<char>(appender(buffer), significand, significand_size);
2556 detail::fill_n(appender(buffer), exponent, '0');
2557 return grouping.apply(out, string_view(buffer.data(), buffer.size()));
2558}
2559
2560template <typename Char, typename UInt,
2561 FMT_ENABLE_IF(std::is_integral<UInt>::value)>
2562inline auto write_significand(Char* out, UInt significand, int significand_size,
2563 int integral_size, Char decimal_point) -> Char* {
2564 if (!decimal_point)
2565 return format_decimal(out, significand, significand_size).end;
2566 out += significand_size + 1;
2567 Char* end = out;
2568 int floating_size = significand_size - integral_size;
2569 for (int i = floating_size / 2; i > 0; --i) {
2570 out -= 2;
2571 copy2(out, digits2(static_cast<std::size_t>(significand % 100)));
2572 significand /= 100;
2573 }
2574 if (floating_size % 2 != 0) {
2575 *--out = static_cast<Char>('0' + significand % 10);
2576 significand /= 10;
2577 }
2578 *--out = decimal_point;
2579 format_decimal(out - integral_size, significand, integral_size);
2580 return end;
2581}
2582
2583template <typename OutputIt, typename UInt, typename Char,
2584 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
2585inline auto write_significand(OutputIt out, UInt significand,
2586 int significand_size, int integral_size,
2587 Char decimal_point) -> OutputIt {
2588 // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
2589 Char buffer[digits10<UInt>() + 2];
2590 auto end = write_significand(buffer, significand, significand_size,
2591 integral_size, decimal_point);
2592 return detail::copy_str_noinline<Char>(buffer, end, out);
2593}
2594
2595template <typename OutputIt, typename Char>
2596FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand,
2597 int significand_size, int integral_size,
2598 Char decimal_point) -> OutputIt {
2599 out = detail::copy_str_noinline<Char>(significand,
2600 significand + integral_size, out);
2601 if (!decimal_point) return out;
2602 *out++ = decimal_point;
2603 return detail::copy_str_noinline<Char>(significand + integral_size,
2604 significand + significand_size, out);
2605}
2606
2607template <typename OutputIt, typename Char, typename T, typename Grouping>
2608FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
2609 int significand_size, int integral_size,
2610 Char decimal_point,
2611 const Grouping& grouping) -> OutputIt {
2612 if (!grouping.has_separator()) {
2613 return write_significand(out, significand, significand_size, integral_size,
2615 }
2618 significand_size, integral_size, decimal_point);
2619 grouping.apply(
2620 out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size)));
2621 return detail::copy_str_noinline<Char>(buffer.data() + integral_size,
2622 buffer.end(), out);
2623}
2624
2625template <typename OutputIt, typename DecimalFP, typename Char,
2626 typename Grouping = digit_grouping<Char>>
2627FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f,
2628 const format_specs<Char>& specs,
2629 float_specs fspecs, locale_ref loc)
2630 -> OutputIt {
2631 auto significand = f.significand;
2632 int significand_size = get_significand_size(f);
2633 const Char zero = static_cast<Char>('0');
2634 auto sign = fspecs.sign;
2635 size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
2636 using iterator = reserve_iterator<OutputIt>;
2637
2638 Char decimal_point =
2639 fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.');
2640
2641 int output_exp = f.exponent + significand_size - 1;
2642 auto use_exp_format = [=]() {
2643 if (fspecs.format == float_format::exp) return true;
2644 if (fspecs.format != float_format::general) return false;
2645 // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
2646 // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
2647 const int exp_lower = -4, exp_upper = 16;
2648 return output_exp < exp_lower ||
2649 output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
2650 };
2651 if (use_exp_format()) {
2652 int num_zeros = 0;
2653 if (fspecs.showpoint) {
2654 num_zeros = fspecs.precision - significand_size;
2655 if (num_zeros < 0) num_zeros = 0;
2656 size += to_unsigned(num_zeros);
2657 } else if (significand_size == 1) {
2658 decimal_point = Char();
2659 }
2660 auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
2661 int exp_digits = 2;
2662 if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
2663
2664 size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
2665 char exp_char = fspecs.upper ? 'E' : 'e';
2666 auto write = [=](iterator it) {
2667 if (sign) *it++ = detail::sign<Char>(sign);
2668 // Insert a decimal point after the first digit and add an exponent.
2669 it = write_significand(it, significand, significand_size, 1,
2671 if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero);
2672 *it++ = static_cast<Char>(exp_char);
2673 return write_exponent<Char>(output_exp, it);
2674 };
2675 return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)
2676 : base_iterator(out, write(reserve(out, size)));
2677 }
2678
2679 int exp = f.exponent + significand_size;
2680 if (f.exponent >= 0) {
2681 // 1234e5 -> 123400000[.0+]
2682 size += to_unsigned(f.exponent);
2683 int num_zeros = fspecs.precision - exp;
2684 abort_fuzzing_if(num_zeros > 5000);
2685 if (fspecs.showpoint) {
2686 ++size;
2687 if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 0;
2688 if (num_zeros > 0) size += to_unsigned(num_zeros);
2689 }
2690 auto grouping = Grouping(loc, fspecs.locale);
2691 size += to_unsigned(grouping.count_separators(exp));
2692 return write_padded<align::right>(out, specs, size, [&](iterator it) {
2693 if (sign) *it++ = detail::sign<Char>(sign);
2694 it = write_significand<Char>(it, significand, significand_size,
2695 f.exponent, grouping);
2696 if (!fspecs.showpoint) return it;
2697 *it++ = decimal_point;
2698 return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
2699 });
2700 } else if (exp > 0) {
2701 // 1234e-2 -> 12.34[0+]
2702 int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
2703 size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
2704 auto grouping = Grouping(loc, fspecs.locale);
2705 size += to_unsigned(grouping.count_separators(exp));
2706 return write_padded<align::right>(out, specs, size, [&](iterator it) {
2707 if (sign) *it++ = detail::sign<Char>(sign);
2708 it = write_significand(it, significand, significand_size, exp,
2709 decimal_point, grouping);
2710 return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
2711 });
2712 }
2713 // 1234e-6 -> 0.001234
2714 int num_zeros = -exp;
2715 if (significand_size == 0 && fspecs.precision >= 0 &&
2716 fspecs.precision < num_zeros) {
2717 num_zeros = fspecs.precision;
2718 }
2719 bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
2720 size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);
2721 return write_padded<align::right>(out, specs, size, [&](iterator it) {
2722 if (sign) *it++ = detail::sign<Char>(sign);
2723 *it++ = zero;
2724 if (!pointy) return it;
2725 *it++ = decimal_point;
2726 it = detail::fill_n(it, num_zeros, zero);
2727 return write_significand<Char>(it, significand, significand_size);
2728 });
2729}
2730
2731template <typename Char> class fallback_digit_grouping {
2732 public:
2734
2735 constexpr bool has_separator() const { return false; }
2736
2737 constexpr int count_separators(int) const { return 0; }
2738
2739 template <typename Out, typename C>
2740 constexpr Out apply(Out out, basic_string_view<C>) const {
2741 return out;
2742 }
2743};
2744
2745template <typename OutputIt, typename DecimalFP, typename Char>
2746FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f,
2747 const format_specs<Char>& specs,
2748 float_specs fspecs, locale_ref loc)
2749 -> OutputIt {
2750 if (is_constant_evaluated()) {
2751 return do_write_float<OutputIt, DecimalFP, Char,
2752 fallback_digit_grouping<Char>>(out, f, specs, fspecs,
2753 loc);
2754 } else {
2755 return do_write_float(out, f, specs, fspecs, loc);
2756 }
2757}
2758
2759template <typename T> constexpr bool isnan(T value) {
2760 return !(value >= value); // std::isnan doesn't support __float128.
2761}
2762
2763template <typename T, typename Enable = void>
2764struct has_isfinite : std::false_type {};
2765
2766template <typename T>
2767struct has_isfinite<T, enable_if_t<sizeof(std::isfinite(T())) != 0>>
2768 : std::true_type {};
2769
2770template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value&&
2771 has_isfinite<T>::value)>
2773 constexpr T inf = T(std::numeric_limits<double>::infinity());
2776 return std::isfinite(value);
2777}
2778template <typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)>
2780 T inf = T(std::numeric_limits<double>::infinity());
2781 // std::isfinite doesn't support __float128.
2783}
2784
2785template <typename T, FMT_ENABLE_IF(is_floating_point<T>::value)>
2787 if (is_constant_evaluated()) {
2788#ifdef __cpp_if_constexpr
2789 if constexpr (std::numeric_limits<double>::is_iec559) {
2790 auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
2791 return (bits >> (num_bits<uint64_t>() - 1)) != 0;
2792 }
2793#endif
2794 }
2795 return std::signbit(static_cast<double>(value));
2796}
2797
2798inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) {
2799 // Adjust fixed precision by exponent because it is relative to decimal
2800 // point.
2801 if (exp10 > 0 && precision > max_value<int>() - exp10)
2802 FMT_THROW(format_error("number is too big"));
2803 precision += exp10;
2804}
2805
2806class bigint {
2807 private:
2808 // A bigint is stored as an array of bigits (big digits), with bigit at index
2809 // 0 being the least significant one.
2810 using bigit = uint32_t;
2811 using double_bigit = uint64_t;
2812 enum { bigits_capacity = 32 };
2814 int exp_;
2815
2816 FMT_CONSTEXPR20 bigit operator[](int index) const {
2817 return bigits_[to_unsigned(index)];
2818 }
2819 FMT_CONSTEXPR20 bigit& operator[](int index) {
2820 return bigits_[to_unsigned(index)];
2821 }
2822
2823 static constexpr const int bigit_bits = num_bits<bigit>();
2824
2825 friend struct formatter<bigint>;
2826
2827 FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) {
2828 auto result = static_cast<double_bigit>((*this)[index]) - other - borrow;
2829 (*this)[index] = static_cast<bigit>(result);
2830 borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1));
2831 }
2832
2833 FMT_CONSTEXPR20 void remove_leading_zeros() {
2834 int num_bigits = static_cast<int>(bigits_.size()) - 1;
2835 while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits;
2836 bigits_.resize(to_unsigned(num_bigits + 1));
2837 }
2838
2839 // Computes *this -= other assuming aligned bigints and *this >= other.
2840 FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) {
2841 FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints");
2842 FMT_ASSERT(compare(*this, other) >= 0, "");
2843 bigit borrow = 0;
2844 int i = other.exp_ - exp_;
2845 for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j)
2846 subtract_bigits(i, other.bigits_[j], borrow);
2847 while (borrow > 0) subtract_bigits(i, 0, borrow);
2848 remove_leading_zeros();
2849 }
2850
2851 FMT_CONSTEXPR20 void multiply(uint32_t value) {
2852 const double_bigit wide_value = value;
2853 bigit carry = 0;
2854 for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2855 double_bigit result = bigits_[i] * wide_value + carry;
2856 bigits_[i] = static_cast<bigit>(result);
2857 carry = static_cast<bigit>(result >> bigit_bits);
2858 }
2859 if (carry != 0) bigits_.push_back(carry);
2860 }
2861
2862 template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
2863 std::is_same<UInt, uint128_t>::value)>
2864 FMT_CONSTEXPR20 void multiply(UInt value) {
2865 using half_uint =
2867 const int shift = num_bits<half_uint>() - bigit_bits;
2868 const UInt lower = static_cast<half_uint>(value);
2869 const UInt upper = value >> num_bits<half_uint>();
2870 UInt carry = 0;
2871 for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2872 UInt result = lower * bigits_[i] + static_cast<bigit>(carry);
2873 carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) +
2874 (carry >> bigit_bits);
2875 bigits_[i] = static_cast<bigit>(result);
2876 }
2877 while (carry != 0) {
2878 bigits_.push_back(static_cast<bigit>(carry));
2879 carry >>= bigit_bits;
2880 }
2881 }
2882
2883 template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value ||
2884 std::is_same<UInt, uint128_t>::value)>
2885 FMT_CONSTEXPR20 void assign(UInt n) {
2886 size_t num_bigits = 0;
2887 do {
2888 bigits_[num_bigits++] = static_cast<bigit>(n);
2889 n >>= bigit_bits;
2890 } while (n != 0);
2891 bigits_.resize(num_bigits);
2892 exp_ = 0;
2893 }
2894
2895 public:
2897 explicit bigint(uint64_t n) { assign(n); }
2898
2899 bigint(const bigint&) = delete;
2900 void operator=(const bigint&) = delete;
2901
2902 FMT_CONSTEXPR20 void assign(const bigint& other) {
2903 auto size = other.bigits_.size();
2904 bigits_.resize(size);
2905 auto data = other.bigits_.data();
2906 copy_str<bigit>(data, data + size, bigits_.data());
2907 exp_ = other.exp_;
2908 }
2909
2910 template <typename Int> FMT_CONSTEXPR20 void operator=(Int n) {
2911 FMT_ASSERT(n > 0, "");
2912 assign(uint64_or_128_t<Int>(n));
2913 }
2914
2916 return static_cast<int>(bigits_.size()) + exp_;
2917 }
2918
2920 FMT_ASSERT(shift >= 0, "");
2921 exp_ += shift / bigit_bits;
2922 shift %= bigit_bits;
2923 if (shift == 0) return *this;
2924 bigit carry = 0;
2925 for (size_t i = 0, n = bigits_.size(); i < n; ++i) {
2926 bigit c = bigits_[i] >> (bigit_bits - shift);
2927 bigits_[i] = (bigits_[i] << shift) + carry;
2928 carry = c;
2929 }
2930 if (carry != 0) bigits_.push_back(carry);
2931 return *this;
2932 }
2933
2934 template <typename Int> FMT_CONSTEXPR20 bigint& operator*=(Int value) {
2935 FMT_ASSERT(value > 0, "");
2937 return *this;
2938 }
2939
2940 friend FMT_CONSTEXPR20 int compare(const bigint& lhs, const bigint& rhs) {
2941 int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits();
2942 if (num_lhs_bigits != num_rhs_bigits)
2943 return num_lhs_bigits > num_rhs_bigits ? 1 : -1;
2944 int i = static_cast<int>(lhs.bigits_.size()) - 1;
2945 int j = static_cast<int>(rhs.bigits_.size()) - 1;
2946 int end = i - j;
2947 if (end < 0) end = 0;
2948 for (; i >= end; --i, --j) {
2949 bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j];
2950 if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1;
2951 }
2952 if (i != j) return i > j ? 1 : -1;
2953 return 0;
2954 }
2955
2956 // Returns compare(lhs1 + lhs2, rhs).
2957 friend FMT_CONSTEXPR20 int add_compare(const bigint& lhs1, const bigint& lhs2,
2958 const bigint& rhs) {
2959 auto minimum = [](int a, int b) { return a < b ? a : b; };
2960 auto maximum = [](int a, int b) { return a > b ? a : b; };
2961 int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits());
2962 int num_rhs_bigits = rhs.num_bigits();
2963 if (max_lhs_bigits + 1 < num_rhs_bigits) return -1;
2964 if (max_lhs_bigits > num_rhs_bigits) return 1;
2965 auto get_bigit = [](const bigint& n, int i) -> bigit {
2966 return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0;
2967 };
2968 double_bigit borrow = 0;
2969 int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_);
2970 for (int i = num_rhs_bigits - 1; i >= min_exp; --i) {
2971 double_bigit sum =
2972 static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i);
2973 bigit rhs_bigit = get_bigit(rhs, i);
2974 if (sum > rhs_bigit + borrow) return 1;
2975 borrow = rhs_bigit + borrow - sum;
2976 if (borrow > 1) return -1;
2977 borrow <<= bigit_bits;
2978 }
2979 return borrow != 0 ? -1 : 0;
2980 }
2981
2982 // Assigns pow(10, exp) to this bigint.
2984 FMT_ASSERT(exp >= 0, "");
2985 if (exp == 0) return *this = 1;
2986 // Find the top bit.
2987 int bitmask = 1;
2988 while (exp >= bitmask) bitmask <<= 1;
2989 bitmask >>= 1;
2990 // pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by
2991 // repeated squaring and multiplication.
2992 *this = 5;
2993 bitmask >>= 1;
2994 while (bitmask != 0) {
2995 square();
2996 if ((exp & bitmask) != 0) *this *= 5;
2997 bitmask >>= 1;
2998 }
2999 *this <<= exp; // Multiply by pow(2, exp) by shifting.
3000 }
3001
3003 int num_bigits = static_cast<int>(bigits_.size());
3004 int num_result_bigits = 2 * num_bigits;
3005 basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_));
3006 bigits_.resize(to_unsigned(num_result_bigits));
3007 auto sum = uint128_t();
3008 for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) {
3009 // Compute bigit at position bigit_index of the result by adding
3010 // cross-product terms n[i] * n[j] such that i + j == bigit_index.
3011 for (int i = 0, j = bigit_index; j >= 0; ++i, --j) {
3012 // Most terms are multiplied twice which can be optimized in the future.
3013 sum += static_cast<double_bigit>(n[i]) * n[j];
3014 }
3015 (*this)[bigit_index] = static_cast<bigit>(sum);
3016 sum >>= num_bits<bigit>(); // Compute the carry.
3017 }
3018 // Do the same for the top half.
3019 for (int bigit_index = num_bigits; bigit_index < num_result_bigits;
3020 ++bigit_index) {
3021 for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;)
3022 sum += static_cast<double_bigit>(n[i++]) * n[j--];
3023 (*this)[bigit_index] = static_cast<bigit>(sum);
3024 sum >>= num_bits<bigit>();
3025 }
3026 remove_leading_zeros();
3027 exp_ *= 2;
3028 }
3029
3030 // If this bigint has a bigger exponent than other, adds trailing zero to make
3031 // exponents equal. This simplifies some operations such as subtraction.
3032 FMT_CONSTEXPR20 void align(const bigint& other) {
3033 int exp_difference = exp_ - other.exp_;
3034 if (exp_difference <= 0) return;
3035 int num_bigits = static_cast<int>(bigits_.size());
3036 bigits_.resize(to_unsigned(num_bigits + exp_difference));
3037 for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j)
3038 bigits_[j] = bigits_[i];
3039 std::uninitialized_fill_n(bigits_.data(), exp_difference, 0);
3040 exp_ -= exp_difference;
3041 }
3042
3043 // Divides this bignum by divisor, assigning the remainder to this and
3044 // returning the quotient.
3046 FMT_ASSERT(this != &divisor, "");
3047 if (compare(*this, divisor) < 0) return 0;
3048 FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, "");
3049 align(divisor);
3050 int quotient = 0;
3051 do {
3052 subtract_aligned(divisor);
3053 ++quotient;
3054 } while (compare(*this, divisor) >= 0);
3055 return quotient;
3056 }
3057};
3058
3059// format_dragon flags.
3062 fixup = 2, // Run fixup to correct exp10 which can be off by one.
3064};
3065
3066// Formats a floating-point number using a variation of the Fixed-Precision
3067// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White:
3068// https://fmt.dev/papers/p372-steele.pdf.
3070 unsigned flags, int num_digits,
3071 buffer<char>& buf, int& exp10) {
3072 bigint numerator; // 2 * R in (FPP)^2.
3073 bigint denominator; // 2 * S in (FPP)^2.
3074 // lower and upper are differences between value and corresponding boundaries.
3075 bigint lower; // (M^- in (FPP)^2).
3076 bigint upper_store; // upper's value if different from lower.
3077 bigint* upper = nullptr; // (M^+ in (FPP)^2).
3078 // Shift numerator and denominator by an extra bit or two (if lower boundary
3079 // is closer) to make lower and upper integers. This eliminates multiplication
3080 // by 2 during later computations.
3081 bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0;
3082 int shift = is_predecessor_closer ? 2 : 1;
3083 if (value.e >= 0) {
3084 numerator = value.f;
3085 numerator <<= value.e + shift;
3086 lower = 1;
3087 lower <<= value.e;
3088 if (is_predecessor_closer) {
3089 upper_store = 1;
3090 upper_store <<= value.e + 1;
3091 upper = &upper_store;
3092 }
3093 denominator.assign_pow10(exp10);
3094 denominator <<= shift;
3095 } else if (exp10 < 0) {
3096 numerator.assign_pow10(-exp10);
3097 lower.assign(numerator);
3098 if (is_predecessor_closer) {
3099 upper_store.assign(numerator);
3100 upper_store <<= 1;
3101 upper = &upper_store;
3102 }
3103 numerator *= value.f;
3104 numerator <<= shift;
3105 denominator = 1;
3106 denominator <<= shift - value.e;
3107 } else {
3108 numerator = value.f;
3109 numerator <<= shift;
3110 denominator.assign_pow10(exp10);
3111 denominator <<= shift - value.e;
3112 lower = 1;
3113 if (is_predecessor_closer) {
3114 upper_store = 1ULL << 1;
3115 upper = &upper_store;
3116 }
3117 }
3118 int even = static_cast<int>((value.f & 1) == 0);
3119 if (!upper) upper = &lower;
3120 bool shortest = num_digits < 0;
3121 if ((flags & dragon::fixup) != 0) {
3122 if (add_compare(numerator, *upper, denominator) + even <= 0) {
3123 --exp10;
3124 numerator *= 10;
3125 if (num_digits < 0) {
3126 lower *= 10;
3127 if (upper != &lower) *upper *= 10;
3128 }
3129 }
3130 if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1);
3131 }
3132 // Invariant: value == (numerator / denominator) * pow(10, exp10).
3133 if (shortest) {
3134 // Generate the shortest representation.
3135 num_digits = 0;
3136 char* data = buf.data();
3137 for (;;) {
3138 int digit = numerator.divmod_assign(denominator);
3139 bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower.
3140 // numerator + upper >[=] pow10:
3141 bool high = add_compare(numerator, *upper, denominator) + even > 0;
3142 data[num_digits++] = static_cast<char>('0' + digit);
3143 if (low || high) {
3144 if (!low) {
3145 ++data[num_digits - 1];
3146 } else if (high) {
3147 int result = add_compare(numerator, numerator, denominator);
3148 // Round half to even.
3149 if (result > 0 || (result == 0 && (digit % 2) != 0))
3150 ++data[num_digits - 1];
3151 }
3152 buf.try_resize(to_unsigned(num_digits));
3153 exp10 -= num_digits - 1;
3154 return;
3155 }
3156 numerator *= 10;
3157 lower *= 10;
3158 if (upper != &lower) *upper *= 10;
3159 }
3160 }
3161 // Generate the given number of digits.
3162 exp10 -= num_digits - 1;
3163 if (num_digits <= 0) {
3164 denominator *= 10;
3165 auto digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0';
3166 buf.push_back(digit);
3167 return;
3168 }
3169 buf.try_resize(to_unsigned(num_digits));
3170 for (int i = 0; i < num_digits - 1; ++i) {
3171 int digit = numerator.divmod_assign(denominator);
3172 buf[i] = static_cast<char>('0' + digit);
3173 numerator *= 10;
3174 }
3175 int digit = numerator.divmod_assign(denominator);
3176 auto result = add_compare(numerator, numerator, denominator);
3177 if (result > 0 || (result == 0 && (digit % 2) != 0)) {
3178 if (digit == 9) {
3179 const auto overflow = '0' + 10;
3180 buf[num_digits - 1] = overflow;
3181 // Propagate the carry.
3182 for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) {
3183 buf[i] = '0';
3184 ++buf[i - 1];
3185 }
3186 if (buf[0] == overflow) {
3187 buf[0] = '1';
3188 if ((flags & dragon::fixed) != 0) buf.push_back('0');
3189 else ++exp10;
3190 }
3191 return;
3192 }
3193 ++digit;
3194 }
3195 buf[num_digits - 1] = static_cast<char>('0' + digit);
3196}
3197
3198// Formats a floating-point number using the hexfloat format.
3199template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)>
3200FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision,
3201 float_specs specs, buffer<char>& buf) {
3202 // float is passed as double to reduce the number of instantiations and to
3203 // simplify implementation.
3204 static_assert(!std::is_same<Float, float>::value, "");
3205
3206 using info = dragonbox::float_info<Float>;
3207
3208 // Assume Float is in the format [sign][exponent][significand].
3209 using carrier_uint = typename info::carrier_uint;
3210
3211 constexpr auto num_float_significand_bits =
3212 detail::num_significand_bits<Float>();
3213
3215 f.e += num_float_significand_bits;
3216 if (!has_implicit_bit<Float>()) --f.e;
3217
3218 constexpr auto num_fraction_bits =
3219 num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0);
3220 constexpr auto num_xdigits = (num_fraction_bits + 3) / 4;
3221
3222 constexpr auto leading_shift = ((num_xdigits - 1) * 4);
3223 const auto leading_mask = carrier_uint(0xF) << leading_shift;
3224 const auto leading_xdigit =
3225 static_cast<uint32_t>((f.f & leading_mask) >> leading_shift);
3226 if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1);
3227
3228 int print_xdigits = num_xdigits - 1;
3229 if (precision >= 0 && print_xdigits > precision) {
3230 const int shift = ((print_xdigits - precision - 1) * 4);
3231 const auto mask = carrier_uint(0xF) << shift;
3232 const auto v = static_cast<uint32_t>((f.f & mask) >> shift);
3233
3234 if (v >= 8) {
3235 const auto inc = carrier_uint(1) << (shift + 4);
3236 f.f += inc;
3237 f.f &= ~(inc - 1);
3238 }
3239
3240 // Check long double overflow
3241 if (!has_implicit_bit<Float>()) {
3242 const auto implicit_bit = carrier_uint(1) << num_float_significand_bits;
3243 if ((f.f & implicit_bit) == implicit_bit) {
3244 f.f >>= 4;
3245 f.e += 4;
3246 }
3247 }
3248
3249 print_xdigits = precision;
3250 }
3251
3252 char xdigits[num_bits<carrier_uint>() / 4];
3253 detail::fill_n(xdigits, sizeof(xdigits), '0');
3254 format_uint<4>(xdigits, f.f, num_xdigits, specs.upper);
3255
3256 // Remove zero tail
3257 while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits;
3258
3259 buf.push_back('0');
3260 buf.push_back(specs.upper ? 'X' : 'x');
3261 buf.push_back(xdigits[0]);
3262 if (specs.showpoint || print_xdigits > 0 || print_xdigits < precision)
3263 buf.push_back('.');
3264 buf.append(xdigits + 1, xdigits + 1 + print_xdigits);
3265 for (; print_xdigits < precision; ++print_xdigits) buf.push_back('0');
3266
3267 buf.push_back(specs.upper ? 'P' : 'p');
3268
3269 uint32_t abs_e;
3270 if (f.e < 0) {
3271 buf.push_back('-');
3272 abs_e = static_cast<uint32_t>(-f.e);
3273 } else {
3274 buf.push_back('+');
3275 abs_e = static_cast<uint32_t>(f.e);
3276 }
3277 format_decimal<char>(appender(buf), abs_e, detail::count_digits(abs_e));
3278}
3279
3280template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)>
3281FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision,
3282 float_specs specs, buffer<char>& buf) {
3283 format_hexfloat(static_cast<double>(value), precision, specs, buf);
3284}
3285
3286template <typename Float>
3287FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs,
3288 buffer<char>& buf) -> int {
3289 // float is passed as double to reduce the number of instantiations.
3290 static_assert(!std::is_same<Float, float>::value, "");
3291 FMT_ASSERT(value >= 0, "value is negative");
3292 auto converted_value = convert_float(value);
3293
3294 const bool fixed = specs.format == float_format::fixed;
3295 if (value <= 0) { // <= instead of == to silence a warning.
3296 if (precision <= 0 || !fixed) {
3297 buf.push_back('0');
3298 return 0;
3299 }
3300 buf.try_resize(to_unsigned(precision));
3301 fill_n(buf.data(), precision, '0');
3302 return -precision;
3303 }
3304
3305 int exp = 0;
3306 bool use_dragon = true;
3307 unsigned dragon_flags = 0;
3308 if (!is_fast_float<Float>() || is_constant_evaluated()) {
3309 const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10)
3310 using info = dragonbox::float_info<decltype(converted_value)>;
3311 const auto f = basic_fp<typename info::carrier_uint>(converted_value);
3312 // Compute exp, an approximate power of 10, such that
3313 // 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1).
3314 // This is based on log10(value) == log2(value) / log2(10) and approximation
3315 // of log2(value) by e + num_fraction_bits idea from double-conversion.
3316 auto e = (f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10;
3317 exp = static_cast<int>(e);
3318 if (e > exp) ++exp; // Compute ceil.
3319 dragon_flags = dragon::fixup;
3320 } else if (precision < 0) {
3321 // Use Dragonbox for the shortest format.
3322 if (specs.binary32) {
3323 auto dec = dragonbox::to_decimal(static_cast<float>(value));
3324 write<char>(buffer_appender<char>(buf), dec.significand);
3325 return dec.exponent;
3326 }
3327 auto dec = dragonbox::to_decimal(static_cast<double>(value));
3328 write<char>(buffer_appender<char>(buf), dec.significand);
3329 return dec.exponent;
3330 } else {
3331 // Extract significand bits and exponent bits.
3332 using info = dragonbox::float_info<double>;
3333 auto br = bit_cast<uint64_t>(static_cast<double>(value));
3334
3335 const uint64_t significand_mask =
3336 (static_cast<uint64_t>(1) << num_significand_bits<double>()) - 1;
3337 uint64_t significand = (br & significand_mask);
3338 int exponent = static_cast<int>((br & exponent_mask<double>()) >>
3339 num_significand_bits<double>());
3340
3341 if (exponent != 0) { // Check if normal.
3342 exponent -= exponent_bias<double>() + num_significand_bits<double>();
3343 significand |=
3344 (static_cast<uint64_t>(1) << num_significand_bits<double>());
3345 significand <<= 1;
3346 } else {
3347 // Normalize subnormal inputs.
3348 FMT_ASSERT(significand != 0, "zeros should not appear here");
3349 int shift = countl_zero(significand);
3350 FMT_ASSERT(shift >= num_bits<uint64_t>() - num_significand_bits<double>(),
3351 "");
3352 shift -= (num_bits<uint64_t>() - num_significand_bits<double>() - 2);
3353 exponent = (std::numeric_limits<double>::min_exponent -
3354 num_significand_bits<double>()) -
3355 shift;
3356 significand <<= shift;
3357 }
3358
3359 // Compute the first several nonzero decimal significand digits.
3360 // We call the number we get the first segment.
3361 const int k = info::kappa - dragonbox::floor_log10_pow2(exponent);
3362 exp = -k;
3363 const int beta = exponent + dragonbox::floor_log2_pow10(k);
3364 uint64_t first_segment;
3365 bool has_more_segments;
3366 int digits_in_the_first_segment;
3367 {
3368 const auto r = dragonbox::umul192_upper128(
3369 significand << beta, dragonbox::get_cached_power(k));
3370 first_segment = r.high();
3371 has_more_segments = r.low() != 0;
3372
3373 // The first segment can have 18 ~ 19 digits.
3374 if (first_segment >= 1000000000000000000ULL) {
3375 digits_in_the_first_segment = 19;
3376 } else {
3377 // When it is of 18-digits, we align it to 19-digits by adding a bogus
3378 // zero at the end.
3379 digits_in_the_first_segment = 18;
3380 first_segment *= 10;
3381 }
3382 }
3383
3384 // Compute the actual number of decimal digits to print.
3385 if (fixed) adjust_precision(precision, exp + digits_in_the_first_segment);
3386
3387 // Use Dragon4 only when there might be not enough digits in the first
3388 // segment.
3389 if (digits_in_the_first_segment > precision) {
3390 use_dragon = false;
3391
3392 if (precision <= 0) {
3393 exp += digits_in_the_first_segment;
3394
3395 if (precision < 0) {
3396 // Nothing to do, since all we have are just leading zeros.
3397 buf.try_resize(0);
3398 } else {
3399 // We may need to round-up.
3400 buf.try_resize(1);
3401 if ((first_segment | static_cast<uint64_t>(has_more_segments)) >
3402 5000000000000000000ULL) {
3403 buf[0] = '1';
3404 } else {
3405 buf[0] = '0';
3406 }
3407 }
3408 } // precision <= 0
3409 else {
3410 exp += digits_in_the_first_segment - precision;
3411
3412 // When precision > 0, we divide the first segment into three
3413 // subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits
3414 // in 32-bits which usually allows faster calculation than in
3415 // 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize
3416 // division-by-constant for large 64-bit divisors, we do it here
3417 // manually. The magic number 7922816251426433760 below is equal to
3418 // ceil(2^(64+32) / 10^10).
3419 const uint32_t first_subsegment = static_cast<uint32_t>(
3420 dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >>
3421 32);
3422 const uint64_t second_third_subsegments =
3423 first_segment - first_subsegment * 10000000000ULL;
3424
3425 uint64_t prod;
3426 uint32_t digits;
3427 bool should_round_up;
3428 int number_of_digits_to_print = precision > 9 ? 9 : precision;
3429
3430 // Print a 9-digits subsegment, either the first or the second.
3431 auto print_subsegment = [&](uint32_t subsegment, char* buffer) {
3432 int number_of_digits_printed = 0;
3433
3434 // If we want to print an odd number of digits from the subsegment,
3435 if ((number_of_digits_to_print & 1) != 0) {
3436 // Convert to 64-bit fixed-point fractional form with 1-digit
3437 // integer part. The magic number 720575941 is a good enough
3438 // approximation of 2^(32 + 24) / 10^8; see
3439 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3440 // for details.
3441 prod = ((subsegment * static_cast<uint64_t>(720575941)) >> 24) + 1;
3442 digits = static_cast<uint32_t>(prod >> 32);
3443 *buffer = static_cast<char>('0' + digits);
3444 number_of_digits_printed++;
3445 }
3446 // If we want to print an even number of digits from the
3447 // first_subsegment,
3448 else {
3449 // Convert to 64-bit fixed-point fractional form with 2-digits
3450 // integer part. The magic number 450359963 is a good enough
3451 // approximation of 2^(32 + 20) / 10^7; see
3452 // https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case
3453 // for details.
3454 prod = ((subsegment * static_cast<uint64_t>(450359963)) >> 20) + 1;
3455 digits = static_cast<uint32_t>(prod >> 32);
3456 copy2(buffer, digits2(digits));
3457 number_of_digits_printed += 2;
3458 }
3459
3460 // Print all digit pairs.
3461 while (number_of_digits_printed < number_of_digits_to_print) {
3462 prod = static_cast<uint32_t>(prod) * static_cast<uint64_t>(100);
3463 digits = static_cast<uint32_t>(prod >> 32);
3464 copy2(buffer + number_of_digits_printed, digits2(digits));
3465 number_of_digits_printed += 2;
3466 }
3467 };
3468
3469 // Print first subsegment.
3470 print_subsegment(first_subsegment, buf.data());
3471
3472 // Perform rounding if the first subsegment is the last subsegment to
3473 // print.
3474 if (precision <= 9) {
3475 // Rounding inside the subsegment.
3476 // We round-up if:
3477 // - either the fractional part is strictly larger than 1/2, or
3478 // - the fractional part is exactly 1/2 and the last digit is odd.
3479 // We rely on the following observations:
3480 // - If fractional_part >= threshold, then the fractional part is
3481 // strictly larger than 1/2.
3482 // - If the MSB of fractional_part is set, then the fractional part
3483 // must be at least 1/2.
3484 // - When the MSB of fractional_part is set, either
3485 // second_third_subsegments being nonzero or has_more_segments
3486 // being true means there are further digits not printed, so the
3487 // fractional part is strictly larger than 1/2.
3488 if (precision < 9) {
3489 uint32_t fractional_part = static_cast<uint32_t>(prod);
3490 should_round_up = fractional_part >=
3492 [8 - number_of_digits_to_print] ||
3493 ((fractional_part >> 31) &
3494 ((digits & 1) | (second_third_subsegments != 0) |
3495 has_more_segments)) != 0;
3496 }
3497 // Rounding at the subsegment boundary.
3498 // In this case, the fractional part is at least 1/2 if and only if
3499 // second_third_subsegments >= 5000000000ULL, and is strictly larger
3500 // than 1/2 if we further have either second_third_subsegments >
3501 // 5000000000ULL or has_more_segments == true.
3502 else {
3503 should_round_up = second_third_subsegments > 5000000000ULL ||
3504 (second_third_subsegments == 5000000000ULL &&
3505 ((digits & 1) != 0 || has_more_segments));
3506 }
3507 }
3508 // Otherwise, print the second subsegment.
3509 else {
3510 // Compilers are not aware of how to leverage the maximum value of
3511 // second_third_subsegments to find out a better magic number which
3512 // allows us to eliminate an additional shift. 1844674407370955162 =
3513 // ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))).
3514 const uint32_t second_subsegment =
3515 static_cast<uint32_t>(dragonbox::umul128_upper64(
3516 second_third_subsegments, 1844674407370955162ULL));
3517 const uint32_t third_subsegment =
3518 static_cast<uint32_t>(second_third_subsegments) -
3519 second_subsegment * 10;
3520
3521 number_of_digits_to_print = precision - 9;
3522 print_subsegment(second_subsegment, buf.data() + 9);
3523
3524 // Rounding inside the subsegment.
3525 if (precision < 18) {
3526 // The condition third_subsegment != 0 implies that the segment was
3527 // of 19 digits, so in this case the third segment should be
3528 // consisting of a genuine digit from the input.
3529 uint32_t fractional_part = static_cast<uint32_t>(prod);
3530 should_round_up = fractional_part >=
3532 [8 - number_of_digits_to_print] ||
3533 ((fractional_part >> 31) &
3534 ((digits & 1) | (third_subsegment != 0) |
3535 has_more_segments)) != 0;
3536 }
3537 // Rounding at the subsegment boundary.
3538 else {
3539 // In this case, the segment must be of 19 digits, thus
3540 // the third subsegment should be consisting of a genuine digit from
3541 // the input.
3542 should_round_up = third_subsegment > 5 ||
3543 (third_subsegment == 5 &&
3544 ((digits & 1) != 0 || has_more_segments));
3545 }
3546 }
3547
3548 // Round-up if necessary.
3549 if (should_round_up) {
3550 ++buf[precision - 1];
3551 for (int i = precision - 1; i > 0 && buf[i] > '9'; --i) {
3552 buf[i] = '0';
3553 ++buf[i - 1];
3554 }
3555 if (buf[0] > '9') {
3556 buf[0] = '1';
3557 if (fixed)
3558 buf[precision++] = '0';
3559 else
3560 ++exp;
3561 }
3562 }
3563 buf.try_resize(to_unsigned(precision));
3564 }
3565 } // if (digits_in_the_first_segment > precision)
3566 else {
3567 // Adjust the exponent for its use in Dragon4.
3568 exp += digits_in_the_first_segment - 1;
3569 }
3570 }
3571 if (use_dragon) {
3572 auto f = basic_fp<uint128_t>();
3573 bool is_predecessor_closer = specs.binary32
3574 ? f.assign(static_cast<float>(value))
3575 : f.assign(converted_value);
3576 if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer;
3577 if (fixed) dragon_flags |= dragon::fixed;
3578 // Limit precision to the maximum possible number of significant digits in
3579 // an IEEE754 double because we don't need to generate zeros.
3580 const int max_double_digits = 767;
3581 if (precision > max_double_digits) precision = max_double_digits;
3582 format_dragon(f, dragon_flags, precision, buf, exp);
3583 }
3584 if (!fixed && !specs.showpoint) {
3585 // Remove trailing zeros.
3586 auto num_digits = buf.size();
3587 while (num_digits > 0 && buf[num_digits - 1] == '0') {
3588 --num_digits;
3589 ++exp;
3590 }
3591 buf.try_resize(num_digits);
3592 }
3593 return exp;
3594}
3595template <typename Char, typename OutputIt, typename T>
3596FMT_CONSTEXPR20 auto write_float(OutputIt out, T value,
3597 format_specs<Char> specs, locale_ref loc)
3598 -> OutputIt {
3599 float_specs fspecs = parse_float_type_spec(specs);
3600 fspecs.sign = specs.sign;
3601 if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit.
3602 fspecs.sign = sign::minus;
3603 value = -value;
3604 } else if (fspecs.sign == sign::minus) {
3605 fspecs.sign = sign::none;
3606 }
3607
3608 if (!detail::isfinite(value))
3609 return write_nonfinite(out, detail::isnan(value), specs, fspecs);
3610
3611 if (specs.align == align::numeric && fspecs.sign) {
3612 auto it = reserve(out, 1);
3613 *it++ = detail::sign<Char>(fspecs.sign);
3614 out = base_iterator(out, it);
3615 fspecs.sign = sign::none;
3616 if (specs.width != 0) --specs.width;
3617 }
3618
3620 if (fspecs.format == float_format::hex) {
3621 if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign));
3622 format_hexfloat(convert_float(value), specs.precision, fspecs, buffer);
3623 return write_bytes<align::right>(out, {buffer.data(), buffer.size()},
3624 specs);
3625 }
3626 int precision = specs.precision >= 0 || specs.type == presentation_type::none
3627 ? specs.precision
3628 : 6;
3629 if (fspecs.format == float_format::exp) {
3630 if (precision == max_value<int>())
3631 throw_format_error("number is too big");
3632 else
3633 ++precision;
3634 } else if (fspecs.format != float_format::fixed && precision == 0) {
3635 precision = 1;
3636 }
3637 if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
3639 fspecs.precision = precision;
3640 auto f = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
3641 return write_float(out, f, specs, fspecs, loc);
3642}
3643
3644template <typename Char, typename OutputIt, typename T,
3645 FMT_ENABLE_IF(is_floating_point<T>::value)>
3646FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs<Char> specs,
3647 locale_ref loc = {}) -> OutputIt {
3648 if (const_check(!is_supported_floating_point(value))) return out;
3649 return specs.localized && write_loc(out, value, specs, loc)
3650 ? out
3651 : write_float(out, value, specs, loc);
3652}
3653
3654template <typename Char, typename OutputIt, typename T,
3655 FMT_ENABLE_IF(is_fast_float<T>::value)>
3656FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
3657 if (is_constant_evaluated()) return write(out, value, format_specs<Char>());
3659
3660 auto fspecs = float_specs();
3661 if (detail::signbit(value)) {
3662 fspecs.sign = sign::minus;
3663 value = -value;
3664 }
3665
3666 constexpr auto specs = format_specs<Char>();
3667 using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
3668 using floaty_uint = typename dragonbox::float_info<floaty>::carrier_uint;
3669 floaty_uint mask = exponent_mask<floaty>();
3670 if ((bit_cast<floaty_uint>(value) & mask) == mask)
3671 return write_nonfinite(out, std::isnan(value), specs, fspecs);
3672
3673 auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
3674 return write_float(out, dec, specs, fspecs, {});
3675}
3676
3677template <typename Char, typename OutputIt, typename T,
3678 FMT_ENABLE_IF(is_floating_point<T>::value &&
3679 !is_fast_float<T>::value)>
3680inline auto write(OutputIt out, T value) -> OutputIt {
3681 return write(out, value, format_specs<Char>());
3682}
3683
3684template <typename Char, typename OutputIt>
3685auto write(OutputIt out, monostate, format_specs<Char> = {}, locale_ref = {})
3686 -> OutputIt {
3687 FMT_ASSERT(false, "");
3688 return out;
3689}
3690
3691template <typename Char, typename OutputIt>
3693 -> OutputIt {
3694 auto it = reserve(out, value.size());
3695 it = copy_str_noinline<Char>(value.begin(), value.end(), it);
3696 return base_iterator(out, it);
3697}
3698
3699template <typename Char, typename OutputIt, typename T,
3700 FMT_ENABLE_IF(is_string<T>::value)>
3701constexpr auto write(OutputIt out, const T& value) -> OutputIt {
3702 return write<Char>(out, to_string_view(value));
3703}
3704
3705// FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
3706template <
3707 typename Char, typename OutputIt, typename T,
3708 bool check =
3709 std::is_enum<T>::value && !std::is_same<T, Char>::value &&
3710 mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value !=
3712 FMT_ENABLE_IF(check)>
3713FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
3714 return write<Char>(out, static_cast<underlying_t<T>>(value));
3715}
3716
3717template <typename Char, typename OutputIt, typename T,
3718 FMT_ENABLE_IF(std::is_same<T, bool>::value)>
3719FMT_CONSTEXPR auto write(OutputIt out, T value,
3720 const format_specs<Char>& specs = {}, locale_ref = {})
3721 -> OutputIt {
3722 return specs.type != presentation_type::none &&
3724 ? write(out, value ? 1 : 0, specs, {})
3725 : write_bytes(out, value ? "true" : "false", specs);
3726}
3727
3728template <typename Char, typename OutputIt>
3729FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
3730 auto it = reserve(out, 1);
3731 *it++ = value;
3732 return base_iterator(out, it);
3733}
3734
3735template <typename Char, typename OutputIt>
3736FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value)
3737 -> OutputIt {
3738 if (value) return write(out, basic_string_view<Char>(value));
3739 throw_format_error("string pointer is null");
3740 return out;
3741}
3742
3743template <typename Char, typename OutputIt, typename T,
3744 FMT_ENABLE_IF(std::is_same<T, void>::value)>
3745auto write(OutputIt out, const T* value, const format_specs<Char>& specs = {},
3746 locale_ref = {}) -> OutputIt {
3747 return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs);
3748}
3749
3750// A write overload that handles implicit conversions.
3751template <typename Char, typename OutputIt, typename T,
3752 typename Context = basic_format_context<OutputIt, Char>>
3753FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<
3754 std::is_class<T>::value && !is_string<T>::value &&
3755 !is_floating_point<T>::value && !std::is_same<T, Char>::value &&
3756 !std::is_same<T, remove_cvref_t<decltype(arg_mapper<Context>().map(
3757 value))>>::value,
3758 OutputIt> {
3759 return write<Char>(out, arg_mapper<Context>().map(value));
3760}
3761
3762template <typename Char, typename OutputIt, typename T,
3763 typename Context = basic_format_context<OutputIt, Char>>
3764FMT_CONSTEXPR auto write(OutputIt out, const T& value)
3766 OutputIt> {
3767 auto ctx = Context(out, {}, {});
3768 return typename Context::template formatter_type<T>().format(value, ctx);
3769}
3770
3771// An argument visitor that formats the argument and writes it via the output
3772// iterator. It's a class and not a generic lambda for compatibility with C++11.
3773template <typename Char> struct default_arg_formatter {
3776
3780
3781 template <typename T> auto operator()(T value) -> iterator {
3782 return write<Char>(out, value);
3783 }
3786 context format_ctx(out, args, loc);
3787 h.format(parse_ctx, format_ctx);
3788 return format_ctx.out();
3789 }
3790};
3791
3792template <typename Char> struct arg_formatter {
3795
3799
3800 template <typename T>
3802 return detail::write(out, value, specs, locale);
3803 }
3805 // User-defined types are handled separately because they require access
3806 // to the parse context.
3807 return out;
3808 }
3809};
3810
3811template <typename Char> struct custom_formatter {
3814
3816 typename basic_format_arg<buffer_context<Char>>::handle h) const {
3817 h.format(parse_ctx, ctx);
3818 }
3819 template <typename T> void operator()(T) const {}
3820};
3821
3822template <typename ErrorHandler> class width_checker {
3823 public:
3824 explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {}
3825
3826 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
3827 FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
3828 if (is_negative(value)) handler_.on_error("negative width");
3829 return static_cast<unsigned long long>(value);
3830 }
3831
3832 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
3833 FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
3834 handler_.on_error("width is not integer");
3835 return 0;
3836 }
3837
3838 private:
3839 ErrorHandler& handler_;
3840};
3841
3842template <typename ErrorHandler> class precision_checker {
3843 public:
3844 explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {}
3845
3846 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
3847 FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
3848 if (is_negative(value)) handler_.on_error("negative precision");
3849 return static_cast<unsigned long long>(value);
3850 }
3851
3852 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
3853 FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
3854 handler_.on_error("precision is not integer");
3855 return 0;
3856 }
3857
3858 private:
3859 ErrorHandler& handler_;
3860};
3861
3862template <template <typename> class Handler, typename FormatArg,
3863 typename ErrorHandler>
3864FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int {
3865 unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
3866 if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big");
3867 return static_cast<int>(value);
3868}
3869
3870template <typename Context, typename ID>
3871FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> decltype(ctx.arg(id)) {
3872 auto arg = ctx.arg(id);
3873 if (!arg) ctx.on_error("argument not found");
3874 return arg;
3875}
3876
3877template <template <typename> class Handler, typename Context>
3880 Context& ctx) {
3881 switch (ref.kind) {
3882 case arg_id_kind::none:
3883 break;
3884 case arg_id_kind::index:
3885 value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.index),
3886 ctx.error_handler());
3887 break;
3888 case arg_id_kind::name:
3889 value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.name),
3890 ctx.error_handler());
3891 break;
3892 }
3893}
3894
3895#if FMT_USE_USER_DEFINED_LITERALS
3896# if FMT_USE_NONTYPE_TEMPLATE_ARGS
3897template <typename T, typename Char, size_t N,
3898 fmt::detail_exported::fixed_string<Char, N> Str>
3899struct statically_named_arg : view {
3900 static constexpr auto name = Str.data;
3901
3902 const T& value;
3903 statically_named_arg(const T& v) : value(v) {}
3904};
3905
3906template <typename T, typename Char, size_t N,
3907 fmt::detail_exported::fixed_string<Char, N> Str>
3908struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
3909
3910template <typename T, typename Char, size_t N,
3911 fmt::detail_exported::fixed_string<Char, N> Str>
3912struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
3913 : std::true_type {};
3914
3915template <typename Char, size_t N,
3916 fmt::detail_exported::fixed_string<Char, N> Str>
3917struct udl_arg {
3918 template <typename T> auto operator=(T&& value) const {
3919 return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
3920 }
3921};
3922# else
3923template <typename Char> struct udl_arg {
3924 const Char* str;
3925
3926 template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
3927 return {str, std::forward<T>(value)};
3928 }
3929};
3930# endif
3931#endif // FMT_USE_USER_DEFINED_LITERALS
3932
3933template <typename Locale, typename Char>
3934auto vformat(const Locale& loc, basic_string_view<Char> fmt,
3936 -> std::basic_string<Char> {
3937 auto buf = basic_memory_buffer<Char>();
3938 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
3939 return {buf.data(), buf.size()};
3940}
3941
3942using format_func = void (*)(detail::buffer<char>&, int, const char*);
3943
3944FMT_API void format_error_code(buffer<char>& out, int error_code,
3945 string_view message) noexcept;
3946
3947FMT_API void report_error(format_func func, int error_code,
3948 const char* message) noexcept;
3949} // namespace detail
3950
3951FMT_API auto vsystem_error(int error_code, string_view format_str,
3953
3954/**
3955 \rst
3956 Constructs :class:`std::system_error` with a message formatted with
3957 ``fmt::format(fmt, args...)``.
3958 *error_code* is a system error code as given by ``errno``.
3959
3960 **Example**::
3961
3962 // This throws std::system_error with the description
3963 // cannot open file 'madeup': No such file or directory
3964 // or similar (system message may vary).
3965 const char* filename = "madeup";
3966 std::FILE* file = std::fopen(filename, "r");
3967 if (!file)
3968 throw fmt::system_error(errno, "cannot open file '{}'", filename);
3969 \endrst
3970 */
3971template <typename... T>
3972auto system_error(int error_code, format_string<T...> fmt, T&&... args)
3974 return vsystem_error(error_code, fmt, fmt::make_format_args(args...));
3975}
3976
3977/**
3978 \rst
3979 Formats an error message for an error returned by an operating system or a
3980 language runtime, for example a file opening error, and writes it to *out*.
3981 The format is the same as the one used by ``std::system_error(ec, message)``
3982 where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.
3983 It is implementation-defined but normally looks like:
3984
3985 .. parsed-literal::
3986 *<message>*: *<system-message>*
3987
3988 where *<message>* is the passed message and *<system-message>* is the system
3989 message corresponding to the error code.
3990 *error_code* is a system error code as given by ``errno``.
3991 \endrst
3992 */
3993FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
3994 const char* message) noexcept;
3995
3996// Reports a system error without throwing an exception.
3997// Can be used to report errors from destructors.
3998FMT_API void report_system_error(int error_code, const char* message) noexcept;
3999
4000/** Fast integer formatter. */
4002 private:
4003 // Buffer should be large enough to hold all digits (digits10 + 1),
4004 // a sign and a null character.
4005 enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
4006 mutable char buffer_[buffer_size];
4007 char* str_;
4008
4009 template <typename UInt> auto format_unsigned(UInt value) -> char* {
4010 auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
4011 return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
4012 }
4013
4014 template <typename Int> auto format_signed(Int value) -> char* {
4015 auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
4016 bool negative = value < 0;
4017 if (negative) abs_value = 0 - abs_value;
4018 auto begin = format_unsigned(abs_value);
4019 if (negative) *--begin = '-';
4020 return begin;
4021 }
4022
4023 public:
4024 explicit format_int(int value) : str_(format_signed(value)) {}
4025 explicit format_int(long value) : str_(format_signed(value)) {}
4026 explicit format_int(long long value) : str_(format_signed(value)) {}
4027 explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
4028 explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
4029 explicit format_int(unsigned long long value)
4030 : str_(format_unsigned(value)) {}
4031
4032 /** Returns the number of characters written to the output buffer. */
4033 auto size() const -> size_t {
4034 return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
4035 }
4036
4037 /**
4038 Returns a pointer to the output buffer content. No terminating null
4039 character is appended.
4040 */
4041 auto data() const -> const char* { return str_; }
4042
4043 /**
4044 Returns a pointer to the output buffer content with terminating null
4045 character appended.
4046 */
4047 auto c_str() const -> const char* {
4048 buffer_[buffer_size - 1] = '\0';
4049 return str_;
4050 }
4051
4052 /**
4053 \rst
4054 Returns the content of the output buffer as an ``std::string``.
4055 \endrst
4056 */
4057 auto str() const -> std::string { return std::string(str_, size()); }
4058};
4059
4060template <typename T, typename Char>
4061struct formatter<T, Char, enable_if_t<detail::has_format_as<T>::value>>
4062 : private formatter<detail::format_as_t<T>, Char> {
4064 using base::parse;
4065
4066 template <typename FormatContext>
4067 auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) {
4068 return base::format(format_as(value), ctx);
4069 }
4070};
4071
4072#define FMT_FORMAT_AS(Type, Base) \
4073 template <typename Char> \
4074 struct formatter<Type, Char> : formatter<Base, Char> {}
4075
4076FMT_FORMAT_AS(signed char, int);
4077FMT_FORMAT_AS(unsigned char, unsigned);
4078FMT_FORMAT_AS(short, int);
4079FMT_FORMAT_AS(unsigned short, unsigned);
4082FMT_FORMAT_AS(Char*, const Char*);
4083FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
4084FMT_FORMAT_AS(std::nullptr_t, const void*);
4086FMT_FORMAT_AS(void*, const void*);
4087
4088template <typename Char, size_t N>
4089struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {};
4090
4091/**
4092 \rst
4093 Converts ``p`` to ``const void*`` for pointer formatting.
4094
4095 **Example**::
4096
4097 auto s = fmt::format("{}", fmt::ptr(p));
4098 \endrst
4099 */
4100template <typename T> auto ptr(T p) -> const void* {
4101 static_assert(std::is_pointer<T>::value, "");
4102 return detail::bit_cast<const void*>(p);
4103}
4104template <typename T, typename Deleter>
4105auto ptr(const std::unique_ptr<T, Deleter>& p) -> const void* {
4106 return p.get();
4107}
4108template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
4109 return p.get();
4110}
4111
4112/**
4113 \rst
4114 Converts ``e`` to the underlying type.
4115
4116 **Example**::
4117
4118 enum class color { red, green, blue };
4119 auto s = fmt::format("{}", fmt::underlying(color::red));
4120 \endrst
4121 */
4122template <typename Enum>
4123constexpr auto underlying(Enum e) noexcept -> underlying_t<Enum> {
4124 return static_cast<underlying_t<Enum>>(e);
4125}
4126
4127namespace enums {
4128template <typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)>
4129constexpr auto format_as(Enum e) noexcept -> underlying_t<Enum> {
4130 return static_cast<underlying_t<Enum>>(e);
4131}
4132} // namespace enums
4133
4134class bytes {
4135 private:
4137 friend struct formatter<bytes>;
4138
4139 public:
4140 explicit bytes(string_view data) : data_(data) {}
4141};
4142
4143template <> struct formatter<bytes> {
4144 private:
4146
4147 public:
4148 template <typename ParseContext>
4149 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* {
4150 return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4152 }
4153
4154 template <typename FormatContext>
4155 auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
4156 detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
4157 specs_.width_ref, ctx);
4158 detail::handle_dynamic_spec<detail::precision_checker>(
4159 specs_.precision, specs_.precision_ref, ctx);
4160 return detail::write_bytes(ctx.out(), b.data_, specs_);
4161 }
4162};
4163
4164// group_digits_view is not derived from view because it copies the argument.
4165template <typename T> struct group_digits_view {
4167};
4168
4169/**
4170 \rst
4171 Returns a view that formats an integer value using ',' as a locale-independent
4172 thousands separator.
4173
4174 **Example**::
4175
4176 fmt::print("{}", fmt::group_digits(12345));
4177 // Output: "12,345"
4178 \endrst
4179 */
4180template <typename T> auto group_digits(T value) -> group_digits_view<T> {
4181 return {value};
4182}
4183
4184template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
4185 private:
4187
4188 public:
4189 template <typename ParseContext>
4190 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* {
4191 return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx,
4193 }
4194
4195 template <typename FormatContext>
4196 auto format(group_digits_view<T> t, FormatContext& ctx)
4197 -> decltype(ctx.out()) {
4198 detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
4199 specs_.width_ref, ctx);
4200 detail::handle_dynamic_spec<detail::precision_checker>(
4201 specs_.precision, specs_.precision_ref, ctx);
4202 return detail::write_int(
4203 ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,
4204 detail::digit_grouping<char>("\3", ","));
4205 }
4206};
4207
4208// DEPRECATED! join_view will be moved to ranges.h.
4209template <typename It, typename Sentinel, typename Char = char>
4212 Sentinel end;
4214
4216 : begin(b), end(e), sep(s) {}
4217};
4218
4219template <typename It, typename Sentinel, typename Char>
4220struct formatter<join_view<It, Sentinel, Char>, Char> {
4221 private:
4222 using value_type =
4223#ifdef __cpp_lib_ranges
4224 std::iter_value_t<It>;
4225#else
4226 typename std::iterator_traits<It>::value_type;
4227#endif
4228 formatter<remove_cvref_t<value_type>, Char> value_formatter_;
4229
4230 public:
4231 template <typename ParseContext>
4232 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const Char* {
4233 return value_formatter_.parse(ctx);
4234 }
4235
4236 template <typename FormatContext>
4238 FormatContext& ctx) const -> decltype(ctx.out()) {
4239 auto it = value.begin;
4240 auto out = ctx.out();
4241 if (it != value.end) {
4242 out = value_formatter_.format(*it, ctx);
4243 ++it;
4244 while (it != value.end) {
4245 out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
4246 ctx.advance_to(out);
4247 out = value_formatter_.format(*it, ctx);
4248 ++it;
4249 }
4250 }
4251 return out;
4252 }
4253};
4254
4255/**
4256 Returns a view that formats the iterator range `[begin, end)` with elements
4257 separated by `sep`.
4258 */
4259template <typename It, typename Sentinel>
4260auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
4261 return {begin, end, sep};
4262}
4263
4264/**
4265 \rst
4266 Returns a view that formats `range` with elements separated by `sep`.
4267
4268 **Example**::
4269
4270 std::vector<int> v = {1, 2, 3};
4271 fmt::print("{}", fmt::join(v, ", "));
4272 // Output: "1, 2, 3"
4273
4274 ``fmt::join`` applies passed format specifiers to the range elements::
4275
4276 fmt::print("{:02}", fmt::join(v, ", "));
4277 // Output: "01, 02, 03"
4278 \endrst
4279 */
4280template <typename Range>
4281auto join(Range&& range, string_view sep)
4283 return join(std::begin(range), std::end(range), sep);
4284}
4285
4286/**
4287 \rst
4288 Converts *value* to ``std::string`` using the default format for type *T*.
4289
4290 **Example**::
4291
4292 #include <fmt/format.h>
4293
4294 std::string answer = fmt::to_string(42);
4295 \endrst
4296 */
4297template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
4298 !detail::has_format_as<T>::value)>
4299inline auto to_string(const T& value) -> std::string {
4300 auto buffer = memory_buffer();
4301 detail::write<char>(appender(buffer), value);
4302 return {buffer.data(), buffer.size()};
4303}
4304
4305template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
4306FMT_NODISCARD inline auto to_string(T value) -> std::string {
4307 // The buffer should be large enough to store the number including the sign
4308 // or "false" for bool.
4309 constexpr int max_size = detail::digits10<T>() + 2;
4310 char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
4311 char* begin = buffer;
4312 return std::string(begin, detail::write<char>(begin, value));
4313}
4314
4315template <typename Char, size_t SIZE>
4317 -> std::basic_string<Char> {
4318 auto size = buf.size();
4319 detail::assume(size < std::basic_string<Char>().max_size());
4320 return std::basic_string<Char>(buf.data(), size);
4321}
4322
4323template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value &&
4324 detail::has_format_as<T>::value)>
4325inline auto to_string(const T& value) -> std::string {
4326 return to_string(format_as(value));
4327}
4328
4330
4331namespace detail {
4332
4333template <typename Char>
4335 typename vformat_args<Char>::type args, locale_ref loc) {
4336 auto out = buffer_appender<Char>(buf);
4337 if (fmt.size() == 2 && equal2(fmt.data(), "{}")) {
4338 auto arg = args.get(0);
4339 if (!arg) error_handler().on_error("argument not found");
4341 return;
4342 }
4343
4344 struct format_handler : error_handler {
4346 buffer_context<Char> context;
4347
4348 format_handler(buffer_appender<Char> p_out, basic_string_view<Char> str,
4350 locale_ref p_loc)
4351 : parse_context(str), context(p_out, p_args, p_loc) {}
4352
4353 void on_text(const Char* begin, const Char* end) {
4354 auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));
4355 context.advance_to(write<Char>(context.out(), text));
4356 }
4357
4358 FMT_CONSTEXPR auto on_arg_id() -> int {
4359 return parse_context.next_arg_id();
4360 }
4361 FMT_CONSTEXPR auto on_arg_id(int id) -> int {
4362 return parse_context.check_arg_id(id), id;
4363 }
4364 FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
4365 int arg_id = context.arg_id(id);
4366 if (arg_id < 0) on_error("argument not found");
4367 return arg_id;
4368 }
4369
4370 FMT_INLINE void on_replacement_field(int id, const Char*) {
4371 auto arg = get_arg(context, id);
4373 default_arg_formatter<Char>{context.out(), context.args(),
4374 context.locale()},
4375 arg));
4376 }
4377
4378 auto on_format_specs(int id, const Char* begin, const Char* end)
4379 -> const Char* {
4380 auto arg = get_arg(context, id);
4381 if (arg.type() == type::custom_type) {
4382 parse_context.advance_to(begin);
4383 visit_format_arg(custom_formatter<Char>{parse_context, context}, arg);
4384 return parse_context.begin();
4385 }
4387 begin = parse_format_specs(begin, end, specs, parse_context, arg.type());
4388 detail::handle_dynamic_spec<detail::width_checker>(
4389 specs.width, specs.width_ref, context);
4390 detail::handle_dynamic_spec<detail::precision_checker>(
4391 specs.precision, specs.precision_ref, context);
4392 if (begin == end || *begin != '}')
4393 on_error("missing '}' in format string");
4394 auto f = arg_formatter<Char>{context.out(), specs, context.locale()};
4395 context.advance_to(visit_format_arg(f, arg));
4396 return begin;
4397 }
4398 };
4399 detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));
4400}
4401
4403
4404#ifndef FMT_HEADER_ONLY
4406 typename vformat_args<>::type,
4407 locale_ref);
4412extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
4413extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
4414#endif // FMT_HEADER_ONLY
4415
4416} // namespace detail
4417
4418#if FMT_USE_USER_DEFINED_LITERALS
4419inline namespace literals {
4420/**
4421 \rst
4422 User-defined literal equivalent of :func:`fmt::arg`.
4423
4424 **Example**::
4425
4426 using namespace fmt::literals;
4427 fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
4428 \endrst
4429 */
4430# if FMT_USE_NONTYPE_TEMPLATE_ARGS
4431template <detail_exported::fixed_string Str> constexpr auto operator""_a() {
4432 using char_t = remove_cvref_t<decltype(Str.data[0])>;
4433 return detail::udl_arg<char_t, sizeof(Str.data) / sizeof(char_t), Str>();
4434}
4435# else
4436constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> {
4437 return {s};
4438}
4439# endif
4440} // namespace literals
4441#endif // FMT_USE_USER_DEFINED_LITERALS
4442
4443template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4444inline auto vformat(const Locale& loc, string_view fmt, format_args args)
4445 -> std::string {
4446 return detail::vformat(loc, fmt, args);
4447}
4448
4449template <typename Locale, typename... T,
4450 FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4451inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
4452 -> std::string {
4453 return fmt::vformat(loc, string_view(fmt), fmt::make_format_args(args...));
4454}
4455
4456template <typename OutputIt, typename Locale,
4458 detail::is_locale<Locale>::value)>
4459auto vformat_to(OutputIt out, const Locale& loc, string_view fmt,
4460 format_args args) -> OutputIt {
4461 using detail::get_buffer;
4462 auto&& buf = get_buffer<char>(out);
4463 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
4464 return detail::get_iterator(buf, out);
4465}
4466
4467template <typename OutputIt, typename Locale, typename... T,
4469 detail::is_locale<Locale>::value)>
4470FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
4471 format_string<T...> fmt, T&&... args) -> OutputIt {
4472 return vformat_to(out, loc, fmt, fmt::make_format_args(args...));
4473}
4474
4475template <typename Locale, typename... T,
4476 FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
4479 T&&... args) -> size_t {
4480 auto buf = detail::counting_buffer<>();
4481 detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...),
4482 detail::locale_ref(loc));
4483 return buf.count();
4484}
4485
4487
4488template <typename T, typename Char>
4489template <typename FormatContext>
4491formatter<T, Char,
4493 detail::type::custom_type>>::format(const T& val,
4494 FormatContext& ctx)
4495 const -> decltype(ctx.out()) {
4496 if (specs_.width_ref.kind != detail::arg_id_kind::none ||
4498 auto specs = specs_;
4499 detail::handle_dynamic_spec<detail::width_checker>(specs.width,
4500 specs.width_ref, ctx);
4501 detail::handle_dynamic_spec<detail::precision_checker>(
4502 specs.precision, specs.precision_ref, ctx);
4503 return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
4504 }
4505 return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
4506}
4507
4509
4510#ifdef FMT_HEADER_ONLY
4511# define FMT_FUNC inline
4512# include "format-inl.h"
4513#else
4514# define FMT_FUNC
4515#endif
4516
4517#endif // FMT_FORMAT_H_
and restrictions which apply to each piece of software is included later in this file and or inside of the individual applicable source files The disclaimer of warranty in the WPILib license above applies to all code in and nothing in any of the other licenses gives permission to use the names of FIRST nor the names of the WPILib contributors to endorse or promote products derived from this software The following pieces of software have additional or alternate and or Google Inc All rights reserved Redistribution and use in source and binary with or without are permitted provided that the following conditions are this list of conditions and the following disclaimer *Redistributions in binary form must reproduce the above copyright this list of conditions and the following disclaimer in the documentation and or other materials provided with the distribution *Neither the name of Google Inc nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS AS IS AND ANY EXPRESS OR IMPLIED BUT NOT LIMITED THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY OR CONSEQUENTIAL WHETHER IN STRICT OR EVEN IF ADVISED OF THE POSSIBILITY OF SUCH January AND DISTRIBUTION Definitions License shall mean the terms and conditions for and distribution as defined by Sections through of this document Licensor shall mean the copyright owner or entity authorized by the copyright owner that is granting the License Legal Entity shall mean the union of the acting entity and all other entities that control are controlled by or are under common control with that entity For the purposes of this definition control direct or to cause the direction or management of such whether by contract or including but not limited to software source documentation and configuration files Object form shall mean any form resulting from mechanical transformation or translation of a Source including but not limited to compiled object generated and conversions to other media types Work shall mean the work of whether in Source or Object made available under the as indicated by a copyright notice that is included in or attached to the whether in Source or Object that is based or other modifications as a an original work of authorship For the purposes of this Derivative Works shall not include works that remain separable from
Definition: ThirdPartyNotices.txt:128
Definition: core.h:1081
Definition: core.h:1629
Definition: core.h:1603
\rst A view of a collection of formatting arguments.
Definition: core.h:1857
FMT_CONSTEXPR auto get(int id) const -> format_arg
Returns the argument with the specified id.
Definition: core.h:1931
Definition: core.h:1706
FMT_CONSTEXPR auto locale() -> detail::locale_ref
Definition: core.h:1753
auto args() const -> const format_args &
Definition: core.h:1740
FMT_CONSTEXPR auto out() -> iterator
Definition: core.h:1746
void advance_to(iterator it)
Definition: core.h:1749
FMT_CONSTEXPR auto arg_id(basic_string_view< Char > name) -> int
Definition: core.h:1737
\rst Parsing context consisting of a format string range being parsed and an argument counter for aut...
Definition: core.h:656
FMT_CONSTEXPR auto next_arg_id() -> int
Reports an error if using the manual argument indexing; otherwise returns the next argument index and...
Definition: core.h:693
FMT_CONSTEXPR void check_arg_id(int id)
Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing.
Definition: core.h:708
FMT_CONSTEXPR void advance_to(iterator it)
Advances the begin iterator to it.
Definition: core.h:685
constexpr auto begin() const noexcept -> iterator
Returns an iterator to the beginning of the format string range being parsed.
Definition: core.h:675
A compile-time format string.
Definition: core.h:2721
\rst A dynamically growing memory buffer for trivially copyable/constructible types with the first SI...
Definition: format.h:918
const T & const_reference
Definition: format.h:957
FMT_CONSTEXPR20 void resize(size_t count)
Resizes the buffer to contain count elements.
Definition: format.h:1016
FMT_CONSTEXPR20 ~basic_memory_buffer()
Definition: format.h:965
auto operator=(basic_memory_buffer &&other) noexcept -> basic_memory_buffer &
\rst Moves the content of the other basic_memory_buffer object to this one.
Definition: format.h:1002
void reserve(size_t new_capacity)
Increases the buffer capacity to new_capacity.
Definition: format.h:1019
auto get_allocator() const -> Allocator
Definition: format.h:1010
FMT_CONSTEXPR20 basic_memory_buffer(const Allocator &alloc=Allocator())
Definition: format.h:959
void append(const ContiguousRange &range)
Definition: format.h:1024
FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer &&other) noexcept
\rst Constructs a :class:fmt::basic_memory_buffer object moving the content of the other object to it...
Definition: format.h:993
T value_type
Definition: format.h:956
An implementation of std::basic_string_view for pre-C++17.
Definition: core.h:398
constexpr auto end() const noexcept -> iterator
Definition: core.h:446
constexpr auto size() const noexcept -> size_t
Returns the string size.
Definition: core.h:443
constexpr auto data() const noexcept -> const Char *
Returns a pointer to the string data.
Definition: core.h:440
constexpr auto begin() const noexcept -> iterator
Definition: core.h:445
Definition: format.h:4134
bytes(string_view data)
Definition: format.h:4140
Definition: format.h:2806
friend FMT_CONSTEXPR20 int compare(const bigint &lhs, const bigint &rhs)
Definition: format.h:2940
FMT_CONSTEXPR20 void square()
Definition: format.h:3002
FMT_CONSTEXPR20 bigint & operator*=(Int value)
Definition: format.h:2934
FMT_CONSTEXPR20 bigint()
Definition: format.h:2896
FMT_CONSTEXPR20 int num_bigits() const
Definition: format.h:2915
void operator=(const bigint &)=delete
bigint(uint64_t n)
Definition: format.h:2897
FMT_CONSTEXPR20 void assign(const bigint &other)
Definition: format.h:2902
friend FMT_CONSTEXPR20 int add_compare(const bigint &lhs1, const bigint &lhs2, const bigint &rhs)
Definition: format.h:2957
FMT_CONSTEXPR20 void assign_pow10(int exp)
Definition: format.h:2983
FMT_CONSTEXPR20 void operator=(Int n)
Definition: format.h:2910
FMT_CONSTEXPR20 void align(const bigint &other)
Definition: format.h:3032
FMT_CONSTEXPR20 int divmod_assign(const bigint &divisor)
Definition: format.h:3045
FMT_NOINLINE FMT_CONSTEXPR20 bigint & operator<<=(int shift)
Definition: format.h:2919
bigint(const bigint &)=delete
FMT_CONSTEXPR20 void push_back(const T &value)
Definition: core.h:865
FMT_INLINE auto end() noexcept -> T *
Definition: core.h:832
FMT_CONSTEXPR20 void try_reserve(size_t new_capacity)
Definition: core.h:861
FMT_CONSTEXPR20 void try_resize(size_t count)
Definition: core.h:852
FMT_CONSTEXPR void set(T *buf_data, size_t buf_capacity) noexcept
Sets the buffer data and capacity.
Definition: core.h:816
void clear()
Clears this buffer.
Definition: core.h:848
constexpr auto size() const noexcept -> size_t
Returns the size of this buffer.
Definition: core.h:838
void append(const U *begin, const U *end)
Appends data to the end of the buffer.
constexpr auto capacity() const noexcept -> size_t
Returns the capacity of this buffer.
Definition: core.h:841
FMT_CONSTEXPR auto data() noexcept -> T *
Returns a pointer to the buffer data (not null-terminated).
Definition: core.h:844
Definition: core.h:1019
Definition: format.h:2300
FMT_CONSTEXPR size_t count() const
Definition: format.h:2317
FMT_CONSTEXPR counting_iterator & operator++()
Definition: format.h:2319
FMT_CONSTEXPR counting_iterator operator++(int)
Definition: format.h:2323
FMT_CONSTEXPR counting_iterator()
Definition: format.h:2315
FMT_CONSTEXPR friend counting_iterator operator+(counting_iterator it, difference_type n)
Definition: format.h:2329
void pointer
Definition: format.h:2307
FMT_CONSTEXPR value_type operator*() const
Definition: format.h:2335
std::ptrdiff_t difference_type
Definition: format.h:2306
std::output_iterator_tag iterator_category
Definition: format.h:2305
void reference
Definition: format.h:2308
FMT_UNCHECKED_ITERATOR(counting_iterator)
Definition: format.h:2071
bool has_separator() const
Definition: format.h:2102
digit_grouping(locale_ref loc, bool localized=true)
Definition: format.h:2093
Out apply(Out out, basic_string_view< C > digits) const
Definition: format.h:2113
digit_grouping(std::string grouping, std::basic_string< Char > sep)
Definition: format.h:2099
int count_separators(int num_digits) const
Definition: format.h:2104
Definition: format.h:2731
constexpr int count_separators(int) const
Definition: format.h:2737
constexpr Out apply(Out out, basic_string_view< C >) const
Definition: format.h:2740
constexpr bool has_separator() const
Definition: format.h:2735
constexpr fallback_digit_grouping(locale_ref, bool)
Definition: format.h:2733
Definition: format.h:310
auto xsputn(const char_type *s, streamsize count) -> streamsize override
Definition: format.h:335
auto overflow(int_type ch) -> int_type override
Definition: format.h:329
formatbuf(buffer< char_type > &buf)
Definition: format.h:320
Definition: core.h:1529
Definition: format.h:3842
FMT_CONSTEXPR auto operator()(T) -> unsigned long long
Definition: format.h:3853
FMT_CONSTEXPR precision_checker(ErrorHandler &eh)
Definition: format.h:3844
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long
Definition: format.h:3847
Definition: format.h:1425
std::string str() const
Definition: format.h:1442
static bool convert(Buffer &buf, basic_string_view< WChar > s, to_utf8_error_policy policy=to_utf8_error_policy::abort)
Definition: format.h:1453
to_utf8(basic_string_view< WChar > s, to_utf8_error_policy policy=to_utf8_error_policy::abort)
Definition: format.h:1431
to_utf8()
Definition: format.h:1430
bool convert(basic_string_view< WChar > s, to_utf8_error_policy policy=to_utf8_error_policy::abort)
Definition: format.h:1447
size_t size() const
Definition: format.h:1440
const char * c_str() const
Definition: format.h:1441
Definition: format.h:368
FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback &
Definition: format.h:438
constexpr uint64_t low() const noexcept
Definition: format.h:377
constexpr uint128_fallback(uint64_t hi, uint64_t lo)
Definition: format.h:373
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback
Definition: format.h:428
friend constexpr auto operator==(const uint128_fallback &lhs, const uint128_fallback &rhs) -> bool
Definition: format.h:384
friend auto operator-(const uint128_fallback &lhs, uint64_t rhs) -> uint128_fallback
Definition: format.h:424
friend constexpr auto operator|(const uint128_fallback &lhs, const uint128_fallback &rhs) -> uint128_fallback
Definition: format.h:396
friend auto operator*(const uint128_fallback &lhs, uint32_t rhs) -> uint128_fallback
Definition: format.h:416
FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback
Definition: format.h:433
FMT_CONSTEXPR20 uint128_fallback & operator+=(uint64_t n) noexcept
Definition: format.h:453
friend constexpr auto operator!=(const uint128_fallback &lhs, const uint128_fallback &rhs) -> bool
Definition: format.h:388
friend constexpr auto operator~(const uint128_fallback &n) -> uint128_fallback
Definition: format.h:406
friend auto operator+(const uint128_fallback &lhs, const uint128_fallback &rhs) -> uint128_fallback
Definition: format.h:410
friend constexpr auto operator>(const uint128_fallback &lhs, const uint128_fallback &rhs) -> bool
Definition: format.h:392
constexpr uint128_fallback(uint64_t value=0)
Definition: format.h:374
FMT_CONSTEXPR void operator+=(uint128_fallback n)
Definition: format.h:441
friend constexpr auto operator&(const uint128_fallback &lhs, const uint128_fallback &rhs) -> uint128_fallback
Definition: format.h:401
FMT_CONSTEXPR void operator&=(uint128_fallback n)
Definition: format.h:448
constexpr uint64_t high() const noexcept
Definition: format.h:376
Definition: format.h:1410
FMT_API utf8_to_utf16(string_view s)
Definition: format-inl.h:1387
auto size() const -> size_t
Definition: format.h:1417
auto c_str() const -> const wchar_t *
Definition: format.h:1418
auto str() const -> std::wstring
Definition: format.h:1419
Definition: core.h:1238
Definition: format.h:3822
FMT_CONSTEXPR width_checker(ErrorHandler &eh)
Definition: format.h:3824
FMT_CONSTEXPR auto operator()(T) -> unsigned long long
Definition: format.h:3833
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long
Definition: format.h:3827
Definition: format.h:1098
auto put(appender out, loc_value val, const format_specs<> &specs) const -> bool
Definition: format.h:1119
static FMT_API Locale::id id
Definition: format.h:1109
virtual auto do_put(appender out, loc_value val, const format_specs<> &specs) const -> bool
format_facet(Locale &loc)
Definition: format-inl.h:131
format_facet(string_view sep="", std::initializer_list< unsigned char > g={3}, std::string decimal_point=".")
Definition: format.h:1112
Fast integer formatter.
Definition: format.h:4001
format_int(unsigned long long value)
Definition: format.h:4029
auto str() const -> std::string
\rst Returns the content of the output buffer as an std::string.
Definition: format.h:4057
auto size() const -> size_t
Returns the number of characters written to the output buffer.
Definition: format.h:4033
format_int(int value)
Definition: format.h:4024
format_int(long value)
Definition: format.h:4025
format_int(long long value)
Definition: format.h:4026
auto c_str() const -> const char *
Returns a pointer to the output buffer content with terminating null character appended.
Definition: format.h:4047
auto data() const -> const char *
Returns a pointer to the output buffer content.
Definition: format.h:4041
format_int(unsigned value)
Definition: format.h:4027
format_int(unsigned long value)
Definition: format.h:4028
Definition: format.h:1080
loc_value(T)
Definition: format.h:1089
loc_value(T value)
Definition: format.h:1086
auto visit(Visitor &&vis) -> decltype(vis(0))
Definition: format.h:1091
typename std::enable_if< B, T >::type enable_if_t
Definition: core.h:256
#define FMT_ASSERT(condition, message)
Definition: core.h:336
FMT_CONSTEXPR FMT_INLINE auto visit_format_arg(Visitor &&vis, const basic_format_arg< Context > &arg) -> decltype(vis(0))
\rst Visits an argument dispatching to the appropriate visit method based on the argument type.
Definition: core.h:1665
#define FMT_END_EXPORT
Definition: core.h:185
basic_string_view< char > string_view
Definition: core.h:501
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
\rst Returns a named argument to be used in a formatting function.
Definition: core.h:1841
#define FMT_NODISCARD
Definition: core.h:154
typename std::remove_reference< T >::type remove_reference_t
Definition: core.h:261
typename detail::char_t_impl< S >::type char_t
String's character type.
Definition: core.h:646
#define FMT_CONSTEXPR
Definition: core.h:105
#define FMT_BEGIN_NAMESPACE
Definition: core.h:174
#define FMT_API
Definition: core.h:202
constexpr auto make_format_args(T &... args) -> format_arg_store< Context, remove_cvref_t< T >... >
\rst Constructs a ~fmtformat_arg_store object that contains references to arguments and can be implic...
Definition: core.h:1824
#define FMT_ENABLE_IF(...)
Definition: core.h:286
#define FMT_BEGIN_EXPORT
Definition: core.h:184
#define FMT_CONSTEXPR_CHAR_TRAITS
Definition: core.h:129
#define FMT_INLINE
Definition: core.h:162
#define FMT_MSC_WARNING(...)
Definition: core.h:58
typename type_identity< T >::type type_identity_t
Definition: core.h:267
typename std::conditional< B, T, F >::type conditional_t
Definition: core.h:258
#define FMT_CONSTEXPR20
Definition: core.h:113
sign::type sign_t
Definition: core.h:1990
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
Definition: core.h:265
typename std::underlying_type< T >::type underlying_t
Definition: core.h:269
#define FMT_END_NAMESPACE
Definition: core.h:177
auto system_error(int error_code, format_string< T... > fmt, T &&... args) -> std::system_error
\rst Constructs :class:std::system_error with a message formatted with fmt::format(fmt,...
Definition: format.h:3972
FMT_API void report_system_error(int error_code, const char *message) noexcept
Definition: format-inl.h:1413
#define FMT_FORMAT_AS(Type, Base)
Definition: format.h:4072
#define FMT_USE_LONG_DOUBLE
Definition: format.h:826
FMT_API auto vsystem_error(int error_code, string_view format_str, format_args args) -> std::system_error
Definition: format-inl.h:145
FMT_INLINE auto format_to(OutputIt out, const Locale &loc, format_string< T... > fmt, T &&... args) -> OutputIt
Definition: format.h:4470
FMT_API void format_system_error(detail::buffer< char > &out, int error_code, const char *message) noexcept
\rst Formats an error message for an error returned by an operating system or a language runtime,...
Definition: format-inl.h:1402
#define FMT_FALLTHROUGH
Definition: format.h:65
auto join(It begin, Sentinel end, string_view sep) -> join_view< It, Sentinel >
Returns a view that formats the iterator range [begin, end) with elements separated by sep.
Definition: format.h:4260
#define FMT_USE_FLOAT
Definition: format.h:820
#define FMT_VISIBILITY(value)
Definition: format.h:99
auto vformat(const Locale &loc, string_view fmt, format_args args) -> std::string
Definition: format.h:4444
auto vformat_to(OutputIt out, const Locale &loc, string_view fmt, format_args args) -> OutputIt
Definition: format.h:4459
auto to_string(const T &value) -> std::string
\rst Converts value to std::string using the default format for type T.
Definition: format.h:4299
basic_memory_buffer< char > memory_buffer
Definition: format.h:1029
auto format(const Locale &loc, format_string< T... > fmt, T &&... args) -> std::string
Definition: format.h:4451
FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale &loc, format_string< T... > fmt, T &&... args) -> size_t
Definition: format.h:4477
#define FMT_NOINLINE
Definition: format.h:111
auto group_digits(T value) -> group_digits_view< T >
\rst Returns a view that formats an integer value using ',' as a locale-independent thousands separat...
Definition: format.h:4180
#define FMT_INLINE_VARIABLE
Definition: format.h:54
constexpr auto underlying(Enum e) noexcept -> underlying_t< Enum >
\rst Converts e to the underlying type.
Definition: format.h:4123
#define FMT_THROW(x)
Definition: format.h:129
auto ptr(T p) -> const void *
\rst Converts p to const void* for pointer formatting.
Definition: format.h:4100
#define FMT_USE_DOUBLE
Definition: format.h:823
#define FMT_REDUCE_INT_INSTANTIATIONS
Definition: format.h:169
#define FMT_POWERS_OF_10(factor)
Definition: format.h:1156
dimensionless::scalar_t exp(const ScalarUnit x) noexcept
Compute exponential function.
Definition: math.h:332
Definition: core.h:1982
FMT_FUNC uint128_fallback get_cached_power(int k) noexcept
Definition: format-inl.h:1115
uint32_t divisor
Definition: format-inl.h:197
int floor_log2_pow10(int e) noexcept
Definition: format.h:1528
uint64_t umul128_upper64(uint64_t x, uint64_t y) noexcept
Definition: format.h:1534
uint128_fallback umul192_upper128(uint64_t x, uint128_fallback y) noexcept
Definition: format.h:1547
int floor_log10_pow2(int e) noexcept
Definition: format.h:1522
decimal_fp< T > to_decimal(T x) noexcept
Definition: format-inl.h:1235
An error reported from a formatting function.
Definition: format.h:1054
constexpr auto compile_string_to_view(const Char(&s)[N]) -> basic_string_view< Char >
Definition: format.h:1067
detail namespace with internal helper functions
Definition: xchar.h:20
FMT_CONSTEXPR auto code_point_length(const Char *begin) -> int
Definition: core.h:2112
constexpr auto digits10< int128_opt >() noexcept -> int
Definition: format.h:1286
uint128_fallback umul128(uint64_t x, uint64_t y) noexcept
Definition: format.h:1491
FMT_CONSTEXPR auto format_uint(Char *buffer, UInt value, int num_digits, bool upper=false) -> Char *
Definition: format.h:1383
FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(OutputIt out, write_int_arg< T > arg, const format_specs< Char > &specs, locale_ref loc) -> OutputIt
Definition: format.h:2270
FMT_FUNC bool write_console(std::FILE *, string_view)
Definition: format-inl.h:1428
FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP &f, const format_specs< Char > &specs, float_specs fspecs, locale_ref loc) -> OutputIt
Definition: format.h:2627
FMT_CONSTEXPR auto write_char(OutputIt out, Char value, const format_specs< Char > &specs) -> OutputIt
Definition: format.h:2000
constexpr auto to_ascii(Char c) -> char
Definition: core.h:2102
FMT_CONSTEXPR20 auto bit_cast(const From &from) -> To
Definition: format.h:343
FMT_CONSTEXPR auto check_char_specs(const format_specs< Char > &specs) -> bool
Definition: core.h:2558
decltype(std::end(std::declval< T & >())) sentinel_t
Definition: format.h:552
FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, unsigned prefix, const format_specs< Char > &specs, W write_digits) -> OutputIt
Definition: format.h:2048
template FMT_API auto thousands_sep_impl< char >(locale_ref) -> thousands_sep_result< char >
std::integral_constant< bool, std::numeric_limits< T >::is_signed||std::is_same< T, int128_opt >::value > is_signed
Definition: format.h:811
FMT_CONSTEXPR void ignore_unused(const T &...)
Definition: core.h:302
auto decimal_point(locale_ref loc) -> Char
Definition: format.h:1308
FMT_INLINE void assume(bool condition)
Definition: format.h:540
auto get_buffer(OutputIt out) -> iterator_buffer< OutputIt, T >
Definition: core.h:1117
FMT_CONSTEXPR void handle_dynamic_spec(int &value, arg_ref< typename Context::char_type > ref, Context &ctx)
Definition: format.h:3878
constexpr auto num_bits() -> int
Definition: format.h:492
FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, const format_specs< Char > &specs) -> OutputIt
Definition: format.h:1819
uint128_opt
Definition: core.h:367
auto write(OutputIt out, const std::tm &time, const std::locale &loc, char format, char modifier=0) -> OutputIt
Definition: chrono.h:419
FMT_CONSTEXPR void prefix_append(unsigned &prefix, unsigned value)
Definition: format.h:2166
auto write_loc(std::back_insert_iterator< detail::buffer< wchar_t > > out, loc_value value, const format_specs< wchar_t > &specs, locale_ref loc) -> bool
Definition: xchar.h:25
auto is_big_endian() -> bool
Definition: format.h:353
conditional_t< long_short, unsigned, unsigned long long > ulong_type
Definition: core.h:1316
FMT_CONSTEXPR auto count_digits_fallback(T n) -> int
Definition: format.h:1179
void(*)(detail::buffer< char > &, int, const char *) format_func
Definition: format.h:3942
FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs< Char > &specs, size_t size, size_t width, F &&f) -> OutputIt
Definition: format.h:1794
auto compute_width(basic_string_view< Char > s) -> size_t
Definition: format.h:738
constexpr auto num_bits< uint128_t >() -> int
Definition: format.h:497
constexpr auto digits10() noexcept -> int
Definition: format.h:1283
FMT_CONSTEXPR20 auto format_decimal(Char *out, UInt value, int size) -> format_decimal_result< Char * >
Definition: format.h:1350
dragon
Definition: format.h:3060
@ fixup
Definition: format.h:3062
@ predecessor_closer
Definition: format.h:3061
@ fixed
Definition: format.h:3063
auto reserve(std::back_insert_iterator< Container > it, size_t n) -> typename Container::value_type *
Definition: format.h:571
std::is_same< T, float128 > is_float128
Definition: format.h:851
constexpr auto digits10< uint128_t >() noexcept -> int
Definition: format.h:1287
FMT_CONSTEXPR20 void adjust_precision(int &precision, int exp10)
Definition: format.h:2798
constexpr auto max_value() -> T
Definition: format.h:489
FMT_INLINE auto to_string_view(const Char *s) -> basic_string_view< Char >
Definition: core.h:517
void float128
Definition: format.h:849
int128_opt
Definition: core.h:366
@ value
the parser finished reading a JSON value
FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP &f, const format_specs< Char > &specs, float_specs fspecs, locale_ref loc) -> OutputIt
Definition: format.h:2746
constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point
Definition: format.h:702
FMT_FUNC void print(std::FILE *f, string_view text)
Definition: format-inl.h:1452
FMT_CONSTEXPR auto get_arg(Context &ctx, ID id) -> decltype(ctx.arg(id))
Definition: format.h:3871
FMT_FUNC void report_error(format_func func, int error_code, const char *message) noexcept
Definition: format-inl.h:66
FMT_FUNC void throw_format_error(const char *message)
Definition: format-inl.h:39
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t< Char > &fill) -> OutputIt
Definition: format.h:1779
constexpr auto to_pointer(OutputIt, size_t) -> T *
Definition: format.h:596
FMT_FUNC void format_error_code(detail::buffer< char > &out, int error_code, string_view message) noexcept
Definition: format-inl.h:43
to_utf8_error_policy
Definition: format.h:1422
auto equal2(const Char *lhs, const char *rhs) -> bool
Definition: format.h:1316
constexpr bool has_implicit_bit()
Definition: format.h:1608
typename std::enable_if< B, T >::type enable_if_t
Definition: cpp_future.h:38
FMT_CONSTEXPR20 FMT_INLINE void copy2(Char *dst, const char *src)
Definition: format.h:1325
bool_constant< std::is_floating_point< T >::value||is_float128< T >::value > is_floating_point
Definition: format.h:855
auto write_ptr(OutputIt out, UIntPtr value, const format_specs< Char > *specs) -> OutputIt
Definition: format.h:1829
auto vformat(const Locale &loc, basic_string_view< Char > fmt, basic_format_args< buffer_context< type_identity_t< Char > > > args) -> std::basic_string< Char >
Definition: format.h:3934
remove_reference_t< decltype(reserve(std::declval< OutputIt & >(), 0))> reserve_iterator
Definition: format.h:593
auto decimal_point(locale_ref loc) -> wchar_t
Definition: format.h:1311
float_format
Definition: format.h:2441
decltype(std::begin(std::declval< T & >())) iterator_t
Definition: format.h:551
FMT_CONSTEXPR20 void format_hexfloat(Float value, int precision, float_specs specs, buffer< char > &buf)
Definition: format.h:3200
FMT_CONSTEXPR auto is_utf8() -> bool
Definition: core.h:380
FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, buffer< char > &buf) -> int
Definition: format.h:3287
template FMT_API auto thousands_sep_impl< wchar_t >(locale_ref) -> thousands_sep_result< wchar_t >
@ error
throw a parse_error exception in case of a tag
auto write_escaped_char(OutputIt out, Char v) -> OutputIt
Definition: format.h:1986
constexpr auto num_bits< int128_opt >() -> int
Definition: format.h:496
FMT_CONSTEXPR FMT_INLINE auto make_arg(T &val) -> value< Context >
Definition: core.h:1558
FMT_CONSTEXPR uint64_t multiply(uint64_t lhs, uint64_t rhs)
Definition: format.h:1725
auto thousands_sep(locale_ref loc) -> thousands_sep_result< Char >
Definition: format.h:1297
conditional_t< FMT_USE_INT128, uint128_opt, uint128_fallback > uint128_t
Definition: format.h:479
FMT_CONSTEXPR fp operator*(fp x, fp y)
Definition: format.h:1742
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T &value) -> OutputIt
Definition: format.h:622
constexpr int num_significand_bits()
Definition: format.h:1615
std::integral_constant< bool, Value > bool_constant
Definition: type_traits.h:688
constexpr auto exponent_bias() -> int
Definition: format.h:1629
FMT_CONSTEXPR auto parse_float_type_spec(const format_specs< Char > &specs, ErrorHandler &&eh={}) -> float_specs
Definition: format.h:2459
auto get_container(std::back_insert_iterator< Container > it) -> Container &
Definition: core.h:765
constexpr Char sign(Sign s)
Definition: format.h:1172
constexpr auto count() -> size_t
Definition: core.h:1203
conditional_t< std::is_same< T, char >::value, appender, std::back_insert_iterator< buffer< T > > > buffer_appender
Definition: core.h:1113
FMT_CONSTEXPR auto utf8_decode(const char *s, uint32_t *c, int *e) -> const char *
Definition: format.h:665
FMT_CONSTEXPR void abort_fuzzing_if(bool condition)
Definition: format.h:291
constexpr auto write_significand(OutputIt out, const char *significand, int significand_size) -> OutputIt
Definition: format.h:2537
auto write_escaped_cp(OutputIt out, const find_escape_result< Char > &escape) -> OutputIt
Definition: format.h:1925
FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, format_specs< Char > specs, const float_specs &fspecs) -> OutputIt
Definition: format.h:2503
auto base_iterator(std::back_insert_iterator< Container > it, typename Container::value_type *) -> std::back_insert_iterator< Container >
Definition: format.h:608
constexpr auto get_significand_size(const big_decimal_fp &f) -> int
Definition: format.h:2528
FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool
Definition: format.h:1139
FMT_INLINE auto get_iterator(Buf &buf, OutputIt) -> decltype(buf.out())
Definition: core.h:1127
auto needs_escape(uint32_t cp) -> bool
Definition: format.h:1845
constexpr auto convert_float(T value) -> convert_float_result< T >
Definition: format.h:1774
auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt
Definition: format.h:1915
constexpr auto set(type rhs) -> int
Definition: core.h:610
auto code_point_index(basic_string_view< Char > s, size_t n) -> size_t
Definition: format.h:783
conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > uint64_or_128_t
Definition: format.h:1154
bool isfinite(T)
Definition: chrono.h:1600
conditional_t< std::is_same< T, float >::value||doublish, double, T > convert_float_result
Definition: format.h:1771
auto get_data(std::basic_string< Char > &s) -> Char *
Definition: format.h:556
FMT_FUNC auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result< Char >
Definition: format-inl.h:93
FMT_CONSTEXPR bool isfinite(T value)
Definition: format.h:2779
auto is_printable(uint16_t x, const singleton *singletons, size_t singletons_size, const unsigned char *singleton_lowers, const unsigned char *normal, size_t normal_size) -> bool
Definition: format-inl.h:1474
constexpr bool isnan(T value)
Definition: format.h:2759
state
Definition: core.h:2271
FMT_CONSTEXPR void for_each_codepoint(string_view s, F f)
Definition: format.h:707
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)
Definition: color.h:436
FMT_CONSTEXPR20 auto countl_zero_fallback(UInt n) -> int
Definition: format.h:519
constexpr auto is_negative(T value) -> bool
Definition: format.h:1130
type
Definition: core.h:556
constexpr FMT_INLINE auto const_check(T value) -> T
Definition: core.h:323
conditional_t< long_short, int, long long > long_type
Definition: core.h:1315
FMT_CONSTEXPR auto to_unsigned(Int value) -> typename std::make_unsigned< Int >::type
Definition: core.h:374
uint128_t uintptr_t
Definition: format.h:484
auto find_escape(const Char *begin, const Char *end) -> find_escape_result< Char >
Definition: format.h:1863
FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It
Definition: format.h:1637
FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char *begin, const Char *end, dynamic_format_specs< Char > &specs, basic_format_parse_context< Char > &ctx, type arg_type) -> const Char *
Definition: core.h:2275
FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) -> write_int_arg< uint32_or_64_or_128_t< T > >
Definition: format.h:2177
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
Definition: format.h:817
FMT_CONSTEXPR20 auto count_digits(uint64_t n) -> int
Definition: format.h:1222
FMT_CONSTEXPR basic_fp< F > normalize(basic_fp< F > value)
Definition: format.h:1708
constexpr FMT_INLINE auto is_constant_evaluated(bool default_value=false) noexcept -> bool
Definition: core.h:304
FMT_CONSTEXPR auto parse_align(const Char *begin, const Char *end, format_specs< Char > &specs) -> const Char *
Definition: format.h:2399
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
Definition: format.h:1152
FMT_FUNC Char decimal_point_impl(locale_ref loc)
Definition: format-inl.h:99
FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end, OutputIt out) -> OutputIt
Definition: format.h:643
constexpr auto exponent_mask() -> typename dragonbox::float_info< Float >::carrier_uint
Definition: format.h:1623
typename conditional_t< std::is_integral< Char >::value, std::make_unsigned< Char >, type_identity< uint32_t > >::type make_unsigned_char
Definition: format.h:1860
FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int
Definition: format.h:3864
constexpr const char * digits2(size_t value)
Definition: format.h:1162
FMT_CONSTEXPR20 auto countl_zero(uint32_t n) -> int
Definition: format.h:526
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition: string_escape.h:50
char8_type
Definition: format.h:639
FMT_CONSTEXPR20 void format_dragon(basic_fp< uint128_t > value, unsigned flags, int num_digits, buffer< char > &buf, int &exp10)
Definition: format.h:3069
auto write_escaped_string(OutputIt out, basic_string_view< Char > str) -> OutputIt
Definition: format.h:1970
FMT_INLINE FMT_CONSTEXPR bool signbit(T value)
Definition: format.h:2786
Definition: format.h:4127
constexpr auto format_as(Enum e) noexcept -> underlying_t< Enum >
Definition: format.h:4129
constexpr common_return_t< T1, T2 > beta(const T1 a, const T2 b) noexcept
Compile-time beta function.
Definition: beta.hpp:42
Definition: xchar.h:71
Definition: core.h:1987
Definition: array.h:89
static constexpr const unit_t< compound_unit< energy::joule, time::seconds > > h(6.626070040e-34)
Planck constant.
static constexpr const unit_t< compound_unit< charge::coulomb, inverse< substance::mol > > > F(N_A *e)
Faraday constant.
static constexpr const charge::coulomb_t e(1.6021766208e-19)
elementary charge.
static constexpr const velocity::meters_per_second_t c(299792458.0)
Speed of light in vacuum.
UnitTypeLhs() max(const UnitTypeLhs &lhs, const UnitTypeRhs &rhs)
Definition: base.h:3417
b
Definition: data.h:44
bits
Definition: data.h:44
Definition: format.h:284
Definition: format.h:283
Definition: format.h:3792
auto operator()(typename basic_format_arg< context >::handle) -> iterator
Definition: format.h:3804
FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator
Definition: format.h:3801
iterator out
Definition: format.h:3796
locale_ref locale
Definition: format.h:3798
const format_specs< Char > & specs
Definition: format.h:3797
buffer_appender< Char > iterator
Definition: format.h:3793
Definition: core.h:1335
Definition: core.h:2067
arg_id_kind kind
Definition: core.h:2081
union detail::arg_ref::value val
Definition: format.h:1746
static constexpr uint32_t fractional_part_rounding_thresholds[8]
Definition: format.h:1750
Definition: format.h:1658
FMT_CONSTEXPR basic_fp(Float n)
Definition: format.h:1669
constexpr basic_fp(uint64_t f_val, int e_val)
Definition: format.h:1666
FMT_CONSTEXPR auto assign(Float n) -> bool
Definition: format.h:1673
constexpr basic_fp()
Definition: format.h:1665
int e
Definition: format.h:1660
static constexpr const int num_significand_bits
Definition: format.h:1662
F f
Definition: format.h:1659
Definition: format.h:2522
const char * significand
Definition: format.h:2523
int significand_size
Definition: format.h:2524
int exponent
Definition: format.h:2525
Definition: format.h:2311
FMT_CONSTEXPR void operator=(const T &)
Definition: format.h:2312
Definition: format.h:3811
void operator()(T) const
Definition: format.h:3819
buffer_context< Char > & ctx
Definition: format.h:3813
basic_format_parse_context< Char > & parse_ctx
Definition: format.h:3812
void operator()(typename basic_format_arg< buffer_context< Char > >::handle h) const
Definition: format.h:3815
Definition: format.h:1762
Definition: format.h:3773
iterator out
Definition: format.h:3777
auto operator()(typename basic_format_arg< context >::handle h) -> iterator
Definition: format.h:3784
buffer_appender< Char > iterator
Definition: format.h:3774
locale_ref loc
Definition: format.h:3779
auto operator()(T value) -> iterator
Definition: format.h:3781
basic_format_args< context > args
Definition: format.h:3778
Definition: format.h:1598
int exponent
Definition: format.h:1601
significand_type significand
Definition: format.h:1600
typename float_info< T >::carrier_uint significand_type
Definition: format.h:1599
uint64_t carrier_uint
Definition: format.h:1572
uint32_t carrier_uint
Definition: format.h:1560
Definition: format.h:1557
Definition: core.h:2095
arg_ref< Char > width_ref
Definition: core.h:2096
arg_ref< Char > precision_ref
Definition: core.h:2097
Definition: core.h:632
FMT_NORETURN void on_error(const char *message)
Definition: core.h:636
Definition: core.h:1995
Definition: format.h:1850
const Char * end
Definition: format.h:1852
const Char * begin
Definition: format.h:1851
uint32_t cp
Definition: format.h:1853
Definition: format.h:2448
int precision
Definition: format.h:2449
bool showpoint
Definition: format.h:2455
bool locale
Definition: format.h:2453
bool upper
Definition: format.h:2452
sign_t sign
Definition: format.h:2451
float_format format
Definition: format.h:2450
bool binary32
Definition: format.h:2454
Definition: format.h:1341
Iterator end
Definition: format.h:1343
Iterator begin
Definition: format.h:1342
Definition: format.h:2764
Definition: format.h:804
Definition: core.h:1514
Definition: core.h:548
Definition: format.h:2192
std::string grouping
Definition: format.h:2196
auto operator()(T value) -> bool
Definition: format.h:2200
auto operator()(T) -> bool
Definition: format.h:2208
std::basic_string< Char > decimal_point
Definition: format.h:2197
buffer_appender< Char > out
Definition: format.h:2193
std::basic_string< Char > sep
Definition: format.h:2195
const format_specs< Char > & specs
Definition: format.h:2194
Definition: core.h:349
Definition: format.h:298
static constexpr CharT value[sizeof...(C)]
Definition: format.h:299
Definition: format.h:1289
Char thousands_sep
Definition: format.h:1291
std::string grouping
Definition: format.h:1290
Definition: core.h:1135
Definition: format.h:2171
unsigned prefix
Definition: format.h:2173
UInt abs_value
Definition: format.h:2172
Definition: format.h:2023
FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, const format_specs< Char > &specs)
Definition: format.h:2027
size_t size
Definition: format.h:2024
size_t padding
Definition: format.h:2025
Definition: format.h:278
Definition: format.h:277
Definition: core.h:2042
int width
Definition: core.h:2043
detail::fill_t< Char > fill
Definition: core.h:2050
int precision
Definition: core.h:2044
sign_t sign
Definition: core.h:2047
align_t align
Definition: core.h:2046
presentation_type type
Definition: core.h:2045
bool alt
Definition: core.h:2048
bool localized
Definition: core.h:2049
auto format(const T &value, FormatContext &ctx) const -> decltype(ctx.out())
Definition: format.h:4067
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> const char *
Definition: format.h:4149
auto format(bytes b, FormatContext &ctx) -> decltype(ctx.out())
Definition: format.h:4155
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> const char *
Definition: format.h:4190
auto format(group_digits_view< T > t, FormatContext &ctx) -> decltype(ctx.out())
Definition: format.h:4196
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> const Char *
Definition: format.h:4232
auto format(const join_view< It, Sentinel, Char > &value, FormatContext &ctx) const -> decltype(ctx.out())
Definition: format.h:4237
Definition: core.h:1068
Definition: format.h:4165
T value
Definition: format.h:4166
Definition: core.h:272
Definition: format.h:4210
It begin
Definition: format.h:4211
join_view(It b, Sentinel e, basic_string_view< Char > s)
Definition: format.h:4215
Sentinel end
Definition: format.h:4212
basic_string_view< Char > sep
Definition: format.h:4213
Definition: core.h:276
Definition: core.h:266
basic_string_view< Char > name
Definition: core.h:2087
int index
Definition: core.h:2086