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