SimulationCraft
SimulationCraft is a tool to explore combat mechanics in the popular MMO RPG World of Warcraft (tm).
format.h
1 /*
2  Formatting library for C++
3 
4  Copyright (c) 2012 - present, Victor Zverovich
5 
6  Permission is hereby granted, free of charge, to any person obtaining
7  a copy of this software and associated documentation files (the
8  "Software"), to deal in the Software without restriction, including
9  without limitation the rights to use, copy, modify, merge, publish,
10  distribute, sublicense, and/or sell copies of the Software, and to
11  permit persons to whom the Software is furnished to do so, subject to
12  the following conditions:
13 
14  The above copyright notice and this permission notice shall be
15  included in all copies or substantial portions of the Software.
16 
17  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20  NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21  LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22  OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23  WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 
25  --- Optional exception to the license ---
26 
27  As an exception, if, as a result of your compiling your source code, portions
28  of this Software are embedded into a machine-executable object form of such
29  source code, you may redistribute such embedded portions in such object form
30  without including the above copyright and permission notices.
31  */
32 
33 #ifndef FMT_FORMAT_H_
34 #define FMT_FORMAT_H_
35 
36 #include <cmath> // std::signbit
37 #include <cstdint> // uint32_t
38 #include <limits> // std::numeric_limits
39 #include <memory> // std::uninitialized_copy
40 #include <stdexcept> // std::runtime_error
41 #include <system_error> // std::system_error
42 #include <utility> // std::swap
43 
44 #ifdef __cpp_lib_bit_cast
45 # include <bit> // std::bitcast
46 #endif
47 
48 #include "core.h"
49 
50 #if FMT_GCC_VERSION
51 # define FMT_GCC_VISIBILITY_HIDDEN __attribute__((visibility("hidden")))
52 #else
53 # define FMT_GCC_VISIBILITY_HIDDEN
54 #endif
55 
56 #ifdef __NVCC__
57 # define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
58 #else
59 # define FMT_CUDA_VERSION 0
60 #endif
61 
62 #ifdef __has_builtin
63 # define FMT_HAS_BUILTIN(x) __has_builtin(x)
64 #else
65 # define FMT_HAS_BUILTIN(x) 0
66 #endif
67 
68 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
69 # define FMT_NOINLINE __attribute__((noinline))
70 #else
71 # define FMT_NOINLINE
72 #endif
73 
74 #if FMT_MSC_VER
75 # define FMT_MSC_DEFAULT = default
76 #else
77 # define FMT_MSC_DEFAULT
78 #endif
79 
80 #ifndef FMT_THROW
81 # if FMT_EXCEPTIONS
82 # if FMT_MSC_VER || FMT_NVCC
83 FMT_BEGIN_NAMESPACE
84 namespace detail {
85 template <typename Exception> inline void do_throw(const Exception& x) {
86  // Silence unreachable code warnings in MSVC and NVCC because these
87  // are nearly impossible to fix in a generic code.
88  volatile bool b = true;
89  if (b) throw x;
90 }
91 } // namespace detail
92 FMT_END_NAMESPACE
93 # define FMT_THROW(x) detail::do_throw(x)
94 # else
95 # define FMT_THROW(x) throw x
96 # endif
97 # else
98 # define FMT_THROW(x) \
99  do { \
100  FMT_ASSERT(false, (x).what()); \
101  } while (false)
102 # endif
103 #endif
104 
105 #if FMT_EXCEPTIONS
106 # define FMT_TRY try
107 # define FMT_CATCH(x) catch (x)
108 #else
109 # define FMT_TRY if (true)
110 # define FMT_CATCH(x) if (false)
111 #endif
112 
113 #ifndef FMT_MAYBE_UNUSED
114 # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
115 # define FMT_MAYBE_UNUSED [[maybe_unused]]
116 # else
117 # define FMT_MAYBE_UNUSED
118 # endif
119 #endif
120 
121 // Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers.
122 #if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC
123 # define FMT_DEPRECATED_ALIAS
124 #else
125 # define FMT_DEPRECATED_ALIAS FMT_DEPRECATED
126 #endif
127 
128 #ifndef FMT_USE_USER_DEFINED_LITERALS
129 // EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
130 # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
131  FMT_MSC_VER >= 1900) && \
132  (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
133 # define FMT_USE_USER_DEFINED_LITERALS 1
134 # else
135 # define FMT_USE_USER_DEFINED_LITERALS 0
136 # endif
137 #endif
138 
139 // Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
140 // integer formatter template instantiations to just one by only using the
141 // largest integer type. This results in a reduction in binary size but will
142 // cause a decrease in integer formatting performance.
143 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
144 # define FMT_REDUCE_INT_INSTANTIATIONS 0
145 #endif
146 
147 // __builtin_clz is broken in clang with Microsoft CodeGen:
148 // https://github.com/fmtlib/fmt/issues/519.
149 #if !FMT_MSC_VER
150 # if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION
151 # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
152 # endif
153 # if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
154 # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
155 # endif
156 #endif
157 
158 // __builtin_ctz is broken in Intel Compiler Classic on Windows:
159 // https://github.com/fmtlib/fmt/issues/2510.
160 #ifndef __ICL
161 # if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION
162 # define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
163 # endif
164 # if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || FMT_ICC_VERSION
165 # define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
166 # endif
167 #endif
168 
169 #if FMT_MSC_VER
170 # include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
171 #endif
172 
173 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
174 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
175 // MSVC intrinsics if the clz and clzll builtins are not available.
176 #if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL)
177 FMT_BEGIN_NAMESPACE
178 namespace detail {
179 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
180 # if !defined(__clang__)
181 # pragma intrinsic(_BitScanForward)
182 # pragma intrinsic(_BitScanReverse)
183 # if defined(_WIN64)
184 # pragma intrinsic(_BitScanForward64)
185 # pragma intrinsic(_BitScanReverse64)
186 # endif
187 # endif
188 
189 inline auto clz(uint32_t x) -> int {
190  unsigned long r = 0;
191  _BitScanReverse(&r, x);
192  FMT_ASSERT(x != 0, "");
193  // Static analysis complains about using uninitialized data
194  // "r", but the only way that can happen is if "x" is 0,
195  // which the callers guarantee to not happen.
196  FMT_MSC_WARNING(suppress : 6102)
197  return 31 ^ static_cast<int>(r);
198 }
199 # define FMT_BUILTIN_CLZ(n) detail::clz(n)
200 
201 inline auto clzll(uint64_t x) -> int {
202  unsigned long r = 0;
203 # ifdef _WIN64
204  _BitScanReverse64(&r, x);
205 # else
206  // Scan the high 32 bits.
207  if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) return 63 ^ (r + 32);
208  // Scan the low 32 bits.
209  _BitScanReverse(&r, static_cast<uint32_t>(x));
210 # endif
211  FMT_ASSERT(x != 0, "");
212  FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
213  return 63 ^ static_cast<int>(r);
214 }
215 # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
216 
217 inline auto ctz(uint32_t x) -> int {
218  unsigned long r = 0;
219  _BitScanForward(&r, x);
220  FMT_ASSERT(x != 0, "");
221  FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
222  return static_cast<int>(r);
223 }
224 # define FMT_BUILTIN_CTZ(n) detail::ctz(n)
225 
226 inline auto ctzll(uint64_t x) -> int {
227  unsigned long r = 0;
228  FMT_ASSERT(x != 0, "");
229  FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
230 # ifdef _WIN64
231  _BitScanForward64(&r, x);
232 # else
233  // Scan the low 32 bits.
234  if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);
235  // Scan the high 32 bits.
236  _BitScanForward(&r, static_cast<uint32_t>(x >> 32));
237  r += 32;
238 # endif
239  return static_cast<int>(r);
240 }
241 # define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
242 } // namespace detail
243 FMT_END_NAMESPACE
244 #endif
245 
246 #ifdef FMT_HEADER_ONLY
247 # define FMT_HEADER_ONLY_CONSTEXPR20 FMT_CONSTEXPR20
248 #else
249 # define FMT_HEADER_ONLY_CONSTEXPR20
250 #endif
251 
252 FMT_BEGIN_NAMESPACE
253 namespace detail {
254 
255 template <typename Streambuf> class formatbuf : public Streambuf {
256  private:
257  using char_type = typename Streambuf::char_type;
258  using streamsize = decltype(std::declval<Streambuf>().sputn(nullptr, 0));
259  using int_type = typename Streambuf::int_type;
260  using traits_type = typename Streambuf::traits_type;
261 
262  buffer<char_type>& buffer_;
263 
264  public:
265  explicit formatbuf(buffer<char_type>& buf) : buffer_(buf) {}
266 
267  protected:
268  // The put area is always empty. This makes the implementation simpler and has
269  // the advantage that the streambuf and the buffer are always in sync and
270  // sputc never writes into uninitialized memory. A disadvantage is that each
271  // call to sputc always results in a (virtual) call to overflow. There is no
272  // disadvantage here for sputn since this always results in a call to xsputn.
273 
274  auto overflow(int_type ch) -> int_type override {
275  if (!traits_type::eq_int_type(ch, traits_type::eof()))
276  buffer_.push_back(static_cast<char_type>(ch));
277  return ch;
278  }
279 
280  auto xsputn(const char_type* s, streamsize count) -> streamsize override {
281  buffer_.append(s, s + count);
282  return count;
283  }
284 };
285 
286 // Implementation of std::bit_cast for pre-C++20.
287 template <typename To, typename From>
288 FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To {
289  static_assert(sizeof(To) == sizeof(From), "size mismatch");
290 #ifdef __cpp_lib_bit_cast
291  if (is_constant_evaluated()) return std::bit_cast<To>(from);
292 #endif
293  auto to = To();
294  std::memcpy(&to, &from, sizeof(to));
295  return to;
296 }
297 
298 inline auto is_big_endian() -> bool {
299 #ifdef _WIN32
300  return false;
301 #elif defined(__BIG_ENDIAN__)
302  return true;
303 #elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__)
304  return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__;
305 #else
306  struct bytes {
307  char data[sizeof(int)];
308  };
309  return bit_cast<bytes>(1).data[0] == 0;
310 #endif
311 }
312 
313 // A fallback implementation of uintptr_t for systems that lack it.
315  unsigned char value[sizeof(void*)];
316 
317  fallback_uintptr() = default;
318  explicit fallback_uintptr(const void* p) {
319  *this = bit_cast<fallback_uintptr>(p);
320  if (const_check(is_big_endian())) {
321  for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
322  std::swap(value[i], value[j]);
323  }
324  }
325 };
326 #ifdef UINTPTR_MAX
327 using uintptr_t = ::uintptr_t;
328 inline auto to_uintptr(const void* p) -> uintptr_t {
329  return bit_cast<uintptr_t>(p);
330 }
331 #else
333 inline auto to_uintptr(const void* p) -> fallback_uintptr {
334  return fallback_uintptr(p);
335 }
336 #endif
337 
338 // Returns the largest possible value for type T. Same as
339 // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
340 template <typename T> constexpr auto max_value() -> T {
341  return (std::numeric_limits<T>::max)();
342 }
343 template <typename T> constexpr auto num_bits() -> int {
344  return std::numeric_limits<T>::digits;
345 }
346 // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
347 template <> constexpr auto num_bits<int128_t>() -> int { return 128; }
348 template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
349 template <> constexpr auto num_bits<fallback_uintptr>() -> int {
350  return static_cast<int>(sizeof(void*) *
351  std::numeric_limits<unsigned char>::digits);
352 }
353 
354 FMT_INLINE void assume(bool condition) {
355  (void)condition;
356 #if FMT_HAS_BUILTIN(__builtin_assume)
357  __builtin_assume(condition);
358 #endif
359 }
360 
361 // An approximation of iterator_t for pre-C++20 systems.
362 template <typename T>
363 using iterator_t = decltype(std::begin(std::declval<T&>()));
364 template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
365 
366 // A workaround for std::string not having mutable data() until C++17.
367 template <typename Char>
368 inline auto get_data(std::basic_string<Char>& s) -> Char* {
369  return &s[0];
370 }
371 template <typename Container>
372 inline auto get_data(Container& c) -> typename Container::value_type* {
373  return c.data();
374 }
375 
376 #if defined(_SECURE_SCL) && _SECURE_SCL
377 // Make a checked iterator to avoid MSVC warnings.
378 template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
379 template <typename T>
380 constexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> {
381  return {p, size};
382 }
383 #else
384 template <typename T> using checked_ptr = T*;
385 template <typename T> constexpr auto make_checked(T* p, size_t) -> T* {
386  return p;
387 }
388 #endif
389 
390 // Attempts to reserve space for n extra characters in the output range.
391 // Returns a pointer to the reserved range or a reference to it.
392 template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
393 #if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
394 __attribute__((no_sanitize("undefined")))
395 #endif
396 inline auto
397 reserve(std::back_insert_iterator<Container> it, size_t n)
398  -> checked_ptr<typename Container::value_type> {
399  Container& c = get_container(it);
400  size_t size = c.size();
401  c.resize(size + n);
402  return make_checked(get_data(c) + size, n);
403 }
404 
405 template <typename T>
406 inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> {
407  buffer<T>& buf = get_container(it);
408  buf.try_reserve(buf.size() + n);
409  return it;
410 }
411 
412 template <typename Iterator>
413 constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
414  return it;
415 }
416 
417 template <typename OutputIt>
418 using reserve_iterator =
419  remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
420 
421 template <typename T, typename OutputIt>
422 constexpr auto to_pointer(OutputIt, size_t) -> T* {
423  return nullptr;
424 }
425 template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
426  buffer<T>& buf = get_container(it);
427  auto size = buf.size();
428  if (buf.capacity() < size + n) return nullptr;
429  buf.try_resize(size + n);
430  return buf.data() + size;
431 }
432 
433 template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
434 inline auto base_iterator(std::back_insert_iterator<Container>& it,
435  checked_ptr<typename Container::value_type>)
436  -> std::back_insert_iterator<Container> {
437  return it;
438 }
439 
440 template <typename Iterator>
441 constexpr auto base_iterator(Iterator, Iterator it) -> Iterator {
442  return it;
443 }
444 
445 // <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
446 // instead (#1998).
447 template <typename OutputIt, typename Size, typename T>
448 FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)
449  -> OutputIt {
450  for (Size i = 0; i < count; ++i) *out++ = value;
451  return out;
452 }
453 template <typename T, typename Size>
454 FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
455  if (is_constant_evaluated()) {
456  return fill_n<T*, Size, T>(out, count, value);
457  }
458  std::memset(out, value, to_unsigned(count));
459  return out + count;
460 }
461 
462 #ifdef __cpp_char8_t
463 using char8_type = char8_t;
464 #else
465 enum char8_type : unsigned char {};
466 #endif
467 
468 template <typename OutChar, typename InputIt, typename OutputIt>
469 FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,
470  OutputIt out) -> OutputIt {
471  return copy_str<OutChar>(begin, end, out);
472 }
473 
474 // A public domain branchless UTF-8 decoder by Christopher Wellons:
475 // https://github.com/skeeto/branchless-utf8
476 /* Decode the next character, c, from s, reporting errors in e.
477  *
478  * Since this is a branchless decoder, four bytes will be read from the
479  * buffer regardless of the actual length of the next character. This
480  * means the buffer _must_ have at least three bytes of zero padding
481  * following the end of the data stream.
482  *
483  * Errors are reported in e, which will be non-zero if the parsed
484  * character was somehow invalid: invalid byte sequence, non-canonical
485  * encoding, or a surrogate half.
486  *
487  * The function returns a pointer to the next character. When an error
488  * occurs, this pointer will be a guess that depends on the particular
489  * error, but it will always advance at least one byte.
490  */
491 FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)
492  -> const char* {
493  constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
494  constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
495  constexpr const int shiftc[] = {0, 18, 12, 6, 0};
496  constexpr const int shifte[] = {0, 6, 4, 2, 0};
497 
498  int len = code_point_length(s);
499  const char* next = s + len;
500 
501  // Assume a four-byte character and load four bytes. Unused bits are
502  // shifted out.
503  *c = uint32_t(s[0] & masks[len]) << 18;
504  *c |= uint32_t(s[1] & 0x3f) << 12;
505  *c |= uint32_t(s[2] & 0x3f) << 6;
506  *c |= uint32_t(s[3] & 0x3f) << 0;
507  *c >>= shiftc[len];
508 
509  // Accumulate the various error conditions.
510  using uchar = unsigned char;
511  *e = (*c < mins[len]) << 6; // non-canonical encoding
512  *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
513  *e |= (*c > 0x10FFFF) << 8; // out of range?
514  *e |= (uchar(s[1]) & 0xc0) >> 2;
515  *e |= (uchar(s[2]) & 0xc0) >> 4;
516  *e |= uchar(s[3]) >> 6;
517  *e ^= 0x2a; // top two bits of each tail byte correct?
518  *e >>= shifte[len];
519 
520  return next;
521 }
522 
523 constexpr uint32_t invalid_code_point = ~uint32_t();
524 
525 // Invokes f(cp, sv) for every code point cp in s with sv being the string view
526 // corresponding to the code point. cp is invalid_code_point on error.
527 template <typename F>
528 FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) {
529  auto decode = [f](const char* buf_ptr, const char* ptr) {
530  auto cp = uint32_t();
531  auto error = 0;
532  auto end = utf8_decode(buf_ptr, &cp, &error);
533  bool result = f(error ? invalid_code_point : cp,
534  string_view(ptr, to_unsigned(end - buf_ptr)));
535  return result ? end : nullptr;
536  };
537  auto p = s.data();
538  const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
539  if (s.size() >= block_size) {
540  for (auto end = p + s.size() - block_size + 1; p < end;) {
541  p = decode(p, p);
542  if (!p) return;
543  }
544  }
545  if (auto num_chars_left = s.data() + s.size() - p) {
546  char buf[2 * block_size - 1] = {};
547  copy_str<char>(p, p + num_chars_left, buf);
548  const char* buf_ptr = buf;
549  do {
550  auto end = decode(buf_ptr, p);
551  if (!end) return;
552  p += end - buf_ptr;
553  buf_ptr = end;
554  } while (buf_ptr - buf < num_chars_left);
555  }
556 }
557 
558 template <typename Char>
559 inline auto compute_width(basic_string_view<Char> s) -> size_t {
560  return s.size();
561 }
562 
563 // Computes approximate display width of a UTF-8 string.
564 FMT_CONSTEXPR inline size_t compute_width(string_view s) {
565  size_t num_code_points = 0;
566  // It is not a lambda for compatibility with C++14.
567  struct count_code_points {
568  size_t* count;
569  FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool {
570  *count += detail::to_unsigned(
571  1 +
572  (cp >= 0x1100 &&
573  (cp <= 0x115f || // Hangul Jamo init. consonants
574  cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET
575  cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET
576  // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
577  (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
578  (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables
579  (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
580  (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms
581  (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms
582  (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
583  (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms
584  (cp >= 0x20000 && cp <= 0x2fffd) || // CJK
585  (cp >= 0x30000 && cp <= 0x3fffd) ||
586  // Miscellaneous Symbols and Pictographs + Emoticons:
587  (cp >= 0x1f300 && cp <= 0x1f64f) ||
588  // Supplemental Symbols and Pictographs:
589  (cp >= 0x1f900 && cp <= 0x1f9ff))));
590  return true;
591  }
592  };
593  for_each_codepoint(s, count_code_points{&num_code_points});
594  return num_code_points;
595 }
596 
597 inline auto compute_width(basic_string_view<char8_type> s) -> size_t {
598  return compute_width(basic_string_view<char>(
599  reinterpret_cast<const char*>(s.data()), s.size()));
600 }
601 
602 template <typename Char>
603 inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t {
604  size_t size = s.size();
605  return n < size ? n : size;
606 }
607 
608 // Calculates the index of the nth code point in a UTF-8 string.
609 inline auto code_point_index(basic_string_view<char8_type> s, size_t n)
610  -> size_t {
611  const char8_type* data = s.data();
612  size_t num_code_points = 0;
613  for (size_t i = 0, size = s.size(); i != size; ++i) {
614  if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i;
615  }
616  return s.size();
617 }
618 
619 template <typename T, bool = std::is_floating_point<T>::value>
620 struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
621  sizeof(T) <= sizeof(double)> {};
622 template <typename T> struct is_fast_float<T, false> : std::false_type {};
623 
624 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
625 # define FMT_USE_FULL_CACHE_DRAGONBOX 0
626 #endif
627 
628 template <typename T>
629 template <typename U>
630 void buffer<T>::append(const U* begin, const U* end) {
631  while (begin != end) {
632  auto count = to_unsigned(end - begin);
633  try_reserve(size_ + count);
634  auto free_cap = capacity_ - size_;
635  if (free_cap < count) count = free_cap;
636  std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));
637  size_ += count;
638  begin += count;
639  }
640 }
641 
642 template <typename T, typename Enable = void>
643 struct is_locale : std::false_type {};
644 template <typename T>
645 struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
646 } // namespace detail
647 
648 FMT_MODULE_EXPORT_BEGIN
649 
650 // The number of characters to store in the basic_memory_buffer object itself
651 // to avoid dynamic memory allocation.
652 enum { inline_buffer_size = 500 };
653 
675 template <typename T, size_t SIZE = inline_buffer_size,
676  typename Allocator = std::allocator<T>>
677 class basic_memory_buffer final : public detail::buffer<T> {
678  private:
679  T store_[SIZE];
680 
681  // Don't inherit from Allocator avoid generating type_info for it.
682  Allocator alloc_;
683 
684  // Deallocate memory allocated by the buffer.
685  FMT_CONSTEXPR20 void deallocate() {
686  T* data = this->data();
687  if (data != store_) alloc_.deallocate(data, this->capacity());
688  }
689 
690  protected:
691  FMT_CONSTEXPR20 void grow(size_t size) override;
692 
693  public:
694  using value_type = T;
695  using const_reference = const T&;
696 
697  FMT_CONSTEXPR20 explicit basic_memory_buffer(
698  const Allocator& alloc = Allocator())
699  : alloc_(alloc) {
700  this->set(store_, SIZE);
701  if (detail::is_constant_evaluated()) {
702  detail::fill_n(store_, SIZE, T{});
703  }
704  }
705  FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); }
706 
707  private:
708  // Move data from other to this buffer.
709  FMT_CONSTEXPR20 void move(basic_memory_buffer& other) {
710  alloc_ = std::move(other.alloc_);
711  T* data = other.data();
712  size_t size = other.size(), capacity = other.capacity();
713  if (data == other.store_) {
714  this->set(store_, capacity);
715  if (detail::is_constant_evaluated()) {
716  detail::copy_str<T>(other.store_, other.store_ + size,
717  detail::make_checked(store_, capacity));
718  } else {
719  std::uninitialized_copy(other.store_, other.store_ + size,
720  detail::make_checked(store_, capacity));
721  }
722  } else {
723  this->set(data, capacity);
724  // Set pointer to the inline array so that delete is not called
725  // when deallocating.
726  other.set(other.store_, 0);
727  }
728  this->resize(size);
729  }
730 
731  public:
738  FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other)
739  FMT_NOEXCEPT {
740  move(other);
741  }
742 
748  auto operator=(basic_memory_buffer&& other) FMT_NOEXCEPT
749  -> basic_memory_buffer& {
750  FMT_ASSERT(this != &other, "");
751  deallocate();
752  move(other);
753  return *this;
754  }
755 
756  // Returns a copy of the allocator associated with this buffer.
757  auto get_allocator() const -> Allocator { return alloc_; }
758 
763  FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); }
764 
766  void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
767 
768  // Directly append data into the buffer
769  using detail::buffer<T>::append;
770  template <typename ContiguousRange>
771  void append(const ContiguousRange& range) {
772  append(range.data(), range.data() + range.size());
773  }
774 };
775 
776 template <typename T, size_t SIZE, typename Allocator>
778  size_t size) {
779 #ifdef FMT_FUZZ
780  if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
781 #endif
782  const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
783  size_t old_capacity = this->capacity();
784  size_t new_capacity = old_capacity + old_capacity / 2;
785  if (size > new_capacity)
786  new_capacity = size;
787  else if (new_capacity > max_size)
788  new_capacity = size > max_size ? size : max_size;
789  T* old_data = this->data();
790  T* new_data =
791  std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
792  // The following code doesn't throw, so the raw pointer above doesn't leak.
793  std::uninitialized_copy(old_data, old_data + this->size(),
794  detail::make_checked(new_data, new_capacity));
795  this->set(new_data, new_capacity);
796  // deallocate must not throw according to the standard, but even if it does,
797  // the buffer already uses the new storage and will deallocate it in
798  // destructor.
799  if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
800 }
801 
803 
804 template <typename T, size_t SIZE, typename Allocator>
805 struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
806 };
807 
808 namespace detail {
809 FMT_API void print(std::FILE*, string_view);
810 }
811 
813 FMT_CLASS_API
814 class FMT_API format_error : public std::runtime_error {
815  public:
816  explicit format_error(const char* message) : std::runtime_error(message) {}
817  explicit format_error(const std::string& message)
818  : std::runtime_error(message) {}
819  format_error(const format_error&) = default;
820  format_error& operator=(const format_error&) = default;
821  format_error(format_error&&) = default;
822  format_error& operator=(format_error&&) = default;
823  ~format_error() FMT_NOEXCEPT override FMT_MSC_DEFAULT;
824 };
825 
834 template <typename... Args, typename S, typename Char = char_t<S>>
835 FMT_INLINE auto make_args_checked(const S& fmt,
836  const remove_reference_t<Args>&... args)
837  -> format_arg_store<buffer_context<Char>, remove_reference_t<Args>...> {
838  static_assert(
839  detail::count<(
840  std::is_base_of<detail::view, remove_reference_t<Args>>::value &&
841  std::is_reference<Args>::value)...>() == 0,
842  "passing views as lvalues is disallowed");
843  detail::check_format_string<Args...>(fmt);
844  return {args...};
845 }
846 
847 // compile-time support
848 namespace detail_exported {
849 #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
850 template <typename Char, size_t N> struct fixed_string {
851  constexpr fixed_string(const Char (&str)[N]) {
852  detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
853  str + N, data);
854  }
855  Char data[N]{};
856 };
857 #endif
858 
859 // Converts a compile-time string to basic_string_view.
860 template <typename Char, size_t N>
861 constexpr auto compile_string_to_view(const Char (&s)[N])
863  // Remove trailing NUL character if needed. Won't be present if this is used
864  // with a raw character array (i.e. not defined as a string).
865  return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
866 }
867 template <typename Char>
868 constexpr auto compile_string_to_view(detail::std_string_view<Char> s)
870  return {s.data(), s.size()};
871 }
872 } // namespace detail_exported
873 
874 FMT_BEGIN_DETAIL_NAMESPACE
875 
876 template <typename T> struct is_integral : std::is_integral<T> {};
877 template <> struct is_integral<int128_t> : std::true_type {};
878 template <> struct is_integral<uint128_t> : std::true_type {};
879 
880 template <typename T>
881 using is_signed =
882  std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
883  std::is_same<T, int128_t>::value>;
884 
885 // Returns true if value is negative, false otherwise.
886 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
887 template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
888 FMT_CONSTEXPR auto is_negative(T value) -> bool {
889  return value < 0;
890 }
891 template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
892 FMT_CONSTEXPR auto is_negative(T) -> bool {
893  return false;
894 }
895 
896 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
897 FMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t {
898  return (std::is_same<T, float>::value && FMT_USE_FLOAT) ||
899  (std::is_same<T, double>::value && FMT_USE_DOUBLE) ||
900  (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE);
901 }
902 
903 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
904 // represent all values of an integral type T.
905 template <typename T>
906 using uint32_or_64_or_128_t =
907  conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS,
908  uint32_t,
909  conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
910 template <typename T>
911 using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>;
912 
913 #define FMT_POWERS_OF_10(factor) \
914  factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
915  (factor)*1000000, (factor)*10000000, (factor)*100000000, \
916  (factor)*1000000000
917 
918 // Converts value in the range [0, 100) to a string.
919 constexpr const char* digits2(size_t value) {
920  // GCC generates slightly better code when value is pointer-size.
921  return &"0001020304050607080910111213141516171819"
922  "2021222324252627282930313233343536373839"
923  "4041424344454647484950515253545556575859"
924  "6061626364656667686970717273747576777879"
925  "8081828384858687888990919293949596979899"[value * 2];
926 }
927 
928 // Sign is a template parameter to workaround a bug in gcc 4.8.
929 template <typename Char, typename Sign> constexpr Char sign(Sign s) {
930 #if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604
931  static_assert(std::is_same<Sign, sign_t>::value, "");
932 #endif
933  return static_cast<Char>("\0-+ "[s]);
934 }
935 
936 template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
937  int count = 1;
938  for (;;) {
939  // Integer division is slow so do it for a group of four digits instead
940  // of for every digit. The idea comes from the talk by Alexandrescu
941  // "Three Optimization Tips for C++". See speed-test for a comparison.
942  if (n < 10) return count;
943  if (n < 100) return count + 1;
944  if (n < 1000) return count + 2;
945  if (n < 10000) return count + 3;
946  n /= 10000u;
947  count += 4;
948  }
949 }
950 #if FMT_USE_INT128
951 FMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int {
952  return count_digits_fallback(n);
953 }
954 #endif
955 
956 #ifdef FMT_BUILTIN_CLZLL
957 // It is a separate function rather than a part of count_digits to workaround
958 // the lack of static constexpr in constexpr functions.
959 inline auto do_count_digits(uint64_t n) -> int {
960  // This has comparable performance to the version by Kendall Willets
961  // (https://github.com/fmtlib/format-benchmark/blob/master/digits10)
962  // but uses smaller tables.
963  // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
964  static constexpr uint8_t bsr2log10[] = {
965  1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
966  6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
967  10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
968  15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
969  auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
970  static constexpr const uint64_t zero_or_powers_of_10[] = {
971  0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
972  10000000000000000000ULL};
973  return t - (n < zero_or_powers_of_10[t]);
974 }
975 #endif
976 
977 // Returns the number of decimal digits in n. Leading zeros are not counted
978 // except for n == 0 in which case count_digits returns 1.
979 FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
980 #ifdef FMT_BUILTIN_CLZLL
981  if (!is_constant_evaluated()) {
982  return do_count_digits(n);
983  }
984 #endif
985  return count_digits_fallback(n);
986 }
987 
988 // Counts the number of digits in n. BITS = log2(radix).
989 template <int BITS, typename UInt>
990 FMT_CONSTEXPR auto count_digits(UInt n) -> int {
991 #ifdef FMT_BUILTIN_CLZ
992  if (num_bits<UInt>() == 32)
993  return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
994 #endif
995  // Lambda avoids unreachable code warnings from NVHPC.
996  return [](UInt m) {
997  int num_digits = 0;
998  do {
999  ++num_digits;
1000  } while ((m >>= BITS) != 0);
1001  return num_digits;
1002  }(n);
1003 }
1004 
1005 template <> auto count_digits<4>(detail::fallback_uintptr n) -> int;
1006 
1007 #ifdef FMT_BUILTIN_CLZ
1008 // It is a separate function rather than a part of count_digits to workaround
1009 // the lack of static constexpr in constexpr functions.
1010 FMT_INLINE auto do_count_digits(uint32_t n) -> int {
1011 // An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
1012 // This increments the upper 32 bits (log10(T) - 1) when >= T is added.
1013 # define FMT_INC(T) (((sizeof(# T) - 1ull) << 32) - T)
1014  static constexpr uint64_t table[] = {
1015  FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
1016  FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
1017  FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
1018  FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
1019  FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
1020  FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
1021  FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
1022  FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
1023  FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
1024  FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
1025  FMT_INC(1000000000), FMT_INC(1000000000) // 4B
1026  };
1027  auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31];
1028  return static_cast<int>((n + inc) >> 32);
1029 }
1030 #endif
1031 
1032 // Optional version of count_digits for better performance on 32-bit platforms.
1033 FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
1034 #ifdef FMT_BUILTIN_CLZ
1035  if (!is_constant_evaluated()) {
1036  return do_count_digits(n);
1037  }
1038 #endif
1039  return count_digits_fallback(n);
1040 }
1041 
1042 template <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int {
1043  return std::numeric_limits<Int>::digits10;
1044 }
1045 template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int {
1046  return 38;
1047 }
1048 template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int {
1049  return 38;
1050 }
1051 
1052 template <typename Char> struct thousands_sep_result {
1053  std::string grouping;
1054  Char thousands_sep;
1055 };
1056 
1057 template <typename Char>
1058 FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;
1059 template <typename Char>
1060 inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> {
1061  auto result = thousands_sep_impl<char>(loc);
1062  return {result.grouping, Char(result.thousands_sep)};
1063 }
1064 template <>
1065 inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {
1066  return thousands_sep_impl<wchar_t>(loc);
1067 }
1068 
1069 template <typename Char>
1070 FMT_API auto decimal_point_impl(locale_ref loc) -> Char;
1071 template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
1072  return Char(decimal_point_impl<char>(loc));
1073 }
1074 template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
1075  return decimal_point_impl<wchar_t>(loc);
1076 }
1077 
1078 // Compares two characters for equality.
1079 template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
1080  return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1081 }
1082 inline auto equal2(const char* lhs, const char* rhs) -> bool {
1083  return memcmp(lhs, rhs, 2) == 0;
1084 }
1085 
1086 // Copies two characters from src to dst.
1087 template <typename Char>
1088 FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) {
1089  if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) {
1090  memcpy(dst, src, 2);
1091  return;
1092  }
1093  *dst++ = static_cast<Char>(*src++);
1094  *dst = static_cast<Char>(*src);
1095 }
1096 
1097 template <typename Iterator> struct format_decimal_result {
1098  Iterator begin;
1099  Iterator end;
1100 };
1101 
1102 // Formats a decimal unsigned integer value writing into out pointing to a
1103 // buffer of specified size. The caller must ensure that the buffer is large
1104 // enough.
1105 template <typename Char, typename UInt>
1106 FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)
1108  FMT_ASSERT(size >= count_digits(value), "invalid digit count");
1109  out += size;
1110  Char* end = out;
1111  while (value >= 100) {
1112  // Integer division is slow so do it for a group of two digits instead
1113  // of for every digit. The idea comes from the talk by Alexandrescu
1114  // "Three Optimization Tips for C++". See speed-test for a comparison.
1115  out -= 2;
1116  copy2(out, digits2(static_cast<size_t>(value % 100)));
1117  value /= 100;
1118  }
1119  if (value < 10) {
1120  *--out = static_cast<Char>('0' + value);
1121  return {out, end};
1122  }
1123  out -= 2;
1124  copy2(out, digits2(static_cast<size_t>(value)));
1125  return {out, end};
1126 }
1127 
1128 template <typename Char, typename UInt, typename Iterator,
1129  FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
1130 inline auto format_decimal(Iterator out, UInt value, int size)
1132  // Buffer is large enough to hold all digits (digits10 + 1).
1133  Char buffer[digits10<UInt>() + 1];
1134  auto end = format_decimal(buffer, value, size).end;
1135  return {out, detail::copy_str_noinline<Char>(buffer, end, out)};
1136 }
1137 
1138 template <unsigned BASE_BITS, typename Char, typename UInt>
1139 FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,
1140  bool upper = false) -> Char* {
1141  buffer += num_digits;
1142  Char* end = buffer;
1143  do {
1144  const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef";
1145  unsigned digit = (value & ((1 << BASE_BITS) - 1));
1146  *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
1147  : digits[digit]);
1148  } while ((value >>= BASE_BITS) != 0);
1149  return end;
1150 }
1151 
1152 template <unsigned BASE_BITS, typename Char>
1153 auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
1154  bool = false) -> Char* {
1155  auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
1156  int start = (num_digits + char_digits - 1) / char_digits - 1;
1157  if (int start_digits = num_digits % char_digits) {
1158  unsigned value = n.value[start--];
1159  buffer = format_uint<BASE_BITS>(buffer, value, start_digits);
1160  }
1161  for (; start >= 0; --start) {
1162  unsigned value = n.value[start];
1163  buffer += char_digits;
1164  auto p = buffer;
1165  for (int i = 0; i < char_digits; ++i) {
1166  unsigned digit = (value & ((1 << BASE_BITS) - 1));
1167  *--p = static_cast<Char>("0123456789abcdef"[digit]);
1168  value >>= BASE_BITS;
1169  }
1170  }
1171  return buffer;
1172 }
1173 
1174 template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
1175 inline auto format_uint(It out, UInt value, int num_digits, bool upper = false)
1176  -> It {
1177  if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1178  format_uint<BASE_BITS>(ptr, value, num_digits, upper);
1179  return out;
1180  }
1181  // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1182  char buffer[num_bits<UInt>() / BASE_BITS + 1];
1183  format_uint<BASE_BITS>(buffer, value, num_digits, upper);
1184  return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out);
1185 }
1186 
1187 // A converter from UTF-8 to UTF-16.
1189  private:
1191 
1192  public:
1193  FMT_API explicit utf8_to_utf16(string_view s);
1194  operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
1195  auto size() const -> size_t { return buffer_.size() - 1; }
1196  auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1197  auto str() const -> std::wstring { return {&buffer_[0], size()}; }
1198 };
1199 
1200 namespace dragonbox {
1201 
1202 // Type-specific information that Dragonbox uses.
1203 template <class T> struct float_info;
1204 
1205 template <> struct float_info<float> {
1206  using carrier_uint = uint32_t;
1207  static const int significand_bits = 23;
1208  static const int exponent_bits = 8;
1209  static const int min_exponent = -126;
1210  static const int max_exponent = 127;
1211  static const int exponent_bias = -127;
1212  static const int decimal_digits = 9;
1213  static const int kappa = 1;
1214  static const int big_divisor = 100;
1215  static const int small_divisor = 10;
1216  static const int min_k = -31;
1217  static const int max_k = 46;
1218  static const int cache_bits = 64;
1219  static const int divisibility_check_by_5_threshold = 39;
1220  static const int case_fc_pm_half_lower_threshold = -1;
1221  static const int case_fc_pm_half_upper_threshold = 6;
1222  static const int case_fc_lower_threshold = -2;
1223  static const int case_fc_upper_threshold = 6;
1224  static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1225  static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1226  static const int shorter_interval_tie_lower_threshold = -35;
1227  static const int shorter_interval_tie_upper_threshold = -35;
1228  static const int max_trailing_zeros = 7;
1229 };
1230 
1231 template <> struct float_info<double> {
1232  using carrier_uint = uint64_t;
1233  static const int significand_bits = 52;
1234  static const int exponent_bits = 11;
1235  static const int min_exponent = -1022;
1236  static const int max_exponent = 1023;
1237  static const int exponent_bias = -1023;
1238  static const int decimal_digits = 17;
1239  static const int kappa = 2;
1240  static const int big_divisor = 1000;
1241  static const int small_divisor = 100;
1242  static const int min_k = -292;
1243  static const int max_k = 326;
1244  static const int cache_bits = 128;
1245  static const int divisibility_check_by_5_threshold = 86;
1246  static const int case_fc_pm_half_lower_threshold = -2;
1247  static const int case_fc_pm_half_upper_threshold = 9;
1248  static const int case_fc_lower_threshold = -4;
1249  static const int case_fc_upper_threshold = 9;
1250  static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1251  static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1252  static const int shorter_interval_tie_lower_threshold = -77;
1253  static const int shorter_interval_tie_upper_threshold = -77;
1254  static const int max_trailing_zeros = 16;
1255 };
1256 
1257 template <typename T> struct decimal_fp {
1258  using significand_type = typename float_info<T>::carrier_uint;
1259  significand_type significand;
1260  int exponent;
1261 };
1262 
1263 template <typename T>
1264 FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>;
1265 } // namespace dragonbox
1266 
1267 template <typename T>
1268 constexpr auto exponent_mask() ->
1270  using uint = typename dragonbox::float_info<T>::carrier_uint;
1271  return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)
1273 }
1274 
1275 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1276 template <typename Char, typename It>
1277 FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It {
1278  FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
1279  if (exp < 0) {
1280  *it++ = static_cast<Char>('-');
1281  exp = -exp;
1282  } else {
1283  *it++ = static_cast<Char>('+');
1284  }
1285  if (exp >= 100) {
1286  const char* top = digits2(to_unsigned(exp / 100));
1287  if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
1288  *it++ = static_cast<Char>(top[1]);
1289  exp %= 100;
1290  }
1291  const char* d = digits2(to_unsigned(exp));
1292  *it++ = static_cast<Char>(d[0]);
1293  *it++ = static_cast<Char>(d[1]);
1294  return it;
1295 }
1296 
1297 template <typename T>
1298 FMT_HEADER_ONLY_CONSTEXPR20 auto format_float(T value, int precision,
1299  float_specs specs,
1300  buffer<char>& buf) -> int;
1301 
1302 // Formats a floating-point number with snprintf.
1303 template <typename T>
1304 auto snprintf_float(T value, int precision, float_specs specs,
1305  buffer<char>& buf) -> int;
1306 
1307 template <typename T> constexpr auto promote_float(T value) -> T {
1308  return value;
1309 }
1310 constexpr auto promote_float(float value) -> double {
1311  return static_cast<double>(value);
1312 }
1313 
1314 template <typename OutputIt, typename Char>
1315 FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,
1316  const fill_t<Char>& fill) -> OutputIt {
1317  auto fill_size = fill.size();
1318  if (fill_size == 1) return detail::fill_n(it, n, fill[0]);
1319  auto data = fill.data();
1320  for (size_t i = 0; i < n; ++i)
1321  it = copy_str<Char>(data, data + fill_size, it);
1322  return it;
1323 }
1324 
1325 // Writes the output of f, padded according to format specifications in specs.
1326 // size: output size in code units.
1327 // width: output display width in (terminal) column positions.
1328 template <align::type align = align::left, typename OutputIt, typename Char,
1329  typename F>
1330 FMT_CONSTEXPR auto write_padded(OutputIt out,
1331  const basic_format_specs<Char>& specs,
1332  size_t size, size_t width, F&& f) -> OutputIt {
1333  static_assert(align == align::left || align == align::right, "");
1334  unsigned spec_width = to_unsigned(specs.width);
1335  size_t padding = spec_width > width ? spec_width - width : 0;
1336  // Shifts are encoded as string literals because static constexpr is not
1337  // supported in constexpr functions.
1338  auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01";
1339  size_t left_padding = padding >> shifts[specs.align];
1340  size_t right_padding = padding - left_padding;
1341  auto it = reserve(out, size + padding * specs.fill.size());
1342  if (left_padding != 0) it = fill(it, left_padding, specs.fill);
1343  it = f(it);
1344  if (right_padding != 0) it = fill(it, right_padding, specs.fill);
1345  return base_iterator(out, it);
1346 }
1347 
1348 template <align::type align = align::left, typename OutputIt, typename Char,
1349  typename F>
1350 constexpr auto write_padded(OutputIt out, const basic_format_specs<Char>& specs,
1351  size_t size, F&& f) -> OutputIt {
1352  return write_padded<align>(out, specs, size, size, f);
1353 }
1354 
1355 template <align::type align = align::left, typename Char, typename OutputIt>
1356 FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes,
1357  const basic_format_specs<Char>& specs)
1358  -> OutputIt {
1359  return write_padded<align>(
1360  out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
1361  const char* data = bytes.data();
1362  return copy_str<Char>(data, data + bytes.size(), it);
1363  });
1364 }
1365 
1366 template <typename Char, typename OutputIt, typename UIntPtr>
1367 auto write_ptr(OutputIt out, UIntPtr value,
1368  const basic_format_specs<Char>* specs) -> OutputIt {
1369  int num_digits = count_digits<4>(value);
1370  auto size = to_unsigned(num_digits) + size_t(2);
1371  auto write = [=](reserve_iterator<OutputIt> it) {
1372  *it++ = static_cast<Char>('0');
1373  *it++ = static_cast<Char>('x');
1374  return format_uint<4, Char>(it, value, num_digits);
1375  };
1376  return specs ? write_padded<align::right>(out, *specs, size, write)
1377  : base_iterator(out, write(reserve(out, size)));
1378 }
1379 
1380 template <typename Char, typename OutputIt>
1381 FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
1382  const basic_format_specs<Char>& specs)
1383  -> OutputIt {
1384  return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
1385  *it++ = value;
1386  return it;
1387  });
1388 }
1389 template <typename Char, typename OutputIt>
1390 FMT_CONSTEXPR auto write(OutputIt out, Char value,
1391  const basic_format_specs<Char>& specs,
1392  locale_ref loc = {}) -> OutputIt {
1393  return check_char_specs(specs)
1394  ? write_char(out, value, specs)
1395  : write(out, static_cast<int>(value), specs, loc);
1396 }
1397 
1398 // Data for write_int that doesn't depend on output iterator type. It is used to
1399 // avoid template code bloat.
1400 template <typename Char> struct write_int_data {
1401  size_t size;
1402  size_t padding;
1403 
1404  FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix,
1405  const basic_format_specs<Char>& specs)
1406  : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
1407  if (specs.align == align::numeric) {
1408  auto width = to_unsigned(specs.width);
1409  if (width > size) {
1410  padding = width - size;
1411  size = width;
1412  }
1413  } else if (specs.precision > num_digits) {
1414  size = (prefix >> 24) + to_unsigned(specs.precision);
1415  padding = to_unsigned(specs.precision - num_digits);
1416  }
1417  }
1418 };
1419 
1420 // Writes an integer in the format
1421 // <left-padding><prefix><numeric-padding><digits><right-padding>
1422 // where <digits> are written by write_digits(it).
1423 // prefix contains chars in three lower bytes and the size in the fourth byte.
1424 template <typename OutputIt, typename Char, typename W>
1425 FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits,
1426  unsigned prefix,
1427  const basic_format_specs<Char>& specs,
1428  W write_digits) -> OutputIt {
1429  // Slightly faster check for specs.width == 0 && specs.precision == -1.
1430  if ((specs.width | (specs.precision + 1)) == 0) {
1431  auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
1432  if (prefix != 0) {
1433  for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1434  *it++ = static_cast<Char>(p & 0xff);
1435  }
1436  return base_iterator(out, write_digits(it));
1437  }
1438  auto data = write_int_data<Char>(num_digits, prefix, specs);
1439  return write_padded<align::right>(
1440  out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
1441  for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1442  *it++ = static_cast<Char>(p & 0xff);
1443  it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
1444  return write_digits(it);
1445  });
1446 }
1447 
1448 template <typename Char> class digit_grouping {
1449  private:
1451 
1452  struct next_state {
1453  std::string::const_iterator group;
1454  int pos;
1455  };
1456  next_state initial_state() const { return {sep_.grouping.begin(), 0}; }
1457 
1458  // Returns the next digit group separator position.
1459  int next(next_state& state) const {
1460  if (!sep_.thousands_sep) return max_value<int>();
1461  if (state.group == sep_.grouping.end())
1462  return state.pos += sep_.grouping.back();
1463  if (*state.group <= 0 || *state.group == max_value<char>())
1464  return max_value<int>();
1465  state.pos += *state.group++;
1466  return state.pos;
1467  }
1468 
1469  public:
1470  explicit digit_grouping(locale_ref loc, bool localized = true) {
1471  if (localized)
1472  sep_ = thousands_sep<Char>(loc);
1473  else
1474  sep_.thousands_sep = Char();
1475  }
1476  explicit digit_grouping(thousands_sep_result<Char> sep) : sep_(sep) {}
1477 
1478  Char separator() const { return sep_.thousands_sep; }
1479 
1480  int count_separators(int num_digits) const {
1481  int count = 0;
1482  auto state = initial_state();
1483  while (num_digits > next(state)) ++count;
1484  return count;
1485  }
1486 
1487  // Applies grouping to digits and write the output to out.
1488  template <typename Out, typename C>
1489  Out apply(Out out, basic_string_view<C> digits) const {
1490  auto num_digits = static_cast<int>(digits.size());
1491  auto separators = basic_memory_buffer<int>();
1492  separators.push_back(0);
1493  auto state = initial_state();
1494  while (int i = next(state)) {
1495  if (i >= num_digits) break;
1496  separators.push_back(i);
1497  }
1498  for (int i = 0, sep_index = static_cast<int>(separators.size() - 1);
1499  i < num_digits; ++i) {
1500  if (num_digits - i == separators[sep_index]) {
1501  *out++ = separator();
1502  --sep_index;
1503  }
1504  *out++ = static_cast<Char>(digits[to_unsigned(i)]);
1505  }
1506  return out;
1507  }
1508 };
1509 
1510 template <typename OutputIt, typename UInt, typename Char>
1511 auto write_int_localized(OutputIt out, UInt value, unsigned prefix,
1512  const basic_format_specs<Char>& specs,
1513  const digit_grouping<Char>& grouping) -> OutputIt {
1514  static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
1515  int num_digits = count_digits(value);
1516  char digits[40];
1517  format_decimal(digits, value, num_digits);
1518  unsigned size = to_unsigned((prefix != 0 ? 1 : 0) + num_digits +
1519  grouping.count_separators(num_digits));
1520  return write_padded<align::right>(
1521  out, specs, size, size, [&](reserve_iterator<OutputIt> it) {
1522  if (prefix != 0) *it++ = static_cast<Char>(prefix);
1523  return grouping.apply(it, string_view(digits, to_unsigned(num_digits)));
1524  });
1525 }
1526 
1527 template <typename OutputIt, typename UInt, typename Char>
1528 auto write_int_localized(OutputIt& out, UInt value, unsigned prefix,
1529  const basic_format_specs<Char>& specs, locale_ref loc)
1530  -> bool {
1531  auto grouping = digit_grouping<Char>(loc);
1532  out = write_int_localized(out, value, prefix, specs, grouping);
1533  return true;
1534 }
1535 
1536 FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
1537  prefix |= prefix != 0 ? value << 8 : value;
1538  prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
1539 }
1540 
1541 template <typename UInt> struct write_int_arg {
1542  UInt abs_value;
1543  unsigned prefix;
1544 };
1545 
1546 template <typename T>
1547 FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign)
1549  auto prefix = 0u;
1550  auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
1551  if (is_negative(value)) {
1552  prefix = 0x01000000 | '-';
1553  abs_value = 0 - abs_value;
1554  } else {
1555  constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
1556  0x1000000u | ' '};
1557  prefix = prefixes[sign];
1558  }
1559  return {abs_value, prefix};
1560 }
1561 
1562 template <typename Char, typename OutputIt, typename T>
1563 FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg,
1564  const basic_format_specs<Char>& specs,
1565  locale_ref loc) -> OutputIt {
1566  static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, "");
1567  auto abs_value = arg.abs_value;
1568  auto prefix = arg.prefix;
1569  switch (specs.type) {
1570  case presentation_type::none:
1571  case presentation_type::dec: {
1572  if (specs.localized &&
1573  write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),
1574  prefix, specs, loc)) {
1575  return out;
1576  }
1577  auto num_digits = count_digits(abs_value);
1578  return write_int(
1579  out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
1580  return format_decimal<Char>(it, abs_value, num_digits).end;
1581  });
1582  }
1583  case presentation_type::hex_lower:
1584  case presentation_type::hex_upper: {
1585  bool upper = specs.type == presentation_type::hex_upper;
1586  if (specs.alt)
1587  prefix_append(prefix, unsigned(upper ? 'X' : 'x') << 8 | '0');
1588  int num_digits = count_digits<4>(abs_value);
1589  return write_int(
1590  out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
1591  return format_uint<4, Char>(it, abs_value, num_digits, upper);
1592  });
1593  }
1594  case presentation_type::bin_lower:
1595  case presentation_type::bin_upper: {
1596  bool upper = specs.type == presentation_type::bin_upper;
1597  if (specs.alt)
1598  prefix_append(prefix, unsigned(upper ? 'B' : 'b') << 8 | '0');
1599  int num_digits = count_digits<1>(abs_value);
1600  return write_int(out, num_digits, prefix, specs,
1601  [=](reserve_iterator<OutputIt> it) {
1602  return format_uint<1, Char>(it, abs_value, num_digits);
1603  });
1604  }
1605  case presentation_type::oct: {
1606  int num_digits = count_digits<3>(abs_value);
1607  // Octal prefix '0' is counted as a digit, so only add it if precision
1608  // is not greater than the number of digits.
1609  if (specs.alt && specs.precision <= num_digits && abs_value != 0)
1610  prefix_append(prefix, '0');
1611  return write_int(out, num_digits, prefix, specs,
1612  [=](reserve_iterator<OutputIt> it) {
1613  return format_uint<3, Char>(it, abs_value, num_digits);
1614  });
1615  }
1616  case presentation_type::chr:
1617  return write_char(out, static_cast<Char>(abs_value), specs);
1618  default:
1619  throw_format_error("invalid type specifier");
1620  }
1621  return out;
1622 }
1623 template <typename Char, typename OutputIt, typename T>
1624 FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(
1625  OutputIt out, write_int_arg<T> arg, const basic_format_specs<Char>& specs,
1626  locale_ref loc) -> OutputIt {
1627  return write_int(out, arg, specs, loc);
1628 }
1629 template <typename Char, typename OutputIt, typename T,
1630  FMT_ENABLE_IF(is_integral<T>::value &&
1631  !std::is_same<T, bool>::value &&
1632  std::is_same<OutputIt, buffer_appender<Char>>::value)>
1633 FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
1634  const basic_format_specs<Char>& specs,
1635  locale_ref loc) -> OutputIt {
1636  return write_int_noinline(out, make_write_int_arg(value, specs.sign), specs,
1637  loc);
1638 }
1639 // An inlined version of write used in format string compilation.
1640 template <typename Char, typename OutputIt, typename T,
1641  FMT_ENABLE_IF(is_integral<T>::value &&
1642  !std::is_same<T, bool>::value &&
1643  !std::is_same<OutputIt, buffer_appender<Char>>::value)>
1644 FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value,
1645  const basic_format_specs<Char>& specs,
1646  locale_ref loc) -> OutputIt {
1647  return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
1648 }
1649 
1650 template <typename Char, typename OutputIt>
1651 FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s,
1652  const basic_format_specs<Char>& specs) -> OutputIt {
1653  auto data = s.data();
1654  auto size = s.size();
1655  if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
1656  size = code_point_index(s, to_unsigned(specs.precision));
1657  auto width =
1658  specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0;
1659  return write_padded(out, specs, size, width,
1660  [=](reserve_iterator<OutputIt> it) {
1661  return copy_str<Char>(data, data + size, it);
1662  });
1663 }
1664 template <typename Char, typename OutputIt>
1665 FMT_CONSTEXPR auto write(OutputIt out,
1666  basic_string_view<type_identity_t<Char>> s,
1667  const basic_format_specs<Char>& specs, locale_ref)
1668  -> OutputIt {
1669  check_string_type_spec(specs.type);
1670  return write(out, s, specs);
1671 }
1672 template <typename Char, typename OutputIt>
1673 FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
1674  const basic_format_specs<Char>& specs, locale_ref)
1675  -> OutputIt {
1676  return check_cstring_type_spec(specs.type)
1677  ? write(out, basic_string_view<Char>(s), specs, {})
1678  : write_ptr<Char>(out, to_uintptr(s), &specs);
1679 }
1680 
1681 template <typename Char, typename OutputIt>
1682 FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isinf,
1684  const float_specs& fspecs) -> OutputIt {
1685  auto str =
1686  isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
1687  constexpr size_t str_size = 3;
1688  auto sign = fspecs.sign;
1689  auto size = str_size + (sign ? 1 : 0);
1690  // Replace '0'-padding with space for non-finite values.
1691  const bool is_zero_fill =
1692  specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0');
1693  if (is_zero_fill) specs.fill[0] = static_cast<Char>(' ');
1694  return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
1695  if (sign) *it++ = detail::sign<Char>(sign);
1696  return copy_str<Char>(str, str + str_size, it);
1697  });
1698 }
1699 
1700 // A decimal floating-point number significand * pow(10, exp).
1702  const char* significand;
1703  int significand_size;
1704  int exponent;
1705 };
1706 
1707 constexpr auto get_significand_size(const big_decimal_fp& fp) -> int {
1708  return fp.significand_size;
1709 }
1710 template <typename T>
1711 inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int {
1712  return count_digits(fp.significand);
1713 }
1714 
1715 template <typename Char, typename OutputIt>
1716 constexpr auto write_significand(OutputIt out, const char* significand,
1717  int significand_size) -> OutputIt {
1718  return copy_str<Char>(significand, significand + significand_size, out);
1719 }
1720 template <typename Char, typename OutputIt, typename UInt>
1721 inline auto write_significand(OutputIt out, UInt significand,
1722  int significand_size) -> OutputIt {
1723  return format_decimal<Char>(out, significand, significand_size).end;
1724 }
1725 template <typename Char, typename OutputIt, typename T, typename Grouping>
1726 FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
1727  int significand_size, int exponent,
1728  const Grouping& grouping) -> OutputIt {
1729  if (!grouping.separator()) {
1730  out = write_significand<Char>(out, significand, significand_size);
1731  return detail::fill_n(out, exponent, static_cast<Char>('0'));
1732  }
1733  auto buffer = memory_buffer();
1734  write_significand<char>(appender(buffer), significand, significand_size);
1735  detail::fill_n(appender(buffer), exponent, '0');
1736  return grouping.apply(out, string_view(buffer.data(), buffer.size()));
1737 }
1738 
1739 template <typename Char, typename UInt,
1740  FMT_ENABLE_IF(std::is_integral<UInt>::value)>
1741 inline auto write_significand(Char* out, UInt significand, int significand_size,
1742  int integral_size, Char decimal_point) -> Char* {
1743  if (!decimal_point)
1744  return format_decimal(out, significand, significand_size).end;
1745  out += significand_size + 1;
1746  Char* end = out;
1747  int floating_size = significand_size - integral_size;
1748  for (int i = floating_size / 2; i > 0; --i) {
1749  out -= 2;
1750  copy2(out, digits2(significand % 100));
1751  significand /= 100;
1752  }
1753  if (floating_size % 2 != 0) {
1754  *--out = static_cast<Char>('0' + significand % 10);
1755  significand /= 10;
1756  }
1757  *--out = decimal_point;
1758  format_decimal(out - integral_size, significand, integral_size);
1759  return end;
1760 }
1761 
1762 template <typename OutputIt, typename UInt, typename Char,
1763  FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
1764 inline auto write_significand(OutputIt out, UInt significand,
1765  int significand_size, int integral_size,
1766  Char decimal_point) -> OutputIt {
1767  // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
1768  Char buffer[digits10<UInt>() + 2];
1769  auto end = write_significand(buffer, significand, significand_size,
1770  integral_size, decimal_point);
1771  return detail::copy_str_noinline<Char>(buffer, end, out);
1772 }
1773 
1774 template <typename OutputIt, typename Char>
1775 FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand,
1776  int significand_size, int integral_size,
1777  Char decimal_point) -> OutputIt {
1778  out = detail::copy_str_noinline<Char>(significand,
1779  significand + integral_size, out);
1780  if (!decimal_point) return out;
1781  *out++ = decimal_point;
1782  return detail::copy_str_noinline<Char>(significand + integral_size,
1783  significand + significand_size, out);
1784 }
1785 
1786 template <typename OutputIt, typename Char, typename T, typename Grouping>
1787 FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand,
1788  int significand_size, int integral_size,
1789  Char decimal_point,
1790  const Grouping& grouping) -> OutputIt {
1791  if (!grouping.separator()) {
1792  return write_significand(out, significand, significand_size, integral_size,
1793  decimal_point);
1794  }
1795  auto buffer = basic_memory_buffer<Char>();
1796  write_significand(buffer_appender<Char>(buffer), significand,
1797  significand_size, integral_size, decimal_point);
1798  grouping.apply(
1799  out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size)));
1800  return detail::copy_str_noinline<Char>(buffer.data() + integral_size,
1801  buffer.end(), out);
1802 }
1803 
1804 template <typename OutputIt, typename DecimalFP, typename Char,
1805  typename Grouping = digit_grouping<Char>>
1806 FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& fp,
1807  const basic_format_specs<Char>& specs,
1808  float_specs fspecs, locale_ref loc)
1809  -> OutputIt {
1810  auto significand = fp.significand;
1811  int significand_size = get_significand_size(fp);
1812  constexpr Char zero = static_cast<Char>('0');
1813  auto sign = fspecs.sign;
1814  size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
1815  using iterator = reserve_iterator<OutputIt>;
1816 
1817  Char decimal_point =
1818  fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.');
1819 
1820  int output_exp = fp.exponent + significand_size - 1;
1821  auto use_exp_format = [=]() {
1822  if (fspecs.format == float_format::exp) return true;
1823  if (fspecs.format != float_format::general) return false;
1824  // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
1825  // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
1826  const int exp_lower = -4, exp_upper = 16;
1827  return output_exp < exp_lower ||
1828  output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
1829  };
1830  if (use_exp_format()) {
1831  int num_zeros = 0;
1832  if (fspecs.showpoint) {
1833  num_zeros = fspecs.precision - significand_size;
1834  if (num_zeros < 0) num_zeros = 0;
1835  size += to_unsigned(num_zeros);
1836  } else if (significand_size == 1) {
1837  decimal_point = Char();
1838  }
1839  auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
1840  int exp_digits = 2;
1841  if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
1842 
1843  size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
1844  char exp_char = fspecs.upper ? 'E' : 'e';
1845  auto write = [=](iterator it) {
1846  if (sign) *it++ = detail::sign<Char>(sign);
1847  // Insert a decimal point after the first digit and add an exponent.
1848  it = write_significand(it, significand, significand_size, 1,
1849  decimal_point);
1850  if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero);
1851  *it++ = static_cast<Char>(exp_char);
1852  return write_exponent<Char>(output_exp, it);
1853  };
1854  return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)
1855  : base_iterator(out, write(reserve(out, size)));
1856  }
1857 
1858  int exp = fp.exponent + significand_size;
1859  if (fp.exponent >= 0) {
1860  // 1234e5 -> 123400000[.0+]
1861  size += to_unsigned(fp.exponent);
1862  int num_zeros = fspecs.precision - exp;
1863 #ifdef FMT_FUZZ
1864  if (num_zeros > 5000)
1865  throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
1866 #endif
1867  if (fspecs.showpoint) {
1868  if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1;
1869  if (num_zeros > 0) size += to_unsigned(num_zeros) + 1;
1870  }
1871  auto grouping = Grouping(loc, fspecs.locale);
1872  size += to_unsigned(grouping.count_separators(significand_size));
1873  return write_padded<align::right>(out, specs, size, [&](iterator it) {
1874  if (sign) *it++ = detail::sign<Char>(sign);
1875  it = write_significand<Char>(it, significand, significand_size,
1876  fp.exponent, grouping);
1877  if (!fspecs.showpoint) return it;
1878  *it++ = decimal_point;
1879  return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
1880  });
1881  } else if (exp > 0) {
1882  // 1234e-2 -> 12.34[0+]
1883  int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
1884  size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
1885  auto grouping = Grouping(loc, fspecs.locale);
1886  size += to_unsigned(grouping.count_separators(significand_size));
1887  return write_padded<align::right>(out, specs, size, [&](iterator it) {
1888  if (sign) *it++ = detail::sign<Char>(sign);
1889  it = write_significand(it, significand, significand_size, exp,
1890  decimal_point, grouping);
1891  return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
1892  });
1893  }
1894  // 1234e-6 -> 0.001234
1895  int num_zeros = -exp;
1896  if (significand_size == 0 && fspecs.precision >= 0 &&
1897  fspecs.precision < num_zeros) {
1898  num_zeros = fspecs.precision;
1899  }
1900  bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
1901  size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);
1902  return write_padded<align::right>(out, specs, size, [&](iterator it) {
1903  if (sign) *it++ = detail::sign<Char>(sign);
1904  *it++ = zero;
1905  if (!pointy) return it;
1906  *it++ = decimal_point;
1907  it = detail::fill_n(it, num_zeros, zero);
1908  return write_significand<Char>(it, significand, significand_size);
1909  });
1910 }
1911 
1912 template <typename Char> class fallback_digit_grouping {
1913  public:
1914  constexpr fallback_digit_grouping(locale_ref, bool) {}
1915 
1916  constexpr Char separator() const { return Char(); }
1917 
1918  constexpr int count_separators(int) const { return 0; }
1919 
1920  template <typename Out, typename C>
1921  constexpr Out apply(Out out, basic_string_view<C>) const {
1922  return out;
1923  }
1924 };
1925 
1926 template <typename OutputIt, typename DecimalFP, typename Char>
1927 FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& fp,
1928  const basic_format_specs<Char>& specs,
1929  float_specs fspecs, locale_ref loc)
1930  -> OutputIt {
1931  if (is_constant_evaluated()) {
1932  return do_write_float<OutputIt, DecimalFP, Char,
1933  fallback_digit_grouping<Char>>(out, fp, specs, fspecs,
1934  loc);
1935  } else {
1936  return do_write_float(out, fp, specs, fspecs, loc);
1937  }
1938 }
1939 
1940 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1941 FMT_CONSTEXPR20 bool isinf(T value) {
1942  if (is_constant_evaluated()) {
1943 #if defined(__cpp_if_constexpr)
1944  if constexpr (std::numeric_limits<double>::is_iec559) {
1945  auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
1946  constexpr auto significand_bits =
1948  return (bits & exponent_mask<double>()) &&
1949  !(bits & ((uint64_t(1) << significand_bits) - 1));
1950  }
1951 #endif
1952  }
1953  return std::isinf(value);
1954 }
1955 
1956 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1957 FMT_CONSTEXPR20 bool isfinite(T value) {
1958  if (is_constant_evaluated()) {
1959 #if defined(__cpp_if_constexpr)
1960  if constexpr (std::numeric_limits<double>::is_iec559) {
1961  auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
1962  return (bits & exponent_mask<double>()) != exponent_mask<double>();
1963  }
1964 #endif
1965  }
1966  return std::isfinite(value);
1967 }
1968 
1969 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1970 FMT_INLINE FMT_CONSTEXPR bool signbit(T value) {
1971  if (is_constant_evaluated()) {
1972 #ifdef __cpp_if_constexpr
1973  if constexpr (std::numeric_limits<double>::is_iec559) {
1974  auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value));
1975  return (bits & (uint64_t(1) << (num_bits<uint64_t>() - 1))) != 0;
1976  }
1977 #endif
1978  }
1979  return std::signbit(value);
1980 }
1981 
1982 template <typename Char, typename OutputIt, typename T,
1983  FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1984 FMT_CONSTEXPR20 auto write(OutputIt out, T value,
1985  basic_format_specs<Char> specs, locale_ref loc = {})
1986  -> OutputIt {
1987  if (const_check(!is_supported_floating_point(value))) return out;
1988  float_specs fspecs = parse_float_type_spec(specs);
1989  fspecs.sign = specs.sign;
1990  if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit.
1991  fspecs.sign = sign::minus;
1992  value = -value;
1993  } else if (fspecs.sign == sign::minus) {
1994  fspecs.sign = sign::none;
1995  }
1996 
1997  if (!detail::isfinite(value))
1998  return write_nonfinite(out, detail::isinf(value), specs, fspecs);
1999 
2000  if (specs.align == align::numeric && fspecs.sign) {
2001  auto it = reserve(out, 1);
2002  *it++ = detail::sign<Char>(fspecs.sign);
2003  out = base_iterator(out, it);
2004  fspecs.sign = sign::none;
2005  if (specs.width != 0) --specs.width;
2006  }
2007 
2008  memory_buffer buffer;
2009  if (fspecs.format == float_format::hex) {
2010  if (fspecs.sign) buffer.push_back(detail::sign<char>(fspecs.sign));
2011  snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
2012  return write_bytes<align::right>(out, {buffer.data(), buffer.size()},
2013  specs);
2014  }
2015  int precision = specs.precision >= 0 || specs.type == presentation_type::none
2016  ? specs.precision
2017  : 6;
2018  if (fspecs.format == float_format::exp) {
2019  if (precision == max_value<int>())
2020  throw_format_error("number is too big");
2021  else
2022  ++precision;
2023  }
2024  if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
2025  if (!is_fast_float<T>()) fspecs.fallback = true;
2026  int exp = format_float(promote_float(value), precision, fspecs, buffer);
2027  fspecs.precision = precision;
2028  auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
2029  return write_float(out, fp, specs, fspecs, loc);
2030 }
2031 
2032 template <typename Char, typename OutputIt, typename T,
2033  FMT_ENABLE_IF(is_fast_float<T>::value)>
2034 FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt {
2035  if (is_constant_evaluated()) {
2036  return write(out, value, basic_format_specs<Char>());
2037  }
2038 
2039  if (const_check(!is_supported_floating_point(value))) return out;
2040 
2041  using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
2042  using uint = typename dragonbox::float_info<floaty>::carrier_uint;
2043  auto bits = bit_cast<uint>(value);
2044 
2045  auto fspecs = float_specs();
2046  if (detail::signbit(value)) {
2047  fspecs.sign = sign::minus;
2048  value = -value;
2049  }
2050 
2051  constexpr auto specs = basic_format_specs<Char>();
2052  uint mask = exponent_mask<floaty>();
2053  if ((bits & mask) == mask)
2054  return write_nonfinite(out, std::isinf(value), specs, fspecs);
2055 
2056  auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
2057  return write_float(out, dec, specs, fspecs, {});
2058 }
2059 
2060 template <typename Char, typename OutputIt, typename T,
2061  FMT_ENABLE_IF(std::is_floating_point<T>::value &&
2062  !is_fast_float<T>::value)>
2063 inline auto write(OutputIt out, T value) -> OutputIt {
2064  return write(out, value, basic_format_specs<Char>());
2065 }
2066 
2067 template <typename Char, typename OutputIt>
2068 auto write(OutputIt out, monostate, basic_format_specs<Char> = {},
2069  locale_ref = {}) -> OutputIt {
2070  FMT_ASSERT(false, "");
2071  return out;
2072 }
2073 
2074 template <typename Char, typename OutputIt>
2075 FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value)
2076  -> OutputIt {
2077  auto it = reserve(out, value.size());
2078  it = copy_str_noinline<Char>(value.begin(), value.end(), it);
2079  return base_iterator(out, it);
2080 }
2081 
2082 template <typename Char, typename OutputIt, typename T,
2083  FMT_ENABLE_IF(is_string<T>::value)>
2084 constexpr auto write(OutputIt out, const T& value) -> OutputIt {
2085  return write<Char>(out, to_string_view(value));
2086 }
2087 
2088 template <typename Char, typename OutputIt, typename T,
2089  FMT_ENABLE_IF(is_integral<T>::value &&
2090  !std::is_same<T, bool>::value &&
2091  !std::is_same<T, Char>::value)>
2092 FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
2093  auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2094  bool negative = is_negative(value);
2095  // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2096  if (negative) abs_value = ~abs_value + 1;
2097  int num_digits = count_digits(abs_value);
2098  auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
2099  auto it = reserve(out, size);
2100  if (auto ptr = to_pointer<Char>(it, size)) {
2101  if (negative) *ptr++ = static_cast<Char>('-');
2102  format_decimal<Char>(ptr, abs_value, num_digits);
2103  return out;
2104  }
2105  if (negative) *it++ = static_cast<Char>('-');
2106  it = format_decimal<Char>(it, abs_value, num_digits).end;
2107  return base_iterator(out, it);
2108 }
2109 
2110 // FMT_ENABLE_IF() condition separated to workaround an MSVC bug.
2111 template <
2112  typename Char, typename OutputIt, typename T,
2113  bool check =
2114  std::is_enum<T>::value && !std::is_same<T, Char>::value &&
2116  type::custom_type,
2117  FMT_ENABLE_IF(check)>
2118 FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
2119  return write<Char>(
2120  out, static_cast<typename std::underlying_type<T>::type>(value));
2121 }
2122 
2123 template <typename Char, typename OutputIt, typename T,
2124  FMT_ENABLE_IF(std::is_same<T, bool>::value)>
2125 FMT_CONSTEXPR auto write(OutputIt out, T value,
2126  const basic_format_specs<Char>& specs = {},
2127  locale_ref = {}) -> OutputIt {
2128  return specs.type != presentation_type::none &&
2129  specs.type != presentation_type::string
2130  ? write(out, value ? 1 : 0, specs, {})
2131  : write_bytes(out, value ? "true" : "false", specs);
2132 }
2133 
2134 template <typename Char, typename OutputIt>
2135 FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
2136  auto it = reserve(out, 1);
2137  *it++ = value;
2138  return base_iterator(out, it);
2139 }
2140 
2141 template <typename Char, typename OutputIt>
2142 FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value)
2143  -> OutputIt {
2144  if (!value) {
2145  throw_format_error("string pointer is null");
2146  } else {
2147  out = write(out, basic_string_view<Char>(value));
2148  }
2149  return out;
2150 }
2151 
2152 template <typename Char, typename OutputIt, typename T,
2153  FMT_ENABLE_IF(std::is_same<T, void>::value)>
2154 auto write(OutputIt out, const T* value,
2155  const basic_format_specs<Char>& specs = {}, locale_ref = {})
2156  -> OutputIt {
2157  check_pointer_type_spec(specs.type, error_handler());
2158  return write_ptr<Char>(out, to_uintptr(value), &specs);
2159 }
2160 
2161 // A write overload that handles implicit conversions.
2162 template <typename Char, typename OutputIt, typename T,
2163  typename Context = basic_format_context<OutputIt, Char>>
2164 FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t<
2165  std::is_class<T>::value && !is_string<T>::value &&
2166  !std::is_same<T, Char>::value &&
2167  !std::is_same<const T&,
2168  decltype(arg_mapper<Context>().map(value))>::value,
2169  OutputIt> {
2170  return write<Char>(out, arg_mapper<Context>().map(value));
2171 }
2172 
2173 template <typename Char, typename OutputIt, typename T,
2174  typename Context = basic_format_context<OutputIt, Char>>
2175 FMT_CONSTEXPR auto write(OutputIt out, const T& value)
2176  -> enable_if_t<mapped_type_constant<T, Context>::value == type::custom_type,
2177  OutputIt> {
2178  using formatter_type =
2179  conditional_t<has_formatter<T, Context>::value,
2180  typename Context::template formatter_type<T>,
2182  auto ctx = Context(out, {}, {});
2183  return formatter_type().format(value, ctx);
2184 }
2185 
2186 // An argument visitor that formats the argument and writes it via the output
2187 // iterator. It's a class and not a generic lambda for compatibility with C++11.
2188 template <typename Char> struct default_arg_formatter {
2189  using iterator = buffer_appender<Char>;
2190  using context = buffer_context<Char>;
2191 
2192  iterator out;
2194  locale_ref loc;
2195 
2196  template <typename T> auto operator()(T value) -> iterator {
2197  return write<Char>(out, value);
2198  }
2199  auto operator()(typename basic_format_arg<context>::handle h) -> iterator {
2200  basic_format_parse_context<Char> parse_ctx({});
2201  context format_ctx(out, args, loc);
2202  h.format(parse_ctx, format_ctx);
2203  return format_ctx.out();
2204  }
2205 };
2206 
2207 template <typename Char> struct arg_formatter {
2208  using iterator = buffer_appender<Char>;
2209  using context = buffer_context<Char>;
2210 
2211  iterator out;
2212  const basic_format_specs<Char>& specs;
2213  locale_ref locale;
2214 
2215  template <typename T>
2216  FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator {
2217  return detail::write(out, value, specs, locale);
2218  }
2219  auto operator()(typename basic_format_arg<context>::handle) -> iterator {
2220  // User-defined types are handled separately because they require access
2221  // to the parse context.
2222  return out;
2223  }
2224 };
2225 
2226 template <typename Char> struct custom_formatter {
2228  buffer_context<Char>& ctx;
2229 
2230  void operator()(
2231  typename basic_format_arg<buffer_context<Char>>::handle h) const {
2232  h.format(parse_ctx, ctx);
2233  }
2234  template <typename T> void operator()(T) const {}
2235 };
2236 
2237 template <typename T>
2238 using is_integer =
2239  bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
2240  !std::is_same<T, char>::value &&
2241  !std::is_same<T, wchar_t>::value>;
2242 
2243 template <typename ErrorHandler> class width_checker {
2244  public:
2245  explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {}
2246 
2247  template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2248  FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
2249  if (is_negative(value)) handler_.on_error("negative width");
2250  return static_cast<unsigned long long>(value);
2251  }
2252 
2253  template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2254  FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
2255  handler_.on_error("width is not integer");
2256  return 0;
2257  }
2258 
2259  private:
2260  ErrorHandler& handler_;
2261 };
2262 
2263 template <typename ErrorHandler> class precision_checker {
2264  public:
2265  explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {}
2266 
2267  template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2268  FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
2269  if (is_negative(value)) handler_.on_error("negative precision");
2270  return static_cast<unsigned long long>(value);
2271  }
2272 
2273  template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2274  FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
2275  handler_.on_error("precision is not integer");
2276  return 0;
2277  }
2278 
2279  private:
2280  ErrorHandler& handler_;
2281 };
2282 
2283 template <template <typename> class Handler, typename FormatArg,
2284  typename ErrorHandler>
2285 FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int {
2286  unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
2287  if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big");
2288  return static_cast<int>(value);
2289 }
2290 
2291 template <typename Context, typename ID>
2292 FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) ->
2293  typename Context::format_arg {
2294  auto arg = ctx.arg(id);
2295  if (!arg) ctx.on_error("argument not found");
2296  return arg;
2297 }
2298 
2299 // The standard format specifier handler with checking.
2300 template <typename Char> class specs_handler : public specs_setter<Char> {
2301  private:
2302  basic_format_parse_context<Char>& parse_context_;
2303  buffer_context<Char>& context_;
2304 
2305  // This is only needed for compatibility with gcc 4.4.
2307 
2308  FMT_CONSTEXPR auto get_arg(auto_id) -> format_arg {
2309  return detail::get_arg(context_, parse_context_.next_arg_id());
2310  }
2311 
2312  FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg {
2313  parse_context_.check_arg_id(arg_id);
2314  return detail::get_arg(context_, arg_id);
2315  }
2316 
2317  FMT_CONSTEXPR auto get_arg(basic_string_view<Char> arg_id) -> format_arg {
2318  parse_context_.check_arg_id(arg_id);
2319  return detail::get_arg(context_, arg_id);
2320  }
2321 
2322  public:
2323  FMT_CONSTEXPR specs_handler(basic_format_specs<Char>& specs,
2325  buffer_context<Char>& ctx)
2326  : specs_setter<Char>(specs), parse_context_(parse_ctx), context_(ctx) {}
2327 
2328  template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
2329  this->specs_.width = get_dynamic_spec<width_checker>(
2330  get_arg(arg_id), context_.error_handler());
2331  }
2332 
2333  template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
2334  this->specs_.precision = get_dynamic_spec<precision_checker>(
2335  get_arg(arg_id), context_.error_handler());
2336  }
2337 
2338  void on_error(const char* message) { context_.on_error(message); }
2339 };
2340 
2341 template <template <typename> class Handler, typename Context>
2342 FMT_CONSTEXPR void handle_dynamic_spec(int& value,
2344  Context& ctx) {
2345  switch (ref.kind) {
2346  case arg_id_kind::none:
2347  break;
2348  case arg_id_kind::index:
2349  value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
2350  ctx.error_handler());
2351  break;
2352  case arg_id_kind::name:
2353  value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
2354  ctx.error_handler());
2355  break;
2356  }
2357 }
2358 
2359 #define FMT_STRING_IMPL(s, base, explicit) \
2360  [] { \
2361  /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
2362  /* Use a macro-like name to avoid shadowing warnings. */ \
2363  struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \
2364  using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
2365  FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
2366  operator fmt::basic_string_view<char_type>() const { \
2367  return fmt::detail_exported::compile_string_to_view<char_type>(s); \
2368  } \
2369  }; \
2370  return FMT_COMPILE_STRING(); \
2371  }()
2372 
2383 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, )
2384 
2385 #if FMT_USE_USER_DEFINED_LITERALS
2386 template <typename Char> struct udl_formatter {
2388 
2389  template <typename... T>
2390  auto operator()(T&&... args) const -> std::basic_string<Char> {
2391  return vformat(str, fmt::make_args_checked<T...>(str, args...));
2392  }
2393 };
2394 
2395 # if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
2396 template <typename T, typename Char, size_t N,
2397  fmt::detail_exported::fixed_string<Char, N> Str>
2398 struct statically_named_arg : view {
2399  static constexpr auto name = Str.data;
2400 
2401  const T& value;
2402  statically_named_arg(const T& v) : value(v) {}
2403 };
2404 
2405 template <typename T, typename Char, size_t N,
2406  fmt::detail_exported::fixed_string<Char, N> Str>
2407 struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
2408 
2409 template <typename T, typename Char, size_t N,
2410  fmt::detail_exported::fixed_string<Char, N> Str>
2411 struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
2412  : std::true_type {};
2413 
2414 template <typename Char, size_t N,
2415  fmt::detail_exported::fixed_string<Char, N> Str>
2416 struct udl_arg {
2417  template <typename T> auto operator=(T&& value) const {
2418  return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
2419  }
2420 };
2421 # else
2422 template <typename Char> struct udl_arg {
2423  const Char* str;
2424 
2425  template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
2426  return {str, std::forward<T>(value)};
2427  }
2428 };
2429 # endif
2430 #endif // FMT_USE_USER_DEFINED_LITERALS
2431 
2432 template <typename Locale, typename Char>
2433 auto vformat(const Locale& loc, basic_string_view<Char> format_str,
2434  basic_format_args<buffer_context<type_identity_t<Char>>> args)
2435  -> std::basic_string<Char> {
2437  detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc));
2438  return {buffer.data(), buffer.size()};
2439 }
2440 
2441 using format_func = void (*)(detail::buffer<char>&, int, const char*);
2442 
2443 FMT_API void format_error_code(buffer<char>& out, int error_code,
2444  string_view message) FMT_NOEXCEPT;
2445 
2446 FMT_API void report_error(format_func func, int error_code,
2447  const char* message) FMT_NOEXCEPT;
2448 FMT_END_DETAIL_NAMESPACE
2449 
2450 FMT_API auto vsystem_error(int error_code, string_view format_str,
2451  format_args args) -> std::system_error;
2452 
2470 template <typename... T>
2471 auto system_error(int error_code, format_string<T...> fmt, T&&... args)
2472  -> std::system_error {
2473  return vsystem_error(error_code, fmt, fmt::make_format_args(args...));
2474 }
2475 
2492 FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
2493  const char* message) FMT_NOEXCEPT;
2494 
2495 // Reports a system error without throwing an exception.
2496 // Can be used to report errors from destructors.
2497 FMT_API void report_system_error(int error_code,
2498  const char* message) FMT_NOEXCEPT;
2499 
2501 class format_int {
2502  private:
2503  // Buffer should be large enough to hold all digits (digits10 + 1),
2504  // a sign and a null character.
2505  enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
2506  mutable char buffer_[buffer_size];
2507  char* str_;
2508 
2509  template <typename UInt> auto format_unsigned(UInt value) -> char* {
2510  auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
2511  return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
2512  }
2513 
2514  template <typename Int> auto format_signed(Int value) -> char* {
2515  auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
2516  bool negative = value < 0;
2517  if (negative) abs_value = 0 - abs_value;
2518  auto begin = format_unsigned(abs_value);
2519  if (negative) *--begin = '-';
2520  return begin;
2521  }
2522 
2523  public:
2524  explicit format_int(int value) : str_(format_signed(value)) {}
2525  explicit format_int(long value) : str_(format_signed(value)) {}
2526  explicit format_int(long long value) : str_(format_signed(value)) {}
2527  explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
2528  explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
2529  explicit format_int(unsigned long long value)
2530  : str_(format_unsigned(value)) {}
2531 
2533  auto size() const -> size_t {
2534  return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
2535  }
2536 
2541  auto data() const -> const char* { return str_; }
2542 
2547  auto c_str() const -> const char* {
2548  buffer_[buffer_size - 1] = '\0';
2549  return str_;
2550  }
2551 
2557  auto str() const -> std::string { return std::string(str_, size()); }
2558 };
2559 
2560 template <typename T, typename Char>
2561 template <typename FormatContext>
2562 FMT_CONSTEXPR FMT_INLINE auto
2563 formatter<T, Char,
2564  enable_if_t<detail::type_constant<T, Char>::value !=
2565  detail::type::custom_type>>::format(const T& val,
2566  FormatContext& ctx)
2567  const -> decltype(ctx.out()) {
2568  if (specs_.width_ref.kind != detail::arg_id_kind::none ||
2569  specs_.precision_ref.kind != detail::arg_id_kind::none) {
2570  auto specs = specs_;
2571  detail::handle_dynamic_spec<detail::width_checker>(specs.width,
2572  specs.width_ref, ctx);
2573  detail::handle_dynamic_spec<detail::precision_checker>(
2574  specs.precision, specs.precision_ref, ctx);
2575  return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
2576  }
2577  return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
2578 }
2579 
2580 #define FMT_FORMAT_AS(Type, Base) \
2581  template <typename Char> \
2582  struct formatter<Type, Char> : formatter<Base, Char> { \
2583  template <typename FormatContext> \
2584  auto format(Type const& val, FormatContext& ctx) const \
2585  -> decltype(ctx.out()) { \
2586  return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
2587  } \
2588  }
2589 
2590 FMT_FORMAT_AS(signed char, int);
2591 FMT_FORMAT_AS(unsigned char, unsigned);
2592 FMT_FORMAT_AS(short, int);
2593 FMT_FORMAT_AS(unsigned short, unsigned);
2594 FMT_FORMAT_AS(long, long long);
2595 FMT_FORMAT_AS(unsigned long, unsigned long long);
2596 FMT_FORMAT_AS(Char*, const Char*);
2597 FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
2598 FMT_FORMAT_AS(std::nullptr_t, const void*);
2599 FMT_FORMAT_AS(detail::byte, unsigned char);
2600 FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
2601 
2602 template <typename Char>
2604  template <typename FormatContext>
2605  auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) {
2606  return formatter<const void*, Char>::format(val, ctx);
2607  }
2608 };
2609 
2610 template <typename Char, size_t N>
2611 struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
2612  template <typename FormatContext>
2613  FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const
2614  -> decltype(ctx.out()) {
2615  return formatter<basic_string_view<Char>, Char>::format(val, ctx);
2616  }
2617 };
2618 
2619 // A formatter for types known only at run time such as variant alternatives.
2620 //
2621 // Usage:
2622 // using variant = std::variant<int, std::string>;
2623 // template <>
2624 // struct formatter<variant>: dynamic_formatter<> {
2625 // auto format(const variant& v, format_context& ctx) {
2626 // return visit([&](const auto& val) {
2627 // return dynamic_formatter<>::format(val, ctx);
2628 // }, v);
2629 // }
2630 // };
2631 template <typename Char = char> class dynamic_formatter {
2632  private:
2633  detail::dynamic_format_specs<Char> specs_;
2634  const Char* format_str_;
2635 
2636  struct null_handler : detail::error_handler {
2637  void on_align(align_t) {}
2638  void on_sign(sign_t) {}
2639  void on_hash() {}
2640  };
2641 
2642  template <typename Context> void handle_specs(Context& ctx) {
2643  detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
2644  specs_.width_ref, ctx);
2645  detail::handle_dynamic_spec<detail::precision_checker>(
2646  specs_.precision, specs_.precision_ref, ctx);
2647  }
2648 
2649  public:
2650  template <typename ParseContext>
2651  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2652  format_str_ = ctx.begin();
2653  // Checks are deferred to formatting time when the argument type is known.
2654  detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
2655  return detail::parse_format_specs(ctx.begin(), ctx.end(), handler);
2656  }
2657 
2658  template <typename T, typename FormatContext>
2659  auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
2660  handle_specs(ctx);
2661  detail::specs_checker<null_handler> checker(
2662  null_handler(), detail::mapped_type_constant<T, FormatContext>::value);
2663  checker.on_align(specs_.align);
2664  if (specs_.sign != sign::none) checker.on_sign(specs_.sign);
2665  if (specs_.alt) checker.on_hash();
2666  if (specs_.precision >= 0) checker.end_precision();
2667  return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
2668  }
2669 };
2670 
2680 template <typename T> auto ptr(T p) -> const void* {
2681  static_assert(std::is_pointer<T>::value, "");
2682  return detail::bit_cast<const void*>(p);
2683 }
2684 template <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* {
2685  return p.get();
2686 }
2687 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
2688  return p.get();
2689 }
2690 
2691 class bytes {
2692  private:
2693  string_view data_;
2694  friend struct formatter<bytes>;
2695 
2696  public:
2697  explicit bytes(string_view data) : data_(data) {}
2698 };
2699 
2700 template <> struct formatter<bytes> {
2701  private:
2702  detail::dynamic_format_specs<char> specs_;
2703 
2704  public:
2705  template <typename ParseContext>
2706  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2707  using handler_type = detail::dynamic_specs_handler<ParseContext>;
2708  detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
2709  detail::type::string_type);
2710  auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
2711  detail::check_string_type_spec(specs_.type, ctx.error_handler());
2712  return it;
2713  }
2714 
2715  template <typename FormatContext>
2716  auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
2717  detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
2718  specs_.width_ref, ctx);
2719  detail::handle_dynamic_spec<detail::precision_checker>(
2720  specs_.precision, specs_.precision_ref, ctx);
2721  return detail::write_bytes(ctx.out(), b.data_, specs_);
2722  }
2723 };
2724 
2725 // group_digits_view is not derived from view because it copies the argument.
2726 template <typename T> struct group_digits_view { T value; };
2727 
2739 template <typename T> auto group_digits(T value) -> group_digits_view<T> {
2740  return {value};
2741 }
2742 
2743 template <typename T> struct formatter<group_digits_view<T>> : formatter<T> {
2744  private:
2745  detail::dynamic_format_specs<char> specs_;
2746 
2747  public:
2748  template <typename ParseContext>
2749  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2750  using handler_type = detail::dynamic_specs_handler<ParseContext>;
2751  detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
2752  detail::type::int_type);
2753  auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
2754  detail::check_string_type_spec(specs_.type, ctx.error_handler());
2755  return it;
2756  }
2757 
2758  template <typename FormatContext>
2759  auto format(group_digits_view<T> t, FormatContext& ctx)
2760  -> decltype(ctx.out()) {
2761  detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
2762  specs_.width_ref, ctx);
2763  detail::handle_dynamic_spec<detail::precision_checker>(
2764  specs_.precision, specs_.precision_ref, ctx);
2765  return detail::write_int_localized(
2766  ctx.out(), static_cast<detail::uint64_or_128_t<T>>(t.value), 0, specs_,
2767  detail::digit_grouping<char>({"\3", ','}));
2768  }
2769 };
2770 
2771 template <typename It, typename Sentinel, typename Char = char>
2772 struct join_view : detail::view {
2773  It begin;
2774  Sentinel end;
2776 
2777  join_view(It b, Sentinel e, basic_string_view<Char> s)
2778  : begin(b), end(e), sep(s) {}
2779 };
2780 
2781 template <typename It, typename Sentinel, typename Char>
2783 
2784 template <typename It, typename Sentinel, typename Char>
2785 struct formatter<join_view<It, Sentinel, Char>, Char> {
2786  private:
2787  using value_type =
2788 #ifdef __cpp_lib_ranges
2789  std::iter_value_t<It>;
2790 #else
2791  typename std::iterator_traits<It>::value_type;
2792 #endif
2793  using context = buffer_context<Char>;
2794  using mapper = detail::arg_mapper<context>;
2795 
2796  template <typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)>
2797  static auto map(const T& value) -> const T& {
2798  return value;
2799  }
2800  template <typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)>
2801  static auto map(const T& value) -> decltype(mapper().map(value)) {
2802  return mapper().map(value);
2803  }
2804 
2805  using formatter_type =
2806  conditional_t<is_formattable<value_type, Char>::value,
2807  formatter<remove_cvref_t<decltype(map(
2808  std::declval<const value_type&>()))>,
2809  Char>,
2810  detail::fallback_formatter<value_type, Char>>;
2811 
2812  formatter_type value_formatter_;
2813 
2814  public:
2815  template <typename ParseContext>
2816  FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2817  return value_formatter_.parse(ctx);
2818  }
2819 
2820  template <typename FormatContext>
2821  auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx)
2822  -> decltype(ctx.out()) {
2823  auto it = value.begin;
2824  auto out = ctx.out();
2825  if (it != value.end) {
2826  out = value_formatter_.format(map(*it), ctx);
2827  ++it;
2828  while (it != value.end) {
2829  out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
2830  ctx.advance_to(out);
2831  out = value_formatter_.format(map(*it), ctx);
2832  ++it;
2833  }
2834  }
2835  return out;
2836  }
2837 };
2838 
2843 template <typename It, typename Sentinel>
2844 auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
2845  return {begin, end, sep};
2846 }
2847 
2864 template <typename Range>
2865 auto join(Range&& range, string_view sep)
2866  -> join_view<detail::iterator_t<Range>, detail::sentinel_t<Range>> {
2867  return join(std::begin(range), std::end(range), sep);
2868 }
2869 
2881 template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
2882 inline auto to_string(const T& value) -> std::string {
2883  auto result = std::string();
2884  detail::write<char>(std::back_inserter(result), value);
2885  return result;
2886 }
2887 
2888 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
2889 FMT_NODISCARD inline auto to_string(T value) -> std::string {
2890  // The buffer should be large enough to store the number including the sign
2891  // or "false" for bool.
2892  constexpr int max_size = detail::digits10<T>() + 2;
2893  char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
2894  char* begin = buffer;
2895  return std::string(begin, detail::write<char>(begin, value));
2896 }
2897 
2898 template <typename Char, size_t SIZE>
2899 FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf)
2900  -> std::basic_string<Char> {
2901  auto size = buf.size();
2902  detail::assume(size < std::basic_string<Char>().max_size());
2903  return std::basic_string<Char>(buf.data(), size);
2904 }
2905 
2906 FMT_BEGIN_DETAIL_NAMESPACE
2907 
2908 template <typename Char>
2909 void vformat_to(
2911  basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args,
2912  locale_ref loc) {
2913  // workaround for msvc bug regarding name-lookup in module
2914  // link names into function scope
2915  using detail::arg_formatter;
2916  using detail::buffer_appender;
2917  using detail::custom_formatter;
2918  using detail::default_arg_formatter;
2919  using detail::get_arg;
2920  using detail::locale_ref;
2921  using detail::parse_format_specs;
2922  using detail::specs_checker;
2923  using detail::specs_handler;
2924  using detail::to_unsigned;
2925  using detail::type;
2926  using detail::write;
2927  auto out = buffer_appender<Char>(buf);
2928  if (fmt.size() == 2 && equal2(fmt.data(), "{}")) {
2929  auto arg = args.get(0);
2930  if (!arg) error_handler().on_error("argument not found");
2931  visit_format_arg(default_arg_formatter<Char>{out, args, loc}, arg);
2932  return;
2933  }
2934 
2935  struct format_handler : error_handler {
2936  basic_format_parse_context<Char> parse_context;
2938 
2939  format_handler(buffer_appender<Char> out, basic_string_view<Char> str,
2941  : parse_context(str), context(out, args, loc) {}
2942 
2943  void on_text(const Char* begin, const Char* end) {
2944  auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));
2945  context.advance_to(write<Char>(context.out(), text));
2946  }
2947 
2948  FMT_CONSTEXPR auto on_arg_id() -> int {
2949  return parse_context.next_arg_id();
2950  }
2951  FMT_CONSTEXPR auto on_arg_id(int id) -> int {
2952  return parse_context.check_arg_id(id), id;
2953  }
2954  FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
2955  int arg_id = context.arg_id(id);
2956  if (arg_id < 0) on_error("argument not found");
2957  return arg_id;
2958  }
2959 
2960  FMT_INLINE void on_replacement_field(int id, const Char*) {
2961  auto arg = get_arg(context, id);
2962  context.advance_to(visit_format_arg(
2963  default_arg_formatter<Char>{context.out(), context.args(),
2964  context.locale()},
2965  arg));
2966  }
2967 
2968  auto on_format_specs(int id, const Char* begin, const Char* end)
2969  -> const Char* {
2970  auto arg = get_arg(context, id);
2971  if (arg.type() == type::custom_type) {
2972  parse_context.advance_to(parse_context.begin() +
2973  (begin - &*parse_context.begin()));
2974  visit_format_arg(custom_formatter<Char>{parse_context, context}, arg);
2975  return parse_context.begin();
2976  }
2977  auto specs = basic_format_specs<Char>();
2979  specs_handler<Char>(specs, parse_context, context), arg.type());
2980  begin = parse_format_specs(begin, end, handler);
2981  if (begin == end || *begin != '}')
2982  on_error("missing '}' in format string");
2983  auto f = arg_formatter<Char>{context.out(), specs, context.locale()};
2984  context.advance_to(visit_format_arg(f, arg));
2985  return begin;
2986  }
2987  };
2988  detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));
2989 }
2990 
2991 #ifndef FMT_HEADER_ONLY
2992 extern template FMT_API auto thousands_sep_impl<char>(locale_ref)
2994 extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)
2996 extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
2997 extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
2998 extern template auto format_float<double>(double value, int precision,
2999  float_specs specs, buffer<char>& buf)
3000  -> int;
3001 extern template auto format_float<long double>(long double value, int precision,
3002  float_specs specs,
3003  buffer<char>& buf) -> int;
3004 void snprintf_float(float, int, float_specs, buffer<char>&) = delete;
3005 extern template auto snprintf_float<double>(double value, int precision,
3006  float_specs specs,
3007  buffer<char>& buf) -> int;
3008 extern template auto snprintf_float<long double>(long double value,
3009  int precision,
3010  float_specs specs,
3011  buffer<char>& buf) -> int;
3012 #endif // FMT_HEADER_ONLY
3013 
3014 FMT_END_DETAIL_NAMESPACE
3015 
3016 #if FMT_USE_USER_DEFINED_LITERALS
3017 inline namespace literals {
3028 # if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
3029 template <detail_exported::fixed_string Str>
3030 constexpr auto operator""_a()
3031  -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,
3032  sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {
3033  return {};
3034 }
3035 # else
3036 constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> {
3037  return {s};
3038 }
3039 # endif
3040 
3041 // DEPRECATED!
3042 // User-defined literal equivalent of fmt::format.
3043 FMT_DEPRECATED constexpr auto operator"" _format(const char* s, size_t n)
3044  -> detail::udl_formatter<char> {
3045  return {{s, n}};
3046 }
3047 } // namespace literals
3048 #endif // FMT_USE_USER_DEFINED_LITERALS
3049 
3050 template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
3051 inline auto vformat(const Locale& loc, string_view fmt, format_args args)
3052  -> std::string {
3053  return detail::vformat(loc, fmt, args);
3054 }
3055 
3056 template <typename Locale, typename... T,
3057  FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
3058 inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
3059  -> std::string {
3060  return vformat(loc, string_view(fmt), fmt::make_format_args(args...));
3061 }
3062 
3063 template <typename... T, size_t SIZE, typename Allocator>
3064 FMT_DEPRECATED auto format_to(basic_memory_buffer<char, SIZE, Allocator>& buf,
3065  format_string<T...> fmt, T&&... args)
3066  -> appender {
3067  detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...));
3068  return appender(buf);
3069 }
3070 
3071 template <typename OutputIt, typename Locale,
3072  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
3073  detail::is_locale<Locale>::value)>
3074 auto vformat_to(OutputIt out, const Locale& loc, string_view fmt,
3075  format_args args) -> OutputIt {
3076  using detail::get_buffer;
3077  auto&& buf = get_buffer<char>(out);
3078  detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
3079  return detail::get_iterator(buf);
3080 }
3081 
3082 template <typename OutputIt, typename Locale, typename... T,
3083  FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
3084  detail::is_locale<Locale>::value)>
3085 FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
3086  format_string<T...> fmt, T&&... args) -> OutputIt {
3087  return vformat_to(out, loc, fmt, fmt::make_format_args(args...));
3088 }
3089 
3090 FMT_MODULE_EXPORT_END
3091 FMT_END_NAMESPACE
3092 
3093 #ifdef FMT_DEPRECATED_INCLUDE_XCHAR
3094 # include "xchar.h"
3095 #endif
3096 
3097 #ifdef FMT_HEADER_ONLY
3098 # define FMT_FUNC inline
3099 # include "format-inl.h"
3100 #else
3101 # define FMT_FUNC
3102 #endif
3103 
3104 #endif // FMT_FORMAT_H_
Definition: format.h:2726
Definition: core.h:2020
A dynamically growing memory buffer for trivially copyable/constructible types with the first SIZE el...
Definition: format.h:677
Definition: format.h:1257
auto size() const -> size_t
Returns the number of characters written to the output buffer.
Definition: format.h:2533
constexpr auto size() const FMT_NOEXCEPT -> size_t
Returns the size of this buffer.
Definition: core.h:820
Definition: core.h:707
auto c_str() const -> const char *
Returns a pointer to the output buffer content with terminating null character appended.
Definition: format.h:2547
Definition: core.h:1092
void reserve(size_t new_capacity)
Increases the buffer capacity to new_capacity.
Definition: format.h:766
Definition: format.h:2226
FMT_CONSTEXPR void advance_to(iterator it)
Advances the begin iterator to it.
Definition: core.h:663
constexpr auto begin() const FMT_NOEXCEPT -> iterator
Returns an iterator to the beginning of the format string range being parsed.
Definition: core.h:651
Definition: core.h:590
Definition: core.h:613
Definition: format.h:1052
FMT_CONSTEXPR20 void resize(size_t count)
Resizes the buffer to contain count elements.
Definition: format.h:763
Fast integer formatter.
Definition: format.h:2501
Definition: core.h:2139
Definition: generic.hpp:135
Definition: span.hpp:609
FMT_CONSTEXPR auto get(int id) const -> format_arg
Returns the argument with the specified id.
Definition: core.h:1976
Definition: format.h:1448
constexpr auto capacity() const FMT_NOEXCEPT -> size_t
Returns the capacity of this buffer.
Definition: core.h:823
Definition: format.h:2243
A compile-time format string.
Definition: core.h:3049
Definition: core.h:719
Definition: format.h:1200
constexpr auto data() const FMT_NOEXCEPT -> const Char *
Returns a pointer to the string data.
Definition: core.h:492
void append(const U *begin, const U *end)
Appends data to the end of the buffer.
Definition: core.h:2737
An array of references to arguments.
Definition: core.h:1819
Definition: core.h:2106
Definition: format.h:848
FMT_CONSTEXPR auto next_arg_id() -> int
Reports an error if using the manual argument indexing; otherwise returns the next argument index and...
Definition: core.h:671
Definition: format.h:1541
constexpr auto size() const FMT_NOEXCEPT -> size_t
Returns the string size.
Definition: core.h:495
Definition: format.h:2631
Definition: format.h:2772
Definition: sc_data.cpp:17
A view of a collection of formatting arguments.
Definition: core.h:702
Definition: format.h:314
Definition: format.h:1188
Definition: core.h:2024
FMT_CONSTEXPR auto data() FMT_NOEXCEPT -> T *
Returns a pointer to the buffer data.
Definition: core.h:826
Definition: core.h:1051
Definition: format.h:2188
FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer &&other) FMT_NOEXCEPT
Constructs a :class:fmt::basic_memory_buffer object moving the content of the other object to it...
Definition: format.h:738
A formatting error such as invalid format string.
Definition: format.h:814
Definition: core.h:334
Definition: core.h:701
Definition: core.h:1552
Definition: format.h:2207
Definition: format.h:2300
Definition: format.h:1701
Definition: core.h:2817
auto str() const -> std::string
Returns the content of the output buffer as an std::string.
Definition: format.h:2557
Definition: core.h:2079
Definition: xchar.h:49
auto data() const -> const char *
Returns a pointer to the output buffer content.
Definition: format.h:2541
Definition: format.h:876
auto operator=(basic_memory_buffer &&other) FMT_NOEXCEPT -> basic_memory_buffer &
Moves the content of the other basic_memory_buffer object to this one.
Definition: format.h:748
Definition: format.h:1097
Definition: format.h:1400
Definition: format.h:255
Definition: core.h:1669
Definition: core.h:1040
Definition: format.h:1203
Definition: core.h:1049
Definition: color.hpp:198
Definition: core.h:2142
Definition: core.h:1208
Definition: core.h:1298
Definition: core.h:2032
FMT_CONSTEXPR void check_arg_id(int)
Reports an error if using the automatic argument indexing; otherwise switches to the manual indexing...
Definition: core.h:683
Definition: core.h:1093
Definition: core.h:1506
Definition: core.h:1156
Definition: format.h:2691
Definition: format.h:1912
Definition: core.h:1742
Definition: format.h:2263