• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <algorithm>
37 #include <cerrno>
38 #include <cmath>
39 #include <cstdint>
40 #include <limits>
41 #include <memory>
42 #include <stdexcept>
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 __cplusplus == 201103L || __cplusplus == 201402L
73 #  if defined(__INTEL_COMPILER) || defined(__PGI)
74 #    define FMT_FALLTHROUGH
75 #  elif defined(__clang__)
76 #    define FMT_FALLTHROUGH [[clang::fallthrough]]
77 #  elif FMT_GCC_VERSION >= 700 && \
78       (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 520)
79 #    define FMT_FALLTHROUGH [[gnu::fallthrough]]
80 #  else
81 #    define FMT_FALLTHROUGH
82 #  endif
83 #elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough) || \
84     (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
85 #  define FMT_FALLTHROUGH [[fallthrough]]
86 #else
87 #  define FMT_FALLTHROUGH
88 #endif
89 
90 #ifndef FMT_MAYBE_UNUSED
91 #  if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
92 #    define FMT_MAYBE_UNUSED [[maybe_unused]]
93 #  else
94 #    define FMT_MAYBE_UNUSED
95 #  endif
96 #endif
97 
98 #ifndef FMT_THROW
99 #  if FMT_EXCEPTIONS
100 #    if FMT_MSC_VER || FMT_NVCC
101 FMT_BEGIN_NAMESPACE
102 namespace detail {
do_throw(const Exception & x)103 template <typename Exception> inline void do_throw(const Exception& x) {
104   // Silence unreachable code warnings in MSVC and NVCC because these
105   // are nearly impossible to fix in a generic code.
106   volatile bool b = true;
107   if (b) throw x;
108 }
109 }  // namespace detail
110 FMT_END_NAMESPACE
111 #      define FMT_THROW(x) detail::do_throw(x)
112 #    else
113 #      define FMT_THROW(x) throw x
114 #    endif
115 #  else
116 #    define FMT_THROW(x)              \
117       do {                            \
118         static_cast<void>(sizeof(x)); \
119         FMT_ASSERT(false, "");        \
120       } while (false)
121 #  endif
122 #endif
123 
124 #if FMT_EXCEPTIONS
125 #  define FMT_TRY try
126 #  define FMT_CATCH(x) catch (x)
127 #else
128 #  define FMT_TRY if (true)
129 #  define FMT_CATCH(x) if (false)
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 #ifndef FMT_USE_UDL_TEMPLATE
144 // EDG frontend based compilers (icc, nvcc, PGI, etc) and GCC < 6.4 do not
145 // properly support UDL templates and GCC >= 9 warns about them.
146 #  if FMT_USE_USER_DEFINED_LITERALS &&                         \
147       (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= 501) && \
148       ((FMT_GCC_VERSION >= 604 && __cplusplus >= 201402L) ||   \
149        FMT_CLANG_VERSION >= 304) &&                            \
150       !defined(__PGI) && !defined(__NVCC__)
151 #    define FMT_USE_UDL_TEMPLATE 1
152 #  else
153 #    define FMT_USE_UDL_TEMPLATE 0
154 #  endif
155 #endif
156 
157 #ifndef FMT_USE_FLOAT
158 #  define FMT_USE_FLOAT 1
159 #endif
160 
161 #ifndef FMT_USE_DOUBLE
162 #  define FMT_USE_DOUBLE 1
163 #endif
164 
165 #ifndef FMT_USE_LONG_DOUBLE
166 #  define FMT_USE_LONG_DOUBLE 1
167 #endif
168 
169 // Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
170 // int_writer template instances to just one by only using the largest integer
171 // type. This results in a reduction in binary size but will cause a decrease in
172 // integer formatting performance.
173 #if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
174 #  define FMT_REDUCE_INT_INSTANTIATIONS 0
175 #endif
176 
177 // __builtin_clz is broken in clang with Microsoft CodeGen:
178 // https://github.com/fmtlib/fmt/issues/519
179 #if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clz)) && !FMT_MSC_VER
180 #  define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
181 #endif
182 #if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clzll)) && !FMT_MSC_VER
183 #  define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
184 #endif
185 #if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctz))
186 #  define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
187 #endif
188 #if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctzll))
189 #  define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
190 #endif
191 
192 #if FMT_MSC_VER
193 #  include <intrin.h>  // _BitScanReverse[64], _BitScanForward[64], _umul128
194 #endif
195 
196 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
197 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
198 // MSVC intrinsics if the clz and clzll builtins are not available.
199 #if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && \
200     !defined(FMT_BUILTIN_CTZLL) && !defined(_MANAGED)
201 FMT_BEGIN_NAMESPACE
202 namespace detail {
203 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
204 #  ifndef __clang__
205 #    pragma intrinsic(_BitScanForward)
206 #    pragma intrinsic(_BitScanReverse)
207 #  endif
208 #  if defined(_WIN64) && !defined(__clang__)
209 #    pragma intrinsic(_BitScanForward64)
210 #    pragma intrinsic(_BitScanReverse64)
211 #  endif
212 
clz(uint32_t x)213 inline int clz(uint32_t x) {
214   unsigned long r = 0;
215   _BitScanReverse(&r, x);
216   FMT_ASSERT(x != 0, "");
217   // Static analysis complains about using uninitialized data
218   // "r", but the only way that can happen is if "x" is 0,
219   // which the callers guarantee to not happen.
220   FMT_SUPPRESS_MSC_WARNING(6102)
221   return 31 ^ static_cast<int>(r);
222 }
223 #  define FMT_BUILTIN_CLZ(n) detail::clz(n)
224 
clzll(uint64_t x)225 inline int clzll(uint64_t x) {
226   unsigned long r = 0;
227 #  ifdef _WIN64
228   _BitScanReverse64(&r, x);
229 #  else
230   // Scan the high 32 bits.
231   if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) return 63 ^ (r + 32);
232   // Scan the low 32 bits.
233   _BitScanReverse(&r, static_cast<uint32_t>(x));
234 #  endif
235   FMT_ASSERT(x != 0, "");
236   FMT_SUPPRESS_MSC_WARNING(6102)  // Suppress a bogus static analysis warning.
237   return 63 ^ static_cast<int>(r);
238 }
239 #  define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
240 
ctz(uint32_t x)241 inline int ctz(uint32_t x) {
242   unsigned long r = 0;
243   _BitScanForward(&r, x);
244   FMT_ASSERT(x != 0, "");
245   FMT_SUPPRESS_MSC_WARNING(6102)  // Suppress a bogus static analysis warning.
246   return static_cast<int>(r);
247 }
248 #  define FMT_BUILTIN_CTZ(n) detail::ctz(n)
249 
ctzll(uint64_t x)250 inline int ctzll(uint64_t x) {
251   unsigned long r = 0;
252   FMT_ASSERT(x != 0, "");
253   FMT_SUPPRESS_MSC_WARNING(6102)  // Suppress a bogus static analysis warning.
254 #  ifdef _WIN64
255   _BitScanForward64(&r, x);
256 #  else
257   // Scan the low 32 bits.
258   if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);
259   // Scan the high 32 bits.
260   _BitScanForward(&r, static_cast<uint32_t>(x >> 32));
261   r += 32;
262 #  endif
263   return static_cast<int>(r);
264 }
265 #  define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
266 }  // namespace detail
267 FMT_END_NAMESPACE
268 #endif
269 
270 // Enable the deprecated numeric alignment.
271 #ifndef FMT_DEPRECATED_NUMERIC_ALIGN
272 #  define FMT_DEPRECATED_NUMERIC_ALIGN 0
273 #endif
274 
275 FMT_BEGIN_NAMESPACE
276 namespace detail {
277 
278 // An equivalent of `*reinterpret_cast<Dest*>(&source)` that doesn't have
279 // undefined behavior (e.g. due to type aliasing).
280 // Example: uint64_t d = bit_cast<uint64_t>(2.718);
281 template <typename Dest, typename Source>
bit_cast(const Source & source)282 inline Dest bit_cast(const Source& source) {
283   static_assert(sizeof(Dest) == sizeof(Source), "size mismatch");
284   Dest dest;
285   std::memcpy(&dest, &source, sizeof(dest));
286   return dest;
287 }
288 
is_big_endian()289 inline bool is_big_endian() {
290   const auto u = 1u;
291   struct bytes {
292     char data[sizeof(u)];
293   };
294   return bit_cast<bytes>(u).data[0] == 0;
295 }
296 
297 // A fallback implementation of uintptr_t for systems that lack it.
298 struct fallback_uintptr {
299   unsigned char value[sizeof(void*)];
300 
301   fallback_uintptr() = default;
fallback_uintptrfallback_uintptr302   explicit fallback_uintptr(const void* p) {
303     *this = bit_cast<fallback_uintptr>(p);
304     if (is_big_endian()) {
305       for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
306         std::swap(value[i], value[j]);
307     }
308   }
309 };
310 #ifdef UINTPTR_MAX
311 using uintptr_t = ::uintptr_t;
to_uintptr(const void * p)312 inline uintptr_t to_uintptr(const void* p) { return bit_cast<uintptr_t>(p); }
313 #else
314 using uintptr_t = fallback_uintptr;
to_uintptr(const void * p)315 inline fallback_uintptr to_uintptr(const void* p) {
316   return fallback_uintptr(p);
317 }
318 #endif
319 
320 // Returns the largest possible value for type T. Same as
321 // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
max_value()322 template <typename T> constexpr T max_value() {
323   return (std::numeric_limits<T>::max)();
324 }
num_bits()325 template <typename T> constexpr int num_bits() {
326   return std::numeric_limits<T>::digits;
327 }
328 // std::numeric_limits<T>::digits may return 0 for 128-bit ints.
329 template <> constexpr int num_bits<int128_t>() { return 128; }
330 template <> constexpr int num_bits<uint128_t>() { return 128; }
331 template <> constexpr int num_bits<fallback_uintptr>() {
332   return static_cast<int>(sizeof(void*) *
333                           std::numeric_limits<unsigned char>::digits);
334 }
335 
assume(bool condition)336 FMT_INLINE void assume(bool condition) {
337   (void)condition;
338 #if FMT_HAS_BUILTIN(__builtin_assume)
339   __builtin_assume(condition);
340 #endif
341 }
342 
343 // An approximation of iterator_t for pre-C++20 systems.
344 template <typename T>
345 using iterator_t = decltype(std::begin(std::declval<T&>()));
346 template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
347 
348 // A workaround for std::string not having mutable data() until C++17.
get_data(std::basic_string<Char> & s)349 template <typename Char> inline Char* get_data(std::basic_string<Char>& s) {
350   return &s[0];
351 }
352 template <typename Container>
get_data(Container & c)353 inline typename Container::value_type* get_data(Container& c) {
354   return c.data();
355 }
356 
357 #if defined(_SECURE_SCL) && _SECURE_SCL
358 // Make a checked iterator to avoid MSVC warnings.
359 template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
make_checked(T * p,size_t size)360 template <typename T> checked_ptr<T> make_checked(T* p, size_t size) {
361   return {p, size};
362 }
363 #else
364 template <typename T> using checked_ptr = T*;
make_checked(T * p,size_t)365 template <typename T> inline T* make_checked(T* p, size_t) { return p; }
366 #endif
367 
368 template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
369 #if FMT_CLANG_VERSION
370 __attribute__((no_sanitize("undefined")))
371 #endif
372 inline checked_ptr<typename Container::value_type>
reserve(std::back_insert_iterator<Container> it,size_t n)373 reserve(std::back_insert_iterator<Container> it, size_t n) {
374   Container& c = get_container(it);
375   size_t size = c.size();
376   c.resize(size + n);
377   return make_checked(get_data(c) + size, n);
378 }
379 
380 template <typename T>
reserve(buffer_appender<T> it,size_t n)381 inline buffer_appender<T> reserve(buffer_appender<T> it, size_t n) {
382   buffer<T>& buf = get_container(it);
383   buf.try_reserve(buf.size() + n);
384   return it;
385 }
386 
reserve(Iterator & it,size_t)387 template <typename Iterator> inline Iterator& reserve(Iterator& it, size_t) {
388   return it;
389 }
390 
391 template <typename T, typename OutputIt>
to_pointer(OutputIt,size_t)392 constexpr T* to_pointer(OutputIt, size_t) {
393   return nullptr;
394 }
to_pointer(buffer_appender<T> it,size_t n)395 template <typename T> T* to_pointer(buffer_appender<T> it, size_t n) {
396   buffer<T>& buf = get_container(it);
397   auto size = buf.size();
398   if (buf.capacity() < size + n) return nullptr;
399   buf.try_resize(size + n);
400   return buf.data() + size;
401 }
402 
403 template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
base_iterator(std::back_insert_iterator<Container> & it,checked_ptr<typename Container::value_type>)404 inline std::back_insert_iterator<Container> base_iterator(
405     std::back_insert_iterator<Container>& it,
406     checked_ptr<typename Container::value_type>) {
407   return it;
408 }
409 
410 template <typename Iterator>
base_iterator(Iterator,Iterator it)411 inline Iterator base_iterator(Iterator, Iterator it) {
412   return it;
413 }
414 
415 // An output iterator that counts the number of objects written to it and
416 // discards them.
417 class counting_iterator {
418  private:
419   size_t count_;
420 
421  public:
422   using iterator_category = std::output_iterator_tag;
423   using difference_type = std::ptrdiff_t;
424   using pointer = void;
425   using reference = void;
426   using _Unchecked_type = counting_iterator;  // Mark iterator as checked.
427 
428   struct value_type {
429     template <typename T> void operator=(const T&) {}
430   };
431 
counting_iterator()432   counting_iterator() : count_(0) {}
433 
count()434   size_t count() const { return count_; }
435 
436   counting_iterator& operator++() {
437     ++count_;
438     return *this;
439   }
440   counting_iterator operator++(int) {
441     auto it = *this;
442     ++*this;
443     return it;
444   }
445 
446   friend counting_iterator operator+(counting_iterator it, difference_type n) {
447     it.count_ += static_cast<size_t>(n);
448     return it;
449   }
450 
451   value_type operator*() const { return {}; }
452 };
453 
454 template <typename OutputIt> class truncating_iterator_base {
455  protected:
456   OutputIt out_;
457   size_t limit_;
458   size_t count_;
459 
truncating_iterator_base(OutputIt out,size_t limit)460   truncating_iterator_base(OutputIt out, size_t limit)
461       : out_(out), limit_(limit), count_(0) {}
462 
463  public:
464   using iterator_category = std::output_iterator_tag;
465   using value_type = typename std::iterator_traits<OutputIt>::value_type;
466   using difference_type = void;
467   using pointer = void;
468   using reference = void;
469   using _Unchecked_type =
470       truncating_iterator_base;  // Mark iterator as checked.
471 
base()472   OutputIt base() const { return out_; }
count()473   size_t count() const { return count_; }
474 };
475 
476 // An output iterator that truncates the output and counts the number of objects
477 // written to it.
478 template <typename OutputIt,
479           typename Enable = typename std::is_void<
480               typename std::iterator_traits<OutputIt>::value_type>::type>
481 class truncating_iterator;
482 
483 template <typename OutputIt>
484 class truncating_iterator<OutputIt, std::false_type>
485     : public truncating_iterator_base<OutputIt> {
486   mutable typename truncating_iterator_base<OutputIt>::value_type blackhole_;
487 
488  public:
489   using value_type = typename truncating_iterator_base<OutputIt>::value_type;
490 
truncating_iterator(OutputIt out,size_t limit)491   truncating_iterator(OutputIt out, size_t limit)
492       : truncating_iterator_base<OutputIt>(out, limit) {}
493 
494   truncating_iterator& operator++() {
495     if (this->count_++ < this->limit_) ++this->out_;
496     return *this;
497   }
498 
499   truncating_iterator operator++(int) {
500     auto it = *this;
501     ++*this;
502     return it;
503   }
504 
505   value_type& operator*() const {
506     return this->count_ < this->limit_ ? *this->out_ : blackhole_;
507   }
508 };
509 
510 template <typename OutputIt>
511 class truncating_iterator<OutputIt, std::true_type>
512     : public truncating_iterator_base<OutputIt> {
513  public:
truncating_iterator(OutputIt out,size_t limit)514   truncating_iterator(OutputIt out, size_t limit)
515       : truncating_iterator_base<OutputIt>(out, limit) {}
516 
517   template <typename T> truncating_iterator& operator=(T val) {
518     if (this->count_++ < this->limit_) *this->out_++ = val;
519     return *this;
520   }
521 
522   truncating_iterator& operator++() { return *this; }
523   truncating_iterator& operator++(int) { return *this; }
524   truncating_iterator& operator*() { return *this; }
525 };
526 
527 template <typename Char>
count_code_points(basic_string_view<Char> s)528 inline size_t count_code_points(basic_string_view<Char> s) {
529   return s.size();
530 }
531 
532 // Counts the number of code points in a UTF-8 string.
count_code_points(basic_string_view<char> s)533 inline size_t count_code_points(basic_string_view<char> s) {
534   const char* data = s.data();
535   size_t num_code_points = 0;
536   for (size_t i = 0, size = s.size(); i != size; ++i) {
537     if ((data[i] & 0xc0) != 0x80) ++num_code_points;
538   }
539   return num_code_points;
540 }
541 
count_code_points(basic_string_view<char8_type> s)542 inline size_t count_code_points(basic_string_view<char8_type> s) {
543   return count_code_points(basic_string_view<char>(
544       reinterpret_cast<const char*>(s.data()), s.size()));
545 }
546 
547 template <typename Char>
code_point_index(basic_string_view<Char> s,size_t n)548 inline size_t code_point_index(basic_string_view<Char> s, size_t n) {
549   size_t size = s.size();
550   return n < size ? n : size;
551 }
552 
553 // Calculates the index of the nth code point in a UTF-8 string.
code_point_index(basic_string_view<char8_type> s,size_t n)554 inline size_t code_point_index(basic_string_view<char8_type> s, size_t n) {
555   const char8_type* data = s.data();
556   size_t num_code_points = 0;
557   for (size_t i = 0, size = s.size(); i != size; ++i) {
558     if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) {
559       return i;
560     }
561   }
562   return s.size();
563 }
564 
565 template <typename InputIt, typename OutChar>
566 using needs_conversion = bool_constant<
567     std::is_same<typename std::iterator_traits<InputIt>::value_type,
568                  char>::value &&
569     std::is_same<OutChar, char8_type>::value>;
570 
571 template <typename OutChar, typename InputIt, typename OutputIt,
572           FMT_ENABLE_IF(!needs_conversion<InputIt, OutChar>::value)>
copy_str(InputIt begin,InputIt end,OutputIt it)573 OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
574   return std::copy(begin, end, it);
575 }
576 
577 template <typename OutChar, typename InputIt, typename OutputIt,
578           FMT_ENABLE_IF(needs_conversion<InputIt, OutChar>::value)>
copy_str(InputIt begin,InputIt end,OutputIt it)579 OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
580   return std::transform(begin, end, it,
581                         [](char c) { return static_cast<char8_type>(c); });
582 }
583 
584 template <typename Char, typename InputIt>
copy_str(InputIt begin,InputIt end,counting_iterator it)585 inline counting_iterator copy_str(InputIt begin, InputIt end,
586                                   counting_iterator it) {
587   return it + (end - begin);
588 }
589 
590 template <typename T>
591 using is_fast_float = bool_constant<std::numeric_limits<T>::is_iec559 &&
592                                     sizeof(T) <= sizeof(double)>;
593 
594 #ifndef FMT_USE_FULL_CACHE_DRAGONBOX
595 #  define FMT_USE_FULL_CACHE_DRAGONBOX 0
596 #endif
597 
598 template <typename T>
599 template <typename U>
append(const U * begin,const U * end)600 void buffer<T>::append(const U* begin, const U* end) {
601   do {
602     auto count = to_unsigned(end - begin);
603     try_reserve(size_ + count);
604     auto free_cap = capacity_ - size_;
605     if (free_cap < count) count = free_cap;
606     std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));
607     size_ += count;
608     begin += count;
609   } while (begin != end);
610 }
611 
612 template <typename OutputIt, typename T, typename Traits>
flush()613 void iterator_buffer<OutputIt, T, Traits>::flush() {
614   out_ = std::copy_n(data_, this->limit(this->size()), out_);
615   this->clear();
616 }
617 }  // namespace detail
618 
619 // The number of characters to store in the basic_memory_buffer object itself
620 // to avoid dynamic memory allocation.
621 enum { inline_buffer_size = 500 };
622 
623 /**
624   \rst
625   A dynamically growing memory buffer for trivially copyable/constructible types
626   with the first ``SIZE`` elements stored in the object itself.
627 
628   You can use one of the following type aliases for common character types:
629 
630   +----------------+------------------------------+
631   | Type           | Definition                   |
632   +================+==============================+
633   | memory_buffer  | basic_memory_buffer<char>    |
634   +----------------+------------------------------+
635   | wmemory_buffer | basic_memory_buffer<wchar_t> |
636   +----------------+------------------------------+
637 
638   **Example**::
639 
640      fmt::memory_buffer out;
641      format_to(out, "The answer is {}.", 42);
642 
643   This will append the following output to the ``out`` object:
644 
645   .. code-block:: none
646 
647      The answer is 42.
648 
649   The output can be converted to an ``std::string`` with ``to_string(out)``.
650   \endrst
651  */
652 template <typename T, size_t SIZE = inline_buffer_size,
653           typename Allocator = std::allocator<T>>
654 class basic_memory_buffer final : public detail::buffer<T> {
655  private:
656   T store_[SIZE];
657 
658   // Don't inherit from Allocator avoid generating type_info for it.
659   Allocator alloc_;
660 
661   // Deallocate memory allocated by the buffer.
deallocate()662   void deallocate() {
663     T* data = this->data();
664     if (data != store_) alloc_.deallocate(data, this->capacity());
665   }
666 
667  protected:
668   void grow(size_t size) final FMT_OVERRIDE;
669 
670  public:
671   using value_type = T;
672   using const_reference = const T&;
673 
674   explicit basic_memory_buffer(const Allocator& alloc = Allocator())
alloc_(alloc)675       : alloc_(alloc) {
676     this->set(store_, SIZE);
677   }
~basic_memory_buffer()678   ~basic_memory_buffer() { deallocate(); }
679 
680  private:
681   // Move data from other to this buffer.
move(basic_memory_buffer & other)682   void move(basic_memory_buffer& other) {
683     alloc_ = std::move(other.alloc_);
684     T* data = other.data();
685     size_t size = other.size(), capacity = other.capacity();
686     if (data == other.store_) {
687       this->set(store_, capacity);
688       std::uninitialized_copy(other.store_, other.store_ + size,
689                               detail::make_checked(store_, capacity));
690     } else {
691       this->set(data, capacity);
692       // Set pointer to the inline array so that delete is not called
693       // when deallocating.
694       other.set(other.store_, 0);
695     }
696     this->resize(size);
697   }
698 
699  public:
700   /**
701     \rst
702     Constructs a :class:`fmt::basic_memory_buffer` object moving the content
703     of the other object to it.
704     \endrst
705    */
basic_memory_buffer(basic_memory_buffer && other)706   basic_memory_buffer(basic_memory_buffer&& other) FMT_NOEXCEPT { move(other); }
707 
708   /**
709     \rst
710     Moves the content of the other ``basic_memory_buffer`` object to this one.
711     \endrst
712    */
713   basic_memory_buffer& operator=(basic_memory_buffer&& other) FMT_NOEXCEPT {
714     FMT_ASSERT(this != &other, "");
715     deallocate();
716     move(other);
717     return *this;
718   }
719 
720   // Returns a copy of the allocator associated with this buffer.
get_allocator()721   Allocator get_allocator() const { return alloc_; }
722 
723   /**
724     Resizes the buffer to contain *count* elements. If T is a POD type new
725     elements may not be initialized.
726    */
resize(size_t count)727   void resize(size_t count) { this->try_resize(count); }
728 
729   /** Increases the buffer capacity to *new_capacity*. */
reserve(size_t new_capacity)730   void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
731 
732   // Directly append data into the buffer
733   using detail::buffer<T>::append;
734   template <typename ContiguousRange>
append(const ContiguousRange & range)735   void append(const ContiguousRange& range) {
736     append(range.data(), range.data() + range.size());
737   }
738 };
739 
740 template <typename T, size_t SIZE, typename Allocator>
grow(size_t size)741 void basic_memory_buffer<T, SIZE, Allocator>::grow(size_t size) {
742 #ifdef FMT_FUZZ
743   if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
744 #endif
745   size_t old_capacity = this->capacity();
746   size_t new_capacity = old_capacity + old_capacity / 2;
747   if (size > new_capacity) new_capacity = size;
748   T* old_data = this->data();
749   T* new_data =
750       std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
751   // The following code doesn't throw, so the raw pointer above doesn't leak.
752   std::uninitialized_copy(old_data, old_data + this->size(),
753                           detail::make_checked(new_data, new_capacity));
754   this->set(new_data, new_capacity);
755   // deallocate must not throw according to the standard, but even if it does,
756   // the buffer already uses the new storage and will deallocate it in
757   // destructor.
758   if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
759 }
760 
761 using memory_buffer = basic_memory_buffer<char>;
762 using wmemory_buffer = basic_memory_buffer<wchar_t>;
763 
764 template <typename T, size_t SIZE, typename Allocator>
765 struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
766 };
767 
768 /** A formatting error such as invalid format string. */
769 FMT_CLASS_API
770 class FMT_API format_error : public std::runtime_error {
771  public:
772   explicit format_error(const char* message) : std::runtime_error(message) {}
773   explicit format_error(const std::string& message)
774       : std::runtime_error(message) {}
775   format_error(const format_error&) = default;
776   format_error& operator=(const format_error&) = default;
777   format_error(format_error&&) = default;
778   format_error& operator=(format_error&&) = default;
779   ~format_error() FMT_NOEXCEPT FMT_OVERRIDE;
780 };
781 
782 namespace detail {
783 
784 template <typename T>
785 using is_signed =
786     std::integral_constant<bool, std::numeric_limits<T>::is_signed ||
787                                      std::is_same<T, int128_t>::value>;
788 
789 // Returns true if value is negative, false otherwise.
790 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
791 template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
792 FMT_CONSTEXPR bool is_negative(T value) {
793   return value < 0;
794 }
795 template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
796 FMT_CONSTEXPR bool is_negative(T) {
797   return false;
798 }
799 
800 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
801 FMT_CONSTEXPR bool is_supported_floating_point(T) {
802   return (std::is_same<T, float>::value && FMT_USE_FLOAT) ||
803          (std::is_same<T, double>::value && FMT_USE_DOUBLE) ||
804          (std::is_same<T, long double>::value && FMT_USE_LONG_DOUBLE);
805 }
806 
807 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
808 // represent all values of an integral type T.
809 template <typename T>
810 using uint32_or_64_or_128_t =
811     conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS,
812                   uint32_t,
813                   conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
814 
815 // 128-bit integer type used internally
816 struct FMT_EXTERN_TEMPLATE_API uint128_wrapper {
817   uint128_wrapper() = default;
818 
819 #if FMT_USE_INT128
820   uint128_t internal_;
821 
822   uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT
823       : internal_{static_cast<uint128_t>(low) |
824                   (static_cast<uint128_t>(high) << 64)} {}
825 
826   uint128_wrapper(uint128_t u) : internal_{u} {}
827 
828   uint64_t high() const FMT_NOEXCEPT { return uint64_t(internal_ >> 64); }
829   uint64_t low() const FMT_NOEXCEPT { return uint64_t(internal_); }
830 
831   uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {
832     internal_ += n;
833     return *this;
834   }
835 #else
836   uint64_t high_;
837   uint64_t low_;
838 
839   uint128_wrapper(uint64_t high, uint64_t low) FMT_NOEXCEPT : high_{high},
840                                                               low_{low} {}
841 
842   uint64_t high() const FMT_NOEXCEPT { return high_; }
843   uint64_t low() const FMT_NOEXCEPT { return low_; }
844 
845   uint128_wrapper& operator+=(uint64_t n) FMT_NOEXCEPT {
846 #  if defined(_MSC_VER) && defined(_M_X64)
847     unsigned char carry = _addcarry_u64(0, low_, n, &low_);
848     _addcarry_u64(carry, high_, 0, &high_);
849     return *this;
850 #  else
851     uint64_t sum = low_ + n;
852     high_ += (sum < low_ ? 1 : 0);
853     low_ = sum;
854     return *this;
855 #  endif
856   }
857 #endif
858 };
859 
860 // Table entry type for divisibility test used internally
861 template <typename T> struct FMT_EXTERN_TEMPLATE_API divtest_table_entry {
862   T mod_inv;
863   T max_quotient;
864 };
865 
866 // Static data is placed in this class template for the header-only config.
867 template <typename T = void> struct FMT_EXTERN_TEMPLATE_API basic_data {
868   static const uint64_t powers_of_10_64[];
869   static const uint32_t zero_or_powers_of_10_32_new[];
870   static const uint64_t zero_or_powers_of_10_64_new[];
871   static const uint64_t grisu_pow10_significands[];
872   static const int16_t grisu_pow10_exponents[];
873   static const divtest_table_entry<uint32_t> divtest_table_for_pow5_32[];
874   static const divtest_table_entry<uint64_t> divtest_table_for_pow5_64[];
875   static const uint64_t dragonbox_pow10_significands_64[];
876   static const uint128_wrapper dragonbox_pow10_significands_128[];
877   // log10(2) = 0x0.4d104d427de7fbcc...
878   static const uint64_t log10_2_significand = 0x4d104d427de7fbcc;
879 #if !FMT_USE_FULL_CACHE_DRAGONBOX
880   static const uint64_t powers_of_5_64[];
881   static const uint32_t dragonbox_pow10_recovery_errors[];
882 #endif
883   // GCC generates slightly better code for pairs than chars.
884   using digit_pair = char[2];
885   static const digit_pair digits[];
886   static const char hex_digits[];
887   static const char foreground_color[];
888   static const char background_color[];
889   static const char reset_color[5];
890   static const wchar_t wreset_color[5];
891   static const char signs[];
892   static const char left_padding_shifts[5];
893   static const char right_padding_shifts[5];
894 
895   // DEPRECATED! These are for ABI compatibility.
896   static const uint32_t zero_or_powers_of_10_32[];
897   static const uint64_t zero_or_powers_of_10_64[];
898 };
899 
900 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
901 // This is a function instead of an array to workaround a bug in GCC10 (#1810).
902 FMT_INLINE uint16_t bsr2log10(int bsr) {
903   static constexpr uint16_t data[] = {
904       1,  1,  1,  2,  2,  2,  3,  3,  3,  4,  4,  4,  4,  5,  5,  5,
905       6,  6,  6,  7,  7,  7,  7,  8,  8,  8,  9,  9,  9,  10, 10, 10,
906       10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
907       15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
908   return data[bsr];
909 }
910 
911 #ifndef FMT_EXPORTED
912 FMT_EXTERN template struct basic_data<void>;
913 #endif
914 
915 // This is a struct rather than an alias to avoid shadowing warnings in gcc.
916 struct data : basic_data<> {};
917 
918 #ifdef FMT_BUILTIN_CLZLL
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 inline int count_digits(uint64_t n) {
922   // https://github.com/fmtlib/format-benchmark/blob/master/digits10
923   auto t = bsr2log10(FMT_BUILTIN_CLZLL(n | 1) ^ 63);
924   return t - (n < data::zero_or_powers_of_10_64_new[t]);
925 }
926 #else
927 // Fallback version of count_digits used when __builtin_clz is not available.
928 inline int count_digits(uint64_t n) {
929   int count = 1;
930   for (;;) {
931     // Integer division is slow so do it for a group of four digits instead
932     // of for every digit. The idea comes from the talk by Alexandrescu
933     // "Three Optimization Tips for C++". See speed-test for a comparison.
934     if (n < 10) return count;
935     if (n < 100) return count + 1;
936     if (n < 1000) return count + 2;
937     if (n < 10000) return count + 3;
938     n /= 10000u;
939     count += 4;
940   }
941 }
942 #endif
943 
944 #if FMT_USE_INT128
945 inline int count_digits(uint128_t n) {
946   int count = 1;
947   for (;;) {
948     // Integer division is slow so do it for a group of four digits instead
949     // of for every digit. The idea comes from the talk by Alexandrescu
950     // "Three Optimization Tips for C++". See speed-test for a comparison.
951     if (n < 10) return count;
952     if (n < 100) return count + 1;
953     if (n < 1000) return count + 2;
954     if (n < 10000) return count + 3;
955     n /= 10000U;
956     count += 4;
957   }
958 }
959 #endif
960 
961 // Counts the number of digits in n. BITS = log2(radix).
962 template <unsigned BITS, typename UInt> inline int count_digits(UInt n) {
963   int num_digits = 0;
964   do {
965     ++num_digits;
966   } while ((n >>= BITS) != 0);
967   return num_digits;
968 }
969 
970 template <> int count_digits<4>(detail::fallback_uintptr n);
971 
972 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
973 #  define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
974 #elif FMT_MSC_VER
975 #  define FMT_ALWAYS_INLINE __forceinline
976 #else
977 #  define FMT_ALWAYS_INLINE inline
978 #endif
979 
980 // To suppress unnecessary security cookie checks
981 #if FMT_MSC_VER && !FMT_CLANG_VERSION
982 #  define FMT_SAFEBUFFERS __declspec(safebuffers)
983 #else
984 #  define FMT_SAFEBUFFERS
985 #endif
986 
987 #ifdef FMT_BUILTIN_CLZ
988 // Optional version of count_digits for better performance on 32-bit platforms.
989 inline int count_digits(uint32_t n) {
990   auto t = bsr2log10(FMT_BUILTIN_CLZ(n | 1) ^ 31);
991   return t - (n < data::zero_or_powers_of_10_32_new[t]);
992 }
993 #endif
994 
995 template <typename Int> constexpr int digits10() FMT_NOEXCEPT {
996   return std::numeric_limits<Int>::digits10;
997 }
998 template <> constexpr int digits10<int128_t>() FMT_NOEXCEPT { return 38; }
999 template <> constexpr int digits10<uint128_t>() FMT_NOEXCEPT { return 38; }
1000 
1001 template <typename Char> FMT_API std::string grouping_impl(locale_ref loc);
1002 template <typename Char> inline std::string grouping(locale_ref loc) {
1003   return grouping_impl<char>(loc);
1004 }
1005 template <> inline std::string grouping<wchar_t>(locale_ref loc) {
1006   return grouping_impl<wchar_t>(loc);
1007 }
1008 
1009 template <typename Char> FMT_API Char thousands_sep_impl(locale_ref loc);
1010 template <typename Char> inline Char thousands_sep(locale_ref loc) {
1011   return Char(thousands_sep_impl<char>(loc));
1012 }
1013 template <> inline wchar_t thousands_sep(locale_ref loc) {
1014   return thousands_sep_impl<wchar_t>(loc);
1015 }
1016 
1017 template <typename Char> FMT_API Char decimal_point_impl(locale_ref loc);
1018 template <typename Char> inline Char decimal_point(locale_ref loc) {
1019   return Char(decimal_point_impl<char>(loc));
1020 }
1021 template <> inline wchar_t decimal_point(locale_ref loc) {
1022   return decimal_point_impl<wchar_t>(loc);
1023 }
1024 
1025 // Compares two characters for equality.
1026 template <typename Char> bool equal2(const Char* lhs, const char* rhs) {
1027   return lhs[0] == rhs[0] && lhs[1] == rhs[1];
1028 }
1029 inline bool equal2(const char* lhs, const char* rhs) {
1030   return memcmp(lhs, rhs, 2) == 0;
1031 }
1032 
1033 // Copies two characters from src to dst.
1034 template <typename Char> void copy2(Char* dst, const char* src) {
1035   *dst++ = static_cast<Char>(*src++);
1036   *dst = static_cast<Char>(*src);
1037 }
1038 FMT_INLINE void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
1039 
1040 template <typename Iterator> struct format_decimal_result {
1041   Iterator begin;
1042   Iterator end;
1043 };
1044 
1045 // Formats a decimal unsigned integer value writing into out pointing to a
1046 // buffer of specified size. The caller must ensure that the buffer is large
1047 // enough.
1048 template <typename Char, typename UInt>
1049 inline format_decimal_result<Char*> format_decimal(Char* out, UInt value,
1050                                                    int size) {
1051   FMT_ASSERT(size >= count_digits(value), "invalid digit count");
1052   out += size;
1053   Char* end = out;
1054   while (value >= 100) {
1055     // Integer division is slow so do it for a group of two digits instead
1056     // of for every digit. The idea comes from the talk by Alexandrescu
1057     // "Three Optimization Tips for C++". See speed-test for a comparison.
1058     out -= 2;
1059     copy2(out, data::digits[value % 100]);
1060     value /= 100;
1061   }
1062   if (value < 10) {
1063     *--out = static_cast<Char>('0' + value);
1064     return {out, end};
1065   }
1066   out -= 2;
1067   copy2(out, data::digits[value]);
1068   return {out, end};
1069 }
1070 
1071 template <typename Char, typename UInt, typename Iterator,
1072           FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
1073 inline format_decimal_result<Iterator> format_decimal(Iterator out, UInt value,
1074                                                       int size) {
1075   // Buffer is large enough to hold all digits (digits10 + 1).
1076   Char buffer[digits10<UInt>() + 1];
1077   auto end = format_decimal(buffer, value, size).end;
1078   return {out, detail::copy_str<Char>(buffer, end, out)};
1079 }
1080 
1081 template <unsigned BASE_BITS, typename Char, typename UInt>
1082 inline Char* format_uint(Char* buffer, UInt value, int num_digits,
1083                          bool upper = false) {
1084   buffer += num_digits;
1085   Char* end = buffer;
1086   do {
1087     const char* digits = upper ? "0123456789ABCDEF" : data::hex_digits;
1088     unsigned digit = (value & ((1 << BASE_BITS) - 1));
1089     *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
1090                                                 : digits[digit]);
1091   } while ((value >>= BASE_BITS) != 0);
1092   return end;
1093 }
1094 
1095 template <unsigned BASE_BITS, typename Char>
1096 Char* format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
1097                   bool = false) {
1098   auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
1099   int start = (num_digits + char_digits - 1) / char_digits - 1;
1100   if (int start_digits = num_digits % char_digits) {
1101     unsigned value = n.value[start--];
1102     buffer = format_uint<BASE_BITS>(buffer, value, start_digits);
1103   }
1104   for (; start >= 0; --start) {
1105     unsigned value = n.value[start];
1106     buffer += char_digits;
1107     auto p = buffer;
1108     for (int i = 0; i < char_digits; ++i) {
1109       unsigned digit = (value & ((1 << BASE_BITS) - 1));
1110       *--p = static_cast<Char>(data::hex_digits[digit]);
1111       value >>= BASE_BITS;
1112     }
1113   }
1114   return buffer;
1115 }
1116 
1117 template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
1118 inline It format_uint(It out, UInt value, int num_digits, bool upper = false) {
1119   if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1120     format_uint<BASE_BITS>(ptr, value, num_digits, upper);
1121     return out;
1122   }
1123   // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1124   char buffer[num_bits<UInt>() / BASE_BITS + 1];
1125   format_uint<BASE_BITS>(buffer, value, num_digits, upper);
1126   return detail::copy_str<Char>(buffer, buffer + num_digits, out);
1127 }
1128 
1129 // A converter from UTF-8 to UTF-16.
1130 class utf8_to_utf16 {
1131  private:
1132   wmemory_buffer buffer_;
1133 
1134  public:
1135   FMT_API explicit utf8_to_utf16(string_view s);
1136   operator wstring_view() const { return {&buffer_[0], size()}; }
1137   size_t size() const { return buffer_.size() - 1; }
1138   const wchar_t* c_str() const { return &buffer_[0]; }
1139   std::wstring str() const { return {&buffer_[0], size()}; }
1140 };
1141 
1142 template <typename T = void> struct null {};
1143 
1144 // Workaround an array initialization issue in gcc 4.8.
1145 template <typename Char> struct fill_t {
1146  private:
1147   enum { max_size = 4 };
1148   Char data_[max_size] = {Char(' '), Char(0), Char(0), Char(0)};
1149   unsigned char size_ = 1;
1150 
1151  public:
1152   FMT_CONSTEXPR void operator=(basic_string_view<Char> s) {
1153     auto size = s.size();
1154     if (size > max_size) {
1155       FMT_THROW(format_error("invalid fill"));
1156       return;
1157     }
1158     for (size_t i = 0; i < size; ++i) data_[i] = s[i];
1159     size_ = static_cast<unsigned char>(size);
1160   }
1161 
1162   size_t size() const { return size_; }
1163   const Char* data() const { return data_; }
1164 
1165   FMT_CONSTEXPR Char& operator[](size_t index) { return data_[index]; }
1166   FMT_CONSTEXPR const Char& operator[](size_t index) const {
1167     return data_[index];
1168   }
1169 };
1170 }  // namespace detail
1171 
1172 // We cannot use enum classes as bit fields because of a gcc bug
1173 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
1174 namespace align {
1175 enum type { none, left, right, center, numeric };
1176 }
1177 using align_t = align::type;
1178 
1179 namespace sign {
1180 enum type { none, minus, plus, space };
1181 }
1182 using sign_t = sign::type;
1183 
1184 // Format specifiers for built-in and string types.
1185 template <typename Char> struct basic_format_specs {
1186   int width;
1187   int precision;
1188   char type;
1189   align_t align : 4;
1190   sign_t sign : 3;
1191   bool alt : 1;  // Alternate form ('#').
1192   detail::fill_t<Char> fill;
1193 
1194   constexpr basic_format_specs()
1195       : width(0),
1196         precision(-1),
1197         type(0),
1198         align(align::none),
1199         sign(sign::none),
1200         alt(false) {}
1201 };
1202 
1203 using format_specs = basic_format_specs<char>;
1204 
1205 namespace detail {
1206 namespace dragonbox {
1207 
1208 // Type-specific information that Dragonbox uses.
1209 template <class T> struct float_info;
1210 
1211 template <> struct float_info<float> {
1212   using carrier_uint = uint32_t;
1213   static const int significand_bits = 23;
1214   static const int exponent_bits = 8;
1215   static const int min_exponent = -126;
1216   static const int max_exponent = 127;
1217   static const int exponent_bias = -127;
1218   static const int decimal_digits = 9;
1219   static const int kappa = 1;
1220   static const int big_divisor = 100;
1221   static const int small_divisor = 10;
1222   static const int min_k = -31;
1223   static const int max_k = 46;
1224   static const int cache_bits = 64;
1225   static const int divisibility_check_by_5_threshold = 39;
1226   static const int case_fc_pm_half_lower_threshold = -1;
1227   static const int case_fc_pm_half_upper_threshold = 6;
1228   static const int case_fc_lower_threshold = -2;
1229   static const int case_fc_upper_threshold = 6;
1230   static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1231   static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1232   static const int shorter_interval_tie_lower_threshold = -35;
1233   static const int shorter_interval_tie_upper_threshold = -35;
1234   static const int max_trailing_zeros = 7;
1235 };
1236 
1237 template <> struct float_info<double> {
1238   using carrier_uint = uint64_t;
1239   static const int significand_bits = 52;
1240   static const int exponent_bits = 11;
1241   static const int min_exponent = -1022;
1242   static const int max_exponent = 1023;
1243   static const int exponent_bias = -1023;
1244   static const int decimal_digits = 17;
1245   static const int kappa = 2;
1246   static const int big_divisor = 1000;
1247   static const int small_divisor = 100;
1248   static const int min_k = -292;
1249   static const int max_k = 326;
1250   static const int cache_bits = 128;
1251   static const int divisibility_check_by_5_threshold = 86;
1252   static const int case_fc_pm_half_lower_threshold = -2;
1253   static const int case_fc_pm_half_upper_threshold = 9;
1254   static const int case_fc_lower_threshold = -4;
1255   static const int case_fc_upper_threshold = 9;
1256   static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1257   static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1258   static const int shorter_interval_tie_lower_threshold = -77;
1259   static const int shorter_interval_tie_upper_threshold = -77;
1260   static const int max_trailing_zeros = 16;
1261 };
1262 
1263 template <typename T> struct decimal_fp {
1264   using significand_type = typename float_info<T>::carrier_uint;
1265   significand_type significand;
1266   int exponent;
1267 };
1268 
1269 template <typename T> FMT_API decimal_fp<T> to_decimal(T x) FMT_NOEXCEPT;
1270 }  // namespace dragonbox
1271 
1272 template <typename T>
1273 constexpr typename dragonbox::float_info<T>::carrier_uint exponent_mask() {
1274   using uint = typename dragonbox::float_info<T>::carrier_uint;
1275   return ((uint(1) << dragonbox::float_info<T>::exponent_bits) - 1)
1276          << dragonbox::float_info<T>::significand_bits;
1277 }
1278 
1279 // A floating-point presentation format.
1280 enum class float_format : unsigned char {
1281   general,  // General: exponent notation or fixed point based on magnitude.
1282   exp,      // Exponent notation with the default precision of 6, e.g. 1.2e-3.
1283   fixed,    // Fixed point with the default precision of 6, e.g. 0.0012.
1284   hex
1285 };
1286 
1287 struct float_specs {
1288   int precision;
1289   float_format format : 8;
1290   sign_t sign : 8;
1291   bool upper : 1;
1292   bool locale : 1;
1293   bool binary32 : 1;
1294   bool use_grisu : 1;
1295   bool showpoint : 1;
1296 };
1297 
1298 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1299 template <typename Char, typename It> It write_exponent(int exp, It it) {
1300   FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
1301   if (exp < 0) {
1302     *it++ = static_cast<Char>('-');
1303     exp = -exp;
1304   } else {
1305     *it++ = static_cast<Char>('+');
1306   }
1307   if (exp >= 100) {
1308     const char* top = data::digits[exp / 100];
1309     if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
1310     *it++ = static_cast<Char>(top[1]);
1311     exp %= 100;
1312   }
1313   const char* d = data::digits[exp];
1314   *it++ = static_cast<Char>(d[0]);
1315   *it++ = static_cast<Char>(d[1]);
1316   return it;
1317 }
1318 
1319 template <typename T>
1320 int format_float(T value, int precision, float_specs specs, buffer<char>& buf);
1321 
1322 // Formats a floating-point number with snprintf.
1323 template <typename T>
1324 int snprintf_float(T value, int precision, float_specs specs,
1325                    buffer<char>& buf);
1326 
1327 template <typename T> T promote_float(T value) { return value; }
1328 inline double promote_float(float value) { return static_cast<double>(value); }
1329 
1330 template <typename Handler>
1331 FMT_CONSTEXPR void handle_int_type_spec(char spec, Handler&& handler) {
1332   switch (spec) {
1333   case 0:
1334   case 'd':
1335     handler.on_dec();
1336     break;
1337   case 'x':
1338   case 'X':
1339     handler.on_hex();
1340     break;
1341   case 'b':
1342   case 'B':
1343     handler.on_bin();
1344     break;
1345   case 'o':
1346     handler.on_oct();
1347     break;
1348 #ifdef FMT_DEPRECATED_N_SPECIFIER
1349   case 'n':
1350 #endif
1351   case 'L':
1352     handler.on_num();
1353     break;
1354   case 'c':
1355     handler.on_chr();
1356     break;
1357   default:
1358     handler.on_error();
1359   }
1360 }
1361 
1362 template <typename ErrorHandler = error_handler, typename Char>
1363 FMT_CONSTEXPR float_specs parse_float_type_spec(
1364     const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
1365   auto result = float_specs();
1366   result.showpoint = specs.alt;
1367   switch (specs.type) {
1368   case 0:
1369     result.format = float_format::general;
1370     result.showpoint |= specs.precision > 0;
1371     break;
1372   case 'G':
1373     result.upper = true;
1374     FMT_FALLTHROUGH;
1375   case 'g':
1376     result.format = float_format::general;
1377     break;
1378   case 'E':
1379     result.upper = true;
1380     FMT_FALLTHROUGH;
1381   case 'e':
1382     result.format = float_format::exp;
1383     result.showpoint |= specs.precision != 0;
1384     break;
1385   case 'F':
1386     result.upper = true;
1387     FMT_FALLTHROUGH;
1388   case 'f':
1389     result.format = float_format::fixed;
1390     result.showpoint |= specs.precision != 0;
1391     break;
1392   case 'A':
1393     result.upper = true;
1394     FMT_FALLTHROUGH;
1395   case 'a':
1396     result.format = float_format::hex;
1397     break;
1398 #ifdef FMT_DEPRECATED_N_SPECIFIER
1399   case 'n':
1400 #endif
1401   case 'L':
1402     result.locale = true;
1403     break;
1404   default:
1405     eh.on_error("invalid type specifier");
1406     break;
1407   }
1408   return result;
1409 }
1410 
1411 template <typename Char, typename Handler>
1412 FMT_CONSTEXPR void handle_char_specs(const basic_format_specs<Char>* specs,
1413                                      Handler&& handler) {
1414   if (!specs) return handler.on_char();
1415   if (specs->type && specs->type != 'c') return handler.on_int();
1416   if (specs->align == align::numeric || specs->sign != sign::none || specs->alt)
1417     handler.on_error("invalid format specifier for char");
1418   handler.on_char();
1419 }
1420 
1421 template <typename Char, typename Handler>
1422 FMT_CONSTEXPR void handle_cstring_type_spec(Char spec, Handler&& handler) {
1423   if (spec == 0 || spec == 's')
1424     handler.on_string();
1425   else if (spec == 'p')
1426     handler.on_pointer();
1427   else
1428     handler.on_error("invalid type specifier");
1429 }
1430 
1431 template <typename Char, typename ErrorHandler>
1432 FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler&& eh) {
1433   if (spec != 0 && spec != 's') eh.on_error("invalid type specifier");
1434 }
1435 
1436 template <typename Char, typename ErrorHandler>
1437 FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler&& eh) {
1438   if (spec != 0 && spec != 'p') eh.on_error("invalid type specifier");
1439 }
1440 
1441 template <typename ErrorHandler> class int_type_checker : private ErrorHandler {
1442  public:
1443   FMT_CONSTEXPR explicit int_type_checker(ErrorHandler eh) : ErrorHandler(eh) {}
1444 
1445   FMT_CONSTEXPR void on_dec() {}
1446   FMT_CONSTEXPR void on_hex() {}
1447   FMT_CONSTEXPR void on_bin() {}
1448   FMT_CONSTEXPR void on_oct() {}
1449   FMT_CONSTEXPR void on_num() {}
1450   FMT_CONSTEXPR void on_chr() {}
1451 
1452   FMT_CONSTEXPR void on_error() {
1453     ErrorHandler::on_error("invalid type specifier");
1454   }
1455 };
1456 
1457 template <typename ErrorHandler>
1458 class char_specs_checker : public ErrorHandler {
1459  private:
1460   char type_;
1461 
1462  public:
1463   FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
1464       : ErrorHandler(eh), type_(type) {}
1465 
1466   FMT_CONSTEXPR void on_int() {
1467     handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
1468   }
1469   FMT_CONSTEXPR void on_char() {}
1470 };
1471 
1472 template <typename ErrorHandler>
1473 class cstring_type_checker : public ErrorHandler {
1474  public:
1475   FMT_CONSTEXPR explicit cstring_type_checker(ErrorHandler eh)
1476       : ErrorHandler(eh) {}
1477 
1478   FMT_CONSTEXPR void on_string() {}
1479   FMT_CONSTEXPR void on_pointer() {}
1480 };
1481 
1482 template <typename OutputIt, typename Char>
1483 FMT_NOINLINE OutputIt fill(OutputIt it, size_t n, const fill_t<Char>& fill) {
1484   auto fill_size = fill.size();
1485   if (fill_size == 1) return std::fill_n(it, n, fill[0]);
1486   for (size_t i = 0; i < n; ++i) it = std::copy_n(fill.data(), fill_size, it);
1487   return it;
1488 }
1489 
1490 // Writes the output of f, padded according to format specifications in specs.
1491 // size: output size in code units.
1492 // width: output display width in (terminal) column positions.
1493 template <align::type align = align::left, typename OutputIt, typename Char,
1494           typename F>
1495 inline OutputIt write_padded(OutputIt out,
1496                              const basic_format_specs<Char>& specs, size_t size,
1497                              size_t width, F&& f) {
1498   static_assert(align == align::left || align == align::right, "");
1499   unsigned spec_width = to_unsigned(specs.width);
1500   size_t padding = spec_width > width ? spec_width - width : 0;
1501   auto* shifts = align == align::left ? data::left_padding_shifts
1502                                       : data::right_padding_shifts;
1503   size_t left_padding = padding >> shifts[specs.align];
1504   auto it = reserve(out, size + padding * specs.fill.size());
1505   it = fill(it, left_padding, specs.fill);
1506   it = f(it);
1507   it = fill(it, padding - left_padding, specs.fill);
1508   return base_iterator(out, it);
1509 }
1510 
1511 template <align::type align = align::left, typename OutputIt, typename Char,
1512           typename F>
1513 inline OutputIt write_padded(OutputIt out,
1514                              const basic_format_specs<Char>& specs, size_t size,
1515                              F&& f) {
1516   return write_padded<align>(out, specs, size, size, f);
1517 }
1518 
1519 template <typename Char, typename OutputIt>
1520 OutputIt write_bytes(OutputIt out, string_view bytes,
1521                      const basic_format_specs<Char>& specs) {
1522   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1523   return write_padded(out, specs, bytes.size(), [bytes](iterator it) {
1524     const char* data = bytes.data();
1525     return copy_str<Char>(data, data + bytes.size(), it);
1526   });
1527 }
1528 
1529 // Data for write_int that doesn't depend on output iterator type. It is used to
1530 // avoid template code bloat.
1531 template <typename Char> struct write_int_data {
1532   size_t size;
1533   size_t padding;
1534 
1535   write_int_data(int num_digits, string_view prefix,
1536                  const basic_format_specs<Char>& specs)
1537       : size(prefix.size() + to_unsigned(num_digits)), padding(0) {
1538     if (specs.align == align::numeric) {
1539       auto width = to_unsigned(specs.width);
1540       if (width > size) {
1541         padding = width - size;
1542         size = width;
1543       }
1544     } else if (specs.precision > num_digits) {
1545       size = prefix.size() + to_unsigned(specs.precision);
1546       padding = to_unsigned(specs.precision - num_digits);
1547     }
1548   }
1549 };
1550 
1551 // Writes an integer in the format
1552 //   <left-padding><prefix><numeric-padding><digits><right-padding>
1553 // where <digits> are written by f(it).
1554 template <typename OutputIt, typename Char, typename F>
1555 OutputIt write_int(OutputIt out, int num_digits, string_view prefix,
1556                    const basic_format_specs<Char>& specs, F f) {
1557   auto data = write_int_data<Char>(num_digits, prefix, specs);
1558   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1559   return write_padded<align::right>(out, specs, data.size, [=](iterator it) {
1560     if (prefix.size() != 0)
1561       it = copy_str<Char>(prefix.begin(), prefix.end(), it);
1562     it = std::fill_n(it, data.padding, static_cast<Char>('0'));
1563     return f(it);
1564   });
1565 }
1566 
1567 template <typename StrChar, typename Char, typename OutputIt>
1568 OutputIt write(OutputIt out, basic_string_view<StrChar> s,
1569                const basic_format_specs<Char>& specs) {
1570   auto data = s.data();
1571   auto size = s.size();
1572   if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
1573     size = code_point_index(s, to_unsigned(specs.precision));
1574   auto width = specs.width != 0
1575                    ? count_code_points(basic_string_view<StrChar>(data, size))
1576                    : 0;
1577   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1578   return write_padded(out, specs, size, width, [=](iterator it) {
1579     return copy_str<Char>(data, data + size, it);
1580   });
1581 }
1582 
1583 // The handle_int_type_spec handler that writes an integer.
1584 template <typename OutputIt, typename Char, typename UInt> struct int_writer {
1585   OutputIt out;
1586   locale_ref locale;
1587   const basic_format_specs<Char>& specs;
1588   UInt abs_value;
1589   char prefix[4];
1590   unsigned prefix_size;
1591 
1592   using iterator =
1593       remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
1594 
1595   string_view get_prefix() const { return string_view(prefix, prefix_size); }
1596 
1597   template <typename Int>
1598   int_writer(OutputIt output, locale_ref loc, Int value,
1599              const basic_format_specs<Char>& s)
1600       : out(output),
1601         locale(loc),
1602         specs(s),
1603         abs_value(static_cast<UInt>(value)),
1604         prefix_size(0) {
1605     static_assert(std::is_same<uint32_or_64_or_128_t<Int>, UInt>::value, "");
1606     if (is_negative(value)) {
1607       prefix[0] = '-';
1608       ++prefix_size;
1609       abs_value = 0 - abs_value;
1610     } else if (specs.sign != sign::none && specs.sign != sign::minus) {
1611       prefix[0] = specs.sign == sign::plus ? '+' : ' ';
1612       ++prefix_size;
1613     }
1614   }
1615 
1616   void on_dec() {
1617     auto num_digits = count_digits(abs_value);
1618     out = write_int(
1619         out, num_digits, get_prefix(), specs, [this, num_digits](iterator it) {
1620           return format_decimal<Char>(it, abs_value, num_digits).end;
1621         });
1622   }
1623 
1624   void on_hex() {
1625     if (specs.alt) {
1626       prefix[prefix_size++] = '0';
1627       prefix[prefix_size++] = specs.type;
1628     }
1629     int num_digits = count_digits<4>(abs_value);
1630     out = write_int(out, num_digits, get_prefix(), specs,
1631                     [this, num_digits](iterator it) {
1632                       return format_uint<4, Char>(it, abs_value, num_digits,
1633                                                   specs.type != 'x');
1634                     });
1635   }
1636 
1637   void on_bin() {
1638     if (specs.alt) {
1639       prefix[prefix_size++] = '0';
1640       prefix[prefix_size++] = static_cast<char>(specs.type);
1641     }
1642     int num_digits = count_digits<1>(abs_value);
1643     out = write_int(out, num_digits, get_prefix(), specs,
1644                     [this, num_digits](iterator it) {
1645                       return format_uint<1, Char>(it, abs_value, num_digits);
1646                     });
1647   }
1648 
1649   void on_oct() {
1650     int num_digits = count_digits<3>(abs_value);
1651     if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
1652       // Octal prefix '0' is counted as a digit, so only add it if precision
1653       // is not greater than the number of digits.
1654       prefix[prefix_size++] = '0';
1655     }
1656     out = write_int(out, num_digits, get_prefix(), specs,
1657                     [this, num_digits](iterator it) {
1658                       return format_uint<3, Char>(it, abs_value, num_digits);
1659                     });
1660   }
1661 
1662   enum { sep_size = 1 };
1663 
1664   void on_num() {
1665     std::string groups = grouping<Char>(locale);
1666     if (groups.empty()) return on_dec();
1667     auto sep = thousands_sep<Char>(locale);
1668     if (!sep) return on_dec();
1669     int num_digits = count_digits(abs_value);
1670     int size = num_digits, n = num_digits;
1671     std::string::const_iterator group = groups.cbegin();
1672     while (group != groups.cend() && n > *group && *group > 0 &&
1673            *group != max_value<char>()) {
1674       size += sep_size;
1675       n -= *group;
1676       ++group;
1677     }
1678     if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back());
1679     char digits[40];
1680     format_decimal(digits, abs_value, num_digits);
1681     basic_memory_buffer<Char> buffer;
1682     size += static_cast<int>(prefix_size);
1683     const auto usize = to_unsigned(size);
1684     buffer.resize(usize);
1685     basic_string_view<Char> s(&sep, sep_size);
1686     // Index of a decimal digit with the least significant digit having index 0.
1687     int digit_index = 0;
1688     group = groups.cbegin();
1689     auto p = buffer.data() + size - 1;
1690     for (int i = num_digits - 1; i > 0; --i) {
1691       *p-- = static_cast<Char>(digits[i]);
1692       if (*group <= 0 || ++digit_index % *group != 0 ||
1693           *group == max_value<char>())
1694         continue;
1695       if (group + 1 != groups.cend()) {
1696         digit_index = 0;
1697         ++group;
1698       }
1699       std::uninitialized_copy(s.data(), s.data() + s.size(),
1700                               make_checked(p, s.size()));
1701       p -= s.size();
1702     }
1703     *p-- = static_cast<Char>(*digits);
1704     if (prefix_size != 0) *p = static_cast<Char>('-');
1705     auto data = buffer.data();
1706     out = write_padded<align::right>(
1707         out, specs, usize, usize,
1708         [=](iterator it) { return copy_str<Char>(data, data + size, it); });
1709   }
1710 
1711   void on_chr() { *out++ = static_cast<Char>(abs_value); }
1712 
1713   FMT_NORETURN void on_error() {
1714     FMT_THROW(format_error("invalid type specifier"));
1715   }
1716 };
1717 
1718 template <typename Char, typename OutputIt>
1719 OutputIt write_nonfinite(OutputIt out, bool isinf,
1720                          const basic_format_specs<Char>& specs,
1721                          const float_specs& fspecs) {
1722   auto str =
1723       isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
1724   constexpr size_t str_size = 3;
1725   auto sign = fspecs.sign;
1726   auto size = str_size + (sign ? 1 : 0);
1727   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1728   return write_padded(out, specs, size, [=](iterator it) {
1729     if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1730     return copy_str<Char>(str, str + str_size, it);
1731   });
1732 }
1733 
1734 // A decimal floating-point number significand * pow(10, exp).
1735 struct big_decimal_fp {
1736   const char* significand;
1737   int significand_size;
1738   int exponent;
1739 };
1740 
1741 inline int get_significand_size(const big_decimal_fp& fp) {
1742   return fp.significand_size;
1743 }
1744 template <typename T>
1745 inline int get_significand_size(const dragonbox::decimal_fp<T>& fp) {
1746   return count_digits(fp.significand);
1747 }
1748 
1749 template <typename Char, typename OutputIt>
1750 inline OutputIt write_significand(OutputIt out, const char* significand,
1751                                   int& significand_size) {
1752   return copy_str<Char>(significand, significand + significand_size, out);
1753 }
1754 template <typename Char, typename OutputIt, typename UInt>
1755 inline OutputIt write_significand(OutputIt out, UInt significand,
1756                                   int significand_size) {
1757   return format_decimal<Char>(out, significand, significand_size).end;
1758 }
1759 
1760 template <typename Char, typename UInt,
1761           FMT_ENABLE_IF(std::is_integral<UInt>::value)>
1762 inline Char* write_significand(Char* out, UInt significand,
1763                                int significand_size, int integral_size,
1764                                Char decimal_point) {
1765   if (!decimal_point)
1766     return format_decimal(out, significand, significand_size).end;
1767   auto end = format_decimal(out + 1, significand, significand_size).end;
1768   if (integral_size == 1)
1769     out[0] = out[1];
1770   else
1771     std::copy_n(out + 1, integral_size, out);
1772   out[integral_size] = decimal_point;
1773   return end;
1774 }
1775 
1776 template <typename OutputIt, typename UInt, typename Char,
1777           FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
1778 inline OutputIt write_significand(OutputIt out, UInt significand,
1779                                   int significand_size, int integral_size,
1780                                   Char decimal_point) {
1781   // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
1782   Char buffer[digits10<UInt>() + 2];
1783   auto end = write_significand(buffer, significand, significand_size,
1784                                integral_size, decimal_point);
1785   return detail::copy_str<Char>(buffer, end, out);
1786 }
1787 
1788 template <typename OutputIt, typename Char>
1789 inline OutputIt write_significand(OutputIt out, const char* significand,
1790                                   int significand_size, int integral_size,
1791                                   Char decimal_point) {
1792   out = detail::copy_str<Char>(significand, significand + integral_size, out);
1793   if (!decimal_point) return out;
1794   *out++ = decimal_point;
1795   return detail::copy_str<Char>(significand + integral_size,
1796                                 significand + significand_size, out);
1797 }
1798 
1799 template <typename OutputIt, typename DecimalFP, typename Char>
1800 OutputIt write_float(OutputIt out, const DecimalFP& fp,
1801                      const basic_format_specs<Char>& specs, float_specs fspecs,
1802                      Char decimal_point) {
1803   auto significand = fp.significand;
1804   int significand_size = get_significand_size(fp);
1805   static const Char zero = static_cast<Char>('0');
1806   auto sign = fspecs.sign;
1807   size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
1808   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1809 
1810   int output_exp = fp.exponent + significand_size - 1;
1811   auto use_exp_format = [=]() {
1812     if (fspecs.format == float_format::exp) return true;
1813     if (fspecs.format != float_format::general) return false;
1814     // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
1815     // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
1816     const int exp_lower = -4, exp_upper = 16;
1817     return output_exp < exp_lower ||
1818            output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
1819   };
1820   if (use_exp_format()) {
1821     int num_zeros = 0;
1822     if (fspecs.showpoint) {
1823       num_zeros = (std::max)(fspecs.precision - significand_size, 0);
1824       size += to_unsigned(num_zeros);
1825     } else if (significand_size == 1) {
1826       decimal_point = Char();
1827     }
1828     auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
1829     int exp_digits = 2;
1830     if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
1831 
1832     size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
1833     char exp_char = fspecs.upper ? 'E' : 'e';
1834     auto write = [=](iterator it) {
1835       if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1836       // Insert a decimal point after the first digit and add an exponent.
1837       it = write_significand(it, significand, significand_size, 1,
1838                              decimal_point);
1839       if (num_zeros > 0) it = std::fill_n(it, num_zeros, zero);
1840       *it++ = static_cast<Char>(exp_char);
1841       return write_exponent<Char>(output_exp, it);
1842     };
1843     return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)
1844                            : base_iterator(out, write(reserve(out, size)));
1845   }
1846 
1847   int exp = fp.exponent + significand_size;
1848   if (fp.exponent >= 0) {
1849     // 1234e5 -> 123400000[.0+]
1850     size += to_unsigned(fp.exponent);
1851     int num_zeros = fspecs.precision - exp;
1852 #ifdef FMT_FUZZ
1853     if (num_zeros > 5000)
1854       throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
1855 #endif
1856     if (fspecs.showpoint) {
1857       if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1;
1858       if (num_zeros > 0) size += to_unsigned(num_zeros);
1859     }
1860     return write_padded<align::right>(out, specs, size, [&](iterator it) {
1861       if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1862       it = write_significand<Char>(it, significand, significand_size);
1863       it = std::fill_n(it, fp.exponent, zero);
1864       if (!fspecs.showpoint) return it;
1865       *it++ = decimal_point;
1866       return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it;
1867     });
1868   } else if (exp > 0) {
1869     // 1234e-2 -> 12.34[0+]
1870     int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
1871     size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
1872     return write_padded<align::right>(out, specs, size, [&](iterator it) {
1873       if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1874       it = write_significand(it, significand, significand_size, exp,
1875                              decimal_point);
1876       return num_zeros > 0 ? std::fill_n(it, num_zeros, zero) : it;
1877     });
1878   }
1879   // 1234e-6 -> 0.001234
1880   int num_zeros = -exp;
1881   if (significand_size == 0 && fspecs.precision >= 0 &&
1882       fspecs.precision < num_zeros) {
1883     num_zeros = fspecs.precision;
1884   }
1885   size += 2 + to_unsigned(num_zeros);
1886   return write_padded<align::right>(out, specs, size, [&](iterator it) {
1887     if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1888     *it++ = zero;
1889     if (num_zeros == 0 && significand_size == 0 && !fspecs.showpoint) return it;
1890     *it++ = decimal_point;
1891     it = std::fill_n(it, num_zeros, zero);
1892     return write_significand<Char>(it, significand, significand_size);
1893   });
1894 }
1895 
1896 template <typename Char, typename OutputIt, typename T,
1897           FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1898 OutputIt write(OutputIt out, T value, basic_format_specs<Char> specs,
1899                locale_ref loc = {}) {
1900   if (const_check(!is_supported_floating_point(value))) return out;
1901   float_specs fspecs = parse_float_type_spec(specs);
1902   fspecs.sign = specs.sign;
1903   if (std::signbit(value)) {  // value < 0 is false for NaN so use signbit.
1904     fspecs.sign = sign::minus;
1905     value = -value;
1906   } else if (fspecs.sign == sign::minus) {
1907     fspecs.sign = sign::none;
1908   }
1909 
1910   if (!std::isfinite(value))
1911     return write_nonfinite(out, std::isinf(value), specs, fspecs);
1912 
1913   if (specs.align == align::numeric && fspecs.sign) {
1914     auto it = reserve(out, 1);
1915     *it++ = static_cast<Char>(data::signs[fspecs.sign]);
1916     out = base_iterator(out, it);
1917     fspecs.sign = sign::none;
1918     if (specs.width != 0) --specs.width;
1919   }
1920 
1921   memory_buffer buffer;
1922   if (fspecs.format == float_format::hex) {
1923     if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
1924     snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
1925     return write_bytes(out, {buffer.data(), buffer.size()}, specs);
1926   }
1927   int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
1928   if (fspecs.format == float_format::exp) {
1929     if (precision == max_value<int>())
1930       FMT_THROW(format_error("number is too big"));
1931     else
1932       ++precision;
1933   }
1934   if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1935   fspecs.use_grisu = is_fast_float<T>();
1936   int exp = format_float(promote_float(value), precision, fspecs, buffer);
1937   fspecs.precision = precision;
1938   Char point =
1939       fspecs.locale ? decimal_point<Char>(loc) : static_cast<Char>('.');
1940   auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
1941   return write_float(out, fp, specs, fspecs, point);
1942 }
1943 
1944 template <typename Char, typename OutputIt, typename T,
1945           FMT_ENABLE_IF(is_fast_float<T>::value)>
1946 OutputIt write(OutputIt out, T value) {
1947   if (const_check(!is_supported_floating_point(value))) return out;
1948 
1949   using floaty = conditional_t<std::is_same<T, long double>::value, double, T>;
1950   using uint = typename dragonbox::float_info<floaty>::carrier_uint;
1951   auto bits = bit_cast<uint>(value);
1952 
1953   auto fspecs = float_specs();
1954   auto sign_bit = bits & (uint(1) << (num_bits<uint>() - 1));
1955   if (sign_bit != 0) {
1956     fspecs.sign = sign::minus;
1957     value = -value;
1958   }
1959 
1960   static const auto specs = basic_format_specs<Char>();
1961   uint mask = exponent_mask<floaty>();
1962   if ((bits & mask) == mask)
1963     return write_nonfinite(out, std::isinf(value), specs, fspecs);
1964 
1965   auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
1966   return write_float(out, dec, specs, fspecs, static_cast<Char>('.'));
1967 }
1968 
1969 template <typename Char, typename OutputIt, typename T,
1970           FMT_ENABLE_IF(std::is_floating_point<T>::value &&
1971                         !is_fast_float<T>::value)>
1972 inline OutputIt write(OutputIt out, T value) {
1973   return write(out, value, basic_format_specs<Char>());
1974 }
1975 
1976 template <typename Char, typename OutputIt>
1977 OutputIt write_char(OutputIt out, Char value,
1978                     const basic_format_specs<Char>& specs) {
1979   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1980   return write_padded(out, specs, 1, [=](iterator it) {
1981     *it++ = value;
1982     return it;
1983   });
1984 }
1985 
1986 template <typename Char, typename OutputIt, typename UIntPtr>
1987 OutputIt write_ptr(OutputIt out, UIntPtr value,
1988                    const basic_format_specs<Char>* specs) {
1989   int num_digits = count_digits<4>(value);
1990   auto size = to_unsigned(num_digits) + size_t(2);
1991   using iterator = remove_reference_t<decltype(reserve(out, 0))>;
1992   auto write = [=](iterator it) {
1993     *it++ = static_cast<Char>('0');
1994     *it++ = static_cast<Char>('x');
1995     return format_uint<4, Char>(it, value, num_digits);
1996   };
1997   return specs ? write_padded<align::right>(out, *specs, size, write)
1998                : base_iterator(out, write(reserve(out, size)));
1999 }
2000 
2001 template <typename T> struct is_integral : std::is_integral<T> {};
2002 template <> struct is_integral<int128_t> : std::true_type {};
2003 template <> struct is_integral<uint128_t> : std::true_type {};
2004 
2005 template <typename Char, typename OutputIt>
2006 OutputIt write(OutputIt out, monostate) {
2007   FMT_ASSERT(false, "");
2008   return out;
2009 }
2010 
2011 template <typename Char, typename OutputIt,
2012           FMT_ENABLE_IF(!std::is_same<Char, char>::value)>
2013 OutputIt write(OutputIt out, string_view value) {
2014   auto it = reserve(out, value.size());
2015   it = copy_str<Char>(value.begin(), value.end(), it);
2016   return base_iterator(out, it);
2017 }
2018 
2019 template <typename Char, typename OutputIt>
2020 OutputIt write(OutputIt out, basic_string_view<Char> value) {
2021   auto it = reserve(out, value.size());
2022   it = std::copy(value.begin(), value.end(), it);
2023   return base_iterator(out, it);
2024 }
2025 
2026 template <typename Char>
2027 buffer_appender<Char> write(buffer_appender<Char> out,
2028                             basic_string_view<Char> value) {
2029   get_container(out).append(value.begin(), value.end());
2030   return out;
2031 }
2032 
2033 template <typename Char, typename OutputIt, typename T,
2034           FMT_ENABLE_IF(is_integral<T>::value &&
2035                         !std::is_same<T, bool>::value &&
2036                         !std::is_same<T, Char>::value)>
2037 OutputIt write(OutputIt out, T value) {
2038   auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
2039   bool negative = is_negative(value);
2040   // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
2041   if (negative) abs_value = ~abs_value + 1;
2042   int num_digits = count_digits(abs_value);
2043   auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
2044   auto it = reserve(out, size);
2045   if (auto ptr = to_pointer<Char>(it, size)) {
2046     if (negative) *ptr++ = static_cast<Char>('-');
2047     format_decimal<Char>(ptr, abs_value, num_digits);
2048     return out;
2049   }
2050   if (negative) *it++ = static_cast<Char>('-');
2051   it = format_decimal<Char>(it, abs_value, num_digits).end;
2052   return base_iterator(out, it);
2053 }
2054 
2055 template <typename Char, typename OutputIt>
2056 OutputIt write(OutputIt out, bool value) {
2057   return write<Char>(out, string_view(value ? "true" : "false"));
2058 }
2059 
2060 template <typename Char, typename OutputIt>
2061 OutputIt write(OutputIt out, Char value) {
2062   auto it = reserve(out, 1);
2063   *it++ = value;
2064   return base_iterator(out, it);
2065 }
2066 
2067 template <typename Char, typename OutputIt>
2068 OutputIt write(OutputIt out, const Char* value) {
2069   if (!value) {
2070     FMT_THROW(format_error("string pointer is null"));
2071   } else {
2072     auto length = std::char_traits<Char>::length(value);
2073     out = write(out, basic_string_view<Char>(value, length));
2074   }
2075   return out;
2076 }
2077 
2078 template <typename Char, typename OutputIt>
2079 OutputIt write(OutputIt out, const void* value) {
2080   return write_ptr<Char>(out, to_uintptr(value), nullptr);
2081 }
2082 
2083 template <typename Char, typename OutputIt, typename T>
2084 auto write(OutputIt out, const T& value) -> typename std::enable_if<
2085     mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value ==
2086         type::custom_type,
2087     OutputIt>::type {
2088   using context_type = basic_format_context<OutputIt, Char>;
2089   using formatter_type =
2090       conditional_t<has_formatter<T, context_type>::value,
2091                     typename context_type::template formatter_type<T>,
2092                     fallback_formatter<T, Char>>;
2093   context_type ctx(out, {}, {});
2094   return formatter_type().format(value, ctx);
2095 }
2096 
2097 // An argument visitor that formats the argument and writes it via the output
2098 // iterator. It's a class and not a generic lambda for compatibility with C++11.
2099 template <typename OutputIt, typename Char> struct default_arg_formatter {
2100   using context = basic_format_context<OutputIt, Char>;
2101 
2102   OutputIt out;
2103   basic_format_args<context> args;
2104   locale_ref loc;
2105 
2106   template <typename T> OutputIt operator()(T value) {
2107     return write<Char>(out, value);
2108   }
2109 
2110   OutputIt operator()(typename basic_format_arg<context>::handle handle) {
2111     basic_format_parse_context<Char> parse_ctx({});
2112     basic_format_context<OutputIt, Char> format_ctx(out, args, loc);
2113     handle.format(parse_ctx, format_ctx);
2114     return format_ctx.out();
2115   }
2116 };
2117 
2118 template <typename OutputIt, typename Char,
2119           typename ErrorHandler = error_handler>
2120 class arg_formatter_base {
2121  public:
2122   using iterator = OutputIt;
2123   using char_type = Char;
2124   using format_specs = basic_format_specs<Char>;
2125 
2126  private:
2127   iterator out_;
2128   locale_ref locale_;
2129   format_specs* specs_;
2130 
2131   // Attempts to reserve space for n extra characters in the output range.
2132   // Returns a pointer to the reserved range or a reference to out_.
2133   auto reserve(size_t n) -> decltype(detail::reserve(out_, n)) {
2134     return detail::reserve(out_, n);
2135   }
2136 
2137   using reserve_iterator = remove_reference_t<decltype(
2138       detail::reserve(std::declval<iterator&>(), 0))>;
2139 
2140   template <typename T> void write_int(T value, const format_specs& spec) {
2141     using uint_type = uint32_or_64_or_128_t<T>;
2142     int_writer<iterator, Char, uint_type> w(out_, locale_, value, spec);
2143     handle_int_type_spec(spec.type, w);
2144     out_ = w.out;
2145   }
2146 
2147   void write(char value) {
2148     auto&& it = reserve(1);
2149     *it++ = value;
2150   }
2151 
2152   template <typename Ch, FMT_ENABLE_IF(std::is_same<Ch, Char>::value)>
2153   void write(Ch value) {
2154     out_ = detail::write<Char>(out_, value);
2155   }
2156 
2157   void write(string_view value) {
2158     auto&& it = reserve(value.size());
2159     it = copy_str<Char>(value.begin(), value.end(), it);
2160   }
2161   void write(wstring_view value) {
2162     static_assert(std::is_same<Char, wchar_t>::value, "");
2163     auto&& it = reserve(value.size());
2164     it = std::copy(value.begin(), value.end(), it);
2165   }
2166 
2167   template <typename Ch>
2168   void write(const Ch* s, size_t size, const format_specs& specs) {
2169     auto width = specs.width != 0
2170                      ? count_code_points(basic_string_view<Ch>(s, size))
2171                      : 0;
2172     out_ = write_padded(out_, specs, size, width, [=](reserve_iterator it) {
2173       return copy_str<Char>(s, s + size, it);
2174     });
2175   }
2176 
2177   template <typename Ch>
2178   void write(basic_string_view<Ch> s, const format_specs& specs = {}) {
2179     out_ = detail::write(out_, s, specs);
2180   }
2181 
2182   void write_pointer(const void* p) {
2183     out_ = write_ptr<char_type>(out_, to_uintptr(p), specs_);
2184   }
2185 
2186   struct char_spec_handler : ErrorHandler {
2187     arg_formatter_base& formatter;
2188     Char value;
2189 
2190     char_spec_handler(arg_formatter_base& f, Char val)
2191         : formatter(f), value(val) {}
2192 
2193     void on_int() {
2194       // char is only formatted as int if there are specs.
2195       formatter.write_int(static_cast<int>(value), *formatter.specs_);
2196     }
2197     void on_char() {
2198       if (formatter.specs_)
2199         formatter.out_ = write_char(formatter.out_, value, *formatter.specs_);
2200       else
2201         formatter.write(value);
2202     }
2203   };
2204 
2205   struct cstring_spec_handler : error_handler {
2206     arg_formatter_base& formatter;
2207     const Char* value;
2208 
2209     cstring_spec_handler(arg_formatter_base& f, const Char* val)
2210         : formatter(f), value(val) {}
2211 
2212     void on_string() { formatter.write(value); }
2213     void on_pointer() { formatter.write_pointer(value); }
2214   };
2215 
2216  protected:
2217   iterator out() { return out_; }
2218   format_specs* specs() { return specs_; }
2219 
2220   void write(bool value) {
2221     if (specs_)
2222       write(string_view(value ? "true" : "false"), *specs_);
2223     else
2224       out_ = detail::write<Char>(out_, value);
2225   }
2226 
2227   void write(const Char* value) {
2228     if (!value) {
2229       FMT_THROW(format_error("string pointer is null"));
2230     } else {
2231       auto length = std::char_traits<char_type>::length(value);
2232       basic_string_view<char_type> sv(value, length);
2233       specs_ ? write(sv, *specs_) : write(sv);
2234     }
2235   }
2236 
2237  public:
2238   arg_formatter_base(OutputIt out, format_specs* s, locale_ref loc)
2239       : out_(out), locale_(loc), specs_(s) {}
2240 
2241   iterator operator()(monostate) {
2242     FMT_ASSERT(false, "invalid argument type");
2243     return out_;
2244   }
2245 
2246   template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
2247   FMT_INLINE iterator operator()(T value) {
2248     if (specs_)
2249       write_int(value, *specs_);
2250     else
2251       out_ = detail::write<Char>(out_, value);
2252     return out_;
2253   }
2254 
2255   iterator operator()(Char value) {
2256     handle_char_specs(specs_,
2257                       char_spec_handler(*this, static_cast<Char>(value)));
2258     return out_;
2259   }
2260 
2261   iterator operator()(bool value) {
2262     if (specs_ && specs_->type) return (*this)(value ? 1 : 0);
2263     write(value != 0);
2264     return out_;
2265   }
2266 
2267   template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
2268   iterator operator()(T value) {
2269     auto specs = specs_ ? *specs_ : format_specs();
2270     if (const_check(is_supported_floating_point(value)))
2271       out_ = detail::write(out_, value, specs, locale_);
2272     else
2273       FMT_ASSERT(false, "unsupported float argument type");
2274     return out_;
2275   }
2276 
2277   iterator operator()(const Char* value) {
2278     if (!specs_) return write(value), out_;
2279     handle_cstring_type_spec(specs_->type, cstring_spec_handler(*this, value));
2280     return out_;
2281   }
2282 
2283   iterator operator()(basic_string_view<Char> value) {
2284     if (specs_) {
2285       check_string_type_spec(specs_->type, error_handler());
2286       write(value, *specs_);
2287     } else {
2288       write(value);
2289     }
2290     return out_;
2291   }
2292 
2293   iterator operator()(const void* value) {
2294     if (specs_) check_pointer_type_spec(specs_->type, error_handler());
2295     write_pointer(value);
2296     return out_;
2297   }
2298 };
2299 
2300 /** The default argument formatter. */
2301 template <typename OutputIt, typename Char>
2302 class arg_formatter : public arg_formatter_base<OutputIt, Char> {
2303  private:
2304   using char_type = Char;
2305   using base = arg_formatter_base<OutputIt, Char>;
2306   using context_type = basic_format_context<OutputIt, Char>;
2307 
2308   context_type& ctx_;
2309   basic_format_parse_context<char_type>* parse_ctx_;
2310   const Char* ptr_;
2311 
2312  public:
2313   using iterator = typename base::iterator;
2314   using format_specs = typename base::format_specs;
2315 
2316   /**
2317     \rst
2318     Constructs an argument formatter object.
2319     *ctx* is a reference to the formatting context,
2320     *specs* contains format specifier information for standard argument types.
2321     \endrst
2322    */
2323   explicit arg_formatter(
2324       context_type& ctx,
2325       basic_format_parse_context<char_type>* parse_ctx = nullptr,
2326       format_specs* specs = nullptr, const Char* ptr = nullptr)
2327       : base(ctx.out(), specs, ctx.locale()),
2328         ctx_(ctx),
2329         parse_ctx_(parse_ctx),
2330         ptr_(ptr) {}
2331 
2332   using base::operator();
2333 
2334   /** Formats an argument of a user-defined type. */
2335   iterator operator()(typename basic_format_arg<context_type>::handle handle) {
2336     if (ptr_) advance_to(*parse_ctx_, ptr_);
2337     handle.format(*parse_ctx_, ctx_);
2338     return ctx_.out();
2339   }
2340 };
2341 
2342 template <typename Char> FMT_CONSTEXPR bool is_name_start(Char c) {
2343   return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || '_' == c;
2344 }
2345 
2346 // Parses the range [begin, end) as an unsigned integer. This function assumes
2347 // that the range is non-empty and the first character is a digit.
2348 template <typename Char, typename ErrorHandler>
2349 FMT_CONSTEXPR int parse_nonnegative_int(const Char*& begin, const Char* end,
2350                                         ErrorHandler&& eh) {
2351   FMT_ASSERT(begin != end && '0' <= *begin && *begin <= '9', "");
2352   unsigned value = 0;
2353   // Convert to unsigned to prevent a warning.
2354   constexpr unsigned max_int = max_value<int>();
2355   unsigned big = max_int / 10;
2356   do {
2357     // Check for overflow.
2358     if (value > big) {
2359       value = max_int + 1;
2360       break;
2361     }
2362     value = value * 10 + unsigned(*begin - '0');
2363     ++begin;
2364   } while (begin != end && '0' <= *begin && *begin <= '9');
2365   if (value > max_int) eh.on_error("number is too big");
2366   return static_cast<int>(value);
2367 }
2368 
2369 template <typename Context> class custom_formatter {
2370  private:
2371   using char_type = typename Context::char_type;
2372 
2373   basic_format_parse_context<char_type>& parse_ctx_;
2374   Context& ctx_;
2375 
2376  public:
2377   explicit custom_formatter(basic_format_parse_context<char_type>& parse_ctx,
2378                             Context& ctx)
2379       : parse_ctx_(parse_ctx), ctx_(ctx) {}
2380 
2381   void operator()(typename basic_format_arg<Context>::handle h) const {
2382     h.format(parse_ctx_, ctx_);
2383   }
2384 
2385   template <typename T> void operator()(T) const {}
2386 };
2387 
2388 template <typename T>
2389 using is_integer =
2390     bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
2391                   !std::is_same<T, char>::value &&
2392                   !std::is_same<T, wchar_t>::value>;
2393 
2394 template <typename ErrorHandler> class width_checker {
2395  public:
2396   explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {}
2397 
2398   template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2399   FMT_CONSTEXPR unsigned long long operator()(T value) {
2400     if (is_negative(value)) handler_.on_error("negative width");
2401     return static_cast<unsigned long long>(value);
2402   }
2403 
2404   template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2405   FMT_CONSTEXPR unsigned long long operator()(T) {
2406     handler_.on_error("width is not integer");
2407     return 0;
2408   }
2409 
2410  private:
2411   ErrorHandler& handler_;
2412 };
2413 
2414 template <typename ErrorHandler> class precision_checker {
2415  public:
2416   explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {}
2417 
2418   template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2419   FMT_CONSTEXPR unsigned long long operator()(T value) {
2420     if (is_negative(value)) handler_.on_error("negative precision");
2421     return static_cast<unsigned long long>(value);
2422   }
2423 
2424   template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2425   FMT_CONSTEXPR unsigned long long operator()(T) {
2426     handler_.on_error("precision is not integer");
2427     return 0;
2428   }
2429 
2430  private:
2431   ErrorHandler& handler_;
2432 };
2433 
2434 // A format specifier handler that sets fields in basic_format_specs.
2435 template <typename Char> class specs_setter {
2436  public:
2437   explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char>& specs)
2438       : specs_(specs) {}
2439 
2440   FMT_CONSTEXPR specs_setter(const specs_setter& other)
2441       : specs_(other.specs_) {}
2442 
2443   FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; }
2444   FMT_CONSTEXPR void on_fill(basic_string_view<Char> fill) {
2445     specs_.fill = fill;
2446   }
2447   FMT_CONSTEXPR void on_plus() { specs_.sign = sign::plus; }
2448   FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; }
2449   FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; }
2450   FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
2451 
2452   FMT_CONSTEXPR void on_zero() {
2453     specs_.align = align::numeric;
2454     specs_.fill[0] = Char('0');
2455   }
2456 
2457   FMT_CONSTEXPR void on_width(int width) { specs_.width = width; }
2458   FMT_CONSTEXPR void on_precision(int precision) {
2459     specs_.precision = precision;
2460   }
2461   FMT_CONSTEXPR void end_precision() {}
2462 
2463   FMT_CONSTEXPR void on_type(Char type) {
2464     specs_.type = static_cast<char>(type);
2465   }
2466 
2467  protected:
2468   basic_format_specs<Char>& specs_;
2469 };
2470 
2471 template <typename ErrorHandler> class numeric_specs_checker {
2472  public:
2473   FMT_CONSTEXPR numeric_specs_checker(ErrorHandler& eh, detail::type arg_type)
2474       : error_handler_(eh), arg_type_(arg_type) {}
2475 
2476   FMT_CONSTEXPR void require_numeric_argument() {
2477     if (!is_arithmetic_type(arg_type_))
2478       error_handler_.on_error("format specifier requires numeric argument");
2479   }
2480 
2481   FMT_CONSTEXPR void check_sign() {
2482     require_numeric_argument();
2483     if (is_integral_type(arg_type_) && arg_type_ != type::int_type &&
2484         arg_type_ != type::long_long_type && arg_type_ != type::char_type) {
2485       error_handler_.on_error("format specifier requires signed argument");
2486     }
2487   }
2488 
2489   FMT_CONSTEXPR void check_precision() {
2490     if (is_integral_type(arg_type_) || arg_type_ == type::pointer_type)
2491       error_handler_.on_error("precision not allowed for this argument type");
2492   }
2493 
2494  private:
2495   ErrorHandler& error_handler_;
2496   detail::type arg_type_;
2497 };
2498 
2499 // A format specifier handler that checks if specifiers are consistent with the
2500 // argument type.
2501 template <typename Handler> class specs_checker : public Handler {
2502  private:
2503   numeric_specs_checker<Handler> checker_;
2504 
2505   // Suppress an MSVC warning about using this in initializer list.
2506   FMT_CONSTEXPR Handler& error_handler() { return *this; }
2507 
2508  public:
2509   FMT_CONSTEXPR specs_checker(const Handler& handler, detail::type arg_type)
2510       : Handler(handler), checker_(error_handler(), arg_type) {}
2511 
2512   FMT_CONSTEXPR specs_checker(const specs_checker& other)
2513       : Handler(other), checker_(error_handler(), other.arg_type_) {}
2514 
2515   FMT_CONSTEXPR void on_align(align_t align) {
2516     if (align == align::numeric) checker_.require_numeric_argument();
2517     Handler::on_align(align);
2518   }
2519 
2520   FMT_CONSTEXPR void on_plus() {
2521     checker_.check_sign();
2522     Handler::on_plus();
2523   }
2524 
2525   FMT_CONSTEXPR void on_minus() {
2526     checker_.check_sign();
2527     Handler::on_minus();
2528   }
2529 
2530   FMT_CONSTEXPR void on_space() {
2531     checker_.check_sign();
2532     Handler::on_space();
2533   }
2534 
2535   FMT_CONSTEXPR void on_hash() {
2536     checker_.require_numeric_argument();
2537     Handler::on_hash();
2538   }
2539 
2540   FMT_CONSTEXPR void on_zero() {
2541     checker_.require_numeric_argument();
2542     Handler::on_zero();
2543   }
2544 
2545   FMT_CONSTEXPR void end_precision() { checker_.check_precision(); }
2546 };
2547 
2548 template <template <typename> class Handler, typename FormatArg,
2549           typename ErrorHandler>
2550 FMT_CONSTEXPR int get_dynamic_spec(FormatArg arg, ErrorHandler eh) {
2551   unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
2552   if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big");
2553   return static_cast<int>(value);
2554 }
2555 
2556 struct auto_id {};
2557 
2558 template <typename Context, typename ID>
2559 FMT_CONSTEXPR typename Context::format_arg get_arg(Context& ctx, ID id) {
2560   auto arg = ctx.arg(id);
2561   if (!arg) ctx.on_error("argument not found");
2562   return arg;
2563 }
2564 
2565 // The standard format specifier handler with checking.
2566 template <typename ParseContext, typename Context>
2567 class specs_handler : public specs_setter<typename Context::char_type> {
2568  public:
2569   using char_type = typename Context::char_type;
2570 
2571   FMT_CONSTEXPR specs_handler(basic_format_specs<char_type>& specs,
2572                               ParseContext& parse_ctx, Context& ctx)
2573       : specs_setter<char_type>(specs),
2574         parse_context_(parse_ctx),
2575         context_(ctx) {}
2576 
2577   template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
2578     this->specs_.width = get_dynamic_spec<width_checker>(
2579         get_arg(arg_id), context_.error_handler());
2580   }
2581 
2582   template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
2583     this->specs_.precision = get_dynamic_spec<precision_checker>(
2584         get_arg(arg_id), context_.error_handler());
2585   }
2586 
2587   void on_error(const char* message) { context_.on_error(message); }
2588 
2589  private:
2590   // This is only needed for compatibility with gcc 4.4.
2591   using format_arg = typename Context::format_arg;
2592 
2593   FMT_CONSTEXPR format_arg get_arg(auto_id) {
2594     return detail::get_arg(context_, parse_context_.next_arg_id());
2595   }
2596 
2597   FMT_CONSTEXPR format_arg get_arg(int arg_id) {
2598     parse_context_.check_arg_id(arg_id);
2599     return detail::get_arg(context_, arg_id);
2600   }
2601 
2602   FMT_CONSTEXPR format_arg get_arg(basic_string_view<char_type> arg_id) {
2603     parse_context_.check_arg_id(arg_id);
2604     return detail::get_arg(context_, arg_id);
2605   }
2606 
2607   ParseContext& parse_context_;
2608   Context& context_;
2609 };
2610 
2611 enum class arg_id_kind { none, index, name };
2612 
2613 // An argument reference.
2614 template <typename Char> struct arg_ref {
2615   FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}
2616 
2617   FMT_CONSTEXPR explicit arg_ref(int index)
2618       : kind(arg_id_kind::index), val(index) {}
2619   FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)
2620       : kind(arg_id_kind::name), val(name) {}
2621 
2622   FMT_CONSTEXPR arg_ref& operator=(int idx) {
2623     kind = arg_id_kind::index;
2624     val.index = idx;
2625     return *this;
2626   }
2627 
2628   arg_id_kind kind;
2629   union value {
2630     FMT_CONSTEXPR value(int id = 0) : index{id} {}
2631     FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {}
2632 
2633     int index;
2634     basic_string_view<Char> name;
2635   } val;
2636 };
2637 
2638 // Format specifiers with width and precision resolved at formatting rather
2639 // than parsing time to allow re-using the same parsed specifiers with
2640 // different sets of arguments (precompilation of format strings).
2641 template <typename Char>
2642 struct dynamic_format_specs : basic_format_specs<Char> {
2643   arg_ref<Char> width_ref;
2644   arg_ref<Char> precision_ref;
2645 };
2646 
2647 // Format spec handler that saves references to arguments representing dynamic
2648 // width and precision to be resolved at formatting time.
2649 template <typename ParseContext>
2650 class dynamic_specs_handler
2651     : public specs_setter<typename ParseContext::char_type> {
2652  public:
2653   using char_type = typename ParseContext::char_type;
2654 
2655   FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type>& specs,
2656                                       ParseContext& ctx)
2657       : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}
2658 
2659   FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other)
2660       : specs_setter<char_type>(other),
2661         specs_(other.specs_),
2662         context_(other.context_) {}
2663 
2664   template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
2665     specs_.width_ref = make_arg_ref(arg_id);
2666   }
2667 
2668   template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
2669     specs_.precision_ref = make_arg_ref(arg_id);
2670   }
2671 
2672   FMT_CONSTEXPR void on_error(const char* message) {
2673     context_.on_error(message);
2674   }
2675 
2676  private:
2677   using arg_ref_type = arg_ref<char_type>;
2678 
2679   FMT_CONSTEXPR arg_ref_type make_arg_ref(int arg_id) {
2680     context_.check_arg_id(arg_id);
2681     return arg_ref_type(arg_id);
2682   }
2683 
2684   FMT_CONSTEXPR arg_ref_type make_arg_ref(auto_id) {
2685     return arg_ref_type(context_.next_arg_id());
2686   }
2687 
2688   FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<char_type> arg_id) {
2689     context_.check_arg_id(arg_id);
2690     basic_string_view<char_type> format_str(
2691         context_.begin(), to_unsigned(context_.end() - context_.begin()));
2692     return arg_ref_type(arg_id);
2693   }
2694 
2695   dynamic_format_specs<char_type>& specs_;
2696   ParseContext& context_;
2697 };
2698 
2699 template <typename Char, typename IDHandler>
2700 FMT_CONSTEXPR const Char* parse_arg_id(const Char* begin, const Char* end,
2701                                        IDHandler&& handler) {
2702   FMT_ASSERT(begin != end, "");
2703   Char c = *begin;
2704   if (c == '}' || c == ':') {
2705     handler();
2706     return begin;
2707   }
2708   if (c >= '0' && c <= '9') {
2709     int index = 0;
2710     if (c != '0')
2711       index = parse_nonnegative_int(begin, end, handler);
2712     else
2713       ++begin;
2714     if (begin == end || (*begin != '}' && *begin != ':'))
2715       handler.on_error("invalid format string");
2716     else
2717       handler(index);
2718     return begin;
2719   }
2720   if (!is_name_start(c)) {
2721     handler.on_error("invalid format string");
2722     return begin;
2723   }
2724   auto it = begin;
2725   do {
2726     ++it;
2727   } while (it != end && (is_name_start(c = *it) || ('0' <= c && c <= '9')));
2728   handler(basic_string_view<Char>(begin, to_unsigned(it - begin)));
2729   return it;
2730 }
2731 
2732 // Adapts SpecHandler to IDHandler API for dynamic width.
2733 template <typename SpecHandler, typename Char> struct width_adapter {
2734   explicit FMT_CONSTEXPR width_adapter(SpecHandler& h) : handler(h) {}
2735 
2736   FMT_CONSTEXPR void operator()() { handler.on_dynamic_width(auto_id()); }
2737   FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_width(id); }
2738   FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2739     handler.on_dynamic_width(id);
2740   }
2741 
2742   FMT_CONSTEXPR void on_error(const char* message) {
2743     handler.on_error(message);
2744   }
2745 
2746   SpecHandler& handler;
2747 };
2748 
2749 // Adapts SpecHandler to IDHandler API for dynamic precision.
2750 template <typename SpecHandler, typename Char> struct precision_adapter {
2751   explicit FMT_CONSTEXPR precision_adapter(SpecHandler& h) : handler(h) {}
2752 
2753   FMT_CONSTEXPR void operator()() { handler.on_dynamic_precision(auto_id()); }
2754   FMT_CONSTEXPR void operator()(int id) { handler.on_dynamic_precision(id); }
2755   FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2756     handler.on_dynamic_precision(id);
2757   }
2758 
2759   FMT_CONSTEXPR void on_error(const char* message) {
2760     handler.on_error(message);
2761   }
2762 
2763   SpecHandler& handler;
2764 };
2765 
2766 template <typename Char>
2767 FMT_CONSTEXPR int code_point_length(const Char* begin) {
2768   if (const_check(sizeof(Char) != 1)) return 1;
2769   constexpr char lengths[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
2770                               0, 0, 0, 0, 0, 0, 0, 0, 2, 2, 2, 2, 3, 3, 4, 0};
2771   int len = lengths[static_cast<unsigned char>(*begin) >> 3];
2772 
2773   // Compute the pointer to the next character early so that the next
2774   // iteration can start working on the next character. Neither Clang
2775   // nor GCC figure out this reordering on their own.
2776   return len + !len;
2777 }
2778 
2779 template <typename Char> constexpr bool is_ascii_letter(Char c) {
2780   return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
2781 }
2782 
2783 // Converts a character to ASCII. Returns a number > 127 on conversion failure.
2784 template <typename Char, FMT_ENABLE_IF(std::is_integral<Char>::value)>
2785 constexpr Char to_ascii(Char value) {
2786   return value;
2787 }
2788 template <typename Char, FMT_ENABLE_IF(std::is_enum<Char>::value)>
2789 constexpr typename std::underlying_type<Char>::type to_ascii(Char value) {
2790   return value;
2791 }
2792 
2793 // Parses fill and alignment.
2794 template <typename Char, typename Handler>
2795 FMT_CONSTEXPR const Char* parse_align(const Char* begin, const Char* end,
2796                                       Handler&& handler) {
2797   FMT_ASSERT(begin != end, "");
2798   auto align = align::none;
2799   auto p = begin + code_point_length(begin);
2800   if (p >= end) p = begin;
2801   for (;;) {
2802     switch (to_ascii(*p)) {
2803     case '<':
2804       align = align::left;
2805       break;
2806     case '>':
2807       align = align::right;
2808       break;
2809 #if FMT_DEPRECATED_NUMERIC_ALIGN
2810     case '=':
2811       align = align::numeric;
2812       break;
2813 #endif
2814     case '^':
2815       align = align::center;
2816       break;
2817     }
2818     if (align != align::none) {
2819       if (p != begin) {
2820         auto c = *begin;
2821         if (c == '{')
2822           return handler.on_error("invalid fill character '{'"), begin;
2823         handler.on_fill(basic_string_view<Char>(begin, to_unsigned(p - begin)));
2824         begin = p + 1;
2825       } else
2826         ++begin;
2827       handler.on_align(align);
2828       break;
2829     } else if (p == begin) {
2830       break;
2831     }
2832     p = begin;
2833   }
2834   return begin;
2835 }
2836 
2837 template <typename Char, typename Handler>
2838 FMT_CONSTEXPR const Char* parse_width(const Char* begin, const Char* end,
2839                                       Handler&& handler) {
2840   FMT_ASSERT(begin != end, "");
2841   if ('0' <= *begin && *begin <= '9') {
2842     handler.on_width(parse_nonnegative_int(begin, end, handler));
2843   } else if (*begin == '{') {
2844     ++begin;
2845     if (begin != end)
2846       begin = parse_arg_id(begin, end, width_adapter<Handler, Char>(handler));
2847     if (begin == end || *begin != '}')
2848       return handler.on_error("invalid format string"), begin;
2849     ++begin;
2850   }
2851   return begin;
2852 }
2853 
2854 template <typename Char, typename Handler>
2855 FMT_CONSTEXPR const Char* parse_precision(const Char* begin, const Char* end,
2856                                           Handler&& handler) {
2857   ++begin;
2858   auto c = begin != end ? *begin : Char();
2859   if ('0' <= c && c <= '9') {
2860     handler.on_precision(parse_nonnegative_int(begin, end, handler));
2861   } else if (c == '{') {
2862     ++begin;
2863     if (begin != end) {
2864       begin =
2865           parse_arg_id(begin, end, precision_adapter<Handler, Char>(handler));
2866     }
2867     if (begin == end || *begin++ != '}')
2868       return handler.on_error("invalid format string"), begin;
2869   } else {
2870     return handler.on_error("missing precision specifier"), begin;
2871   }
2872   handler.end_precision();
2873   return begin;
2874 }
2875 
2876 // Parses standard format specifiers and sends notifications about parsed
2877 // components to handler.
2878 template <typename Char, typename SpecHandler>
2879 FMT_CONSTEXPR const Char* parse_format_specs(const Char* begin, const Char* end,
2880                                              SpecHandler&& handler) {
2881   if (begin == end) return begin;
2882 
2883   begin = parse_align(begin, end, handler);
2884   if (begin == end) return begin;
2885 
2886   // Parse sign.
2887   switch (to_ascii(*begin)) {
2888   case '+':
2889     handler.on_plus();
2890     ++begin;
2891     break;
2892   case '-':
2893     handler.on_minus();
2894     ++begin;
2895     break;
2896   case ' ':
2897     handler.on_space();
2898     ++begin;
2899     break;
2900   }
2901   if (begin == end) return begin;
2902 
2903   if (*begin == '#') {
2904     handler.on_hash();
2905     if (++begin == end) return begin;
2906   }
2907 
2908   // Parse zero flag.
2909   if (*begin == '0') {
2910     handler.on_zero();
2911     if (++begin == end) return begin;
2912   }
2913 
2914   begin = parse_width(begin, end, handler);
2915   if (begin == end) return begin;
2916 
2917   // Parse precision.
2918   if (*begin == '.') {
2919     begin = parse_precision(begin, end, handler);
2920   }
2921 
2922   // Parse type.
2923   if (begin != end && *begin != '}') handler.on_type(*begin++);
2924   return begin;
2925 }
2926 
2927 // Return the result via the out param to workaround gcc bug 77539.
2928 template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
2929 FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr& out) {
2930   for (out = first; out != last; ++out) {
2931     if (*out == value) return true;
2932   }
2933   return false;
2934 }
2935 
2936 template <>
2937 inline bool find<false, char>(const char* first, const char* last, char value,
2938                               const char*& out) {
2939   out = static_cast<const char*>(
2940       std::memchr(first, value, detail::to_unsigned(last - first)));
2941   return out != nullptr;
2942 }
2943 
2944 template <typename Handler, typename Char> struct id_adapter {
2945   Handler& handler;
2946   int arg_id;
2947 
2948   FMT_CONSTEXPR void operator()() { arg_id = handler.on_arg_id(); }
2949   FMT_CONSTEXPR void operator()(int id) { arg_id = handler.on_arg_id(id); }
2950   FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2951     arg_id = handler.on_arg_id(id);
2952   }
2953   FMT_CONSTEXPR void on_error(const char* message) {
2954     handler.on_error(message);
2955   }
2956 };
2957 
2958 template <typename Char, typename Handler>
2959 FMT_CONSTEXPR const Char* parse_replacement_field(const Char* begin,
2960                                                   const Char* end,
2961                                                   Handler&& handler) {
2962   ++begin;
2963   if (begin == end) return handler.on_error("invalid format string"), end;
2964   if (*begin == '}') {
2965     handler.on_replacement_field(handler.on_arg_id(), begin);
2966   } else if (*begin == '{') {
2967     handler.on_text(begin, begin + 1);
2968   } else {
2969     auto adapter = id_adapter<Handler, Char>{handler, 0};
2970     begin = parse_arg_id(begin, end, adapter);
2971     Char c = begin != end ? *begin : Char();
2972     if (c == '}') {
2973       handler.on_replacement_field(adapter.arg_id, begin);
2974     } else if (c == ':') {
2975       begin = handler.on_format_specs(adapter.arg_id, begin + 1, end);
2976       if (begin == end || *begin != '}')
2977         return handler.on_error("unknown format specifier"), end;
2978     } else {
2979       return handler.on_error("missing '}' in format string"), end;
2980     }
2981   }
2982   return begin + 1;
2983 }
2984 
2985 template <bool IS_CONSTEXPR, typename Char, typename Handler>
2986 FMT_CONSTEXPR_DECL FMT_INLINE void parse_format_string(
2987     basic_string_view<Char> format_str, Handler&& handler) {
2988   auto begin = format_str.data();
2989   auto end = begin + format_str.size();
2990   if (end - begin < 32) {
2991     // Use a simple loop instead of memchr for small strings.
2992     const Char* p = begin;
2993     while (p != end) {
2994       auto c = *p++;
2995       if (c == '{') {
2996         handler.on_text(begin, p - 1);
2997         begin = p = parse_replacement_field(p - 1, end, handler);
2998       } else if (c == '}') {
2999         if (p == end || *p != '}')
3000           return handler.on_error("unmatched '}' in format string");
3001         handler.on_text(begin, p);
3002         begin = ++p;
3003       }
3004     }
3005     handler.on_text(begin, end);
3006     return;
3007   }
3008   struct writer {
3009     FMT_CONSTEXPR void operator()(const Char* pbegin, const Char* pend) {
3010       if (pbegin == pend) return;
3011       for (;;) {
3012         const Char* p = nullptr;
3013         if (!find<IS_CONSTEXPR>(pbegin, pend, '}', p))
3014           return handler_.on_text(pbegin, pend);
3015         ++p;
3016         if (p == pend || *p != '}')
3017           return handler_.on_error("unmatched '}' in format string");
3018         handler_.on_text(pbegin, p);
3019         pbegin = p + 1;
3020       }
3021     }
3022     Handler& handler_;
3023   } write{handler};
3024   while (begin != end) {
3025     // Doing two passes with memchr (one for '{' and another for '}') is up to
3026     // 2.5x faster than the naive one-pass implementation on big format strings.
3027     const Char* p = begin;
3028     if (*begin != '{' && !find<IS_CONSTEXPR>(begin + 1, end, '{', p))
3029       return write(begin, end);
3030     write(begin, p);
3031     begin = parse_replacement_field(p, end, handler);
3032   }
3033 }
3034 
3035 template <typename T, typename ParseContext>
3036 FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
3037     ParseContext& ctx) {
3038   using char_type = typename ParseContext::char_type;
3039   using context = buffer_context<char_type>;
3040   using mapped_type =
3041       conditional_t<detail::mapped_type_constant<T, context>::value !=
3042                         type::custom_type,
3043                     decltype(arg_mapper<context>().map(std::declval<T>())), T>;
3044   auto f = conditional_t<has_formatter<mapped_type, context>::value,
3045                          formatter<mapped_type, char_type>,
3046                          detail::fallback_formatter<T, char_type>>();
3047   return f.parse(ctx);
3048 }
3049 
3050 template <typename OutputIt, typename Char, typename Context>
3051 struct format_handler : detail::error_handler {
3052   basic_format_parse_context<Char> parse_context;
3053   Context context;
3054 
3055   format_handler(OutputIt out, basic_string_view<Char> str,
3056                  basic_format_args<Context> format_args, detail::locale_ref loc)
3057       : parse_context(str), context(out, format_args, loc) {}
3058 
3059   void on_text(const Char* begin, const Char* end) {
3060     auto size = to_unsigned(end - begin);
3061     auto out = context.out();
3062     auto&& it = reserve(out, size);
3063     it = std::copy_n(begin, size, it);
3064     context.advance_to(out);
3065   }
3066 
3067   int on_arg_id() { return parse_context.next_arg_id(); }
3068   int on_arg_id(int id) { return parse_context.check_arg_id(id), id; }
3069   int on_arg_id(basic_string_view<Char> id) {
3070     int arg_id = context.arg_id(id);
3071     if (arg_id < 0) on_error("argument not found");
3072     return arg_id;
3073   }
3074 
3075   FMT_INLINE void on_replacement_field(int id, const Char*) {
3076     auto arg = get_arg(context, id);
3077     context.advance_to(visit_format_arg(
3078         default_arg_formatter<OutputIt, Char>{context.out(), context.args(),
3079                                               context.locale()},
3080         arg));
3081   }
3082 
3083   const Char* on_format_specs(int id, const Char* begin, const Char* end) {
3084     auto arg = get_arg(context, id);
3085     if (arg.type() == type::custom_type) {
3086       advance_to(parse_context, begin);
3087       visit_format_arg(custom_formatter<Context>(parse_context, context), arg);
3088       return parse_context.begin();
3089     }
3090     auto specs = basic_format_specs<Char>();
3091     if (begin + 1 < end && begin[1] == '}' && is_ascii_letter(*begin)) {
3092       specs.type = static_cast<char>(*begin++);
3093     } else {
3094       using parse_context_t = basic_format_parse_context<Char>;
3095       specs_checker<specs_handler<parse_context_t, Context>> handler(
3096           specs_handler<parse_context_t, Context>(specs, parse_context,
3097                                                   context),
3098           arg.type());
3099       begin = parse_format_specs(begin, end, handler);
3100       if (begin == end || *begin != '}')
3101         on_error("missing '}' in format string");
3102     }
3103     context.advance_to(visit_format_arg(
3104         arg_formatter<OutputIt, Char>(context, &parse_context, &specs), arg));
3105     return begin;
3106   }
3107 };
3108 
3109 // A parse context with extra argument id checks. It is only used at compile
3110 // time because adding checks at runtime would introduce substantial overhead
3111 // and would be redundant since argument ids are checked when arguments are
3112 // retrieved anyway.
3113 template <typename Char, typename ErrorHandler = error_handler>
3114 class compile_parse_context
3115     : public basic_format_parse_context<Char, ErrorHandler> {
3116  private:
3117   int num_args_;
3118   using base = basic_format_parse_context<Char, ErrorHandler>;
3119 
3120  public:
3121   explicit FMT_CONSTEXPR compile_parse_context(
3122       basic_string_view<Char> format_str, int num_args = max_value<int>(),
3123       ErrorHandler eh = {})
3124       : base(format_str, eh), num_args_(num_args) {}
3125 
3126   FMT_CONSTEXPR int next_arg_id() {
3127     int id = base::next_arg_id();
3128     if (id >= num_args_) this->on_error("argument not found");
3129     return id;
3130   }
3131 
3132   FMT_CONSTEXPR void check_arg_id(int id) {
3133     base::check_arg_id(id);
3134     if (id >= num_args_) this->on_error("argument not found");
3135   }
3136   using base::check_arg_id;
3137 };
3138 
3139 template <typename Char, typename ErrorHandler, typename... Args>
3140 class format_string_checker {
3141  public:
3142   explicit FMT_CONSTEXPR format_string_checker(
3143       basic_string_view<Char> format_str, ErrorHandler eh)
3144       : context_(format_str, num_args, eh),
3145         parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
3146 
3147   FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
3148 
3149   FMT_CONSTEXPR int on_arg_id() { return context_.next_arg_id(); }
3150   FMT_CONSTEXPR int on_arg_id(int id) { return context_.check_arg_id(id), id; }
3151   FMT_CONSTEXPR int on_arg_id(basic_string_view<Char>) {
3152     on_error("compile-time checks don't support named arguments");
3153     return 0;
3154   }
3155 
3156   FMT_CONSTEXPR void on_replacement_field(int, const Char*) {}
3157 
3158   FMT_CONSTEXPR const Char* on_format_specs(int id, const Char* begin,
3159                                             const Char*) {
3160     advance_to(context_, begin);
3161     return id < num_args ? parse_funcs_[id](context_) : begin;
3162   }
3163 
3164   FMT_CONSTEXPR void on_error(const char* message) {
3165     context_.on_error(message);
3166   }
3167 
3168  private:
3169   using parse_context_type = compile_parse_context<Char, ErrorHandler>;
3170   enum { num_args = sizeof...(Args) };
3171 
3172   // Format specifier parsing function.
3173   using parse_func = const Char* (*)(parse_context_type&);
3174 
3175   parse_context_type context_;
3176   parse_func parse_funcs_[num_args > 0 ? num_args : 1];
3177 };
3178 
3179 // Converts string literals to basic_string_view.
3180 template <typename Char, size_t N>
3181 FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
3182     const Char (&s)[N]) {
3183   // Remove trailing null character if needed. Won't be present if this is used
3184   // with raw character array (i.e. not defined as a string).
3185   return {s,
3186           N - ((std::char_traits<Char>::to_int_type(s[N - 1]) == 0) ? 1 : 0)};
3187 }
3188 
3189 // Converts string_view to basic_string_view.
3190 template <typename Char>
3191 FMT_CONSTEXPR basic_string_view<Char> compile_string_to_view(
3192     const std_string_view<Char>& s) {
3193   return {s.data(), s.size()};
3194 }
3195 
3196 #define FMT_STRING_IMPL(s, base)                                  \
3197   [] {                                                            \
3198     /* Use a macro-like name to avoid shadowing warnings. */      \
3199     struct FMT_COMPILE_STRING : base {                            \
3200       using char_type = fmt::remove_cvref_t<decltype(s[0])>;      \
3201       FMT_MAYBE_UNUSED FMT_CONSTEXPR                              \
3202       operator fmt::basic_string_view<char_type>() const {        \
3203         return fmt::detail::compile_string_to_view<char_type>(s); \
3204       }                                                           \
3205     };                                                            \
3206     return FMT_COMPILE_STRING();                                  \
3207   }()
3208 
3209 /**
3210   \rst
3211   Constructs a compile-time format string from a string literal *s*.
3212 
3213   **Example**::
3214 
3215     // A compile-time error because 'd' is an invalid specifier for strings.
3216     std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
3217   \endrst
3218  */
3219 #define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string)
3220 
3221 template <typename... Args, typename S,
3222           enable_if_t<(is_compile_string<S>::value), int>>
3223 void check_format_string(S format_str) {
3224   FMT_CONSTEXPR_DECL auto s = to_string_view(format_str);
3225   using checker = format_string_checker<typename S::char_type, error_handler,
3226                                         remove_cvref_t<Args>...>;
3227   FMT_CONSTEXPR_DECL bool invalid_format =
3228       (parse_format_string<true>(s, checker(s, {})), true);
3229   (void)invalid_format;
3230 }
3231 
3232 template <template <typename> class Handler, typename Context>
3233 void handle_dynamic_spec(int& value, arg_ref<typename Context::char_type> ref,
3234                          Context& ctx) {
3235   switch (ref.kind) {
3236   case arg_id_kind::none:
3237     break;
3238   case arg_id_kind::index:
3239     value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
3240                                               ctx.error_handler());
3241     break;
3242   case arg_id_kind::name:
3243     value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
3244                                               ctx.error_handler());
3245     break;
3246   }
3247 }
3248 
3249 using format_func = void (*)(detail::buffer<char>&, int, string_view);
3250 
3251 FMT_API void format_error_code(buffer<char>& out, int error_code,
3252                                string_view message) FMT_NOEXCEPT;
3253 
3254 FMT_API void report_error(format_func func, int error_code,
3255                           string_view message) FMT_NOEXCEPT;
3256 }  // namespace detail
3257 
3258 template <typename OutputIt, typename Char>
3259 using arg_formatter FMT_DEPRECATED_ALIAS =
3260     detail::arg_formatter<OutputIt, Char>;
3261 
3262 /**
3263  An error returned by an operating system or a language runtime,
3264  for example a file opening error.
3265 */
3266 FMT_CLASS_API
3267 class FMT_API system_error : public std::runtime_error {
3268  private:
3269   void init(int err_code, string_view format_str, format_args args);
3270 
3271  protected:
3272   int error_code_;
3273 
3274   system_error() : std::runtime_error(""), error_code_(0) {}
3275 
3276  public:
3277   /**
3278    \rst
3279    Constructs a :class:`fmt::system_error` object with a description
3280    formatted with `fmt::format_system_error`. *message* and additional
3281    arguments passed into the constructor are formatted similarly to
3282    `fmt::format`.
3283 
3284    **Example**::
3285 
3286      // This throws a system_error with the description
3287      //   cannot open file 'madeup': No such file or directory
3288      // or similar (system message may vary).
3289      const char *filename = "madeup";
3290      std::FILE *file = std::fopen(filename, "r");
3291      if (!file)
3292        throw fmt::system_error(errno, "cannot open file '{}'", filename);
3293    \endrst
3294   */
3295   template <typename... Args>
3296   system_error(int error_code, string_view message, const Args&... args)
3297       : std::runtime_error("") {
3298     init(error_code, message, make_format_args(args...));
3299   }
3300   system_error(const system_error&) = default;
3301   system_error& operator=(const system_error&) = default;
3302   system_error(system_error&&) = default;
3303   system_error& operator=(system_error&&) = default;
3304   ~system_error() FMT_NOEXCEPT FMT_OVERRIDE;
3305 
3306   int error_code() const { return error_code_; }
3307 };
3308 
3309 /**
3310   \rst
3311   Formats an error returned by an operating system or a language runtime,
3312   for example a file opening error, and writes it to *out* in the following
3313   form:
3314 
3315   .. parsed-literal::
3316      *<message>*: *<system-message>*
3317 
3318   where *<message>* is the passed message and *<system-message>* is
3319   the system message corresponding to the error code.
3320   *error_code* is a system error code as given by ``errno``.
3321   If *error_code* is not a valid error code such as -1, the system message
3322   may look like "Unknown error -1" and is platform-dependent.
3323   \endrst
3324  */
3325 FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
3326                                  string_view message) FMT_NOEXCEPT;
3327 
3328 // Reports a system error without throwing an exception.
3329 // Can be used to report errors from destructors.
3330 FMT_API void report_system_error(int error_code,
3331                                  string_view message) FMT_NOEXCEPT;
3332 
3333 /** Fast integer formatter. */
3334 class format_int {
3335  private:
3336   // Buffer should be large enough to hold all digits (digits10 + 1),
3337   // a sign and a null character.
3338   enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
3339   mutable char buffer_[buffer_size];
3340   char* str_;
3341 
3342   template <typename UInt> char* format_unsigned(UInt value) {
3343     auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
3344     return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
3345   }
3346 
3347   template <typename Int> char* format_signed(Int value) {
3348     auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
3349     bool negative = value < 0;
3350     if (negative) abs_value = 0 - abs_value;
3351     auto begin = format_unsigned(abs_value);
3352     if (negative) *--begin = '-';
3353     return begin;
3354   }
3355 
3356  public:
3357   explicit format_int(int value) : str_(format_signed(value)) {}
3358   explicit format_int(long value) : str_(format_signed(value)) {}
3359   explicit format_int(long long value) : str_(format_signed(value)) {}
3360   explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
3361   explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
3362   explicit format_int(unsigned long long value)
3363       : str_(format_unsigned(value)) {}
3364 
3365   /** Returns the number of characters written to the output buffer. */
3366   size_t size() const {
3367     return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
3368   }
3369 
3370   /**
3371     Returns a pointer to the output buffer content. No terminating null
3372     character is appended.
3373    */
3374   const char* data() const { return str_; }
3375 
3376   /**
3377     Returns a pointer to the output buffer content with terminating null
3378     character appended.
3379    */
3380   const char* c_str() const {
3381     buffer_[buffer_size - 1] = '\0';
3382     return str_;
3383   }
3384 
3385   /**
3386     \rst
3387     Returns the content of the output buffer as an ``std::string``.
3388     \endrst
3389    */
3390   std::string str() const { return std::string(str_, size()); }
3391 };
3392 
3393 // A formatter specialization for the core types corresponding to detail::type
3394 // constants.
3395 template <typename T, typename Char>
3396 struct formatter<T, Char,
3397                  enable_if_t<detail::type_constant<T, Char>::value !=
3398                              detail::type::custom_type>> {
3399   FMT_CONSTEXPR formatter() = default;
3400 
3401   // Parses format specifiers stopping either at the end of the range or at the
3402   // terminating '}'.
3403   template <typename ParseContext>
3404   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3405     using handler_type = detail::dynamic_specs_handler<ParseContext>;
3406     auto type = detail::type_constant<T, Char>::value;
3407     detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
3408                                                 type);
3409     auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
3410     auto eh = ctx.error_handler();
3411     switch (type) {
3412     case detail::type::none_type:
3413       FMT_ASSERT(false, "invalid argument type");
3414       break;
3415     case detail::type::int_type:
3416     case detail::type::uint_type:
3417     case detail::type::long_long_type:
3418     case detail::type::ulong_long_type:
3419     case detail::type::int128_type:
3420     case detail::type::uint128_type:
3421     case detail::type::bool_type:
3422       handle_int_type_spec(specs_.type,
3423                            detail::int_type_checker<decltype(eh)>(eh));
3424       break;
3425     case detail::type::char_type:
3426       handle_char_specs(
3427           &specs_, detail::char_specs_checker<decltype(eh)>(specs_.type, eh));
3428       break;
3429     case detail::type::float_type:
3430       if (detail::const_check(FMT_USE_FLOAT))
3431         detail::parse_float_type_spec(specs_, eh);
3432       else
3433         FMT_ASSERT(false, "float support disabled");
3434       break;
3435     case detail::type::double_type:
3436       if (detail::const_check(FMT_USE_DOUBLE))
3437         detail::parse_float_type_spec(specs_, eh);
3438       else
3439         FMT_ASSERT(false, "double support disabled");
3440       break;
3441     case detail::type::long_double_type:
3442       if (detail::const_check(FMT_USE_LONG_DOUBLE))
3443         detail::parse_float_type_spec(specs_, eh);
3444       else
3445         FMT_ASSERT(false, "long double support disabled");
3446       break;
3447     case detail::type::cstring_type:
3448       detail::handle_cstring_type_spec(
3449           specs_.type, detail::cstring_type_checker<decltype(eh)>(eh));
3450       break;
3451     case detail::type::string_type:
3452       detail::check_string_type_spec(specs_.type, eh);
3453       break;
3454     case detail::type::pointer_type:
3455       detail::check_pointer_type_spec(specs_.type, eh);
3456       break;
3457     case detail::type::custom_type:
3458       // Custom format specifiers should be checked in parse functions of
3459       // formatter specializations.
3460       break;
3461     }
3462     return it;
3463   }
3464 
3465   template <typename FormatContext>
3466   auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3467     detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
3468                                                        specs_.width_ref, ctx);
3469     detail::handle_dynamic_spec<detail::precision_checker>(
3470         specs_.precision, specs_.precision_ref, ctx);
3471     using af = detail::arg_formatter<typename FormatContext::iterator,
3472                                      typename FormatContext::char_type>;
3473     return visit_format_arg(af(ctx, nullptr, &specs_),
3474                             detail::make_arg<FormatContext>(val));
3475   }
3476 
3477  private:
3478   detail::dynamic_format_specs<Char> specs_;
3479 };
3480 
3481 #define FMT_FORMAT_AS(Type, Base)                                             \
3482   template <typename Char>                                                    \
3483   struct formatter<Type, Char> : formatter<Base, Char> {                      \
3484     template <typename FormatContext>                                         \
3485     auto format(Type const& val, FormatContext& ctx) -> decltype(ctx.out()) { \
3486       return formatter<Base, Char>::format(val, ctx);                         \
3487     }                                                                         \
3488   }
3489 
3490 FMT_FORMAT_AS(signed char, int);
3491 FMT_FORMAT_AS(unsigned char, unsigned);
3492 FMT_FORMAT_AS(short, int);
3493 FMT_FORMAT_AS(unsigned short, unsigned);
3494 FMT_FORMAT_AS(long, long long);
3495 FMT_FORMAT_AS(unsigned long, unsigned long long);
3496 FMT_FORMAT_AS(Char*, const Char*);
3497 FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
3498 FMT_FORMAT_AS(std::nullptr_t, const void*);
3499 FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
3500 
3501 template <typename Char>
3502 struct formatter<void*, Char> : formatter<const void*, Char> {
3503   template <typename FormatContext>
3504   auto format(void* val, FormatContext& ctx) -> decltype(ctx.out()) {
3505     return formatter<const void*, Char>::format(val, ctx);
3506   }
3507 };
3508 
3509 template <typename Char, size_t N>
3510 struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
3511   template <typename FormatContext>
3512   auto format(const Char* val, FormatContext& ctx) -> decltype(ctx.out()) {
3513     return formatter<basic_string_view<Char>, Char>::format(val, ctx);
3514   }
3515 };
3516 
3517 // A formatter for types known only at run time such as variant alternatives.
3518 //
3519 // Usage:
3520 //   using variant = std::variant<int, std::string>;
3521 //   template <>
3522 //   struct formatter<variant>: dynamic_formatter<> {
3523 //     auto format(const variant& v, format_context& ctx) {
3524 //       return visit([&](const auto& val) {
3525 //           return dynamic_formatter<>::format(val, ctx);
3526 //       }, v);
3527 //     }
3528 //   };
3529 template <typename Char = char> class dynamic_formatter {
3530  private:
3531   struct null_handler : detail::error_handler {
3532     void on_align(align_t) {}
3533     void on_plus() {}
3534     void on_minus() {}
3535     void on_space() {}
3536     void on_hash() {}
3537   };
3538 
3539  public:
3540   template <typename ParseContext>
3541   auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3542     format_str_ = ctx.begin();
3543     // Checks are deferred to formatting time when the argument type is known.
3544     detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
3545     return parse_format_specs(ctx.begin(), ctx.end(), handler);
3546   }
3547 
3548   template <typename T, typename FormatContext>
3549   auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3550     handle_specs(ctx);
3551     detail::specs_checker<null_handler> checker(
3552         null_handler(), detail::mapped_type_constant<T, FormatContext>::value);
3553     checker.on_align(specs_.align);
3554     switch (specs_.sign) {
3555     case sign::none:
3556       break;
3557     case sign::plus:
3558       checker.on_plus();
3559       break;
3560     case sign::minus:
3561       checker.on_minus();
3562       break;
3563     case sign::space:
3564       checker.on_space();
3565       break;
3566     }
3567     if (specs_.alt) checker.on_hash();
3568     if (specs_.precision >= 0) checker.end_precision();
3569     using af = detail::arg_formatter<typename FormatContext::iterator,
3570                                      typename FormatContext::char_type>;
3571     visit_format_arg(af(ctx, nullptr, &specs_),
3572                      detail::make_arg<FormatContext>(val));
3573     return ctx.out();
3574   }
3575 
3576  private:
3577   template <typename Context> void handle_specs(Context& ctx) {
3578     detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
3579                                                        specs_.width_ref, ctx);
3580     detail::handle_dynamic_spec<detail::precision_checker>(
3581         specs_.precision, specs_.precision_ref, ctx);
3582   }
3583 
3584   detail::dynamic_format_specs<Char> specs_;
3585   const Char* format_str_;
3586 };
3587 
3588 template <typename Char, typename ErrorHandler>
3589 FMT_CONSTEXPR void advance_to(
3590     basic_format_parse_context<Char, ErrorHandler>& ctx, const Char* p) {
3591   ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
3592 }
3593 
3594 /**
3595   \rst
3596   Converts ``p`` to ``const void*`` for pointer formatting.
3597 
3598   **Example**::
3599 
3600     auto s = fmt::format("{}", fmt::ptr(p));
3601   \endrst
3602  */
3603 template <typename T> inline const void* ptr(const T* p) { return p; }
3604 template <typename T> inline const void* ptr(const std::unique_ptr<T>& p) {
3605   return p.get();
3606 }
3607 template <typename T> inline const void* ptr(const std::shared_ptr<T>& p) {
3608   return p.get();
3609 }
3610 
3611 class bytes {
3612  private:
3613   string_view data_;
3614   friend struct formatter<bytes>;
3615 
3616  public:
3617   explicit bytes(string_view data) : data_(data) {}
3618 };
3619 
3620 template <> struct formatter<bytes> {
3621  private:
3622   detail::dynamic_format_specs<char> specs_;
3623 
3624  public:
3625   template <typename ParseContext>
3626   FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3627     using handler_type = detail::dynamic_specs_handler<ParseContext>;
3628     detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
3629                                                 detail::type::string_type);
3630     auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
3631     detail::check_string_type_spec(specs_.type, ctx.error_handler());
3632     return it;
3633   }
3634 
3635   template <typename FormatContext>
3636   auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
3637     detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
3638                                                        specs_.width_ref, ctx);
3639     detail::handle_dynamic_spec<detail::precision_checker>(
3640         specs_.precision, specs_.precision_ref, ctx);
3641     return detail::write_bytes(ctx.out(), b.data_, specs_);
3642   }
3643 };
3644 
3645 template <typename It, typename Sentinel, typename Char>
3646 struct arg_join : detail::view {
3647   It begin;
3648   Sentinel end;
3649   basic_string_view<Char> sep;
3650 
3651   arg_join(It b, Sentinel e, basic_string_view<Char> s)
3652       : begin(b), end(e), sep(s) {}
3653 };
3654 
3655 template <typename It, typename Sentinel, typename Char>
3656 struct formatter<arg_join<It, Sentinel, Char>, Char>
3657     : formatter<typename std::iterator_traits<It>::value_type, Char> {
3658   template <typename FormatContext>
3659   auto format(const arg_join<It, Sentinel, Char>& value, FormatContext& ctx)
3660       -> decltype(ctx.out()) {
3661     using base = formatter<typename std::iterator_traits<It>::value_type, Char>;
3662     auto it = value.begin;
3663     auto out = ctx.out();
3664     if (it != value.end) {
3665       out = base::format(*it++, ctx);
3666       while (it != value.end) {
3667         out = std::copy(value.sep.begin(), value.sep.end(), out);
3668         ctx.advance_to(out);
3669         out = base::format(*it++, ctx);
3670       }
3671     }
3672     return out;
3673   }
3674 };
3675 
3676 /**
3677   Returns an object that formats the iterator range `[begin, end)` with elements
3678   separated by `sep`.
3679  */
3680 template <typename It, typename Sentinel>
3681 arg_join<It, Sentinel, char> join(It begin, Sentinel end, string_view sep) {
3682   return {begin, end, sep};
3683 }
3684 
3685 template <typename It, typename Sentinel>
3686 arg_join<It, Sentinel, wchar_t> join(It begin, Sentinel end, wstring_view sep) {
3687   return {begin, end, sep};
3688 }
3689 
3690 /**
3691   \rst
3692   Returns an object that formats `range` with elements separated by `sep`.
3693 
3694   **Example**::
3695 
3696     std::vector<int> v = {1, 2, 3};
3697     fmt::print("{}", fmt::join(v, ", "));
3698     // Output: "1, 2, 3"
3699 
3700   ``fmt::join`` applies passed format specifiers to the range elements::
3701 
3702     fmt::print("{:02}", fmt::join(v, ", "));
3703     // Output: "01, 02, 03"
3704   \endrst
3705  */
3706 template <typename Range>
3707 arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, char> join(
3708     Range&& range, string_view sep) {
3709   return join(std::begin(range), std::end(range), sep);
3710 }
3711 
3712 template <typename Range>
3713 arg_join<detail::iterator_t<Range>, detail::sentinel_t<Range>, wchar_t> join(
3714     Range&& range, wstring_view sep) {
3715   return join(std::begin(range), std::end(range), sep);
3716 }
3717 
3718 /**
3719   \rst
3720   Converts *value* to ``std::string`` using the default format for type *T*.
3721 
3722   **Example**::
3723 
3724     #include <fmt/format.h>
3725 
3726     std::string answer = fmt::to_string(42);
3727   \endrst
3728  */
3729 template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
3730 inline std::string to_string(const T& value) {
3731   std::string result;
3732   detail::write<char>(std::back_inserter(result), value);
3733   return result;
3734 }
3735 
3736 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
3737 inline std::string to_string(T value) {
3738   // The buffer should be large enough to store the number including the sign or
3739   // "false" for bool.
3740   constexpr int max_size = detail::digits10<T>() + 2;
3741   char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
3742   char* begin = buffer;
3743   return std::string(begin, detail::write<char>(begin, value));
3744 }
3745 
3746 /**
3747   Converts *value* to ``std::wstring`` using the default format for type *T*.
3748  */
3749 template <typename T> inline std::wstring to_wstring(const T& value) {
3750   return format(L"{}", value);
3751 }
3752 
3753 template <typename Char, size_t SIZE>
3754 std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
3755   auto size = buf.size();
3756   detail::assume(size < std::basic_string<Char>().max_size());
3757   return std::basic_string<Char>(buf.data(), size);
3758 }
3759 
3760 template <typename Char>
3761 void detail::vformat_to(
3762     detail::buffer<Char>& buf, basic_string_view<Char> format_str,
3763     basic_format_args<buffer_context<type_identity_t<Char>>> args,
3764     detail::locale_ref loc) {
3765   using iterator = typename buffer_context<Char>::iterator;
3766   auto out = buffer_appender<Char>(buf);
3767   if (format_str.size() == 2 && equal2(format_str.data(), "{}")) {
3768     auto arg = args.get(0);
3769     if (!arg) error_handler().on_error("argument not found");
3770     visit_format_arg(default_arg_formatter<iterator, Char>{out, args, loc},
3771                      arg);
3772     return;
3773   }
3774   format_handler<iterator, Char, buffer_context<Char>> h(out, format_str, args,
3775                                                          loc);
3776   parse_format_string<false>(format_str, h);
3777 }
3778 
3779 #ifndef FMT_HEADER_ONLY
3780 extern template void detail::vformat_to(detail::buffer<char>&, string_view,
3781                                         basic_format_args<format_context>,
3782                                         detail::locale_ref);
3783 namespace detail {
3784 
3785 extern template FMT_API std::string grouping_impl<char>(locale_ref loc);
3786 extern template FMT_API std::string grouping_impl<wchar_t>(locale_ref loc);
3787 extern template FMT_API char thousands_sep_impl<char>(locale_ref loc);
3788 extern template FMT_API wchar_t thousands_sep_impl<wchar_t>(locale_ref loc);
3789 extern template FMT_API char decimal_point_impl(locale_ref loc);
3790 extern template FMT_API wchar_t decimal_point_impl(locale_ref loc);
3791 extern template int format_float<double>(double value, int precision,
3792                                          float_specs specs, buffer<char>& buf);
3793 extern template int format_float<long double>(long double value, int precision,
3794                                               float_specs specs,
3795                                               buffer<char>& buf);
3796 int snprintf_float(float value, int precision, float_specs specs,
3797                    buffer<char>& buf) = delete;
3798 extern template int snprintf_float<double>(double value, int precision,
3799                                            float_specs specs,
3800                                            buffer<char>& buf);
3801 extern template int snprintf_float<long double>(long double value,
3802                                                 int precision,
3803                                                 float_specs specs,
3804                                                 buffer<char>& buf);
3805 }  // namespace detail
3806 #endif
3807 
3808 template <typename S, typename Char = char_t<S>,
3809           FMT_ENABLE_IF(detail::is_string<S>::value)>
3810 inline void vformat_to(
3811     detail::buffer<Char>& buf, const S& format_str,
3812     basic_format_args<FMT_BUFFER_CONTEXT(type_identity_t<Char>)> args) {
3813   return detail::vformat_to(buf, to_string_view(format_str), args);
3814 }
3815 
3816 template <typename S, typename... Args, size_t SIZE = inline_buffer_size,
3817           typename Char = enable_if_t<detail::is_string<S>::value, char_t<S>>>
3818 inline typename buffer_context<Char>::iterator format_to(
3819     basic_memory_buffer<Char, SIZE>& buf, const S& format_str, Args&&... args) {
3820   const auto& vargs = fmt::make_args_checked<Args...>(format_str, args...);
3821   detail::vformat_to(buf, to_string_view(format_str), vargs);
3822   return detail::buffer_appender<Char>(buf);
3823 }
3824 
3825 template <typename OutputIt, typename Char = char>
3826 using format_context_t = basic_format_context<OutputIt, Char>;
3827 
3828 template <typename OutputIt, typename Char = char>
3829 using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;
3830 
3831 template <typename OutputIt, typename Char = typename OutputIt::value_type>
3832 using format_to_n_context FMT_DEPRECATED_ALIAS = buffer_context<Char>;
3833 
3834 template <typename OutputIt, typename Char = typename OutputIt::value_type>
3835 using format_to_n_args FMT_DEPRECATED_ALIAS =
3836     basic_format_args<buffer_context<Char>>;
3837 
3838 template <typename OutputIt, typename Char, typename... Args>
3839 FMT_DEPRECATED format_arg_store<buffer_context<Char>, Args...>
3840 make_format_to_n_args(const Args&... args) {
3841   return format_arg_store<buffer_context<Char>, Args...>(args...);
3842 }
3843 
3844 template <typename Char, enable_if_t<(!std::is_same<Char, char>::value), int>>
3845 std::basic_string<Char> detail::vformat(
3846     basic_string_view<Char> format_str,
3847     basic_format_args<buffer_context<type_identity_t<Char>>> args) {
3848   basic_memory_buffer<Char> buffer;
3849   detail::vformat_to(buffer, format_str, args);
3850   return to_string(buffer);
3851 }
3852 
3853 template <typename Char, FMT_ENABLE_IF(std::is_same<Char, wchar_t>::value)>
3854 void vprint(std::FILE* f, basic_string_view<Char> format_str,
3855             wformat_args args) {
3856   wmemory_buffer buffer;
3857   detail::vformat_to(buffer, format_str, args);
3858   buffer.push_back(L'\0');
3859   if (std::fputws(buffer.data(), f) == -1)
3860     FMT_THROW(system_error(errno, "cannot write to file"));
3861 }
3862 
3863 template <typename Char, FMT_ENABLE_IF(std::is_same<Char, wchar_t>::value)>
3864 void vprint(basic_string_view<Char> format_str, wformat_args args) {
3865   vprint(stdout, format_str, args);
3866 }
3867 
3868 #if FMT_USE_USER_DEFINED_LITERALS
3869 namespace detail {
3870 
3871 #  if FMT_USE_UDL_TEMPLATE
3872 template <typename Char, Char... CHARS> class udl_formatter {
3873  public:
3874   template <typename... Args>
3875   std::basic_string<Char> operator()(Args&&... args) const {
3876     static FMT_CONSTEXPR_DECL Char s[] = {CHARS..., '\0'};
3877     return format(FMT_STRING(s), std::forward<Args>(args)...);
3878   }
3879 };
3880 #  else
3881 template <typename Char> struct udl_formatter {
3882   basic_string_view<Char> str;
3883 
3884   template <typename... Args>
3885   std::basic_string<Char> operator()(Args&&... args) const {
3886     return format(str, std::forward<Args>(args)...);
3887   }
3888 };
3889 #  endif  // FMT_USE_UDL_TEMPLATE
3890 
3891 template <typename Char> struct udl_arg {
3892   const Char* str;
3893 
3894   template <typename T> named_arg<Char, T> operator=(T&& value) const {
3895     return {str, std::forward<T>(value)};
3896   }
3897 };
3898 }  // namespace detail
3899 
3900 inline namespace literals {
3901 #  if FMT_USE_UDL_TEMPLATE
3902 #    pragma GCC diagnostic push
3903 #    pragma GCC diagnostic ignored "-Wpedantic"
3904 #    if FMT_CLANG_VERSION
3905 #      pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
3906 #    endif
3907 template <typename Char, Char... CHARS>
3908 FMT_CONSTEXPR detail::udl_formatter<Char, CHARS...> operator""_format() {
3909   return {};
3910 }
3911 #    pragma GCC diagnostic pop
3912 #  else
3913 /**
3914   \rst
3915   User-defined literal equivalent of :func:`fmt::format`.
3916 
3917   **Example**::
3918 
3919     using namespace fmt::literals;
3920     std::string message = "The answer is {}"_format(42);
3921   \endrst
3922  */
3923 FMT_CONSTEXPR detail::udl_formatter<char> operator"" _format(const char* s,
3924                                                              size_t n) {
3925   return {{s, n}};
3926 }
3927 FMT_CONSTEXPR detail::udl_formatter<wchar_t> operator"" _format(
3928     const wchar_t* s, size_t n) {
3929   return {{s, n}};
3930 }
3931 #  endif  // FMT_USE_UDL_TEMPLATE
3932 
3933 /**
3934   \rst
3935   User-defined literal equivalent of :func:`fmt::arg`.
3936 
3937   **Example**::
3938 
3939     using namespace fmt::literals;
3940     fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
3941   \endrst
3942  */
3943 FMT_CONSTEXPR detail::udl_arg<char> operator"" _a(const char* s, size_t) {
3944   return {s};
3945 }
3946 FMT_CONSTEXPR detail::udl_arg<wchar_t> operator"" _a(const wchar_t* s, size_t) {
3947   return {s};
3948 }
3949 }  // namespace literals
3950 #endif  // FMT_USE_USER_DEFINED_LITERALS
3951 FMT_END_NAMESPACE
3952 
3953 #ifdef FMT_HEADER_ONLY
3954 #  define FMT_FUNC inline
3955 #  include "format-inl.h"
3956 #else
3957 #  define FMT_FUNC
3958 #endif
3959 
3960 #endif  // FMT_FORMAT_H_
3961