2 Formatting library for C++
4 Copyright (c) 2012 - present, Victor Zverovich
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:
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
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.
25 --- Optional exception to the license ---
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.
46 #ifdef __INTEL_COMPILER
47 # define FMT_ICC_VERSION __INTEL_COMPILER
49 # define FMT_ICC_VERSION __ICL
51 # define FMT_ICC_VERSION 0
55 # define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
57 # define FMT_CUDA_VERSION 0
61 # define FMT_HAS_BUILTIN(x) __has_builtin(x)
63 # define FMT_HAS_BUILTIN(x) 0
66 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
67 # define FMT_NOINLINE __attribute__((noinline))
72 #if __cplusplus == 201103L || __cplusplus == 201402L
73 # if defined(__clang__)
74 # define FMT_FALLTHROUGH [[clang::fallthrough]]
75 # elif FMT_GCC_VERSION >= 700 && !defined(__PGI)
76 # define FMT_FALLTHROUGH [[gnu::fallthrough]]
78 # define FMT_FALLTHROUGH
80 #elif FMT_HAS_CPP17_ATTRIBUTE(fallthrough) || \
81 (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L)
82 # define FMT_FALLTHROUGH [[fallthrough]]
84 # define FMT_FALLTHROUGH
87 #ifndef FMT_MAYBE_UNUSED
88 # if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused)
89 # define FMT_MAYBE_UNUSED [[maybe_unused]]
91 # define FMT_MAYBE_UNUSED
97 # if FMT_MSC_VER || FMT_NVCC
100 template <typename Exception
> inline void do_throw(const Exception
& x
) {
101 // Silence unreachable code warnings in MSVC and NVCC because these
102 // are nearly impossible to fix in a generic code.
103 volatile bool b
= true;
106 } // namespace detail
108 # define FMT_THROW(x) detail::do_throw(x)
110 # define FMT_THROW(x) throw x
113 # define FMT_THROW(x) \
115 static_cast<void>(sizeof(x)); \
116 FMT_ASSERT(false, ""); \
123 # define FMT_CATCH(x) catch (x)
125 # define FMT_TRY if (true)
126 # define FMT_CATCH(x) if (false)
129 #ifndef FMT_USE_USER_DEFINED_LITERALS
130 // For Intel and NVIDIA compilers both they and the system gcc/msc support UDLs.
131 # if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
132 FMT_MSC_VER >= 1900) && \
133 (!(FMT_ICC_VERSION || FMT_CUDA_VERSION) || FMT_ICC_VERSION >= 1500 || \
134 FMT_CUDA_VERSION >= 700)
135 # define FMT_USE_USER_DEFINED_LITERALS 1
137 # define FMT_USE_USER_DEFINED_LITERALS 0
141 #ifndef FMT_USE_UDL_TEMPLATE
142 // EDG front end based compilers (icc, nvcc) and GCC < 6.4 do not propertly
143 // support UDL templates and GCC >= 9 warns about them.
144 # if FMT_USE_USER_DEFINED_LITERALS && FMT_ICC_VERSION == 0 && \
145 FMT_CUDA_VERSION == 0 && \
146 ((FMT_GCC_VERSION >= 604 && __cplusplus >= 201402L) || \
147 FMT_CLANG_VERSION >= 304)
148 # define FMT_USE_UDL_TEMPLATE 1
150 # define FMT_USE_UDL_TEMPLATE 0
154 #ifndef FMT_USE_FLOAT
155 # define FMT_USE_FLOAT 1
158 #ifndef FMT_USE_DOUBLE
159 # define FMT_USE_DOUBLE 1
162 #ifndef FMT_USE_LONG_DOUBLE
163 # define FMT_USE_LONG_DOUBLE 1
166 // __builtin_clz is broken in clang with Microsoft CodeGen:
167 // https://github.com/fmtlib/fmt/issues/519
168 #if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clz)) && !FMT_MSC_VER
169 # define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
171 #if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clzll)) && !FMT_MSC_VER
172 # define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
175 // Some compilers masquerade as both MSVC and GCC-likes or otherwise support
176 // __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
177 // MSVC intrinsics if the clz and clzll builtins are not available.
178 #if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(_MANAGED)
179 # include <intrin.h> // _BitScanReverse, _BitScanReverse64
183 // Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
185 # pragma intrinsic(_BitScanReverse)
187 inline uint32_t clz(uint32_t x
) {
189 _BitScanReverse(&r
, x
);
191 FMT_ASSERT(x
!= 0, "");
192 // Static analysis complains about using uninitialized data
193 // "r", but the only way that can happen is if "x" is 0,
194 // which the callers guarantee to not happen.
195 FMT_SUPPRESS_MSC_WARNING(6102)
198 # define FMT_BUILTIN_CLZ(n) detail::clz(n)
200 # if defined(_WIN64) && !defined(__clang__)
201 # pragma intrinsic(_BitScanReverse64)
204 inline uint32_t clzll(uint64_t x
) {
207 _BitScanReverse64(&r
, x
);
209 // Scan the high 32 bits.
210 if (_BitScanReverse(&r
, static_cast<uint32_t>(x
>> 32))) return 63 - (r
+ 32);
212 // Scan the low 32 bits.
213 _BitScanReverse(&r
, static_cast<uint32_t>(x
));
216 FMT_ASSERT(x
!= 0, "");
217 // Static analysis complains about using uninitialized data
218 // "r", but the only way that can happen is if "x" is 0,
219 // which the callers guarantee to not happen.
220 FMT_SUPPRESS_MSC_WARNING(6102)
223 # define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
224 } // namespace detail
228 // Enable the deprecated numeric alignment.
229 #ifndef FMT_NUMERIC_ALIGN
230 # define FMT_NUMERIC_ALIGN 1
236 // An equivalent of `*reinterpret_cast<Dest*>(&source)` that doesn't have
237 // undefined behavior (e.g. due to type aliasing).
238 // Example: uint64_t d = bit_cast<uint64_t>(2.718);
239 template <typename Dest
, typename Source
>
240 inline Dest
bit_cast(const Source
& source
) {
241 static_assert(sizeof(Dest
) == sizeof(Source
), "size mismatch");
243 std::memcpy(&dest
, &source
, sizeof(dest
));
247 inline bool is_big_endian() {
250 char data
[sizeof(u
)];
252 return bit_cast
<bytes
>(u
).data
[0] == 0;
255 // A fallback implementation of uintptr_t for systems that lack it.
256 struct fallback_uintptr
{
257 unsigned char value
[sizeof(void*)];
259 fallback_uintptr() = default;
260 explicit fallback_uintptr(const void* p
) {
261 *this = bit_cast
<fallback_uintptr
>(p
);
262 if (is_big_endian()) {
263 for (size_t i
= 0, j
= sizeof(void*) - 1; i
< j
; ++i
, --j
)
264 std::swap(value
[i
], value
[j
]);
269 using uintptr_t = ::uintptr_t;
270 inline uintptr_t to_uintptr(const void* p
) { return bit_cast
<uintptr_t>(p
); }
272 using uintptr_t = fallback_uintptr
;
273 inline fallback_uintptr
to_uintptr(const void* p
) {
274 return fallback_uintptr(p
);
278 // Returns the largest possible value for type T. Same as
279 // std::numeric_limits<T>::max() but shorter and not affected by the max macro.
280 template <typename T
> constexpr T
max_value() {
281 return (std::numeric_limits
<T
>::max
)();
283 template <typename T
> constexpr int num_bits() {
284 return std::numeric_limits
<T
>::digits
;
286 template <> constexpr int num_bits
<fallback_uintptr
>() {
287 return static_cast<int>(sizeof(void*) *
288 std::numeric_limits
<unsigned char>::digits
);
291 FMT_INLINE
void assume(bool condition
) {
293 #if FMT_HAS_BUILTIN(__builtin_assume)
294 __builtin_assume(condition
);
298 // A workaround for gcc 4.8 to make void_t work in a SFINAE context.
299 template <typename
... Ts
> struct void_t_impl
{ using type
= void; };
301 template <typename
... Ts
>
302 using void_t
= typename
detail::void_t_impl
<Ts
...>::type
;
304 // An approximation of iterator_t for pre-C++20 systems.
305 template <typename T
>
306 using iterator_t
= decltype(std::begin(std::declval
<T
&>()));
307 template <typename T
> using sentinel_t
= decltype(std::end(std::declval
<T
&>()));
309 // Detect the iterator category of *any* given type in a SFINAE-friendly way.
310 // Unfortunately, older implementations of std::iterator_traits are not safe
311 // for use in a SFINAE-context.
312 template <typename It
, typename Enable
= void>
313 struct iterator_category
: std::false_type
{};
315 template <typename T
> struct iterator_category
<T
*> {
316 using type
= std::random_access_iterator_tag
;
319 template <typename It
>
320 struct iterator_category
<It
, void_t
<typename
It::iterator_category
>> {
321 using type
= typename
It::iterator_category
;
324 // Detect if *any* given type models the OutputIterator concept.
325 template <typename It
> class is_output_iterator
{
326 // Check for mutability because all iterator categories derived from
327 // std::input_iterator_tag *may* also meet the requirements of an
328 // OutputIterator, thereby falling into the category of 'mutable iterators'
329 // [iterator.requirements.general] clause 4. The compiler reveals this
330 // property only at the point of *actually dereferencing* the iterator!
331 template <typename U
>
332 static decltype(*(std::declval
<U
>())) test(std::input_iterator_tag
);
333 template <typename U
> static char& test(std::output_iterator_tag
);
334 template <typename U
> static const char& test(...);
336 using type
= decltype(test
<It
>(typename iterator_category
<It
>::type
{}));
339 enum { value
= !std::is_const
<remove_reference_t
<type
>>::value
};
342 // A workaround for std::string not having mutable data() until C++17.
343 template <typename Char
> inline Char
* get_data(std::basic_string
<Char
>& s
) {
346 template <typename Container
>
347 inline typename
Container::value_type
* get_data(Container
& c
) {
351 #if defined(_SECURE_SCL) && _SECURE_SCL
352 // Make a checked iterator to avoid MSVC warnings.
353 template <typename T
> using checked_ptr
= stdext::checked_array_iterator
<T
*>;
354 template <typename T
> checked_ptr
<T
> make_checked(T
* p
, size_t size
) {
358 template <typename T
> using checked_ptr
= T
*;
359 template <typename T
> inline T
* make_checked(T
* p
, size_t) { return p
; }
362 template <typename Container
, FMT_ENABLE_IF(is_contiguous
<Container
>::value
)>
363 #if FMT_CLANG_VERSION
364 __attribute__((no_sanitize("undefined")))
366 inline checked_ptr
<typename
Container::value_type
>
367 reserve(std::back_insert_iterator
<Container
> it
, size_t n
) {
368 Container
& c
= get_container(it
);
369 size_t size
= c
.size();
371 return make_checked(get_data(c
) + size
, n
);
374 template <typename Iterator
> inline Iterator
& reserve(Iterator
& it
, size_t) {
378 template <typename Container
, FMT_ENABLE_IF(is_contiguous
<Container
>::value
)>
379 inline std::back_insert_iterator
<Container
> base_iterator(
380 std::back_insert_iterator
<Container
>& it
,
381 checked_ptr
<typename
Container::value_type
>) {
385 template <typename Iterator
>
386 inline Iterator
base_iterator(Iterator
, Iterator it
) {
390 // An output iterator that counts the number of objects written to it and
392 class counting_iterator
{
397 using iterator_category
= std::output_iterator_tag
;
398 using difference_type
= std::ptrdiff_t;
399 using pointer
= void;
400 using reference
= void;
401 using _Unchecked_type
= counting_iterator
; // Mark iterator as checked.
404 template <typename T
> void operator=(const T
&) {}
407 counting_iterator() : count_(0) {}
409 size_t count() const { return count_
; }
411 counting_iterator
& operator++() {
416 counting_iterator
operator++(int) {
422 value_type
operator*() const { return {}; }
425 template <typename OutputIt
> class truncating_iterator_base
{
431 truncating_iterator_base(OutputIt out
, size_t limit
)
432 : out_(out
), limit_(limit
), count_(0) {}
435 using iterator_category
= std::output_iterator_tag
;
436 using value_type
= typename
std::iterator_traits
<OutputIt
>::value_type
;
437 using difference_type
= void;
438 using pointer
= void;
439 using reference
= void;
440 using _Unchecked_type
=
441 truncating_iterator_base
; // Mark iterator as checked.
443 OutputIt
base() const { return out_
; }
444 size_t count() const { return count_
; }
447 // An output iterator that truncates the output and counts the number of objects
449 template <typename OutputIt
,
450 typename Enable
= typename
std::is_void
<
451 typename
std::iterator_traits
<OutputIt
>::value_type
>::type
>
452 class truncating_iterator
;
454 template <typename OutputIt
>
455 class truncating_iterator
<OutputIt
, std::false_type
>
456 : public truncating_iterator_base
<OutputIt
> {
457 mutable typename truncating_iterator_base
<OutputIt
>::value_type blackhole_
;
460 using value_type
= typename truncating_iterator_base
<OutputIt
>::value_type
;
462 truncating_iterator(OutputIt out
, size_t limit
)
463 : truncating_iterator_base
<OutputIt
>(out
, limit
) {}
465 truncating_iterator
& operator++() {
466 if (this->count_
++ < this->limit_
) ++this->out_
;
470 truncating_iterator
operator++(int) {
476 value_type
& operator*() const {
477 return this->count_
< this->limit_
? *this->out_
: blackhole_
;
481 template <typename OutputIt
>
482 class truncating_iterator
<OutputIt
, std::true_type
>
483 : public truncating_iterator_base
<OutputIt
> {
485 truncating_iterator(OutputIt out
, size_t limit
)
486 : truncating_iterator_base
<OutputIt
>(out
, limit
) {}
488 template <typename T
> truncating_iterator
& operator=(T val
) {
489 if (this->count_
++ < this->limit_
) *this->out_
++ = val
;
493 truncating_iterator
& operator++() { return *this; }
494 truncating_iterator
& operator++(int) { return *this; }
495 truncating_iterator
& operator*() { return *this; }
498 // A range with the specified output iterator and value type.
499 template <typename OutputIt
, typename T
= typename
OutputIt::value_type
>
505 using value_type
= T
;
506 using iterator
= OutputIt
;
509 explicit output_range(OutputIt it
) : it_(it
) {}
510 OutputIt
begin() const { return it_
; }
511 sentinel
end() const { return {}; } // Sentinel is not used yet.
514 template <typename Char
>
515 inline size_t count_code_points(basic_string_view
<Char
> s
) {
519 // Counts the number of code points in a UTF-8 string.
520 inline size_t count_code_points(basic_string_view
<char> s
) {
521 const char* data
= s
.data();
522 size_t num_code_points
= 0;
523 for (size_t i
= 0, size
= s
.size(); i
!= size
; ++i
) {
524 if ((data
[i
] & 0xc0) != 0x80) ++num_code_points
;
526 return num_code_points
;
529 inline size_t count_code_points(basic_string_view
<char8_type
> s
) {
530 return count_code_points(basic_string_view
<char>(
531 reinterpret_cast<const char*>(s
.data()), s
.size()));
534 template <typename Char
>
535 inline size_t code_point_index(basic_string_view
<Char
> s
, size_t n
) {
536 size_t size
= s
.size();
537 return n
< size
? n
: size
;
540 // Calculates the index of the nth code point in a UTF-8 string.
541 inline size_t code_point_index(basic_string_view
<char8_type
> s
, size_t n
) {
542 const char8_type
* data
= s
.data();
543 size_t num_code_points
= 0;
544 for (size_t i
= 0, size
= s
.size(); i
!= size
; ++i
) {
545 if ((data
[i
] & 0xc0) != 0x80 && ++num_code_points
> n
) {
552 inline char8_type
to_char8_t(char c
) { return static_cast<char8_type
>(c
); }
554 template <typename InputIt
, typename OutChar
>
555 using needs_conversion
= bool_constant
<
556 std::is_same
<typename
std::iterator_traits
<InputIt
>::value_type
,
558 std::is_same
<OutChar
, char8_type
>::value
>;
560 template <typename OutChar
, typename InputIt
, typename OutputIt
,
561 FMT_ENABLE_IF(!needs_conversion
<InputIt
, OutChar
>::value
)>
562 OutputIt
copy_str(InputIt begin
, InputIt end
, OutputIt it
) {
563 return std::copy(begin
, end
, it
);
566 template <typename OutChar
, typename InputIt
, typename OutputIt
,
567 FMT_ENABLE_IF(needs_conversion
<InputIt
, OutChar
>::value
)>
568 OutputIt
copy_str(InputIt begin
, InputIt end
, OutputIt it
) {
569 return std::transform(begin
, end
, it
, to_char8_t
);
572 #ifndef FMT_USE_GRISU
573 # define FMT_USE_GRISU 1
576 template <typename T
> constexpr bool use_grisu() {
577 return FMT_USE_GRISU
&& std::numeric_limits
<double>::is_iec559
&&
578 sizeof(T
) <= sizeof(double);
581 template <typename T
>
582 template <typename U
>
583 void buffer
<T
>::append(const U
* begin
, const U
* end
) {
584 size_t new_size
= size_
+ to_unsigned(end
- begin
);
586 std::uninitialized_copy(begin
, end
, make_checked(ptr_
, capacity_
) + size_
);
589 } // namespace detail
591 // A range with an iterator appending to a buffer.
592 template <typename T
>
594 : public detail::output_range
<std::back_insert_iterator
<detail::buffer
<T
>>,
597 using iterator
= std::back_insert_iterator
<detail::buffer
<T
>>;
598 using detail::output_range
<iterator
, T
>::output_range
;
599 buffer_range(detail::buffer
<T
>& buf
)
600 : detail::output_range
<iterator
, T
>(std::back_inserter(buf
)) {}
603 // The number of characters to store in the basic_memory_buffer object itself
604 // to avoid dynamic memory allocation.
605 enum { inline_buffer_size
= 500 };
609 A dynamically growing memory buffer for trivially copyable/constructible types
610 with the first ``SIZE`` elements stored in the object itself.
612 You can use one of the following type aliases for common character types:
614 +----------------+------------------------------+
615 | Type | Definition |
616 +================+==============================+
617 | memory_buffer | basic_memory_buffer<char> |
618 +----------------+------------------------------+
619 | wmemory_buffer | basic_memory_buffer<wchar_t> |
620 +----------------+------------------------------+
624 fmt::memory_buffer out;
625 format_to(out, "The answer is {}.", 42);
627 This will append the following output to the ``out`` object:
633 The output can be converted to an ``std::string`` with ``to_string(out)``.
636 template <typename T
, size_t SIZE
= inline_buffer_size
,
637 typename Allocator
= std::allocator
<T
>>
638 class basic_memory_buffer
: public detail::buffer
<T
> {
642 // Don't inherit from Allocator avoid generating type_info for it.
645 // Deallocate memory allocated by the buffer.
647 T
* data
= this->data();
648 if (data
!= store_
) alloc_
.deallocate(data
, this->capacity());
652 void grow(size_t size
) FMT_OVERRIDE
;
655 using value_type
= T
;
656 using const_reference
= const T
&;
658 explicit basic_memory_buffer(const Allocator
& alloc
= Allocator())
660 this->set(store_
, SIZE
);
662 ~basic_memory_buffer() FMT_OVERRIDE
{ deallocate(); }
665 // Move data from other to this buffer.
666 void move(basic_memory_buffer
& other
) {
667 alloc_
= std::move(other
.alloc_
);
668 T
* data
= other
.data();
669 size_t size
= other
.size(), capacity
= other
.capacity();
670 if (data
== other
.store_
) {
671 this->set(store_
, capacity
);
672 std::uninitialized_copy(other
.store_
, other
.store_
+ size
,
673 detail::make_checked(store_
, capacity
));
675 this->set(data
, capacity
);
676 // Set pointer to the inline array so that delete is not called
677 // when deallocating.
678 other
.set(other
.store_
, 0);
686 Constructs a :class:`fmt::basic_memory_buffer` object moving the content
687 of the other object to it.
690 basic_memory_buffer(basic_memory_buffer
&& other
) FMT_NOEXCEPT
{ move(other
); }
694 Moves the content of the other ``basic_memory_buffer`` object to this one.
697 basic_memory_buffer
& operator=(basic_memory_buffer
&& other
) FMT_NOEXCEPT
{
698 FMT_ASSERT(this != &other
, "");
704 // Returns a copy of the allocator associated with this buffer.
705 Allocator
get_allocator() const { return alloc_
; }
708 template <typename T
, size_t SIZE
, typename Allocator
>
709 void basic_memory_buffer
<T
, SIZE
, Allocator
>::grow(size_t size
) {
711 if (size
> 5000) throw std::runtime_error("fuzz mode - won't grow that much");
713 size_t old_capacity
= this->capacity();
714 size_t new_capacity
= old_capacity
+ old_capacity
/ 2;
715 if (size
> new_capacity
) new_capacity
= size
;
716 T
* old_data
= this->data();
718 std::allocator_traits
<Allocator
>::allocate(alloc_
, new_capacity
);
719 // The following code doesn't throw, so the raw pointer above doesn't leak.
720 std::uninitialized_copy(old_data
, old_data
+ this->size(),
721 detail::make_checked(new_data
, new_capacity
));
722 this->set(new_data
, new_capacity
);
723 // deallocate must not throw according to the standard, but even if it does,
724 // the buffer already uses the new storage and will deallocate it in
726 if (old_data
!= store_
) alloc_
.deallocate(old_data
, old_capacity
);
729 using memory_buffer
= basic_memory_buffer
<char>;
730 using wmemory_buffer
= basic_memory_buffer
<wchar_t>;
732 /** A formatting error such as invalid format string. */
734 class FMT_API format_error
: public std::runtime_error
{
736 explicit format_error(const char* message
) : std::runtime_error(message
) {}
737 explicit format_error(const std::string
& message
)
738 : std::runtime_error(message
) {}
739 format_error(const format_error
&) = default;
740 format_error
& operator=(const format_error
&) = default;
741 format_error(format_error
&&) = default;
742 format_error
& operator=(format_error
&&) = default;
743 ~format_error() FMT_NOEXCEPT FMT_OVERRIDE
;
748 // Returns true if value is negative, false otherwise.
749 // Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
750 template <typename T
, FMT_ENABLE_IF(std::numeric_limits
<T
>::is_signed
)>
751 FMT_CONSTEXPR
bool is_negative(T value
) {
754 template <typename T
, FMT_ENABLE_IF(!std::numeric_limits
<T
>::is_signed
)>
755 FMT_CONSTEXPR
bool is_negative(T
) {
759 template <typename T
, FMT_ENABLE_IF(std::is_floating_point
<T
>::value
)>
760 FMT_CONSTEXPR
bool is_supported_floating_point(T
) {
761 return (std::is_same
<T
, float>::value
&& FMT_USE_FLOAT
) ||
762 (std::is_same
<T
, double>::value
&& FMT_USE_DOUBLE
) ||
763 (std::is_same
<T
, long double>::value
&& FMT_USE_LONG_DOUBLE
);
766 // Smallest of uint32_t, uint64_t, uint128_t that is large enough to
767 // represent all values of T.
768 template <typename T
>
769 using uint32_or_64_or_128_t
= conditional_t
<
770 std::numeric_limits
<T
>::digits
<= 32, uint32_t,
771 conditional_t
<std::numeric_limits
<T
>::digits
<= 64, uint64_t, uint128_t
>>;
773 // Static data is placed in this class template for the header-only config.
774 template <typename T
= void> struct FMT_EXTERN_TEMPLATE_API basic_data
{
775 static const uint64_t powers_of_10_64
[];
776 static const uint32_t zero_or_powers_of_10_32
[];
777 static const uint64_t zero_or_powers_of_10_64
[];
778 static const uint64_t pow10_significands
[];
779 static const int16_t pow10_exponents
[];
780 static const char digits
[];
781 static const char hex_digits
[];
782 static const char foreground_color
[];
783 static const char background_color
[];
784 static const char reset_color
[5];
785 static const wchar_t wreset_color
[5];
786 static const char signs
[];
787 static const char left_padding_shifts
[5];
788 static const char right_padding_shifts
[5];
791 FMT_EXTERN
template struct basic_data
<void>;
793 // This is a struct rather than an alias to avoid shadowing warnings in gcc.
794 struct data
: basic_data
<> {};
796 #ifdef FMT_BUILTIN_CLZLL
797 // Returns the number of decimal digits in n. Leading zeros are not counted
798 // except for n == 0 in which case count_digits returns 1.
799 inline int count_digits(uint64_t n
) {
800 // Based on http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog10
801 // and the benchmark https://github.com/localvoid/cxx-benchmark-count-digits.
802 int t
= (64 - FMT_BUILTIN_CLZLL(n
| 1)) * 1233 >> 12;
803 return t
- (n
< data::zero_or_powers_of_10_64
[t
]) + 1;
806 // Fallback version of count_digits used when __builtin_clz is not available.
807 inline int count_digits(uint64_t n
) {
810 // Integer division is slow so do it for a group of four digits instead
811 // of for every digit. The idea comes from the talk by Alexandrescu
812 // "Three Optimization Tips for C++". See speed-test for a comparison.
813 if (n
< 10) return count
;
814 if (n
< 100) return count
+ 1;
815 if (n
< 1000) return count
+ 2;
816 if (n
< 10000) return count
+ 3;
824 inline int count_digits(uint128_t n
) {
827 // Integer division is slow so do it for a group of four digits instead
828 // of for every digit. The idea comes from the talk by Alexandrescu
829 // "Three Optimization Tips for C++". See speed-test for a comparison.
830 if (n
< 10) return count
;
831 if (n
< 100) return count
+ 1;
832 if (n
< 1000) return count
+ 2;
833 if (n
< 10000) return count
+ 3;
840 // Counts the number of digits in n. BITS = log2(radix).
841 template <unsigned BITS
, typename UInt
> inline int count_digits(UInt n
) {
845 } while ((n
>>= BITS
) != 0);
849 template <> int count_digits
<4>(detail::fallback_uintptr n
);
851 #if FMT_GCC_VERSION || FMT_CLANG_VERSION
852 # define FMT_ALWAYS_INLINE inline __attribute__((always_inline))
854 # define FMT_ALWAYS_INLINE
857 #ifdef FMT_BUILTIN_CLZ
858 // Optional version of count_digits for better performance on 32-bit platforms.
859 inline int count_digits(uint32_t n
) {
860 int t
= (32 - FMT_BUILTIN_CLZ(n
| 1)) * 1233 >> 12;
861 return t
- (n
< data::zero_or_powers_of_10_32
[t
]) + 1;
865 template <typename Char
> FMT_API
std::string
grouping_impl(locale_ref loc
);
866 template <typename Char
> inline std::string
grouping(locale_ref loc
) {
867 return grouping_impl
<char>(loc
);
869 template <> inline std::string grouping
<wchar_t>(locale_ref loc
) {
870 return grouping_impl
<wchar_t>(loc
);
873 template <typename Char
> FMT_API Char
thousands_sep_impl(locale_ref loc
);
874 template <typename Char
> inline Char
thousands_sep(locale_ref loc
) {
875 return Char(thousands_sep_impl
<char>(loc
));
877 template <> inline wchar_t thousands_sep(locale_ref loc
) {
878 return thousands_sep_impl
<wchar_t>(loc
);
881 template <typename Char
> FMT_API Char
decimal_point_impl(locale_ref loc
);
882 template <typename Char
> inline Char
decimal_point(locale_ref loc
) {
883 return Char(decimal_point_impl
<char>(loc
));
885 template <> inline wchar_t decimal_point(locale_ref loc
) {
886 return decimal_point_impl
<wchar_t>(loc
);
889 // Formats a decimal unsigned integer value writing into buffer.
890 // add_thousands_sep is called after writing each char to add a thousands
891 // separator if necessary.
892 template <typename UInt
, typename Char
, typename F
>
893 inline Char
* format_decimal(Char
* buffer
, UInt value
, int num_digits
,
894 F add_thousands_sep
) {
895 FMT_ASSERT(num_digits
>= 0, "invalid digit count");
896 buffer
+= num_digits
;
898 while (value
>= 100) {
899 // Integer division is slow so do it for a group of two digits instead
900 // of for every digit. The idea comes from the talk by Alexandrescu
901 // "Three Optimization Tips for C++". See speed-test for a comparison.
902 auto index
= static_cast<unsigned>((value
% 100) * 2);
904 *--buffer
= static_cast<Char
>(data::digits
[index
+ 1]);
905 add_thousands_sep(buffer
);
906 *--buffer
= static_cast<Char
>(data::digits
[index
]);
907 add_thousands_sep(buffer
);
910 *--buffer
= static_cast<Char
>('0' + value
);
913 auto index
= static_cast<unsigned>(value
* 2);
914 *--buffer
= static_cast<Char
>(data::digits
[index
+ 1]);
915 add_thousands_sep(buffer
);
916 *--buffer
= static_cast<Char
>(data::digits
[index
]);
920 template <typename Int
> constexpr int digits10() FMT_NOEXCEPT
{
921 return std::numeric_limits
<Int
>::digits10
;
923 template <> constexpr int digits10
<int128_t
>() FMT_NOEXCEPT
{ return 38; }
924 template <> constexpr int digits10
<uint128_t
>() FMT_NOEXCEPT
{ return 38; }
926 template <typename Char
, typename UInt
, typename Iterator
, typename F
>
927 inline Iterator
format_decimal(Iterator out
, UInt value
, int num_digits
,
928 F add_thousands_sep
) {
929 FMT_ASSERT(num_digits
>= 0, "invalid digit count");
930 // Buffer should be large enough to hold all digits (<= digits10 + 1).
931 enum { max_size
= digits10
<UInt
>() + 1 };
932 Char buffer
[2 * max_size
];
933 auto end
= format_decimal(buffer
, value
, num_digits
, add_thousands_sep
);
934 return detail::copy_str
<Char
>(buffer
, end
, out
);
937 template <typename Char
, typename It
, typename UInt
>
938 inline It
format_decimal(It out
, UInt value
, int num_digits
) {
939 return format_decimal
<Char
>(out
, value
, num_digits
, [](Char
*) {});
942 template <unsigned BASE_BITS
, typename Char
, typename UInt
>
943 inline Char
* format_uint(Char
* buffer
, UInt value
, int num_digits
,
944 bool upper
= false) {
945 buffer
+= num_digits
;
948 const char* digits
= upper
? "0123456789ABCDEF" : data::hex_digits
;
949 unsigned digit
= (value
& ((1 << BASE_BITS
) - 1));
950 *--buffer
= static_cast<Char
>(BASE_BITS
< 4 ? static_cast<char>('0' + digit
)
952 } while ((value
>>= BASE_BITS
) != 0);
956 template <unsigned BASE_BITS
, typename Char
>
957 Char
* format_uint(Char
* buffer
, detail::fallback_uintptr n
, int num_digits
,
959 auto char_digits
= std::numeric_limits
<unsigned char>::digits
/ 4;
960 int start
= (num_digits
+ char_digits
- 1) / char_digits
- 1;
961 if (int start_digits
= num_digits
% char_digits
) {
962 unsigned value
= n
.value
[start
--];
963 buffer
= format_uint
<BASE_BITS
>(buffer
, value
, start_digits
);
965 for (; start
>= 0; --start
) {
966 unsigned value
= n
.value
[start
];
967 buffer
+= char_digits
;
969 for (int i
= 0; i
< char_digits
; ++i
) {
970 unsigned digit
= (value
& ((1 << BASE_BITS
) - 1));
971 *--p
= static_cast<Char
>(data::hex_digits
[digit
]);
978 template <unsigned BASE_BITS
, typename Char
, typename It
, typename UInt
>
979 inline It
format_uint(It out
, UInt value
, int num_digits
, bool upper
= false) {
980 // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
981 char buffer
[num_bits
<UInt
>() / BASE_BITS
+ 1];
982 format_uint
<BASE_BITS
>(buffer
, value
, num_digits
, upper
);
983 return detail::copy_str
<Char
>(buffer
, buffer
+ num_digits
, out
);
986 // A converter from UTF-8 to UTF-16.
987 class utf8_to_utf16
{
989 wmemory_buffer buffer_
;
992 FMT_API
explicit utf8_to_utf16(string_view s
);
993 operator wstring_view() const { return {&buffer_
[0], size()}; }
994 size_t size() const { return buffer_
.size() - 1; }
995 const wchar_t* c_str() const { return &buffer_
[0]; }
996 std::wstring
str() const { return {&buffer_
[0], size()}; }
999 template <typename T
= void> struct null
{};
1001 // Workaround an array initialization issue in gcc 4.8.
1002 template <typename Char
> struct fill_t
{
1004 enum { max_size
= 4 };
1005 Char data_
[max_size
];
1006 unsigned char size_
;
1009 FMT_CONSTEXPR
void operator=(basic_string_view
<Char
> s
) {
1010 auto size
= s
.size();
1011 if (size
> max_size
) {
1012 FMT_THROW(format_error("invalid fill"));
1015 for (size_t i
= 0; i
< size
; ++i
) data_
[i
] = s
[i
];
1016 size_
= static_cast<unsigned char>(size
);
1019 size_t size() const { return size_
; }
1020 const Char
* data() const { return data_
; }
1022 FMT_CONSTEXPR Char
& operator[](size_t index
) { return data_
[index
]; }
1023 FMT_CONSTEXPR
const Char
& operator[](size_t index
) const {
1024 return data_
[index
];
1027 static FMT_CONSTEXPR fill_t
<Char
> make() {
1028 auto fill
= fill_t
<Char
>();
1029 fill
[0] = Char(' ');
1034 } // namespace detail
1036 // We cannot use enum classes as bit fields because of a gcc bug
1037 // https://gcc.gnu.org/bugzilla/show_bug.cgi?id=61414.
1039 enum type
{ none
, left
, right
, center
, numeric
};
1041 using align_t
= align::type
;
1044 enum type
{ none
, minus
, plus
, space
};
1046 using sign_t
= sign::type
;
1048 // Format specifiers for built-in and string types.
1049 template <typename Char
> struct basic_format_specs
{
1055 bool alt
: 1; // Alternate form ('#').
1056 detail::fill_t
<Char
> fill
;
1058 constexpr basic_format_specs()
1065 fill(detail::fill_t
<Char
>::make()) {}
1068 using format_specs
= basic_format_specs
<char>;
1072 // A floating-point presentation format.
1073 enum class float_format
: unsigned char {
1074 general
, // General: exponent notation or fixed point based on magnitude.
1075 exp
, // Exponent notation with the default precision of 6, e.g. 1.2e-3.
1076 fixed
, // Fixed point with the default precision of 6, e.g. 0.0012.
1080 struct float_specs
{
1082 float_format format
: 8;
1091 // Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1092 template <typename Char
, typename It
> It
write_exponent(int exp
, It it
) {
1093 FMT_ASSERT(-10000 < exp
&& exp
< 10000, "exponent out of range");
1095 *it
++ = static_cast<Char
>('-');
1098 *it
++ = static_cast<Char
>('+');
1101 const char* top
= data::digits
+ (exp
/ 100) * 2;
1102 if (exp
>= 1000) *it
++ = static_cast<Char
>(top
[0]);
1103 *it
++ = static_cast<Char
>(top
[1]);
1106 const char* d
= data::digits
+ exp
* 2;
1107 *it
++ = static_cast<Char
>(d
[0]);
1108 *it
++ = static_cast<Char
>(d
[1]);
1112 template <typename Char
> class float_writer
{
1114 // The number is given as v = digits_ * pow(10, exp_).
1115 const char* digits_
;
1120 Char decimal_point_
;
1122 template <typename It
> It
prettify(It it
) const {
1123 // pow(10, full_exp - 1) <= v <= pow(10, full_exp).
1124 int full_exp
= num_digits_
+ exp_
;
1125 if (specs_
.format
== float_format::exp
) {
1126 // Insert a decimal point after the first digit and add an exponent.
1127 *it
++ = static_cast<Char
>(*digits_
);
1128 int num_zeros
= specs_
.precision
- num_digits_
;
1129 if (num_digits_
> 1 || specs_
.showpoint
) *it
++ = decimal_point_
;
1130 it
= copy_str
<Char
>(digits_
+ 1, digits_
+ num_digits_
, it
);
1131 if (num_zeros
> 0 && specs_
.showpoint
)
1132 it
= std::fill_n(it
, num_zeros
, static_cast<Char
>('0'));
1133 *it
++ = static_cast<Char
>(specs_
.upper
? 'E' : 'e');
1134 return write_exponent
<Char
>(full_exp
- 1, it
);
1136 if (num_digits_
<= full_exp
) {
1137 // 1234e7 -> 12340000000[.0+]
1138 it
= copy_str
<Char
>(digits_
, digits_
+ num_digits_
, it
);
1139 it
= std::fill_n(it
, full_exp
- num_digits_
, static_cast<Char
>('0'));
1140 if (specs_
.showpoint
|| specs_
.precision
< 0) {
1141 *it
++ = decimal_point_
;
1142 int num_zeros
= specs_
.precision
- full_exp
;
1143 if (num_zeros
<= 0) {
1144 if (specs_
.format
!= float_format::fixed
)
1145 *it
++ = static_cast<Char
>('0');
1149 if (num_zeros
> 5000)
1150 throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
1152 it
= std::fill_n(it
, num_zeros
, static_cast<Char
>('0'));
1154 } else if (full_exp
> 0) {
1155 // 1234e-2 -> 12.34[0+]
1156 it
= copy_str
<Char
>(digits_
, digits_
+ full_exp
, it
);
1157 if (!specs_
.showpoint
) {
1158 // Remove trailing zeros.
1159 int num_digits
= num_digits_
;
1160 while (num_digits
> full_exp
&& digits_
[num_digits
- 1] == '0')
1162 if (num_digits
!= full_exp
) *it
++ = decimal_point_
;
1163 return copy_str
<Char
>(digits_
+ full_exp
, digits_
+ num_digits
, it
);
1165 *it
++ = decimal_point_
;
1166 it
= copy_str
<Char
>(digits_
+ full_exp
, digits_
+ num_digits_
, it
);
1167 if (specs_
.precision
> num_digits_
) {
1168 // Add trailing zeros.
1169 int num_zeros
= specs_
.precision
- num_digits_
;
1170 it
= std::fill_n(it
, num_zeros
, static_cast<Char
>('0'));
1173 // 1234e-6 -> 0.001234
1174 *it
++ = static_cast<Char
>('0');
1175 int num_zeros
= -full_exp
;
1176 int num_digits
= num_digits_
;
1177 if (num_digits
== 0 && specs_
.precision
>= 0 &&
1178 specs_
.precision
< num_zeros
) {
1179 num_zeros
= specs_
.precision
;
1181 // Remove trailing zeros.
1182 if (!specs_
.showpoint
)
1183 while (num_digits
> 0 && digits_
[num_digits
- 1] == '0') --num_digits
;
1184 if (num_zeros
!= 0 || num_digits
!= 0 || specs_
.showpoint
) {
1185 *it
++ = decimal_point_
;
1186 it
= std::fill_n(it
, num_zeros
, static_cast<Char
>('0'));
1187 it
= copy_str
<Char
>(digits_
, digits_
+ num_digits
, it
);
1194 float_writer(const char* digits
, int num_digits
, int exp
, float_specs specs
,
1197 num_digits_(num_digits
),
1200 decimal_point_(decimal_point
) {
1201 int full_exp
= num_digits
+ exp
- 1;
1202 int precision
= specs
.precision
> 0 ? specs
.precision
: 16;
1203 if (specs_
.format
== float_format::general
&&
1204 !(full_exp
>= -4 && full_exp
< precision
)) {
1205 specs_
.format
= float_format::exp
;
1207 size_
= prettify(counting_iterator()).count();
1208 size_
+= specs
.sign
? 1 : 0;
1211 size_t size() const { return size_
; }
1213 template <typename It
> It
operator()(It it
) const {
1214 if (specs_
.sign
) *it
++ = static_cast<Char
>(data::signs
[specs_
.sign
]);
1215 return prettify(it
);
1219 template <typename T
>
1220 int format_float(T value
, int precision
, float_specs specs
, buffer
<char>& buf
);
1222 // Formats a floating-point number with snprintf.
1223 template <typename T
>
1224 int snprintf_float(T value
, int precision
, float_specs specs
,
1227 template <typename T
> T
promote_float(T value
) { return value
; }
1228 inline double promote_float(float value
) { return static_cast<double>(value
); }
1230 template <typename Handler
>
1231 FMT_CONSTEXPR
void handle_int_type_spec(char spec
, Handler
&& handler
) {
1260 template <typename ErrorHandler
= error_handler
, typename Char
>
1261 FMT_CONSTEXPR float_specs
parse_float_type_spec(
1262 const basic_format_specs
<Char
>& specs
, ErrorHandler
&& eh
= {}) {
1263 auto result
= float_specs();
1264 result
.showpoint
= specs
.alt
;
1265 switch (specs
.type
) {
1267 result
.format
= float_format::general
;
1268 result
.showpoint
|= specs
.precision
> 0;
1271 result
.upper
= true;
1274 result
.format
= float_format::general
;
1277 result
.upper
= true;
1280 result
.format
= float_format::exp
;
1281 result
.showpoint
|= specs
.precision
!= 0;
1284 result
.upper
= true;
1287 result
.format
= float_format::fixed
;
1288 result
.showpoint
|= specs
.precision
!= 0;
1291 result
.upper
= true;
1294 result
.format
= float_format::hex
;
1298 result
.locale
= true;
1301 eh
.on_error("invalid type specifier");
1307 template <typename Char
, typename Handler
>
1308 FMT_CONSTEXPR
void handle_char_specs(const basic_format_specs
<Char
>* specs
,
1309 Handler
&& handler
) {
1310 if (!specs
) return handler
.on_char();
1311 if (specs
->type
&& specs
->type
!= 'c') return handler
.on_int();
1312 if (specs
->align
== align::numeric
|| specs
->sign
!= sign::none
|| specs
->alt
)
1313 handler
.on_error("invalid format specifier for char");
1317 template <typename Char
, typename Handler
>
1318 FMT_CONSTEXPR
void handle_cstring_type_spec(Char spec
, Handler
&& handler
) {
1319 if (spec
== 0 || spec
== 's')
1320 handler
.on_string();
1321 else if (spec
== 'p')
1322 handler
.on_pointer();
1324 handler
.on_error("invalid type specifier");
1327 template <typename Char
, typename ErrorHandler
>
1328 FMT_CONSTEXPR
void check_string_type_spec(Char spec
, ErrorHandler
&& eh
) {
1329 if (spec
!= 0 && spec
!= 's') eh
.on_error("invalid type specifier");
1332 template <typename Char
, typename ErrorHandler
>
1333 FMT_CONSTEXPR
void check_pointer_type_spec(Char spec
, ErrorHandler
&& eh
) {
1334 if (spec
!= 0 && spec
!= 'p') eh
.on_error("invalid type specifier");
1337 template <typename ErrorHandler
> class int_type_checker
: private ErrorHandler
{
1339 FMT_CONSTEXPR
explicit int_type_checker(ErrorHandler eh
) : ErrorHandler(eh
) {}
1341 FMT_CONSTEXPR
void on_dec() {}
1342 FMT_CONSTEXPR
void on_hex() {}
1343 FMT_CONSTEXPR
void on_bin() {}
1344 FMT_CONSTEXPR
void on_oct() {}
1345 FMT_CONSTEXPR
void on_num() {}
1346 FMT_CONSTEXPR
void on_chr() {}
1348 FMT_CONSTEXPR
void on_error() {
1349 ErrorHandler::on_error("invalid type specifier");
1353 template <typename ErrorHandler
>
1354 class char_specs_checker
: public ErrorHandler
{
1359 FMT_CONSTEXPR
char_specs_checker(char type
, ErrorHandler eh
)
1360 : ErrorHandler(eh
), type_(type
) {}
1362 FMT_CONSTEXPR
void on_int() {
1363 handle_int_type_spec(type_
, int_type_checker
<ErrorHandler
>(*this));
1365 FMT_CONSTEXPR
void on_char() {}
1368 template <typename ErrorHandler
>
1369 class cstring_type_checker
: public ErrorHandler
{
1371 FMT_CONSTEXPR
explicit cstring_type_checker(ErrorHandler eh
)
1372 : ErrorHandler(eh
) {}
1374 FMT_CONSTEXPR
void on_string() {}
1375 FMT_CONSTEXPR
void on_pointer() {}
1378 template <typename OutputIt
, typename Char
>
1379 FMT_NOINLINE OutputIt
fill(OutputIt it
, size_t n
, const fill_t
<Char
>& fill
) {
1380 auto fill_size
= fill
.size();
1381 if (fill_size
== 1) return std::fill_n(it
, n
, fill
[0]);
1382 for (size_t i
= 0; i
< n
; ++i
) it
= std::copy_n(fill
.data(), fill_size
, it
);
1386 // Writes the output of f, padded according to format specifications in specs.
1387 // size: output size in code units.
1388 // width: output display width in (terminal) column positions.
1389 template <align::type align
= align::left
, typename OutputIt
, typename Char
,
1391 inline OutputIt
write_padded(OutputIt out
,
1392 const basic_format_specs
<Char
>& specs
, size_t size
,
1393 size_t width
, const F
& f
) {
1394 static_assert(align
== align::left
|| align
== align::right
, "");
1395 unsigned spec_width
= to_unsigned(specs
.width
);
1396 size_t padding
= spec_width
> width
? spec_width
- width
: 0;
1397 auto* shifts
= align
== align::left
? data::left_padding_shifts
1398 : data::right_padding_shifts
;
1399 size_t left_padding
= padding
>> shifts
[specs
.align
];
1400 auto it
= reserve(out
, size
+ padding
* specs
.fill
.size());
1401 it
= fill(it
, left_padding
, specs
.fill
);
1403 it
= fill(it
, padding
- left_padding
, specs
.fill
);
1404 return base_iterator(out
, it
);
1407 template <align::type align
= align::left
, typename OutputIt
, typename Char
,
1409 inline OutputIt
write_padded(OutputIt out
,
1410 const basic_format_specs
<Char
>& specs
, size_t size
,
1412 return write_padded
<align
>(out
, specs
, size
, size
, f
);
1415 // Data for write_int that doesn't depend on output iterator type. It is used to
1416 // avoid template code bloat.
1417 template <typename Char
> struct write_int_data
{
1421 write_int_data(int num_digits
, string_view prefix
,
1422 const basic_format_specs
<Char
>& specs
)
1423 : size(prefix
.size() + to_unsigned(num_digits
)), padding(0) {
1424 if (specs
.align
== align::numeric
) {
1425 auto width
= to_unsigned(specs
.width
);
1427 padding
= width
- size
;
1430 } else if (specs
.precision
> num_digits
) {
1431 size
= prefix
.size() + to_unsigned(specs
.precision
);
1432 padding
= to_unsigned(specs
.precision
- num_digits
);
1437 // Writes an integer in the format
1438 // <left-padding><prefix><numeric-padding><digits><right-padding>
1439 // where <digits> are written by f(it).
1440 template <typename OutputIt
, typename Char
, typename F
>
1441 OutputIt
write_int(OutputIt out
, int num_digits
, string_view prefix
,
1442 const basic_format_specs
<Char
>& specs
, F f
) {
1443 auto data
= write_int_data
<Char
>(num_digits
, prefix
, specs
);
1444 using iterator
= remove_reference_t
<decltype(reserve(out
, 0))>;
1445 return write_padded
<align::right
>(out
, specs
, data
.size
, [=](iterator it
) {
1446 if (prefix
.size() != 0)
1447 it
= copy_str
<Char
>(prefix
.begin(), prefix
.end(), it
);
1448 it
= std::fill_n(it
, data
.padding
, static_cast<Char
>('0'));
1453 // The handle_int_type_spec handler that writes an integer.
1454 template <typename OutputIt
, typename Char
, typename UInt
> struct int_writer
{
1457 const basic_format_specs
<Char
>& specs
;
1460 unsigned prefix_size
;
1463 remove_reference_t
<decltype(reserve(std::declval
<OutputIt
&>(), 0))>;
1465 string_view
get_prefix() const { return string_view(prefix
, prefix_size
); }
1467 template <typename Int
>
1468 int_writer(OutputIt output
, locale_ref loc
, Int value
,
1469 const basic_format_specs
<Char
>& s
)
1473 abs_value(static_cast<UInt
>(value
)),
1475 static_assert(std::is_same
<uint32_or_64_or_128_t
<Int
>, UInt
>::value
, "");
1476 if (is_negative(value
)) {
1479 abs_value
= 0 - abs_value
;
1480 } else if (specs
.sign
!= sign::none
&& specs
.sign
!= sign::minus
) {
1481 prefix
[0] = specs
.sign
== sign::plus
? '+' : ' ';
1487 auto num_digits
= count_digits(abs_value
);
1488 out
= write_int(out
, num_digits
, get_prefix(), specs
,
1489 [this, num_digits
](iterator it
) {
1490 return format_decimal
<Char
>(it
, abs_value
, num_digits
);
1496 prefix
[prefix_size
++] = '0';
1497 prefix
[prefix_size
++] = specs
.type
;
1499 int num_digits
= count_digits
<4>(abs_value
);
1500 out
= write_int(out
, num_digits
, get_prefix(), specs
,
1501 [this, num_digits
](iterator it
) {
1502 return format_uint
<4, Char
>(it
, abs_value
, num_digits
,
1509 prefix
[prefix_size
++] = '0';
1510 prefix
[prefix_size
++] = static_cast<char>(specs
.type
);
1512 int num_digits
= count_digits
<1>(abs_value
);
1513 out
= write_int(out
, num_digits
, get_prefix(), specs
,
1514 [this, num_digits
](iterator it
) {
1515 return format_uint
<1, Char
>(it
, abs_value
, num_digits
);
1520 int num_digits
= count_digits
<3>(abs_value
);
1521 if (specs
.alt
&& specs
.precision
<= num_digits
&& abs_value
!= 0) {
1522 // Octal prefix '0' is counted as a digit, so only add it if precision
1523 // is not greater than the number of digits.
1524 prefix
[prefix_size
++] = '0';
1526 out
= write_int(out
, num_digits
, get_prefix(), specs
,
1527 [this, num_digits
](iterator it
) {
1528 return format_uint
<3, Char
>(it
, abs_value
, num_digits
);
1532 enum { sep_size
= 1 };
1537 const std::string
& groups
;
1540 template <typename It
> It
operator()(It it
) const {
1541 basic_string_view
<Char
> s(&sep
, sep_size
);
1542 // Index of a decimal digit with the least significant digit having
1544 int digit_index
= 0;
1545 std::string::const_iterator group
= groups
.cbegin();
1546 return format_decimal
<Char
>(
1547 it
, abs_value
, size
, [this, s
, &group
, &digit_index
](Char
*& buffer
) {
1548 if (*group
<= 0 || ++digit_index
% *group
!= 0 ||
1549 *group
== max_value
<char>())
1551 if (group
+ 1 != groups
.cend()) {
1556 std::uninitialized_copy(s
.data(), s
.data() + s
.size(),
1557 make_checked(buffer
, s
.size()));
1563 std::string groups
= grouping
<Char
>(locale
);
1564 if (groups
.empty()) return on_dec();
1565 auto sep
= thousands_sep
<Char
>(locale
);
1566 if (!sep
) return on_dec();
1567 int num_digits
= count_digits(abs_value
);
1568 int size
= num_digits
;
1569 std::string::const_iterator group
= groups
.cbegin();
1570 while (group
!= groups
.cend() && num_digits
> *group
&& *group
> 0 &&
1571 *group
!= max_value
<char>()) {
1573 num_digits
-= *group
;
1576 if (group
== groups
.cend())
1577 size
+= sep_size
* ((num_digits
- 1) / groups
.back());
1578 out
= write_int(out
, size
, get_prefix(), specs
,
1579 num_writer
{abs_value
, size
, groups
, sep
});
1582 void on_chr() { *out
++ = static_cast<Char
>(abs_value
); }
1584 FMT_NORETURN
void on_error() {
1585 FMT_THROW(format_error("invalid type specifier"));
1589 template <typename Char
, typename OutputIt
>
1590 OutputIt
write_bytes(OutputIt out
, string_view bytes
,
1591 const basic_format_specs
<Char
>& specs
) {
1592 using iterator
= remove_reference_t
<decltype(reserve(out
, 0))>;
1593 return write_padded(out
, specs
, bytes
.size(), [bytes
](iterator it
) {
1594 const char* data
= bytes
.data();
1595 return copy_str
<Char
>(data
, data
+ bytes
.size(), it
);
1599 template <typename Char
, typename OutputIt
>
1600 OutputIt
write_nonfinite(OutputIt out
, bool isinf
,
1601 const basic_format_specs
<Char
>& specs
,
1602 const float_specs
& fspecs
) {
1604 isinf
? (fspecs
.upper
? "INF" : "inf") : (fspecs
.upper
? "NAN" : "nan");
1605 constexpr size_t str_size
= 3;
1606 auto sign
= fspecs
.sign
;
1607 auto size
= str_size
+ (sign
? 1 : 0);
1608 using iterator
= remove_reference_t
<decltype(reserve(out
, 0))>;
1609 return write_padded(out
, specs
, size
, [=](iterator it
) {
1610 if (sign
) *it
++ = static_cast<Char
>(data::signs
[sign
]);
1611 return copy_str
<Char
>(str
, str
+ str_size
, it
);
1615 template <typename Char
, typename OutputIt
, typename T
,
1616 FMT_ENABLE_IF(std::is_floating_point
<T
>::value
)>
1617 OutputIt
write(OutputIt out
, T value
, basic_format_specs
<Char
> specs
= {},
1618 locale_ref loc
= {}) {
1619 if (const_check(!is_supported_floating_point(value
))) return out
;
1620 float_specs fspecs
= parse_float_type_spec(specs
);
1621 fspecs
.sign
= specs
.sign
;
1622 if (std::signbit(value
)) { // value < 0 is false for NaN so use signbit.
1623 fspecs
.sign
= sign::minus
;
1625 } else if (fspecs
.sign
== sign::minus
) {
1626 fspecs
.sign
= sign::none
;
1629 if (!std::isfinite(value
))
1630 return write_nonfinite(out
, std::isinf(value
), specs
, fspecs
);
1632 if (specs
.align
== align::numeric
&& fspecs
.sign
) {
1633 auto it
= reserve(out
, 1);
1634 *it
++ = static_cast<Char
>(data::signs
[fspecs
.sign
]);
1635 out
= base_iterator(out
, it
);
1636 fspecs
.sign
= sign::none
;
1637 if (specs
.width
!= 0) --specs
.width
;
1640 memory_buffer buffer
;
1641 if (fspecs
.format
== float_format::hex
) {
1642 if (fspecs
.sign
) buffer
.push_back(data::signs
[fspecs
.sign
]);
1643 snprintf_float(promote_float(value
), specs
.precision
, fspecs
, buffer
);
1644 return write_bytes(out
, {buffer
.data(), buffer
.size()}, specs
);
1646 int precision
= specs
.precision
>= 0 || !specs
.type
? specs
.precision
: 6;
1647 if (fspecs
.format
== float_format::exp
) {
1648 if (precision
== max_value
<int>())
1649 FMT_THROW(format_error("number is too big"));
1653 if (const_check(std::is_same
<T
, float>())) fspecs
.binary32
= true;
1654 fspecs
.use_grisu
= use_grisu
<T
>();
1655 int exp
= format_float(promote_float(value
), precision
, fspecs
, buffer
);
1656 fspecs
.precision
= precision
;
1658 fspecs
.locale
? decimal_point
<Char
>(loc
) : static_cast<Char
>('.');
1659 float_writer
<Char
> w(buffer
.data(), static_cast<int>(buffer
.size()), exp
,
1661 return write_padded
<align::right
>(out
, specs
, w
.size(), w
);
1664 template <typename StrChar
, typename Char
, typename OutputIt
>
1665 OutputIt
write(OutputIt out
, basic_string_view
<StrChar
> s
,
1666 const basic_format_specs
<Char
>& specs
= {}) {
1667 auto data
= s
.data();
1668 auto size
= s
.size();
1669 if (specs
.precision
>= 0 && to_unsigned(specs
.precision
) < size
)
1670 size
= code_point_index(s
, to_unsigned(specs
.precision
));
1671 auto width
= specs
.width
!= 0
1672 ? count_code_points(basic_string_view
<StrChar
>(data
, size
))
1674 using iterator
= remove_reference_t
<decltype(reserve(out
, 0))>;
1675 return write_padded(out
, specs
, size
, width
, [=](iterator it
) {
1676 return copy_str
<Char
>(data
, data
+ size
, it
);
1680 template <typename Char
, typename OutputIt
, typename UIntPtr
>
1681 OutputIt
write_ptr(OutputIt out
, UIntPtr value
,
1682 const basic_format_specs
<Char
>* specs
) {
1683 int num_digits
= count_digits
<4>(value
);
1684 auto size
= to_unsigned(num_digits
) + size_t(2);
1685 using iterator
= remove_reference_t
<decltype(reserve(out
, 0))>;
1686 auto write
= [=](iterator it
) {
1687 *it
++ = static_cast<Char
>('0');
1688 *it
++ = static_cast<Char
>('x');
1689 return format_uint
<4, Char
>(it
, value
, num_digits
);
1691 return specs
? write_padded
<align::right
>(out
, *specs
, size
, write
)
1692 : base_iterator(out
, write(reserve(out
, size
)));
1695 template <typename T
> struct is_integral
: std::is_integral
<T
> {};
1696 template <> struct is_integral
<int128_t
> : std::true_type
{};
1697 template <> struct is_integral
<uint128_t
> : std::true_type
{};
1699 template <typename Range
, typename ErrorHandler
= detail::error_handler
>
1700 class arg_formatter_base
{
1702 using char_type
= typename
Range::value_type
;
1703 using iterator
= typename
Range::iterator
;
1704 using format_specs
= basic_format_specs
<char_type
>;
1707 iterator out_
; // Output iterator.
1709 format_specs
* specs_
;
1711 // Attempts to reserve space for n extra characters in the output range.
1712 // Returns a pointer to the reserved range or a reference to out_.
1713 auto reserve(size_t n
) -> decltype(detail::reserve(out_
, n
)) {
1714 return detail::reserve(out_
, n
);
1717 using reserve_iterator
= remove_reference_t
<decltype(
1718 detail::reserve(std::declval
<iterator
&>(), 0))>;
1720 struct char_writer
{
1723 size_t size() const { return 1; }
1725 template <typename It
> It
operator()(It it
) const {
1731 void write_char(char_type value
) {
1733 out_
= write_padded(out_
, *specs_
, 1, char_writer
{value
});
1738 // Writes a decimal integer.
1739 template <typename Int
> void write_decimal(Int value
) {
1740 auto abs_value
= static_cast<uint32_or_64_or_128_t
<Int
>>(value
);
1741 bool negative
= is_negative(value
);
1742 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
1743 if (negative
) abs_value
= ~abs_value
+ 1;
1744 int num_digits
= count_digits(abs_value
);
1745 auto&& it
= reserve((negative
? 1 : 0) + static_cast<size_t>(num_digits
));
1746 if (negative
) *it
++ = static_cast<char_type
>('-');
1747 it
= format_decimal
<char_type
>(it
, abs_value
, num_digits
);
1750 void write(int value
) { write_decimal(value
); }
1751 void write(long value
) { write_decimal(value
); }
1752 void write(long long value
) { write_decimal(value
); }
1754 void write(unsigned value
) { write_decimal(value
); }
1755 void write(unsigned long value
) { write_decimal(value
); }
1756 void write(unsigned long long value
) { write_decimal(value
); }
1759 void write(int128_t value
) { write_decimal(value
); }
1760 void write(uint128_t value
) { write_decimal(value
); }
1763 template <typename T
> void write_int(T value
, const format_specs
& spec
) {
1764 using uint_type
= uint32_or_64_or_128_t
<T
>;
1765 int_writer
<iterator
, char_type
, uint_type
> w(out_
, locale_
, value
, spec
);
1766 handle_int_type_spec(spec
.type
, w
);
1770 void write(char value
) {
1771 auto&& it
= reserve(1);
1775 template <typename Char
, FMT_ENABLE_IF(std::is_same
<Char
, char_type
>::value
)>
1776 void write(Char value
) {
1777 auto&& it
= reserve(1);
1781 void write(string_view value
) {
1782 auto&& it
= reserve(value
.size());
1783 it
= copy_str
<char_type
>(value
.begin(), value
.end(), it
);
1785 void write(wstring_view value
) {
1786 static_assert(std::is_same
<char_type
, wchar_t>::value
, "");
1787 auto&& it
= reserve(value
.size());
1788 it
= std::copy(value
.begin(), value
.end(), it
);
1791 template <typename Char
>
1792 void write(const Char
* s
, size_t size
, const format_specs
& specs
) {
1793 auto width
= specs
.width
!= 0
1794 ? count_code_points(basic_string_view
<Char
>(s
, size
))
1796 out_
= write_padded(out_
, specs
, size
, width
, [=](reserve_iterator it
) {
1797 return copy_str
<char_type
>(s
, s
+ size
, it
);
1801 template <typename Char
>
1802 void write(basic_string_view
<Char
> s
, const format_specs
& specs
= {}) {
1803 out_
= detail::write(out_
, s
, specs
);
1806 void write_pointer(const void* p
) {
1807 out_
= write_ptr
<char_type
>(out_
, detail::to_uintptr(p
), specs_
);
1811 iterator
out() { return out_
; }
1812 format_specs
* specs() { return specs_
; }
1814 void write(bool value
) {
1815 string_view
sv(value
? "true" : "false");
1816 specs_
? write(sv
, *specs_
) : write(sv
);
1819 void write(const char_type
* value
) {
1821 FMT_THROW(format_error("string pointer is null"));
1823 auto length
= std::char_traits
<char_type
>::length(value
);
1824 basic_string_view
<char_type
> sv(value
, length
);
1825 specs_
? write(sv
, *specs_
) : write(sv
);
1830 arg_formatter_base(Range r
, format_specs
* s
, locale_ref loc
)
1831 : out_(r
.begin()), locale_(loc
), specs_(s
) {}
1833 iterator
operator()(monostate
) {
1834 FMT_ASSERT(false, "invalid argument type");
1838 template <typename T
, FMT_ENABLE_IF(is_integral
<T
>::value
)>
1839 iterator
operator()(T value
) {
1841 write_int(value
, *specs_
);
1847 iterator
operator()(char_type value
) {
1848 detail::handle_char_specs(
1849 specs_
, char_spec_handler(*this, static_cast<char_type
>(value
)));
1853 iterator
operator()(bool value
) {
1854 if (specs_
&& specs_
->type
) return (*this)(value
? 1 : 0);
1859 template <typename T
, FMT_ENABLE_IF(std::is_floating_point
<T
>::value
)>
1860 iterator
operator()(T value
) {
1861 auto specs
= specs_
? *specs_
: format_specs();
1862 if (const_check(is_supported_floating_point(value
)))
1863 out_
= detail::write(out_
, value
, specs
, locale_
);
1865 FMT_ASSERT(false, "unsupported float argument type");
1869 struct char_spec_handler
: ErrorHandler
{
1870 arg_formatter_base
& formatter
;
1873 char_spec_handler(arg_formatter_base
& f
, char_type val
)
1874 : formatter(f
), value(val
) {}
1877 if (formatter
.specs_
)
1878 formatter
.write_int(static_cast<int>(value
), *formatter
.specs_
);
1880 formatter
.write(value
);
1882 void on_char() { formatter
.write_char(value
); }
1885 struct cstring_spec_handler
: detail::error_handler
{
1886 arg_formatter_base
& formatter
;
1887 const char_type
* value
;
1889 cstring_spec_handler(arg_formatter_base
& f
, const char_type
* val
)
1890 : formatter(f
), value(val
) {}
1892 void on_string() { formatter
.write(value
); }
1893 void on_pointer() { formatter
.write_pointer(value
); }
1896 iterator
operator()(const char_type
* value
) {
1897 if (!specs_
) return write(value
), out();
1898 detail::handle_cstring_type_spec(specs_
->type
,
1899 cstring_spec_handler(*this, value
));
1903 iterator
operator()(basic_string_view
<char_type
> value
) {
1905 detail::check_string_type_spec(specs_
->type
, detail::error_handler());
1906 write(value
, *specs_
);
1913 iterator
operator()(const void* value
) {
1914 if (specs_
) check_pointer_type_spec(specs_
->type
, detail::error_handler());
1915 write_pointer(value
);
1920 template <typename Char
> FMT_CONSTEXPR
bool is_name_start(Char c
) {
1921 return ('a' <= c
&& c
<= 'z') || ('A' <= c
&& c
<= 'Z') || '_' == c
;
1924 // Parses the range [begin, end) as an unsigned integer. This function assumes
1925 // that the range is non-empty and the first character is a digit.
1926 template <typename Char
, typename ErrorHandler
>
1927 FMT_CONSTEXPR
int parse_nonnegative_int(const Char
*& begin
, const Char
* end
,
1928 ErrorHandler
&& eh
) {
1929 FMT_ASSERT(begin
!= end
&& '0' <= *begin
&& *begin
<= '9', "");
1931 // Convert to unsigned to prevent a warning.
1932 constexpr unsigned max_int
= max_value
<int>();
1933 unsigned big
= max_int
/ 10;
1935 // Check for overflow.
1937 value
= max_int
+ 1;
1940 value
= value
* 10 + unsigned(*begin
- '0');
1942 } while (begin
!= end
&& '0' <= *begin
&& *begin
<= '9');
1943 if (value
> max_int
) eh
.on_error("number is too big");
1944 return static_cast<int>(value
);
1947 template <typename Context
> class custom_formatter
{
1949 using char_type
= typename
Context::char_type
;
1951 basic_format_parse_context
<char_type
>& parse_ctx_
;
1955 explicit custom_formatter(basic_format_parse_context
<char_type
>& parse_ctx
,
1957 : parse_ctx_(parse_ctx
), ctx_(ctx
) {}
1959 bool operator()(typename basic_format_arg
<Context
>::handle h
) const {
1960 h
.format(parse_ctx_
, ctx_
);
1964 template <typename T
> bool operator()(T
) const { return false; }
1967 template <typename T
>
1969 bool_constant
<is_integral
<T
>::value
&& !std::is_same
<T
, bool>::value
&&
1970 !std::is_same
<T
, char>::value
&&
1971 !std::is_same
<T
, wchar_t>::value
>;
1973 template <typename ErrorHandler
> class width_checker
{
1975 explicit FMT_CONSTEXPR
width_checker(ErrorHandler
& eh
) : handler_(eh
) {}
1977 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
1978 FMT_CONSTEXPR
unsigned long long operator()(T value
) {
1979 if (is_negative(value
)) handler_
.on_error("negative width");
1980 return static_cast<unsigned long long>(value
);
1983 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
1984 FMT_CONSTEXPR
unsigned long long operator()(T
) {
1985 handler_
.on_error("width is not integer");
1990 ErrorHandler
& handler_
;
1993 template <typename ErrorHandler
> class precision_checker
{
1995 explicit FMT_CONSTEXPR
precision_checker(ErrorHandler
& eh
) : handler_(eh
) {}
1997 template <typename T
, FMT_ENABLE_IF(is_integer
<T
>::value
)>
1998 FMT_CONSTEXPR
unsigned long long operator()(T value
) {
1999 if (is_negative(value
)) handler_
.on_error("negative precision");
2000 return static_cast<unsigned long long>(value
);
2003 template <typename T
, FMT_ENABLE_IF(!is_integer
<T
>::value
)>
2004 FMT_CONSTEXPR
unsigned long long operator()(T
) {
2005 handler_
.on_error("precision is not integer");
2010 ErrorHandler
& handler_
;
2013 // A format specifier handler that sets fields in basic_format_specs.
2014 template <typename Char
> class specs_setter
{
2016 explicit FMT_CONSTEXPR
specs_setter(basic_format_specs
<Char
>& specs
)
2019 FMT_CONSTEXPR
specs_setter(const specs_setter
& other
)
2020 : specs_(other
.specs_
) {}
2022 FMT_CONSTEXPR
void on_align(align_t align
) { specs_
.align
= align
; }
2023 FMT_CONSTEXPR
void on_fill(basic_string_view
<Char
> fill
) {
2026 FMT_CONSTEXPR
void on_plus() { specs_
.sign
= sign::plus
; }
2027 FMT_CONSTEXPR
void on_minus() { specs_
.sign
= sign::minus
; }
2028 FMT_CONSTEXPR
void on_space() { specs_
.sign
= sign::space
; }
2029 FMT_CONSTEXPR
void on_hash() { specs_
.alt
= true; }
2031 FMT_CONSTEXPR
void on_zero() {
2032 specs_
.align
= align::numeric
;
2033 specs_
.fill
[0] = Char('0');
2036 FMT_CONSTEXPR
void on_width(int width
) { specs_
.width
= width
; }
2037 FMT_CONSTEXPR
void on_precision(int precision
) {
2038 specs_
.precision
= precision
;
2040 FMT_CONSTEXPR
void end_precision() {}
2042 FMT_CONSTEXPR
void on_type(Char type
) {
2043 specs_
.type
= static_cast<char>(type
);
2047 basic_format_specs
<Char
>& specs_
;
2050 template <typename ErrorHandler
> class numeric_specs_checker
{
2052 FMT_CONSTEXPR
numeric_specs_checker(ErrorHandler
& eh
, detail::type arg_type
)
2053 : error_handler_(eh
), arg_type_(arg_type
) {}
2055 FMT_CONSTEXPR
void require_numeric_argument() {
2056 if (!is_arithmetic_type(arg_type_
))
2057 error_handler_
.on_error("format specifier requires numeric argument");
2060 FMT_CONSTEXPR
void check_sign() {
2061 require_numeric_argument();
2062 if (is_integral_type(arg_type_
) && arg_type_
!= type::int_type
&&
2063 arg_type_
!= type::long_long_type
&& arg_type_
!= type::char_type
) {
2064 error_handler_
.on_error("format specifier requires signed argument");
2068 FMT_CONSTEXPR
void check_precision() {
2069 if (is_integral_type(arg_type_
) || arg_type_
== type::pointer_type
)
2070 error_handler_
.on_error("precision not allowed for this argument type");
2074 ErrorHandler
& error_handler_
;
2075 detail::type arg_type_
;
2078 // A format specifier handler that checks if specifiers are consistent with the
2080 template <typename Handler
> class specs_checker
: public Handler
{
2082 numeric_specs_checker
<Handler
> checker_
;
2084 // Suppress an MSVC warning about using this in initializer list.
2085 FMT_CONSTEXPR Handler
& error_handler() { return *this; }
2088 FMT_CONSTEXPR
specs_checker(const Handler
& handler
, detail::type arg_type
)
2089 : Handler(handler
), checker_(error_handler(), arg_type
) {}
2091 FMT_CONSTEXPR
specs_checker(const specs_checker
& other
)
2092 : Handler(other
), checker_(error_handler(), other
.arg_type_
) {}
2094 FMT_CONSTEXPR
void on_align(align_t align
) {
2095 if (align
== align::numeric
) checker_
.require_numeric_argument();
2096 Handler::on_align(align
);
2099 FMT_CONSTEXPR
void on_plus() {
2100 checker_
.check_sign();
2104 FMT_CONSTEXPR
void on_minus() {
2105 checker_
.check_sign();
2106 Handler::on_minus();
2109 FMT_CONSTEXPR
void on_space() {
2110 checker_
.check_sign();
2111 Handler::on_space();
2114 FMT_CONSTEXPR
void on_hash() {
2115 checker_
.require_numeric_argument();
2119 FMT_CONSTEXPR
void on_zero() {
2120 checker_
.require_numeric_argument();
2124 FMT_CONSTEXPR
void end_precision() { checker_
.check_precision(); }
2127 template <template <typename
> class Handler
, typename FormatArg
,
2128 typename ErrorHandler
>
2129 FMT_CONSTEXPR
int get_dynamic_spec(FormatArg arg
, ErrorHandler eh
) {
2130 unsigned long long value
= visit_format_arg(Handler
<ErrorHandler
>(eh
), arg
);
2131 if (value
> to_unsigned(max_value
<int>())) eh
.on_error("number is too big");
2132 return static_cast<int>(value
);
2137 template <typename Context
, typename ID
>
2138 FMT_CONSTEXPR typename
Context::format_arg
get_arg(Context
& ctx
, ID id
) {
2139 auto arg
= ctx
.arg(id
);
2140 if (!arg
) ctx
.on_error("argument not found");
2144 // The standard format specifier handler with checking.
2145 template <typename ParseContext
, typename Context
>
2146 class specs_handler
: public specs_setter
<typename
Context::char_type
> {
2148 using char_type
= typename
Context::char_type
;
2150 FMT_CONSTEXPR
specs_handler(basic_format_specs
<char_type
>& specs
,
2151 ParseContext
& parse_ctx
, Context
& ctx
)
2152 : specs_setter
<char_type
>(specs
),
2153 parse_context_(parse_ctx
),
2156 template <typename Id
> FMT_CONSTEXPR
void on_dynamic_width(Id arg_id
) {
2157 this->specs_
.width
= get_dynamic_spec
<width_checker
>(
2158 get_arg(arg_id
), context_
.error_handler());
2161 template <typename Id
> FMT_CONSTEXPR
void on_dynamic_precision(Id arg_id
) {
2162 this->specs_
.precision
= get_dynamic_spec
<precision_checker
>(
2163 get_arg(arg_id
), context_
.error_handler());
2166 void on_error(const char* message
) { context_
.on_error(message
); }
2169 // This is only needed for compatibility with gcc 4.4.
2170 using format_arg
= typename
Context::format_arg
;
2172 FMT_CONSTEXPR format_arg
get_arg(auto_id
) {
2173 return detail::get_arg(context_
, parse_context_
.next_arg_id());
2176 FMT_CONSTEXPR format_arg
get_arg(int arg_id
) {
2177 parse_context_
.check_arg_id(arg_id
);
2178 return detail::get_arg(context_
, arg_id
);
2181 FMT_CONSTEXPR format_arg
get_arg(basic_string_view
<char_type
> arg_id
) {
2182 parse_context_
.check_arg_id(arg_id
);
2183 return detail::get_arg(context_
, arg_id
);
2186 ParseContext
& parse_context_
;
2190 enum class arg_id_kind
{ none
, index
, name
};
2192 // An argument reference.
2193 template <typename Char
> struct arg_ref
{
2194 FMT_CONSTEXPR
arg_ref() : kind(arg_id_kind::none
), val() {}
2196 FMT_CONSTEXPR
explicit arg_ref(int index
)
2197 : kind(arg_id_kind::index
), val(index
) {}
2198 FMT_CONSTEXPR
explicit arg_ref(basic_string_view
<Char
> name
)
2199 : kind(arg_id_kind::name
), val(name
) {}
2201 FMT_CONSTEXPR arg_ref
& operator=(int idx
) {
2202 kind
= arg_id_kind::index
;
2209 FMT_CONSTEXPR
value(int id
= 0) : index
{id
} {}
2210 FMT_CONSTEXPR
value(basic_string_view
<Char
> n
) : name(n
) {}
2213 basic_string_view
<Char
> name
;
2217 // Format specifiers with width and precision resolved at formatting rather
2218 // than parsing time to allow re-using the same parsed specifiers with
2219 // different sets of arguments (precompilation of format strings).
2220 template <typename Char
>
2221 struct dynamic_format_specs
: basic_format_specs
<Char
> {
2222 arg_ref
<Char
> width_ref
;
2223 arg_ref
<Char
> precision_ref
;
2226 // Format spec handler that saves references to arguments representing dynamic
2227 // width and precision to be resolved at formatting time.
2228 template <typename ParseContext
>
2229 class dynamic_specs_handler
2230 : public specs_setter
<typename
ParseContext::char_type
> {
2232 using char_type
= typename
ParseContext::char_type
;
2234 FMT_CONSTEXPR
dynamic_specs_handler(dynamic_format_specs
<char_type
>& specs
,
2236 : specs_setter
<char_type
>(specs
), specs_(specs
), context_(ctx
) {}
2238 FMT_CONSTEXPR
dynamic_specs_handler(const dynamic_specs_handler
& other
)
2239 : specs_setter
<char_type
>(other
),
2240 specs_(other
.specs_
),
2241 context_(other
.context_
) {}
2243 template <typename Id
> FMT_CONSTEXPR
void on_dynamic_width(Id arg_id
) {
2244 specs_
.width_ref
= make_arg_ref(arg_id
);
2247 template <typename Id
> FMT_CONSTEXPR
void on_dynamic_precision(Id arg_id
) {
2248 specs_
.precision_ref
= make_arg_ref(arg_id
);
2251 FMT_CONSTEXPR
void on_error(const char* message
) {
2252 context_
.on_error(message
);
2256 using arg_ref_type
= arg_ref
<char_type
>;
2258 FMT_CONSTEXPR arg_ref_type
make_arg_ref(int arg_id
) {
2259 context_
.check_arg_id(arg_id
);
2260 return arg_ref_type(arg_id
);
2263 FMT_CONSTEXPR arg_ref_type
make_arg_ref(auto_id
) {
2264 return arg_ref_type(context_
.next_arg_id());
2267 FMT_CONSTEXPR arg_ref_type
make_arg_ref(basic_string_view
<char_type
> arg_id
) {
2268 context_
.check_arg_id(arg_id
);
2269 basic_string_view
<char_type
> format_str(
2270 context_
.begin(), to_unsigned(context_
.end() - context_
.begin()));
2271 return arg_ref_type(arg_id
);
2274 dynamic_format_specs
<char_type
>& specs_
;
2275 ParseContext
& context_
;
2278 template <typename Char
, typename IDHandler
>
2279 FMT_CONSTEXPR
const Char
* parse_arg_id(const Char
* begin
, const Char
* end
,
2280 IDHandler
&& handler
) {
2281 FMT_ASSERT(begin
!= end
, "");
2283 if (c
== '}' || c
== ':') {
2287 if (c
>= '0' && c
<= '9') {
2290 index
= parse_nonnegative_int(begin
, end
, handler
);
2293 if (begin
== end
|| (*begin
!= '}' && *begin
!= ':'))
2294 handler
.on_error("invalid format string");
2299 if (!is_name_start(c
)) {
2300 handler
.on_error("invalid format string");
2306 } while (it
!= end
&& (is_name_start(c
= *it
) || ('0' <= c
&& c
<= '9')));
2307 handler(basic_string_view
<Char
>(begin
, to_unsigned(it
- begin
)));
2311 // Adapts SpecHandler to IDHandler API for dynamic width.
2312 template <typename SpecHandler
, typename Char
> struct width_adapter
{
2313 explicit FMT_CONSTEXPR
width_adapter(SpecHandler
& h
) : handler(h
) {}
2315 FMT_CONSTEXPR
void operator()() { handler
.on_dynamic_width(auto_id()); }
2316 FMT_CONSTEXPR
void operator()(int id
) { handler
.on_dynamic_width(id
); }
2317 FMT_CONSTEXPR
void operator()(basic_string_view
<Char
> id
) {
2318 handler
.on_dynamic_width(id
);
2321 FMT_CONSTEXPR
void on_error(const char* message
) {
2322 handler
.on_error(message
);
2325 SpecHandler
& handler
;
2328 // Adapts SpecHandler to IDHandler API for dynamic precision.
2329 template <typename SpecHandler
, typename Char
> struct precision_adapter
{
2330 explicit FMT_CONSTEXPR
precision_adapter(SpecHandler
& h
) : handler(h
) {}
2332 FMT_CONSTEXPR
void operator()() { handler
.on_dynamic_precision(auto_id()); }
2333 FMT_CONSTEXPR
void operator()(int id
) { handler
.on_dynamic_precision(id
); }
2334 FMT_CONSTEXPR
void operator()(basic_string_view
<Char
> id
) {
2335 handler
.on_dynamic_precision(id
);
2338 FMT_CONSTEXPR
void on_error(const char* message
) {
2339 handler
.on_error(message
);
2342 SpecHandler
& handler
;
2345 template <typename Char
>
2346 FMT_CONSTEXPR
const Char
* next_code_point(const Char
* begin
, const Char
* end
) {
2347 if (const_check(sizeof(Char
) != 1) || (*begin
& 0x80) == 0) return begin
+ 1;
2350 } while (begin
!= end
&& (*begin
& 0xc0) == 0x80);
2354 // Parses fill and alignment.
2355 template <typename Char
, typename Handler
>
2356 FMT_CONSTEXPR
const Char
* parse_align(const Char
* begin
, const Char
* end
,
2357 Handler
&& handler
) {
2358 FMT_ASSERT(begin
!= end
, "");
2359 auto align
= align::none
;
2360 auto p
= next_code_point(begin
, end
);
2361 if (p
== end
) p
= begin
;
2363 switch (static_cast<char>(*p
)) {
2365 align
= align::left
;
2368 align
= align::right
;
2370 #if FMT_NUMERIC_ALIGN
2372 align
= align::numeric
;
2376 align
= align::center
;
2379 if (align
!= align::none
) {
2383 return handler
.on_error("invalid fill character '{'"), begin
;
2384 handler
.on_fill(basic_string_view
<Char
>(begin
, to_unsigned(p
- begin
)));
2388 handler
.on_align(align
);
2390 } else if (p
== begin
) {
2398 template <typename Char
, typename Handler
>
2399 FMT_CONSTEXPR
const Char
* parse_width(const Char
* begin
, const Char
* end
,
2400 Handler
&& handler
) {
2401 FMT_ASSERT(begin
!= end
, "");
2402 if ('0' <= *begin
&& *begin
<= '9') {
2403 handler
.on_width(parse_nonnegative_int(begin
, end
, handler
));
2404 } else if (*begin
== '{') {
2407 begin
= parse_arg_id(begin
, end
, width_adapter
<Handler
, Char
>(handler
));
2408 if (begin
== end
|| *begin
!= '}')
2409 return handler
.on_error("invalid format string"), begin
;
2415 template <typename Char
, typename Handler
>
2416 FMT_CONSTEXPR
const Char
* parse_precision(const Char
* begin
, const Char
* end
,
2417 Handler
&& handler
) {
2419 auto c
= begin
!= end
? *begin
: Char();
2420 if ('0' <= c
&& c
<= '9') {
2421 handler
.on_precision(parse_nonnegative_int(begin
, end
, handler
));
2422 } else if (c
== '{') {
2426 parse_arg_id(begin
, end
, precision_adapter
<Handler
, Char
>(handler
));
2428 if (begin
== end
|| *begin
++ != '}')
2429 return handler
.on_error("invalid format string"), begin
;
2431 return handler
.on_error("missing precision specifier"), begin
;
2433 handler
.end_precision();
2437 // Parses standard format specifiers and sends notifications about parsed
2438 // components to handler.
2439 template <typename Char
, typename SpecHandler
>
2440 FMT_CONSTEXPR
const Char
* parse_format_specs(const Char
* begin
, const Char
* end
,
2441 SpecHandler
&& handler
) {
2442 if (begin
== end
|| *begin
== '}') return begin
;
2444 begin
= parse_align(begin
, end
, handler
);
2445 if (begin
== end
) return begin
;
2448 switch (static_cast<char>(*begin
)) {
2462 if (begin
== end
) return begin
;
2464 if (*begin
== '#') {
2466 if (++begin
== end
) return begin
;
2470 if (*begin
== '0') {
2472 if (++begin
== end
) return begin
;
2475 begin
= parse_width(begin
, end
, handler
);
2476 if (begin
== end
) return begin
;
2479 if (*begin
== '.') {
2480 begin
= parse_precision(begin
, end
, handler
);
2484 if (begin
!= end
&& *begin
!= '}') handler
.on_type(*begin
++);
2488 // Return the result via the out param to workaround gcc bug 77539.
2489 template <bool IS_CONSTEXPR
, typename T
, typename Ptr
= const T
*>
2490 FMT_CONSTEXPR
bool find(Ptr first
, Ptr last
, T value
, Ptr
& out
) {
2491 for (out
= first
; out
!= last
; ++out
) {
2492 if (*out
== value
) return true;
2498 inline bool find
<false, char>(const char* first
, const char* last
, char value
,
2500 out
= static_cast<const char*>(
2501 std::memchr(first
, value
, detail::to_unsigned(last
- first
)));
2502 return out
!= nullptr;
2505 template <typename Handler
, typename Char
> struct id_adapter
{
2506 FMT_CONSTEXPR
void operator()() { handler
.on_arg_id(); }
2507 FMT_CONSTEXPR
void operator()(int id
) { handler
.on_arg_id(id
); }
2508 FMT_CONSTEXPR
void operator()(basic_string_view
<Char
> id
) {
2509 handler
.on_arg_id(id
);
2511 FMT_CONSTEXPR
void on_error(const char* message
) {
2512 handler
.on_error(message
);
2517 template <bool IS_CONSTEXPR
, typename Char
, typename Handler
>
2518 FMT_CONSTEXPR
void parse_format_string(basic_string_view
<Char
> format_str
,
2519 Handler
&& handler
) {
2521 FMT_CONSTEXPR
void operator()(const Char
* begin
, const Char
* end
) {
2522 if (begin
== end
) return;
2524 const Char
* p
= nullptr;
2525 if (!find
<IS_CONSTEXPR
>(begin
, end
, '}', p
))
2526 return handler_
.on_text(begin
, end
);
2528 if (p
== end
|| *p
!= '}')
2529 return handler_
.on_error("unmatched '}' in format string");
2530 handler_
.on_text(begin
, p
);
2536 auto begin
= format_str
.data();
2537 auto end
= begin
+ format_str
.size();
2538 while (begin
!= end
) {
2539 // Doing two passes with memchr (one for '{' and another for '}') is up to
2540 // 2.5x faster than the naive one-pass implementation on big format strings.
2541 const Char
* p
= begin
;
2542 if (*begin
!= '{' && !find
<IS_CONSTEXPR
>(begin
+ 1, end
, '{', p
))
2543 return write(begin
, end
);
2546 if (p
== end
) return handler
.on_error("invalid format string");
2547 if (static_cast<char>(*p
) == '}') {
2548 handler
.on_arg_id();
2549 handler
.on_replacement_field(p
);
2550 } else if (*p
== '{') {
2551 handler
.on_text(p
, p
+ 1);
2553 p
= parse_arg_id(p
, end
, id_adapter
<Handler
, Char
>{handler
});
2554 Char c
= p
!= end
? *p
: Char();
2556 handler
.on_replacement_field(p
);
2557 } else if (c
== ':') {
2558 p
= handler
.on_format_specs(p
+ 1, end
);
2559 if (p
== end
|| *p
!= '}')
2560 return handler
.on_error("unknown format specifier");
2562 return handler
.on_error("missing '}' in format string");
2569 template <typename T
, typename ParseContext
>
2570 FMT_CONSTEXPR
const typename
ParseContext::char_type
* parse_format_specs(
2571 ParseContext
& ctx
) {
2572 using char_type
= typename
ParseContext::char_type
;
2573 using context
= buffer_context
<char_type
>;
2575 conditional_t
<detail::mapped_type_constant
<T
, context
>::value
!=
2577 decltype(arg_mapper
<context
>().map(std::declval
<T
>())), T
>;
2578 auto f
= conditional_t
<has_formatter
<mapped_type
, context
>::value
,
2579 formatter
<mapped_type
, char_type
>,
2580 detail::fallback_formatter
<T
, char_type
>>();
2581 return f
.parse(ctx
);
2584 // A parse context with extra argument id checks. It is only used at compile
2585 // time because adding checks at runtime would introduce substantial overhead
2586 // and would be redundant since argument ids are checked when arguments are
2587 // retrieved anyway.
2588 template <typename Char
, typename ErrorHandler
= error_handler
>
2589 class compile_parse_context
2590 : public basic_format_parse_context
<Char
, ErrorHandler
> {
2593 using base
= basic_format_parse_context
<Char
, ErrorHandler
>;
2596 explicit FMT_CONSTEXPR
compile_parse_context(
2597 basic_string_view
<Char
> format_str
, int num_args
= max_value
<int>(),
2598 ErrorHandler eh
= {})
2599 : base(format_str
, eh
), num_args_(num_args
) {}
2601 FMT_CONSTEXPR
int next_arg_id() {
2602 int id
= base::next_arg_id();
2603 if (id
>= num_args_
) this->on_error("argument not found");
2607 FMT_CONSTEXPR
void check_arg_id(int id
) {
2608 base::check_arg_id(id
);
2609 if (id
>= num_args_
) this->on_error("argument not found");
2611 using base::check_arg_id
;
2614 template <typename Char
, typename ErrorHandler
, typename
... Args
>
2615 class format_string_checker
{
2617 explicit FMT_CONSTEXPR
format_string_checker(
2618 basic_string_view
<Char
> format_str
, ErrorHandler eh
)
2620 context_(format_str
, num_args
, eh
),
2621 parse_funcs_
{&parse_format_specs
<Args
, parse_context_type
>...} {}
2623 FMT_CONSTEXPR
void on_text(const Char
*, const Char
*) {}
2625 FMT_CONSTEXPR
void on_arg_id() { arg_id_
= context_
.next_arg_id(); }
2626 FMT_CONSTEXPR
void on_arg_id(int id
) {
2628 context_
.check_arg_id(id
);
2630 FMT_CONSTEXPR
void on_arg_id(basic_string_view
<Char
>) {
2631 on_error("compile-time checks don't support named arguments");
2634 FMT_CONSTEXPR
void on_replacement_field(const Char
*) {}
2636 FMT_CONSTEXPR
const Char
* on_format_specs(const Char
* begin
, const Char
*) {
2637 advance_to(context_
, begin
);
2638 return arg_id_
< num_args
? parse_funcs_
[arg_id_
](context_
) : begin
;
2641 FMT_CONSTEXPR
void on_error(const char* message
) {
2642 context_
.on_error(message
);
2646 using parse_context_type
= compile_parse_context
<Char
, ErrorHandler
>;
2647 enum { num_args
= sizeof...(Args
) };
2649 // Format specifier parsing function.
2650 using parse_func
= const Char
* (*)(parse_context_type
&);
2653 parse_context_type context_
;
2654 parse_func parse_funcs_
[num_args
> 0 ? num_args
: 1];
2657 // Converts string literals to basic_string_view.
2658 template <typename Char
, size_t N
>
2659 FMT_CONSTEXPR basic_string_view
<Char
> compile_string_to_view(
2660 const Char (&s
)[N
]) {
2661 // Remove trailing null character if needed. Won't be present if this is used
2662 // with raw character array (i.e. not defined as a string).
2664 N
- ((std::char_traits
<Char
>::to_int_type(s
[N
- 1]) == 0) ? 1 : 0)};
2667 // Converts string_view to basic_string_view.
2668 template <typename Char
>
2669 FMT_CONSTEXPR basic_string_view
<Char
> compile_string_to_view(
2670 const std_string_view
<Char
>& s
) {
2671 return {s
.data(), s
.size()};
2674 #define FMT_STRING_IMPL(s, ...) \
2676 /* Use a macro-like name to avoid shadowing warnings. */ \
2677 struct FMT_COMPILE_STRING : fmt::compile_string { \
2678 using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
2679 FMT_MAYBE_UNUSED __VA_ARGS__ FMT_CONSTEXPR \
2680 operator fmt::basic_string_view<char_type>() const { \
2681 return fmt::detail::compile_string_to_view<char_type>(s); \
2684 return FMT_COMPILE_STRING(); \
2689 Constructs a compile-time format string from a string literal *s*.
2693 // A compile-time error because 'd' is an invalid specifier for strings.
2694 std::string s = format(FMT_STRING("{:d}"), "foo");
2697 #define FMT_STRING(s) FMT_STRING_IMPL(s, )
2699 template <typename
... Args
, typename S
,
2700 enable_if_t
<(is_compile_string
<S
>::value
), int>>
2701 void check_format_string(S format_str
) {
2702 FMT_CONSTEXPR_DECL
auto s
= to_string_view(format_str
);
2703 using checker
= format_string_checker
<typename
S::char_type
, error_handler
,
2704 remove_cvref_t
<Args
>...>;
2705 FMT_CONSTEXPR_DECL
bool invalid_format
=
2706 (parse_format_string
<true>(s
, checker(s
, {})), true);
2707 (void)invalid_format
;
2710 template <template <typename
> class Handler
, typename Context
>
2711 void handle_dynamic_spec(int& value
, arg_ref
<typename
Context::char_type
> ref
,
2714 case arg_id_kind::none
:
2716 case arg_id_kind::index
:
2717 value
= detail::get_dynamic_spec
<Handler
>(ctx
.arg(ref
.val
.index
),
2718 ctx
.error_handler());
2720 case arg_id_kind::name
:
2721 value
= detail::get_dynamic_spec
<Handler
>(ctx
.arg(ref
.val
.name
),
2722 ctx
.error_handler());
2727 using format_func
= void (*)(detail::buffer
<char>&, int, string_view
);
2729 FMT_API
void format_error_code(buffer
<char>& out
, int error_code
,
2730 string_view message
) FMT_NOEXCEPT
;
2732 FMT_API
void report_error(format_func func
, int error_code
,
2733 string_view message
) FMT_NOEXCEPT
;
2734 } // namespace detail
2736 /** The default argument formatter. */
2737 template <typename Range
>
2738 class arg_formatter
: public detail::arg_formatter_base
<Range
> {
2740 using char_type
= typename
Range::value_type
;
2741 using base
= detail::arg_formatter_base
<Range
>;
2742 using context_type
= basic_format_context
<typename
base::iterator
, char_type
>;
2745 basic_format_parse_context
<char_type
>* parse_ctx_
;
2748 using range
= Range
;
2749 using iterator
= typename
base::iterator
;
2750 using format_specs
= typename
base::format_specs
;
2754 Constructs an argument formatter object.
2755 *ctx* is a reference to the formatting context,
2756 *specs* contains format specifier information for standard argument types.
2759 explicit arg_formatter(
2761 basic_format_parse_context
<char_type
>* parse_ctx
= nullptr,
2762 format_specs
* specs
= nullptr)
2763 : base(Range(ctx
.out()), specs
, ctx
.locale()),
2765 parse_ctx_(parse_ctx
) {}
2767 using base::operator();
2769 /** Formats an argument of a user-defined type. */
2770 iterator
operator()(typename basic_format_arg
<context_type
>::handle handle
) {
2771 handle
.format(*parse_ctx_
, ctx_
);
2777 An error returned by an operating system or a language runtime,
2778 for example a file opening error.
2781 class FMT_API system_error
: public std::runtime_error
{
2783 void init(int err_code
, string_view format_str
, format_args args
);
2788 system_error() : std::runtime_error(""), error_code_(0) {}
2793 Constructs a :class:`fmt::system_error` object with a description
2794 formatted with `fmt::format_system_error`. *message* and additional
2795 arguments passed into the constructor are formatted similarly to
2800 // This throws a system_error with the description
2801 // cannot open file 'madeup': No such file or directory
2802 // or similar (system message may vary).
2803 const char *filename = "madeup";
2804 std::FILE *file = std::fopen(filename, "r");
2806 throw fmt::system_error(errno, "cannot open file '{}'", filename);
2809 template <typename
... Args
>
2810 system_error(int error_code
, string_view message
, const Args
&... args
)
2811 : std::runtime_error("") {
2812 init(error_code
, message
, make_format_args(args
...));
2814 system_error(const system_error
&) = default;
2815 system_error
& operator=(const system_error
&) = default;
2816 system_error(system_error
&&) = default;
2817 system_error
& operator=(system_error
&&) = default;
2818 ~system_error() FMT_NOEXCEPT FMT_OVERRIDE
;
2820 int error_code() const { return error_code_
; }
2825 Formats an error returned by an operating system or a language runtime,
2826 for example a file opening error, and writes it to *out* in the following
2830 *<message>*: *<system-message>*
2832 where *<message>* is the passed message and *<system-message>* is
2833 the system message corresponding to the error code.
2834 *error_code* is a system error code as given by ``errno``.
2835 If *error_code* is not a valid error code such as -1, the system message
2836 may look like "Unknown error -1" and is platform-dependent.
2839 FMT_API
void format_system_error(detail::buffer
<char>& out
, int error_code
,
2840 string_view message
) FMT_NOEXCEPT
;
2842 // Reports a system error without throwing an exception.
2843 // Can be used to report errors from destructors.
2844 FMT_API
void report_system_error(int error_code
,
2845 string_view message
) FMT_NOEXCEPT
;
2847 /** Fast integer formatter. */
2850 // Buffer should be large enough to hold all digits (digits10 + 1),
2851 // a sign and a null character.
2852 enum { buffer_size
= std::numeric_limits
<unsigned long long>::digits10
+ 3 };
2853 mutable char buffer_
[buffer_size
];
2856 // Formats value in reverse and returns a pointer to the beginning.
2857 char* format_decimal(unsigned long long value
) {
2858 char* ptr
= buffer_
+ (buffer_size
- 1); // Parens to workaround MSVC bug.
2859 while (value
>= 100) {
2860 // Integer division is slow so do it for a group of two digits instead
2861 // of for every digit. The idea comes from the talk by Alexandrescu
2862 // "Three Optimization Tips for C++". See speed-test for a comparison.
2863 auto index
= static_cast<unsigned>((value
% 100) * 2);
2865 *--ptr
= detail::data::digits
[index
+ 1];
2866 *--ptr
= detail::data::digits
[index
];
2869 *--ptr
= static_cast<char>('0' + value
);
2872 auto index
= static_cast<unsigned>(value
* 2);
2873 *--ptr
= detail::data::digits
[index
+ 1];
2874 *--ptr
= detail::data::digits
[index
];
2878 void format_signed(long long value
) {
2879 auto abs_value
= static_cast<unsigned long long>(value
);
2880 bool negative
= value
< 0;
2881 if (negative
) abs_value
= 0 - abs_value
;
2882 str_
= format_decimal(abs_value
);
2883 if (negative
) *--str_
= '-';
2887 explicit format_int(int value
) { format_signed(value
); }
2888 explicit format_int(long value
) { format_signed(value
); }
2889 explicit format_int(long long value
) { format_signed(value
); }
2890 explicit format_int(unsigned value
) : str_(format_decimal(value
)) {}
2891 explicit format_int(unsigned long value
) : str_(format_decimal(value
)) {}
2892 explicit format_int(unsigned long long value
) : str_(format_decimal(value
)) {}
2894 /** Returns the number of characters written to the output buffer. */
2895 size_t size() const {
2896 return detail::to_unsigned(buffer_
- str_
+ buffer_size
- 1);
2900 Returns a pointer to the output buffer content. No terminating null
2901 character is appended.
2903 const char* data() const { return str_
; }
2906 Returns a pointer to the output buffer content with terminating null
2909 const char* c_str() const {
2910 buffer_
[buffer_size
- 1] = '\0';
2916 Returns the content of the output buffer as an ``std::string``.
2919 std::string
str() const { return std::string(str_
, size()); }
2922 // A formatter specialization for the core types corresponding to detail::type
2924 template <typename T
, typename Char
>
2925 struct formatter
<T
, Char
,
2926 enable_if_t
<detail::type_constant
<T
, Char
>::value
!=
2927 detail::type::custom_type
>> {
2928 FMT_CONSTEXPR
formatter() = default;
2930 // Parses format specifiers stopping either at the end of the range or at the
2932 template <typename ParseContext
>
2933 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> decltype(ctx
.begin()) {
2934 using handler_type
= detail::dynamic_specs_handler
<ParseContext
>;
2935 auto type
= detail::type_constant
<T
, Char
>::value
;
2936 detail::specs_checker
<handler_type
> handler(handler_type(specs_
, ctx
),
2938 auto it
= parse_format_specs(ctx
.begin(), ctx
.end(), handler
);
2939 auto eh
= ctx
.error_handler();
2941 case detail::type::none_type
:
2942 FMT_ASSERT(false, "invalid argument type");
2944 case detail::type::int_type
:
2945 case detail::type::uint_type
:
2946 case detail::type::long_long_type
:
2947 case detail::type::ulong_long_type
:
2948 case detail::type::int128_type
:
2949 case detail::type::uint128_type
:
2950 case detail::type::bool_type
:
2951 handle_int_type_spec(specs_
.type
,
2952 detail::int_type_checker
<decltype(eh
)>(eh
));
2954 case detail::type::char_type
:
2956 &specs_
, detail::char_specs_checker
<decltype(eh
)>(specs_
.type
, eh
));
2958 case detail::type::float_type
:
2959 if (detail::const_check(FMT_USE_FLOAT
))
2960 detail::parse_float_type_spec(specs_
, eh
);
2962 FMT_ASSERT(false, "float support disabled");
2964 case detail::type::double_type
:
2965 if (detail::const_check(FMT_USE_DOUBLE
))
2966 detail::parse_float_type_spec(specs_
, eh
);
2968 FMT_ASSERT(false, "double support disabled");
2970 case detail::type::long_double_type
:
2971 if (detail::const_check(FMT_USE_LONG_DOUBLE
))
2972 detail::parse_float_type_spec(specs_
, eh
);
2974 FMT_ASSERT(false, "long double support disabled");
2976 case detail::type::cstring_type
:
2977 detail::handle_cstring_type_spec(
2978 specs_
.type
, detail::cstring_type_checker
<decltype(eh
)>(eh
));
2980 case detail::type::string_type
:
2981 detail::check_string_type_spec(specs_
.type
, eh
);
2983 case detail::type::pointer_type
:
2984 detail::check_pointer_type_spec(specs_
.type
, eh
);
2986 case detail::type::custom_type
:
2987 // Custom format specifiers should be checked in parse functions of
2988 // formatter specializations.
2994 template <typename FormatContext
>
2995 auto format(const T
& val
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
2996 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
2997 specs_
.width_ref
, ctx
);
2998 detail::handle_dynamic_spec
<detail::precision_checker
>(
2999 specs_
.precision
, specs_
.precision_ref
, ctx
);
3000 using range_type
= detail::output_range
<typename
FormatContext::iterator
,
3001 typename
FormatContext::char_type
>;
3002 return visit_format_arg(arg_formatter
<range_type
>(ctx
, nullptr, &specs_
),
3003 detail::make_arg
<FormatContext
>(val
));
3007 detail::dynamic_format_specs
<Char
> specs_
;
3010 #define FMT_FORMAT_AS(Type, Base) \
3011 template <typename Char> \
3012 struct formatter<Type, Char> : formatter<Base, Char> { \
3013 template <typename FormatContext> \
3014 auto format(Type const& val, FormatContext& ctx) -> decltype(ctx.out()) { \
3015 return formatter<Base, Char>::format(val, ctx); \
3019 FMT_FORMAT_AS(signed char, int);
3020 FMT_FORMAT_AS(unsigned char, unsigned);
3021 FMT_FORMAT_AS(short, int);
3022 FMT_FORMAT_AS(unsigned short, unsigned);
3023 FMT_FORMAT_AS(long, long long);
3024 FMT_FORMAT_AS(unsigned long, unsigned long long);
3025 FMT_FORMAT_AS(Char
*, const Char
*);
3026 FMT_FORMAT_AS(std::basic_string
<Char
>, basic_string_view
<Char
>);
3027 FMT_FORMAT_AS(std::nullptr_t
, const void*);
3028 FMT_FORMAT_AS(detail::std_string_view
<Char
>, basic_string_view
<Char
>);
3030 template <typename Char
>
3031 struct formatter
<void*, Char
> : formatter
<const void*, Char
> {
3032 template <typename FormatContext
>
3033 auto format(void* val
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
3034 return formatter
<const void*, Char
>::format(val
, ctx
);
3038 template <typename Char
, size_t N
>
3039 struct formatter
<Char
[N
], Char
> : formatter
<basic_string_view
<Char
>, Char
> {
3040 template <typename FormatContext
>
3041 auto format(const Char
* val
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
3042 return formatter
<basic_string_view
<Char
>, Char
>::format(val
, ctx
);
3046 // A formatter for types known only at run time such as variant alternatives.
3049 // using variant = std::variant<int, std::string>;
3051 // struct formatter<variant>: dynamic_formatter<> {
3052 // void format(buffer &buf, const variant &v, context &ctx) {
3053 // visit([&](const auto &val) { format(buf, val, ctx); }, v);
3056 template <typename Char
= char> class dynamic_formatter
{
3058 struct null_handler
: detail::error_handler
{
3059 void on_align(align_t
) {}
3067 template <typename ParseContext
>
3068 auto parse(ParseContext
& ctx
) -> decltype(ctx
.begin()) {
3069 format_str_
= ctx
.begin();
3070 // Checks are deferred to formatting time when the argument type is known.
3071 detail::dynamic_specs_handler
<ParseContext
> handler(specs_
, ctx
);
3072 return parse_format_specs(ctx
.begin(), ctx
.end(), handler
);
3075 template <typename T
, typename FormatContext
>
3076 auto format(const T
& val
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
3078 detail::specs_checker
<null_handler
> checker(
3079 null_handler(), detail::mapped_type_constant
<T
, FormatContext
>::value
);
3080 checker
.on_align(specs_
.align
);
3081 switch (specs_
.sign
) {
3094 if (specs_
.alt
) checker
.on_hash();
3095 if (specs_
.precision
>= 0) checker
.end_precision();
3096 using range
= detail::output_range
<typename
FormatContext::iterator
,
3097 typename
FormatContext::char_type
>;
3098 visit_format_arg(arg_formatter
<range
>(ctx
, nullptr, &specs_
),
3099 detail::make_arg
<FormatContext
>(val
));
3104 template <typename Context
> void handle_specs(Context
& ctx
) {
3105 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
3106 specs_
.width_ref
, ctx
);
3107 detail::handle_dynamic_spec
<detail::precision_checker
>(
3108 specs_
.precision
, specs_
.precision_ref
, ctx
);
3111 detail::dynamic_format_specs
<Char
> specs_
;
3112 const Char
* format_str_
;
3115 template <typename Char
, typename ErrorHandler
>
3116 FMT_CONSTEXPR
void advance_to(
3117 basic_format_parse_context
<Char
, ErrorHandler
>& ctx
, const Char
* p
) {
3118 ctx
.advance_to(ctx
.begin() + (p
- &*ctx
.begin()));
3121 template <typename ArgFormatter
, typename Char
, typename Context
>
3122 struct format_handler
: detail::error_handler
{
3123 using range
= typename
ArgFormatter::range
;
3125 format_handler(range r
, basic_string_view
<Char
> str
,
3126 basic_format_args
<Context
> format_args
, detail::locale_ref loc
)
3127 : parse_context(str
), context(r
.begin(), format_args
, loc
) {}
3129 void on_text(const Char
* begin
, const Char
* end
) {
3130 auto size
= detail::to_unsigned(end
- begin
);
3131 auto out
= context
.out();
3132 auto&& it
= detail::reserve(out
, size
);
3133 it
= std::copy_n(begin
, size
, it
);
3134 context
.advance_to(out
);
3137 template <typename ID
> void get_arg(ID id
) {
3138 arg
= detail::get_arg(context
, id
);
3141 void on_arg_id() { get_arg(parse_context
.next_arg_id()); }
3142 void on_arg_id(int id
) {
3143 parse_context
.check_arg_id(id
);
3146 void on_arg_id(basic_string_view
<Char
> id
) { get_arg(id
); }
3148 void on_replacement_field(const Char
* p
) {
3149 advance_to(parse_context
, p
);
3151 visit_format_arg(ArgFormatter(context
, &parse_context
), arg
));
3154 const Char
* on_format_specs(const Char
* begin
, const Char
* end
) {
3155 advance_to(parse_context
, begin
);
3156 detail::custom_formatter
<Context
> f(parse_context
, context
);
3157 if (visit_format_arg(f
, arg
)) return parse_context
.begin();
3158 basic_format_specs
<Char
> specs
;
3159 using detail::specs_handler
;
3160 using parse_context_t
= basic_format_parse_context
<Char
>;
3161 detail::specs_checker
<specs_handler
<parse_context_t
, Context
>> handler(
3162 specs_handler
<parse_context_t
, Context
>(specs
, parse_context
, context
),
3164 begin
= parse_format_specs(begin
, end
, handler
);
3165 if (begin
== end
|| *begin
!= '}') on_error("missing '}' in format string");
3166 advance_to(parse_context
, begin
);
3168 visit_format_arg(ArgFormatter(context
, &parse_context
, &specs
), arg
));
3172 basic_format_parse_context
<Char
> parse_context
;
3174 basic_format_arg
<Context
> arg
;
3177 /** Formats arguments and writes the output to the range. */
3178 template <typename ArgFormatter
, typename Char
, typename Context
>
3179 typename
Context::iterator
vformat_to(
3180 typename
ArgFormatter::range out
, basic_string_view
<Char
> format_str
,
3181 basic_format_args
<Context
> args
,
3182 detail::locale_ref loc
= detail::locale_ref()) {
3183 format_handler
<ArgFormatter
, Char
, Context
> h(out
, format_str
, args
, loc
);
3184 if (format_str
.size() == 2 && format_str
[0] == '{' && format_str
[1] == '}') {
3185 auto arg
= detail::get_arg(h
.context
, 0);
3186 h
.parse_context
.advance_to(&format_str
[1]);
3187 return visit_format_arg(ArgFormatter(h
.context
, &h
.parse_context
), arg
);
3189 detail::parse_format_string
<false>(format_str
, h
);
3190 return h
.context
.out();
3193 // Casts ``p`` to ``const void*`` for pointer formatting.
3195 // auto s = format("{}", ptr(p));
3196 template <typename T
> inline const void* ptr(const T
* p
) { return p
; }
3197 template <typename T
> inline const void* ptr(const std::unique_ptr
<T
>& p
) {
3200 template <typename T
> inline const void* ptr(const std::shared_ptr
<T
>& p
) {
3207 friend struct formatter
<bytes
>;
3210 explicit bytes(string_view data
) : data_(data
) {}
3213 template <> struct formatter
<bytes
> {
3214 template <typename ParseContext
>
3215 FMT_CONSTEXPR
auto parse(ParseContext
& ctx
) -> decltype(ctx
.begin()) {
3216 using handler_type
= detail::dynamic_specs_handler
<ParseContext
>;
3217 detail::specs_checker
<handler_type
> handler(handler_type(specs_
, ctx
),
3218 detail::type::string_type
);
3219 auto it
= parse_format_specs(ctx
.begin(), ctx
.end(), handler
);
3220 detail::check_string_type_spec(specs_
.type
, ctx
.error_handler());
3224 template <typename FormatContext
>
3225 auto format(bytes b
, FormatContext
& ctx
) -> decltype(ctx
.out()) {
3226 detail::handle_dynamic_spec
<detail::width_checker
>(specs_
.width
,
3227 specs_
.width_ref
, ctx
);
3228 detail::handle_dynamic_spec
<detail::precision_checker
>(
3229 specs_
.precision
, specs_
.precision_ref
, ctx
);
3230 return detail::write_bytes(ctx
.out(), b
.data_
, specs_
);
3234 detail::dynamic_format_specs
<char> specs_
;
3237 template <typename It
, typename Sentinel
, typename Char
>
3238 struct arg_join
: detail::view
{
3241 basic_string_view
<Char
> sep
;
3243 arg_join(It b
, Sentinel e
, basic_string_view
<Char
> s
)
3244 : begin(b
), end(e
), sep(s
) {}
3247 template <typename It
, typename Sentinel
, typename Char
>
3248 struct formatter
<arg_join
<It
, Sentinel
, Char
>, Char
>
3249 : formatter
<typename
std::iterator_traits
<It
>::value_type
, Char
> {
3250 template <typename FormatContext
>
3251 auto format(const arg_join
<It
, Sentinel
, Char
>& value
, FormatContext
& ctx
)
3252 -> decltype(ctx
.out()) {
3253 using base
= formatter
<typename
std::iterator_traits
<It
>::value_type
, Char
>;
3254 auto it
= value
.begin
;
3255 auto out
= ctx
.out();
3256 if (it
!= value
.end
) {
3257 out
= base::format(*it
++, ctx
);
3258 while (it
!= value
.end
) {
3259 out
= std::copy(value
.sep
.begin(), value
.sep
.end(), out
);
3260 ctx
.advance_to(out
);
3261 out
= base::format(*it
++, ctx
);
3269 Returns an object that formats the iterator range `[begin, end)` with elements
3272 template <typename It
, typename Sentinel
>
3273 arg_join
<It
, Sentinel
, char> join(It begin
, Sentinel end
, string_view sep
) {
3274 return {begin
, end
, sep
};
3277 template <typename It
, typename Sentinel
>
3278 arg_join
<It
, Sentinel
, wchar_t> join(It begin
, Sentinel end
, wstring_view sep
) {
3279 return {begin
, end
, sep
};
3284 Returns an object that formats `range` with elements separated by `sep`.
3288 std::vector<int> v = {1, 2, 3};
3289 fmt::print("{}", fmt::join(v, ", "));
3290 // Output: "1, 2, 3"
3292 ``fmt::join`` applies passed format specifiers to the range elements::
3294 fmt::print("{:02}", fmt::join(v, ", "));
3295 // Output: "01, 02, 03"
3298 template <typename Range
>
3299 arg_join
<detail::iterator_t
<const Range
>, detail::sentinel_t
<const Range
>, char>
3300 join(const Range
& range
, string_view sep
) {
3301 return join(std::begin(range
), std::end(range
), sep
);
3304 template <typename Range
>
3305 arg_join
<detail::iterator_t
<const Range
>, detail::sentinel_t
<const Range
>,
3307 join(const Range
& range
, wstring_view sep
) {
3308 return join(std::begin(range
), std::end(range
), sep
);
3313 Converts *value* to ``std::string`` using the default format for type *T*.
3317 #include <fmt/format.h>
3319 std::string answer = fmt::to_string(42);
3322 template <typename T
> inline std::string
to_string(const T
& value
) {
3323 return format("{}", value
);
3327 Converts *value* to ``std::wstring`` using the default format for type *T*.
3329 template <typename T
> inline std::wstring
to_wstring(const T
& value
) {
3330 return format(L
"{}", value
);
3333 template <typename Char
, size_t SIZE
>
3334 std::basic_string
<Char
> to_string(const basic_memory_buffer
<Char
, SIZE
>& buf
) {
3335 auto size
= buf
.size();
3336 detail::assume(size
< std::basic_string
<Char
>().max_size());
3337 return std::basic_string
<Char
>(buf
.data(), size
);
3340 template <typename Char
>
3341 typename buffer_context
<Char
>::iterator
detail::vformat_to(
3342 detail::buffer
<Char
>& buf
, basic_string_view
<Char
> format_str
,
3343 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
3344 using range
= buffer_range
<Char
>;
3345 return vformat_to
<arg_formatter
<range
>>(buf
, to_string_view(format_str
),
3349 #ifndef FMT_HEADER_ONLY
3350 extern template format_context::iterator
detail::vformat_to(
3351 detail::buffer
<char>&, string_view
, basic_format_args
<format_context
>);
3353 extern template FMT_API
std::string grouping_impl
<char>(locale_ref loc
);
3354 extern template FMT_API
std::string grouping_impl
<wchar_t>(locale_ref loc
);
3355 extern template FMT_API
char thousands_sep_impl
<char>(locale_ref loc
);
3356 extern template FMT_API
wchar_t thousands_sep_impl
<wchar_t>(locale_ref loc
);
3357 extern template FMT_API
char decimal_point_impl(locale_ref loc
);
3358 extern template FMT_API
wchar_t decimal_point_impl(locale_ref loc
);
3359 extern template int format_float
<double>(double value
, int precision
,
3360 float_specs specs
, buffer
<char>& buf
);
3361 extern template int format_float
<long double>(long double value
, int precision
,
3364 int snprintf_float(float value
, int precision
, float_specs specs
,
3365 buffer
<char>& buf
) = delete;
3366 extern template int snprintf_float
<double>(double value
, int precision
,
3369 extern template int snprintf_float
<long double>(long double value
,
3373 } // namespace detail
3376 template <typename S
, typename Char
= char_t
<S
>,
3377 FMT_ENABLE_IF(detail::is_string
<S
>::value
)>
3378 inline typename buffer_context
<Char
>::iterator
vformat_to(
3379 detail::buffer
<Char
>& buf
, const S
& format_str
,
3380 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
3381 return detail::vformat_to(buf
, to_string_view(format_str
), args
);
3384 template <typename S
, typename
... Args
, size_t SIZE
= inline_buffer_size
,
3385 typename Char
= enable_if_t
<detail::is_string
<S
>::value
, char_t
<S
>>>
3386 inline typename buffer_context
<Char
>::iterator
format_to(
3387 basic_memory_buffer
<Char
, SIZE
>& buf
, const S
& format_str
, Args
&&... args
) {
3388 detail::check_format_string
<Args
...>(format_str
);
3389 using context
= buffer_context
<Char
>;
3390 return detail::vformat_to(buf
, to_string_view(format_str
),
3391 make_format_args
<context
>(args
...));
3394 template <typename OutputIt
, typename Char
= char>
3395 using format_context_t
= basic_format_context
<OutputIt
, Char
>;
3397 template <typename OutputIt
, typename Char
= char>
3398 using format_args_t
= basic_format_args
<format_context_t
<OutputIt
, Char
>>;
3401 typename S
, typename OutputIt
, typename
... Args
,
3402 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
>::value
&&
3403 !detail::is_contiguous_back_insert_iterator
<OutputIt
>::value
)>
3404 inline OutputIt
vformat_to(
3405 OutputIt out
, const S
& format_str
,
3406 format_args_t
<type_identity_t
<OutputIt
>, char_t
<S
>> args
) {
3407 using range
= detail::output_range
<OutputIt
, char_t
<S
>>;
3408 return vformat_to
<arg_formatter
<range
>>(range(out
),
3409 to_string_view(format_str
), args
);
3414 Formats arguments, writes the result to the output iterator ``out`` and returns
3415 the iterator past the end of the output range.
3419 std::vector<char> out;
3420 fmt::format_to(std::back_inserter(out), "{}", 42);
3423 template <typename OutputIt
, typename S
, typename
... Args
,
3425 detail::is_output_iterator
<OutputIt
>::value
&&
3426 !detail::is_contiguous_back_insert_iterator
<OutputIt
>::value
&&
3427 detail::is_string
<S
>::value
)>
3428 inline OutputIt
format_to(OutputIt out
, const S
& format_str
, Args
&&... args
) {
3429 detail::check_format_string
<Args
...>(format_str
);
3430 using context
= format_context_t
<OutputIt
, char_t
<S
>>;
3431 return vformat_to(out
, to_string_view(format_str
),
3432 make_format_args
<context
>(args
...));
3435 template <typename OutputIt
> struct format_to_n_result
{
3436 /** Iterator past the end of the output range. */
3438 /** Total (not truncated) output size. */
3442 template <typename OutputIt
, typename Char
= typename
OutputIt::value_type
>
3443 using format_to_n_context
=
3444 format_context_t
<detail::truncating_iterator
<OutputIt
>, Char
>;
3446 template <typename OutputIt
, typename Char
= typename
OutputIt::value_type
>
3447 using format_to_n_args
= basic_format_args
<format_to_n_context
<OutputIt
, Char
>>;
3449 template <typename OutputIt
, typename Char
, typename
... Args
>
3450 inline format_arg_store
<format_to_n_context
<OutputIt
, Char
>, Args
...>
3451 make_format_to_n_args(const Args
&... args
) {
3452 return format_arg_store
<format_to_n_context
<OutputIt
, Char
>, Args
...>(
3456 template <typename OutputIt
, typename Char
, typename
... Args
,
3457 FMT_ENABLE_IF(detail::is_output_iterator
<OutputIt
>::value
)>
3458 inline format_to_n_result
<OutputIt
> vformat_to_n(
3459 OutputIt out
, size_t n
, basic_string_view
<Char
> format_str
,
3460 format_to_n_args
<type_identity_t
<OutputIt
>, type_identity_t
<Char
>> args
) {
3461 auto it
= vformat_to(detail::truncating_iterator
<OutputIt
>(out
, n
),
3463 return {it
.base(), it
.count()};
3468 Formats arguments, writes up to ``n`` characters of the result to the output
3469 iterator ``out`` and returns the total output size and the iterator past the
3470 end of the output range.
3473 template <typename OutputIt
, typename S
, typename
... Args
,
3474 FMT_ENABLE_IF(detail::is_string
<S
>::value
&&
3475 detail::is_output_iterator
<OutputIt
>::value
)>
3476 inline format_to_n_result
<OutputIt
> format_to_n(OutputIt out
, size_t n
,
3477 const S
& format_str
,
3478 const Args
&... args
) {
3479 detail::check_format_string
<Args
...>(format_str
);
3480 using context
= format_to_n_context
<OutputIt
, char_t
<S
>>;
3481 return vformat_to_n(out
, n
, to_string_view(format_str
),
3482 make_format_args
<context
>(args
...));
3485 template <typename Char
>
3486 std::basic_string
<Char
> detail::vformat(
3487 basic_string_view
<Char
> format_str
,
3488 basic_format_args
<buffer_context
<type_identity_t
<Char
>>> args
) {
3489 basic_memory_buffer
<Char
> buffer
;
3490 detail::vformat_to(buffer
, format_str
, args
);
3491 return to_string(buffer
);
3495 Returns the number of characters in the output of
3496 ``format(format_str, args...)``.
3498 template <typename
... Args
>
3499 inline size_t formatted_size(string_view format_str
, const Args
&... args
) {
3500 return format_to(detail::counting_iterator(), format_str
, args
...).count();
3503 template <typename Char
, FMT_ENABLE_IF(std::is_same
<Char
, wchar_t>::value
)>
3504 void vprint(std::FILE* f
, basic_string_view
<Char
> format_str
,
3505 wformat_args args
) {
3506 wmemory_buffer buffer
;
3507 detail::vformat_to(buffer
, format_str
, args
);
3508 buffer
.push_back(L
'\0');
3509 if (std::fputws(buffer
.data(), f
) == -1)
3510 FMT_THROW(system_error(errno
, "cannot write to file"));
3513 template <typename Char
, FMT_ENABLE_IF(std::is_same
<Char
, wchar_t>::value
)>
3514 void vprint(basic_string_view
<Char
> format_str
, wformat_args args
) {
3515 vprint(stdout
, format_str
, args
);
3518 #if FMT_USE_USER_DEFINED_LITERALS
3521 # if FMT_USE_UDL_TEMPLATE
3522 template <typename Char
, Char
... CHARS
> class udl_formatter
{
3524 template <typename
... Args
>
3525 std::basic_string
<Char
> operator()(Args
&&... args
) const {
3526 static FMT_CONSTEXPR_DECL Char s
[] = {CHARS
..., '\0'};
3527 check_format_string
<remove_cvref_t
<Args
>...>(FMT_STRING(s
));
3528 return format(s
, std::forward
<Args
>(args
)...);
3532 template <typename Char
> struct udl_formatter
{
3533 basic_string_view
<Char
> str
;
3535 template <typename
... Args
>
3536 std::basic_string
<Char
> operator()(Args
&&... args
) const {
3537 return format(str
, std::forward
<Args
>(args
)...);
3540 # endif // FMT_USE_UDL_TEMPLATE
3542 template <typename Char
> struct udl_arg
{
3545 template <typename T
> named_arg
<Char
, T
> operator=(T
&& value
) const {
3546 return {str
, std::forward
<T
>(value
)};
3549 } // namespace detail
3551 inline namespace literals
{
3552 # if FMT_USE_UDL_TEMPLATE
3553 # pragma GCC diagnostic push
3554 # pragma GCC diagnostic ignored "-Wpedantic"
3555 # if FMT_CLANG_VERSION
3556 # pragma GCC diagnostic ignored "-Wgnu-string-literal-operator-template"
3558 template <typename Char
, Char
... CHARS
>
3559 FMT_CONSTEXPR
detail::udl_formatter
<Char
, CHARS
...> operator""_format() {
3562 # pragma GCC diagnostic pop
3566 User-defined literal equivalent of :func:`fmt::format`.
3570 using namespace fmt::literals;
3571 std::string message = "The answer is {}"_format(42);
3574 FMT_CONSTEXPR
detail::udl_formatter
<char> operator"" _format(const char* s
,
3578 FMT_CONSTEXPR
detail::udl_formatter
<wchar_t> operator"" _format(
3579 const wchar_t* s
, size_t n
) {
3582 # endif // FMT_USE_UDL_TEMPLATE
3586 User-defined literal equivalent of :func:`fmt::arg`.
3590 using namespace fmt::literals;
3591 fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
3594 FMT_CONSTEXPR
detail::udl_arg
<char> operator"" _a(const char* s
, size_t) {
3597 FMT_CONSTEXPR
detail::udl_arg
<wchar_t> operator"" _a(const wchar_t* s
, size_t) {
3600 } // namespace literals
3601 #endif // FMT_USE_USER_DEFINED_LITERALS
3604 #ifdef FMT_HEADER_ONLY
3605 # define FMT_FUNC inline
3606 # include "format-inl.h"
3611 #endif // FMT_FORMAT_H_