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