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