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