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
82FMT_BEGIN_NAMESPACE
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
91FMT_END_NAMESPACE
92# define FMT_THROW(x) internal::do_throw(x)
93# else
94# define FMT_THROW(x) throw x
95# endif
96# else
97# define FMT_THROW(x) \
98 do { \
99 static_cast<void>(sizeof(x)); \
100 FMT_ASSERT(false, ""); \
101 } while (false)
102# endif
103#endif
104
105#ifndef FMT_USE_USER_DEFINED_LITERALS
106// For Intel and NVIDIA compilers both they and the system gcc/msc support UDLs.
107# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
108 FMT_MSC_VER >= 1900) && \
109 (!(FMT_ICC_VERSION || FMT_CUDA_VERSION) || FMT_ICC_VERSION >= 1500 || \
110 FMT_CUDA_VERSION >= 700)
111# define FMT_USE_USER_DEFINED_LITERALS 1
112# else
113# define FMT_USE_USER_DEFINED_LITERALS 0
114# endif
115#endif
116
117#ifndef FMT_USE_UDL_TEMPLATE
118// EDG front end based compilers (icc, nvcc) do not support UDL templates yet
119// and GCC 9 warns about them.
120# if FMT_USE_USER_DEFINED_LITERALS && FMT_ICC_VERSION == 0 && \
121 FMT_CUDA_VERSION == 0 && \
122 ((FMT_GCC_VERSION >= 600 && FMT_GCC_VERSION <= 900 && \
123 __cplusplus >= 201402L) || \
124 FMT_CLANG_VERSION >= 304)
125# define FMT_USE_UDL_TEMPLATE 1
126# else
127# define FMT_USE_UDL_TEMPLATE 0
128# endif
129#endif
130
131// __builtin_clz is broken in clang with Microsoft CodeGen:
132// https://github.com/fmtlib/fmt/issues/519
133#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clz)) && !FMT_MSC_VER
134# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
135#endif
136#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clzll)) && !FMT_MSC_VER
137# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
138#endif
139
140// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
141// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
142// MSVC intrinsics if the clz and clzll builtins are not available.
143#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)
144# include <intrin.h> // _BitScanReverse, _BitScanReverse64
145
146FMT_BEGIN_NAMESPACE
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
190FMT_END_NAMESPACE
191#endif
192
193// Enable the deprecated numeric alignment.
194#ifndef FMT_NUMERIC_ALIGN
195# define FMT_NUMERIC_ALIGN 1
196#endif
197
198// Enable the deprecated percent specifier.
199#ifndef FMT_DEPRECATED_PERCENT
200# define FMT_DEPRECATED_PERCENT 0
201#endif
202
203FMT_BEGIN_NAMESPACE
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.
230struct fallback_uintptr {
231 unsigned char value[sizeof(void*)];
232
233 fallback_uintptr() = default;
234 explicit fallback_uintptr(const void* p) {
235 *this = bit_cast<fallback_uintptr>(p);
236 if (is_big_endian()) {
237 for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
238 std::swap(value[i], value[j]);
239 }
240 }
241};
242#ifdef UINTPTR_MAX
243using uintptr_t = ::uintptr_t;
244inline uintptr_t to_uintptr(const void* p) { return bit_cast<uintptr_t>(p); }
245#else
246using uintptr_t = fallback_uintptr;
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)>
323inline checked_ptr<typename Container::value_type> reserve(
324 std::back_insert_iterator<Container>& it, std::size_t n) {
325 Container& c = get_container(it);
326 std::size_t size = c.size();
327 c.resize(size + n);
328 return make_checked(get_data(c) + size, n);
329}
330
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.
338class counting_iterator {
339 private:
340 std::size_t count_;
341
342 public:
343 using iterator_category = std::output_iterator_tag;
344 using difference_type = std::ptrdiff_t;
345 using pointer = void;
346 using reference = void;
347 using _Unchecked_type = counting_iterator; // Mark iterator as checked.
348
349 struct value_type {
350 template <typename T> void operator=(const T&) {}
351 };
352
353 counting_iterator() : count_(0) {}
354
355 std::size_t count() const { return count_; }
356
357 counting_iterator& operator++() {
358 ++count_;
359 return *this;
360 }
361
362 counting_iterator operator++(int) {
363 auto it = *this;
364 ++*this;
365 return it;
366 }
367
368 value_type operator*() const { return {}; }
369};
370
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;
385 using _Unchecked_type =
386 truncating_iterator_base; // Mark iterator as checked.
387
388 OutputIt base() const { return out_; }
389 std::size_t count() const { return count_; }
390};
391
392// An output iterator that truncates the output and counts the number of objects
393// written to it.
394template <typename OutputIt,
395 typename Enable = typename std::is_void<
396 typename std::iterator_traits<OutputIt>::value_type>::type>
397class truncating_iterator;
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
412 truncating_iterator& operator++() {
413 if (this->count_++ < this->limit_) ++this->out_;
414 return *this;
415 }
416
417 truncating_iterator operator++(int) {
418 auto it = *this;
419 ++*this;
420 return it;
421 }
422
423 value_type& operator*() const {
424 return this->count_ < this->limit_ ? *this->out_ : blackhole_;
425 }
426};
427
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
437 truncating_iterator& operator=(value_type val) {
438 if (this->count_++ < this->limit_) this->out_ = val;
439 return *this;
440 }
441
442 truncating_iterator& operator++() { return *this; }
443 truncating_iterator& operator++(int) { return *this; }
444 truncating_iterator& operator*() { return *this; }
445};
446
447// A range with the specified output iterator and value type.
448template <typename OutputIt, typename T = typename OutputIt::value_type>
449class output_range {
450 private:
451 OutputIt it_;
452
453 public:
454 using value_type = T;
455 using iterator = OutputIt;
456 struct sentinel {};
457
458 explicit output_range(OutputIt it) : it_(it) {}
459 OutputIt begin() const { return it_; }
460 sentinel end() const { return {}; } // Sentinel is not used yet.
461};
462
463template <typename Char>
464inline size_t count_code_points(basic_string_view<Char> s) {
465 return s.size();
466}
467
468// Counts the number of code points in a UTF-8 string.
469inline size_t count_code_points(basic_string_view<char8_t> s) {
470 const char8_t* data = s.data();
471 size_t num_code_points = 0;
472 for (size_t i = 0, size = s.size(); i != size; ++i) {
473 if ((data[i] & 0xc0) != 0x80) ++num_code_points;
474 }
475 return num_code_points;
476}
477
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.
485inline size_t code_point_index(basic_string_view<char8_t> s, size_t n) {
486 const char8_t* data = s.data();
487 size_t num_code_points = 0;
488 for (size_t i = 0, size = s.size(); i != size; ++i) {
489 if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) {
490 return i;
491 }
492 }
493 return s.size();
494}
495
496inline char8_t to_char8_t(char c) { return static_cast<char8_t>(c); }
497
498template <typename InputIt, typename OutChar>
499using needs_conversion = bool_constant<
500 std::is_same<typename std::iterator_traits<InputIt>::value_type,
501 char>::value &&
502 std::is_same<OutChar, char8_t>::value>;
503
504template <typename OutChar, typename InputIt, typename OutputIt,
505 FMT_ENABLE_IF(!needs_conversion<InputIt, OutChar>::value)>
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>
537class buffer_range : public internal::output_range<
538 std::back_insert_iterator<internal::buffer<T>>, T> {
539 public:
540 using iterator = std::back_insert_iterator<internal::buffer<T>>;
541 using internal::output_range<iterator, T>::output_range;
542 buffer_range(internal::buffer<T>& buf)
543 : internal::output_range<iterator, T>(std::back_inserter(buf)) {}
544};
545
546// A UTF-8 string view.
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 }
620 ~basic_memory_buffer() FMT_OVERRIDE { deallocate(); }
621
622 private:
623 // Move data from other to this buffer.
624 void move(basic_memory_buffer& other) {
625 Allocator &this_alloc = *this, &other_alloc = other;
626 this_alloc = std::move(other_alloc);
627 T* data = other.data();
628 std::size_t size = other.size(), capacity = other.capacity();
629 if (data == other.store_) {
630 this->set(store_, capacity);
631 std::uninitialized_copy(other.store_, other.store_ + size,
632 internal::make_checked(store_, capacity));
633 } else {
634 this->set(data, capacity);
635 // Set pointer to the inline array so that delete is not called
636 // when deallocating.
637 other.set(other.store_, 0);
638 }
639 this->resize(size);
640 }
641
642 public:
643 /**
644 \rst
645 Constructs a :class:`fmt::basic_memory_buffer` object moving the content
646 of the other object to it.
647 \endrst
648 */
649 basic_memory_buffer(basic_memory_buffer&& other) FMT_NOEXCEPT { move(other); }
650
651 /**
652 \rst
653 Moves the content of the other ``basic_memory_buffer`` object to this one.
654 \endrst
655 */
656 basic_memory_buffer& operator=(basic_memory_buffer&& other) FMT_NOEXCEPT {
657 FMT_ASSERT(this != &other, "");
658 deallocate();
659 move(other);
660 return *this;
661 }
662
663 // Returns a copy of the allocator associated with this buffer.
664 Allocator get_allocator() const { return *this; }
665};
666
667template <typename T, std::size_t SIZE, typename Allocator>
668void basic_memory_buffer<T, SIZE, Allocator>::grow(std::size_t size) {
669#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
670 if (size > 1000) throw std::runtime_error("fuzz mode - won't grow that much");
671#endif
672 std::size_t old_capacity = this->capacity();
673 std::size_t new_capacity = old_capacity + old_capacity / 2;
674 if (size > new_capacity) new_capacity = size;
675 T* old_data = this->data();
676 T* new_data = std::allocator_traits<Allocator>::allocate(*this, new_capacity);
677 // The following code doesn't throw, so the raw pointer above doesn't leak.
678 std::uninitialized_copy(old_data, old_data + this->size(),
679 internal::make_checked(new_data, new_capacity));
680 this->set(new_data, new_capacity);
681 // deallocate must not throw according to the standard, but even if it does,
682 // the buffer already uses the new storage and will deallocate it in
683 // destructor.
684 if (old_data != store_) Allocator::deallocate(old_data, old_capacity);
685}
686
687using memory_buffer = basic_memory_buffer<char>;
688using wmemory_buffer = basic_memory_buffer<wchar_t>;
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;
697 format_error& operator=(const format_error&) = default;
698 format_error(format_error&&) = default;
699 format_error& operator=(format_error&&) = default;
700 ~format_error() FMT_NOEXCEPT FMT_OVERRIDE;
701};
702
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)>
708FMT_CONSTEXPR bool is_negative(T value) {
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>
719using uint32_or_64_or_128_t = conditional_t<
720 std::numeric_limits<T>::digits <= 32, uint32_t,
721 conditional_t<std::numeric_limits<T>::digits <= 64, uint64_t, uint128_t>>;
722
723// Static data is placed in this class template for the header-only config.
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
739FMT_EXTERN template struct basic_data<void>;
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
994 static FMT_CONSTEXPR fill_t<Char> make() {
995 auto fill = fill_t<Char>();
996 fill[0] = Char(' ');
997 return fill;
998 }
999};
1000} // namespace internal
1001
1002// We cannot use enum classes as bit fields because of a gcc bug
1003// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
1004namespace align {
1005enum type { none, left, right, center, numeric };
1006}
1007using align_t = align::type;
1008
1009namespace sign {
1010enum type { none, minus, plus, space };
1011}
1012using sign_t = sign::type;
1013
1014// Format specifiers for built-in and string types.
1015template <typename Char> struct basic_format_specs {
1016 int width;
1017 int precision;
1018 char type;
1019 align_t align : 4;
1020 sign_t sign : 3;
1021 bool alt : 1; // Alternate form ('#').
1022 internal::fill_t<Char> fill;
1023
1024 constexpr basic_format_specs()
1025 : width(0),
1026 precision(-1),
1027 type(0),
1028 align(align::none),
1029 sign(sign::none),
1030 alt(false),
1031 fill(internal::fill_t<Char>::make()) {}
1032};
1033
1034using format_specs = basic_format_specs<char>;
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
1046struct float_specs {
1047 int precision;
1048 float_format format : 8;
1049 sign_t sign : 8;
1050 bool upper : 1;
1051 bool locale : 1;
1052 bool percent : 1;
1053 bool binary32 : 1;
1054 bool use_grisu : 1;
1055 bool trailing_zeros : 1;
1056};
1057
1058// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
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_;
1083 int num_digits_;
1084 int exp_;
1085 size_t size_;
1086 float_specs specs_;
1087 Char decimal_point_;
1088
1089 template <typename It> It prettify(It it) const {
1090 // pow(10, full_exp - 1) <= v <= pow(10, full_exp).
1091 int full_exp = num_digits_ + exp_;
1092 if (specs_.format == float_format::exp) {
1093 // Insert a decimal point after the first digit and add an exponent.
1094 *it++ = static_cast<Char>(*digits_);
1095 int num_zeros = specs_.precision - num_digits_;
1096 bool trailing_zeros = num_zeros > 0 && specs_.trailing_zeros;
1097 if (num_digits_ > 1 || trailing_zeros) *it++ = decimal_point_;
1098 it = copy_str<Char>(digits_ + 1, digits_ + num_digits_, it);
1099 if (trailing_zeros)
1100 it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
1101 *it++ = static_cast<Char>(specs_.upper ? 'E' : 'e');
1102 return write_exponent<Char>(full_exp - 1, it);
1103 }
1104 if (num_digits_ <= full_exp) {
1105 // 1234e7 -> 12340000000[.0+]
1106 it = copy_str<Char>(digits_, digits_ + num_digits_, it);
1107 it = std::fill_n(it, full_exp - num_digits_, static_cast<Char>('0'));
1108 if (specs_.trailing_zeros) {
1109 *it++ = decimal_point_;
1110 int num_zeros = specs_.precision - full_exp;
1111 if (num_zeros <= 0) {
1112 if (specs_.format != float_format::fixed)
1113 *it++ = static_cast<Char>('0');
1114 return it;
1115 }
1116#ifdef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
1117 if (num_zeros > 1000)
1118 throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
1119#endif
1120 it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
1121 }
1122 } else if (full_exp > 0) {
1123 // 1234e-2 -> 12.34[0+]
1124 it = copy_str<Char>(digits_, digits_ + full_exp, it);
1125 if (!specs_.trailing_zeros) {
1126 // Remove trailing zeros.
1127 int num_digits = num_digits_;
1128 while (num_digits > full_exp && digits_[num_digits - 1] == '0')
1129 --num_digits;
1130 if (num_digits != full_exp) *it++ = decimal_point_;
1131 return copy_str<Char>(digits_ + full_exp, digits_ + num_digits, it);
1132 }
1133 *it++ = decimal_point_;
1134 it = copy_str<Char>(digits_ + full_exp, digits_ + num_digits_, it);
1135 if (specs_.precision > num_digits_) {
1136 // Add trailing zeros.
1137 int num_zeros = specs_.precision - num_digits_;
1138 it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
1139 }
1140 } else {
1141 // 1234e-6 -> 0.001234
1142 *it++ = static_cast<Char>('0');
1143 int num_zeros = -full_exp;
1144 if (specs_.precision >= 0 && specs_.precision < num_zeros)
1145 num_zeros = specs_.precision;
1146 int num_digits = num_digits_;
1147 if (!specs_.trailing_zeros)
1148 while (num_digits > 0 && digits_[num_digits - 1] == '0') --num_digits;
1149 if (num_zeros != 0 || num_digits != 0) {
1150 *it++ = decimal_point_;
1151 it = std::fill_n(it, num_zeros, static_cast<Char>('0'));
1152 it = copy_str<Char>(digits_, digits_ + num_digits, it);
1153 }
1154 }
1155 return it;
1156 }
1157
1158 public:
1159 float_writer(const char* digits, int num_digits, int exp, float_specs specs,
1160 Char decimal_point)
1161 : digits_(digits),
1162 num_digits_(num_digits),
1163 exp_(exp),
1164 specs_(specs),
1165 decimal_point_(decimal_point) {
1166 int full_exp = num_digits + exp - 1;
1167 int precision = specs.precision > 0 ? specs.precision : 16;
1168 if (specs_.format == float_format::general &&
1169 !(full_exp >= -4 && full_exp < precision)) {
1170 specs_.format = float_format::exp;
1171 }
1172 size_ = prettify(counting_iterator()).count();
1173 size_ += specs.sign ? 1 : 0;
1174 }
1175
1176 size_t size() const { return size_; }
1177 size_t width() const { return size(); }
1178
1179 template <typename It> void operator()(It&& it) {
1180 if (specs_.sign) *it++ = static_cast<Char>(data::signs[specs_.sign]);
1181 it = prettify(it);
1182 }
1183};
1184
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>
1223FMT_CONSTEXPR float_specs parse_float_type_spec(
1224 const basic_format_specs<Char>& specs, ErrorHandler&& eh = {}) {
1225 auto result = float_specs();
1226 result.trailing_zeros = specs.alt;
1227 switch (specs.type) {
1228 case 0:
1229 result.format = float_format::general;
1230 result.trailing_zeros |= specs.precision != 0;
1231 break;
1232 case 'G':
1233 result.upper = true;
1234 FMT_FALLTHROUGH;
1235 case 'g':
1236 result.format = float_format::general;
1237 break;
1238 case 'E':
1239 result.upper = true;
1240 FMT_FALLTHROUGH;
1241 case 'e':
1242 result.format = float_format::exp;
1243 result.trailing_zeros |= specs.precision != 0;
1244 break;
1245 case 'F':
1246 result.upper = true;
1247 FMT_FALLTHROUGH;
1248 case 'f':
1249 result.format = float_format::fixed;
1250 result.trailing_zeros |= specs.precision != 0;
1251 break;
1252#if FMT_DEPRECATED_PERCENT
1253 case '%':
1254 result.format = float_format::fixed;
1255 result.percent = true;
1256 break;
1257#endif
1258 case 'A':
1259 result.upper = true;
1260 FMT_FALLTHROUGH;
1261 case 'a':
1262 result.format = float_format::hex;
1263 break;
1264 case 'n':
1265 result.locale = true;
1266 break;
1267 default:
1268 eh.on_error("invalid type specifier");
1269 break;
1270 }
1271 return result;
1272}
1273
1274template <typename Char, typename Handler>
1275FMT_CONSTEXPR void handle_char_specs(const basic_format_specs<Char>* specs,
1276 Handler&& handler) {
1277 if (!specs) return handler.on_char();
1278 if (specs->type && specs->type != 'c') return handler.on_int();
1279 if (specs->align == align::numeric || specs->sign != sign::none || specs->alt)
1280 handler.on_error("invalid format specifier for char");
1281 handler.on_char();
1282}
1283
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
1308 FMT_CONSTEXPR void on_dec() {}
1309 FMT_CONSTEXPR void on_hex() {}
1310 FMT_CONSTEXPR void on_bin() {}
1311 FMT_CONSTEXPR void on_oct() {}
1312 FMT_CONSTEXPR void on_num() {}
1313
1314 FMT_CONSTEXPR void on_error() {
1315 ErrorHandler::on_error("invalid type specifier");
1316 }
1317};
1318
1319template <typename ErrorHandler>
1320class char_specs_checker : public ErrorHandler {
1321 private:
1322 char type_;
1323
1324 public:
1325 FMT_CONSTEXPR char_specs_checker(char type, ErrorHandler eh)
1326 : ErrorHandler(eh), type_(type) {}
1327
1328 FMT_CONSTEXPR void on_int() {
1329 handle_int_type_spec(type_, int_type_checker<ErrorHandler>(*this));
1330 }
1331 FMT_CONSTEXPR void on_char() {}
1332};
1333
1334template <typename ErrorHandler>
1335class cstring_type_checker : public ErrorHandler {
1336 public:
1337 FMT_CONSTEXPR explicit cstring_type_checker(ErrorHandler eh)
1338 : ErrorHandler(eh) {}
1339
1340 FMT_CONSTEXPR void on_string() {}
1341 FMT_CONSTEXPR void on_pointer() {}
1342};
1343
1344template <typename Context>
1345void arg_map<Context>::init(const basic_format_args<Context>& args) {
1346 if (map_) return;
1347 map_ = new entry[internal::to_unsigned(args.max_size())];
1348 if (args.is_packed()) {
1349 for (int i = 0;; ++i) {
1350 internal::type arg_type = args.type(i);
1351 if (arg_type == internal::none_type) return;
1352 if (arg_type == internal::named_arg_type) push_back(args.values_[i]);
1353 }
1354 }
1355 for (int i = 0, n = args.max_size(); i < n; ++i) {
1356 auto type = args.args_[i].type_;
1357 if (type == internal::named_arg_type) push_back(args.args_[i].value_);
1358 }
1359}
1360
1361template <typename Char> struct nonfinite_writer {
1362 sign_t sign;
1363 const char* str;
1364 static constexpr size_t str_size = 3;
1365
1366 size_t size() const { return str_size + (sign ? 1 : 0); }
1367 size_t width() const { return size(); }
1368
1369 template <typename It> void operator()(It&& it) const {
1370 if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1371 it = copy_str<Char>(str, str + str_size, it);
1372 }
1373};
1374
1375// This template provides operations for formatting and writing data into a
1376// character range.
1377template <typename Range> class basic_writer {
1378 public:
1379 using char_type = typename Range::value_type;
1380 using iterator = typename Range::iterator;
1381 using format_specs = basic_format_specs<char_type>;
1382
1383 private:
1384 iterator out_; // Output iterator.
1385 locale_ref locale_;
1386
1387 // Attempts to reserve space for n extra characters in the output range.
1388 // Returns a pointer to the reserved range or a reference to out_.
1389 auto reserve(std::size_t n) -> decltype(internal::reserve(out_, n)) {
1390 return internal::reserve(out_, n);
1391 }
1392
1393 template <typename F> struct padded_int_writer {
1394 size_t size_;
1395 string_view prefix;
1396 char_type fill;
1397 std::size_t padding;
1398 F f;
1399
1400 size_t size() const { return size_; }
1401 size_t width() const { return size_; }
1402
1403 template <typename It> void operator()(It&& it) const {
1404 if (prefix.size() != 0)
1405 it = copy_str<char_type>(prefix.begin(), prefix.end(), it);
1406 it = std::fill_n(it, padding, fill);
1407 f(it);
1408 }
1409 };
1410
1411 // Writes an integer in the format
1412 // <left-padding><prefix><numeric-padding><digits><right-padding>
1413 // where <digits> are written by f(it).
1414 template <typename F>
1415 void write_int(int num_digits, string_view prefix, format_specs specs, F f) {
1416 std::size_t size = prefix.size() + to_unsigned(num_digits);
1417 char_type fill = specs.fill[0];
1418 std::size_t padding = 0;
1419 if (specs.align == align::numeric) {
1420 auto unsiged_width = to_unsigned(specs.width);
1421 if (unsiged_width > size) {
1422 padding = unsiged_width - size;
1423 size = unsiged_width;
1424 }
1425 } else if (specs.precision > num_digits) {
1426 size = prefix.size() + to_unsigned(specs.precision);
1427 padding = to_unsigned(specs.precision - num_digits);
1428 fill = static_cast<char_type>('0');
1429 }
1430 if (specs.align == align::none) specs.align = align::right;
1431 write_padded(specs, padded_int_writer<F>{size, prefix, fill, padding, f});
1432 }
1433
1434 // Writes a decimal integer.
1435 template <typename Int> void write_decimal(Int value) {
1436 auto abs_value = static_cast<uint32_or_64_or_128_t<Int>>(value);
1437 bool negative = is_negative(value);
1438 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
1439 if (negative) abs_value = ~abs_value + 1;
1440 int num_digits = count_digits(abs_value);
1441 auto&& it = reserve((negative ? 1 : 0) + static_cast<size_t>(num_digits));
1442 if (negative) *it++ = static_cast<char_type>('-');
1443 it = format_decimal<char_type>(it, abs_value, num_digits);
1444 }
1445
1446 // The handle_int_type_spec handler that writes an integer.
1447 template <typename Int, typename Specs> struct int_writer {
1448 using unsigned_type = uint32_or_64_or_128_t<Int>;
1449
1450 basic_writer<Range>& writer;
1451 const Specs& specs;
1452 unsigned_type abs_value;
1453 char prefix[4];
1454 unsigned prefix_size;
1455
1456 string_view get_prefix() const { return string_view(prefix, prefix_size); }
1457
1458 int_writer(basic_writer<Range>& w, Int value, const Specs& s)
1459 : writer(w),
1460 specs(s),
1461 abs_value(static_cast<unsigned_type>(value)),
1462 prefix_size(0) {
1463 if (is_negative(value)) {
1464 prefix[0] = '-';
1465 ++prefix_size;
1466 abs_value = 0 - abs_value;
1467 } else if (specs.sign != sign::none && specs.sign != sign::minus) {
1468 prefix[0] = specs.sign == sign::plus ? '+' : ' ';
1469 ++prefix_size;
1470 }
1471 }
1472
1473 struct dec_writer {
1474 unsigned_type abs_value;
1475 int num_digits;
1476
1477 template <typename It> void operator()(It&& it) const {
1478 it = internal::format_decimal<char_type>(it, abs_value, num_digits);
1479 }
1480 };
1481
1482 void on_dec() {
1483 int num_digits = count_digits(abs_value);
1484 writer.write_int(num_digits, get_prefix(), specs,
1485 dec_writer{abs_value, num_digits});
1486 }
1487
1488 struct hex_writer {
1489 int_writer& self;
1490 int num_digits;
1491
1492 template <typename It> void operator()(It&& it) const {
1493 it = format_uint<4, char_type>(it, self.abs_value, num_digits,
1494 self.specs.type != 'x');
1495 }
1496 };
1497
1498 void on_hex() {
1499 if (specs.alt) {
1500 prefix[prefix_size++] = '0';
1501 prefix[prefix_size++] = specs.type;
1502 }
1503 int num_digits = count_digits<4>(abs_value);
1504 writer.write_int(num_digits, get_prefix(), specs,
1505 hex_writer{*this, num_digits});
1506 }
1507
1508 template <int BITS> struct bin_writer {
1509 unsigned_type abs_value;
1510 int num_digits;
1511
1512 template <typename It> void operator()(It&& it) const {
1513 it = format_uint<BITS, char_type>(it, abs_value, num_digits);
1514 }
1515 };
1516
1517 void on_bin() {
1518 if (specs.alt) {
1519 prefix[prefix_size++] = '0';
1520 prefix[prefix_size++] = static_cast<char>(specs.type);
1521 }
1522 int num_digits = count_digits<1>(abs_value);
1523 writer.write_int(num_digits, get_prefix(), specs,
1524 bin_writer<1>{abs_value, num_digits});
1525 }
1526
1527 void on_oct() {
1528 int num_digits = count_digits<3>(abs_value);
1529 if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
1530 // Octal prefix '0' is counted as a digit, so only add it if precision
1531 // is not greater than the number of digits.
1532 prefix[prefix_size++] = '0';
1533 }
1534 writer.write_int(num_digits, get_prefix(), specs,
1535 bin_writer<3>{abs_value, num_digits});
1536 }
1537
1538 enum { sep_size = 1 };
1539
1540 struct num_writer {
1541 unsigned_type abs_value;
1542 int size;
1543 const std::string& groups;
1544 char_type sep;
1545
1546 template <typename It> void operator()(It&& it) const {
1547 basic_string_view<char_type> s(&sep, sep_size);
1548 // Index of a decimal digit with the least significant digit having
1549 // index 0.
1550 int digit_index = 0;
1551 std::string::const_iterator group = groups.cbegin();
1552 it = format_decimal<char_type>(
1553 it, abs_value, size,
1554 [this, s, &group, &digit_index](char_type*& buffer) {
1555 if (*group <= 0 || ++digit_index % *group != 0 ||
1556 *group == max_value<char>())
1557 return;
1558 if (group + 1 != groups.cend()) {
1559 digit_index = 0;
1560 ++group;
1561 }
1562 buffer -= s.size();
1563 std::uninitialized_copy(s.data(), s.data() + s.size(),
1564 make_checked(buffer, s.size()));
1565 });
1566 }
1567 };
1568
1569 void on_num() {
1570 std::string groups = grouping<char_type>(writer.locale_);
1571 if (groups.empty()) return on_dec();
1572 auto sep = thousands_sep<char_type>(writer.locale_);
1573 if (!sep) return on_dec();
1574 int num_digits = count_digits(abs_value);
1575 int size = num_digits;
1576 std::string::const_iterator group = groups.cbegin();
1577 while (group != groups.cend() && num_digits > *group && *group > 0 &&
1578 *group != max_value<char>()) {
1579 size += sep_size;
1580 num_digits -= *group;
1581 ++group;
1582 }
1583 if (group == groups.cend())
1584 size += sep_size * ((num_digits - 1) / groups.back());
1585 writer.write_int(size, get_prefix(), specs,
1586 num_writer{abs_value, size, groups, sep});
1587 }
1588
1589 FMT_NORETURN void on_error() {
1590 FMT_THROW(format_error("invalid type specifier"));
1591 }
1592 };
1593
1594 template <typename Char> struct str_writer {
1595 const Char* s;
1596 size_t size_;
1597
1598 size_t size() const { return size_; }
1599 size_t width() const {
1600 return count_code_points(basic_string_view<Char>(s, size_));
1601 }
1602
1603 template <typename It> void operator()(It&& it) const {
1604 it = copy_str<char_type>(s, s + size_, it);
1605 }
1606 };
1607
1608 template <typename UIntPtr> struct pointer_writer {
1609 UIntPtr value;
1610 int num_digits;
1611
1612 size_t size() const { return to_unsigned(num_digits) + 2; }
1613 size_t width() const { return size(); }
1614
1615 template <typename It> void operator()(It&& it) const {
1616 *it++ = static_cast<char_type>('0');
1617 *it++ = static_cast<char_type>('x');
1618 it = format_uint<4, char_type>(it, value, num_digits);
1619 }
1620 };
1621
1622 public:
1623 explicit basic_writer(Range out, locale_ref loc = locale_ref())
1624 : out_(out.begin()), locale_(loc) {}
1625
1626 iterator out() const { return out_; }
1627
1628 // Writes a value in the format
1629 // <left-padding><value><right-padding>
1630 // where <value> is written by f(it).
1631 template <typename F> void write_padded(const format_specs& specs, F&& f) {
1632 // User-perceived width (in code points).
1633 unsigned width = to_unsigned(specs.width);
1634 size_t size = f.size(); // The number of code units.
1635 size_t num_code_points = width != 0 ? f.width() : size;
1636 if (width <= num_code_points) return f(reserve(size));
1637 auto&& it = reserve(width + (size - num_code_points));
1638 char_type fill = specs.fill[0];
1639 std::size_t padding = width - num_code_points;
1640 if (specs.align == align::right) {
1641 it = std::fill_n(it, padding, fill);
1642 f(it);
1643 } else if (specs.align == align::center) {
1644 std::size_t left_padding = padding / 2;
1645 it = std::fill_n(it, left_padding, fill);
1646 f(it);
1647 it = std::fill_n(it, padding - left_padding, fill);
1648 } else {
1649 f(it);
1650 it = std::fill_n(it, padding, fill);
1651 }
1652 }
1653
1654 void write(int value) { write_decimal(value); }
1655 void write(long value) { write_decimal(value); }
1656 void write(long long value) { write_decimal(value); }
1657
1658 void write(unsigned value) { write_decimal(value); }
1659 void write(unsigned long value) { write_decimal(value); }
1660 void write(unsigned long long value) { write_decimal(value); }
1661
1662#if FMT_USE_INT128
1663 void write(int128_t value) { write_decimal(value); }
1664 void write(uint128_t value) { write_decimal(value); }
1665#endif
1666
1667 template <typename T, typename Spec>
1668 void write_int(T value, const Spec& spec) {
1669 handle_int_type_spec(spec.type, int_writer<T, Spec>(*this, value, spec));
1670 }
1671
1672 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1673 void write(T value, format_specs specs = {}) {
1674 float_specs fspecs = parse_float_type_spec(specs);
1675 fspecs.sign = specs.sign;
1676 if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
1677 fspecs.sign = sign::minus;
1678 value = -value;
1679 } else if (fspecs.sign == sign::minus) {
1680 fspecs.sign = sign::none;
1681 }
1682
1683 if (!std::isfinite(value)) {
1684 auto str = std::isinf(value) ? (fspecs.upper ? "INF" : "inf")
1685 : (fspecs.upper ? "NAN" : "nan");
1686 return write_padded(specs, nonfinite_writer<char_type>{fspecs.sign, str});
1687 }
1688
1689 if (specs.align == align::none) {
1690 specs.align = align::right;
1691 } else if (specs.align == align::numeric) {
1692 if (fspecs.sign) {
1693 auto&& it = reserve(1);
1694 *it++ = static_cast<char_type>(data::signs[fspecs.sign]);
1695 fspecs.sign = sign::none;
1696 if (specs.width != 0) --specs.width;
1697 }
1698 specs.align = align::right;
1699 }
1700
1701 memory_buffer buffer;
1702 if (fspecs.format == float_format::hex) {
1703 if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
1704 snprintf_float(promote_float(value), specs.precision, fspecs, buffer);
1705 write_padded(specs, str_writer<char>{buffer.data(), buffer.size()});
1706 return;
1707 }
1708 int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
1709 if (fspecs.format == float_format::exp) ++precision;
1710 if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1711 fspecs.use_grisu = use_grisu<T>();
1712 if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) value *= 100;
1713 int exp = format_float(promote_float(value), precision, fspecs, buffer);
1714 if (const_check(FMT_DEPRECATED_PERCENT) && fspecs.percent) {
1715 buffer.push_back('%');
1716 --exp; // Adjust decimal place position.
1717 }
1718 fspecs.precision = precision;
1719 char_type point = fspecs.locale ? decimal_point<char_type>(locale_)
1720 : static_cast<char_type>('.');
1721 write_padded(specs, float_writer<char_type>(buffer.data(),
1722 static_cast<int>(buffer.size()),
1723 exp, fspecs, point));
1724 }
1725
1726 void write(char value) {
1727 auto&& it = reserve(1);
1728 *it++ = value;
1729 }
1730
1731 template <typename Char, FMT_ENABLE_IF(std::is_same<Char, char_type>::value)>
1732 void write(Char value) {
1733 auto&& it = reserve(1);
1734 *it++ = value;
1735 }
1736
1737 void write(string_view value) {
1738 auto&& it = reserve(value.size());
1739 it = copy_str<char_type>(value.begin(), value.end(), it);
1740 }
1741 void write(wstring_view value) {
1742 static_assert(std::is_same<char_type, wchar_t>::value, "");
1743 auto&& it = reserve(value.size());
1744 it = std::copy(value.begin(), value.end(), it);
1745 }
1746
1747 template <typename Char>
1748 void write(const Char* s, std::size_t size, const format_specs& specs) {
1749 write_padded(specs, str_writer<Char>{s, size});
1750 }
1751
1752 template <typename Char>
1753 void write(basic_string_view<Char> s, const format_specs& specs = {}) {
1754 const Char* data = s.data();
1755 std::size_t size = s.size();
1756 if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
1757 size = code_point_index(s, to_unsigned(specs.precision));
1758 write(data, size, specs);
1759 }
1760
1761 template <typename UIntPtr>
1762 void write_pointer(UIntPtr value, const format_specs* specs) {
1763 int num_digits = count_digits<4>(value);
1764 auto pw = pointer_writer<UIntPtr>{value, num_digits};
1765 if (!specs) return pw(reserve(to_unsigned(num_digits) + 2));
1766 format_specs specs_copy = *specs;
1767 if (specs_copy.align == align::none) specs_copy.align = align::right;
1768 write_padded(specs_copy, pw);
1769 }
1770};
1771
1772using writer = basic_writer<buffer_range<char>>;
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>
1779class arg_formatter_base {
1780 public:
1781 using char_type = typename Range::value_type;
1782 using iterator = typename Range::iterator;
1783 using format_specs = basic_format_specs<char_type>;
1784
1785 private:
1786 using writer_type = basic_writer<Range>;
1787 writer_type writer_;
1788 format_specs* specs_;
1789
1790 struct char_writer {
1791 char_type value;
1792
1793 size_t size() const { return 1; }
1794 size_t width() const { return 1; }
1795
1796 template <typename It> void operator()(It&& it) const { *it++ = value; }
1797 };
1798
1799 void write_char(char_type value) {
1800 if (specs_)
1801 writer_.write_padded(*specs_, char_writer{value});
1802 else
1803 writer_.write(value);
1804 }
1805
1806 void write_pointer(const void* p) {
1807 writer_.write_pointer(internal::to_uintptr(p), specs_);
1808 }
1809
1810 protected:
1811 writer_type& writer() { return writer_; }
1812 FMT_DEPRECATED format_specs* spec() { return specs_; }
1813 format_specs* specs() { return specs_; }
1814 iterator out() { return writer_.out(); }
1815
1816 void write(bool value) {
1817 string_view sv(value ? "true" : "false");
1818 specs_ ? writer_.write(sv, *specs_) : writer_.write(sv);
1819 }
1820
1821 void write(const char_type* value) {
1822 if (!value) {
1823 FMT_THROW(format_error("string pointer is null"));
1824 } else {
1825 auto length = std::char_traits<char_type>::length(value);
1826 basic_string_view<char_type> sv(value, length);
1827 specs_ ? writer_.write(sv, *specs_) : writer_.write(sv);
1828 }
1829 }
1830
1831 public:
1832 arg_formatter_base(Range r, format_specs* s, locale_ref loc)
1833 : writer_(r, loc), specs_(s) {}
1834
1835 iterator operator()(monostate) {
1836 FMT_ASSERT(false, "invalid argument type");
1837 return out();
1838 }
1839
1840 template <typename T, FMT_ENABLE_IF(is_integral<T>::value)>
1841 iterator operator()(T value) {
1842 if (specs_)
1843 writer_.write_int(value, *specs_);
1844 else
1845 writer_.write(value);
1846 return out();
1847 }
1848
1849 iterator operator()(char_type value) {
1850 internal::handle_char_specs(
1851 specs_, char_spec_handler(*this, static_cast<char_type>(value)));
1852 return out();
1853 }
1854
1855 iterator operator()(bool value) {
1856 if (specs_ && specs_->type) return (*this)(value ? 1 : 0);
1857 write(value != 0);
1858 return out();
1859 }
1860
1861 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1862 iterator operator()(T value) {
1863 writer_.write(value, specs_ ? *specs_ : format_specs());
1864 return out();
1865 }
1866
1867 struct char_spec_handler : ErrorHandler {
1868 arg_formatter_base& formatter;
1869 char_type value;
1870
1871 char_spec_handler(arg_formatter_base& f, char_type val)
1872 : formatter(f), value(val) {}
1873
1874 void on_int() {
1875 if (formatter.specs_)
1876 formatter.writer_.write_int(value, *formatter.specs_);
1877 else
1878 formatter.writer_.write(value);
1879 }
1880 void on_char() { formatter.write_char(value); }
1881 };
1882
1883 struct cstring_spec_handler : internal::error_handler {
1884 arg_formatter_base& formatter;
1885 const char_type* value;
1886
1887 cstring_spec_handler(arg_formatter_base& f, const char_type* val)
1888 : formatter(f), value(val) {}
1889
1890 void on_string() { formatter.write(value); }
1891 void on_pointer() { formatter.write_pointer(value); }
1892 };
1893
1894 iterator operator()(const char_type* value) {
1895 if (!specs_) return write(value), out();
1896 internal::handle_cstring_type_spec(specs_->type,
1897 cstring_spec_handler(*this, value));
1898 return out();
1899 }
1900
1901 iterator operator()(basic_string_view<char_type> value) {
1902 if (specs_) {
1903 internal::check_string_type_spec(specs_->type, internal::error_handler());
1904 writer_.write(value, *specs_);
1905 } else {
1906 writer_.write(value);
1907 }
1908 return out();
1909 }
1910
1911 iterator operator()(const void* value) {
1912 if (specs_)
1913 check_pointer_type_spec(specs_->type, internal::error_handler());
1914 write_pointer(value);
1915 return out();
1916 }
1917};
1918
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
1954 basic_format_parse_context<char_type>& parse_ctx_;
1955 Context& ctx_;
1956
1957 public:
1958 explicit custom_formatter(basic_format_parse_context<char_type>& parse_ctx,
1959 Context& ctx)
1960 : parse_ctx_(parse_ctx), ctx_(ctx) {}
1961
1962 bool operator()(typename basic_format_arg<Context>::handle h) const {
1963 h.format(parse_ctx_, ctx_);
1964 return true;
1965 }
1966
1967 template <typename T> bool operator()(T) const { return false; }
1968};
1969
1970template <typename T>
1971using is_integer =
1972 bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value &&
1973 !std::is_same<T, char>::value &&
1974 !std::is_same<T, wchar_t>::value>;
1975
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:
2019 explicit FMT_CONSTEXPR specs_setter(basic_format_specs<Char>& specs)
2020 : specs_(specs) {}
2021
2022 FMT_CONSTEXPR specs_setter(const specs_setter& other)
2023 : specs_(other.specs_) {}
2024
2025 FMT_CONSTEXPR void on_align(align_t align) { specs_.align = align; }
2026 FMT_CONSTEXPR void on_fill(Char fill) { specs_.fill[0] = fill; }
2027 FMT_CONSTEXPR void on_plus() { specs_.sign = sign::plus; }
2028 FMT_CONSTEXPR void on_minus() { specs_.sign = sign::minus; }
2029 FMT_CONSTEXPR void on_space() { specs_.sign = sign::space; }
2030 FMT_CONSTEXPR void on_hash() { specs_.alt = true; }
2031
2032 FMT_CONSTEXPR void on_zero() {
2033 specs_.align = align::numeric;
2034 specs_.fill[0] = Char('0');
2035 }
2036
2037 FMT_CONSTEXPR void on_width(int width) { specs_.width = width; }
2038 FMT_CONSTEXPR void on_precision(int precision) {
2039 specs_.precision = precision;
2040 }
2041 FMT_CONSTEXPR void end_precision() {}
2042
2043 FMT_CONSTEXPR void on_type(Char type) {
2044 specs_.type = static_cast<char>(type);
2045 }
2046
2047 protected:
2048 basic_format_specs<Char>& specs_;
2049};
2050
2051template <typename ErrorHandler> class numeric_specs_checker {
2052 public:
2053 FMT_CONSTEXPR numeric_specs_checker(ErrorHandler& eh, internal::type arg_type)
2054 : error_handler_(eh), arg_type_(arg_type) {}
2055
2056 FMT_CONSTEXPR void require_numeric_argument() {
2057 if (!is_arithmetic_type(arg_type_))
2058 error_handler_.on_error("format specifier requires numeric argument");
2059 }
2060
2061 FMT_CONSTEXPR void check_sign() {
2062 require_numeric_argument();
2063 if (is_integral_type(arg_type_) && arg_type_ != int_type &&
2064 arg_type_ != long_long_type && arg_type_ != internal::char_type) {
2065 error_handler_.on_error("format specifier requires signed argument");
2066 }
2067 }
2068
2069 FMT_CONSTEXPR void check_precision() {
2070 if (is_integral_type(arg_type_) || arg_type_ == internal::pointer_type)
2071 error_handler_.on_error("precision not allowed for this argument type");
2072 }
2073
2074 private:
2075 ErrorHandler& error_handler_;
2076 internal::type arg_type_;
2077};
2078
2079// A format specifier handler that checks if specifiers are consistent with the
2080// argument type.
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
2086 FMT_CONSTEXPR specs_checker(const specs_checker& other)
2087 : Handler(other), checker_(*this, other.arg_type_) {}
2088
2089 FMT_CONSTEXPR void on_align(align_t align) {
2090 if (align == align::numeric) checker_.require_numeric_argument();
2091 Handler::on_align(align);
2092 }
2093
2094 FMT_CONSTEXPR void on_plus() {
2095 checker_.check_sign();
2096 Handler::on_plus();
2097 }
2098
2099 FMT_CONSTEXPR void on_minus() {
2100 checker_.check_sign();
2101 Handler::on_minus();
2102 }
2103
2104 FMT_CONSTEXPR void on_space() {
2105 checker_.check_sign();
2106 Handler::on_space();
2107 }
2108
2109 FMT_CONSTEXPR void on_hash() {
2110 checker_.require_numeric_argument();
2111 Handler::on_hash();
2112 }
2113
2114 FMT_CONSTEXPR void on_zero() {
2115 checker_.require_numeric_argument();
2116 Handler::on_zero();
2117 }
2118
2119 FMT_CONSTEXPR void end_precision() { checker_.check_precision(); }
2120
2121 private:
2122 numeric_specs_checker<Handler> checker_;
2123};
2124
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
2148 FMT_CONSTEXPR specs_handler(basic_format_specs<char_type>& specs,
2149 ParseContext& parse_ctx, Context& ctx)
2150 : specs_setter<char_type>(specs),
2151 parse_context_(parse_ctx),
2152 context_(ctx) {}
2153
2154 template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
2155 this->specs_.width = get_dynamic_spec<width_checker>(
2156 get_arg(arg_id), context_.error_handler());
2157 }
2158
2159 template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
2160 this->specs_.precision = get_dynamic_spec<precision_checker>(
2161 get_arg(arg_id), context_.error_handler());
2162 }
2163
2164 void on_error(const char* message) { context_.on_error(message); }
2165
2166 private:
2167 // This is only needed for compatibility with gcc 4.4.
2168 using format_arg = typename Context::format_arg;
2169
2170 FMT_CONSTEXPR format_arg get_arg(auto_id) {
2171 return internal::get_arg(context_, parse_context_.next_arg_id());
2172 }
2173
2174 FMT_CONSTEXPR format_arg get_arg(int arg_id) {
2175 parse_context_.check_arg_id(arg_id);
2176 return internal::get_arg(context_, arg_id);
2177 }
2178
2179 FMT_CONSTEXPR format_arg get_arg(basic_string_view<char_type> arg_id) {
2180 parse_context_.check_arg_id(arg_id);
2181 return context_.arg(arg_id);
2182 }
2183
2184 ParseContext& parse_context_;
2185 Context& context_;
2186};
2187
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) {}
2195 FMT_CONSTEXPR explicit arg_ref(basic_string_view<Char> name)
2196 : kind(arg_id_kind::name), val(name) {}
2197
2198 FMT_CONSTEXPR arg_ref& operator=(int idx) {
2199 kind = arg_id_kind::index;
2200 val.index = idx;
2201 return *this;
2202 }
2203
2204 arg_id_kind kind;
2205 union value {
2206 FMT_CONSTEXPR value(int id = 0) : index{id} {}
2207 FMT_CONSTEXPR value(basic_string_view<Char> n) : name(n) {}
2208
2209 int index;
2210 basic_string_view<Char> name;
2211 } val;
2212};
2213
2214// Format specifiers with width and precision resolved at formatting rather
2215// than parsing time to allow re-using the same parsed specifiers with
2216// different sets of arguments (precompilation of format strings).
2217template <typename Char>
2218struct dynamic_format_specs : basic_format_specs<Char> {
2219 arg_ref<Char> width_ref;
2220 arg_ref<Char> precision_ref;
2221};
2222
2223// Format spec handler that saves references to arguments representing dynamic
2224// width and precision to be resolved at formatting time.
2225template <typename ParseContext>
2226class dynamic_specs_handler
2227 : public specs_setter<typename ParseContext::char_type> {
2228 public:
2229 using char_type = typename ParseContext::char_type;
2230
2231 FMT_CONSTEXPR dynamic_specs_handler(dynamic_format_specs<char_type>& specs,
2232 ParseContext& ctx)
2233 : specs_setter<char_type>(specs), specs_(specs), context_(ctx) {}
2234
2235 FMT_CONSTEXPR dynamic_specs_handler(const dynamic_specs_handler& other)
2236 : specs_setter<char_type>(other),
2237 specs_(other.specs_),
2238 context_(other.context_) {}
2239
2240 template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
2241 specs_.width_ref = make_arg_ref(arg_id);
2242 }
2243
2244 template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
2245 specs_.precision_ref = make_arg_ref(arg_id);
2246 }
2247
2248 FMT_CONSTEXPR void on_error(const char* message) {
2249 context_.on_error(message);
2250 }
2251
2252 private:
2253 using arg_ref_type = arg_ref<char_type>;
2254
2255 FMT_CONSTEXPR arg_ref_type make_arg_ref(int arg_id) {
2256 context_.check_arg_id(arg_id);
2257 return arg_ref_type(arg_id);
2258 }
2259
2260 FMT_CONSTEXPR arg_ref_type make_arg_ref(auto_id) {
2261 return arg_ref_type(context_.next_arg_id());
2262 }
2263
2264 FMT_CONSTEXPR arg_ref_type make_arg_ref(basic_string_view<char_type> arg_id) {
2265 context_.check_arg_id(arg_id);
2266 basic_string_view<char_type> format_str(
2267 context_.begin(), to_unsigned(context_.end() - context_.begin()));
2268 return arg_ref_type(arg_id);
2269 }
2270
2271 dynamic_format_specs<char_type>& specs_;
2272 ParseContext& context_;
2273};
2274
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); }
2310 FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2311 handler.on_dynamic_width(id);
2312 }
2313
2314 FMT_CONSTEXPR void on_error(const char* message) {
2315 handler.on_error(message);
2316 }
2317
2318 SpecHandler& handler;
2319};
2320
2321// Adapts SpecHandler to IDHandler API for dynamic precision.
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); }
2327 FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2328 handler.on_dynamic_precision(id);
2329 }
2330
2331 FMT_CONSTEXPR void on_error(const char* message) {
2332 handler.on_error(message);
2333 }
2334
2335 SpecHandler& handler;
2336};
2337
2338// Parses fill and alignment.
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 '<':
2349 align = align::left;
2350 break;
2351 case '>':
2352 align = align::right;
2353 break;
2354#if FMT_NUMERIC_ALIGN
2355 case '=':
2356 align = align::numeric;
2357 break;
2358#endif
2359 case '^':
2360 align = align::center;
2361 break;
2362 }
2363 if (align != align::none) {
2364 if (i > 0) {
2365 auto c = *begin;
2366 if (c == '{')
2367 return handler.on_error("invalid fill character '{'"), begin;
2368 begin += 2;
2369 handler.on_fill(c);
2370 } else
2371 ++begin;
2372 handler.on_align(align);
2373 break;
2374 }
2375 } while (i-- > 0);
2376 return begin;
2377}
2378
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); }
2489 FMT_CONSTEXPR void operator()(basic_string_view<Char> id) {
2490 handler.on_arg_id(id);
2491 }
2492 FMT_CONSTEXPR void on_error(const char* message) {
2493 handler.on_error(message);
2494 }
2495 Handler& handler;
2496};
2497
2498template <bool IS_CONSTEXPR, typename Char, typename Handler>
2499FMT_CONSTEXPR void parse_format_string(basic_string_view<Char> format_str,
2500 Handler&& handler) {
2501 struct pfs_writer {
2502 FMT_CONSTEXPR void operator()(const Char* begin, const Char* end) {
2503 if (begin == end) return;
2504 for (;;) {
2505 const Char* p = nullptr;
2506 if (!find<IS_CONSTEXPR>(begin, end, '}', p))
2507 return handler_.on_text(begin, end);
2508 ++p;
2509 if (p == end || *p != '}')
2510 return handler_.on_error("unmatched '}' in format string");
2511 handler_.on_text(begin, p);
2512 begin = p + 1;
2513 }
2514 }
2515 Handler& handler_;
2516 } write{handler};
2517 auto begin = format_str.data();
2518 auto end = begin + format_str.size();
2519 while (begin != end) {
2520 // Doing two passes with memchr (one for '{' and another for '}') is up to
2521 // 2.5x faster than the naive one-pass implementation on big format strings.
2522 const Char* p = begin;
2523 if (*begin != '{' && !find<IS_CONSTEXPR>(begin, end, '{', p))
2524 return write(begin, end);
2525 write(begin, p);
2526 ++p;
2527 if (p == end) return handler.on_error("invalid format string");
2528 if (static_cast<char>(*p) == '}') {
2529 handler.on_arg_id();
2530 handler.on_replacement_field(p);
2531 } else if (*p == '{') {
2532 handler.on_text(p, p + 1);
2533 } else {
2534 p = parse_arg_id(p, end, id_adapter<Handler, Char>{handler});
2535 Char c = p != end ? *p : Char();
2536 if (c == '}') {
2537 handler.on_replacement_field(p);
2538 } else if (c == ':') {
2539 p = handler.on_format_specs(p + 1, end);
2540 if (p == end || *p != '}')
2541 return handler.on_error("unknown format specifier");
2542 } else {
2543 return handler.on_error("missing '}' in format string");
2544 }
2545 }
2546 begin = p + 1;
2547 }
2548}
2549
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 =
2556 conditional_t<internal::mapped_type_constant<T, context>::value !=
2557 internal::custom_type,
2558 decltype(arg_mapper<context>().map(std::declval<T>())), T>;
2559 auto f = conditional_t<has_formatter<mapped_type, context>::value,
2560 formatter<mapped_type, char_type>,
2561 internal::fallback_formatter<T, char_type>>();
2562 return f.parse(ctx);
2563}
2564
2565template <typename Char, typename ErrorHandler, typename... Args>
2566class format_string_checker {
2567 public:
2568 explicit FMT_CONSTEXPR format_string_checker(
2569 basic_string_view<Char> format_str, ErrorHandler eh)
2570 : arg_id_(-1),
2571 context_(format_str, eh),
2572 parse_funcs_{&parse_format_specs<Args, parse_context_type>...} {}
2573
2574 FMT_CONSTEXPR void on_text(const Char*, const Char*) {}
2575
2576 FMT_CONSTEXPR void on_arg_id() {
2577 arg_id_ = context_.next_arg_id();
2578 check_arg_id();
2579 }
2580 FMT_CONSTEXPR void on_arg_id(int id) {
2581 arg_id_ = id;
2582 context_.check_arg_id(id);
2583 check_arg_id();
2584 }
2585 FMT_CONSTEXPR void on_arg_id(basic_string_view<Char>) {
2586 on_error("compile-time checks don't support named arguments");
2587 }
2588
2589 FMT_CONSTEXPR void on_replacement_field(const Char*) {}
2590
2591 FMT_CONSTEXPR const Char* on_format_specs(const Char* begin, const Char*) {
2592 advance_to(context_, begin);
2593 return arg_id_ < num_args ? parse_funcs_[arg_id_](context_) : begin;
2594 }
2595
2596 FMT_CONSTEXPR void on_error(const char* message) {
2597 context_.on_error(message);
2598 }
2599
2600 private:
2601 using parse_context_type = basic_format_parse_context<Char, ErrorHandler>;
2602 enum { num_args = sizeof...(Args) };
2603
2604 FMT_CONSTEXPR void check_arg_id() {
2605 if (arg_id_ >= num_args) context_.on_error("argument index out of range");
2606 }
2607
2608 // Format specifier parsing function.
2609 using parse_func = const Char* (*)(parse_context_type&);
2610
2611 int arg_id_;
2612 parse_context_type context_;
2613 parse_func parse_funcs_[num_args > 0 ? num_args : 1];
2614};
2615
2616template <typename Char, typename ErrorHandler, typename... Args>
2617FMT_CONSTEXPR bool do_check_format_string(basic_string_view<Char> s,
2618 ErrorHandler eh = ErrorHandler()) {
2619 format_string_checker<Char, ErrorHandler, Args...> checker(s, eh);
2620 parse_format_string<true>(s, checker);
2621 return true;
2622}
2623
2624template <typename... Args, typename S,
2625 enable_if_t<(is_compile_string<S>::value), int>>
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>
2635void handle_dynamic_spec(int& value, arg_ref<typename Context::char_type> ref,
2636 Context& ctx) {
2637 switch (ref.kind) {
2638 case arg_id_kind::none:
2639 break;
2640 case arg_id_kind::index:
2641 value = internal::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
2642 ctx.error_handler());
2643 break;
2644 case arg_id_kind::name:
2645 value = internal::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
2646 ctx.error_handler());
2647 break;
2648 }
2649}
2650} // namespace internal
2651
2652template <typename Range>
2653using basic_writer FMT_DEPRECATED_ALIAS = internal::basic_writer<Range>;
2654using writer FMT_DEPRECATED_ALIAS = internal::writer;
2655using wwriter FMT_DEPRECATED_ALIAS =
2656 internal::basic_writer<buffer_range<wchar_t>>;
2657
2658/** The default argument formatter. */
2659template <typename Range>
2660class arg_formatter : public internal::arg_formatter_base<Range> {
2661 private:
2662 using char_type = typename Range::value_type;
2663 using base = internal::arg_formatter_base<Range>;
2664 using context_type = basic_format_context<typename base::iterator, char_type>;
2665
2666 context_type& ctx_;
2667 basic_format_parse_context<char_type>* parse_ctx_;
2668
2669 public:
2670 using range = Range;
2671 using iterator = typename base::iterator;
2672 using format_specs = typename base::format_specs;
2673
2674 /**
2675 \rst
2676 Constructs an argument formatter object.
2677 *ctx* is a reference to the formatting context,
2678 *specs* contains format specifier information for standard argument types.
2679 \endrst
2680 */
2681 explicit arg_formatter(
2682 context_type& ctx,
2683 basic_format_parse_context<char_type>* parse_ctx = nullptr,
2684 format_specs* specs = nullptr)
2685 : base(Range(ctx.out()), specs, ctx.locale()),
2686 ctx_(ctx),
2687 parse_ctx_(parse_ctx) {}
2688
2689 using base::operator();
2690
2691 /** Formats an argument of a user-defined type. */
2692 iterator operator()(typename basic_format_arg<context_type>::handle handle) {
2693 handle.format(*parse_ctx_, ctx_);
2694 return ctx_.out();
2695 }
2696};
2697
2698/**
2699 An error returned by an operating system or a language runtime,
2700 for example a file opening error.
2701*/
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:
2707 int error_code_;
2708
2709 system_error() : std::runtime_error(""), error_code_(0) {}
2710
2711 public:
2712 /**
2713 \rst
2714 Constructs a :class:`fmt::system_error` object with a description
2715 formatted with `fmt::format_system_error`. *message* and additional
2716 arguments passed into the constructor are formatted similarly to
2717 `fmt::format`.
2718
2719 **Example**::
2720
2721 // This throws a system_error with the description
2722 // cannot open file 'madeup': No such file or directory
2723 // or similar (system message may vary).
2724 const char *filename = "madeup";
2725 std::FILE *file = std::fopen(filename, "r");
2726 if (!file)
2727 throw fmt::system_error(errno, "cannot open file '{}'", filename);
2728 \endrst
2729 */
2730 template <typename... Args>
2731 system_error(int error_code, string_view message, const Args&... args)
2732 : std::runtime_error("") {
2733 init(error_code, message, make_format_args(args...));
2734 }
2735 system_error(const system_error&) = default;
2736 system_error& operator=(const system_error&) = default;
2737 system_error(system_error&&) = default;
2738 system_error& operator=(system_error&&) = default;
2739 ~system_error() FMT_NOEXCEPT FMT_OVERRIDE;
2740
2741 int error_code() const { return error_code_; }
2742};
2743
2744/**
2745 \rst
2746 Formats an error returned by an operating system or a language runtime,
2747 for example a file opening error, and writes it to *out* in the following
2748 form:
2749
2750 .. parsed-literal::
2751 *<message>*: *<system-message>*
2752
2753 where *<message>* is the passed message and *<system-message>* is
2754 the system message corresponding to the error code.
2755 *error_code* is a system error code as given by ``errno``.
2756 If *error_code* is not a valid error code such as -1, the system message
2757 may look like "Unknown error -1" and is platform-dependent.
2758 \endrst
2759 */
2760FMT_API void format_system_error(internal::buffer<char>& out, int error_code,
2761 string_view message) FMT_NOEXCEPT;
2762
2763// Reports a system error without throwing an exception.
2764// Can be used to report errors from destructors.
2765FMT_API void report_system_error(int error_code,
2766 string_view message) FMT_NOEXCEPT;
2767
2768#if FMT_USE_WINDOWS_H
2769
2770/** A Windows error. */
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. */
2818class format_int {
2819 private:
2820 // Buffer should be large enough to hold all digits (digits10 + 1),
2821 // a sign and a null character.
2822 enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 };
2823 mutable char buffer_[buffer_size];
2824 char* str_;
2825
2826 // Formats value in reverse and returns a pointer to the beginning.
2827 char* format_decimal(unsigned long long value) {
2828 char* ptr = buffer_ + (buffer_size - 1); // Parens to workaround MSVC bug.
2829 while (value >= 100) {
2830 // Integer division is slow so do it for a group of two digits instead
2831 // of for every digit. The idea comes from the talk by Alexandrescu
2832 // "Three Optimization Tips for C++". See speed-test for a comparison.
2833 auto index = static_cast<unsigned>((value % 100) * 2);
2834 value /= 100;
2835 *--ptr = internal::data::digits[index + 1];
2836 *--ptr = internal::data::digits[index];
2837 }
2838 if (value < 10) {
2839 *--ptr = static_cast<char>('0' + value);
2840 return ptr;
2841 }
2842 auto index = static_cast<unsigned>(value * 2);
2843 *--ptr = internal::data::digits[index + 1];
2844 *--ptr = internal::data::digits[index];
2845 return ptr;
2846 }
2847
2848 void format_signed(long long value) {
2849 auto abs_value = static_cast<unsigned long long>(value);
2850 bool negative = value < 0;
2851 if (negative) abs_value = 0 - abs_value;
2852 str_ = format_decimal(abs_value);
2853 if (negative) *--str_ = '-';
2854 }
2855
2856 public:
2857 explicit format_int(int value) { format_signed(value); }
2858 explicit format_int(long value) { format_signed(value); }
2859 explicit format_int(long long value) { format_signed(value); }
2860 explicit format_int(unsigned value) : str_(format_decimal(value)) {}
2861 explicit format_int(unsigned long value) : str_(format_decimal(value)) {}
2862 explicit format_int(unsigned long long value) : str_(format_decimal(value)) {}
2863
2864 /** Returns the number of characters written to the output buffer. */
2865 std::size_t size() const {
2866 return internal::to_unsigned(buffer_ - str_ + buffer_size - 1);
2867 }
2868
2869 /**
2870 Returns a pointer to the output buffer content. No terminating null
2871 character is appended.
2872 */
2873 const char* data() const { return str_; }
2874
2875 /**
2876 Returns a pointer to the output buffer content with terminating null
2877 character appended.
2878 */
2879 const char* c_str() const {
2880 buffer_[buffer_size - 1] = '\0';
2881 return str_;
2882 }
2883
2884 /**
2885 \rst
2886 Returns the content of the output buffer as an ``std::string``.
2887 \endrst
2888 */
2889 std::string str() const { return std::string(str_, size()); }
2890};
2891
2892// A formatter specialization for the core types corresponding to internal::type
2893// constants.
2894template <typename T, typename Char>
2895struct formatter<T, Char,
2896 enable_if_t<internal::type_constant<T, Char>::value !=
2897 internal::custom_type>> {
2898 FMT_CONSTEXPR formatter() = default;
2899
2900 // Parses format specifiers stopping either at the end of the range or at the
2901 // terminating '}'.
2902 template <typename ParseContext>
2903 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2904 using handler_type = internal::dynamic_specs_handler<ParseContext>;
2905 auto type = internal::type_constant<T, Char>::value;
2906 internal::specs_checker<handler_type> handler(handler_type(specs_, ctx),
2907 type);
2908 auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
2909 auto eh = ctx.error_handler();
2910 switch (type) {
2911 case internal::none_type:
2912 case internal::named_arg_type:
2913 FMT_ASSERT(false, "invalid argument type");
2914 break;
2915 case internal::int_type:
2916 case internal::uint_type:
2917 case internal::long_long_type:
2918 case internal::ulong_long_type:
2919 case internal::int128_type:
2920 case internal::uint128_type:
2921 case internal::bool_type:
2922 handle_int_type_spec(specs_.type,
2923 internal::int_type_checker<decltype(eh)>(eh));
2924 break;
2925 case internal::char_type:
2926 handle_char_specs(
2927 &specs_, internal::char_specs_checker<decltype(eh)>(specs_.type, eh));
2928 break;
2929 case internal::float_type:
2930 case internal::double_type:
2931 case internal::long_double_type:
2932 internal::parse_float_type_spec(specs_, eh);
2933 break;
2934 case internal::cstring_type:
2935 internal::handle_cstring_type_spec(
2936 specs_.type, internal::cstring_type_checker<decltype(eh)>(eh));
2937 break;
2938 case internal::string_type:
2939 internal::check_string_type_spec(specs_.type, eh);
2940 break;
2941 case internal::pointer_type:
2942 internal::check_pointer_type_spec(specs_.type, eh);
2943 break;
2944 case internal::custom_type:
2945 // Custom format specifiers should be checked in parse functions of
2946 // formatter specializations.
2947 break;
2948 }
2949 return it;
2950 }
2951
2952 template <typename FormatContext>
2953 auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
2954 internal::handle_dynamic_spec<internal::width_checker>(
2955 specs_.width, specs_.width_ref, ctx);
2956 internal::handle_dynamic_spec<internal::precision_checker>(
2957 specs_.precision, specs_.precision_ref, ctx);
2958 using range_type =
2959 internal::output_range<typename FormatContext::iterator,
2960 typename FormatContext::char_type>;
2961 return visit_format_arg(arg_formatter<range_type>(ctx, nullptr, &specs_),
2962 internal::make_arg<FormatContext>(val));
2963 }
2964
2965 private:
2966 internal::dynamic_format_specs<Char> specs_;
2967};
2968
2969#define FMT_FORMAT_AS(Type, Base) \
2970 template <typename Char> \
2971 struct formatter<Type, Char> : formatter<Base, Char> { \
2972 template <typename FormatContext> \
2973 auto format(const Type& val, FormatContext& ctx) -> decltype(ctx.out()) { \
2974 return formatter<Base, Char>::format(val, ctx); \
2975 } \
2976 }
2977
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*);
2987FMT_FORMAT_AS(internal::std_string_view<Char>, basic_string_view<Char>);
2988
2989template <typename Char>
2990struct formatter<void*, Char> : formatter<const void*, Char> {
2991 template <typename FormatContext>
2992 auto format(void* val, FormatContext& ctx) -> decltype(ctx.out()) {
2993 return formatter<const void*, Char>::format(val, ctx);
2994 }
2995};
2996
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:
3017 struct null_handler : internal::error_handler {
3018 void on_align(align_t) {}
3019 void on_plus() {}
3020 void on_minus() {}
3021 void on_space() {}
3022 void on_hash() {}
3023 };
3024
3025 public:
3026 template <typename ParseContext>
3027 auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
3028 format_str_ = ctx.begin();
3029 // Checks are deferred to formatting time when the argument type is known.
3030 internal::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
3031 return parse_format_specs(ctx.begin(), ctx.end(), handler);
3032 }
3033
3034 template <typename T, typename FormatContext>
3035 auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
3036 handle_specs(ctx);
3037 internal::specs_checker<null_handler> checker(
3038 null_handler(),
3039 internal::mapped_type_constant<T, FormatContext>::value);
3040 checker.on_align(specs_.align);
3041 switch (specs_.sign) {
3042 case sign::none:
3043 break;
3044 case sign::plus:
3045 checker.on_plus();
3046 break;
3047 case sign::minus:
3048 checker.on_minus();
3049 break;
3050 case sign::space:
3051 checker.on_space();
3052 break;
3053 }
3054 if (specs_.alt) checker.on_hash();
3055 if (specs_.precision >= 0) checker.end_precision();
3056 using range = internal::output_range<typename FormatContext::iterator,
3057 typename FormatContext::char_type>;
3058 visit_format_arg(arg_formatter<range>(ctx, nullptr, &specs_),
3059 internal::make_arg<FormatContext>(val));
3060 return ctx.out();
3061 }
3062
3063 private:
3064 template <typename Context> void handle_specs(Context& ctx) {
3065 internal::handle_dynamic_spec<internal::width_checker>(
3066 specs_.width, specs_.width_ref, ctx);
3067 internal::handle_dynamic_spec<internal::precision_checker>(
3068 specs_.precision, specs_.precision_ref, ctx);
3069 }
3070
3071 internal::dynamic_format_specs<Char> specs_;
3072 const Char* format_str_;
3073};
3074
3075template <typename Range, typename Char>
3076typename basic_format_context<Range, Char>::format_arg
3077basic_format_context<Range, Char>::arg(basic_string_view<char_type> name) {
3078 map_.init(args_);
3079 format_arg arg = map_.find(name);
3080 if (arg.type() == internal::none_type) this->on_error("argument not found");
3081 return arg;
3082}
3083
3084template <typename Char, typename ErrorHandler>
3085FMT_CONSTEXPR void advance_to(
3086 basic_format_parse_context<Char, ErrorHandler>& ctx, const Char* p) {
3087 ctx.advance_to(ctx.begin() + (p - &*ctx.begin()));
3088}
3089
3090template <typename ArgFormatter, typename Char, typename Context>
3091struct format_handler : internal::error_handler {
3092 using range = typename ArgFormatter::range;
3093
3094 format_handler(range r, basic_string_view<Char> str,
3095 basic_format_args<Context> format_args,
3096 internal::locale_ref loc)
3097 : parse_context(str), context(r.begin(), format_args, loc) {}
3098
3099 void on_text(const Char* begin, const Char* end) {
3100 auto size = internal::to_unsigned(end - begin);
3101 auto out = context.out();
3102 auto&& it = internal::reserve(out, size);
3103 it = std::copy_n(begin, size, it);
3104 context.advance_to(out);
3105 }
3106
3107 void get_arg(int id) { arg = internal::get_arg(context, id); }
3108
3109 void on_arg_id() { get_arg(parse_context.next_arg_id()); }
3110 void on_arg_id(int id) {
3111 parse_context.check_arg_id(id);
3112 get_arg(id);
3113 }
3114 void on_arg_id(basic_string_view<Char> id) { arg = context.arg(id); }
3115
3116 void on_replacement_field(const Char* p) {
3117 advance_to(parse_context, p);
3118 context.advance_to(
3119 visit_format_arg(ArgFormatter(context, &parse_context), arg));
3120 }
3121
3122 const Char* on_format_specs(const Char* begin, const Char* end) {
3123 advance_to(parse_context, begin);
3124 internal::custom_formatter<Context> f(parse_context, context);
3125 if (visit_format_arg(f, arg)) return parse_context.begin();
3126 basic_format_specs<Char> specs;
3127 using internal::specs_handler;
3128 using parse_context_t = basic_format_parse_context<Char>;
3129 internal::specs_checker<specs_handler<parse_context_t, Context>> handler(
3130 specs_handler<parse_context_t, Context>(specs, parse_context, context),
3131 arg.type());
3132 begin = parse_format_specs(begin, end, handler);
3133 if (begin == end || *begin != '}') on_error("missing '}' in format string");
3134 advance_to(parse_context, begin);
3135 context.advance_to(
3136 visit_format_arg(ArgFormatter(context, &parse_context, &specs), arg));
3137 return begin;
3138 }
3139
3140 basic_format_parse_context<Char> parse_context;
3141 Context context;
3142 basic_format_arg<Context> arg;
3143};
3144
3145/** Formats arguments and writes the output to the range. */
3146template <typename ArgFormatter, typename Char, typename Context>
3147typename Context::iterator vformat_to(
3148 typename ArgFormatter::range out, basic_string_view<Char> format_str,
3149 basic_format_args<Context> args,
3150 internal::locale_ref loc = internal::locale_ref()) {
3151 format_handler<ArgFormatter, Char, Context> h(out, format_str, args, loc);
3152 internal::parse_format_string<false>(format_str, h);
3153 return h.context.out();
3154}
3155
3156// Casts ``p`` to ``const void*`` for pointer formatting.
3157// Example:
3158// auto s = format("{}", ptr(p));
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 {
3168 It begin;
3169 It end;
3170 basic_string_view<Char> sep;
3171
3172 arg_join(It b, It e, basic_string_view<Char> s) : begin(b), end(e), sep(s) {}
3173};
3174
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()) {
3181 using base = formatter<typename std::iterator_traits<It>::value_type, Char>;
3182 auto it = value.begin;
3183 auto out = ctx.out();
3184 if (it != value.end) {
3185 out = base::format(*it++, ctx);
3186 while (it != value.end) {
3187 out = std::copy(value.sep.begin(), value.sep.end(), out);
3188 ctx.advance_to(out);
3189 out = base::format(*it++, ctx);
3190 }
3191 }
3192 return out;
3193 }
3194};
3195
3196/**
3197 Returns an object that formats the iterator range `[begin, end)` with elements
3198 separated by `sep`.
3199 */
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>
3206arg_join<It, wchar_t> join(It begin, It end, wstring_view sep) {
3207 return {begin, end, sep};
3208}
3209
3210/**
3211 \rst
3212 Returns an object that formats `range` with elements separated by `sep`.
3213
3214 **Example**::
3215
3216 std::vector<int> v = {1, 2, 3};
3217 fmt::print("{}", fmt::join(v, ", "));
3218 // Output: "1, 2, 3"
3219 \endrst
3220 */
3221template <typename Range>
3222arg_join<internal::iterator_t<const Range>, char> join(const Range& range,
3223 string_view sep) {
3224 return join(std::begin(range), std::end(range), sep);
3225}
3226
3227template <typename Range>
3228arg_join<internal::iterator_t<const Range>, wchar_t> join(const Range& range,
3229 wstring_view sep) {
3230 return join(std::begin(range), std::end(range), sep);
3231}
3232
3233/**
3234 \rst
3235 Converts *value* to ``std::string`` using the default format for type *T*.
3236 It doesn't support user-defined types with custom formatters.
3237
3238 **Example**::
3239
3240 #include <fmt/format.h>
3241
3242 std::string answer = fmt::to_string(42);
3243 \endrst
3244 */
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>
3262typename buffer_context<Char>::iterator internal::vformat_to(
3263 internal::buffer<Char>& buf, basic_string_view<Char> format_str,
3264 basic_format_args<buffer_context<Char>> args) {
3265 using range = buffer_range<Char>;
3266 return vformat_to<arg_formatter<range>>(buf, to_string_view(format_str),
3267 args);
3268}
3269
3270template <typename S, typename Char = char_t<S>,
3271 FMT_ENABLE_IF(internal::is_string<S>::value)>
3272inline typename buffer_context<Char>::iterator vformat_to(
3273 internal::buffer<Char>& buf, const S& format_str,
3274 basic_format_args<buffer_context<Char>> args) {
3275 return internal::vformat_to(buf, to_string_view(format_str), args);
3276}
3277
3278template <typename S, typename... Args, std::size_t SIZE = inline_buffer_size,
3279 typename Char = enable_if_t<internal::is_string<S>::value, char_t<S>>>
3280inline typename buffer_context<Char>::iterator format_to(
3281 basic_memory_buffer<Char, SIZE>& buf, const S& format_str, Args&&... args) {
3282 internal::check_format_string<Args...>(format_str);
3283 using context = buffer_context<Char>;
3284 return internal::vformat_to(buf, to_string_view(format_str),
3285 {make_format_args<context>(args...)});
3286}
3287
3288template <typename OutputIt, typename Char = char>
3289using format_context_t = basic_format_context<OutputIt, Char>;
3290
3291template <typename OutputIt, typename Char = char>
3292using format_args_t = basic_format_args<format_context_t<OutputIt, Char>>;
3293
3294template <typename S, typename OutputIt, typename... Args,
3295 FMT_ENABLE_IF(
3296 internal::is_output_iterator<OutputIt>::value &&
3297 !internal::is_contiguous_back_insert_iterator<OutputIt>::value)>
3298inline OutputIt vformat_to(OutputIt out, const S& format_str,
3299 format_args_t<OutputIt, char_t<S>> args) {
3300 using range = internal::output_range<OutputIt, char_t<S>>;
3301 return vformat_to<arg_formatter<range>>(range(out),
3302 to_string_view(format_str), args);
3303}
3304
3305/**
3306 \rst
3307 Formats arguments, writes the result to the output iterator ``out`` and returns
3308 the iterator past the end of the output range.
3309
3310 **Example**::
3311
3312 std::vector<char> out;
3313 fmt::format_to(std::back_inserter(out), "{}", 42);
3314 \endrst
3315 */
3316template <typename OutputIt, typename S, typename... Args,
3317 FMT_ENABLE_IF(
3318 internal::is_output_iterator<OutputIt>::value &&
3319 !internal::is_contiguous_back_insert_iterator<OutputIt>::value &&
3320 internal::is_string<S>::value)>
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>
3336using format_to_n_context =
3337 format_context_t<internal::truncating_iterator<OutputIt>, Char>;
3338
3339template <typename OutputIt, typename Char = typename OutputIt::value_type>
3340using format_to_n_args = basic_format_args<format_to_n_context<OutputIt, Char>>;
3341
3342template <typename OutputIt, typename Char, typename... Args>
3343inline format_arg_store<format_to_n_context<OutputIt, Char>, Args...>
3344make_format_to_n_args(const Args&... args) {
3345 return format_arg_store<format_to_n_context<OutputIt, Char>, Args...>(
3346 args...);
3347}
3348
3349template <typename OutputIt, typename Char, typename... Args,
3350 FMT_ENABLE_IF(internal::is_output_iterator<OutputIt>::value)>
3351inline format_to_n_result<OutputIt> vformat_to_n(
3352 OutputIt out, std::size_t n, basic_string_view<Char> format_str,
3353 format_to_n_args<OutputIt, Char> args) {
3354 auto it = vformat_to(internal::truncating_iterator<OutputIt>(out, n),
3355 format_str, args);
3356 return {it.base(), it.count()};
3357}
3358
3359/**
3360 \rst
3361 Formats arguments, writes up to ``n`` characters of the result to the output
3362 iterator ``out`` and returns the total output size and the iterator past the
3363 end of the output range.
3364 \endrst
3365 */
3366template <typename OutputIt, typename S, typename... Args,
3367 FMT_ENABLE_IF(internal::is_string<S>::value&&
3368 internal::is_output_iterator<OutputIt>::value)>
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);
3373 using context = format_to_n_context<OutputIt, char_t<S>>;
3374 return vformat_to_n(out, n, to_string_view(format_str),
3375 {make_format_args<context>(args...)});
3376}
3377
3378template <typename Char>
3379inline std::basic_string<Char> internal::vformat(
3380 basic_string_view<Char> format_str,
3381 basic_format_args<buffer_context<Char>> args) {
3382 basic_memory_buffer<Char> buffer;
3383 internal::vformat_to(buffer, format_str, args);
3384 return to_string(buffer);
3385}
3386
3387/**
3388 Returns the number of characters in the output of
3389 ``format(format_str, args...)``.
3390 */
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)>
3407void vprint(basic_string_view<Char> format_str, wformat_args args) {
3408 vprint(stdout, format_str, args);
3409}
3410
3411#if FMT_USE_USER_DEFINED_LITERALS
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 {
3429 basic_string_view<Char> str;
3430
3431 template <typename... Args>
3432 std::basic_string<Char> operator()(Args&&... args) const {
3433 return format(str, std::forward<Args>(args)...);
3434 }
3435};
3436# endif // FMT_USE_UDL_TEMPLATE
3437
3438template <typename Char> struct udl_arg {
3439 basic_string_view<Char> str;
3440
3441 template <typename T> named_arg<T, Char> operator=(T&& value) const {
3442 return {str, std::forward<T>(value)};
3443 }
3444};
3445
3446} // namespace internal
3447
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
3500FMT_END_NAMESPACE
3501
3502#define FMT_STRING_IMPL(s, ...) \
3503 [] { \
3504 struct str : fmt::compile_string { \
3505 using char_type = typename std::remove_cv<std::remove_pointer< \
3506 typename std::decay<decltype(s)>::type>::type>::type; \
3507 __VA_ARGS__ FMT_CONSTEXPR \
3508 operator fmt::basic_string_view<char_type>() const { \
3509 return {s, sizeof(s) / sizeof(char_type) - 1}; \
3510 } \
3511 } result; \
3512 /* Suppress Qt Creator warning about unused operator. */ \
3513 (void)static_cast<fmt::basic_string_view<typename str::char_type>>( \
3514 result); \
3515 return result; \
3516 }()
3517
3518/**
3519 \rst
3520 Constructs a compile-time format string.
3521
3522 **Example**::
3523
3524 // A compile-time error because 'd' is an invalid specifier for strings.
3525 std::string s = format(FMT_STRING("{:d}"), "foo");
3526 \endrst
3527 */
3528#define FMT_STRING(s) FMT_STRING_IMPL(s, )
3529
3530#if defined(FMT_STRING_ALIAS) && FMT_STRING_ALIAS
3531# define fmt(s) FMT_STRING_IMPL(s, [[deprecated]])
3532#endif
3533
3534#ifdef FMT_HEADER_ONLY
3535# define FMT_FUNC inline
3536# include "format-inl.h"
3537#else
3538# define FMT_FUNC
3539#endif
3540
3541#endif // FMT_FORMAT_H_
3542