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