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