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