SoPlex Documentation
Loading...
Searching...
No Matches
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
83namespace internal {
84template <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
147namespace internal {
148// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
149# ifndef __clang__
150# pragma intrinsic(_BitScanReverse)
151# endif
152inline 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
169inline 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
204namespace internal {
205
206// A helper function to suppress bogus "conditional expression is constant"
207// warnings.
208template <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);
213template <typename Dest, typename Source>
214inline 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
221inline 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
243using uintptr_t = ::uintptr_t;
244inline uintptr_t to_uintptr(const void* p) { return bit_cast<uintptr_t>(p); }
245#else
247inline 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.
254template <typename T> constexpr T max_value() {
255 return (std::numeric_limits<T>::max)();
256}
257template <typename T> constexpr int num_bits() {
258 return std::numeric_limits<T>::digits;
259}
260template <> 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.
266template <typename T>
267using 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.
272template <typename It, typename Enable = void>
273struct iterator_category : std::false_type {};
274
275template <typename T> struct iterator_category<T*> {
276 using type = std::random_access_iterator_tag;
277};
278
279template <typename It>
280struct 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.
285template <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.
303template <typename Char> inline Char* get_data(std::basic_string<Char>& s) {
304 return &s[0];
305}
306template <typename Container>
307inline 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.
313template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
314template <typename T> checked_ptr<T> make_checked(T* p, std::size_t size) {
315 return {p, size};
316}
317#else
318template <typename T> using checked_ptr = T*;
319template <typename T> inline T* make_checked(T* p, std::size_t) { return p; }
320#endif
321
322template <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
331template <typename Iterator>
332inline 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
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
371template <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;
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.
394template <typename OutputIt,
395 typename Enable = typename std::is_void<
396 typename std::iterator_traits<OutputIt>::value_type>::type>
398
399template <typename OutputIt>
400class 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
428template <typename OutputIt>
429class 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.
448template <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
463template <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
478template <typename Char>
479inline 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.
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
496inline char8_t to_char8_t(char c) { return static_cast<char8_t>(c); }
497
498template <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
504template <typename OutChar, typename InputIt, typename OutputIt,
506OutputIt copy_str(InputIt begin, InputIt end, OutputIt it) {
507 return std::copy(begin, end, it);
508}
509
510template <typename OutChar, typename InputIt, typename OutputIt,
511 FMT_ENABLE_IF(needs_conversion<InputIt, OutChar>::value)>
512OutputIt 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
520template <typename T> constexpr bool use_grisu() {
521 return FMT_USE_GRISU && std::numeric_limits<double>::is_iec559 &&
522 sizeof(T) <= sizeof(double);
523}
524
525template <typename T>
526template <typename U>
527void 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.
536template <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.
547class 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
557inline namespace literals {
558inline 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.
566enum { 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 */
597template <typename T, std::size_t SIZE = inline_buffer_size,
598 typename Allocator = std::allocator<T>>
599class 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 }
621
622 private:
623 // Move data from other to this buffer.
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,
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);
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
667template <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. */
691class 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;
701};
702
703namespace 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.
707template <typename T, FMT_ENABLE_IF(std::numeric_limits<T>::is_signed)>
709 return value < 0;
710}
711template <typename T, FMT_ENABLE_IF(!std::numeric_limits<T>::is_signed)>
712FMT_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.
718template <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.
724template <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
740
741// This is a struct rather than an alias to avoid shadowing warnings in gcc.
742struct 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.
747inline 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.
755inline 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
772inline 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).
789template <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
797template <> int count_digits<4>(internal::fallback_uintptr n);
798
799#if FMT_GCC_VERSION || FMT_CLANG_VERSION
800# define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
801#else
802# define FMT_ALWAYS_INLINE
803#endif
804
805#ifdef FMT_BUILTIN_CLZ
806// Optional version of count_digits for better performance on 32-bit platforms.
807inline 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
813template <typename Char> FMT_API std::string grouping_impl(locale_ref loc);
814template <typename Char> inline std::string grouping(locale_ref loc) {
815 return grouping_impl<char>(loc);
816}
817template <> inline std::string grouping<wchar_t>(locale_ref loc) {
818 return grouping_impl<wchar_t>(loc);
819}
820
821template <typename Char> FMT_API Char thousands_sep_impl(locale_ref loc);
822template <typename Char> inline Char thousands_sep(locale_ref loc) {
823 return Char(thousands_sep_impl<char>(loc));
824}
825template <> inline wchar_t thousands_sep(locale_ref loc) {
826 return thousands_sep_impl<wchar_t>(loc);
827}
828
829template <typename Char> FMT_API Char decimal_point_impl(locale_ref loc);
830template <typename Char> inline Char decimal_point(locale_ref loc) {
831 return Char(decimal_point_impl<char>(loc));
832}
833template <> 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.
840template <typename UInt, typename Char, typename F>
841inline 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
868template <typename Int> constexpr int digits10() noexcept {
869 return std::numeric_limits<Int>::digits10;
870}
871template <> constexpr int digits10<int128_t>() noexcept { return 38; }
872template <> constexpr int digits10<uint128_t>() noexcept { return 38; }
873
874template <typename Char, typename UInt, typename Iterator, typename F>
875inline 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
885template <typename Char, typename It, typename UInt>
886inline It format_decimal(It out, UInt value, int num_digits) {
887 return format_decimal<Char>(out, value, num_digits, [](Char*) {});
888}
889
890template <unsigned BASE_BITS, typename Char, typename UInt>
891inline 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
904template <unsigned BASE_BITS, typename Char>
905Char* 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
926template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
927inline 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.
945class 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.
959class 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
977FMT_API void format_windows_error(internal::buffer<char>& out, int error_code,
978 string_view message) FMT_NOEXCEPT;
979#endif
980
981template <typename T = void> struct null {};
982
983// Workaround an array initialization issue in gcc 4.8.
984template <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.
1004namespace align {
1006}
1008
1009namespace sign {
1010enum type { none, minus, plus, space };
1011}
1013
1014// Format specifiers for built-in and string types.
1015template <typename Char> struct basic_format_specs {
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
1036namespace internal {
1037
1038// A floating-point presentation format.
1039enum 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
1050 bool upper : 1;
1051 bool locale : 1;
1052 bool percent : 1;
1053 bool binary32 : 1;
1054 bool use_grisu : 1;
1056};
1057
1058// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1059template <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
1079template <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
1185template <typename T>
1186int format_float(T value, int precision, float_specs specs, buffer<char>& buf);
1187
1188// Formats a floating-point number with snprintf.
1189template <typename T>
1190int snprintf_float(T value, int precision, float_specs specs,
1191 buffer<char>& buf);
1192
1193template <typename T> T promote_float(T value) { return value; }
1194inline double promote_float(float value) { return value; }
1195
1196template <typename Handler>
1197FMT_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
1222template <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
1274template <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
1284template <typename Char, typename Handler>
1285FMT_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
1294template <typename Char, typename ErrorHandler>
1295FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler&& eh) {
1296 if (spec != 0 && spec != 's') eh.on_error("invalid type specifier");
1297}
1298
1299template <typename Char, typename ErrorHandler>
1300FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler&& eh) {
1301 if (spec != 0 && spec != 'p') eh.on_error("invalid type specifier");
1302}
1303
1304template <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
1319template <typename ErrorHandler>
1320class char_specs_checker : public ErrorHandler {
1321 private:
1322 char type_;
1323
1324 public:
1326 : ErrorHandler(eh), type_(type) {}
1327
1332};
1333
1334template <typename ErrorHandler>
1335class cstring_type_checker : public ErrorHandler {
1336 public:
1337 FMT_CONSTEXPR explicit cstring_type_checker(ErrorHandler eh)
1338 : ErrorHandler(eh) {}
1339
1342};
1343
1344template <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
1361template <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.
1377template <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 {
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 {
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
1701 memory_buffer buffer;
1702 if (fspecs.format == float_format::hex) {
1703 if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
1704 snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
1705 write_padded(specs, str_writer<char>{buffer.data(), buffer.size()});
1706 return;
1707 }
1708 int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
1709 if (fspecs.format == float_format::exp) ++precision;
1710 if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1711 fspecs.use_grisu = use_grisu<T>();
1712 if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) value *= 100;
1713 int exp = format_float(promote_float(value), precision, fspecs, buffer);
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
1738 auto&& it = reserve(value.size());
1739 it = copy_str<char_type>(value.begin(), value.end(), it);
1740 }
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
1774template <typename T> struct is_integral : std::is_integral<T> {};
1775template <> struct is_integral<int128_t> : std::true_type {};
1776template <> struct is_integral<uint128_t> : std::true_type {};
1777
1778template <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
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
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);
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)>
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
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)>
1863 writer_.write(value, specs_ ? *specs_ : format_specs());
1864 return out();
1865 }
1866
1867 struct char_spec_handler : ErrorHandler {
1870
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
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
1912 if (specs_)
1914 write_pointer(value);
1915 return out();
1916 }
1917};
1918
1919template <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.
1925template <typename Char, typename ErrorHandler>
1926FMT_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
1950template <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
1970template <typename T>
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
1976template <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
1996template <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.
2017template <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; }
2028 FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; }
2029 FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; }
2030 FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
2031
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
2051template <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.
2081template <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
2125template <template <typename> class Handler, typename FormatArg,
2126 typename ErrorHandler>
2127FMT_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
2133struct auto_id {};
2134
2135template <typename Context>
2136FMT_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.
2143template <typename ParseContext, typename Context>
2144class 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.
2168 using format_arg = typename Context::format_arg;
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
2188enum class arg_id_kind { none, index, name };
2189
2190// An argument reference.
2191template <typename Char> struct arg_ref {
2192 FMT_CONSTEXPR arg_ref() : kind(arg_id_kind::none), val() {}
2193 FMT_CONSTEXPR explicit arg_ref(int index)
2194 : kind(arg_id_kind::index), val(index) {}
2196 : kind(arg_id_kind::name), val(name) {}
2197
2199 kind = arg_id_kind::index;
2200 val.index = idx;
2201 return *this;
2202 }
2203
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).
2217template <typename Char>
2222
2223// Format spec handler that saves references to arguments representing dynamic
2224// width and precision to be resolved at formatting time.
2225template <typename ParseContext>
2227 : public specs_setter<typename ParseContext::char_type> {
2228 public:
2229 using char_type = typename ParseContext::char_type;
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);
2267 context_.begin(), to_unsigned(context_.end() - context_.begin()));
2268 return arg_ref_type(arg_id);
2269 }
2270
2272 ParseContext& context_;
2273};
2274
2275template <typename Char, typename IDHandler>
2276FMT_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.
2305template <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.
2322template <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.
2339template <typename Char, typename Handler>
2340FMT_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 '<':
2350 break;
2351 case '>':
2353 break;
2354#if FMT_NUMERIC_ALIGN
2355 case '=':
2357 break;
2358#endif
2359 case '^':
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
2379template <typename Char, typename Handler>
2380FMT_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
2396template <typename Char, typename Handler>
2397FMT_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.
2420template <typename Char, typename SpecHandler>
2421FMT_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.
2470template <bool IS_CONSTEXPR, typename T, typename Ptr = const T*>
2471FMT_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
2478template <>
2479inline 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
2486template <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
2498template <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
2550template <typename T, typename ParseContext>
2551FMT_CONSTEXPR const typename ParseContext::char_type* parse_format_specs(
2552 ParseContext& ctx) {
2553 using char_type = typename ParseContext::char_type;
2554 using context = buffer_context<char_type>;
2555 using mapped_type =
2558 decltype(arg_mapper<context>().map(std::declval<T>())), T>;
2562 return f.parse(ctx);
2563}
2564
2565template <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 }
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
2613 parse_func parse_funcs_[num_args > 0 ? num_args : 1];
2614};
2615
2616template <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
2624template <typename... Args, typename S,
2626void check_format_string(S format_str) {
2627 FMT_CONSTEXPR_DECL bool invalid_format =
2628 internal::do_check_format_string<typename S::char_type,
2629 internal::error_handler, Args...>(
2630 to_string_view(format_str));
2631 (void)invalid_format;
2632}
2633
2634template <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
2652template <typename Range>
2655using wwriter FMT_DEPRECATED_ALIAS =
2657
2658/** The default argument formatter. */
2659template <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 */
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*/
2702class 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;
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.
2766 string_view message) FMT_NOEXCEPT;
2767
2768#if FMT_USE_WINDOWS_H
2769
2770/** A Windows error. */
2771class 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.
2812FMT_API void report_windows_error(int error_code,
2813 string_view message) FMT_NOEXCEPT;
2814
2815#endif
2816
2817/** Fast integer formatter. */
2819 private:
2820 // Buffer should be large enough to hold all digits (digits10 + 1),
2821 // a sign and a null character.
2822 enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
2823 mutable char buffer_[buffer_size];
2824 char* str_;
2825
2826 // Formats value in reverse and returns a pointer to the beginning.
2827 char* format_decimal(unsigned long long value) {
2828 char* ptr = buffer_ + (buffer_size - 1); // Parens to workaround MSVC bug.
2829 while (value >= 100) {
2830 // Integer division is slow so do it for a group of two digits instead
2831 // of for every digit. The idea comes from the talk by Alexandrescu
2832 // "Three Optimization Tips for C++". See speed-test for a comparison.
2833 auto index = static_cast<unsigned>((value % 100) * 2);
2834 value /= 100;
2835 *--ptr = internal::data::digits[index + 1];
2836 *--ptr = internal::data::digits[index];
2837 }
2838 if (value < 10) {
2839 *--ptr = static_cast<char>('0' + value);
2840 return ptr;
2841 }
2842 auto index = static_cast<unsigned>(value * 2);
2843 *--ptr = internal::data::digits[index + 1];
2844 *--ptr = internal::data::digits[index];
2845 return ptr;
2846 }
2847
2848 void format_signed(long long value) {
2849 auto abs_value = static_cast<unsigned long long>(value);
2850 bool negative = value < 0;
2851 if (negative) abs_value = 0 - abs_value;
2852 str_ = format_decimal(abs_value);
2853 if (negative) *--str_ = '-';
2854 }
2855
2856 public:
2857 explicit format_int(int value) { format_signed(value); }
2858 explicit format_int(long value) { format_signed(value); }
2859 explicit format_int(long long value) { format_signed(value); }
2860 explicit format_int(unsigned value) : str_(format_decimal(value)) {}
2861 explicit format_int(unsigned long value) : str_(format_decimal(value)) {}
2862 explicit format_int(unsigned long long value) : str_(format_decimal(value)) {}
2863
2864 /** Returns the number of characters written to the output buffer. */
2865 std::size_t size() const {
2866 return internal::to_unsigned(buffer_ - str_ + buffer_size - 1);
2867 }
2868
2869 /**
2870 Returns a pointer to the output buffer content. No terminating null
2871 character is appended.
2872 */
2873 const char* data() const { return str_; }
2874
2875 /**
2876 Returns a pointer to the output buffer content with terminating null
2877 character appended.
2878 */
2879 const char* c_str() const {
2880 buffer_[buffer_size - 1] = '\0';
2881 return str_;
2882 }
2883
2884 /**
2885 \rst
2886 Returns the content of the output buffer as an ``std::string``.
2887 \endrst
2888 */
2889 std::string str() const { return std::string(str_, size()); }
2890};
2891
2892// A formatter specialization for the core types corresponding to internal::type
2893// constants.
2894template <typename T, typename Char>
2895struct formatter<T, Char,
2896 enable_if_t<internal::type_constant<T, Char>::value !=
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()) {
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) {
2913 FMT_ASSERT(false, "invalid argument type");
2914 break;
2915 case internal::int_type:
2922 handle_int_type_spec(specs_.type,
2923 internal::int_type_checker<decltype(eh)>(eh));
2924 break;
2926 handle_char_specs(
2927 &specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh));
2928 break;
2933 break;
2936 specs_.type, internal::cstring_type_checker<decltype(eh)>(eh));
2937 break;
2939 internal::check_string_type_spec(specs_.type, eh);
2940 break;
2942 internal::check_pointer_type_spec(specs_.type, eh);
2943 break;
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
2978FMT_FORMAT_AS(signed char, int);
2979FMT_FORMAT_AS(unsigned char, unsigned);
2980FMT_FORMAT_AS(short, int);
2981FMT_FORMAT_AS(unsigned short, unsigned);
2982FMT_FORMAT_AS(long, long long);
2983FMT_FORMAT_AS(unsigned long, unsigned long long);
2984FMT_FORMAT_AS(Char*, const Char*);
2985FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
2986FMT_FORMAT_AS(std::nullptr_t, const void*);
2988
2989template <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
2997template <typename Char, size_t N>
2998struct 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// };
3015template <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.
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
3075template <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
3084template <typename Char, typename ErrorHandler>
3087 ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
3088}
3089
3090template <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. */
3146template <typename ArgFormatter, typename Char, typename Context>
3147typename 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));
3159template <typename T> inline const void* ptr(const T* p) { return p; }
3160template <typename T> inline const void* ptr(const std::unique_ptr<T>& p) {
3161 return p.get();
3162}
3163template <typename T> inline const void* ptr(const std::shared_ptr<T>& p) {
3164 return p.get();
3165}
3166
3167template <typename It, typename Char> struct arg_join : internal::view {
3171
3172 arg_join(It b, It e, basic_string_view<Char> s) : begin(b), end(e), sep(s) {}
3173};
3174
3175template <typename It, typename Char>
3176struct 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 */
3200template <typename It>
3201arg_join<It, char> join(It begin, It end, string_view sep) {
3202 return {begin, end, sep};
3203}
3204
3205template <typename It>
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 */
3221template <typename Range>
3223 string_view sep) {
3224 return join(std::begin(range), std::end(range), sep);
3225}
3226
3227template <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 */
3245template <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 */
3252template <typename T> inline std::wstring to_wstring(const T& value) {
3253 return format(L"{}", value);
3254}
3255
3256template <typename Char, std::size_t SIZE>
3257std::basic_string<Char> to_string(const basic_memory_buffer<Char, SIZE>& buf) {
3258 return std::basic_string<Char>(buf.data(), buf.size());
3259}
3260
3261template <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
3270template <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
3278template <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
3288template <typename OutputIt, typename Char = char>
3290
3291template <typename OutputIt, typename Char = char>
3293
3294template <typename S, typename OutputIt, typename... Args,
3298inline 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 */
3316template <typename OutputIt, typename S, typename... Args,
3321inline 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
3328template <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
3335template <typename OutputIt, typename Char = typename OutputIt::value_type>
3338
3339template <typename OutputIt, typename Char = typename OutputIt::value_type>
3341
3342template <typename OutputIt, typename Char, typename... Args>
3344make_format_to_n_args(const Args&... args) {
3346 args...);
3347}
3348
3349template <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 */
3366template <typename OutputIt, typename S, typename... Args,
3369inline 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);
3374 return vformat_to_n(out, n, to_string_view(format_str),
3375 {make_format_args<context>(args...)});
3376}
3377
3378template <typename Char>
3379inline 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 */
3391template <typename... Args>
3392inline 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
3396template <typename Char, FMT_ENABLE_IF(std::is_same<Char, wchar_t>::value)>
3397void 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
3406template <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
3412namespace internal {
3413
3414# if FMT_USE_UDL_TEMPLATE
3415template <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
3428template <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
3438template <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
3448inline 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
3454template <typename Char, Char... CHARS>
3455FMT_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 */
3470FMT_CONSTEXPR internal::udl_formatter<char> operator"" _format(const char* s,
3471 std::size_t n) {
3472 return {{s, n}};
3473}
3474FMT_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 */
3490FMT_CONSTEXPR internal::udl_arg<char> operator"" _a(const char* s,
3491 std::size_t n) {
3492 return {{s, n}};
3493}
3494FMT_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_
typename base::format_specs format_specs
Definition format.h:2672
basic_format_parse_context< char_type > * parse_ctx_
Definition format.h:2667
context_type & ctx_
Definition format.h:2666
arg_formatter(context_type &ctx, basic_format_parse_context< char_type > *parse_ctx=nullptr, format_specs *specs=nullptr)
Definition format.h:2681
iterator operator()(typename basic_format_arg< context_type >::handle handle)
Definition format.h:2692
Range range
Definition format.h:2670
typename Range::value_type char_type
Definition format.h:2662
typename base::iterator iterator
Definition format.h:2671
void format(basic_format_parse_context< char_type > &parse_ctx, Context &ctx) const
Definition core.h:975
internal::value< Context > value_
Definition core.h:953
internal::type type_
Definition core.h:954
const internal::value< Context > * values_
Definition core.h:1246
const format_arg * args_
Definition core.h:1247
bool is_packed() const
Definition core.h:1250
internal::type type(int index) const
Definition core.h:1252
int max_size() const
Definition core.h:1310
format_arg arg(int id) const
Definition core.h:1162
iterator out()
Definition core.h:1172
OutputIt iterator
Definition core.h:1147
FMT_CONSTEXPR iterator begin() const FMT_NOEXCEPT
Definition core.h:494
FMT_CONSTEXPR void advance_to(iterator it)
Definition core.h:504
~basic_memory_buffer() FMT_OVERRIDE
Definition format.h:620
basic_memory_buffer & operator=(basic_memory_buffer &&other) FMT_NOEXCEPT
Definition format.h:656
void move(basic_memory_buffer &other)
Definition format.h:624
Allocator get_allocator() const
Definition format.h:664
basic_memory_buffer(const Allocator &alloc=Allocator())
Definition format.h:616
const T & const_reference
Definition format.h:614
basic_memory_buffer(basic_memory_buffer &&other) FMT_NOEXCEPT
Definition format.h:649
void grow(std::size_t size) FMT_OVERRIDE
Definition format.h:668
FMT_CONSTEXPR size_t size() const
Definition core.h:323
FMT_CONSTEXPR iterator end() const
Definition core.h:326
FMT_CONSTEXPR const Char * data() const
Definition core.h:320
FMT_CONSTEXPR iterator begin() const
Definition core.h:325
std::back_insert_iterator< internal::buffer< T > > iterator
Definition format.h:540
buffer_range(internal::buffer< T > &buf)
Definition format.h:542
const Char * format_str_
Definition format.h:3072
internal::dynamic_format_specs< Char > specs_
Definition format.h:3071
void handle_specs(Context &ctx)
Definition format.h:3064
auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition format.h:3027
auto format(const T &val, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:3035
format_error(const std::string &message)
Definition format.h:694
format_error(format_error &&)=default
format_error(const char *message)
Definition format.h:693
format_error & operator=(const format_error &)=default
format_error(const format_error &)=default
format_error & operator=(format_error &&)=default
~format_error() FMT_NOEXCEPT FMT_OVERRIDE
const char * c_str() const
Definition format.h:2879
void format_signed(long long value)
Definition format.h:2848
char * format_decimal(unsigned long long value)
Definition format.h:2827
format_int(unsigned long value)
Definition format.h:2861
format_int(int value)
Definition format.h:2857
char * str_
Definition format.h:2824
format_int(long value)
Definition format.h:2858
format_int(unsigned value)
Definition format.h:2860
format_int(long long value)
Definition format.h:2859
format_int(unsigned long long value)
Definition format.h:2862
const char * data() const
Definition format.h:2873
std::size_t size() const
Definition format.h:2865
std::string str() const
Definition format.h:2889
iterator operator()(const void *value)
Definition format.h:1911
writer_type & writer()
Definition format.h:1811
iterator operator()(T value)
Definition format.h:1841
void write(const char_type *value)
Definition format.h:1821
iterator operator()(basic_string_view< char_type > value)
Definition format.h:1901
iterator operator()(bool value)
Definition format.h:1855
iterator operator()(monostate)
Definition format.h:1835
iterator operator()(char_type value)
Definition format.h:1849
void write(bool value)
Definition format.h:1816
typename Range::iterator iterator
Definition format.h:1782
typename Range::value_type char_type
Definition format.h:1781
void write_pointer(const void *p)
Definition format.h:1806
format_specs * specs()
Definition format.h:1813
FMT_DEPRECATED format_specs * spec()
Definition format.h:1812
void write_char(char_type value)
Definition format.h:1799
iterator operator()(const char_type *value)
Definition format.h:1894
arg_formatter_base(Range r, format_specs *s, locale_ref loc)
Definition format.h:1832
void write_int(T value, const Spec &spec)
Definition format.h:1668
void write(unsigned value)
Definition format.h:1658
void write_int(int num_digits, string_view prefix, format_specs specs, F f)
Definition format.h:1415
void write(Char value)
Definition format.h:1732
void write(string_view value)
Definition format.h:1737
void write(int value)
Definition format.h:1654
iterator out() const
Definition format.h:1626
void write(wstring_view value)
Definition format.h:1741
auto reserve(std::size_t n) -> decltype(internal::reserve(out_, n))
Definition format.h:1389
void write_padded(const format_specs &specs, F &&f)
Definition format.h:1631
void write(unsigned long value)
Definition format.h:1659
void write_decimal(Int value)
Definition format.h:1435
void write(const Char *s, std::size_t size, const format_specs &specs)
Definition format.h:1748
typename Range::iterator iterator
Definition format.h:1380
void write(basic_string_view< Char > s, const format_specs &specs={})
Definition format.h:1753
typename Range::value_type char_type
Definition format.h:1379
void write(long long value)
Definition format.h:1656
void write(long value)
Definition format.h:1655
void write_pointer(UIntPtr value, const format_specs *specs)
Definition format.h:1762
basic_writer(Range out, locale_ref loc=locale_ref())
Definition format.h:1623
void write(unsigned long long value)
Definition format.h:1660
void write(T value, format_specs specs={})
Definition format.h:1673
void write(char value)
Definition format.h:1726
T * data() FMT_NOEXCEPT
Definition core.h:613
void append(const U *begin, const U *end)
Definition format.h:527
void push_back(const T &value)
Definition core.h:634
void resize(std::size_t new_size)
Definition core.h:621
std::size_t size() const FMT_NOEXCEPT
Definition core.h:607
void set(T *buf_data, std::size_t buf_capacity) FMT_NOEXCEPT
Definition core.h:587
std::size_t capacity() const FMT_NOEXCEPT
Definition core.h:610
FMT_CONSTEXPR void on_char()
Definition format.h:1331
FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
Definition format.h:1325
FMT_CONSTEXPR void on_int()
Definition format.h:1328
counting_iterator & operator++()
Definition format.h:357
std::output_iterator_tag iterator_category
Definition format.h:343
std::size_t count() const
Definition format.h:355
counting_iterator operator++(int)
Definition format.h:362
value_type operator*() const
Definition format.h:368
std::ptrdiff_t difference_type
Definition format.h:344
FMT_CONSTEXPR cstring_type_checker(ErrorHandler eh)
Definition format.h:1337
FMT_CONSTEXPR void on_string()
Definition format.h:1340
FMT_CONSTEXPR void on_pointer()
Definition format.h:1341
bool operator()(typename basic_format_arg< Context >::handle h) const
Definition format.h:1962
custom_formatter(basic_format_parse_context< char_type > &parse_ctx, Context &ctx)
Definition format.h:1958
basic_format_parse_context< char_type > & parse_ctx_
Definition format.h:1954
bool operator()(T) const
Definition format.h:1967
typename Context::char_type char_type
Definition format.h:1952
FMT_CONSTEXPR void on_error(const char *message)
Definition format.h:2248
FMT_CONSTEXPR arg_ref_type make_arg_ref(auto_id)
Definition format.h:2260
dynamic_format_specs< char_type > & specs_
Definition format.h:2271
FMT_CONSTEXPR arg_ref_type make_arg_ref(int arg_id)
Definition format.h:2255
FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs< char_type > &specs, ParseContext &ctx)
Definition format.h:2231
FMT_CONSTEXPR void on_dynamic_width(Id arg_id)
Definition format.h:2240
FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view< char_type > arg_id)
Definition format.h:2264
typename ParseContext::char_type char_type
Definition format.h:2229
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id)
Definition format.h:2244
FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler &other)
Definition format.h:2235
size_t size() const
Definition format.h:1176
void operator()(It &&it)
Definition format.h:1179
float_writer(const char *digits, int num_digits, int exp, float_specs specs, Char decimal_point)
Definition format.h:1159
float_specs specs_
Definition format.h:1086
size_t width() const
Definition format.h:1177
It prettify(It it) const
Definition format.h:1089
const char * digits_
Definition format.h:1082
FMT_CONSTEXPR const Char * on_format_specs(const Char *begin, const Char *)
Definition format.h:2591
FMT_CONSTEXPR void on_arg_id()
Definition format.h:2576
FMT_CONSTEXPR void on_text(const Char *, const Char *)
Definition format.h:2574
FMT_CONSTEXPR void on_arg_id(int id)
Definition format.h:2580
parse_context_type context_
Definition format.h:2612
FMT_CONSTEXPR void on_replacement_field(const Char *)
Definition format.h:2589
FMT_CONSTEXPR void on_error(const char *message)
Definition format.h:2596
FMT_CONSTEXPR void on_arg_id(basic_string_view< Char >)
Definition format.h:2585
const Char *(*)(parse_context_type &) parse_func
Definition format.h:2609
FMT_CONSTEXPR void check_arg_id()
Definition format.h:2604
FMT_CONSTEXPR format_string_checker(basic_string_view< Char > format_str, ErrorHandler eh)
Definition format.h:2568
FMT_CONSTEXPR void on_hex()
Definition format.h:1309
FMT_CONSTEXPR void on_num()
Definition format.h:1312
FMT_CONSTEXPR int_type_checker(ErrorHandler eh)
Definition format.h:1306
FMT_CONSTEXPR void on_dec()
Definition format.h:1308
FMT_CONSTEXPR void on_oct()
Definition format.h:1311
FMT_CONSTEXPR void on_bin()
Definition format.h:1310
FMT_CONSTEXPR void on_error()
Definition format.h:1314
static const bool value
Definition format.h:299
static decltype(*(std::declval< U >())) test(std::input_iterator_tag)
static char & test(std::output_iterator_tag)
static const char & test(...)
decltype(test< It >(typename iterator_category< It >::type{})) type
Definition format.h:296
FMT_CONSTEXPR numeric_specs_checker(ErrorHandler &eh, internal::type arg_type)
Definition format.h:2053
FMT_CONSTEXPR void require_numeric_argument()
Definition format.h:2056
FMT_CONSTEXPR void check_sign()
Definition format.h:2061
FMT_CONSTEXPR void check_precision()
Definition format.h:2069
ErrorHandler & error_handler_
Definition format.h:2075
sentinel end() const
Definition format.h:460
output_range(OutputIt it)
Definition format.h:458
OutputIt begin() const
Definition format.h:459
FMT_CONSTEXPR precision_checker(ErrorHandler &eh)
Definition format.h:1998
FMT_CONSTEXPR unsigned long long operator()(T)
Definition format.h:2007
FMT_CONSTEXPR unsigned long long operator()(T value)
Definition format.h:2001
ErrorHandler & handler_
Definition format.h:2013
numeric_specs_checker< Handler > checker_
Definition format.h:2122
FMT_CONSTEXPR specs_checker(const specs_checker &other)
Definition format.h:2086
FMT_CONSTEXPR void on_space()
Definition format.h:2104
FMT_CONSTEXPR void on_minus()
Definition format.h:2099
FMT_CONSTEXPR void on_zero()
Definition format.h:2114
FMT_CONSTEXPR void on_plus()
Definition format.h:2094
FMT_CONSTEXPR void end_precision()
Definition format.h:2119
FMT_CONSTEXPR void on_hash()
Definition format.h:2109
FMT_CONSTEXPR specs_checker(const Handler &handler, internal::type arg_type)
Definition format.h:2083
FMT_CONSTEXPR void on_align(align_t align)
Definition format.h:2089
typename Context::format_arg format_arg
Definition format.h:2168
FMT_CONSTEXPR format_arg get_arg(basic_string_view< char_type > arg_id)
Definition format.h:2179
FMT_CONSTEXPR format_arg get_arg(auto_id)
Definition format.h:2170
void on_error(const char *message)
Definition format.h:2164
ParseContext & parse_context_
Definition format.h:2184
FMT_CONSTEXPR format_arg get_arg(int arg_id)
Definition format.h:2174
FMT_CONSTEXPR specs_handler(basic_format_specs< char_type > &specs, ParseContext &parse_ctx, Context &ctx)
Definition format.h:2148
FMT_CONSTEXPR void on_dynamic_width(Id arg_id)
Definition format.h:2154
typename Context::char_type char_type
Definition format.h:2146
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id)
Definition format.h:2159
FMT_CONSTEXPR specs_setter(const specs_setter &other)
Definition format.h:2022
FMT_CONSTEXPR void on_type(Char type)
Definition format.h:2043
FMT_CONSTEXPR specs_setter(basic_format_specs< Char > &specs)
Definition format.h:2019
FMT_CONSTEXPR void on_width(int width)
Definition format.h:2037
FMT_CONSTEXPR void on_fill(Char fill)
Definition format.h:2026
FMT_CONSTEXPR void on_space()
Definition format.h:2029
FMT_CONSTEXPR void on_minus()
Definition format.h:2028
basic_format_specs< Char > & specs_
Definition format.h:2048
FMT_CONSTEXPR void on_zero()
Definition format.h:2032
FMT_CONSTEXPR void on_plus()
Definition format.h:2027
FMT_CONSTEXPR void end_precision()
Definition format.h:2041
FMT_CONSTEXPR void on_precision(int precision)
Definition format.h:2038
FMT_CONSTEXPR void on_hash()
Definition format.h:2030
FMT_CONSTEXPR void on_align(align_t align)
Definition format.h:2025
truncating_iterator(OutputIt out, std::size_t limit)
Definition format.h:409
typename OutputIt::container_type::value_type value_type
Definition format.h:432
truncating_iterator(OutputIt out, std::size_t limit)
Definition format.h:434
truncating_iterator & operator=(value_type val)
Definition format.h:437
std::output_iterator_tag iterator_category
Definition format.h:381
std::size_t count() const
Definition format.h:389
truncating_iterator_base(OutputIt out, std::size_t limit)
Definition format.h:377
FMT_CONSTEXPR unsigned long long operator()(T)
Definition format.h:1987
FMT_CONSTEXPR unsigned long long operator()(T value)
Definition format.h:1981
FMT_CONSTEXPR width_checker(ErrorHandler &eh)
Definition format.h:1978
ErrorHandler & handler_
Definition format.h:1993
system_error(int error_code, string_view message, const Args &... args)
Definition format.h:2731
~system_error() FMT_NOEXCEPT FMT_OVERRIDE
system_error & operator=(const system_error &)=default
system_error(const system_error &)=default
int error_code_
Definition format.h:2707
system_error & operator=(system_error &&)=default
system_error(system_error &&)=default
u8string_view(const char *s, size_t count) FMT_NOEXCEPT
Definition format.h:551
u8string_view(const char *s)
Definition format.h:549
void vprint(std::FILE *f, const text_style &ts, const S &format, basic_format_args< buffer_context< Char > > args)
Definition color.h:502
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
Definition color.h:562
std::size_t formatted_size(const CompiledFormat &cf, const Args &... args)
Definition compile.h:579
format_to_n_result< OutputIt > format_to_n(OutputIt out, size_t n, const CompiledFormat &cf, const Args &... args)
Definition compile.h:570
OutputIt format_to(OutputIt out, const CompiledFormat &cf, const Args &... args)
Definition compile.h:559
typename std::enable_if< B, T >::type enable_if_t
Definition core.h:204
#define FMT_OVERRIDE
Definition core.h:84
#define FMT_ASSERT(condition, message)
Definition core.h:233
std::integral_constant< bool, B > bool_constant
Definition core.h:207
basic_string_view< char > string_view
Definition core.h:364
internal::named_arg< T, Char > arg(const S &name, const T &arg)
Definition core.h:1422
#define FMT_EXTERN
Definition core.h:184
basic_string_view< wchar_t > wstring_view
Definition core.h:365
OutputIt vformat_to(OutputIt out, const S &format_str, basic_format_args< buffer_context< Char > > args)
Definition core.h:1437
#define FMT_CONSTEXPR
Definition core.h:75
format_arg_store< Context, Args... > make_format_args(const Args &... args)
Definition core.h:1225
#define FMT_BEGIN_NAMESPACE
Definition core.h:163
#define FMT_DEPRECATED
Definition core.h:137
FMT_CONSTEXPR auto visit_format_arg(Visitor &&vis, const basic_format_arg< Context > &arg) -> decltype(vis(0))
Definition core.h:1004
#define FMT_API
Definition core.h:177
basic_string_view< Char > to_string_view(const Char *s)
Definition core.h:397
#define FMT_ENABLE_IF(...)
Definition core.h:220
typename internal::char_t_impl< S >::type char_t
Definition core.h:458
#define FMT_EXTERN_TEMPLATE_API
Definition core.h:180
#define FMT_NORETURN
Definition core.h:124
typename std::conditional< B, T, F >::type conditional_t
Definition core.h:206
char8_t
Definition core.h:369
#define FMT_END_NAMESPACE
Definition core.h:158
#define FMT_NOEXCEPT
Definition core.h:116
#define FMT_CONSTEXPR_DECL
Definition core.h:76
typename internal::void_t_impl< Ts... >::type void_t
Definition core.h:272
FMT_FUNC void format_system_error(internal::buffer< char > &out, int error_code, string_view message) FMT_NOEXCEPT
FMT_FUNC void report_system_error(int error_code, fmt::string_view message) FMT_NOEXCEPT
arg_join< It, char > join(It begin, It end, string_view sep)
Definition format.h:3201
#define FMT_FORMAT_AS(Type, Base)
Definition format.h:2969
#define FMT_DEPRECATED_PERCENT
Definition format.h:200
#define FMT_USE_GRISU
Definition format.h:517
#define FMT_FALLTHROUGH
Definition format.h:76
const void * ptr(const T *p)
Definition format.h:3159
std::wstring to_wstring(const T &value)
Definition format.h:3252
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
@ inline_buffer_size
Definition format.h:566
basic_format_specs< char > format_specs
Definition format.h:1034
FMT_CONSTEXPR void advance_to(basic_format_parse_context< Char, ErrorHandler > &ctx, const Char *p)
Definition format.h:3085
format_arg_store< format_to_n_context< OutputIt, Char >, Args... > make_format_to_n_args(const Args &... args)
Definition format.h:3344
#define FMT_THROW(x)
Definition format.h:97
std::string to_string(const T &value)
Definition format.h:3245
@ numeric
Definition format.h:1005
@ left
Definition format.h:1005
@ none
Definition format.h:1005
@ center
Definition format.h:1005
@ right
Definition format.h:1005
FMT_CONSTEXPR bool is_name_start(Char c)
Definition format.h:1919
checked_ptr< typename Container::value_type > reserve(std::back_insert_iterator< Container > &it, std::size_t n)
Definition format.h:323
T * make_checked(T *p, std::size_t)
Definition format.h:319
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 handle_int_type_spec(char spec, Handler &&handler)
Definition format.h:1197
int snprintf_float(T value, int precision, float_specs specs, buffer< char > &buf)
FMT_CONSTEXPR const Char * parse_align(const Char *begin, const Char *end, Handler &&handler)
Definition format.h:2340
Container & get_container(std::back_insert_iterator< Container > it)
Definition core.h:665
FMT_CONSTEXPR const Char * parse_precision(const Char *begin, const Char *end, Handler &&handler)
Definition format.h:2397
constexpr int num_bits< fallback_uintptr >()
Definition format.h:260
FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler &&eh)
Definition format.h:1295
FMT_CONSTEXPR bool do_check_format_string(basic_string_view< Char > s, ErrorHandler eh=ErrorHandler())
Definition format.h:2617
Char * format_uint(Char *buffer, UInt value, int num_digits, bool upper=false)
Definition format.h:891
FMT_CONSTEXPR float_specs parse_float_type_spec(const basic_format_specs< Char > &specs, ErrorHandler &&eh={})
Definition format.h:1223
FMT_CONSTEXPR bool is_arithmetic_type(type t)
Definition core.h:740
T * checked_ptr
Definition format.h:318
FMT_CONSTEXPR const Char * parse_format_specs(const Char *begin, const Char *end, SpecHandler &&handler)
Definition format.h:2421
decltype(std::begin(std::declval< T & >())) iterator_t
Definition format.h:267
char8_t to_char8_t(char c)
Definition format.h:496
FMT_CONSTEXPR int get_dynamic_spec(FormatArg arg, ErrorHandler eh)
Definition format.h:2127
FMT_CONSTEXPR std::make_unsigned< Int >::type to_unsigned(Int value)
Definition core.h:265
Char * get_data(std::basic_string< Char > &s)
Definition format.h:303
Char decimal_point(locale_ref loc)
Definition format.h:830
FMT_FUNC std::string grouping_impl(locale_ref loc)
Definition format-inl.h:203
size_t code_point_index(basic_string_view< Char > s, size_t n)
Definition format.h:479
void reset_color(FILE *stream) FMT_NOEXCEPT
Definition color.h:457
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:1971
OutputIt copy_str(InputIt begin, InputIt end, OutputIt it)
Definition format.h:506
constexpr bool use_grisu()
Definition format.h:520
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:499
int count_digits(uint64_t n)
Definition format.h:755
fallback_uintptr to_uintptr(const void *p)
Definition format.h:247
FMT_CONSTEXPR const Char * parse_width(const Char *begin, const Char *end, Handler &&handler)
Definition format.h:2380
basic_writer< buffer_range< char > > writer
Definition format.h:1772
@ named_arg_type
Definition core.h:689
@ int_type
Definition core.h:691
@ ulong_long_type
Definition core.h:694
@ uint128_type
Definition core.h:696
@ none_type
Definition core.h:688
@ pointer_type
Definition core.h:707
@ float_type
Definition core.h:701
@ cstring_type
Definition core.h:705
@ custom_type
Definition core.h:708
@ uint_type
Definition core.h:692
@ long_long_type
Definition core.h:693
@ bool_type
Definition core.h:697
@ int128_type
Definition core.h:695
@ double_type
Definition core.h:702
@ long_double_type
Definition core.h:703
@ char_type
Definition core.h:698
@ string_type
Definition core.h:706
void check_format_string(const S &)
Definition core.h:1369
std::string grouping(locale_ref loc)
Definition format.h:814
FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler &&eh)
Definition format.h:1300
FMT_CONSTEXPR bool is_negative(T value)
Definition format.h:708
void handle_dynamic_spec(int &value, arg_ref< typename Context::char_type > ref, Context &ctx)
Definition format.h:2635
FMT_CONSTEXPR void handle_cstring_type_spec(Char spec, Handler &&handler)
Definition format.h:1285
Dest bit_cast(const Source &source)
Definition format.h:214
void write(std::basic_ostream< Char > &os, buffer< Char > &buf)
Definition ostream.h:78
size_t count_code_points(basic_string_view< Char > s)
Definition format.h:464
constexpr int digits10() noexcept
Definition format.h:868
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:719
fallback_uintptr uintptr_t
Definition format.h:246
It write_exponent(int exp, It it)
Definition format.h:1059
FMT_CONSTEXPR void parse_format_string(basic_string_view< Char > format_str, Handler &&handler)
Definition format.h:2499
FMT_CONSTEXPR bool is_integral_type(type t)
Definition core.h:735
FMT_CONSTEXPR const Char * parse_arg_id(const Char *begin, const Char *end, IDHandler &&handler)
Definition format.h:2276
T const_check(T value)
Definition format.h:208
constexpr int num_bits()
Definition format.h:257
Char * format_decimal(Char *buffer, UInt value, int num_digits, F add_thousands_sep)
Definition format.h:841
FMT_CONSTEXPR void handle_char_specs(const basic_format_specs< Char > *specs, Handler &&handler)
Definition format.h:1275
int format_float(T value, int precision, float_specs specs, buffer< char > &buf)
FMT_CONSTEXPR int parse_nonnegative_int(const Char *&begin, const Char *end, ErrorHandler &&eh)
Definition format.h:1926
T promote_float(T value)
Definition format.h:1193
std::basic_string< Char > vformat(basic_string_view< Char > format_str, basic_format_args< buffer_context< Char > > args)
Definition format.h:3379
FMT_CONSTEXPR bool find(Ptr first, Ptr last, T value, Ptr &out)
Definition format.h:2471
FMT_CONSTEXPR Context::format_arg get_arg(Context &ctx, int id)
Definition format.h:2136
bool is_big_endian()
Definition format.h:221
constexpr T max_value()
Definition format.h:254
Char thousands_sep(locale_ref loc)
Definition format.h:822
@ plus
Definition format.h:1010
@ none
Definition format.h:1010
@ minus
Definition format.h:1010
@ space
Definition format.h:1010
It begin
Definition format.h:3168
basic_string_view< Char > sep
Definition format.h:3170
arg_join(It b, It e, basic_string_view< Char > s)
Definition format.h:3172
internal::fill_t< Char > fill
Definition format.h:1022
constexpr basic_format_specs()
Definition format.h:1024
basic_format_arg< Context > arg
Definition format.h:3142
void on_arg_id(basic_string_view< Char > id)
Definition format.h:3114
void on_arg_id(int id)
Definition format.h:3110
void on_text(const Char *begin, const Char *end)
Definition format.h:3099
void get_arg(int id)
Definition format.h:3107
void on_arg_id()
Definition format.h:3109
format_handler(range r, basic_string_view< Char > str, basic_format_args< Context > format_args, internal::locale_ref loc)
Definition format.h:3094
const Char * on_format_specs(const Char *begin, const Char *end)
Definition format.h:3122
basic_format_parse_context< Char > parse_context
Definition format.h:3140
typename ArgFormatter::range range
Definition format.h:3092
void on_replacement_field(const Char *p)
Definition format.h:3116
Context context
Definition format.h:3141
std::size_t size
Definition format.h:3332
auto format(const Char *val, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:3000
auto format(const arg_join< It, Char > &value, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:3179
auto format(void *val, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:2992
char_spec_handler(arg_formatter_base &f, char_type val)
Definition format.h:1871
cstring_spec_handler(arg_formatter_base &f, const char_type *val)
Definition format.h:1887
FMT_CONSTEXPR int map(signed char val)
Definition core.h:835
union internal::arg_ref::value val
FMT_CONSTEXPR arg_ref & operator=(int idx)
Definition format.h:2198
FMT_CONSTEXPR arg_ref(int index)
Definition format.h:2193
FMT_CONSTEXPR arg_ref(basic_string_view< Char > name)
Definition format.h:2195
arg_id_kind kind
Definition format.h:2204
FMT_CONSTEXPR arg_ref()
Definition format.h:2192
static const char digits[]
Definition format.h:730
FMT_NORETURN void on_error()
Definition format.h:1589
uint32_or_64_or_128_t< Int > unsigned_type
Definition format.h:1448
basic_writer< Range > & writer
Definition format.h:1450
string_view get_prefix() const
Definition format.h:1456
int_writer(basic_writer< Range > &w, Int value, const Specs &s)
Definition format.h:1458
void operator()(It &&it) const
Definition format.h:1603
arg_ref< Char > width_ref
Definition format.h:2219
arg_ref< Char > precision_ref
Definition format.h:2220
unsigned char value[sizeof(void *)]
Definition format.h:231
fallback_uintptr(const void *p)
Definition format.h:234
FMT_CONSTEXPR const Char & operator[](size_t index) const
Definition format.h:990
FMT_CONSTEXPR Char & operator[](size_t index)
Definition format.h:989
static FMT_CONSTEXPR fill_t< Char > make()
Definition format.h:994
float_format format
Definition format.h:1048
FMT_CONSTEXPR void operator()(basic_string_view< Char > id)
Definition format.h:2489
FMT_CONSTEXPR void on_error(const char *message)
Definition format.h:2492
Handler & handler
Definition format.h:2495
FMT_CONSTEXPR void operator()()
Definition format.h:2487
FMT_CONSTEXPR void operator()(int id)
Definition format.h:2488
std::random_access_iterator_tag type
Definition format.h:276
size_t size() const
Definition format.h:1366
size_t width() const
Definition format.h:1367
void operator()(It &&it) const
Definition format.h:1369
FMT_CONSTEXPR void operator()(basic_string_view< Char > id)
Definition format.h:2327
FMT_CONSTEXPR void on_error(const char *message)
Definition format.h:2331
FMT_CONSTEXPR precision_adapter(SpecHandler &h)
Definition format.h:2323
FMT_CONSTEXPR void operator()()
Definition format.h:2325
FMT_CONSTEXPR void operator()(int id)
Definition format.h:2326
FMT_CONSTEXPR width_adapter(SpecHandler &h)
Definition format.h:2306
FMT_CONSTEXPR void operator()(basic_string_view< Char > id)
Definition format.h:2310
FMT_CONSTEXPR void on_error(const char *message)
Definition format.h:2314
FMT_CONSTEXPR void operator()()
Definition format.h:2308
FMT_CONSTEXPR void operator()(int id)
Definition format.h:2309
SpecHandler & handler
Definition format.h:2318
basic_string_view< Char > name
Definition format.h:2210
FMT_CONSTEXPR value(int id=0)
Definition format.h:2206
FMT_CONSTEXPR value(basic_string_view< Char > n)
Definition format.h:2207