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