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