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