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