Scippy

SoPlex

Sequential object-oriented simPlex

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