spdlog
Loading...
Searching...
No Matches
format.h
Go to the documentation of this file.
1/*
2 Formatting library for C++
3
4 Copyright (c) 2012 - present, Victor Zverovich
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 --- Optional exception to the license ---
26
27 As an exception, if, as a result of your compiling your source code, portions
28 of this Software are embedded into a machine-executable object form of such
29 source code, you may redistribute such embedded portions in such object form
30 without including the above copyright and permission notices.
31 */
32
33#ifndef FMT_FORMAT_H_
34#define FMT_FORMAT_H_
35
36#include <cmath> // std::signbit
37#include <cstdint> // uint32_t
38#include <limits> // std::numeric_limits
39#include <memory> // std::uninitialized_copy
40#include <stdexcept> // std::runtime_error
41#include <system_error> // std::system_error
42#include <utility> // std::swap
43
44#include "core.h"
45
46#ifdef __INTEL_COMPILER
47# define FMT_ICC_VERSION __INTEL_COMPILER
48#elif defined(__ICL)
49# define FMT_ICC_VERSION __ICL
50#else
51# define FMT_ICC_VERSION 0
52#endif
53
54#ifdef __NVCC__
55# define FMT_CUDA_VERSION (__CUDACC_VER_MAJOR__ * 100 + __CUDACC_VER_MINOR__)
56#else
57# define FMT_CUDA_VERSION 0
58#endif
59
60#ifdef __has_builtin
61# define FMT_HAS_BUILTIN(x) __has_builtin(x)
62#else
63# define FMT_HAS_BUILTIN(x) 0
64#endif
65
66#if FMT_GCC_VERSION || FMT_CLANG_VERSION
67# define FMT_NOINLINE __attribute__((noinline))
68#else
69# define FMT_NOINLINE
70#endif
71
72#if FMT_MSC_VER
73# define FMT_MSC_DEFAULT = default
74#else
75# define FMT_MSC_DEFAULT
76#endif
77
78#ifndef FMT_THROW
79# if FMT_EXCEPTIONS
80# if FMT_MSC_VER || FMT_NVCC
82namespace detail {
83template <typename Exception> inline void do_throw(const Exception& x) {
84 // Silence unreachable code warnings in MSVC and NVCC because these
85 // are nearly impossible to fix in a generic code.
86 volatile bool b = true;
87 if (b) throw x;
88}
89} // namespace detail
91# define FMT_THROW(x) detail::do_throw(x)
92# else
93# define FMT_THROW(x) throw x
94# endif
95# else
96# define FMT_THROW(x) \
97 do { \
98 FMT_ASSERT(false, (x).what()); \
99 } while (false)
100# endif
101#endif
102
103#if FMT_EXCEPTIONS
104# define FMT_TRY try
105# define FMT_CATCH(x) catch (x)
106#else
107# define FMT_TRY if (true)
108# define FMT_CATCH(x) if (false)
109#endif
110
111#ifndef FMT_DEPRECATED
112# if FMT_HAS_CPP14_ATTRIBUTE(deprecated) || FMT_MSC_VER >= 1900
113# define FMT_DEPRECATED [[deprecated]]
114# else
115# if (defined(__GNUC__) && !defined(__LCC__)) || defined(__clang__)
116# define FMT_DEPRECATED __attribute__((deprecated))
117# elif FMT_MSC_VER
118# define FMT_DEPRECATED __declspec(deprecated)
119# else
120# define FMT_DEPRECATED /* deprecated */
121# endif
122# endif
123#endif
124
125// Workaround broken [[deprecated]] in the Intel, PGI and NVCC compilers.
126#if FMT_ICC_VERSION || defined(__PGI) || FMT_NVCC
127# define FMT_DEPRECATED_ALIAS
128#else
129# define FMT_DEPRECATED_ALIAS FMT_DEPRECATED
130#endif
131
132#ifndef FMT_USE_USER_DEFINED_LITERALS
133// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs.
134# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 407 || \
135 FMT_MSC_VER >= 1900) && \
136 (!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480)
137# define FMT_USE_USER_DEFINED_LITERALS 1
138# else
139# define FMT_USE_USER_DEFINED_LITERALS 0
140# endif
141#endif
142
143// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of
144// integer formatter template instantiations to just one by only using the
145// largest integer type. This results in a reduction in binary size but will
146// cause a decrease in integer formatting performance.
147#if !defined(FMT_REDUCE_INT_INSTANTIATIONS)
148# define FMT_REDUCE_INT_INSTANTIATIONS 0
149#endif
150
151// __builtin_clz is broken in clang with Microsoft CodeGen:
152// https://github.com/fmtlib/fmt/issues/519
153#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clz)) && !FMT_MSC_VER
154# define FMT_BUILTIN_CLZ(n) __builtin_clz(n)
155#endif
156#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_clzll)) && !FMT_MSC_VER
157# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n)
158#endif
159#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctz))
160# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n)
161#endif
162#if (FMT_GCC_VERSION || FMT_HAS_BUILTIN(__builtin_ctzll))
163# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n)
164#endif
165
166#if FMT_MSC_VER
167# include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128
168#endif
169
170// Some compilers masquerade as both MSVC and GCC-likes or otherwise support
171// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the
172// MSVC intrinsics if the clz and clzll builtins are not available.
173#if FMT_MSC_VER && !defined(FMT_BUILTIN_CLZLL) && !defined(FMT_BUILTIN_CTZLL)
175namespace detail {
176// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning.
177# if !defined(__clang__)
178# pragma managed(push, off)
179# pragma intrinsic(_BitScanForward)
180# pragma intrinsic(_BitScanReverse)
181# if defined(_WIN64)
182# pragma intrinsic(_BitScanForward64)
183# pragma intrinsic(_BitScanReverse64)
184# endif
185# endif
186
187inline auto clz(uint32_t x) -> int {
188 unsigned long r = 0;
189 _BitScanReverse(&r, x);
190 FMT_ASSERT(x != 0, "");
191 // Static analysis complains about using uninitialized data
192 // "r", but the only way that can happen is if "x" is 0,
193 // which the callers guarantee to not happen.
194 FMT_MSC_WARNING(suppress : 6102)
195 return 31 ^ static_cast<int>(r);
196}
197# define FMT_BUILTIN_CLZ(n) detail::clz(n)
198
199inline auto clzll(uint64_t x) -> int {
200 unsigned long r = 0;
201# ifdef _WIN64
202 _BitScanReverse64(&r, x);
203# else
204 // Scan the high 32 bits.
205 if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) return 63 ^ (r + 32);
206 // Scan the low 32 bits.
207 _BitScanReverse(&r, static_cast<uint32_t>(x));
208# endif
209 FMT_ASSERT(x != 0, "");
210 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
211 return 63 ^ static_cast<int>(r);
212}
213# define FMT_BUILTIN_CLZLL(n) detail::clzll(n)
214
215inline auto ctz(uint32_t x) -> int {
216 unsigned long r = 0;
217 _BitScanForward(&r, x);
218 FMT_ASSERT(x != 0, "");
219 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
220 return static_cast<int>(r);
221}
222# define FMT_BUILTIN_CTZ(n) detail::ctz(n)
223
224inline auto ctzll(uint64_t x) -> int {
225 unsigned long r = 0;
226 FMT_ASSERT(x != 0, "");
227 FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning.
228# ifdef _WIN64
229 _BitScanForward64(&r, x);
230# else
231 // Scan the low 32 bits.
232 if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r);
233 // Scan the high 32 bits.
234 _BitScanForward(&r, static_cast<uint32_t>(x >> 32));
235 r += 32;
236# endif
237 return static_cast<int>(r);
238}
239# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n)
240# if !defined(__clang__)
241# pragma managed(pop)
242# endif
243} // namespace detail
245#endif
246
248namespace detail {
249
250#if __cplusplus >= 202002L || \
251 (__cplusplus >= 201709L && FMT_GCC_VERSION >= 1002)
252# define FMT_CONSTEXPR20 constexpr
253#else
254# define FMT_CONSTEXPR20
255#endif
256
257// An equivalent of `*reinterpret_cast<Dest*>(&source)` that doesn't have
258// undefined behavior (e.g. due to type aliasing).
259// Example: uint64_t d = bit_cast<uint64_t>(2.718);
260template <typename Dest, typename Source>
261inline auto bit_cast(const Source& source) -> Dest {
262 static_assert(sizeof(Dest) == sizeof(Source), "size mismatch");
263 Dest dest;
264 std::memcpy(&dest, &source, sizeof(dest));
265 return dest;
266}
267
268inline auto is_big_endian() -> bool {
269 const auto u = 1u;
270 struct bytes {
271 char data[sizeof(u)];
272 };
273 return bit_cast<bytes>(u).data[0] == 0;
274}
275
276// A fallback implementation of uintptr_t for systems that lack it.
278 unsigned char value[sizeof(void*)];
279
280 fallback_uintptr() = default;
281 explicit fallback_uintptr(const void* p) {
282 *this = bit_cast<fallback_uintptr>(p);
283 if (is_big_endian()) {
284 for (size_t i = 0, j = sizeof(void*) - 1; i < j; ++i, --j)
285 std::swap(value[i], value[j]);
286 }
287 }
288};
289#ifdef UINTPTR_MAX
290using uintptr_t = ::uintptr_t;
291inline auto to_uintptr(const void* p) -> uintptr_t {
292 return bit_cast<uintptr_t>(p);
293}
294#else
296inline auto to_uintptr(const void* p) -> fallback_uintptr {
297 return fallback_uintptr(p);
298}
299#endif
300
301// Returns the largest possible value for type T. Same as
302// std::numeric_limits<T>::max() but shorter and not affected by the max macro.
303template <typename T> constexpr auto max_value() -> T {
305}
306template <typename T> constexpr auto num_bits() -> int {
308}
309// std::numeric_limits<T>::digits may return 0 for 128-bit ints.
310template <> constexpr auto num_bits<int128_t>() -> int { return 128; }
311template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
312template <> constexpr auto num_bits<fallback_uintptr>() -> int {
313 return static_cast<int>(sizeof(void*) *
315}
316
317FMT_INLINE void assume(bool condition) {
318 (void)condition;
319#if FMT_HAS_BUILTIN(__builtin_assume)
320 __builtin_assume(condition);
321#endif
322}
323
324// An approximation of iterator_t for pre-C++20 systems.
325template <typename T>
327template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>()));
328
329// A workaround for std::string not having mutable data() until C++17.
330template <typename Char>
331inline auto get_data(std::basic_string<Char>& s) -> Char* {
332 return &s[0];
333}
334template <typename Container>
335inline auto get_data(Container& c) -> typename Container::value_type* {
336 return c.data();
337}
338
339#if defined(_SECURE_SCL) && _SECURE_SCL
340// Make a checked iterator to avoid MSVC warnings.
341template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
342template <typename T> auto make_checked(T* p, size_t size) -> checked_ptr<T> {
343 return {p, size};
344}
345#else
346template <typename T> using checked_ptr = T*;
347template <typename T> inline auto make_checked(T* p, size_t) -> T* { return p; }
348#endif
349
350// Attempts to reserve space for n extra characters in the output range.
351// Returns a pointer to the reserved range or a reference to it.
352template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
353#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION
354__attribute__((no_sanitize("undefined")))
355#endif
356inline auto
359 Container& c = get_container(it);
360 size_t size = c.size();
361 c.resize(size + n);
362 return make_checked(get_data(c) + size, n);
363}
364
365template <typename T>
366inline auto reserve(buffer_appender<T> it, size_t n) -> buffer_appender<T> {
367 buffer<T>& buf = get_container(it);
368 buf.try_reserve(buf.size() + n);
369 return it;
370}
371
372template <typename Iterator>
373constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
374 return it;
375}
376
377template <typename OutputIt>
380
381template <typename T, typename OutputIt>
382constexpr auto to_pointer(OutputIt, size_t) -> T* {
383 return nullptr;
384}
385template <typename T> auto to_pointer(buffer_appender<T> it, size_t n) -> T* {
386 buffer<T>& buf = get_container(it);
387 auto size = buf.size();
388 if (buf.capacity() < size + n) return nullptr;
389 buf.try_resize(size + n);
390 return buf.data() + size;
391}
392
393template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
399
400template <typename Iterator>
401constexpr auto base_iterator(Iterator, Iterator it) -> Iterator {
402 return it;
403}
404
405// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n
406// instead (#1998).
407template <typename OutputIt, typename Size, typename T>
408FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value)
409 -> OutputIt {
410 for (Size i = 0; i < count; ++i) *out++ = value;
411 return out;
412}
413template <typename T, typename Size>
414FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* {
415 if (is_constant_evaluated()) {
416 return fill_n<T*, Size, T>(out, count, value);
417 }
419 return out + count;
420}
421
422#ifdef __cpp_char8_t
423using char8_type = char8_t;
424#else
425enum char8_type : unsigned char {};
426#endif
427
428template <typename OutChar, typename InputIt, typename OutputIt>
429FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end,
430 OutputIt out) -> OutputIt {
431 return copy_str<OutChar>(begin, end, out);
432}
433
434// A public domain branchless UTF-8 decoder by Christopher Wellons:
435// https://github.com/skeeto/branchless-utf8
436/* Decode the next character, c, from s, reporting errors in e.
437 *
438 * Since this is a branchless decoder, four bytes will be read from the
439 * buffer regardless of the actual length of the next character. This
440 * means the buffer _must_ have at least three bytes of zero padding
441 * following the end of the data stream.
442 *
443 * Errors are reported in e, which will be non-zero if the parsed
444 * character was somehow invalid: invalid byte sequence, non-canonical
445 * encoding, or a surrogate half.
446 *
447 * The function returns a pointer to the next character. When an error
448 * occurs, this pointer will be a guess that depends on the particular
449 * error, but it will always advance at least one byte.
450 */
451FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e)
452 -> const char* {
453 constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07};
454 constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536};
455 constexpr const int shiftc[] = {0, 18, 12, 6, 0};
456 constexpr const int shifte[] = {0, 6, 4, 2, 0};
457
458 int len = code_point_length(s);
459 const char* next = s + len;
460
461 // Assume a four-byte character and load four bytes. Unused bits are
462 // shifted out.
463 *c = uint32_t(s[0] & masks[len]) << 18;
464 *c |= uint32_t(s[1] & 0x3f) << 12;
465 *c |= uint32_t(s[2] & 0x3f) << 6;
466 *c |= uint32_t(s[3] & 0x3f) << 0;
467 *c >>= shiftc[len];
468
469 // Accumulate the various error conditions.
470 using uchar = unsigned char;
471 *e = (*c < mins[len]) << 6; // non-canonical encoding
472 *e |= ((*c >> 11) == 0x1b) << 7; // surrogate half?
473 *e |= (*c > 0x10FFFF) << 8; // out of range?
474 *e |= (uchar(s[1]) & 0xc0) >> 2;
475 *e |= (uchar(s[2]) & 0xc0) >> 4;
476 *e |= uchar(s[3]) >> 6;
477 *e ^= 0x2a; // top two bits of each tail byte correct?
478 *e >>= shifte[len];
479
480 return next;
481}
482
483template <typename F>
485 auto decode = [f](const char* p) {
486 auto cp = uint32_t();
487 auto error = 0;
488 p = utf8_decode(p, &cp, &error);
489 f(cp, error);
490 return p;
491 };
492 auto p = s.data();
493 const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars.
494 if (s.size() >= block_size) {
495 for (auto end = p + s.size() - block_size + 1; p < end;) p = decode(p);
496 }
497 if (auto num_chars_left = s.data() + s.size() - p) {
498 char buf[2 * block_size - 1] = {};
499 copy_str<char>(p, p + num_chars_left, buf);
500 p = buf;
501 do {
502 p = decode(p);
503 } while (p - buf < num_chars_left);
504 }
505}
506
507template <typename Char>
508inline auto compute_width(basic_string_view<Char> s) -> size_t {
509 return s.size();
510}
511
512// Computes approximate display width of a UTF-8 string.
514 size_t num_code_points = 0;
515 // It is not a lambda for compatibility with C++14.
516 struct count_code_points {
517 size_t* count;
518 FMT_CONSTEXPR void operator()(uint32_t cp, int error) const {
519 *count += detail::to_unsigned(
520 1 +
521 (error == 0 && cp >= 0x1100 &&
522 (cp <= 0x115f || // Hangul Jamo init. consonants
523 cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET
524 cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET
525 // CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE:
526 (cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) ||
527 (cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables
528 (cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs
529 (cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms
530 (cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms
531 (cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms
532 (cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms
533 (cp >= 0x20000 && cp <= 0x2fffd) || // CJK
534 (cp >= 0x30000 && cp <= 0x3fffd) ||
535 // Miscellaneous Symbols and Pictographs + Emoticons:
536 (cp >= 0x1f300 && cp <= 0x1f64f) ||
537 // Supplemental Symbols and Pictographs:
538 (cp >= 0x1f900 && cp <= 0x1f9ff))));
539 }
540 };
541 for_each_codepoint(s, count_code_points{&num_code_points});
542 return num_code_points;
543}
544
547 reinterpret_cast<const char*>(s.data()), s.size()));
548}
549
550template <typename Char>
551inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t {
552 size_t size = s.size();
553 return n < size ? n : size;
554}
555
556// Calculates the index of the nth code point in a UTF-8 string.
558 -> size_t {
559 const char8_type* data = s.data();
560 size_t num_code_points = 0;
561 for (size_t i = 0, size = s.size(); i != size; ++i) {
562 if ((data[i] & 0xc0) != 0x80 && ++num_code_points > n) return i;
563 }
564 return s.size();
565}
566
567template <typename T>
569 sizeof(T) <= sizeof(double)>;
570
571#ifndef FMT_USE_FULL_CACHE_DRAGONBOX
572# define FMT_USE_FULL_CACHE_DRAGONBOX 0
573#endif
574
575template <typename T>
576template <typename U>
577void buffer<T>::append(const U* begin, const U* end) {
578 while (begin != end) {
579 auto count = to_unsigned(end - begin);
580 try_reserve(size_ + count);
581 auto free_cap = capacity_ - size_;
582 if (free_cap < count) count = free_cap;
583 std::uninitialized_copy_n(begin, count, make_checked(ptr_ + size_, count));
584 size_ += count;
585 begin += count;
586 }
587}
588
589template <typename T, typename Enable = void>
591template <typename T>
592struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
593} // namespace detail
594
596
597// The number of characters to store in the basic_memory_buffer object itself
598// to avoid dynamic memory allocation.
599enum { inline_buffer_size = 500 };
600
601/**
602 \rst
603 A dynamically growing memory buffer for trivially copyable/constructible types
604 with the first ``SIZE`` elements stored in the object itself.
605
606 You can use the ``memory_buffer`` type alias for ``char`` instead.
607
608 **Example**::
609
610 fmt::memory_buffer out;
611 format_to(out, "The answer is {}.", 42);
612
613 This will append the following output to the ``out`` object:
614
615 .. code-block:: none
616
617 The answer is 42.
618
619 The output can be converted to an ``std::string`` with ``to_string(out)``.
620 \endrst
621 */
622template <typename T, size_t SIZE = inline_buffer_size,
623 typename Allocator = std::allocator<T>>
624class basic_memory_buffer final : public detail::buffer<T> {
625 private:
626 T store_[SIZE];
627
628 // Don't inherit from Allocator avoid generating type_info for it.
629 Allocator alloc_;
630
631 // Deallocate memory allocated by the buffer.
632 void deallocate() {
633 T* data = this->data();
634 if (data != store_) alloc_.deallocate(data, this->capacity());
635 }
636
637 protected:
638 void grow(size_t size) final FMT_OVERRIDE;
639
640 public:
641 using value_type = T;
642 using const_reference = const T&;
643
644 explicit basic_memory_buffer(const Allocator& alloc = Allocator())
645 : alloc_(alloc) {
646 this->set(store_, SIZE);
647 }
649
650 private:
651 // Move data from other to this buffer.
653 alloc_ = std::move(other.alloc_);
654 T* data = other.data();
655 size_t size = other.size(), capacity = other.capacity();
656 if (data == other.store_) {
657 this->set(store_, capacity);
658 std::uninitialized_copy(other.store_, other.store_ + size,
659 detail::make_checked(store_, capacity));
660 } else {
661 this->set(data, capacity);
662 // Set pointer to the inline array so that delete is not called
663 // when deallocating.
664 other.set(other.store_, 0);
665 }
666 this->resize(size);
667 }
668
669 public:
670 /**
671 \rst
672 Constructs a :class:`fmt::basic_memory_buffer` object moving the content
673 of the other object to it.
674 \endrst
675 */
677
678 /**
679 \rst
680 Moves the content of the other ``basic_memory_buffer`` object to this one.
681 \endrst
682 */
685 FMT_ASSERT(this != &other, "");
686 deallocate();
687 move(other);
688 return *this;
689 }
690
691 // Returns a copy of the allocator associated with this buffer.
692 auto get_allocator() const -> Allocator { return alloc_; }
693
694 /**
695 Resizes the buffer to contain *count* elements. If T is a POD type new
696 elements may not be initialized.
697 */
698 void resize(size_t count) { this->try_resize(count); }
699
700 /** Increases the buffer capacity to *new_capacity*. */
701 void reserve(size_t new_capacity) { this->try_reserve(new_capacity); }
702
703 // Directly append data into the buffer
704 using detail::buffer<T>::append;
705 template <typename ContiguousRange>
706 void append(const ContiguousRange& range) {
707 append(range.data(), range.data() + range.size());
708 }
709};
710
711template <typename T, size_t SIZE, typename Allocator>
713#ifdef FMT_FUZZ
714 if (size > 5000) throw std::runtime_error("fuzz mode - won't grow that much");
715#endif
716 const size_t max_size = std::allocator_traits<Allocator>::max_size(alloc_);
717 size_t old_capacity = this->capacity();
718 size_t new_capacity = old_capacity + old_capacity / 2;
719 if (size > new_capacity)
720 new_capacity = size;
721 else if (new_capacity > max_size)
722 new_capacity = size > max_size ? size : max_size;
723 T* old_data = this->data();
724 T* new_data =
725 std::allocator_traits<Allocator>::allocate(alloc_, new_capacity);
726 // The following code doesn't throw, so the raw pointer above doesn't leak.
727 std::uninitialized_copy(old_data, old_data + this->size(),
728 detail::make_checked(new_data, new_capacity));
729 this->set(new_data, new_capacity);
730 // deallocate must not throw according to the standard, but even if it does,
731 // the buffer already uses the new storage and will deallocate it in
732 // destructor.
733 if (old_data != store_) alloc_.deallocate(old_data, old_capacity);
734}
735
737
738template <typename T, size_t SIZE, typename Allocator>
740};
741
742namespace detail {
744}
745
746/** A formatting error such as invalid format string. */
749 public:
750 explicit format_error(const char* message) : std::runtime_error(message) {}
751 explicit format_error(const std::string& message)
752 : std::runtime_error(message) {}
753 format_error(const format_error&) = default;
758};
759
760/**
761 \rst
762 Constructs a `~fmt::format_arg_store` object that contains references
763 to arguments and can be implicitly converted to `~fmt::format_args`.
764 If ``fmt`` is a compile-time string then `make_args_checked` checks
765 its validity at compile time.
766 \endrst
767 */
768template <typename... Args, typename S, typename Char = char_t<S>>
770 const remove_reference_t<Args>&... args)
772 static_assert(
773 detail::count<(
776 "passing views as lvalues is disallowed");
777 detail::check_format_string<Args...>(fmt);
778 return {args...};
779}
780
781// compile-time support
783#if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
784template <typename Char, size_t N> struct fixed_string {
785 constexpr fixed_string(const Char (&str)[N]) {
786 detail::copy_str<Char, const Char*, Char*>(static_cast<const Char*>(str),
787 str + N, data);
788 }
789 Char data[N]{};
790};
791#endif
792
793// Converts a compile-time string to basic_string_view.
794template <typename Char, size_t N>
795constexpr auto compile_string_to_view(const Char (&s)[N])
797 // Remove trailing NUL character if needed. Won't be present if this is used
798 // with a raw character array (i.e. not defined as a string).
799 return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)};
800}
801template <typename Char>
802constexpr auto compile_string_to_view(detail::std_string_view<Char> s)
804 return {s.data(), s.size()};
805}
806} // namespace detail_exported
807
809
810inline void throw_format_error(const char* message) {
811 FMT_THROW(format_error(message));
812}
813
814template <typename T> struct is_integral : std::is_integral<T> {};
815template <> struct is_integral<int128_t> : std::true_type {};
816template <> struct is_integral<uint128_t> : std::true_type {};
817
818template <typename T>
822
823// Returns true if value is negative, false otherwise.
824// Same as `value < 0` but doesn't produce warnings if T is an unsigned type.
825template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
827 return value < 0;
828}
829template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
830FMT_CONSTEXPR auto is_negative(T) -> bool {
831 return false;
832}
833
834template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
840
841// Smallest of uint32_t, uint64_t, uint128_t that is large enough to
842// represent all values of an integral type T.
843template <typename T>
846 uint32_t,
847 conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>;
848template <typename T>
850
851#define FMT_POWERS_OF_10(factor) \
852 factor * 10, (factor)*100, (factor)*1000, (factor)*10000, (factor)*100000, \
853 (factor)*1000000, (factor)*10000000, (factor)*100000000, \
854 (factor)*1000000000
855
856// Static data is placed in this class template for the header-only config.
857template <typename T = void> struct basic_data {
858 // log10(2) = 0x0.4d104d427de7fbcc...
859 static const uint64_t log10_2_significand = 0x4d104d427de7fbcc;
860
861 // GCC generates slightly better code for pairs than chars.
862 FMT_API static constexpr const char digits[100][2] = {
863 {'0', '0'}, {'0', '1'}, {'0', '2'}, {'0', '3'}, {'0', '4'}, {'0', '5'},
864 {'0', '6'}, {'0', '7'}, {'0', '8'}, {'0', '9'}, {'1', '0'}, {'1', '1'},
865 {'1', '2'}, {'1', '3'}, {'1', '4'}, {'1', '5'}, {'1', '6'}, {'1', '7'},
866 {'1', '8'}, {'1', '9'}, {'2', '0'}, {'2', '1'}, {'2', '2'}, {'2', '3'},
867 {'2', '4'}, {'2', '5'}, {'2', '6'}, {'2', '7'}, {'2', '8'}, {'2', '9'},
868 {'3', '0'}, {'3', '1'}, {'3', '2'}, {'3', '3'}, {'3', '4'}, {'3', '5'},
869 {'3', '6'}, {'3', '7'}, {'3', '8'}, {'3', '9'}, {'4', '0'}, {'4', '1'},
870 {'4', '2'}, {'4', '3'}, {'4', '4'}, {'4', '5'}, {'4', '6'}, {'4', '7'},
871 {'4', '8'}, {'4', '9'}, {'5', '0'}, {'5', '1'}, {'5', '2'}, {'5', '3'},
872 {'5', '4'}, {'5', '5'}, {'5', '6'}, {'5', '7'}, {'5', '8'}, {'5', '9'},
873 {'6', '0'}, {'6', '1'}, {'6', '2'}, {'6', '3'}, {'6', '4'}, {'6', '5'},
874 {'6', '6'}, {'6', '7'}, {'6', '8'}, {'6', '9'}, {'7', '0'}, {'7', '1'},
875 {'7', '2'}, {'7', '3'}, {'7', '4'}, {'7', '5'}, {'7', '6'}, {'7', '7'},
876 {'7', '8'}, {'7', '9'}, {'8', '0'}, {'8', '1'}, {'8', '2'}, {'8', '3'},
877 {'8', '4'}, {'8', '5'}, {'8', '6'}, {'8', '7'}, {'8', '8'}, {'8', '9'},
878 {'9', '0'}, {'9', '1'}, {'9', '2'}, {'9', '3'}, {'9', '4'}, {'9', '5'},
879 {'9', '6'}, {'9', '7'}, {'9', '8'}, {'9', '9'}};
880
881 FMT_API static constexpr const char hex_digits[] = "0123456789abcdef";
882 FMT_API static constexpr const char signs[4] = {0, '-', '+', ' '};
883 FMT_API static constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+',
884 0x1000000u | ' '};
885 FMT_API static constexpr const char left_padding_shifts[5] = {31, 31, 0, 1,
886 0};
887 FMT_API static constexpr const char right_padding_shifts[5] = {0, 31, 0, 1,
888 0};
889};
890
891#ifdef FMT_SHARED
892// Required for -flto, -fivisibility=hidden and -shared to work
893extern template struct basic_data<void>;
894#endif
895
896// This is a struct rather than an alias to avoid shadowing warnings in gcc.
897struct data : basic_data<> {};
898
899template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int {
900 int count = 1;
901 for (;;) {
902 // Integer division is slow so do it for a group of four digits instead
903 // of for every digit. The idea comes from the talk by Alexandrescu
904 // "Three Optimization Tips for C++". See speed-test for a comparison.
905 if (n < 10) return count;
906 if (n < 100) return count + 1;
907 if (n < 1000) return count + 2;
908 if (n < 10000) return count + 3;
909 n /= 10000u;
910 count += 4;
911 }
912}
913#if FMT_USE_INT128
914FMT_CONSTEXPR inline auto count_digits(uint128_t n) -> int {
915 return count_digits_fallback(n);
916}
917#endif
918
919// Returns the number of decimal digits in n. Leading zeros are not counted
920// except for n == 0 in which case count_digits returns 1.
921FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int {
922#ifdef FMT_BUILTIN_CLZLL
923 if (!is_constant_evaluated()) {
924 // https://github.com/fmtlib/format-benchmark/blob/master/digits10
925 // Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)).
926 constexpr uint16_t bsr2log10[] = {
927 1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,
928 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10,
929 10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15,
930 15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20};
931 auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63];
932 constexpr const uint64_t zero_or_powers_of_10[] = {
933 0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL),
934 10000000000000000000ULL};
935 return t - (n < zero_or_powers_of_10[t]);
936 }
937#endif
938 return count_digits_fallback(n);
939}
940
941// Counts the number of digits in n. BITS = log2(radix).
942template <int BITS, typename UInt>
943FMT_CONSTEXPR auto count_digits(UInt n) -> int {
944#ifdef FMT_BUILTIN_CLZ
945 if (num_bits<UInt>() == 32)
946 return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1;
947#endif
948 int num_digits = 0;
949 do {
950 ++num_digits;
951 } while ((n >>= BITS) != 0);
952 return num_digits;
953}
954
956
957// It is a separate function rather than a part of count_digits to workaround
958// the lack of static constexpr in constexpr functions.
960 // An optimization by Kendall Willets from https://bit.ly/3uOIQrB.
961 // This increments the upper 32 bits (log10(T) - 1) when >= T is added.
962#define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T)
963 static constexpr uint64_t table[] = {
964 FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8
965 FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64
966 FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512
967 FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096
968 FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k
969 FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k
970 FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k
971 FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M
972 FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M
973 FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M
974 FMT_INC(1000000000), FMT_INC(1000000000) // 4B
975 };
976 return table[n];
977}
978
979// Optional version of count_digits for better performance on 32-bit platforms.
980FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int {
981#ifdef FMT_BUILTIN_CLZ
982 if (!is_constant_evaluated()) {
983 auto inc = count_digits_inc(FMT_BUILTIN_CLZ(n | 1) ^ 31);
984 return static_cast<int>((n + inc) >> 32);
985 }
986#endif
987 return count_digits_fallback(n);
988}
989
990template <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int {
992}
993template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int {
994 return 38;
995}
996template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int {
997 return 38;
998}
999
1000template <typename Char> struct thousands_sep_result {
1003};
1004
1005template <typename Char>
1007template <typename Char>
1009 auto result = thousands_sep_impl<char>(loc);
1010 return {result.grouping, Char(result.thousands_sep)};
1011}
1012template <>
1016
1017template <typename Char>
1019template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
1020 return Char(decimal_point_impl<char>(loc));
1021}
1022template <> inline auto decimal_point(locale_ref loc) -> wchar_t {
1023 return decimal_point_impl<wchar_t>(loc);
1024}
1025
1026// Compares two characters for equality.
1027template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
1028 return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1029}
1030inline auto equal2(const char* lhs, const char* rhs) -> bool {
1031 return memcmp(lhs, rhs, 2) == 0;
1032}
1033
1034// Copies two characters from src to dst.
1035template <typename Char> void copy2(Char* dst, const char* src) {
1036 *dst++ = static_cast<Char>(*src++);
1037 *dst = static_cast<Char>(*src);
1038}
1039FMT_INLINE void copy2(char* dst, const char* src) { memcpy(dst, src, 2); }
1040
1041template <typename Iterator> struct format_decimal_result {
1042 Iterator begin;
1043 Iterator end;
1044};
1045
1046// Formats a decimal unsigned integer value writing into out pointing to a
1047// buffer of specified size. The caller must ensure that the buffer is large
1048// enough.
1049template <typename Char, typename UInt>
1050FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size)
1052 FMT_ASSERT(size >= count_digits(value), "invalid digit count");
1053 out += size;
1054 Char* end = out;
1055 if (is_constant_evaluated()) {
1056 while (value >= 10) {
1057 *--out = static_cast<Char>('0' + value % 10);
1058 value /= 10;
1059 }
1060 *--out = static_cast<Char>('0' + value);
1061 return {out, end};
1062 }
1063 while (value >= 100) {
1064 // Integer division is slow so do it for a group of two digits instead
1065 // of for every digit. The idea comes from the talk by Alexandrescu
1066 // "Three Optimization Tips for C++". See speed-test for a comparison.
1067 out -= 2;
1068 copy2(out, data::digits[value % 100]);
1069 value /= 100;
1070 }
1071 if (value < 10) {
1072 *--out = static_cast<Char>('0' + value);
1073 return {out, end};
1074 }
1075 out -= 2;
1076 copy2(out, data::digits[value]);
1077 return {out, end};
1078}
1079
1080template <typename Char, typename UInt, typename Iterator,
1082inline auto format_decimal(Iterator out, UInt value, int size)
1084 // Buffer is large enough to hold all digits (digits10 + 1).
1085 Char buffer[digits10<UInt>() + 1];
1086 auto end = format_decimal(buffer, value, size).end;
1087 return {out, detail::copy_str_noinline<Char>(buffer, end, out)};
1088}
1089
1090template <unsigned BASE_BITS, typename Char, typename UInt>
1091FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits,
1092 bool upper = false) -> Char* {
1093 buffer += num_digits;
1094 Char* end = buffer;
1095 do {
1096 const char* digits = upper ? "0123456789ABCDEF" : data::hex_digits;
1097 unsigned digit = (value & ((1 << BASE_BITS) - 1));
1098 *--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit)
1099 : digits[digit]);
1100 } while ((value >>= BASE_BITS) != 0);
1101 return end;
1102}
1103
1104template <unsigned BASE_BITS, typename Char>
1105auto format_uint(Char* buffer, detail::fallback_uintptr n, int num_digits,
1106 bool = false) -> Char* {
1107 auto char_digits = std::numeric_limits<unsigned char>::digits / 4;
1108 int start = (num_digits + char_digits - 1) / char_digits - 1;
1109 if (int start_digits = num_digits % char_digits) {
1110 unsigned value = n.value[start--];
1111 buffer = format_uint<BASE_BITS>(buffer, value, start_digits);
1112 }
1113 for (; start >= 0; --start) {
1114 unsigned value = n.value[start];
1116 auto p = buffer;
1117 for (int i = 0; i < char_digits; ++i) {
1118 unsigned digit = (value & ((1 << BASE_BITS) - 1));
1119 *--p = static_cast<Char>(data::hex_digits[digit]);
1120 value >>= BASE_BITS;
1121 }
1122 }
1123 return buffer;
1124}
1125
1126template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
1127inline auto format_uint(It out, UInt value, int num_digits, bool upper = false)
1128 -> It {
1129 if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) {
1130 format_uint<BASE_BITS>(ptr, value, num_digits, upper);
1131 return out;
1132 }
1133 // Buffer should be large enough to hold all digits (digits / BASE_BITS + 1).
1134 char buffer[num_bits<UInt>() / BASE_BITS + 1];
1135 format_uint<BASE_BITS>(buffer, value, num_digits, upper);
1136 return detail::copy_str_noinline<Char>(buffer, buffer + num_digits, out);
1137}
1138
1139// A converter from UTF-8 to UTF-16.
1141 private:
1143
1144 public:
1145 FMT_API explicit utf8_to_utf16(string_view s);
1146 operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; }
1147 auto size() const -> size_t { return buffer_.size() - 1; }
1148 auto c_str() const -> const wchar_t* { return &buffer_[0]; }
1149 auto str() const -> std::wstring { return {&buffer_[0], size()}; }
1150};
1151
1152namespace dragonbox {
1153
1154// Type-specific information that Dragonbox uses.
1155template <class T> struct float_info;
1156
1157template <> struct float_info<float> {
1158 using carrier_uint = uint32_t;
1159 static const int significand_bits = 23;
1160 static const int exponent_bits = 8;
1161 static const int min_exponent = -126;
1162 static const int max_exponent = 127;
1163 static const int exponent_bias = -127;
1164 static const int decimal_digits = 9;
1165 static const int kappa = 1;
1166 static const int big_divisor = 100;
1167 static const int small_divisor = 10;
1168 static const int min_k = -31;
1169 static const int max_k = 46;
1170 static const int cache_bits = 64;
1171 static const int divisibility_check_by_5_threshold = 39;
1172 static const int case_fc_pm_half_lower_threshold = -1;
1173 static const int case_fc_pm_half_upper_threshold = 6;
1174 static const int case_fc_lower_threshold = -2;
1175 static const int case_fc_upper_threshold = 6;
1176 static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1177 static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1178 static const int shorter_interval_tie_lower_threshold = -35;
1179 static const int shorter_interval_tie_upper_threshold = -35;
1180 static const int max_trailing_zeros = 7;
1181};
1182
1183template <> struct float_info<double> {
1184 using carrier_uint = uint64_t;
1185 static const int significand_bits = 52;
1186 static const int exponent_bits = 11;
1187 static const int min_exponent = -1022;
1188 static const int max_exponent = 1023;
1189 static const int exponent_bias = -1023;
1190 static const int decimal_digits = 17;
1191 static const int kappa = 2;
1192 static const int big_divisor = 1000;
1193 static const int small_divisor = 100;
1194 static const int min_k = -292;
1195 static const int max_k = 326;
1196 static const int cache_bits = 128;
1197 static const int divisibility_check_by_5_threshold = 86;
1198 static const int case_fc_pm_half_lower_threshold = -2;
1199 static const int case_fc_pm_half_upper_threshold = 9;
1200 static const int case_fc_lower_threshold = -4;
1201 static const int case_fc_upper_threshold = 9;
1202 static const int case_shorter_interval_left_endpoint_lower_threshold = 2;
1203 static const int case_shorter_interval_left_endpoint_upper_threshold = 3;
1204 static const int shorter_interval_tie_lower_threshold = -77;
1205 static const int shorter_interval_tie_upper_threshold = -77;
1206 static const int max_trailing_zeros = 16;
1207};
1208
1214
1215template <typename T>
1216FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>;
1217} // namespace dragonbox
1218
1219template <typename T>
1226
1227// Writes the exponent exp in the form "[+-]d{2,3}" to buffer.
1228template <typename Char, typename It>
1229auto write_exponent(int exp, It it) -> It {
1230 FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range");
1231 if (exp < 0) {
1232 *it++ = static_cast<Char>('-');
1233 exp = -exp;
1234 } else {
1235 *it++ = static_cast<Char>('+');
1236 }
1237 if (exp >= 100) {
1238 const char* top = data::digits[exp / 100];
1239 if (exp >= 1000) *it++ = static_cast<Char>(top[0]);
1240 *it++ = static_cast<Char>(top[1]);
1241 exp %= 100;
1242 }
1243 const char* d = data::digits[exp];
1244 *it++ = static_cast<Char>(d[0]);
1245 *it++ = static_cast<Char>(d[1]);
1246 return it;
1247}
1248
1249template <typename T>
1250auto format_float(T value, int precision, float_specs specs, buffer<char>& buf)
1251 -> int;
1252
1253// Formats a floating-point number with snprintf.
1254template <typename T>
1255auto snprintf_float(T value, int precision, float_specs specs,
1256 buffer<char>& buf) -> int;
1257
1258template <typename T> auto promote_float(T value) -> T { return value; }
1259inline auto promote_float(float value) -> double {
1260 return static_cast<double>(value);
1261}
1262
1263template <typename OutputIt, typename Char>
1264FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n,
1265 const fill_t<Char>& fill) -> OutputIt {
1266 auto fill_size = fill.size();
1267 if (fill_size == 1) return detail::fill_n(it, n, fill[0]);
1268 auto data = fill.data();
1269 for (size_t i = 0; i < n; ++i)
1270 it = copy_str<Char>(data, data + fill_size, it);
1271 return it;
1272}
1273
1274// Writes the output of f, padded according to format specifications in specs.
1275// size: output size in code units.
1276// width: output display width in (terminal) column positions.
1277template <align::type align = align::left, typename OutputIt, typename Char,
1278 typename F>
1279FMT_CONSTEXPR auto write_padded(OutputIt out,
1280 const basic_format_specs<Char>& specs,
1281 size_t size, size_t width, F&& f) -> OutputIt {
1282 static_assert(align == align::left || align == align::right, "");
1283 unsigned spec_width = to_unsigned(specs.width);
1284 size_t padding = spec_width > width ? spec_width - width : 0;
1285 auto* shifts = align == align::left ? data::left_padding_shifts
1287 size_t left_padding = padding >> shifts[specs.align];
1288 size_t right_padding = padding - left_padding;
1289 auto it = reserve(out, size + padding * specs.fill.size());
1290 if (left_padding != 0) it = fill(it, left_padding, specs.fill);
1291 it = f(it);
1292 if (right_padding != 0) it = fill(it, right_padding, specs.fill);
1293 return base_iterator(out, it);
1294}
1295
1296template <align::type align = align::left, typename OutputIt, typename Char,
1297 typename F>
1298constexpr auto write_padded(OutputIt out, const basic_format_specs<Char>& specs,
1299 size_t size, F&& f) -> OutputIt {
1300 return write_padded<align>(out, specs, size, size, f);
1301}
1302
1303template <align::type align = align::left, typename Char, typename OutputIt>
1305 const basic_format_specs<Char>& specs)
1306 -> OutputIt {
1307 return write_padded<align>(
1308 out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) {
1309 const char* data = bytes.data();
1310 return copy_str<Char>(data, data + bytes.size(), it);
1311 });
1312}
1313
1314template <typename Char, typename OutputIt, typename UIntPtr>
1315auto write_ptr(OutputIt out, UIntPtr value,
1316 const basic_format_specs<Char>* specs) -> OutputIt {
1317 int num_digits = count_digits<4>(value);
1318 auto size = to_unsigned(num_digits) + size_t(2);
1319 auto write = [=](reserve_iterator<OutputIt> it) {
1320 *it++ = static_cast<Char>('0');
1321 *it++ = static_cast<Char>('x');
1322 return format_uint<4, Char>(it, value, num_digits);
1323 };
1324 return specs ? write_padded<align::right>(out, *specs, size, write)
1325 : base_iterator(out, write(reserve(out, size)));
1326}
1327
1328template <typename Char, typename OutputIt>
1329FMT_CONSTEXPR auto write_char(OutputIt out, Char value,
1330 const basic_format_specs<Char>& specs)
1331 -> OutputIt {
1332 return write_padded(out, specs, 1, [=](reserve_iterator<OutputIt> it) {
1333 *it++ = value;
1334 return it;
1335 });
1336}
1337template <typename Char, typename OutputIt>
1338FMT_CONSTEXPR auto write(OutputIt out, Char value,
1339 const basic_format_specs<Char>& specs,
1340 locale_ref loc = {}) -> OutputIt {
1341 return check_char_specs(specs)
1342 ? write_char(out, value, specs)
1343 : write(out, static_cast<int>(value), specs, loc);
1344}
1345
1346// Data for write_int that doesn't depend on output iterator type. It is used to
1347// avoid template code bloat.
1348template <typename Char> struct write_int_data {
1349 size_t size;
1350 size_t padding;
1351
1352 FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix,
1353 const basic_format_specs<Char>& specs)
1354 : size((prefix >> 24) + to_unsigned(num_digits)), padding(0) {
1355 if (specs.align == align::numeric) {
1356 auto width = to_unsigned(specs.width);
1357 if (width > size) {
1358 padding = width - size;
1359 size = width;
1360 }
1361 } else if (specs.precision > num_digits) {
1362 size = (prefix >> 24) + to_unsigned(specs.precision);
1363 padding = to_unsigned(specs.precision - num_digits);
1364 }
1365 }
1366};
1367
1368// Writes an integer in the format
1369// <left-padding><prefix><numeric-padding><digits><right-padding>
1370// where <digits> are written by write_digits(it).
1371// prefix contains chars in three lower bytes and the size in the fourth byte.
1372template <typename OutputIt, typename Char, typename W>
1373FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits,
1374 unsigned prefix,
1375 const basic_format_specs<Char>& specs,
1376 W write_digits) -> OutputIt {
1377 // Slightly faster check for specs.width == 0 && specs.precision == -1.
1378 if ((specs.width | (specs.precision + 1)) == 0) {
1379 auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24));
1380 if (prefix != 0) {
1381 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1382 *it++ = static_cast<Char>(p & 0xff);
1383 }
1384 return base_iterator(out, write_digits(it));
1385 }
1386 auto data = write_int_data<Char>(num_digits, prefix, specs);
1387 return write_padded<align::right>(
1388 out, specs, data.size, [=](reserve_iterator<OutputIt> it) {
1389 for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8)
1390 *it++ = static_cast<Char>(p & 0xff);
1391 it = detail::fill_n(it, data.padding, static_cast<Char>('0'));
1392 return write_digits(it);
1393 });
1394}
1395
1396template <typename OutputIt, typename UInt, typename Char>
1397auto write_int_localized(OutputIt& out, UInt value, unsigned prefix,
1398 const basic_format_specs<Char>& specs, locale_ref loc)
1399 -> bool {
1400 static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, "");
1401 const auto sep_size = 1;
1402 auto ts = thousands_sep<Char>(loc);
1403 if (!ts.thousands_sep) return false;
1404 int num_digits = count_digits(value);
1405 int size = num_digits, n = num_digits;
1406 const std::string& groups = ts.grouping;
1407 std::string::const_iterator group = groups.cbegin();
1408 while (group != groups.cend() && n > *group && *group > 0 &&
1409 *group != max_value<char>()) {
1410 size += sep_size;
1411 n -= *group;
1412 ++group;
1413 }
1414 if (group == groups.cend()) size += sep_size * ((n - 1) / groups.back());
1415 char digits[40];
1416 format_decimal(digits, value, num_digits);
1418 if (prefix != 0) ++size;
1419 const auto usize = to_unsigned(size);
1420 buffer.resize(usize);
1421 basic_string_view<Char> s(&ts.thousands_sep, sep_size);
1422 // Index of a decimal digit with the least significant digit having index 0.
1423 int digit_index = 0;
1424 group = groups.cbegin();
1425 auto p = buffer.data() + size - 1;
1426 for (int i = num_digits - 1; i > 0; --i) {
1427 *p-- = static_cast<Char>(digits[i]);
1428 if (*group <= 0 || ++digit_index % *group != 0 ||
1429 *group == max_value<char>())
1430 continue;
1431 if (group + 1 != groups.cend()) {
1432 digit_index = 0;
1433 ++group;
1434 }
1435 std::uninitialized_copy(s.data(), s.data() + s.size(),
1436 make_checked(p, s.size()));
1437 p -= s.size();
1438 }
1439 *p-- = static_cast<Char>(*digits);
1440 if (prefix != 0) *p = static_cast<Char>(prefix);
1441 auto data = buffer.data();
1442 out = write_padded<align::right>(
1443 out, specs, usize, usize, [=](reserve_iterator<OutputIt> it) {
1444 return copy_str<Char>(data, data + size, it);
1445 });
1446 return true;
1447}
1448
1449FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) {
1450 prefix |= prefix != 0 ? value << 8 : value;
1451 prefix += (1u + (value > 0xff ? 1 : 0)) << 24;
1452}
1453
1454template <typename UInt> struct write_int_arg {
1456 unsigned prefix;
1457};
1458
1459template <typename T>
1462 auto prefix = 0u;
1463 auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
1464 if (is_negative(value)) {
1465 prefix = 0x01000000 | '-';
1466 abs_value = 0 - abs_value;
1467 } else {
1468 prefix = data::prefixes[sign];
1469 }
1470 return {abs_value, prefix};
1471}
1472
1473template <typename Char, typename OutputIt, typename T>
1475 const basic_format_specs<Char>& specs,
1476 locale_ref loc) -> OutputIt {
1478 auto abs_value = arg.abs_value;
1479 auto prefix = arg.prefix;
1480 auto utype = static_cast<unsigned>(specs.type);
1481 switch (specs.type) {
1482 case 0:
1483 case 'd': {
1484 if (specs.localized &&
1485 write_int_localized(out, static_cast<uint64_or_128_t<T>>(abs_value),
1486 prefix, specs, loc)) {
1487 return out;
1488 }
1489 auto num_digits = count_digits(abs_value);
1490 return write_int(
1491 out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
1492 return format_decimal<Char>(it, abs_value, num_digits).end;
1493 });
1494 }
1495 case 'x':
1496 case 'X': {
1497 if (specs.alt) prefix_append(prefix, (utype << 8) | '0');
1498 bool upper = specs.type != 'x';
1499 int num_digits = count_digits<4>(abs_value);
1500 return write_int(
1501 out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) {
1502 return format_uint<4, Char>(it, abs_value, num_digits, upper);
1503 });
1504 }
1505 case 'b':
1506 case 'B': {
1507 if (specs.alt) prefix_append(prefix, (utype << 8) | '0');
1508 int num_digits = count_digits<1>(abs_value);
1509 return write_int(out, num_digits, prefix, specs,
1510 [=](reserve_iterator<OutputIt> it) {
1511 return format_uint<1, Char>(it, abs_value, num_digits);
1512 });
1513 }
1514 case 'o': {
1515 int num_digits = count_digits<3>(abs_value);
1516 if (specs.alt && specs.precision <= num_digits && abs_value != 0) {
1517 // Octal prefix '0' is counted as a digit, so only add it if precision
1518 // is not greater than the number of digits.
1519 prefix_append(prefix, '0');
1520 }
1521 return write_int(out, num_digits, prefix, specs,
1522 [=](reserve_iterator<OutputIt> it) {
1523 return format_uint<3, Char>(it, abs_value, num_digits);
1524 });
1525 }
1526 case 'c':
1527 return write_char(out, static_cast<Char>(abs_value), specs);
1528 default:
1529 FMT_THROW(format_error("invalid type specifier"));
1530 }
1531 return out;
1532}
1533template <typename Char, typename OutputIt, typename T,
1537FMT_CONSTEXPR auto write(OutputIt out, T value,
1538 const basic_format_specs<Char>& specs, locale_ref loc)
1539 -> OutputIt {
1540 return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
1541}
1542// An inlined version of write used in format string compilation.
1543template <typename Char, typename OutputIt, typename T,
1548 const basic_format_specs<Char>& specs,
1549 locale_ref loc) -> OutputIt {
1550 return write_int(out, make_write_int_arg(value, specs.sign), specs, loc);
1551}
1552
1553template <typename Char, typename OutputIt>
1555 const basic_format_specs<Char>& specs) -> OutputIt {
1556 auto data = s.data();
1557 auto size = s.size();
1558 if (specs.precision >= 0 && to_unsigned(specs.precision) < size)
1559 size = code_point_index(s, to_unsigned(specs.precision));
1560 auto width =
1561 specs.width != 0 ? compute_width(basic_string_view<Char>(data, size)) : 0;
1562 return write_padded(out, specs, size, width,
1563 [=](reserve_iterator<OutputIt> it) {
1564 return copy_str<Char>(data, data + size, it);
1565 });
1566}
1567template <typename Char, typename OutputIt>
1568FMT_CONSTEXPR auto write(OutputIt out,
1571 -> OutputIt {
1573 return write(out, s, specs);
1574}
1575template <typename Char, typename OutputIt>
1576FMT_CONSTEXPR auto write(OutputIt out, const Char* s,
1578 -> OutputIt {
1579 return check_cstring_type_spec(specs.type)
1580 ? write(out, basic_string_view<Char>(s), specs, {})
1581 : write_ptr<Char>(out, to_uintptr(s), &specs);
1582}
1583
1584template <typename Char, typename OutputIt>
1585auto write_nonfinite(OutputIt out, bool isinf, basic_format_specs<Char> specs,
1586 const float_specs& fspecs) -> OutputIt {
1587 auto str =
1588 isinf ? (fspecs.upper ? "INF" : "inf") : (fspecs.upper ? "NAN" : "nan");
1589 constexpr size_t str_size = 3;
1590 auto sign = fspecs.sign;
1591 auto size = str_size + (sign ? 1 : 0);
1592 // Replace '0'-padding with space for non-finite values.
1593 const bool is_zero_fill =
1594 specs.fill.size() == 1 && *specs.fill.data() == static_cast<Char>('0');
1595 if (is_zero_fill) specs.fill[0] = static_cast<Char>(' ');
1596 return write_padded(out, specs, size, [=](reserve_iterator<OutputIt> it) {
1597 if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1598 return copy_str<Char>(str, str + str_size, it);
1599 });
1600}
1601
1602// A decimal floating-point number significand * pow(10, exp).
1608
1609inline auto get_significand_size(const big_decimal_fp& fp) -> int {
1610 return fp.significand_size;
1611}
1612template <typename T>
1613inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int {
1614 return count_digits(fp.significand);
1615}
1616
1617template <typename Char, typename OutputIt>
1618inline auto write_significand(OutputIt out, const char* significand,
1619 int& significand_size) -> OutputIt {
1620 return copy_str<Char>(significand, significand + significand_size, out);
1621}
1622template <typename Char, typename OutputIt, typename UInt>
1623inline auto write_significand(OutputIt out, UInt significand,
1624 int significand_size) -> OutputIt {
1625 return format_decimal<Char>(out, significand, significand_size).end;
1626}
1627
1628template <typename Char, typename UInt,
1630inline auto write_significand(Char* out, UInt significand, int significand_size,
1631 int integral_size, Char decimal_point) -> Char* {
1632 if (!decimal_point)
1633 return format_decimal(out, significand, significand_size).end;
1634 auto end = format_decimal(out + 1, significand, significand_size).end;
1635 if (integral_size == 1) {
1636 out[0] = out[1];
1637 } else {
1638 std::uninitialized_copy_n(out + 1, integral_size,
1639 make_checked(out, to_unsigned(integral_size)));
1640 }
1641 out[integral_size] = decimal_point;
1642 return end;
1643}
1644
1645template <typename OutputIt, typename UInt, typename Char,
1647inline auto write_significand(OutputIt out, UInt significand,
1648 int significand_size, int integral_size,
1649 Char decimal_point) -> OutputIt {
1650 // Buffer is large enough to hold digits (digits10 + 1) and a decimal point.
1651 Char buffer[digits10<UInt>() + 2];
1652 auto end = write_significand(buffer, significand, significand_size,
1653 integral_size, decimal_point);
1654 return detail::copy_str_noinline<Char>(buffer, end, out);
1655}
1656
1657template <typename OutputIt, typename Char>
1658inline auto write_significand(OutputIt out, const char* significand,
1659 int significand_size, int integral_size,
1660 Char decimal_point) -> OutputIt {
1661 out = detail::copy_str_noinline<Char>(significand,
1662 significand + integral_size, out);
1663 if (!decimal_point) return out;
1664 *out++ = decimal_point;
1665 return detail::copy_str_noinline<Char>(significand + integral_size,
1666 significand + significand_size, out);
1667}
1668
1669template <typename OutputIt, typename DecimalFP, typename Char>
1670auto write_float(OutputIt out, const DecimalFP& fp,
1671 const basic_format_specs<Char>& specs, float_specs fspecs,
1672 Char decimal_point) -> OutputIt {
1673 auto significand = fp.significand;
1674 int significand_size = get_significand_size(fp);
1675 static const Char zero = static_cast<Char>('0');
1676 auto sign = fspecs.sign;
1677 size_t size = to_unsigned(significand_size) + (sign ? 1 : 0);
1678 using iterator = reserve_iterator<OutputIt>;
1679
1680 int output_exp = fp.exponent + significand_size - 1;
1681 auto use_exp_format = [=]() {
1682 if (fspecs.format == float_format::exp) return true;
1683 if (fspecs.format != float_format::general) return false;
1684 // Use the fixed notation if the exponent is in [exp_lower, exp_upper),
1685 // e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation.
1686 const int exp_lower = -4, exp_upper = 16;
1687 return output_exp < exp_lower ||
1688 output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper);
1689 };
1690 if (use_exp_format()) {
1691 int num_zeros = 0;
1692 if (fspecs.showpoint) {
1693 num_zeros = fspecs.precision - significand_size;
1694 if (num_zeros < 0) num_zeros = 0;
1695 size += to_unsigned(num_zeros);
1696 } else if (significand_size == 1) {
1697 decimal_point = Char();
1698 }
1699 auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp;
1700 int exp_digits = 2;
1701 if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3;
1702
1703 size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits);
1704 char exp_char = fspecs.upper ? 'E' : 'e';
1705 auto write = [=](iterator it) {
1706 if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1707 // Insert a decimal point after the first digit and add an exponent.
1708 it = write_significand(it, significand, significand_size, 1,
1710 if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero);
1711 *it++ = static_cast<Char>(exp_char);
1712 return write_exponent<Char>(output_exp, it);
1713 };
1714 return specs.width > 0 ? write_padded<align::right>(out, specs, size, write)
1715 : base_iterator(out, write(reserve(out, size)));
1716 }
1717
1718 int exp = fp.exponent + significand_size;
1719 if (fp.exponent >= 0) {
1720 // 1234e5 -> 123400000[.0+]
1721 size += to_unsigned(fp.exponent);
1722 int num_zeros = fspecs.precision - exp;
1723#ifdef FMT_FUZZ
1724 if (num_zeros > 5000)
1725 throw std::runtime_error("fuzz mode - avoiding excessive cpu use");
1726#endif
1727 if (fspecs.showpoint) {
1728 if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 1;
1729 if (num_zeros > 0) size += to_unsigned(num_zeros) + 1;
1730 }
1731 return write_padded<align::right>(out, specs, size, [&](iterator it) {
1732 if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1733 it = write_significand<Char>(it, significand, significand_size);
1734 it = detail::fill_n(it, fp.exponent, zero);
1735 if (!fspecs.showpoint) return it;
1736 *it++ = decimal_point;
1737 return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
1738 });
1739 } else if (exp > 0) {
1740 // 1234e-2 -> 12.34[0+]
1741 int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0;
1742 size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0);
1743 return write_padded<align::right>(out, specs, size, [&](iterator it) {
1744 if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1745 it = write_significand(it, significand, significand_size, exp,
1747 return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it;
1748 });
1749 }
1750 // 1234e-6 -> 0.001234
1751 int num_zeros = -exp;
1752 if (significand_size == 0 && fspecs.precision >= 0 &&
1753 fspecs.precision < num_zeros) {
1754 num_zeros = fspecs.precision;
1755 }
1756 bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint;
1757 size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros);
1758 return write_padded<align::right>(out, specs, size, [&](iterator it) {
1759 if (sign) *it++ = static_cast<Char>(data::signs[sign]);
1760 *it++ = zero;
1761 if (!pointy) return it;
1762 *it++ = decimal_point;
1763 it = detail::fill_n(it, num_zeros, zero);
1764 return write_significand<Char>(it, significand, significand_size);
1765 });
1766}
1767
1768template <typename Char, typename OutputIt, typename T,
1770auto write(OutputIt out, T value, basic_format_specs<Char> specs,
1771 locale_ref loc = {}) -> OutputIt {
1773 float_specs fspecs = parse_float_type_spec(specs);
1774 fspecs.sign = specs.sign;
1775 if (std::signbit(value)) { // value < 0 is false for NaN so use signbit.
1776 fspecs.sign = sign::minus;
1777 value = -value;
1778 } else if (fspecs.sign == sign::minus) {
1779 fspecs.sign = sign::none;
1780 }
1781
1782 if (!std::isfinite(value))
1783 return write_nonfinite(out, std::isinf(value), specs, fspecs);
1784
1785 if (specs.align == align::numeric && fspecs.sign) {
1786 auto it = reserve(out, 1);
1787 *it++ = static_cast<Char>(data::signs[fspecs.sign]);
1788 out = base_iterator(out, it);
1789 fspecs.sign = sign::none;
1790 if (specs.width != 0) --specs.width;
1791 }
1792
1794 if (fspecs.format == float_format::hex) {
1795 if (fspecs.sign) buffer.push_back(data::signs[fspecs.sign]);
1797 return write_bytes<align::right>(out, {buffer.data(), buffer.size()},
1798 specs);
1799 }
1800 int precision = specs.precision >= 0 || !specs.type ? specs.precision : 6;
1801 if (fspecs.format == float_format::exp) {
1802 if (precision == max_value<int>())
1803 FMT_THROW(format_error("number is too big"));
1804 else
1805 ++precision;
1806 }
1807 if (const_check(std::is_same<T, float>())) fspecs.binary32 = true;
1808 fspecs.use_grisu = is_fast_float<T>();
1809 int exp = format_float(promote_float(value), precision, fspecs, buffer);
1810 fspecs.precision = precision;
1811 Char point =
1812 fspecs.locale ? decimal_point<Char>(loc) : static_cast<Char>('.');
1813 auto fp = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp};
1814 return write_float(out, fp, specs, fspecs, point);
1815}
1816
1817template <typename Char, typename OutputIt, typename T,
1818 FMT_ENABLE_IF(is_fast_float<T>::value)>
1819auto write(OutputIt out, T value) -> OutputIt {
1821
1823 using uint = typename dragonbox::float_info<floaty>::carrier_uint;
1824 auto bits = bit_cast<uint>(value);
1825
1826 auto fspecs = float_specs();
1827 auto sign_bit = bits & (uint(1) << (num_bits<uint>() - 1));
1828 if (sign_bit != 0) {
1829 fspecs.sign = sign::minus;
1830 value = -value;
1831 }
1832
1833 static const auto specs = basic_format_specs<Char>();
1834 uint mask = exponent_mask<floaty>();
1835 if ((bits & mask) == mask)
1836 return write_nonfinite(out, std::isinf(value), specs, fspecs);
1837
1838 auto dec = dragonbox::to_decimal(static_cast<floaty>(value));
1839 return write_float(out, dec, specs, fspecs, static_cast<Char>('.'));
1840}
1841
1842template <typename Char, typename OutputIt, typename T,
1844 !is_fast_float<T>::value)>
1845inline auto write(OutputIt out, T value) -> OutputIt {
1846 return write(out, value, basic_format_specs<Char>());
1847}
1848
1849template <typename Char, typename OutputIt>
1851 locale_ref = {}) -> OutputIt {
1852 FMT_ASSERT(false, "");
1853 return out;
1854}
1855
1856template <typename Char, typename OutputIt>
1858 -> OutputIt {
1859 auto it = reserve(out, value.size());
1860 it = copy_str_noinline<Char>(value.begin(), value.end(), it);
1861 return base_iterator(out, it);
1862}
1863
1864template <typename Char, typename OutputIt, typename T,
1866constexpr auto write(OutputIt out, const T& value) -> OutputIt {
1867 return write<Char>(out, to_string_view(value));
1868}
1869
1870template <typename Char, typename OutputIt, typename T,
1874FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
1875 auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value);
1876 bool negative = is_negative(value);
1877 // Don't do -abs_value since it trips unsigned-integer-overflow sanitizer.
1878 if (negative) abs_value = ~abs_value + 1;
1879 int num_digits = count_digits(abs_value);
1880 auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits);
1881 auto it = reserve(out, size);
1882 if (auto ptr = to_pointer<Char>(it, size)) {
1883 if (negative) *ptr++ = static_cast<Char>('-');
1884 format_decimal<Char>(ptr, abs_value, num_digits);
1885 return out;
1886 }
1887 if (negative) *it++ = static_cast<Char>('-');
1888 it = format_decimal<Char>(it, abs_value, num_digits).end;
1889 return base_iterator(out, it);
1890}
1891
1892// FMT_ENABLE_IF() condition separated to workaround MSVC bug
1893template <
1894 typename Char, typename OutputIt, typename T,
1895 bool check =
1899 FMT_ENABLE_IF(check)>
1900FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt {
1901 return write<Char>(
1902 out, static_cast<typename std::underlying_type<T>::type>(value));
1903}
1904
1905template <typename Char, typename OutputIt, typename T,
1907FMT_CONSTEXPR auto write(OutputIt out, T value,
1908 const basic_format_specs<Char>& specs = {},
1909 locale_ref = {}) -> OutputIt {
1910 return specs.type && specs.type != 's'
1911 ? write(out, value ? 1 : 0, specs, {})
1912 : write_bytes(out, value ? "true" : "false", specs);
1913}
1914
1915template <typename Char, typename OutputIt>
1916FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt {
1917 auto it = reserve(out, 1);
1918 *it++ = value;
1919 return base_iterator(out, it);
1920}
1921
1922template <typename Char, typename OutputIt>
1923FMT_CONSTEXPR_CHAR_TRAITS auto write(OutputIt out, const Char* value)
1924 -> OutputIt {
1925 if (!value) {
1926 FMT_THROW(format_error("string pointer is null"));
1927 } else {
1929 out = write(out, basic_string_view<Char>(value, length));
1930 }
1931 return out;
1932}
1933
1934template <typename Char, typename OutputIt, typename T,
1936auto write(OutputIt out, const T* value,
1937 const basic_format_specs<Char>& specs = {}, locale_ref = {})
1938 -> OutputIt {
1940 return write_ptr<Char>(out, to_uintptr(value), &specs);
1941}
1942
1943template <typename Char, typename OutputIt, typename T>
1944FMT_CONSTEXPR auto write(OutputIt out, const T& value) ->
1945 typename std::enable_if<
1948 OutputIt>::type {
1949 using context_type = basic_format_context<OutputIt, Char>;
1950 using formatter_type =
1952 typename context_type::template formatter_type<T>,
1954 context_type ctx(out, {}, {});
1955 return formatter_type().format(value, ctx);
1956}
1957
1958// An argument visitor that formats the argument and writes it via the output
1959// iterator. It's a class and not a generic lambda for compatibility with C++11.
1960template <typename Char> struct default_arg_formatter {
1963
1967
1968 template <typename T> auto operator()(T value) -> iterator {
1969 return write<Char>(out, value);
1970 }
1973 context format_ctx(out, args, loc);
1974 h.format(parse_ctx, format_ctx);
1975 return format_ctx.out();
1976 }
1977};
1978
1979template <typename Char> struct arg_formatter {
1982
1986
1987 template <typename T>
1989 return detail::write(out, value, specs, locale);
1990 }
1992 // User-defined types are handled separately because they require access
1993 // to the parse context.
1994 return out;
1995 }
1996};
1997
1998template <typename Char> struct custom_formatter {
2001
2003 typename basic_format_arg<buffer_context<Char>>::handle h) const {
2004 h.format(parse_ctx, ctx);
2005 }
2006 template <typename T> void operator()(T) const {}
2007};
2008
2009template <typename T>
2014
2015template <typename ErrorHandler> class width_checker {
2016 public:
2017 explicit FMT_CONSTEXPR width_checker(ErrorHandler& eh) : handler_(eh) {}
2018
2019 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2020 FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
2021 if (is_negative(value)) handler_.on_error("negative width");
2022 return static_cast<unsigned long long>(value);
2023 }
2024
2025 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2026 FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
2027 handler_.on_error("width is not integer");
2028 return 0;
2029 }
2030
2031 private:
2032 ErrorHandler& handler_;
2033};
2034
2035template <typename ErrorHandler> class precision_checker {
2036 public:
2037 explicit FMT_CONSTEXPR precision_checker(ErrorHandler& eh) : handler_(eh) {}
2038
2039 template <typename T, FMT_ENABLE_IF(is_integer<T>::value)>
2040 FMT_CONSTEXPR auto operator()(T value) -> unsigned long long {
2041 if (is_negative(value)) handler_.on_error("negative precision");
2042 return static_cast<unsigned long long>(value);
2043 }
2044
2045 template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)>
2046 FMT_CONSTEXPR auto operator()(T) -> unsigned long long {
2047 handler_.on_error("precision is not integer");
2048 return 0;
2049 }
2050
2051 private:
2052 ErrorHandler& handler_;
2053};
2054
2055template <template <typename> class Handler, typename FormatArg,
2056 typename ErrorHandler>
2057FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int {
2058 unsigned long long value = visit_format_arg(Handler<ErrorHandler>(eh), arg);
2059 if (value > to_unsigned(max_value<int>())) eh.on_error("number is too big");
2060 return static_cast<int>(value);
2061}
2062
2063template <typename Context, typename ID>
2064FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) ->
2065 typename Context::format_arg {
2066 auto arg = ctx.arg(id);
2067 if (!arg) ctx.on_error("argument not found");
2068 return arg;
2069}
2070
2071// The standard format specifier handler with checking.
2072template <typename Char> class specs_handler : public specs_setter<Char> {
2073 private:
2076
2077 // This is only needed for compatibility with gcc 4.4.
2079
2081 return detail::get_arg(context_, parse_context_.next_arg_id());
2082 }
2083
2084 FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg {
2085 parse_context_.check_arg_id(arg_id);
2086 return detail::get_arg(context_, arg_id);
2087 }
2088
2090 parse_context_.check_arg_id(arg_id);
2091 return detail::get_arg(context_, arg_id);
2092 }
2093
2094 public:
2098 : specs_setter<Char>(specs), parse_context_(parse_ctx), context_(ctx) {}
2099
2100 template <typename Id> FMT_CONSTEXPR void on_dynamic_width(Id arg_id) {
2101 this->specs_.width = get_dynamic_spec<width_checker>(
2102 get_arg(arg_id), context_.error_handler());
2103 }
2104
2105 template <typename Id> FMT_CONSTEXPR void on_dynamic_precision(Id arg_id) {
2106 this->specs_.precision = get_dynamic_spec<precision_checker>(
2107 get_arg(arg_id), context_.error_handler());
2108 }
2109
2110 void on_error(const char* message) { context_.on_error(message); }
2111};
2112
2113template <template <typename> class Handler, typename Context>
2116 Context& ctx) {
2117 switch (ref.kind) {
2118 case arg_id_kind::none:
2119 break;
2120 case arg_id_kind::index:
2121 value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.index),
2122 ctx.error_handler());
2123 break;
2124 case arg_id_kind::name:
2125 value = detail::get_dynamic_spec<Handler>(ctx.arg(ref.val.name),
2126 ctx.error_handler());
2127 break;
2128 }
2129}
2130
2131#define FMT_STRING_IMPL(s, base, explicit) \
2132 [] { \
2133 /* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \
2134 /* Use a macro-like name to avoid shadowing warnings. */ \
2135 struct FMT_GCC_VISIBILITY_HIDDEN FMT_COMPILE_STRING : base { \
2136 using char_type = fmt::remove_cvref_t<decltype(s[0])>; \
2137 FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \
2138 operator fmt::basic_string_view<char_type>() const { \
2139 return fmt::detail_exported::compile_string_to_view<char_type>(s); \
2140 } \
2141 }; \
2142 return FMT_COMPILE_STRING(); \
2143 }()
2144
2145/**
2146 \rst
2147 Constructs a compile-time format string from a string literal *s*.
2148
2149 **Example**::
2150
2151 // A compile-time error because 'd' is an invalid specifier for strings.
2152 std::string s = fmt::format(FMT_STRING("{:d}"), "foo");
2153 \endrst
2154 */
2155#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::compile_string, )
2156
2157#if FMT_USE_USER_DEFINED_LITERALS
2158template <typename Char> struct udl_formatter {
2160
2161 template <typename... T>
2162 auto operator()(T&&... args) const -> std::basic_string<Char> {
2163 return vformat(str, fmt::make_args_checked<T...>(str, args...));
2164 }
2165};
2166
2167# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
2168template <typename T, typename Char, size_t N,
2169 fmt::detail_exported::fixed_string<Char, N> Str>
2170struct statically_named_arg : view {
2171 static constexpr auto name = Str.data;
2172
2173 const T& value;
2174 statically_named_arg(const T& v) : value(v) {}
2175};
2176
2177template <typename T, typename Char, size_t N,
2178 fmt::detail_exported::fixed_string<Char, N> Str>
2179struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
2180
2181template <typename T, typename Char, size_t N,
2182 fmt::detail_exported::fixed_string<Char, N> Str>
2183struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
2184 : std::true_type {};
2185
2186template <typename Char, size_t N,
2187 fmt::detail_exported::fixed_string<Char, N> Str>
2188struct udl_arg {
2189 template <typename T> auto operator=(T&& value) const {
2190 return statically_named_arg<T, Char, N, Str>(std::forward<T>(value));
2191 }
2192};
2193# else
2194template <typename Char> struct udl_arg {
2195 const Char* str;
2196
2197 template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> {
2198 return {str, std::forward<T>(value)};
2199 }
2200};
2201# endif
2202#endif // FMT_USE_USER_DEFINED_LITERALS
2203
2204template <typename Locale, typename Char>
2205auto vformat(const Locale& loc, basic_string_view<Char> format_str,
2209 detail::vformat_to(buffer, format_str, args, detail::locale_ref(loc));
2210 return {buffer.data(), buffer.size()};
2211}
2212
2213using format_func = void (*)(detail::buffer<char>&, int, const char*);
2214
2215FMT_API void format_error_code(buffer<char>& out, int error_code,
2216 string_view message) FMT_NOEXCEPT;
2217
2218FMT_API void report_error(format_func func, int error_code,
2219 const char* message) FMT_NOEXCEPT;
2221
2222FMT_API auto vsystem_error(int error_code, string_view format_str,
2224
2225/**
2226 \rst
2227 Constructs :class:`std::system_error` with a message formatted with
2228 ``fmt::format(fmt, args...)``.
2229 *error_code* is a system error code as given by ``errno``.
2230
2231 **Example**::
2232
2233 // This throws std::system_error with the description
2234 // cannot open file 'madeup': No such file or directory
2235 // or similar (system message may vary).
2236 const char* filename = "madeup";
2237 std::FILE* file = std::fopen(filename, "r");
2238 if (!file)
2239 throw fmt::system_error(errno, "cannot open file '{}'", filename);
2240 \endrst
2241*/
2242template <typename... T>
2243auto system_error(int error_code, format_string<T...> fmt, T&&... args)
2245 return vsystem_error(error_code, fmt, fmt::make_format_args(args...));
2246}
2247
2248/**
2249 \rst
2250 Formats an error message for an error returned by an operating system or a
2251 language runtime, for example a file opening error, and writes it to *out*.
2252 The format is the same as the one used by ``std::system_error(ec, message)``
2253 where ``ec`` is ``std::error_code(error_code, std::generic_category()})``.
2254 It is implementation-defined but normally looks like:
2255
2256 .. parsed-literal::
2257 *<message>*: *<system-message>*
2258
2259 where *<message>* is the passed message and *<system-message>* is the system
2260 message corresponding to the error code.
2261 *error_code* is a system error code as given by ``errno``.
2262 \endrst
2263 */
2264FMT_API void format_system_error(detail::buffer<char>& out, int error_code,
2265 const char* message) FMT_NOEXCEPT;
2266
2267// Reports a system error without throwing an exception.
2268// Can be used to report errors from destructors.
2269FMT_API void report_system_error(int error_code,
2270 const char* message) FMT_NOEXCEPT;
2271
2272/** Fast integer formatter. */
2274 private:
2275 // Buffer should be large enough to hold all digits (digits10 + 1),
2276 // a sign and a null character.
2278 mutable char buffer_[buffer_size];
2279 char* str_;
2280
2281 template <typename UInt> auto format_unsigned(UInt value) -> char* {
2282 auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value);
2283 return detail::format_decimal(buffer_, n, buffer_size - 1).begin;
2284 }
2285
2286 template <typename Int> auto format_signed(Int value) -> char* {
2287 auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value);
2288 bool negative = value < 0;
2289 if (negative) abs_value = 0 - abs_value;
2290 auto begin = format_unsigned(abs_value);
2291 if (negative) *--begin = '-';
2292 return begin;
2293 }
2294
2295 public:
2296 explicit format_int(int value) : str_(format_signed(value)) {}
2297 explicit format_int(long value) : str_(format_signed(value)) {}
2298 explicit format_int(long long value) : str_(format_signed(value)) {}
2299 explicit format_int(unsigned value) : str_(format_unsigned(value)) {}
2300 explicit format_int(unsigned long value) : str_(format_unsigned(value)) {}
2301 explicit format_int(unsigned long long value)
2302 : str_(format_unsigned(value)) {}
2303
2304 /** Returns the number of characters written to the output buffer. */
2305 auto size() const -> size_t {
2306 return detail::to_unsigned(buffer_ - str_ + buffer_size - 1);
2307 }
2308
2309 /**
2310 Returns a pointer to the output buffer content. No terminating null
2311 character is appended.
2312 */
2313 auto data() const -> const char* { return str_; }
2314
2315 /**
2316 Returns a pointer to the output buffer content with terminating null
2317 character appended.
2318 */
2319 auto c_str() const -> const char* {
2320 buffer_[buffer_size - 1] = '\0';
2321 return str_;
2322 }
2323
2324 /**
2325 \rst
2326 Returns the content of the output buffer as an ``std::string``.
2327 \endrst
2328 */
2329 auto str() const -> std::string { return std::string(str_, size()); }
2330};
2331
2332template <typename T, typename Char>
2333template <typename FormatContext>
2335formatter<T, Char,
2336 enable_if_t<detail::type_constant<T, Char>::value !=
2337 detail::type::custom_type>>::format(const T& val,
2338 FormatContext& ctx)
2339 const -> decltype(ctx.out()) {
2340 if (specs_.width_ref.kind != detail::arg_id_kind::none ||
2341 specs_.precision_ref.kind != detail::arg_id_kind::none) {
2342 auto specs = specs_;
2343 detail::handle_dynamic_spec<detail::width_checker>(specs.width,
2344 specs.width_ref, ctx);
2345 detail::handle_dynamic_spec<detail::precision_checker>(
2346 specs.precision, specs.precision_ref, ctx);
2347 return detail::write<Char>(ctx.out(), val, specs, ctx.locale());
2348 }
2349 return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
2350}
2351
2352#define FMT_FORMAT_AS(Type, Base) \
2353 template <typename Char> \
2354 struct formatter<Type, Char> : formatter<Base, Char> { \
2355 template <typename FormatContext> \
2356 auto format(Type const& val, FormatContext& ctx) const \
2357 -> decltype(ctx.out()) { \
2358 return formatter<Base, Char>::format(static_cast<Base>(val), ctx); \
2359 } \
2360 }
2361
2362FMT_FORMAT_AS(signed char, int);
2363FMT_FORMAT_AS(unsigned char, unsigned);
2364FMT_FORMAT_AS(short, int);
2365FMT_FORMAT_AS(unsigned short, unsigned);
2366FMT_FORMAT_AS(long, long long);
2367FMT_FORMAT_AS(unsigned long, unsigned long long);
2368FMT_FORMAT_AS(Char*, const Char*);
2371FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
2372
2373template <typename Char>
2375 template <typename FormatContext>
2376 auto format(void* val, FormatContext& ctx) const -> decltype(ctx.out()) {
2377 return formatter<const void*, Char>::format(val, ctx);
2378 }
2379};
2380
2381template <typename Char, size_t N>
2382struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {
2383 template <typename FormatContext>
2384 FMT_CONSTEXPR auto format(const Char* val, FormatContext& ctx) const
2385 -> decltype(ctx.out()) {
2386 return formatter<basic_string_view<Char>, Char>::format(val, ctx);
2387 }
2388};
2389
2390// A formatter for types known only at run time such as variant alternatives.
2391//
2392// Usage:
2393// using variant = std::variant<int, std::string>;
2394// template <>
2395// struct formatter<variant>: dynamic_formatter<> {
2396// auto format(const variant& v, format_context& ctx) {
2397// return visit([&](const auto& val) {
2398// return dynamic_formatter<>::format(val, ctx);
2399// }, v);
2400// }
2401// };
2402template <typename Char = char> class dynamic_formatter {
2403 private:
2404 detail::dynamic_format_specs<Char> specs_;
2405 const Char* format_str_;
2406
2407 struct null_handler : detail::error_handler {
2410 void on_hash() {}
2411 };
2412
2413 template <typename Context> void handle_specs(Context& ctx) {
2414 detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
2415 specs_.width_ref, ctx);
2416 detail::handle_dynamic_spec<detail::precision_checker>(
2417 specs_.precision, specs_.precision_ref, ctx);
2418 }
2419
2420 public:
2421 template <typename ParseContext>
2422 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2423 format_str_ = ctx.begin();
2424 // Checks are deferred to formatting time when the argument type is known.
2425 detail::dynamic_specs_handler<ParseContext> handler(specs_, ctx);
2426 return detail::parse_format_specs(ctx.begin(), ctx.end(), handler);
2427 }
2428
2429 template <typename T, typename FormatContext>
2430 auto format(const T& val, FormatContext& ctx) -> decltype(ctx.out()) {
2431 handle_specs(ctx);
2432 detail::specs_checker<null_handler> checker(
2433 null_handler(), detail::mapped_type_constant<T, FormatContext>::value);
2434 checker.on_align(specs_.align);
2435 if (specs_.sign != sign::none) checker.on_sign(specs_.sign);
2436 if (specs_.alt) checker.on_hash();
2437 if (specs_.precision >= 0) checker.end_precision();
2438 return detail::write<Char>(ctx.out(), val, specs_, ctx.locale());
2439 }
2440};
2441
2442/**
2443 \rst
2444 Converts ``p`` to ``const void*`` for pointer formatting.
2445
2446 **Example**::
2447
2448 auto s = fmt::format("{}", fmt::ptr(p));
2449 \endrst
2450 */
2451template <typename T> auto ptr(T p) -> const void* {
2452 static_assert(std::is_pointer<T>::value, "");
2453 return detail::bit_cast<const void*>(p);
2454}
2455template <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* {
2456 return p.get();
2457}
2458template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
2459 return p.get();
2460}
2461
2462class bytes {
2463 private:
2465 friend struct formatter<bytes>;
2466
2467 public:
2468 explicit bytes(string_view data) : data_(data) {}
2469};
2470
2471template <> struct formatter<bytes> {
2472 private:
2473 detail::dynamic_format_specs<char> specs_;
2474
2475 public:
2476 template <typename ParseContext>
2477 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2478 using handler_type = detail::dynamic_specs_handler<ParseContext>;
2479 detail::specs_checker<handler_type> handler(handler_type(specs_, ctx),
2480 detail::type::string_type);
2481 auto it = parse_format_specs(ctx.begin(), ctx.end(), handler);
2482 detail::check_string_type_spec(specs_.type, ctx.error_handler());
2483 return it;
2484 }
2485
2486 template <typename FormatContext>
2487 auto format(bytes b, FormatContext& ctx) -> decltype(ctx.out()) {
2488 detail::handle_dynamic_spec<detail::width_checker>(specs_.width,
2489 specs_.width_ref, ctx);
2490 detail::handle_dynamic_spec<detail::precision_checker>(
2491 specs_.precision, specs_.precision_ref, ctx);
2492 return detail::write_bytes(ctx.out(), b.data_, specs_);
2493 }
2494};
2495
2496template <typename It, typename Sentinel, typename Char = char>
2497struct join_view : detail::view {
2499 Sentinel end;
2501
2503 : begin(b), end(e), sep(s) {}
2504};
2505
2506template <typename It, typename Sentinel, typename Char>
2508
2509template <typename It, typename Sentinel, typename Char>
2510struct formatter<join_view<It, Sentinel, Char>, Char> {
2511 private:
2514 using mapper = detail::arg_mapper<context>;
2515
2516 template <typename T, FMT_ENABLE_IF(has_formatter<T, context>::value)>
2517 static auto map(const T& value) -> const T& {
2518 return value;
2519 }
2520 template <typename T, FMT_ENABLE_IF(!has_formatter<T, context>::value)>
2521 static auto map(const T& value) -> decltype(mapper().map(value)) {
2522 return mapper().map(value);
2523 }
2524
2527 formatter<remove_cvref_t<decltype(map(
2529 Char>,
2530 detail::fallback_formatter<value_type, Char>>;
2531
2533
2534 public:
2535 template <typename ParseContext>
2536 FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) {
2537 return value_formatter_.parse(ctx);
2538 }
2539
2540 template <typename FormatContext>
2541 auto format(const join_view<It, Sentinel, Char>& value, FormatContext& ctx)
2542 -> decltype(ctx.out()) {
2543 auto it = value.begin;
2544 auto out = ctx.out();
2545 if (it != value.end) {
2546 out = value_formatter_.format(map(*it++), ctx);
2547 while (it != value.end) {
2548 out = detail::copy_str<Char>(value.sep.begin(), value.sep.end(), out);
2549 ctx.advance_to(out);
2550 out = value_formatter_.format(map(*it++), ctx);
2551 }
2552 }
2553 return out;
2554 }
2555};
2556
2557/**
2558 Returns an object that formats the iterator range `[begin, end)` with
2559 elements separated by `sep`.
2560 */
2561template <typename It, typename Sentinel>
2562auto join(It begin, Sentinel end, string_view sep) -> join_view<It, Sentinel> {
2563 return {begin, end, sep};
2564}
2565
2566/**
2567 \rst
2568 Returns an object that formats `range` with elements separated by `sep`.
2569
2570 **Example**::
2571
2572 std::vector<int> v = {1, 2, 3};
2573 fmt::print("{}", fmt::join(v, ", "));
2574 // Output: "1, 2, 3"
2575
2576 ``fmt::join`` applies passed format specifiers to the range elements::
2577
2578 fmt::print("{:02}", fmt::join(v, ", "));
2579 // Output: "01, 02, 03"
2580 \endrst
2581 */
2582template <typename Range>
2583auto join(Range&& range, string_view sep)
2585 return join(std::begin(range), std::end(range), sep);
2586}
2587
2588/**
2589 \rst
2590 Converts *value* to ``std::string`` using the default format for type *T*.
2591
2592 **Example**::
2593
2594 #include <fmt/format.h>
2595
2596 std::string answer = fmt::to_string(42);
2597 \endrst
2598 */
2599template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
2600inline auto to_string(const T& value) -> std::string {
2601 auto result = std::string();
2602 detail::write<char>(std::back_inserter(result), value);
2603 return result;
2604}
2605
2606template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
2607inline auto to_string(T value) -> std::string {
2608 // The buffer should be large enough to store the number including the sign
2609 // or "false" for bool.
2610 constexpr int max_size = detail::digits10<T>() + 2;
2611 char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5];
2612 char* begin = buffer;
2613 return std::string(begin, detail::write<char>(begin, value));
2614}
2615
2616template <typename Char, size_t SIZE>
2619 auto size = buf.size();
2620 detail::assume(size < std::basic_string<Char>().max_size());
2621 return std::basic_string<Char>(buf.data(), size);
2622}
2623
2625
2626template <typename Char>
2630 locale_ref loc) {
2631 // workaround for msvc bug regarding name-lookup in module
2632 // link names into function scope
2633 using detail::arg_formatter;
2634 using detail::buffer_appender;
2635 using detail::custom_formatter;
2636 using detail::default_arg_formatter;
2637 using detail::get_arg;
2638 using detail::locale_ref;
2639 using detail::parse_format_specs;
2640 using detail::specs_checker;
2641 using detail::specs_handler;
2642 using detail::to_unsigned;
2643 using detail::type;
2644 using detail::write;
2645 auto out = buffer_appender<Char>(buf);
2646 if (fmt.size() == 2 && equal2(fmt.data(), "{}")) {
2647 auto arg = args.get(0);
2648 if (!arg) error_handler().on_error("argument not found");
2650 return;
2651 }
2652
2653 struct format_handler : error_handler {
2655 buffer_context<Char> context;
2656
2657 format_handler(buffer_appender<Char> out, basic_string_view<Char> str,
2659 : parse_context(str), context(out, args, loc) {}
2660
2661 void on_text(const Char* begin, const Char* end) {
2662 auto text = basic_string_view<Char>(begin, to_unsigned(end - begin));
2663 context.advance_to(write<Char>(context.out(), text));
2664 }
2665
2666 FMT_CONSTEXPR auto on_arg_id() -> int {
2667 return parse_context.next_arg_id();
2668 }
2669 FMT_CONSTEXPR auto on_arg_id(int id) -> int {
2670 return parse_context.check_arg_id(id), id;
2671 }
2672 FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int {
2673 int arg_id = context.arg_id(id);
2674 if (arg_id < 0) on_error("argument not found");
2675 return arg_id;
2676 }
2677
2678 FMT_INLINE void on_replacement_field(int id, const Char*) {
2679 auto arg = get_arg(context, id);
2681 default_arg_formatter<Char>{context.out(), context.args(),
2682 context.locale()},
2683 arg));
2684 }
2685
2686 auto on_format_specs(int id, const Char* begin, const Char* end)
2687 -> const Char* {
2688 auto arg = get_arg(context, id);
2689 if (arg.type() == type::custom_type) {
2690 parse_context.advance_to(parse_context.begin() +
2691 (begin - &*parse_context.begin()));
2692 visit_format_arg(custom_formatter<Char>{parse_context, context}, arg);
2693 return parse_context.begin();
2694 }
2695 auto specs = basic_format_specs<Char>();
2697 specs_handler<Char>(specs, parse_context, context), arg.type());
2698 begin = parse_format_specs(begin, end, handler);
2699 if (begin == end || *begin != '}')
2700 on_error("missing '}' in format string");
2701 auto f = arg_formatter<Char>{context.out(), specs, context.locale()};
2702 context.advance_to(visit_format_arg(f, arg));
2703 return begin;
2704 }
2705 };
2706 detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc));
2707}
2708
2709#ifndef FMT_HEADER_ONLY
2715extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
2716extern template auto format_float<double>(double value, int precision,
2717 float_specs specs, buffer<char>& buf)
2718 -> int;
2719extern template auto format_float<long double>(long double value, int precision,
2720 float_specs specs,
2721 buffer<char>& buf) -> int;
2722void snprintf_float(float, int, float_specs, buffer<char>&) = delete;
2723extern template auto snprintf_float<double>(double value, int precision,
2724 float_specs specs,
2725 buffer<char>& buf) -> int;
2726extern template auto snprintf_float<long double>(long double value,
2727 int precision,
2728 float_specs specs,
2729 buffer<char>& buf) -> int;
2730#endif // FMT_HEADER_ONLY
2731
2733
2734#if FMT_USE_USER_DEFINED_LITERALS
2735inline namespace literals {
2736/**
2737 \rst
2738 User-defined literal equivalent of :func:`fmt::arg`.
2739
2740 **Example**::
2741
2742 using namespace fmt::literals;
2743 fmt::print("Elapsed time: {s:.2f} seconds", "s"_a=1.23);
2744 \endrst
2745 */
2746# if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
2747template <detail_exported::fixed_string Str>
2748constexpr auto operator""_a()
2749 -> detail::udl_arg<remove_cvref_t<decltype(Str.data[0])>,
2750 sizeof(Str.data) / sizeof(decltype(Str.data[0])), Str> {
2751 return {};
2752}
2753# else
2754constexpr auto operator"" _a(const char* s, size_t) -> detail::udl_arg<char> {
2755 return {s};
2756}
2757# endif
2758
2759/**
2760 \rst
2761 User-defined literal equivalent of :func:`fmt::format`.
2762
2763 **Example**::
2764
2765 using namespace fmt::literals;
2766 std::string message = "The answer is {}"_format(42);
2767 \endrst
2768 */
2769constexpr auto operator"" _format(const char* s, size_t n)
2770 -> detail::udl_formatter<char> {
2771 return {{s, n}};
2772}
2773} // namespace literals
2774#endif // FMT_USE_USER_DEFINED_LITERALS
2775
2776template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
2777inline auto vformat(const Locale& loc, string_view fmt, format_args args)
2778 -> std::string {
2779 return detail::vformat(loc, fmt, args);
2780}
2781
2782template <typename Locale, typename... T,
2784inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args)
2785 -> std::string {
2786 return vformat(loc, string_view(fmt), fmt::make_format_args(args...));
2787}
2788
2789template <typename... T, size_t SIZE, typename Allocator>
2791 format_string<T...> fmt, T&&... args)
2792 -> appender {
2793 detail::vformat_to(buf, string_view(fmt), fmt::make_format_args(args...));
2794 return appender(buf);
2795}
2796
2797template <typename OutputIt, typename Locale,
2798 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
2800auto vformat_to(OutputIt out, const Locale& loc, string_view fmt,
2801 format_args args) -> OutputIt {
2802 using detail::get_buffer;
2803 auto&& buf = get_buffer<char>(out);
2804 detail::vformat_to(buf, fmt, args, detail::locale_ref(loc));
2805 return detail::get_iterator(buf);
2806}
2807
2808template <typename OutputIt, typename Locale, typename... T,
2809 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
2811FMT_INLINE auto format_to(OutputIt out, const Locale& loc,
2812 format_string<T...> fmt, T&&... args) -> OutputIt {
2813 return vformat_to(out, loc, fmt, fmt::make_format_args(args...));
2814}
2815
2818
2819#ifdef FMT_DEPRECATED_INCLUDE_XCHAR
2820# include "xchar.h"
2821#endif
2822
2823#ifdef FMT_HEADER_ONLY
2824# define FMT_FUNC inline
2825# include "format-inl.h"
2826#else
2827# define FMT_FUNC
2828#endif
2829
2830#endif // FMT_FORMAT_H_
T allocate(T... args)
T back(T... args)
T back_inserter(T... args)
T begin(T... args)
FMT_CONSTEXPR auto locale() -> detail::locale_ref
Definition core.h:1632
FMT_CONSTEXPR auto out() -> iterator
Definition core.h:1625
FMT_CONSTEXPR auto arg_id(basic_string_view< char_type > name) -> int
Definition core.h:1614
void on_error(const char *message)
Definition core.h:1622
FMT_CONSTEXPR auto error_handler() -> detail::error_handler
Definition core.h:1621
auto args() const -> const basic_format_args< basic_format_context > &
Definition core.h:1617
void advance_to(iterator it)
Definition core.h:1628
FMT_CONSTEXPR void check_arg_id(int)
Definition core.h:670
FMT_CONSTEXPR auto next_arg_id() -> int
Definition core.h:658
FMT_CONSTEXPR void advance_to(iterator it)
Definition core.h:650
constexpr auto begin() const FMT_NOEXCEPT -> iterator
Definition core.h:638
Allocator alloc_
Definition format.h:629
const T & const_reference
Definition format.h:642
void reserve(size_t new_capacity)
Definition format.h:701
void move(basic_memory_buffer &other)
Definition format.h:652
auto get_allocator() const -> Allocator
Definition format.h:692
void grow(size_t size) final FMT_OVERRIDE
Definition format.h:712
auto operator=(basic_memory_buffer &&other) FMT_NOEXCEPT -> basic_memory_buffer &
Definition format.h:683
void append(const ContiguousRange &range)
Definition format.h:706
void resize(size_t count)
Definition format.h:698
basic_memory_buffer(basic_memory_buffer &&other) FMT_NOEXCEPT
Definition format.h:676
basic_memory_buffer(const Allocator &alloc=Allocator())
Definition format.h:644
constexpr auto data() const -> const Char *
Definition core.h:481
constexpr auto size() const -> size_t
Definition core.h:484
Definition core.h:749
void append(const U *begin, const U *end)
auto size() const FMT_NOEXCEPT -> size_t
Definition core.h:791
void push_back(const T &value)
Definition core.h:820
auto data() FMT_NOEXCEPT -> T *
Definition core.h:797
string_view data_
Definition format.h:2464
bytes(string_view data)
Definition format.h:2468
detail::dynamic_format_specs< Char > specs_
Definition format.h:2404
void handle_specs(Context &ctx)
Definition format.h:2413
const Char * format_str_
Definition format.h:2405
auto format(const T &val, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:2430
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition format.h:2422
~format_error() FMT_NOEXCEPT FMT_OVERRIDE FMT_MSC_DEFAULT
format_error(const format_error &)=default
format_error & operator=(format_error &&)=default
format_error & operator=(const format_error &)=default
format_error(format_error &&)=default
format_error(const char *message)
Definition format.h:750
format_error(const std::string &message)
Definition format.h:751
format_int(unsigned long long value)
Definition format.h:2301
auto str() const -> std::string
Definition format.h:2329
auto size() const -> size_t
Definition format.h:2305
format_int(int value)
Definition format.h:2296
format_int(long value)
Definition format.h:2297
auto format_signed(Int value) -> char *
Definition format.h:2286
format_int(long long value)
Definition format.h:2298
auto format_unsigned(UInt value) -> char *
Definition format.h:2281
auto c_str() const -> const char *
Definition format.h:2319
auto data() const -> const char *
Definition format.h:2313
format_int(unsigned value)
Definition format.h:2299
char * str_
Definition format.h:2279
format_int(unsigned long value)
Definition format.h:2300
ErrorHandler & handler_
Definition format.h:2052
FMT_CONSTEXPR auto operator()(T) -> unsigned long long
Definition format.h:2046
FMT_CONSTEXPR precision_checker(ErrorHandler &eh)
Definition format.h:2037
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long
Definition format.h:2040
buffer_context< Char > & context_
Definition format.h:2075
basic_format_parse_context< Char > & parse_context_
Definition format.h:2074
FMT_CONSTEXPR auto get_arg(basic_string_view< Char > arg_id) -> format_arg
Definition format.h:2089
FMT_CONSTEXPR void on_dynamic_width(Id arg_id)
Definition format.h:2100
void on_error(const char *message)
Definition format.h:2110
FMT_CONSTEXPR specs_handler(basic_format_specs< Char > &specs, basic_format_parse_context< Char > &parse_ctx, buffer_context< Char > &ctx)
Definition format.h:2095
FMT_CONSTEXPR void on_dynamic_precision(Id arg_id)
Definition format.h:2105
FMT_CONSTEXPR auto get_arg(int arg_id) -> format_arg
Definition format.h:2084
FMT_CONSTEXPR auto get_arg(auto_id) -> format_arg
Definition format.h:2080
auto str() const -> std::wstring
Definition format.h:1149
auto size() const -> size_t
Definition format.h:1147
auto c_str() const -> const wchar_t *
Definition format.h:1148
basic_memory_buffer< wchar_t > buffer_
Definition format.h:1142
Definition core.h:1120
constexpr FMT_INLINE value()
Definition core.h:1143
FMT_CONSTEXPR auto operator()(T) -> unsigned long long
Definition format.h:2026
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long
Definition format.h:2020
FMT_CONSTEXPR width_checker(ErrorHandler &eh)
Definition format.h:2017
ErrorHandler & handler_
Definition format.h:2032
auto format_to(OutputIt out, const text_style &ts, const S &format_str, Args &&... args) -> typename std::enable_if< enable, OutputIt >::type
Definition color.h:617
void vformat_to(buffer< Char > &buf, const text_style &ts, basic_string_view< Char > format_str, basic_format_args< buffer_context< type_identity_t< Char > > > args)
Definition color.h:491
std::basic_string< Char > format(const text_style &ts, const S &format_str, const Args &... args)
Definition color.h:583
std::basic_string< Char > vformat(const text_style &ts, const S &format_str, basic_format_args< buffer_context< type_identity_t< Char > > > args)
Definition color.h:562
#define FMT_OVERRIDE
Definition core.h:124
#define FMT_ASSERT(condition, message)
Definition core.h:372
FMT_CONSTEXPR FMT_INLINE auto visit_format_arg(Visitor &&vis, const basic_format_arg< Context > &arg) -> decltype(vis(0))
Definition core.h:1447
FMT_CONSTEXPR FMT_INLINE auto parse_format_specs(const Char *begin, const Char *end, SpecHandler &&handler) -> const Char *
Definition core.h:2277
FMT_CONSTEXPR auto code_point_length(const Char *begin) -> int
Definition core.h:2064
#define FMT_USE_LONG_DOUBLE
Definition core.h:202
auto arg(const Char *name, const T &arg) -> detail::named_arg< Char, T >
Definition core.h:1725
FMT_CONSTEXPR auto check_char_specs(const basic_format_specs< Char > &specs, ErrorHandler &&eh={}) -> bool
Definition core.h:2498
FMT_CONSTEXPR void check_string_type_spec(Char spec, ErrorHandler &&eh={})
Definition core.h:2581
typename std::remove_reference< T >::type remove_reference_t
Definition core.h:326
typename detail::char_t_impl< S >::type char_t
Definition core.h:610
#define FMT_END_DETAIL_NAMESPACE
Definition core.h:245
#define FMT_MODULE_EXPORT_BEGIN
Definition core.h:242
#define FMT_USE_FLOAT
Definition core.h:196
constexpr auto count() -> size_t
Definition core.h:1039
FMT_CONSTEXPR auto check_cstring_type_spec(Char spec, ErrorHandler &&eh={}) -> bool
Definition core.h:2573
#define FMT_CLASS_API
Definition core.h:256
#define FMT_CONSTEXPR
Definition core.h:99
type
Definition core.h:1048
@ custom_type
FMT_CONSTEXPR void check_pointer_type_spec(Char spec, ErrorHandler &&eh)
Definition core.h:2586
#define FMT_BEGIN_NAMESPACE
Definition core.h:235
#define FMT_BEGIN_DETAIL_NAMESPACE
Definition core.h:244
constexpr auto const_check(T value) -> T
Definition core.h:361
#define FMT_API
Definition core.h:264
FMT_BEGIN_DETAIL_NAMESPACE auto get_container(std::back_insert_iterator< Container > it) -> Container &
Definition core.h:716
#define FMT_BUFFER_CONTEXT(Char)
Definition core.h:1641
conditional_t< std::is_same< T, char >::value, appender, std::back_insert_iterator< buffer< T > > > buffer_appender
Definition core.h:945
FMT_BEGIN_DETAIL_NAMESPACE void throw_format_error(const char *message)
Definition format.h:810
#define FMT_ENABLE_IF(...)
Definition core.h:347
void void_t
Definition core.h:1501
#define FMT_CONSTEXPR_CHAR_TRAITS
Definition core.h:116
#define FMT_INLINE
Definition core.h:209
FMT_CONSTEXPR auto to_unsigned(Int value) -> typename std::make_unsigned< Int >::type
Definition core.h:412
#define FMT_MSC_WARNING(...)
Definition core.h:58
typename type_identity< T >::type type_identity_t
Definition core.h:330
FMT_BEGIN_DETAIL_NAMESPACE constexpr FMT_INLINE auto is_constant_evaluated() FMT_NOEXCEPT -> bool
Definition core.h:352
typename std::conditional< B, T, F >::type conditional_t
Definition core.h:323
typename std::remove_cv< remove_reference_t< T > >::type remove_cvref_t
Definition core.h:328
#define FMT_USE_DOUBLE
Definition core.h:199
T
Definition core.h:320
#define FMT_END_NAMESPACE
Definition core.h:230
#define FMT_MODULE_EXPORT_END
Definition core.h:243
#define FMT_NOEXCEPT
Definition core.h:156
FMT_CONSTEXPR auto parse_float_type_spec(const basic_format_specs< Char > &specs, ErrorHandler &&eh={}) -> float_specs
Definition core.h:2529
int128_t
Definition core.h:402
uint128_t
Definition core.h:403
T end(T... args)
FMT_FUNC std::system_error vsystem_error(int error_code, string_view format_str, format_args args)
Definition format-inl.h:132
FMT_FUNC void format_system_error(detail::buffer< char > &out, int error_code, const char *message) FMT_NOEXCEPT
FMT_FUNC void report_system_error(int error_code, const char *message) FMT_NOEXCEPT
void copy2(Char *dst, const char *src)
Definition format.h:1035
auto system_error(int error_code, format_string< T... > fmt, T &&... args) -> std::system_error
Definition format.h:2243
#define FMT_INC(T)
#define FMT_FORMAT_AS(Type, Base)
Definition format.h:2352
auto decimal_point(locale_ref loc) -> Char
Definition format.h:1019
FMT_API auto decimal_point_impl(locale_ref loc) -> Char
FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, const basic_format_specs< Char > &specs) -> OutputIt
Definition format.h:1304
template auto format_float< long double >(long double value, int precision, float_specs specs, buffer< char > &buf) -> int
FMT_INLINE auto make_args_checked(const S &fmt, const remove_reference_t< Args > &... args) -> format_arg_store< buffer_context< Char >, remove_reference_t< Args >... >
Definition format.h:769
auto write_nonfinite(OutputIt out, bool isinf, basic_format_specs< Char > specs, const float_specs &fspecs) -> OutputIt
Definition format.h:1585
FMT_CONSTEXPR20 auto count_digits(uint64_t n) -> int
Definition format.h:921
FMT_CONSTEXPR auto is_supported_floating_point(T) -> uint16_t
Definition format.h:835
auto join(It begin, Sentinel end, string_view sep) -> join_view< It, Sentinel >
Definition format.h:2562
auto get_significand_size(const big_decimal_fp &fp) -> int
Definition format.h:1609
FMT_CONSTEXPR auto count_digits_fallback(T n) -> int
Definition format.h:899
constexpr auto exponent_mask() -> typename dragonbox::float_info< T >::carrier_uint
Definition format.h:1220
void(*)(detail::buffer< char > &, int, const char *) format_func
Definition format.h:2213
auto format_float(T value, int precision, float_specs specs, buffer< char > &buf) -> int
#define FMT_MSC_DEFAULT
Definition format.h:75
auto write_float(OutputIt out, const DecimalFP &fp, const basic_format_specs< Char > &specs, float_specs fspecs, Char decimal_point) -> OutputIt
Definition format.h:1670
auto snprintf_float(T value, int precision, float_specs specs, buffer< char > &buf) -> int
FMT_CONSTEXPR auto write_char(OutputIt out, Char value, const basic_format_specs< Char > &specs) -> OutputIt
Definition format.h:1329
FMT_API void format_error_code(buffer< char > &out, int error_code, string_view message) FMT_NOEXCEPT
FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result< Char >
FMT_CONSTEXPR void handle_dynamic_spec(int &value, arg_ref< typename Context::char_type > ref, Context &ctx)
Definition format.h:2114
constexpr auto digits10() FMT_NOEXCEPT -> int
Definition format.h:990
auto write_significand(OutputIt out, const char *significand, int &significand_size) -> OutputIt
Definition format.h:1618
conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > uint64_or_128_t
Definition format.h:849
FMT_CONSTEXPR20 auto format_decimal(Char *out, UInt value, int size) -> format_decimal_result< Char * >
Definition format.h:1050
auto write_exponent(int exp, It it) -> It
Definition format.h:1229
FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg, ErrorHandler eh) -> int
Definition format.h:2057
conditional_t< num_bits< T >()<=32 &&!FMT_REDUCE_INT_INSTANTIATIONS, uint32_t, conditional_t< num_bits< T >()<=64, uint64_t, uint128_t > > uint32_or_64_or_128_t
Definition format.h:847
FMT_CONSTEXPR auto write_padded(OutputIt out, const basic_format_specs< Char > &specs, size_t size, size_t width, F &&f) -> OutputIt
Definition format.h:1279
#define FMT_DEPRECATED
Definition format.h:120
template auto format_float< double >(double value, int precision, float_specs specs, buffer< char > &buf) -> int
template FMT_API auto thousands_sep_impl< char >(locale_ref) -> thousands_sep_result< char >
auto write_int_localized(OutputIt &out, UInt value, unsigned prefix, const basic_format_specs< Char > &specs, locale_ref loc) -> bool
Definition format.h:1397
FMT_CONSTEXPR void prefix_append(unsigned &prefix, unsigned value)
Definition format.h:1449
auto to_string(const T &value) -> std::string
Definition format.h:2600
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t< Char > &fill) -> OutputIt
Definition format.h:1264
FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, unsigned prefix, const basic_format_specs< Char > &specs, W write_digits) -> OutputIt
Definition format.h:1373
FMT_API void report_error(format_func func, int error_code, const char *message) FMT_NOEXCEPT
auto promote_float(T value) -> T
Definition format.h:1258
template auto snprintf_float< long double >(long double value, int precision, float_specs specs, buffer< char > &buf) -> int
template auto snprintf_float< double >(double value, int precision, float_specs specs, buffer< char > &buf) -> int
auto write_ptr(OutputIt out, UIntPtr value, const basic_format_specs< Char > *specs) -> OutputIt
Definition format.h:1315
@ inline_buffer_size
Definition format.h:599
#define FMT_NOINLINE
Definition format.h:69
constexpr auto digits10< uint128_t >() FMT_NOEXCEPT -> int
Definition format.h:996
constexpr auto digits10< int128_t >() FMT_NOEXCEPT -> int
Definition format.h:993
#define FMT_CONSTEXPR20
Definition format.h:254
auto thousands_sep(locale_ref loc) -> thousands_sep_result< Char >
Definition format.h:1008
auto equal2(const Char *lhs, const char *rhs) -> bool
Definition format.h:1027
FMT_CONSTEXPR auto is_negative(T value) -> bool
Definition format.h:826
#define FMT_THROW(x)
Definition format.h:96
FMT_CONSTEXPR auto get_arg(Context &ctx, ID id) -> typename Context::format_arg
Definition format.h:2064
auto ptr(T p) -> const void *
Definition format.h:2451
FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) -> write_int_arg< uint32_or_64_or_128_t< T > >
Definition format.h:1460
FMT_CONSTEXPR auto write(OutputIt out, Char value, const basic_format_specs< Char > &specs, locale_ref loc={}) -> OutputIt
Definition format.h:1338
FMT_INLINE uint64_t count_digits_inc(int n)
Definition format.h:959
#define FMT_REDUCE_INT_INSTANTIATIONS
Definition format.h:148
FMT_CONSTEXPR auto format_uint(Char *buffer, UInt value, int num_digits, bool upper=false) -> Char *
Definition format.h:1091
#define FMT_POWERS_OF_10(factor)
Definition format.h:851
template FMT_API auto thousands_sep_impl< wchar_t >(locale_ref) -> thousands_sep_result< wchar_t >
auto count_digits< 4 >(detail::fallback_uintptr n) -> int
T isfinite(T... args)
T isinf(T... args)
T length(T... args)
T make_shared(T... args)
T max_size(T... args)
T memcmp(T... args)
T memcpy(T... args)
T memset(T... args)
Definition core.h:1858
type
Definition core.h:1859
@ left
Definition core.h:1859
@ right
Definition core.h:1859
@ numeric
Definition core.h:1859
constexpr auto compile_string_to_view(const Char(&s)[N]) -> basic_string_view< Char >
Definition format.h:795
Definition args.h:19
decltype(std::end(std::declval< T & >())) sentinel_t
Definition format.h:327
FMT_INLINE void assume(bool condition)
Definition format.h:317
constexpr auto num_bits() -> int
Definition format.h:306
auto is_big_endian() -> bool
Definition format.h:268
auto compute_width(basic_string_view< Char > s) -> size_t
Definition format.h:508
constexpr auto num_bits< uint128_t >() -> int
Definition format.h:311
auto base_iterator(std::back_insert_iterator< Container > &it, checked_ptr< typename Container::value_type >) -> std::back_insert_iterator< Container >
Definition format.h:394
constexpr auto max_value() -> T
Definition format.h:303
auto to_uintptr(const void *p) -> fallback_uintptr
Definition format.h:296
decltype(std::begin(std::declval< T & >())) iterator_t
Definition format.h:326
FMT_FUNC void print(std::FILE *f, string_view text)
auto bit_cast(const Source &source) -> Dest
Definition format.h:261
constexpr auto to_pointer(OutputIt, size_t) -> T *
Definition format.h:382
remove_reference_t< decltype(reserve(std::declval< OutputIt & >(), 0))> reserve_iterator
Definition format.h:379
fallback_uintptr uintptr_t
Definition format.h:295
auto write(OutputIt out, const std::tm &time, const std::locale &loc, char format, char modifier=0) -> OutputIt
auto reserve(std::back_insert_iterator< Container > it, size_t n) -> checked_ptr< typename Container::value_type >
Definition format.h:357
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T &value) -> OutputIt
Definition format.h:408
constexpr auto num_bits< fallback_uintptr >() -> int
Definition format.h:312
FMT_CONSTEXPR auto utf8_decode(const char *s, uint32_t *c, int *e) -> const char *
Definition format.h:451
auto code_point_index(basic_string_view< Char > s, size_t n) -> size_t
Definition format.h:551
auto get_data(std::basic_string< Char > &s) -> Char *
Definition format.h:331
FMT_CONSTEXPR void for_each_codepoint(string_view s, F f)
Definition format.h:484
constexpr auto num_bits< int128_t >() -> int
Definition format.h:310
T * checked_ptr
Definition format.h:346
auto make_checked(T *p, size_t) -> T *
Definition format.h:347
FMT_CONSTEXPR FMT_NOINLINE auto copy_str_noinline(InputIt begin, InputIt end, OutputIt out) -> OutputIt
Definition format.h:429
char8_type
Definition format.h:425
FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp< T >
Definition core.h:1862
type
Definition core.h:1863
@ none
Definition core.h:1863
@ minus
Definition core.h:1863
T signbit(T... args)
T size(T... args)
FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator
Definition format.h:1988
const basic_format_specs< Char > & specs
Definition format.h:1984
auto operator()(typename basic_format_arg< context >::handle) -> iterator
Definition format.h:1991
locale_ref locale
Definition format.h:1985
iterator out
Definition format.h:1983
buffer_appender< Char > iterator
Definition format.h:1980
static FMT_API constexpr const char left_padding_shifts[5]
Definition format.h:885
static FMT_API constexpr const char hex_digits[]
Definition format.h:881
static FMT_API constexpr const char digits[100][2]
Definition format.h:862
static FMT_API constexpr const char signs[4]
Definition format.h:882
static FMT_API constexpr const unsigned prefixes[4]
Definition format.h:883
static FMT_API constexpr const char right_padding_shifts[5]
Definition format.h:887
detail::fill_t< Char > fill
Definition core.h:1905
align_t align
Definition core.h:1901
int significand_size
Definition format.h:1605
const char * significand
Definition format.h:1604
void operator()(T) const
Definition format.h:2006
void operator()(typename basic_format_arg< buffer_context< Char > >::handle h) const
Definition format.h:2002
buffer_context< Char > & ctx
Definition format.h:2000
basic_format_parse_context< Char > & parse_ctx
Definition format.h:1999
Definition format.h:897
basic_format_args< context > args
Definition format.h:1965
auto operator()(T value) -> iterator
Definition format.h:1968
auto operator()(typename basic_format_arg< context >::handle h) -> iterator
Definition format.h:1971
buffer_appender< Char > iterator
Definition format.h:1961
fallback_uintptr(const void *p)
Definition format.h:281
typename float_info< T >::carrier_uint significand_type
Definition format.h:1210
significand_type significand
Definition format.h:1211
FMT_NORETURN FMT_API void on_error(const char *message)
float_format format
Definition core.h:2519
int precision
Definition core.h:2518
sign_t sign
Definition core.h:2520
bool use_grisu
Definition core.h:2524
bool binary32
Definition core.h:2523
bool locale
Definition core.h:2522
FMT_CONSTEXPR auto format(const Char *val, FormatContext &ctx) const -> decltype(ctx.out())
Definition format.h:2384
auto format(bytes b, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:2487
detail::dynamic_format_specs< char > specs_
Definition format.h:2473
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition format.h:2477
FMT_CONSTEXPR auto parse(ParseContext &ctx) -> decltype(ctx.begin())
Definition format.h:2536
static auto map(const T &value) -> const T &
Definition format.h:2517
typename std::iterator_traits< It >::value_type value_type
Definition format.h:2512
static auto map(const T &value) -> decltype(mapper().map(value))
Definition format.h:2521
auto format(const join_view< It, Sentinel, Char > &value, FormatContext &ctx) -> decltype(ctx.out())
Definition format.h:2541
conditional_t< is_formattable< value_type, Char >::value, formatter< remove_cvref_t< decltype(map(std::declval< const value_type & >()))>, Char >, detail::fallback_formatter< value_type, Char > > formatter_type
Definition format.h:2530
auto format(void *val, FormatContext &ctx) const -> decltype(ctx.out())
Definition format.h:2376
join_view(It b, Sentinel e, basic_string_view< Char > s)
Definition format.h:2502
Sentinel end
Definition format.h:2499
basic_string_view< Char > sep
Definition format.h:2500
std::string grouping
Definition format.h:1001
Definition core.h:971
UInt abs_value
Definition format.h:1455
unsigned prefix
Definition format.h:1456
FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, const basic_format_specs< Char > &specs)
Definition format.h:1352
size_t padding
Definition format.h:1350
size_t size
Definition format.h:1349
T swap(T... args)
T to_int_type(T... args)
T uninitialized_copy(T... args)
T uninitialized_copy_n(T... args)