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