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