Fix: futex wait: handle spurious futex wakeups
[lttng-tools.git] / src / vendor / fmt / format.h
1 /*
2 Formatting library for C++
3
4 Copyright (c) 2012 - present, Victor Zverovich
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
25 --- Optional exception to the license ---
26
27 As an exception, if, as a result of your compiling your source code, portions
28 of this Software are embedded into a machine-executable object form of such
29 source code, you may redistribute such embedded portions in such object form
30 without including the above copyright and permission notices.
31 */
32
33 #ifndef FMT_FORMAT_H_
34 #define FMT_FORMAT_H_
35
36 #include <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
83 FMT_BEGIN_NAMESPACE
84 namespace detail {
85 template <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
92 FMT_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)
177 FMT_BEGIN_NAMESPACE
178 namespace 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
189 inline 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
201 inline 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
217 inline 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
226 inline 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
243 FMT_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
252 FMT_BEGIN_NAMESPACE
253 namespace detail {
254
255 template <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.
287 template <typename To, typename From>
288 FMT_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
298 inline 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.
314 struct 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
327 using uintptr_t = ::uintptr_t;
328 inline auto to_uintptr(const void* p) -> uintptr_t {
329 return bit_cast<uintptr_t>(p);
330 }
331 #else
332 using uintptr_t = fallback_uintptr;
333 inline 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.
340 template <typename T> constexpr auto max_value() -> T {
341 return (std::numeric_limits<T>::max)();
342 }
343 template <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.
347 template <> constexpr auto num_bits<int128_t>() -> int { return 128; }
348 template <> constexpr auto num_bits<uint128_t>() -> int { return 128; }
349 template <> constexpr auto num_bits<fallback_uintptr>() -> int {
350 return static_cast<int>(sizeof(void*) *
351 std::numeric_limits<unsigned char>::digits);
352 }
353
354 FMT_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.
362 template <typename T>
363 using iterator_t = decltype(std::begin(std::declval<T&>()));
364 template <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.
367 template <typename Char>
368 inline auto get_data(std::basic_string<Char>& s) -> Char* {
369 return &s[0];
370 }
371 template <typename Container>
372 inline 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.
378 template <typename T> using checked_ptr = stdext::checked_array_iterator<T*>;
379 template <typename T>
380 constexpr auto make_checked(T* p, size_t size) -> checked_ptr<T> {
381 return {p, size};
382 }
383 #else
384 template <typename T> using checked_ptr = T*;
385 template <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.
392 template <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
396 inline auto
397 reserve(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
405 template <typename T>
406 inline 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
412 template <typename Iterator>
413 constexpr auto reserve(Iterator& it, size_t) -> Iterator& {
414 return it;
415 }
416
417 template <typename OutputIt>
418 using reserve_iterator =
419 remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>;
420
421 template <typename T, typename OutputIt>
422 constexpr auto to_pointer(OutputIt, size_t) -> T* {
423 return nullptr;
424 }
425 template <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
433 template <typename Container, FMT_ENABLE_IF(is_contiguous<Container>::value)>
434 inline 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
440 template <typename Iterator>
441 constexpr 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).
447 template <typename OutputIt, typename Size, typename T>
448 FMT_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 }
453 template <typename T, typename Size>
454 FMT_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
463 using char8_type = char8_t;
464 #else
465 enum char8_type : unsigned char {};
466 #endif
467
468 template <typename OutChar, typename InputIt, typename OutputIt>
469 FMT_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 */
491 FMT_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
523 constexpr 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.
527 template <typename F>
528 FMT_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
558 template <typename Char>
559 inline 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.
564 FMT_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
597 inline 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
602 template <typename Char>
603 inline 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.
609 inline 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
619 template <typename T, bool = std::is_floating_point<T>::value>
620 struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 &&
621 sizeof(T) <= sizeof(double)> {};
622 template <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
628 template <typename T>
629 template <typename U>
630 void 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
642 template <typename T, typename Enable = void>
643 struct is_locale : std::false_type {};
644 template <typename T>
645 struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {};
646 } // namespace detail
647
648 FMT_MODULE_EXPORT_BEGIN
649
650 // The number of characters to store in the basic_memory_buffer object itself
651 // to avoid dynamic memory allocation.
652 enum { 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 */
675 template <typename T, size_t SIZE = inline_buffer_size,
676 typename Allocator = std::allocator<T>>
677 class 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
776 template <typename T, size_t SIZE, typename Allocator>
777 FMT_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
802 using memory_buffer = basic_memory_buffer<char>;
803
804 template <typename T, size_t SIZE, typename Allocator>
805 struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type {
806 };
807
808 namespace detail {
809 FMT_API void print(std::FILE*, string_view);
810 }
811
812 /** A formatting error such as invalid format string. */
813 FMT_CLASS_API
814 class 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 */
834 template <typename... Args, typename S, typename Char = char_t<S>>
835 FMT_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
848 namespace detail_exported {
849 #if FMT_USE_NONTYPE_TEMPLATE_PARAMETERS
850 template <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.
860 template <typename Char, size_t N>
861 constexpr 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 }
867 template <typename Char>
868 constexpr 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
874 FMT_BEGIN_DETAIL_NAMESPACE
875
876 template <typename T> struct is_integral : std::is_integral<T> {};
877 template <> struct is_integral<int128_t> : std::true_type {};
878 template <> struct is_integral<uint128_t> : std::true_type {};
879
880 template <typename T>
881 using 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.
887 template <typename T, FMT_ENABLE_IF(is_signed<T>::value)>
888 FMT_CONSTEXPR auto is_negative(T value) -> bool {
889 return value < 0;
890 }
891 template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)>
892 FMT_CONSTEXPR auto is_negative(T) -> bool {
893 return false;
894 }
895
896 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
897 FMT_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.
905 template <typename T>
906 using 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>>;
910 template <typename T>
911 using 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.
919 constexpr 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.
929 template <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
936 template <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
951 FMT_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.
959 inline 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.
979 FMT_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).
989 template <int BITS, typename UInt>
990 FMT_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
1005 template <> 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.
1010 FMT_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.
1033 FMT_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
1042 template <typename Int> constexpr auto digits10() FMT_NOEXCEPT -> int {
1043 return std::numeric_limits<Int>::digits10;
1044 }
1045 template <> constexpr auto digits10<int128_t>() FMT_NOEXCEPT -> int {
1046 return 38;
1047 }
1048 template <> constexpr auto digits10<uint128_t>() FMT_NOEXCEPT -> int {
1049 return 38;
1050 }
1051
1052 template <typename Char> struct thousands_sep_result {
1053 std::string grouping;
1054 Char thousands_sep;
1055 };
1056
1057 template <typename Char>
1058 FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>;
1059 template <typename Char>
1060 inline 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 }
1064 template <>
1065 inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> {
1066 return thousands_sep_impl<wchar_t>(loc);
1067 }
1068
1069 template <typename Char>
1070 FMT_API auto decimal_point_impl(locale_ref loc) -> Char;
1071 template <typename Char> inline auto decimal_point(locale_ref loc) -> Char {
1072 return Char(decimal_point_impl<char>(loc));
1073 }
1074 template <> 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.
1079 template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool {
1080 return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]);
1081 }
1082 inline 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.
1087 template <typename Char>
1088 FMT_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
1097 template <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.
1105 template <typename Char, typename UInt>
1106 FMT_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
1128 template <typename Char, typename UInt, typename Iterator,
1129 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)>
1130 inline 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
1138 template <unsigned BASE_BITS, typename Char, typename UInt>
1139 FMT_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
1152 template <unsigned BASE_BITS, typename Char>
1153 auto 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
1174 template <unsigned BASE_BITS, typename Char, typename It, typename UInt>
1175 inline 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.
1188 class 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
1200 namespace dragonbox {
1201
1202 // Type-specific information that Dragonbox uses.
1203 template <class T> struct float_info;
1204
1205 template <> 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
1231 template <> 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
1257 template <typename T> struct decimal_fp {
1258 using significand_type = typename float_info<T>::carrier_uint;
1259 significand_type significand;
1260 int exponent;
1261 };
1262
1263 template <typename T>
1264 FMT_API auto to_decimal(T x) FMT_NOEXCEPT -> decimal_fp<T>;
1265 } // namespace dragonbox
1266
1267 template <typename T>
1268 constexpr 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.
1276 template <typename Char, typename It>
1277 FMT_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
1297 template <typename T>
1298 FMT_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.
1303 template <typename T>
1304 auto snprintf_float(T value, int precision, float_specs specs,
1305 buffer<char>& buf) -> int;
1306
1307 template <typename T> constexpr auto promote_float(T value) -> T {
1308 return value;
1309 }
1310 constexpr auto promote_float(float value) -> double {
1311 return static_cast<double>(value);
1312 }
1313
1314 template <typename OutputIt, typename Char>
1315 FMT_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.
1328 template <align::type align = align::left, typename OutputIt, typename Char,
1329 typename F>
1330 FMT_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
1348 template <align::type align = align::left, typename OutputIt, typename Char,
1349 typename F>
1350 constexpr 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
1355 template <align::type align = align::left, typename Char, typename OutputIt>
1356 FMT_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
1366 template <typename Char, typename OutputIt, typename UIntPtr>
1367 auto 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
1380 template <typename Char, typename OutputIt>
1381 FMT_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 }
1389 template <typename Char, typename OutputIt>
1390 FMT_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.
1400 template <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.
1424 template <typename OutputIt, typename Char, typename W>
1425 FMT_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
1448 template <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
1510 template <typename OutputIt, typename UInt, typename Char>
1511 auto 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
1527 template <typename OutputIt, typename UInt, typename Char>
1528 auto 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
1536 FMT_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
1541 template <typename UInt> struct write_int_arg {
1542 UInt abs_value;
1543 unsigned prefix;
1544 };
1545
1546 template <typename T>
1547 FMT_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
1562 template <typename Char, typename OutputIt, typename T>
1563 FMT_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 }
1623 template <typename Char, typename OutputIt, typename T>
1624 FMT_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 }
1629 template <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)>
1633 FMT_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.
1640 template <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)>
1644 FMT_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
1650 template <typename Char, typename OutputIt>
1651 FMT_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 }
1664 template <typename Char, typename OutputIt>
1665 FMT_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 }
1672 template <typename Char, typename OutputIt>
1673 FMT_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
1681 template <typename Char, typename OutputIt>
1682 FMT_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).
1701 struct big_decimal_fp {
1702 const char* significand;
1703 int significand_size;
1704 int exponent;
1705 };
1706
1707 constexpr auto get_significand_size(const big_decimal_fp& fp) -> int {
1708 return fp.significand_size;
1709 }
1710 template <typename T>
1711 inline auto get_significand_size(const dragonbox::decimal_fp<T>& fp) -> int {
1712 return count_digits(fp.significand);
1713 }
1714
1715 template <typename Char, typename OutputIt>
1716 constexpr auto write_significand(OutputIt out, const char* significand,
1717 int significand_size) -> OutputIt {
1718 return copy_str<Char>(significand, significand + significand_size, out);
1719 }
1720 template <typename Char, typename OutputIt, typename UInt>
1721 inline auto write_significand(OutputIt out, UInt significand,
1722 int significand_size) -> OutputIt {
1723 return format_decimal<Char>(out, significand, significand_size).end;
1724 }
1725 template <typename Char, typename OutputIt, typename T, typename Grouping>
1726 FMT_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
1739 template <typename Char, typename UInt,
1740 FMT_ENABLE_IF(std::is_integral<UInt>::value)>
1741 inline 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
1762 template <typename OutputIt, typename UInt, typename Char,
1763 FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)>
1764 inline 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
1774 template <typename OutputIt, typename Char>
1775 FMT_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
1786 template <typename OutputIt, typename Char, typename T, typename Grouping>
1787 FMT_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
1804 template <typename OutputIt, typename DecimalFP, typename Char,
1805 typename Grouping = digit_grouping<Char>>
1806 FMT_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
1912 template <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
1926 template <typename OutputIt, typename DecimalFP, typename Char>
1927 FMT_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
1940 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1941 FMT_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
1956 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1957 FMT_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
1969 template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1970 FMT_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
1982 template <typename Char, typename OutputIt, typename T,
1983 FMT_ENABLE_IF(std::is_floating_point<T>::value)>
1984 FMT_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
2032 template <typename Char, typename OutputIt, typename T,
2033 FMT_ENABLE_IF(is_fast_float<T>::value)>
2034 FMT_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
2060 template <typename Char, typename OutputIt, typename T,
2061 FMT_ENABLE_IF(std::is_floating_point<T>::value &&
2062 !is_fast_float<T>::value)>
2063 inline auto write(OutputIt out, T value) -> OutputIt {
2064 return write(out, value, basic_format_specs<Char>());
2065 }
2066
2067 template <typename Char, typename OutputIt>
2068 auto write(OutputIt out, monostate, basic_format_specs<Char> = {},
2069 locale_ref = {}) -> OutputIt {
2070 FMT_ASSERT(false, "");
2071 return out;
2072 }
2073
2074 template <typename Char, typename OutputIt>
2075 FMT_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
2082 template <typename Char, typename OutputIt, typename T,
2083 FMT_ENABLE_IF(is_string<T>::value)>
2084 constexpr auto write(OutputIt out, const T& value) -> OutputIt {
2085 return write<Char>(out, to_string_view(value));
2086 }
2087
2088 template <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)>
2092 FMT_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.
2111 template <
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)>
2118 FMT_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
2123 template <typename Char, typename OutputIt, typename T,
2124 FMT_ENABLE_IF(std::is_same<T, bool>::value)>
2125 FMT_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
2134 template <typename Char, typename OutputIt>
2135 FMT_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
2141 template <typename Char, typename OutputIt>
2142 FMT_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
2152 template <typename Char, typename OutputIt, typename T,
2153 FMT_ENABLE_IF(std::is_same<T, void>::value)>
2154 auto 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.
2162 template <typename Char, typename OutputIt, typename T,
2163 typename Context = basic_format_context<OutputIt, Char>>
2164 FMT_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
2173 template <typename Char, typename OutputIt, typename T,
2174 typename Context = basic_format_context<OutputIt, Char>>
2175 FMT_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.
2188 template <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
2207 template <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
2226 template <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
2237 template <typename T>
2238 using 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
2243 template <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
2263 template <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
2283 template <template <typename> class Handler, typename FormatArg,
2284 typename ErrorHandler>
2285 FMT_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
2291 template <typename Context, typename ID>
2292 FMT_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.
2300 template <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
2341 template <template <typename> class Handler, typename Context>
2342 FMT_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
2386 template <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
2396 template <typename T, typename Char, size_t N,
2397 fmt::detail_exported::fixed_string<Char, N> Str>
2398 struct 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
2405 template <typename T, typename Char, size_t N,
2406 fmt::detail_exported::fixed_string<Char, N> Str>
2407 struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {};
2408
2409 template <typename T, typename Char, size_t N,
2410 fmt::detail_exported::fixed_string<Char, N> Str>
2411 struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>>
2412 : std::true_type {};
2413
2414 template <typename Char, size_t N,
2415 fmt::detail_exported::fixed_string<Char, N> Str>
2416 struct 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
2422 template <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
2432 template <typename Locale, typename Char>
2433 auto 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
2441 using format_func = void (*)(detail::buffer<char>&, int, const char*);
2442
2443 FMT_API void format_error_code(buffer<char>& out, int error_code,
2444 string_view message) FMT_NOEXCEPT;
2445
2446 FMT_API void report_error(format_func func, int error_code,
2447 const char* message) FMT_NOEXCEPT;
2448 FMT_END_DETAIL_NAMESPACE
2449
2450 FMT_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 */
2470 template <typename... T>
2471 auto 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 */
2492 FMT_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.
2497 FMT_API void report_system_error(int error_code,
2498 const char* message) FMT_NOEXCEPT;
2499
2500 /** Fast integer formatter. */
2501 class 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
2560 template <typename T, typename Char>
2561 template <typename FormatContext>
2562 FMT_CONSTEXPR FMT_INLINE auto
2563 formatter<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
2590 FMT_FORMAT_AS(signed char, int);
2591 FMT_FORMAT_AS(unsigned char, unsigned);
2592 FMT_FORMAT_AS(short, int);
2593 FMT_FORMAT_AS(unsigned short, unsigned);
2594 FMT_FORMAT_AS(long, long long);
2595 FMT_FORMAT_AS(unsigned long, unsigned long long);
2596 FMT_FORMAT_AS(Char*, const Char*);
2597 FMT_FORMAT_AS(std::basic_string<Char>, basic_string_view<Char>);
2598 FMT_FORMAT_AS(std::nullptr_t, const void*);
2599 FMT_FORMAT_AS(detail::byte, unsigned char);
2600 FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>);
2601
2602 template <typename Char>
2603 struct 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
2610 template <typename Char, size_t N>
2611 struct 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 // };
2631 template <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 */
2680 template <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 }
2684 template <typename T> auto ptr(const std::unique_ptr<T>& p) -> const void* {
2685 return p.get();
2686 }
2687 template <typename T> auto ptr(const std::shared_ptr<T>& p) -> const void* {
2688 return p.get();
2689 }
2690
2691 class 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
2700 template <> 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.
2726 template <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 */
2739 template <typename T> auto group_digits(T value) -> group_digits_view<T> {
2740 return {value};
2741 }
2742
2743 template <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
2771 template <typename It, typename Sentinel, typename Char = char>
2772 struct 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
2781 template <typename It, typename Sentinel, typename Char>
2782 using arg_join FMT_DEPRECATED_ALIAS = join_view<It, Sentinel, Char>;
2783
2784 template <typename It, typename Sentinel, typename Char>
2785 struct 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 */
2843 template <typename It, typename Sentinel>
2844 auto 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 */
2864 template <typename Range>
2865 auto 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 */
2881 template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value)>
2882 inline 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
2888 template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)>
2889 FMT_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
2898 template <typename Char, size_t SIZE>
2899 FMT_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
2906 FMT_BEGIN_DETAIL_NAMESPACE
2907
2908 template <typename Char>
2909 void 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
2992 extern template FMT_API auto thousands_sep_impl<char>(locale_ref)
2993 -> thousands_sep_result<char>;
2994 extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref)
2995 -> thousands_sep_result<wchar_t>;
2996 extern template FMT_API auto decimal_point_impl(locale_ref) -> char;
2997 extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t;
2998 extern template auto format_float<double>(double value, int precision,
2999 float_specs specs, buffer<char>& buf)
3000 -> int;
3001 extern template auto format_float<long double>(long double value, int precision,
3002 float_specs specs,
3003 buffer<char>& buf) -> int;
3004 void snprintf_float(float, int, float_specs, buffer<char>&) = delete;
3005 extern template auto snprintf_float<double>(double value, int precision,
3006 float_specs specs,
3007 buffer<char>& buf) -> int;
3008 extern 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
3014 FMT_END_DETAIL_NAMESPACE
3015
3016 #if FMT_USE_USER_DEFINED_LITERALS
3017 inline 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
3029 template <detail_exported::fixed_string Str>
3030 constexpr 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
3036 constexpr 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.
3043 FMT_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
3050 template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
3051 inline auto vformat(const Locale& loc, string_view fmt, format_args args)
3052 -> std::string {
3053 return detail::vformat(loc, fmt, args);
3054 }
3055
3056 template <typename Locale, typename... T,
3057 FMT_ENABLE_IF(detail::is_locale<Locale>::value)>
3058 inline 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
3063 template <typename... T, size_t SIZE, typename Allocator>
3064 FMT_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
3071 template <typename OutputIt, typename Locale,
3072 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
3073 detail::is_locale<Locale>::value)>
3074 auto 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
3082 template <typename OutputIt, typename Locale, typename... T,
3083 FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&&
3084 detail::is_locale<Locale>::value)>
3085 FMT_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
3090 FMT_MODULE_EXPORT_END
3091 FMT_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.145084 seconds and 4 git commands to generate.