| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1 |
/* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2 |
Formatting library for C++ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4 |
Copyright (c) 2012 - present, Victor Zverovich |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
5 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
6 |
Permission is hereby granted, free of charge, to any person obtaining |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
7 |
a copy of this software and associated documentation files (the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
8 |
"Software"), to deal in the Software without restriction, including |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
9 |
without limitation the rights to use, copy, modify, merge, publish, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
10 |
distribute, sublicense, and/or sell copies of the Software, and to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
11 |
permit persons to whom the Software is furnished to do so, subject to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
12 |
the following conditions: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
13 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
14 |
The above copyright notice and this permission notice shall be |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
15 |
included in all copies or substantial portions of the Software. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
16 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
17 |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
18 |
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
19 |
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
20 |
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
21 |
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
22 |
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
23 |
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
24 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
25 |
--- Optional exception to the license --- |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
26 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
27 |
As an exception, if, as a result of your compiling your source code, portions |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
28 |
of this Software are embedded into a machine-executable object form of such |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
29 |
source code, you may redistribute such embedded portions in such object form |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
30 |
without including the above copyright and permission notices. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
31 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
32 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
33 |
#ifndef FMT_FORMAT_H_ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
34 |
#define FMT_FORMAT_H_ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
35 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
36 |
#ifndef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
37 |
# define _LIBCPP_REMOVE_TRANSITIVE_INCLUDES |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
38 |
# define FMT_REMOVE_TRANSITIVE_INCLUDES |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
39 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
40 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
41 |
#include "base.h" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
42 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
43 |
#ifndef FMT_MODULE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
44 |
# include <cmath> // std::signbit |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
45 |
# include <cstdint> // uint32_t |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
46 |
# include <cstring> // std::memcpy |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
47 |
# include <initializer_list> // std::initializer_list |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
48 |
# include <limits> // std::numeric_limits |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
49 |
# if defined(__GLIBCXX__) && !defined(_GLIBCXX_USE_DUAL_ABI) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
50 |
// Workaround for pre gcc 5 libstdc++. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
51 |
# include <memory> // std::allocator_traits |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
52 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
53 |
# include <stdexcept> // std::runtime_error |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
54 |
# include <string> // std::string |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
55 |
# include <system_error> // std::system_error |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
56 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
57 |
// Checking FMT_CPLUSPLUS for warning suppression in MSVC. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
58 |
# if FMT_HAS_INCLUDE(<bit>) && FMT_CPLUSPLUS > 201703L |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
59 |
# include <bit> // std::bit_cast |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
60 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
61 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
62 |
// libc++ supports string_view in pre-c++17. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
63 |
# if FMT_HAS_INCLUDE(<string_view>) && \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
64 |
(FMT_CPLUSPLUS >= 201703L || defined(_LIBCPP_VERSION)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
65 |
# include <string_view> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
66 |
# define FMT_USE_STRING_VIEW |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
67 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
68 |
#endif // FMT_MODULE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
69 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
70 |
#if defined __cpp_inline_variables && __cpp_inline_variables >= 201606L |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
71 |
# define FMT_INLINE_VARIABLE inline |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
72 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
73 |
# define FMT_INLINE_VARIABLE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
74 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
75 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
76 |
#ifndef FMT_NO_UNIQUE_ADDRESS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
77 |
# if FMT_CPLUSPLUS >= 202002L |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
78 |
# if FMT_HAS_CPP_ATTRIBUTE(no_unique_address) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
79 |
# define FMT_NO_UNIQUE_ADDRESS [[no_unique_address]] |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
80 |
// VS2019 v16.10 and later except clang-cl (https://reviews.llvm.org/D110485). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
81 |
# elif (FMT_MSC_VERSION >= 1929) && !FMT_CLANG_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
82 |
# define FMT_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
83 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
84 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
85 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
86 |
#ifndef FMT_NO_UNIQUE_ADDRESS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
87 |
# define FMT_NO_UNIQUE_ADDRESS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
88 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
89 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
90 |
// Visibility when compiled as a shared library/object. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
91 |
#if defined(FMT_LIB_EXPORT) || defined(FMT_SHARED) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
92 |
# define FMT_SO_VISIBILITY(value) FMT_VISIBILITY(value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
93 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
94 |
# define FMT_SO_VISIBILITY(value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
95 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
96 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
97 |
#ifdef __has_builtin |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
98 |
# define FMT_HAS_BUILTIN(x) __has_builtin(x) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
99 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
100 |
# define FMT_HAS_BUILTIN(x) 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
101 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
102 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
103 |
#if FMT_GCC_VERSION || FMT_CLANG_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
104 |
# define FMT_NOINLINE __attribute__((noinline)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
105 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
106 |
# define FMT_NOINLINE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
107 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
108 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
109 |
namespace std { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
110 |
template <> struct iterator_traits<fmt::appender> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
111 |
using iterator_category = output_iterator_tag; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
112 |
using value_type = char; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
113 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
114 |
} // namespace std |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
115 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
116 |
#ifndef FMT_THROW |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
117 |
# if FMT_EXCEPTIONS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
118 |
# if FMT_MSC_VERSION || defined(__NVCC__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
119 |
FMT_BEGIN_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
120 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
121 |
template <typename Exception> inline void do_throw(const Exception& x) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
122 |
// Silence unreachable code warnings in MSVC and NVCC because these |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
123 |
// are nearly impossible to fix in a generic code. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
124 |
volatile bool b = true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
125 |
if (b) throw x; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
126 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
127 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
128 |
FMT_END_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
129 |
# define FMT_THROW(x) detail::do_throw(x) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
130 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
131 |
# define FMT_THROW(x) throw x |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
132 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
133 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
134 |
# define FMT_THROW(x) \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
135 |
::fmt::detail::assert_fail(__FILE__, __LINE__, (x).what()) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
136 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
137 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
138 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
139 |
#ifndef FMT_MAYBE_UNUSED |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
140 |
# if FMT_HAS_CPP17_ATTRIBUTE(maybe_unused) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
141 |
# define FMT_MAYBE_UNUSED [[maybe_unused]] |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
142 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
143 |
# define FMT_MAYBE_UNUSED |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
144 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
145 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
146 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
147 |
#ifndef FMT_USE_USER_DEFINED_LITERALS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
148 |
// EDG based compilers (Intel, NVIDIA, Elbrus, etc), GCC and MSVC support UDLs. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
149 |
// |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
150 |
// GCC before 4.9 requires a space in `operator"" _a` which is invalid in later |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
151 |
// compiler versions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
152 |
# if (FMT_HAS_FEATURE(cxx_user_literals) || FMT_GCC_VERSION >= 409 || \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
153 |
FMT_MSC_VERSION >= 1900) && \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
154 |
(!defined(__EDG_VERSION__) || __EDG_VERSION__ >= /* UDL feature */ 480) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
155 |
# define FMT_USE_USER_DEFINED_LITERALS 1 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
156 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
157 |
# define FMT_USE_USER_DEFINED_LITERALS 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
158 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
159 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
160 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
161 |
// Defining FMT_REDUCE_INT_INSTANTIATIONS to 1, will reduce the number of |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
162 |
// integer formatter template instantiations to just one by only using the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
163 |
// largest integer type. This results in a reduction in binary size but will |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
164 |
// cause a decrease in integer formatting performance. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
165 |
#if !defined(FMT_REDUCE_INT_INSTANTIATIONS) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
166 |
# define FMT_REDUCE_INT_INSTANTIATIONS 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
167 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
168 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
169 |
// __builtin_clz is broken in clang with Microsoft CodeGen: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
170 |
// https://github.com/fmtlib/fmt/issues/519. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
171 |
#if !FMT_MSC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
172 |
# if FMT_HAS_BUILTIN(__builtin_clz) || FMT_GCC_VERSION || FMT_ICC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
173 |
# define FMT_BUILTIN_CLZ(n) __builtin_clz(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
174 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
175 |
# if FMT_HAS_BUILTIN(__builtin_clzll) || FMT_GCC_VERSION || FMT_ICC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
176 |
# define FMT_BUILTIN_CLZLL(n) __builtin_clzll(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
177 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
178 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
179 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
180 |
// __builtin_ctz is broken in Intel Compiler Classic on Windows: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
181 |
// https://github.com/fmtlib/fmt/issues/2510. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
182 |
#ifndef __ICL |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
183 |
# if FMT_HAS_BUILTIN(__builtin_ctz) || FMT_GCC_VERSION || FMT_ICC_VERSION || \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
184 |
defined(__NVCOMPILER) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
185 |
# define FMT_BUILTIN_CTZ(n) __builtin_ctz(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
186 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
187 |
# if FMT_HAS_BUILTIN(__builtin_ctzll) || FMT_GCC_VERSION || \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
188 |
FMT_ICC_VERSION || defined(__NVCOMPILER) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
189 |
# define FMT_BUILTIN_CTZLL(n) __builtin_ctzll(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
190 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
191 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
192 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
193 |
#if FMT_MSC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
194 |
# include <intrin.h> // _BitScanReverse[64], _BitScanForward[64], _umul128 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
195 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
196 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
197 |
// Some compilers masquerade as both MSVC and GCC-likes or otherwise support |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
198 |
// __builtin_clz and __builtin_clzll, so only define FMT_BUILTIN_CLZ using the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
199 |
// MSVC intrinsics if the clz and clzll builtins are not available. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
200 |
#if FMT_MSC_VERSION && !defined(FMT_BUILTIN_CLZLL) && \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
201 |
!defined(FMT_BUILTIN_CTZLL) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
202 |
FMT_BEGIN_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
203 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
204 |
// Avoid Clang with Microsoft CodeGen's -Wunknown-pragmas warning. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
205 |
# if !defined(__clang__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
206 |
# pragma intrinsic(_BitScanForward) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
207 |
# pragma intrinsic(_BitScanReverse) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
208 |
# if defined(_WIN64) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
209 |
# pragma intrinsic(_BitScanForward64) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
210 |
# pragma intrinsic(_BitScanReverse64) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
211 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
212 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
213 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
214 |
inline auto clz(uint32_t x) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
215 |
unsigned long r = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
216 |
_BitScanReverse(&r, x); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
217 |
FMT_ASSERT(x != 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
218 |
// Static analysis complains about using uninitialized data |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
219 |
// "r", but the only way that can happen is if "x" is 0, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
220 |
// which the callers guarantee to not happen. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
221 |
FMT_MSC_WARNING(suppress : 6102) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
222 |
return 31 ^ static_cast<int>(r); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
223 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
224 |
# define FMT_BUILTIN_CLZ(n) detail::clz(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
225 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
226 |
inline auto clzll(uint64_t x) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
227 |
unsigned long r = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
228 |
# ifdef _WIN64 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
229 |
_BitScanReverse64(&r, x); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
230 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
231 |
// Scan the high 32 bits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
232 |
if (_BitScanReverse(&r, static_cast<uint32_t>(x >> 32))) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
233 |
return 63 ^ static_cast<int>(r + 32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
234 |
// Scan the low 32 bits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
235 |
_BitScanReverse(&r, static_cast<uint32_t>(x)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
236 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
237 |
FMT_ASSERT(x != 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
238 |
FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
239 |
return 63 ^ static_cast<int>(r); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
240 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
241 |
# define FMT_BUILTIN_CLZLL(n) detail::clzll(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
242 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
243 |
inline auto ctz(uint32_t x) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
244 |
unsigned long r = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
245 |
_BitScanForward(&r, x); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
246 |
FMT_ASSERT(x != 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
247 |
FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
248 |
return static_cast<int>(r); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
249 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
250 |
# define FMT_BUILTIN_CTZ(n) detail::ctz(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
251 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
252 |
inline auto ctzll(uint64_t x) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
253 |
unsigned long r = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
254 |
FMT_ASSERT(x != 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
255 |
FMT_MSC_WARNING(suppress : 6102) // Suppress a bogus static analysis warning. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
256 |
# ifdef _WIN64 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
257 |
_BitScanForward64(&r, x); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
258 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
259 |
// Scan the low 32 bits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
260 |
if (_BitScanForward(&r, static_cast<uint32_t>(x))) return static_cast<int>(r); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
261 |
// Scan the high 32 bits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
262 |
_BitScanForward(&r, static_cast<uint32_t>(x >> 32)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
263 |
r += 32; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
264 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
265 |
return static_cast<int>(r); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
266 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
267 |
# define FMT_BUILTIN_CTZLL(n) detail::ctzll(n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
268 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
269 |
FMT_END_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
270 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
271 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
272 |
FMT_BEGIN_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
273 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
274 |
template <typename Char, typename Traits, typename Allocator> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
275 |
struct is_contiguous<std::basic_string<Char, Traits, Allocator>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
276 |
: std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
277 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
278 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
279 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
280 |
FMT_CONSTEXPR inline void abort_fuzzing_if(bool condition) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
281 |
ignore_unused(condition); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
282 |
#ifdef FMT_FUZZ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
283 |
if (condition) throw std::runtime_error("fuzzing limit reached"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
284 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
285 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
286 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
287 |
#if defined(FMT_USE_STRING_VIEW) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
288 |
template <typename Char> using std_string_view = std::basic_string_view<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
289 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
290 |
template <typename T> struct std_string_view {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
291 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
292 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
293 |
// Implementation of std::bit_cast for pre-C++20. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
294 |
template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) == sizeof(From))> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
295 |
FMT_CONSTEXPR20 auto bit_cast(const From& from) -> To { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
296 |
#ifdef __cpp_lib_bit_cast |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
297 |
if (is_constant_evaluated()) return std::bit_cast<To>(from); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
298 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
299 |
auto to = To(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
300 |
// The cast suppresses a bogus -Wclass-memaccess on GCC. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
301 |
std::memcpy(static_cast<void*>(&to), &from, sizeof(to)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
302 |
return to; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
303 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
304 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
305 |
inline auto is_big_endian() -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
306 |
#ifdef _WIN32 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
307 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
308 |
#elif defined(__BIG_ENDIAN__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
309 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
310 |
#elif defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
311 |
return __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
312 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
313 |
struct bytes { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
314 |
char data[sizeof(int)]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
315 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
316 |
return bit_cast<bytes>(1).data[0] == 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
317 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
318 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
319 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
320 |
class uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
321 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
322 |
uint64_t lo_, hi_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
323 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
324 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
325 |
constexpr uint128_fallback(uint64_t hi, uint64_t lo) : lo_(lo), hi_(hi) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
326 |
constexpr uint128_fallback(uint64_t value = 0) : lo_(value), hi_(0) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
327 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
328 |
constexpr auto high() const noexcept -> uint64_t { return hi_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
329 |
constexpr auto low() const noexcept -> uint64_t { return lo_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
330 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
331 |
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
332 |
constexpr explicit operator T() const { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
333 |
return static_cast<T>(lo_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
334 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
335 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
336 |
friend constexpr auto operator==(const uint128_fallback& lhs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
337 |
const uint128_fallback& rhs) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
338 |
return lhs.hi_ == rhs.hi_ && lhs.lo_ == rhs.lo_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
339 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
340 |
friend constexpr auto operator!=(const uint128_fallback& lhs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
341 |
const uint128_fallback& rhs) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
342 |
return !(lhs == rhs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
343 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
344 |
friend constexpr auto operator>(const uint128_fallback& lhs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
345 |
const uint128_fallback& rhs) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
346 |
return lhs.hi_ != rhs.hi_ ? lhs.hi_ > rhs.hi_ : lhs.lo_ > rhs.lo_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
347 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
348 |
friend constexpr auto operator|(const uint128_fallback& lhs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
349 |
const uint128_fallback& rhs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
350 |
-> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
351 |
return {lhs.hi_ | rhs.hi_, lhs.lo_ | rhs.lo_}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
352 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
353 |
friend constexpr auto operator&(const uint128_fallback& lhs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
354 |
const uint128_fallback& rhs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
355 |
-> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
356 |
return {lhs.hi_ & rhs.hi_, lhs.lo_ & rhs.lo_}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
357 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
358 |
friend constexpr auto operator~(const uint128_fallback& n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
359 |
-> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
360 |
return {~n.hi_, ~n.lo_}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
361 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
362 |
friend auto operator+(const uint128_fallback& lhs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
363 |
const uint128_fallback& rhs) -> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
364 |
auto result = uint128_fallback(lhs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
365 |
result += rhs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
366 |
return result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
367 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
368 |
friend auto operator*(const uint128_fallback& lhs, uint32_t rhs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
369 |
-> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
370 |
FMT_ASSERT(lhs.hi_ == 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
371 |
uint64_t hi = (lhs.lo_ >> 32) * rhs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
372 |
uint64_t lo = (lhs.lo_ & ~uint32_t()) * rhs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
373 |
uint64_t new_lo = (hi << 32) + lo; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
374 |
return {(hi >> 32) + (new_lo < lo ? 1 : 0), new_lo}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
375 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
376 |
friend auto operator-(const uint128_fallback& lhs, uint64_t rhs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
377 |
-> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
378 |
return {lhs.hi_ - (lhs.lo_ < rhs ? 1 : 0), lhs.lo_ - rhs}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
379 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
380 |
FMT_CONSTEXPR auto operator>>(int shift) const -> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
381 |
if (shift == 64) return {0, hi_}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
382 |
if (shift > 64) return uint128_fallback(0, hi_) >> (shift - 64); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
383 |
return {hi_ >> shift, (hi_ << (64 - shift)) | (lo_ >> shift)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
384 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
385 |
FMT_CONSTEXPR auto operator<<(int shift) const -> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
386 |
if (shift == 64) return {lo_, 0}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
387 |
if (shift > 64) return uint128_fallback(lo_, 0) << (shift - 64); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
388 |
return {hi_ << shift | (lo_ >> (64 - shift)), (lo_ << shift)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
389 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
390 |
FMT_CONSTEXPR auto operator>>=(int shift) -> uint128_fallback& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
391 |
return *this = *this >> shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
392 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
393 |
FMT_CONSTEXPR void operator+=(uint128_fallback n) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
394 |
uint64_t new_lo = lo_ + n.lo_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
395 |
uint64_t new_hi = hi_ + n.hi_ + (new_lo < lo_ ? 1 : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
396 |
FMT_ASSERT(new_hi >= hi_, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
397 |
lo_ = new_lo; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
398 |
hi_ = new_hi; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
399 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
400 |
FMT_CONSTEXPR void operator&=(uint128_fallback n) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
401 |
lo_ &= n.lo_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
402 |
hi_ &= n.hi_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
403 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
404 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
405 |
FMT_CONSTEXPR20 auto operator+=(uint64_t n) noexcept -> uint128_fallback& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
406 |
if (is_constant_evaluated()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
407 |
lo_ += n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
408 |
hi_ += (lo_ < n ? 1 : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
409 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
410 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
411 |
#if FMT_HAS_BUILTIN(__builtin_addcll) && !defined(__ibmxl__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
412 |
unsigned long long carry; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
413 |
lo_ = __builtin_addcll(lo_, n, 0, &carry); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
414 |
hi_ += carry; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
415 |
#elif FMT_HAS_BUILTIN(__builtin_ia32_addcarryx_u64) && !defined(__ibmxl__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
416 |
unsigned long long result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
417 |
auto carry = __builtin_ia32_addcarryx_u64(0, lo_, n, &result); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
418 |
lo_ = result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
419 |
hi_ += carry; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
420 |
#elif defined(_MSC_VER) && defined(_M_X64) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
421 |
auto carry = _addcarry_u64(0, lo_, n, &lo_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
422 |
_addcarry_u64(carry, hi_, 0, &hi_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
423 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
424 |
lo_ += n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
425 |
hi_ += (lo_ < n ? 1 : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
426 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
427 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
428 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
429 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
430 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
431 |
using uint128_t = conditional_t<FMT_USE_INT128, uint128_opt, uint128_fallback>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
432 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
433 |
#ifdef UINTPTR_MAX |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
434 |
using uintptr_t = ::uintptr_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
435 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
436 |
using uintptr_t = uint128_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
437 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
438 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
439 |
// Returns the largest possible value for type T. Same as |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
440 |
// std::numeric_limits<T>::max() but shorter and not affected by the max macro. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
441 |
template <typename T> constexpr auto max_value() -> T { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
442 |
return (std::numeric_limits<T>::max)(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
443 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
444 |
template <typename T> constexpr auto num_bits() -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
445 |
return std::numeric_limits<T>::digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
446 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
447 |
// std::numeric_limits<T>::digits may return 0 for 128-bit ints. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
448 |
template <> constexpr auto num_bits<int128_opt>() -> int { return 128; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
449 |
template <> constexpr auto num_bits<uint128_opt>() -> int { return 128; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
450 |
template <> constexpr auto num_bits<uint128_fallback>() -> int { return 128; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
451 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
452 |
// A heterogeneous bit_cast used for converting 96-bit long double to uint128_t |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
453 |
// and 128-bit pointers to uint128_fallback. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
454 |
template <typename To, typename From, FMT_ENABLE_IF(sizeof(To) > sizeof(From))> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
455 |
inline auto bit_cast(const From& from) -> To { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
456 |
constexpr auto size = static_cast<int>(sizeof(From) / sizeof(unsigned)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
457 |
struct data_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
458 |
unsigned value[static_cast<unsigned>(size)]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
459 |
} data = bit_cast<data_t>(from); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
460 |
auto result = To(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
461 |
if (const_check(is_big_endian())) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
462 |
for (int i = 0; i < size; ++i) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
463 |
result = (result << num_bits<unsigned>()) | data.value[i]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
464 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
465 |
for (int i = size - 1; i >= 0; --i) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
466 |
result = (result << num_bits<unsigned>()) | data.value[i]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
467 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
468 |
return result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
469 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
470 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
471 |
template <typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
472 |
FMT_CONSTEXPR20 inline auto countl_zero_fallback(UInt n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
473 |
int lz = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
474 |
constexpr UInt msb_mask = static_cast<UInt>(1) << (num_bits<UInt>() - 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
475 |
for (; (n & msb_mask) == 0; n <<= 1) lz++; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
476 |
return lz; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
477 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
478 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
479 |
FMT_CONSTEXPR20 inline auto countl_zero(uint32_t n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
480 |
#ifdef FMT_BUILTIN_CLZ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
481 |
if (!is_constant_evaluated()) return FMT_BUILTIN_CLZ(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
482 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
483 |
return countl_zero_fallback(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
484 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
485 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
486 |
FMT_CONSTEXPR20 inline auto countl_zero(uint64_t n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
487 |
#ifdef FMT_BUILTIN_CLZLL |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
488 |
if (!is_constant_evaluated()) return FMT_BUILTIN_CLZLL(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
489 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
490 |
return countl_zero_fallback(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
491 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
492 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
493 |
FMT_INLINE void assume(bool condition) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
494 |
(void)condition; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
495 |
#if FMT_HAS_BUILTIN(__builtin_assume) && !FMT_ICC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
496 |
__builtin_assume(condition); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
497 |
#elif FMT_GCC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
498 |
if (!condition) __builtin_unreachable(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
499 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
500 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
501 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
502 |
// An approximation of iterator_t for pre-C++20 systems. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
503 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
504 |
using iterator_t = decltype(std::begin(std::declval<T&>())); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
505 |
template <typename T> using sentinel_t = decltype(std::end(std::declval<T&>())); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
506 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
507 |
// A workaround for std::string not having mutable data() until C++17. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
508 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
509 |
inline auto get_data(std::basic_string<Char>& s) -> Char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
510 |
return &s[0]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
511 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
512 |
template <typename Container> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
513 |
inline auto get_data(Container& c) -> typename Container::value_type* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
514 |
return c.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
515 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
516 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
517 |
// Attempts to reserve space for n extra characters in the output range. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
518 |
// Returns a pointer to the reserved range or a reference to it. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
519 |
template <typename OutputIt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
520 |
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&& |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
521 |
is_contiguous<typename OutputIt::container>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
522 |
#if FMT_CLANG_VERSION >= 307 && !FMT_ICC_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
523 |
__attribute__((no_sanitize("undefined"))) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
524 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
525 |
inline auto |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
526 |
reserve(OutputIt it, size_t n) -> typename OutputIt::value_type* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
527 |
auto& c = get_container(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
528 |
size_t size = c.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
529 |
c.resize(size + n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
530 |
return get_data(c) + size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
531 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
532 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
533 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
534 |
inline auto reserve(basic_appender<T> it, size_t n) -> basic_appender<T> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
535 |
buffer<T>& buf = get_container(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
536 |
buf.try_reserve(buf.size() + n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
537 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
538 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
539 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
540 |
template <typename Iterator> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
541 |
constexpr auto reserve(Iterator& it, size_t) -> Iterator& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
542 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
543 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
544 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
545 |
template <typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
546 |
using reserve_iterator = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
547 |
remove_reference_t<decltype(reserve(std::declval<OutputIt&>(), 0))>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
548 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
549 |
template <typename T, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
550 |
constexpr auto to_pointer(OutputIt, size_t) -> T* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
551 |
return nullptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
552 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
553 |
template <typename T> auto to_pointer(basic_appender<T> it, size_t n) -> T* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
554 |
buffer<T>& buf = get_container(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
555 |
auto size = buf.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
556 |
buf.try_reserve(size + n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
557 |
if (buf.capacity() < size + n) return nullptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
558 |
buf.try_resize(size + n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
559 |
return buf.data() + size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
560 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
561 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
562 |
template <typename OutputIt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
563 |
FMT_ENABLE_IF(is_back_insert_iterator<OutputIt>::value&& |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
564 |
is_contiguous<typename OutputIt::container>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
565 |
inline auto base_iterator(OutputIt it, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
566 |
typename OutputIt::container_type::value_type*) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
567 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
568 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
569 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
570 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
571 |
template <typename Iterator> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
572 |
constexpr auto base_iterator(Iterator, Iterator it) -> Iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
573 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
574 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
575 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
576 |
// <algorithm> is spectacularly slow to compile in C++20 so use a simple fill_n |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
577 |
// instead (#1998). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
578 |
template <typename OutputIt, typename Size, typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
579 |
FMT_CONSTEXPR auto fill_n(OutputIt out, Size count, const T& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
580 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
581 |
for (Size i = 0; i < count; ++i) *out++ = value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
582 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
583 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
584 |
template <typename T, typename Size> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
585 |
FMT_CONSTEXPR20 auto fill_n(T* out, Size count, char value) -> T* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
586 |
if (is_constant_evaluated()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
587 |
return fill_n<T*, Size, T>(out, count, value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
588 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
589 |
std::memset(out, value, to_unsigned(count)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
590 |
return out + count; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
591 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
592 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
593 |
template <typename OutChar, typename InputIt, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
594 |
FMT_CONSTEXPR FMT_NOINLINE auto copy_noinline(InputIt begin, InputIt end, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
595 |
OutputIt out) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
596 |
return copy<OutChar>(begin, end, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
597 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
598 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
599 |
// A public domain branchless UTF-8 decoder by Christopher Wellons: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
600 |
// https://github.com/skeeto/branchless-utf8 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
601 |
/* Decode the next character, c, from s, reporting errors in e. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
602 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
603 |
* Since this is a branchless decoder, four bytes will be read from the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
604 |
* buffer regardless of the actual length of the next character. This |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
605 |
* means the buffer _must_ have at least three bytes of zero padding |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
606 |
* following the end of the data stream. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
607 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
608 |
* Errors are reported in e, which will be non-zero if the parsed |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
609 |
* character was somehow invalid: invalid byte sequence, non-canonical |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
610 |
* encoding, or a surrogate half. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
611 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
612 |
* The function returns a pointer to the next character. When an error |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
613 |
* occurs, this pointer will be a guess that depends on the particular |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
614 |
* error, but it will always advance at least one byte. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
615 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
616 |
FMT_CONSTEXPR inline auto utf8_decode(const char* s, uint32_t* c, int* e) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
617 |
-> const char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
618 |
constexpr const int masks[] = {0x00, 0x7f, 0x1f, 0x0f, 0x07}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
619 |
constexpr const uint32_t mins[] = {4194304, 0, 128, 2048, 65536}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
620 |
constexpr const int shiftc[] = {0, 18, 12, 6, 0}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
621 |
constexpr const int shifte[] = {0, 6, 4, 2, 0}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
622 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
623 |
int len = "\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\1\0\0\0\0\0\0\0\0\2\2\2\2\3\3\4" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
624 |
[static_cast<unsigned char>(*s) >> 3]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
625 |
// Compute the pointer to the next character early so that the next |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
626 |
// iteration can start working on the next character. Neither Clang |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
627 |
// nor GCC figure out this reordering on their own. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
628 |
const char* next = s + len + !len; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
629 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
630 |
using uchar = unsigned char; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
631 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
632 |
// Assume a four-byte character and load four bytes. Unused bits are |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
633 |
// shifted out. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
634 |
*c = uint32_t(uchar(s[0]) & masks[len]) << 18; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
635 |
*c |= uint32_t(uchar(s[1]) & 0x3f) << 12; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
636 |
*c |= uint32_t(uchar(s[2]) & 0x3f) << 6; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
637 |
*c |= uint32_t(uchar(s[3]) & 0x3f) << 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
638 |
*c >>= shiftc[len]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
639 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
640 |
// Accumulate the various error conditions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
641 |
*e = (*c < mins[len]) << 6; // non-canonical encoding |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
642 |
*e |= ((*c >> 11) == 0x1b) << 7; // surrogate half? |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
643 |
*e |= (*c > 0x10FFFF) << 8; // out of range? |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
644 |
*e |= (uchar(s[1]) & 0xc0) >> 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
645 |
*e |= (uchar(s[2]) & 0xc0) >> 4; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
646 |
*e |= uchar(s[3]) >> 6; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
647 |
*e ^= 0x2a; // top two bits of each tail byte correct? |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
648 |
*e >>= shifte[len]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
649 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
650 |
return next; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
651 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
652 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
653 |
constexpr FMT_INLINE_VARIABLE uint32_t invalid_code_point = ~uint32_t(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
654 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
655 |
// Invokes f(cp, sv) for every code point cp in s with sv being the string view |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
656 |
// corresponding to the code point. cp is invalid_code_point on error. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
657 |
template <typename F> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
658 |
FMT_CONSTEXPR void for_each_codepoint(string_view s, F f) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
659 |
auto decode = [f](const char* buf_ptr, const char* ptr) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
660 |
auto cp = uint32_t(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
661 |
auto error = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
662 |
auto end = utf8_decode(buf_ptr, &cp, &error); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
663 |
bool result = f(error ? invalid_code_point : cp, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
664 |
string_view(ptr, error ? 1 : to_unsigned(end - buf_ptr))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
665 |
return result ? (error ? buf_ptr + 1 : end) : nullptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
666 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
667 |
auto p = s.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
668 |
const size_t block_size = 4; // utf8_decode always reads blocks of 4 chars. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
669 |
if (s.size() >= block_size) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
670 |
for (auto end = p + s.size() - block_size + 1; p < end;) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
671 |
p = decode(p, p); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
672 |
if (!p) return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
673 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
674 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
675 |
if (auto num_chars_left = s.data() + s.size() - p) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
676 |
char buf[2 * block_size - 1] = {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
677 |
copy<char>(p, p + num_chars_left, buf); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
678 |
const char* buf_ptr = buf; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
679 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
680 |
auto end = decode(buf_ptr, p); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
681 |
if (!end) return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
682 |
p += end - buf_ptr; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
683 |
buf_ptr = end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
684 |
} while (buf_ptr - buf < num_chars_left); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
685 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
686 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
687 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
688 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
689 |
inline auto compute_width(basic_string_view<Char> s) -> size_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
690 |
return s.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
691 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
692 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
693 |
// Computes approximate display width of a UTF-8 string. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
694 |
FMT_CONSTEXPR inline auto compute_width(string_view s) -> size_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
695 |
size_t num_code_points = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
696 |
// It is not a lambda for compatibility with C++14. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
697 |
struct count_code_points { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
698 |
size_t* count; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
699 |
FMT_CONSTEXPR auto operator()(uint32_t cp, string_view) const -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
700 |
*count += detail::to_unsigned( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
701 |
1 + |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
702 |
(cp >= 0x1100 && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
703 |
(cp <= 0x115f || // Hangul Jamo init. consonants |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
704 |
cp == 0x2329 || // LEFT-POINTING ANGLE BRACKET |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
705 |
cp == 0x232a || // RIGHT-POINTING ANGLE BRACKET |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
706 |
// CJK ... Yi except IDEOGRAPHIC HALF FILL SPACE: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
707 |
(cp >= 0x2e80 && cp <= 0xa4cf && cp != 0x303f) || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
708 |
(cp >= 0xac00 && cp <= 0xd7a3) || // Hangul Syllables |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
709 |
(cp >= 0xf900 && cp <= 0xfaff) || // CJK Compatibility Ideographs |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
710 |
(cp >= 0xfe10 && cp <= 0xfe19) || // Vertical Forms |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
711 |
(cp >= 0xfe30 && cp <= 0xfe6f) || // CJK Compatibility Forms |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
712 |
(cp >= 0xff00 && cp <= 0xff60) || // Fullwidth Forms |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
713 |
(cp >= 0xffe0 && cp <= 0xffe6) || // Fullwidth Forms |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
714 |
(cp >= 0x20000 && cp <= 0x2fffd) || // CJK |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
715 |
(cp >= 0x30000 && cp <= 0x3fffd) || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
716 |
// Miscellaneous Symbols and Pictographs + Emoticons: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
717 |
(cp >= 0x1f300 && cp <= 0x1f64f) || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
718 |
// Supplemental Symbols and Pictographs: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
719 |
(cp >= 0x1f900 && cp <= 0x1f9ff)))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
720 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
721 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
722 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
723 |
// We could avoid branches by using utf8_decode directly. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
724 |
for_each_codepoint(s, count_code_points{&num_code_points}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
725 |
return num_code_points; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
726 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
727 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
728 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
729 |
inline auto code_point_index(basic_string_view<Char> s, size_t n) -> size_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
730 |
size_t size = s.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
731 |
return n < size ? n : size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
732 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
733 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
734 |
// Calculates the index of the nth code point in a UTF-8 string. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
735 |
inline auto code_point_index(string_view s, size_t n) -> size_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
736 |
size_t result = s.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
737 |
const char* begin = s.begin(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
738 |
for_each_codepoint(s, [begin, &n, &result](uint32_t, string_view sv) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
739 |
if (n != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
740 |
--n; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
741 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
742 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
743 |
result = to_unsigned(sv.begin() - begin); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
744 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
745 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
746 |
return result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
747 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
748 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
749 |
template <typename T> struct is_integral : std::is_integral<T> {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
750 |
template <> struct is_integral<int128_opt> : std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
751 |
template <> struct is_integral<uint128_t> : std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
752 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
753 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
754 |
using is_signed = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
755 |
std::integral_constant<bool, std::numeric_limits<T>::is_signed || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
756 |
std::is_same<T, int128_opt>::value>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
757 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
758 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
759 |
using is_integer = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
760 |
bool_constant<is_integral<T>::value && !std::is_same<T, bool>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
761 |
!std::is_same<T, char>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
762 |
!std::is_same<T, wchar_t>::value>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
763 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
764 |
#ifndef FMT_USE_FLOAT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
765 |
# define FMT_USE_FLOAT 1 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
766 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
767 |
#ifndef FMT_USE_DOUBLE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
768 |
# define FMT_USE_DOUBLE 1 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
769 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
770 |
#ifndef FMT_USE_LONG_DOUBLE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
771 |
# define FMT_USE_LONG_DOUBLE 1 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
772 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
773 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
774 |
#if defined(FMT_USE_FLOAT128) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
775 |
// Use the provided definition. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
776 |
#elif FMT_CLANG_VERSION && FMT_HAS_INCLUDE(<quadmath.h>) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
777 |
# define FMT_USE_FLOAT128 1 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
778 |
#elif FMT_GCC_VERSION && defined(_GLIBCXX_USE_FLOAT128) && \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
779 |
!defined(__STRICT_ANSI__) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
780 |
# define FMT_USE_FLOAT128 1 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
781 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
782 |
# define FMT_USE_FLOAT128 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
783 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
784 |
#if FMT_USE_FLOAT128 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
785 |
using float128 = __float128; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
786 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
787 |
using float128 = void; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
788 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
789 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
790 |
template <typename T> using is_float128 = std::is_same<T, float128>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
791 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
792 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
793 |
using is_floating_point = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
794 |
bool_constant<std::is_floating_point<T>::value || is_float128<T>::value>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
795 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
796 |
template <typename T, bool = std::is_floating_point<T>::value> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
797 |
struct is_fast_float : bool_constant<std::numeric_limits<T>::is_iec559 && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
798 |
sizeof(T) <= sizeof(double)> {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
799 |
template <typename T> struct is_fast_float<T, false> : std::false_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
800 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
801 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
802 |
using is_double_double = bool_constant<std::numeric_limits<T>::digits == 106>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
803 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
804 |
#ifndef FMT_USE_FULL_CACHE_DRAGONBOX |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
805 |
# define FMT_USE_FULL_CACHE_DRAGONBOX 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
806 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
807 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
808 |
template <typename T, typename Enable = void> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
809 |
struct is_locale : std::false_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
810 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
811 |
struct is_locale<T, void_t<decltype(T::classic())>> : std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
812 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
813 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
814 |
FMT_BEGIN_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
815 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
816 |
// The number of characters to store in the basic_memory_buffer object itself |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
817 |
// to avoid dynamic memory allocation. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
818 |
enum { inline_buffer_size = 500 }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
819 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
820 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
821 |
* A dynamically growing memory buffer for trivially copyable/constructible |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
822 |
* types with the first `SIZE` elements stored in the object itself. Most |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
823 |
* commonly used via the `memory_buffer` alias for `char`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
824 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
825 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
826 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
827 |
* auto out = fmt::memory_buffer(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
828 |
* fmt::format_to(std::back_inserter(out), "The answer is {}.", 42); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
829 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
830 |
* This will append "The answer is 42." to `out`. The buffer content can be |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
831 |
* converted to `std::string` with `to_string(out)`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
832 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
833 |
template <typename T, size_t SIZE = inline_buffer_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
834 |
typename Allocator = std::allocator<T>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
835 |
class basic_memory_buffer : public detail::buffer<T> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
836 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
837 |
T store_[SIZE]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
838 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
839 |
// Don't inherit from Allocator to avoid generating type_info for it. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
840 |
FMT_NO_UNIQUE_ADDRESS Allocator alloc_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
841 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
842 |
// Deallocate memory allocated by the buffer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
843 |
FMT_CONSTEXPR20 void deallocate() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
844 |
T* data = this->data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
845 |
if (data != store_) alloc_.deallocate(data, this->capacity()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
846 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
847 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
848 |
static FMT_CONSTEXPR20 void grow(detail::buffer<T>& buf, size_t size) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
849 |
detail::abort_fuzzing_if(size > 5000); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
850 |
auto& self = static_cast<basic_memory_buffer&>(buf); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
851 |
const size_t max_size = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
852 |
std::allocator_traits<Allocator>::max_size(self.alloc_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
853 |
size_t old_capacity = buf.capacity(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
854 |
size_t new_capacity = old_capacity + old_capacity / 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
855 |
if (size > new_capacity) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
856 |
new_capacity = size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
857 |
else if (new_capacity > max_size) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
858 |
new_capacity = size > max_size ? size : max_size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
859 |
T* old_data = buf.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
860 |
T* new_data = self.alloc_.allocate(new_capacity); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
861 |
// Suppress a bogus -Wstringop-overflow in gcc 13.1 (#3481). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
862 |
detail::assume(buf.size() <= new_capacity); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
863 |
// The following code doesn't throw, so the raw pointer above doesn't leak. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
864 |
memcpy(new_data, old_data, buf.size() * sizeof(T)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
865 |
self.set(new_data, new_capacity); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
866 |
// deallocate must not throw according to the standard, but even if it does, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
867 |
// the buffer already uses the new storage and will deallocate it in |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
868 |
// destructor. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
869 |
if (old_data != self.store_) self.alloc_.deallocate(old_data, old_capacity); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
870 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
871 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
872 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
873 |
using value_type = T; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
874 |
using const_reference = const T&; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
875 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
876 |
FMT_CONSTEXPR20 explicit basic_memory_buffer( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
877 |
const Allocator& alloc = Allocator()) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
878 |
: detail::buffer<T>(grow), alloc_(alloc) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
879 |
this->set(store_, SIZE); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
880 |
if (detail::is_constant_evaluated()) detail::fill_n(store_, SIZE, T()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
881 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
882 |
FMT_CONSTEXPR20 ~basic_memory_buffer() { deallocate(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
883 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
884 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
885 |
// Move data from other to this buffer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
886 |
FMT_CONSTEXPR20 void move(basic_memory_buffer& other) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
887 |
alloc_ = std::move(other.alloc_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
888 |
T* data = other.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
889 |
size_t size = other.size(), capacity = other.capacity(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
890 |
if (data == other.store_) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
891 |
this->set(store_, capacity); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
892 |
detail::copy<T>(other.store_, other.store_ + size, store_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
893 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
894 |
this->set(data, capacity); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
895 |
// Set pointer to the inline array so that delete is not called |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
896 |
// when deallocating. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
897 |
other.set(other.store_, 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
898 |
other.clear(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
899 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
900 |
this->resize(size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
901 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
902 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
903 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
904 |
/// Constructs a `basic_memory_buffer` object moving the content of the other |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
905 |
/// object to it. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
906 |
FMT_CONSTEXPR20 basic_memory_buffer(basic_memory_buffer&& other) noexcept |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
907 |
: detail::buffer<T>(grow) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
908 |
move(other); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
909 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
910 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
911 |
/// Moves the content of the other `basic_memory_buffer` object to this one. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
912 |
auto operator=(basic_memory_buffer&& other) noexcept -> basic_memory_buffer& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
913 |
FMT_ASSERT(this != &other, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
914 |
deallocate(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
915 |
move(other); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
916 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
917 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
918 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
919 |
// Returns a copy of the allocator associated with this buffer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
920 |
auto get_allocator() const -> Allocator { return alloc_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
921 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
922 |
/// Resizes the buffer to contain `count` elements. If T is a POD type new |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
923 |
/// elements may not be initialized. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
924 |
FMT_CONSTEXPR20 void resize(size_t count) { this->try_resize(count); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
925 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
926 |
/// Increases the buffer capacity to `new_capacity`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
927 |
void reserve(size_t new_capacity) { this->try_reserve(new_capacity); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
928 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
929 |
using detail::buffer<T>::append; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
930 |
template <typename ContiguousRange> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
931 |
void append(const ContiguousRange& range) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
932 |
append(range.data(), range.data() + range.size()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
933 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
934 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
935 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
936 |
using memory_buffer = basic_memory_buffer<char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
937 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
938 |
template <typename T, size_t SIZE, typename Allocator> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
939 |
struct is_contiguous<basic_memory_buffer<T, SIZE, Allocator>> : std::true_type { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
940 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
941 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
942 |
FMT_END_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
943 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
944 |
FMT_API auto write_console(int fd, string_view text) -> bool; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
945 |
FMT_API void print(std::FILE*, string_view); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
946 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
947 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
948 |
FMT_BEGIN_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
949 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
950 |
// Suppress a misleading warning in older versions of clang. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
951 |
#if FMT_CLANG_VERSION |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
952 |
# pragma clang diagnostic ignored "-Wweak-vtables" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
953 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
954 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
955 |
/// An error reported from a formatting function. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
956 |
class FMT_SO_VISIBILITY("default") format_error : public std::runtime_error { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
957 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
958 |
using std::runtime_error::runtime_error; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
959 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
960 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
961 |
namespace detail_exported { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
962 |
#if FMT_USE_NONTYPE_TEMPLATE_ARGS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
963 |
template <typename Char, size_t N> struct fixed_string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
964 |
constexpr fixed_string(const Char (&str)[N]) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
965 |
detail::copy<Char, const Char*, Char*>(static_cast<const Char*>(str), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
966 |
str + N, data); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
967 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
968 |
Char data[N] = {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
969 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
970 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
971 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
972 |
// Converts a compile-time string to basic_string_view. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
973 |
template <typename Char, size_t N> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
974 |
constexpr auto compile_string_to_view(const Char (&s)[N]) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
975 |
-> basic_string_view<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
976 |
// Remove trailing NUL character if needed. Won't be present if this is used |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
977 |
// with a raw character array (i.e. not defined as a string). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
978 |
return {s, N - (std::char_traits<Char>::to_int_type(s[N - 1]) == 0 ? 1 : 0)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
979 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
980 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
981 |
constexpr auto compile_string_to_view(basic_string_view<Char> s) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
982 |
-> basic_string_view<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
983 |
return s; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
984 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
985 |
} // namespace detail_exported |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
986 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
987 |
// A generic formatting context with custom output iterator and character |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
988 |
// (code unit) support. Char is the format string code unit type which can be |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
989 |
// different from OutputIt::value_type. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
990 |
template <typename OutputIt, typename Char> class generic_context { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
991 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
992 |
OutputIt out_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
993 |
basic_format_args<generic_context> args_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
994 |
detail::locale_ref loc_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
995 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
996 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
997 |
using char_type = Char; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
998 |
using iterator = OutputIt; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
999 |
using parse_context_type = basic_format_parse_context<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1000 |
template <typename T> using formatter_type = formatter<T, Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1001 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1002 |
constexpr generic_context(OutputIt out, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1003 |
basic_format_args<generic_context> ctx_args, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1004 |
detail::locale_ref loc = {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1005 |
: out_(out), args_(ctx_args), loc_(loc) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1006 |
generic_context(generic_context&&) = default; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1007 |
generic_context(const generic_context&) = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1008 |
void operator=(const generic_context&) = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1009 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1010 |
constexpr auto arg(int id) const -> basic_format_arg<generic_context> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1011 |
return args_.get(id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1012 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1013 |
auto arg(basic_string_view<Char> name) -> basic_format_arg<generic_context> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1014 |
return args_.get(name); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1015 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1016 |
FMT_CONSTEXPR auto arg_id(basic_string_view<Char> name) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1017 |
return args_.get_id(name); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1018 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1019 |
auto args() const -> const basic_format_args<generic_context>& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1020 |
return args_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1021 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1022 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1023 |
FMT_CONSTEXPR auto out() -> iterator { return out_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1024 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1025 |
void advance_to(iterator it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1026 |
if (!detail::is_back_insert_iterator<iterator>()) out_ = it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1027 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1028 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1029 |
FMT_CONSTEXPR auto locale() -> detail::locale_ref { return loc_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1030 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1031 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1032 |
class loc_value { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1033 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1034 |
basic_format_arg<format_context> value_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1035 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1036 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1037 |
template <typename T, FMT_ENABLE_IF(!detail::is_float128<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1038 |
loc_value(T value) : value_(detail::make_arg<format_context>(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1039 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1040 |
template <typename T, FMT_ENABLE_IF(detail::is_float128<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1041 |
loc_value(T) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1042 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1043 |
template <typename Visitor> auto visit(Visitor&& vis) -> decltype(vis(0)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1044 |
return value_.visit(vis); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1045 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1046 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1047 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1048 |
// A locale facet that formats values in UTF-8. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1049 |
// It is parameterized on the locale to avoid the heavy <locale> include. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1050 |
template <typename Locale> class format_facet : public Locale::facet { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1051 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1052 |
std::string separator_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1053 |
std::string grouping_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1054 |
std::string decimal_point_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1055 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1056 |
protected: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1057 |
virtual auto do_put(appender out, loc_value val, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1058 |
const format_specs& specs) const -> bool; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1059 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1060 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1061 |
static FMT_API typename Locale::id id; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1062 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1063 |
explicit format_facet(Locale& loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1064 |
explicit format_facet(string_view sep = "", |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1065 |
std::initializer_list<unsigned char> g = {3}, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1066 |
std::string decimal_point = ".") |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1067 |
: separator_(sep.data(), sep.size()), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1068 |
grouping_(g.begin(), g.end()), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1069 |
decimal_point_(decimal_point) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1070 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1071 |
auto put(appender out, loc_value val, const format_specs& specs) const |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1072 |
-> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1073 |
return do_put(out, val, specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1074 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1075 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1076 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1077 |
FMT_END_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1078 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1079 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1080 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1081 |
// Returns true if value is negative, false otherwise. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1082 |
// Same as `value < 0` but doesn't produce warnings if T is an unsigned type. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1083 |
template <typename T, FMT_ENABLE_IF(is_signed<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1084 |
constexpr auto is_negative(T value) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1085 |
return value < 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1086 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1087 |
template <typename T, FMT_ENABLE_IF(!is_signed<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1088 |
constexpr auto is_negative(T) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1089 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1090 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1091 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1092 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1093 |
FMT_CONSTEXPR auto is_supported_floating_point(T) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1094 |
if (std::is_same<T, float>()) return FMT_USE_FLOAT; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1095 |
if (std::is_same<T, double>()) return FMT_USE_DOUBLE; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1096 |
if (std::is_same<T, long double>()) return FMT_USE_LONG_DOUBLE; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1097 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1098 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1099 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1100 |
// Smallest of uint32_t, uint64_t, uint128_t that is large enough to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1101 |
// represent all values of an integral type T. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1102 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1103 |
using uint32_or_64_or_128_t = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1104 |
conditional_t<num_bits<T>() <= 32 && !FMT_REDUCE_INT_INSTANTIATIONS, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1105 |
uint32_t, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1106 |
conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1107 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1108 |
using uint64_or_128_t = conditional_t<num_bits<T>() <= 64, uint64_t, uint128_t>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1109 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1110 |
#define FMT_POWERS_OF_10(factor) \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1111 |
factor * 10, (factor) * 100, (factor) * 1000, (factor) * 10000, \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1112 |
(factor) * 100000, (factor) * 1000000, (factor) * 10000000, \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1113 |
(factor) * 100000000, (factor) * 1000000000 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1114 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1115 |
// Converts value in the range [0, 100) to a string. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1116 |
constexpr auto digits2(size_t value) -> const char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1117 |
// GCC generates slightly better code when value is pointer-size. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1118 |
return &"0001020304050607080910111213141516171819" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1119 |
"2021222324252627282930313233343536373839" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1120 |
"4041424344454647484950515253545556575859" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1121 |
"6061626364656667686970717273747576777879" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1122 |
"8081828384858687888990919293949596979899"[value * 2]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1123 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1124 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1125 |
// Sign is a template parameter to workaround a bug in gcc 4.8. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1126 |
template <typename Char, typename Sign> constexpr auto sign(Sign s) -> Char { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1127 |
#if !FMT_GCC_VERSION || FMT_GCC_VERSION >= 604 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1128 |
static_assert(std::is_same<Sign, sign_t>::value, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1129 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1130 |
return static_cast<char>(((' ' << 24) | ('+' << 16) | ('-' << 8)) >> (s * 8)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1131 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1132 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1133 |
template <typename T> FMT_CONSTEXPR auto count_digits_fallback(T n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1134 |
int count = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1135 |
for (;;) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1136 |
// Integer division is slow so do it for a group of four digits instead |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1137 |
// of for every digit. The idea comes from the talk by Alexandrescu |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1138 |
// "Three Optimization Tips for C++". See speed-test for a comparison. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1139 |
if (n < 10) return count; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1140 |
if (n < 100) return count + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1141 |
if (n < 1000) return count + 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1142 |
if (n < 10000) return count + 3; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1143 |
n /= 10000u; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1144 |
count += 4; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1145 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1146 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1147 |
#if FMT_USE_INT128 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1148 |
FMT_CONSTEXPR inline auto count_digits(uint128_opt n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1149 |
return count_digits_fallback(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1150 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1151 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1152 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1153 |
#ifdef FMT_BUILTIN_CLZLL |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1154 |
// It is a separate function rather than a part of count_digits to workaround |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1155 |
// the lack of static constexpr in constexpr functions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1156 |
inline auto do_count_digits(uint64_t n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1157 |
// This has comparable performance to the version by Kendall Willets |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1158 |
// (https://github.com/fmtlib/format-benchmark/blob/master/digits10) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1159 |
// but uses smaller tables. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1160 |
// Maps bsr(n) to ceil(log10(pow(2, bsr(n) + 1) - 1)). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1161 |
static constexpr uint8_t bsr2log10[] = { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1162 |
1, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1163 |
6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1164 |
10, 11, 11, 11, 12, 12, 12, 13, 13, 13, 13, 14, 14, 14, 15, 15, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1165 |
15, 16, 16, 16, 16, 17, 17, 17, 18, 18, 18, 19, 19, 19, 19, 20}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1166 |
auto t = bsr2log10[FMT_BUILTIN_CLZLL(n | 1) ^ 63]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1167 |
static constexpr const uint64_t zero_or_powers_of_10[] = { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1168 |
0, 0, FMT_POWERS_OF_10(1U), FMT_POWERS_OF_10(1000000000ULL), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1169 |
10000000000000000000ULL}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1170 |
return t - (n < zero_or_powers_of_10[t]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1171 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1172 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1173 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1174 |
// Returns the number of decimal digits in n. Leading zeros are not counted |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1175 |
// except for n == 0 in which case count_digits returns 1. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1176 |
FMT_CONSTEXPR20 inline auto count_digits(uint64_t n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1177 |
#ifdef FMT_BUILTIN_CLZLL |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1178 |
if (!is_constant_evaluated()) return do_count_digits(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1179 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1180 |
return count_digits_fallback(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1181 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1182 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1183 |
// Counts the number of digits in n. BITS = log2(radix). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1184 |
template <int BITS, typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1185 |
FMT_CONSTEXPR auto count_digits(UInt n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1186 |
#ifdef FMT_BUILTIN_CLZ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1187 |
if (!is_constant_evaluated() && num_bits<UInt>() == 32) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1188 |
return (FMT_BUILTIN_CLZ(static_cast<uint32_t>(n) | 1) ^ 31) / BITS + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1189 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1190 |
// Lambda avoids unreachable code warnings from NVHPC. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1191 |
return [](UInt m) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1192 |
int num_digits = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1193 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1194 |
++num_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1195 |
} while ((m >>= BITS) != 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1196 |
return num_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1197 |
}(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1198 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1199 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1200 |
#ifdef FMT_BUILTIN_CLZ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1201 |
// It is a separate function rather than a part of count_digits to workaround |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1202 |
// the lack of static constexpr in constexpr functions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1203 |
FMT_INLINE auto do_count_digits(uint32_t n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1204 |
// An optimization by Kendall Willets from https://bit.ly/3uOIQrB. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1205 |
// This increments the upper 32 bits (log10(T) - 1) when >= T is added. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1206 |
# define FMT_INC(T) (((sizeof(#T) - 1ull) << 32) - T) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1207 |
static constexpr uint64_t table[] = { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1208 |
FMT_INC(0), FMT_INC(0), FMT_INC(0), // 8 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1209 |
FMT_INC(10), FMT_INC(10), FMT_INC(10), // 64 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1210 |
FMT_INC(100), FMT_INC(100), FMT_INC(100), // 512 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1211 |
FMT_INC(1000), FMT_INC(1000), FMT_INC(1000), // 4096 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1212 |
FMT_INC(10000), FMT_INC(10000), FMT_INC(10000), // 32k |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1213 |
FMT_INC(100000), FMT_INC(100000), FMT_INC(100000), // 256k |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1214 |
FMT_INC(1000000), FMT_INC(1000000), FMT_INC(1000000), // 2048k |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1215 |
FMT_INC(10000000), FMT_INC(10000000), FMT_INC(10000000), // 16M |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1216 |
FMT_INC(100000000), FMT_INC(100000000), FMT_INC(100000000), // 128M |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1217 |
FMT_INC(1000000000), FMT_INC(1000000000), FMT_INC(1000000000), // 1024M |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1218 |
FMT_INC(1000000000), FMT_INC(1000000000) // 4B |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1219 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1220 |
auto inc = table[FMT_BUILTIN_CLZ(n | 1) ^ 31]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1221 |
return static_cast<int>((n + inc) >> 32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1222 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1223 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1224 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1225 |
// Optional version of count_digits for better performance on 32-bit platforms. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1226 |
FMT_CONSTEXPR20 inline auto count_digits(uint32_t n) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1227 |
#ifdef FMT_BUILTIN_CLZ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1228 |
if (!is_constant_evaluated()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1229 |
return do_count_digits(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1230 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1231 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1232 |
return count_digits_fallback(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1233 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1234 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1235 |
template <typename Int> constexpr auto digits10() noexcept -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1236 |
return std::numeric_limits<Int>::digits10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1237 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1238 |
template <> constexpr auto digits10<int128_opt>() noexcept -> int { return 38; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1239 |
template <> constexpr auto digits10<uint128_t>() noexcept -> int { return 38; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1240 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1241 |
template <typename Char> struct thousands_sep_result { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1242 |
std::string grouping; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1243 |
Char thousands_sep; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1244 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1245 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1246 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1247 |
FMT_API auto thousands_sep_impl(locale_ref loc) -> thousands_sep_result<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1248 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1249 |
inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1250 |
auto result = thousands_sep_impl<char>(loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1251 |
return {result.grouping, Char(result.thousands_sep)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1252 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1253 |
template <> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1254 |
inline auto thousands_sep(locale_ref loc) -> thousands_sep_result<wchar_t> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1255 |
return thousands_sep_impl<wchar_t>(loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1256 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1257 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1258 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1259 |
FMT_API auto decimal_point_impl(locale_ref loc) -> Char; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1260 |
template <typename Char> inline auto decimal_point(locale_ref loc) -> Char { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1261 |
return Char(decimal_point_impl<char>(loc)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1262 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1263 |
template <> inline auto decimal_point(locale_ref loc) -> wchar_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1264 |
return decimal_point_impl<wchar_t>(loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1265 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1266 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1267 |
// Compares two characters for equality. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1268 |
template <typename Char> auto equal2(const Char* lhs, const char* rhs) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1269 |
return lhs[0] == Char(rhs[0]) && lhs[1] == Char(rhs[1]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1270 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1271 |
inline auto equal2(const char* lhs, const char* rhs) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1272 |
return memcmp(lhs, rhs, 2) == 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1273 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1274 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1275 |
// Copies two characters from src to dst. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1276 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1277 |
FMT_CONSTEXPR20 FMT_INLINE void copy2(Char* dst, const char* src) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1278 |
if (!is_constant_evaluated() && sizeof(Char) == sizeof(char)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1279 |
memcpy(dst, src, 2); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1280 |
return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1281 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1282 |
*dst++ = static_cast<Char>(*src++); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1283 |
*dst = static_cast<Char>(*src); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1284 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1285 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1286 |
template <typename Iterator> struct format_decimal_result { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1287 |
Iterator begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1288 |
Iterator end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1289 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1290 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1291 |
// Formats a decimal unsigned integer value writing into out pointing to a |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1292 |
// buffer of specified size. The caller must ensure that the buffer is large |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1293 |
// enough. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1294 |
template <typename Char, typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1295 |
FMT_CONSTEXPR20 auto format_decimal(Char* out, UInt value, int size) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1296 |
-> format_decimal_result<Char*> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1297 |
FMT_ASSERT(size >= count_digits(value), "invalid digit count"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1298 |
out += size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1299 |
Char* end = out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1300 |
while (value >= 100) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1301 |
// Integer division is slow so do it for a group of two digits instead |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1302 |
// of for every digit. The idea comes from the talk by Alexandrescu |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1303 |
// "Three Optimization Tips for C++". See speed-test for a comparison. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1304 |
out -= 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1305 |
copy2(out, digits2(static_cast<size_t>(value % 100))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1306 |
value /= 100; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1307 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1308 |
if (value < 10) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1309 |
*--out = static_cast<Char>('0' + value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1310 |
return {out, end}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1311 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1312 |
out -= 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1313 |
copy2(out, digits2(static_cast<size_t>(value))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1314 |
return {out, end}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1315 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1316 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1317 |
template <typename Char, typename UInt, typename Iterator, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1318 |
FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<Iterator>>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1319 |
FMT_CONSTEXPR inline auto format_decimal(Iterator out, UInt value, int size) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1320 |
-> format_decimal_result<Iterator> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1321 |
// Buffer is large enough to hold all digits (digits10 + 1). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1322 |
Char buffer[digits10<UInt>() + 1] = {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1323 |
auto end = format_decimal(buffer, value, size).end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1324 |
return {out, detail::copy_noinline<Char>(buffer, end, out)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1325 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1326 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1327 |
template <unsigned BASE_BITS, typename Char, typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1328 |
FMT_CONSTEXPR auto format_uint(Char* buffer, UInt value, int num_digits, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1329 |
bool upper = false) -> Char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1330 |
buffer += num_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1331 |
Char* end = buffer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1332 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1333 |
const char* digits = upper ? "0123456789ABCDEF" : "0123456789abcdef"; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1334 |
unsigned digit = static_cast<unsigned>(value & ((1 << BASE_BITS) - 1)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1335 |
*--buffer = static_cast<Char>(BASE_BITS < 4 ? static_cast<char>('0' + digit) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1336 |
: digits[digit]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1337 |
} while ((value >>= BASE_BITS) != 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1338 |
return end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1339 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1340 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1341 |
template <unsigned BASE_BITS, typename Char, typename It, typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1342 |
FMT_CONSTEXPR inline auto format_uint(It out, UInt value, int num_digits, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1343 |
bool upper = false) -> It { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1344 |
if (auto ptr = to_pointer<Char>(out, to_unsigned(num_digits))) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1345 |
format_uint<BASE_BITS>(ptr, value, num_digits, upper); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1346 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1347 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1348 |
// Buffer should be large enough to hold all digits (digits / BASE_BITS + 1). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1349 |
char buffer[num_bits<UInt>() / BASE_BITS + 1] = {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1350 |
format_uint<BASE_BITS>(buffer, value, num_digits, upper); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1351 |
return detail::copy_noinline<Char>(buffer, buffer + num_digits, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1352 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1353 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1354 |
// A converter from UTF-8 to UTF-16. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1355 |
class utf8_to_utf16 { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1356 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1357 |
basic_memory_buffer<wchar_t> buffer_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1358 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1359 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1360 |
FMT_API explicit utf8_to_utf16(string_view s); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1361 |
operator basic_string_view<wchar_t>() const { return {&buffer_[0], size()}; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1362 |
auto size() const -> size_t { return buffer_.size() - 1; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1363 |
auto c_str() const -> const wchar_t* { return &buffer_[0]; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1364 |
auto str() const -> std::wstring { return {&buffer_[0], size()}; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1365 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1366 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1367 |
enum class to_utf8_error_policy { abort, replace }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1368 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1369 |
// A converter from UTF-16/UTF-32 (host endian) to UTF-8. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1370 |
template <typename WChar, typename Buffer = memory_buffer> class to_utf8 { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1371 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1372 |
Buffer buffer_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1373 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1374 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1375 |
to_utf8() {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1376 |
explicit to_utf8(basic_string_view<WChar> s, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1377 |
to_utf8_error_policy policy = to_utf8_error_policy::abort) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1378 |
static_assert(sizeof(WChar) == 2 || sizeof(WChar) == 4, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1379 |
"Expect utf16 or utf32"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1380 |
if (!convert(s, policy)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1381 |
FMT_THROW(std::runtime_error(sizeof(WChar) == 2 ? "invalid utf16" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1382 |
: "invalid utf32")); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1383 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1384 |
operator string_view() const { return string_view(&buffer_[0], size()); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1385 |
auto size() const -> size_t { return buffer_.size() - 1; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1386 |
auto c_str() const -> const char* { return &buffer_[0]; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1387 |
auto str() const -> std::string { return std::string(&buffer_[0], size()); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1388 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1389 |
// Performs conversion returning a bool instead of throwing exception on |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1390 |
// conversion error. This method may still throw in case of memory allocation |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1391 |
// error. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1392 |
auto convert(basic_string_view<WChar> s, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1393 |
to_utf8_error_policy policy = to_utf8_error_policy::abort) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1394 |
-> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1395 |
if (!convert(buffer_, s, policy)) return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1396 |
buffer_.push_back(0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1397 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1398 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1399 |
static auto convert(Buffer& buf, basic_string_view<WChar> s, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1400 |
to_utf8_error_policy policy = to_utf8_error_policy::abort) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1401 |
-> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1402 |
for (auto p = s.begin(); p != s.end(); ++p) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1403 |
uint32_t c = static_cast<uint32_t>(*p); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1404 |
if (sizeof(WChar) == 2 && c >= 0xd800 && c <= 0xdfff) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1405 |
// Handle a surrogate pair. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1406 |
++p; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1407 |
if (p == s.end() || (c & 0xfc00) != 0xd800 || (*p & 0xfc00) != 0xdc00) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1408 |
if (policy == to_utf8_error_policy::abort) return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1409 |
buf.append(string_view("\xEF\xBF\xBD")); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1410 |
--p; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1411 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1412 |
c = (c << 10) + static_cast<uint32_t>(*p) - 0x35fdc00; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1413 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1414 |
} else if (c < 0x80) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1415 |
buf.push_back(static_cast<char>(c)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1416 |
} else if (c < 0x800) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1417 |
buf.push_back(static_cast<char>(0xc0 | (c >> 6))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1418 |
buf.push_back(static_cast<char>(0x80 | (c & 0x3f))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1419 |
} else if ((c >= 0x800 && c <= 0xd7ff) || (c >= 0xe000 && c <= 0xffff)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1420 |
buf.push_back(static_cast<char>(0xe0 | (c >> 12))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1421 |
buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1422 |
buf.push_back(static_cast<char>(0x80 | (c & 0x3f))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1423 |
} else if (c >= 0x10000 && c <= 0x10ffff) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1424 |
buf.push_back(static_cast<char>(0xf0 | (c >> 18))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1425 |
buf.push_back(static_cast<char>(0x80 | ((c & 0x3ffff) >> 12))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1426 |
buf.push_back(static_cast<char>(0x80 | ((c & 0xfff) >> 6))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1427 |
buf.push_back(static_cast<char>(0x80 | (c & 0x3f))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1428 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1429 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1430 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1431 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1432 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1433 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1434 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1435 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1436 |
// Computes 128-bit result of multiplication of two 64-bit unsigned integers. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1437 |
inline auto umul128(uint64_t x, uint64_t y) noexcept -> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1438 |
#if FMT_USE_INT128 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1439 |
auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1440 |
return {static_cast<uint64_t>(p >> 64), static_cast<uint64_t>(p)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1441 |
#elif defined(_MSC_VER) && defined(_M_X64) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1442 |
auto hi = uint64_t(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1443 |
auto lo = _umul128(x, y, &hi); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1444 |
return {hi, lo}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1445 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1446 |
const uint64_t mask = static_cast<uint64_t>(max_value<uint32_t>()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1447 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1448 |
uint64_t a = x >> 32; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1449 |
uint64_t b = x & mask; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1450 |
uint64_t c = y >> 32; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1451 |
uint64_t d = y & mask; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1452 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1453 |
uint64_t ac = a * c; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1454 |
uint64_t bc = b * c; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1455 |
uint64_t ad = a * d; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1456 |
uint64_t bd = b * d; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1457 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1458 |
uint64_t intermediate = (bd >> 32) + (ad & mask) + (bc & mask); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1459 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1460 |
return {ac + (intermediate >> 32) + (ad >> 32) + (bc >> 32), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1461 |
(intermediate << 32) + (bd & mask)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1462 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1463 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1464 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1465 |
namespace dragonbox { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1466 |
// Computes floor(log10(pow(2, e))) for e in [-2620, 2620] using the method from |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1467 |
// https://fmt.dev/papers/Dragonbox.pdf#page=28, section 6.1. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1468 |
inline auto floor_log10_pow2(int e) noexcept -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1469 |
FMT_ASSERT(e <= 2620 && e >= -2620, "too large exponent"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1470 |
static_assert((-1 >> 1) == -1, "right shift is not arithmetic"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1471 |
return (e * 315653) >> 20; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1472 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1473 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1474 |
inline auto floor_log2_pow10(int e) noexcept -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1475 |
FMT_ASSERT(e <= 1233 && e >= -1233, "too large exponent"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1476 |
return (e * 1741647) >> 19; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1477 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1478 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1479 |
// Computes upper 64 bits of multiplication of two 64-bit unsigned integers. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1480 |
inline auto umul128_upper64(uint64_t x, uint64_t y) noexcept -> uint64_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1481 |
#if FMT_USE_INT128 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1482 |
auto p = static_cast<uint128_opt>(x) * static_cast<uint128_opt>(y); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1483 |
return static_cast<uint64_t>(p >> 64); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1484 |
#elif defined(_MSC_VER) && defined(_M_X64) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1485 |
return __umulh(x, y); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1486 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1487 |
return umul128(x, y).high(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1488 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1489 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1490 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1491 |
// Computes upper 128 bits of multiplication of a 64-bit unsigned integer and a |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1492 |
// 128-bit unsigned integer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1493 |
inline auto umul192_upper128(uint64_t x, uint128_fallback y) noexcept |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1494 |
-> uint128_fallback { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1495 |
uint128_fallback r = umul128(x, y.high()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1496 |
r += umul128_upper64(x, y.low()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1497 |
return r; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1498 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1499 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1500 |
FMT_API auto get_cached_power(int k) noexcept -> uint128_fallback; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1501 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1502 |
// Type-specific information that Dragonbox uses. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1503 |
template <typename T, typename Enable = void> struct float_info; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1504 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1505 |
template <> struct float_info<float> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1506 |
using carrier_uint = uint32_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1507 |
static const int exponent_bits = 8; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1508 |
static const int kappa = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1509 |
static const int big_divisor = 100; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1510 |
static const int small_divisor = 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1511 |
static const int min_k = -31; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1512 |
static const int max_k = 46; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1513 |
static const int shorter_interval_tie_lower_threshold = -35; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1514 |
static const int shorter_interval_tie_upper_threshold = -35; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1515 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1516 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1517 |
template <> struct float_info<double> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1518 |
using carrier_uint = uint64_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1519 |
static const int exponent_bits = 11; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1520 |
static const int kappa = 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1521 |
static const int big_divisor = 1000; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1522 |
static const int small_divisor = 100; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1523 |
static const int min_k = -292; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1524 |
static const int max_k = 341; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1525 |
static const int shorter_interval_tie_lower_threshold = -77; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1526 |
static const int shorter_interval_tie_upper_threshold = -77; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1527 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1528 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1529 |
// An 80- or 128-bit floating point number. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1530 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1531 |
struct float_info<T, enable_if_t<std::numeric_limits<T>::digits == 64 || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1532 |
std::numeric_limits<T>::digits == 113 || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1533 |
is_float128<T>::value>> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1534 |
using carrier_uint = detail::uint128_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1535 |
static const int exponent_bits = 15; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1536 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1537 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1538 |
// A double-double floating point number. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1539 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1540 |
struct float_info<T, enable_if_t<is_double_double<T>::value>> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1541 |
using carrier_uint = detail::uint128_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1542 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1543 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1544 |
template <typename T> struct decimal_fp { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1545 |
using significand_type = typename float_info<T>::carrier_uint; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1546 |
significand_type significand; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1547 |
int exponent; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1548 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1549 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1550 |
template <typename T> FMT_API auto to_decimal(T x) noexcept -> decimal_fp<T>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1551 |
} // namespace dragonbox |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1552 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1553 |
// Returns true iff Float has the implicit bit which is not stored. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1554 |
template <typename Float> constexpr auto has_implicit_bit() -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1555 |
// An 80-bit FP number has a 64-bit significand an no implicit bit. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1556 |
return std::numeric_limits<Float>::digits != 64; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1557 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1558 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1559 |
// Returns the number of significand bits stored in Float. The implicit bit is |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1560 |
// not counted since it is not stored. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1561 |
template <typename Float> constexpr auto num_significand_bits() -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1562 |
// std::numeric_limits may not support __float128. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1563 |
return is_float128<Float>() ? 112 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1564 |
: (std::numeric_limits<Float>::digits - |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1565 |
(has_implicit_bit<Float>() ? 1 : 0)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1566 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1567 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1568 |
template <typename Float> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1569 |
constexpr auto exponent_mask() -> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1570 |
typename dragonbox::float_info<Float>::carrier_uint { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1571 |
using float_uint = typename dragonbox::float_info<Float>::carrier_uint; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1572 |
return ((float_uint(1) << dragonbox::float_info<Float>::exponent_bits) - 1) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1573 |
<< num_significand_bits<Float>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1574 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1575 |
template <typename Float> constexpr auto exponent_bias() -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1576 |
// std::numeric_limits may not support __float128. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1577 |
return is_float128<Float>() ? 16383 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1578 |
: std::numeric_limits<Float>::max_exponent - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1579 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1580 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1581 |
// Writes the exponent exp in the form "[+-]d{2,3}" to buffer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1582 |
template <typename Char, typename It> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1583 |
FMT_CONSTEXPR auto write_exponent(int exp, It it) -> It { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1584 |
FMT_ASSERT(-10000 < exp && exp < 10000, "exponent out of range"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1585 |
if (exp < 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1586 |
*it++ = static_cast<Char>('-'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1587 |
exp = -exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1588 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1589 |
*it++ = static_cast<Char>('+'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1590 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1591 |
if (exp >= 100) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1592 |
const char* top = digits2(to_unsigned(exp / 100)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1593 |
if (exp >= 1000) *it++ = static_cast<Char>(top[0]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1594 |
*it++ = static_cast<Char>(top[1]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1595 |
exp %= 100; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1596 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1597 |
const char* d = digits2(to_unsigned(exp)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1598 |
*it++ = static_cast<Char>(d[0]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1599 |
*it++ = static_cast<Char>(d[1]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1600 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1601 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1602 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1603 |
// A floating-point number f * pow(2, e) where F is an unsigned type. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1604 |
template <typename F> struct basic_fp { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1605 |
F f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1606 |
int e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1607 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1608 |
static constexpr const int num_significand_bits = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1609 |
static_cast<int>(sizeof(F) * num_bits<unsigned char>()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1610 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1611 |
constexpr basic_fp() : f(0), e(0) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1612 |
constexpr basic_fp(uint64_t f_val, int e_val) : f(f_val), e(e_val) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1613 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1614 |
// Constructs fp from an IEEE754 floating-point number. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1615 |
template <typename Float> FMT_CONSTEXPR basic_fp(Float n) { assign(n); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1616 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1617 |
// Assigns n to this and return true iff predecessor is closer than successor. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1618 |
template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1619 |
FMT_CONSTEXPR auto assign(Float n) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1620 |
static_assert(std::numeric_limits<Float>::digits <= 113, "unsupported FP"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1621 |
// Assume Float is in the format [sign][exponent][significand]. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1622 |
using carrier_uint = typename dragonbox::float_info<Float>::carrier_uint; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1623 |
const auto num_float_significand_bits = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1624 |
detail::num_significand_bits<Float>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1625 |
const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1626 |
const auto significand_mask = implicit_bit - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1627 |
auto u = bit_cast<carrier_uint>(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1628 |
f = static_cast<F>(u & significand_mask); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1629 |
auto biased_e = static_cast<int>((u & exponent_mask<Float>()) >> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1630 |
num_float_significand_bits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1631 |
// The predecessor is closer if n is a normalized power of 2 (f == 0) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1632 |
// other than the smallest normalized number (biased_e > 1). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1633 |
auto is_predecessor_closer = f == 0 && biased_e > 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1634 |
if (biased_e == 0) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1635 |
biased_e = 1; // Subnormals use biased exponent 1 (min exponent). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1636 |
else if (has_implicit_bit<Float>()) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1637 |
f += static_cast<F>(implicit_bit); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1638 |
e = biased_e - exponent_bias<Float>() - num_float_significand_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1639 |
if (!has_implicit_bit<Float>()) ++e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1640 |
return is_predecessor_closer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1641 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1642 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1643 |
template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1644 |
FMT_CONSTEXPR auto assign(Float n) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1645 |
static_assert(std::numeric_limits<double>::is_iec559, "unsupported FP"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1646 |
return assign(static_cast<double>(n)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1647 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1648 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1649 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1650 |
using fp = basic_fp<unsigned long long>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1651 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1652 |
// Normalizes the value converted from double and multiplied by (1 << SHIFT). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1653 |
template <int SHIFT = 0, typename F> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1654 |
FMT_CONSTEXPR auto normalize(basic_fp<F> value) -> basic_fp<F> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1655 |
// Handle subnormals. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1656 |
const auto implicit_bit = F(1) << num_significand_bits<double>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1657 |
const auto shifted_implicit_bit = implicit_bit << SHIFT; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1658 |
while ((value.f & shifted_implicit_bit) == 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1659 |
value.f <<= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1660 |
--value.e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1661 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1662 |
// Subtract 1 to account for hidden bit. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1663 |
const auto offset = basic_fp<F>::num_significand_bits - |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1664 |
num_significand_bits<double>() - SHIFT - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1665 |
value.f <<= offset; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1666 |
value.e -= offset; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1667 |
return value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1668 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1669 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1670 |
// Computes lhs * rhs / pow(2, 64) rounded to nearest with half-up tie breaking. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1671 |
FMT_CONSTEXPR inline auto multiply(uint64_t lhs, uint64_t rhs) -> uint64_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1672 |
#if FMT_USE_INT128 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1673 |
auto product = static_cast<__uint128_t>(lhs) * rhs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1674 |
auto f = static_cast<uint64_t>(product >> 64); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1675 |
return (static_cast<uint64_t>(product) & (1ULL << 63)) != 0 ? f + 1 : f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1676 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1677 |
// Multiply 32-bit parts of significands. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1678 |
uint64_t mask = (1ULL << 32) - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1679 |
uint64_t a = lhs >> 32, b = lhs & mask; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1680 |
uint64_t c = rhs >> 32, d = rhs & mask; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1681 |
uint64_t ac = a * c, bc = b * c, ad = a * d, bd = b * d; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1682 |
// Compute mid 64-bit of result and round. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1683 |
uint64_t mid = (bd >> 32) + (ad & mask) + (bc & mask) + (1U << 31); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1684 |
return ac + (ad >> 32) + (bc >> 32) + (mid >> 32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1685 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1686 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1687 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1688 |
FMT_CONSTEXPR inline auto operator*(fp x, fp y) -> fp { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1689 |
return {multiply(x.f, y.f), x.e + y.e + 64}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1690 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1691 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1692 |
template <typename T, bool doublish = num_bits<T>() == num_bits<double>()> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1693 |
using convert_float_result = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1694 |
conditional_t<std::is_same<T, float>::value || doublish, double, T>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1695 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1696 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1697 |
constexpr auto convert_float(T value) -> convert_float_result<T> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1698 |
return static_cast<convert_float_result<T>>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1699 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1700 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1701 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1702 |
FMT_NOINLINE FMT_CONSTEXPR auto fill(OutputIt it, size_t n, const fill_t& fill) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1703 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1704 |
auto fill_size = fill.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1705 |
if (fill_size == 1) return detail::fill_n(it, n, fill.template get<Char>()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1706 |
if (const Char* data = fill.template data<Char>()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1707 |
for (size_t i = 0; i < n; ++i) it = copy<Char>(data, data + fill_size, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1708 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1709 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1710 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1711 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1712 |
// Writes the output of f, padded according to format specifications in specs. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1713 |
// size: output size in code units. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1714 |
// width: output display width in (terminal) column positions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1715 |
template <typename Char, align::type align = align::left, typename OutputIt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1716 |
typename F> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1717 |
FMT_CONSTEXPR auto write_padded(OutputIt out, const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1718 |
size_t size, size_t width, F&& f) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1719 |
static_assert(align == align::left || align == align::right, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1720 |
unsigned spec_width = to_unsigned(specs.width); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1721 |
size_t padding = spec_width > width ? spec_width - width : 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1722 |
// Shifts are encoded as string literals because static constexpr is not |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1723 |
// supported in constexpr functions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1724 |
auto* shifts = align == align::left ? "\x1f\x1f\x00\x01" : "\x00\x1f\x00\x01"; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1725 |
size_t left_padding = padding >> shifts[specs.align]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1726 |
size_t right_padding = padding - left_padding; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1727 |
auto it = reserve(out, size + padding * specs.fill.size()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1728 |
if (left_padding != 0) it = fill<Char>(it, left_padding, specs.fill); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1729 |
it = f(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1730 |
if (right_padding != 0) it = fill<Char>(it, right_padding, specs.fill); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1731 |
return base_iterator(out, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1732 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1733 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1734 |
template <typename Char, align::type align = align::left, typename OutputIt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1735 |
typename F> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1736 |
constexpr auto write_padded(OutputIt out, const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1737 |
size_t size, F&& f) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1738 |
return write_padded<Char, align>(out, specs, size, size, f); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1739 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1740 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1741 |
template <typename Char, align::type align = align::left, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1742 |
FMT_CONSTEXPR auto write_bytes(OutputIt out, string_view bytes, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1743 |
const format_specs& specs = {}) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1744 |
return write_padded<Char, align>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1745 |
out, specs, bytes.size(), [bytes](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1746 |
const char* data = bytes.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1747 |
return copy<Char>(data, data + bytes.size(), it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1748 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1749 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1750 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1751 |
template <typename Char, typename OutputIt, typename UIntPtr> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1752 |
auto write_ptr(OutputIt out, UIntPtr value, const format_specs* specs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1753 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1754 |
int num_digits = count_digits<4>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1755 |
auto size = to_unsigned(num_digits) + size_t(2); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1756 |
auto write = [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1757 |
*it++ = static_cast<Char>('0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1758 |
*it++ = static_cast<Char>('x'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1759 |
return format_uint<4, Char>(it, value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1760 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1761 |
return specs ? write_padded<Char, align::right>(out, *specs, size, write) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1762 |
: base_iterator(out, write(reserve(out, size))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1763 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1764 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1765 |
// Returns true iff the code point cp is printable. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1766 |
FMT_API auto is_printable(uint32_t cp) -> bool; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1767 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1768 |
inline auto needs_escape(uint32_t cp) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1769 |
return cp < 0x20 || cp == 0x7f || cp == '"' || cp == '\\' || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1770 |
!is_printable(cp); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1771 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1772 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1773 |
template <typename Char> struct find_escape_result { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1774 |
const Char* begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1775 |
const Char* end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1776 |
uint32_t cp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1777 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1778 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1779 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1780 |
auto find_escape(const Char* begin, const Char* end) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1781 |
-> find_escape_result<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1782 |
for (; begin != end; ++begin) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1783 |
uint32_t cp = static_cast<unsigned_char<Char>>(*begin); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1784 |
if (const_check(sizeof(Char) == 1) && cp >= 0x80) continue; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1785 |
if (needs_escape(cp)) return {begin, begin + 1, cp}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1786 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1787 |
return {begin, nullptr, 0}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1788 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1789 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1790 |
inline auto find_escape(const char* begin, const char* end) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1791 |
-> find_escape_result<char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1792 |
if (!use_utf8()) return find_escape<char>(begin, end); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1793 |
auto result = find_escape_result<char>{end, nullptr, 0}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1794 |
for_each_codepoint(string_view(begin, to_unsigned(end - begin)), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1795 |
[&](uint32_t cp, string_view sv) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1796 |
if (needs_escape(cp)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1797 |
result = {sv.begin(), sv.end(), cp}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1798 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1799 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1800 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1801 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1802 |
return result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1803 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1804 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1805 |
#define FMT_STRING_IMPL(s, base, explicit) \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1806 |
[] { \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1807 |
/* Use the hidden visibility as a workaround for a GCC bug (#1973). */ \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1808 |
/* Use a macro-like name to avoid shadowing warnings. */ \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1809 |
struct FMT_VISIBILITY("hidden") FMT_COMPILE_STRING : base { \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1810 |
using char_type FMT_MAYBE_UNUSED = fmt::remove_cvref_t<decltype(s[0])>; \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1811 |
FMT_MAYBE_UNUSED FMT_CONSTEXPR explicit \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1812 |
operator fmt::basic_string_view<char_type>() const { \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1813 |
return fmt::detail_exported::compile_string_to_view<char_type>(s); \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1814 |
} \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1815 |
}; \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1816 |
return FMT_COMPILE_STRING(); \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1817 |
}() |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1818 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1819 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1820 |
* Constructs a compile-time format string from a string literal `s`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1821 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1822 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1823 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1824 |
* // A compile-time error because 'd' is an invalid specifier for strings. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1825 |
* std::string s = fmt::format(FMT_STRING("{:d}"), "foo"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1826 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1827 |
#define FMT_STRING(s) FMT_STRING_IMPL(s, fmt::detail::compile_string, ) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1828 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1829 |
template <size_t width, typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1830 |
auto write_codepoint(OutputIt out, char prefix, uint32_t cp) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1831 |
*out++ = static_cast<Char>('\\'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1832 |
*out++ = static_cast<Char>(prefix); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1833 |
Char buf[width]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1834 |
fill_n(buf, width, static_cast<Char>('0')); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1835 |
format_uint<4>(buf, cp, width); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1836 |
return copy<Char>(buf, buf + width, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1837 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1838 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1839 |
template <typename OutputIt, typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1840 |
auto write_escaped_cp(OutputIt out, const find_escape_result<Char>& escape) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1841 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1842 |
auto c = static_cast<Char>(escape.cp); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1843 |
switch (escape.cp) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1844 |
case '\n': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1845 |
*out++ = static_cast<Char>('\\'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1846 |
c = static_cast<Char>('n'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1847 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1848 |
case '\r': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1849 |
*out++ = static_cast<Char>('\\'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1850 |
c = static_cast<Char>('r'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1851 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1852 |
case '\t': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1853 |
*out++ = static_cast<Char>('\\'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1854 |
c = static_cast<Char>('t'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1855 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1856 |
case '"': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1857 |
FMT_FALLTHROUGH; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1858 |
case '\'': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1859 |
FMT_FALLTHROUGH; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1860 |
case '\\': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1861 |
*out++ = static_cast<Char>('\\'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1862 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1863 |
default: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1864 |
if (escape.cp < 0x100) return write_codepoint<2, Char>(out, 'x', escape.cp); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1865 |
if (escape.cp < 0x10000) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1866 |
return write_codepoint<4, Char>(out, 'u', escape.cp); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1867 |
if (escape.cp < 0x110000) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1868 |
return write_codepoint<8, Char>(out, 'U', escape.cp); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1869 |
for (Char escape_char : basic_string_view<Char>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1870 |
escape.begin, to_unsigned(escape.end - escape.begin))) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1871 |
out = write_codepoint<2, Char>(out, 'x', |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1872 |
static_cast<uint32_t>(escape_char) & 0xFF); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1873 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1874 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1875 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1876 |
*out++ = c; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1877 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1878 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1879 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1880 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1881 |
auto write_escaped_string(OutputIt out, basic_string_view<Char> str) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1882 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1883 |
*out++ = static_cast<Char>('"'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1884 |
auto begin = str.begin(), end = str.end(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1885 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1886 |
auto escape = find_escape(begin, end); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1887 |
out = copy<Char>(begin, escape.begin, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1888 |
begin = escape.end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1889 |
if (!begin) break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1890 |
out = write_escaped_cp<OutputIt, Char>(out, escape); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1891 |
} while (begin != end); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1892 |
*out++ = static_cast<Char>('"'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1893 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1894 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1895 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1896 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1897 |
auto write_escaped_char(OutputIt out, Char v) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1898 |
Char v_array[1] = {v}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1899 |
*out++ = static_cast<Char>('\''); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1900 |
if ((needs_escape(static_cast<uint32_t>(v)) && v != static_cast<Char>('"')) || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1901 |
v == static_cast<Char>('\'')) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1902 |
out = write_escaped_cp(out, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1903 |
find_escape_result<Char>{v_array, v_array + 1, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1904 |
static_cast<uint32_t>(v)}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1905 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1906 |
*out++ = v; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1907 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1908 |
*out++ = static_cast<Char>('\''); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1909 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1910 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1911 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1912 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1913 |
FMT_CONSTEXPR auto write_char(OutputIt out, Char value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1914 |
const format_specs& specs) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1915 |
bool is_debug = specs.type == presentation_type::debug; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1916 |
return write_padded<Char>(out, specs, 1, [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1917 |
if (is_debug) return write_escaped_char(it, value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1918 |
*it++ = value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1919 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1920 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1921 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1922 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1923 |
FMT_CONSTEXPR auto write(OutputIt out, Char value, const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1924 |
locale_ref loc = {}) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1925 |
// char is formatted as unsigned char for consistency across platforms. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1926 |
using unsigned_type = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1927 |
conditional_t<std::is_same<Char, char>::value, unsigned char, unsigned>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1928 |
return check_char_specs(specs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1929 |
? write_char<Char>(out, value, specs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1930 |
: write<Char>(out, static_cast<unsigned_type>(value), specs, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1931 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1932 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1933 |
// Data for write_int that doesn't depend on output iterator type. It is used to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1934 |
// avoid template code bloat. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1935 |
template <typename Char> struct write_int_data { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1936 |
size_t size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1937 |
size_t padding; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1938 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1939 |
FMT_CONSTEXPR write_int_data(int num_digits, unsigned prefix, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1940 |
const format_specs& specs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1941 |
: size((prefix >> 24) + to_unsigned(num_digits)), padding(0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1942 |
if (specs.align == align::numeric) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1943 |
auto width = to_unsigned(specs.width); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1944 |
if (width > size) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1945 |
padding = width - size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1946 |
size = width; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1947 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1948 |
} else if (specs.precision > num_digits) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1949 |
size = (prefix >> 24) + to_unsigned(specs.precision); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1950 |
padding = to_unsigned(specs.precision - num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1951 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1952 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1953 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1954 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1955 |
// Writes an integer in the format |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1956 |
// <left-padding><prefix><numeric-padding><digits><right-padding> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1957 |
// where <digits> are written by write_digits(it). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1958 |
// prefix contains chars in three lower bytes and the size in the fourth byte. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1959 |
template <typename Char, typename OutputIt, typename W> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1960 |
FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, int num_digits, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1961 |
unsigned prefix, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1962 |
const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1963 |
W write_digits) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1964 |
// Slightly faster check for specs.width == 0 && specs.precision == -1. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1965 |
if ((specs.width | (specs.precision + 1)) == 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1966 |
auto it = reserve(out, to_unsigned(num_digits) + (prefix >> 24)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1967 |
if (prefix != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1968 |
for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1969 |
*it++ = static_cast<Char>(p & 0xff); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1970 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1971 |
return base_iterator(out, write_digits(it)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1972 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1973 |
auto data = write_int_data<Char>(num_digits, prefix, specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1974 |
return write_padded<Char, align::right>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1975 |
out, specs, data.size, [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1976 |
for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1977 |
*it++ = static_cast<Char>(p & 0xff); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1978 |
it = detail::fill_n(it, data.padding, static_cast<Char>('0')); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1979 |
return write_digits(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1980 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1981 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1982 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1983 |
template <typename Char> class digit_grouping { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1984 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1985 |
std::string grouping_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1986 |
std::basic_string<Char> thousands_sep_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1987 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1988 |
struct next_state { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1989 |
std::string::const_iterator group; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1990 |
int pos; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1991 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1992 |
auto initial_state() const -> next_state { return {grouping_.begin(), 0}; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1993 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1994 |
// Returns the next digit group separator position. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1995 |
auto next(next_state& state) const -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1996 |
if (thousands_sep_.empty()) return max_value<int>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1997 |
if (state.group == grouping_.end()) return state.pos += grouping_.back(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1998 |
if (*state.group <= 0 || *state.group == max_value<char>()) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
1999 |
return max_value<int>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2000 |
state.pos += *state.group++; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2001 |
return state.pos; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2002 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2003 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2004 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2005 |
explicit digit_grouping(locale_ref loc, bool localized = true) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2006 |
if (!localized) return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2007 |
auto sep = thousands_sep<Char>(loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2008 |
grouping_ = sep.grouping; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2009 |
if (sep.thousands_sep) thousands_sep_.assign(1, sep.thousands_sep); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2010 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2011 |
digit_grouping(std::string grouping, std::basic_string<Char> sep) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2012 |
: grouping_(std::move(grouping)), thousands_sep_(std::move(sep)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2013 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2014 |
auto has_separator() const -> bool { return !thousands_sep_.empty(); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2015 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2016 |
auto count_separators(int num_digits) const -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2017 |
int count = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2018 |
auto state = initial_state(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2019 |
while (num_digits > next(state)) ++count; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2020 |
return count; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2021 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2022 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2023 |
// Applies grouping to digits and write the output to out. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2024 |
template <typename Out, typename C> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2025 |
auto apply(Out out, basic_string_view<C> digits) const -> Out { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2026 |
auto num_digits = static_cast<int>(digits.size()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2027 |
auto separators = basic_memory_buffer<int>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2028 |
separators.push_back(0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2029 |
auto state = initial_state(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2030 |
while (int i = next(state)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2031 |
if (i >= num_digits) break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2032 |
separators.push_back(i); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2033 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2034 |
for (int i = 0, sep_index = static_cast<int>(separators.size() - 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2035 |
i < num_digits; ++i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2036 |
if (num_digits - i == separators[sep_index]) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2037 |
out = copy<Char>(thousands_sep_.data(), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2038 |
thousands_sep_.data() + thousands_sep_.size(), out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2039 |
--sep_index; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2040 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2041 |
*out++ = static_cast<Char>(digits[to_unsigned(i)]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2042 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2043 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2044 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2045 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2046 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2047 |
FMT_CONSTEXPR inline void prefix_append(unsigned& prefix, unsigned value) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2048 |
prefix |= prefix != 0 ? value << 8 : value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2049 |
prefix += (1u + (value > 0xff ? 1 : 0)) << 24; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2050 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2051 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2052 |
// Writes a decimal integer with digit grouping. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2053 |
template <typename OutputIt, typename UInt, typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2054 |
auto write_int(OutputIt out, UInt value, unsigned prefix, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2055 |
const format_specs& specs, const digit_grouping<Char>& grouping) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2056 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2057 |
static_assert(std::is_same<uint64_or_128_t<UInt>, UInt>::value, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2058 |
int num_digits = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2059 |
auto buffer = memory_buffer(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2060 |
switch (specs.type) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2061 |
default: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2062 |
FMT_ASSERT(false, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2063 |
FMT_FALLTHROUGH; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2064 |
case presentation_type::none: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2065 |
case presentation_type::dec: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2066 |
num_digits = count_digits(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2067 |
format_decimal<char>(appender(buffer), value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2068 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2069 |
case presentation_type::hex: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2070 |
if (specs.alt) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2071 |
prefix_append(prefix, unsigned(specs.upper ? 'X' : 'x') << 8 | '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2072 |
num_digits = count_digits<4>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2073 |
format_uint<4, char>(appender(buffer), value, num_digits, specs.upper); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2074 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2075 |
case presentation_type::oct: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2076 |
num_digits = count_digits<3>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2077 |
// Octal prefix '0' is counted as a digit, so only add it if precision |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2078 |
// is not greater than the number of digits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2079 |
if (specs.alt && specs.precision <= num_digits && value != 0) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2080 |
prefix_append(prefix, '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2081 |
format_uint<3, char>(appender(buffer), value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2082 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2083 |
case presentation_type::bin: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2084 |
if (specs.alt) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2085 |
prefix_append(prefix, unsigned(specs.upper ? 'B' : 'b') << 8 | '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2086 |
num_digits = count_digits<1>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2087 |
format_uint<1, char>(appender(buffer), value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2088 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2089 |
case presentation_type::chr: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2090 |
return write_char<Char>(out, static_cast<Char>(value), specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2091 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2092 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2093 |
unsigned size = (prefix != 0 ? prefix >> 24 : 0) + to_unsigned(num_digits) + |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2094 |
to_unsigned(grouping.count_separators(num_digits)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2095 |
return write_padded<Char, align::right>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2096 |
out, specs, size, size, [&](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2097 |
for (unsigned p = prefix & 0xffffff; p != 0; p >>= 8) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2098 |
*it++ = static_cast<Char>(p & 0xff); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2099 |
return grouping.apply(it, string_view(buffer.data(), buffer.size())); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2100 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2101 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2102 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2103 |
// Writes a localized value. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2104 |
FMT_API auto write_loc(appender out, loc_value value, const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2105 |
locale_ref loc) -> bool; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2106 |
template <typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2107 |
inline auto write_loc(OutputIt, loc_value, const format_specs&, locale_ref) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2108 |
-> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2109 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2110 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2111 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2112 |
template <typename UInt> struct write_int_arg { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2113 |
UInt abs_value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2114 |
unsigned prefix; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2115 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2116 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2117 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2118 |
FMT_CONSTEXPR auto make_write_int_arg(T value, sign_t sign) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2119 |
-> write_int_arg<uint32_or_64_or_128_t<T>> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2120 |
auto prefix = 0u; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2121 |
auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2122 |
if (is_negative(value)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2123 |
prefix = 0x01000000 | '-'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2124 |
abs_value = 0 - abs_value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2125 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2126 |
constexpr const unsigned prefixes[4] = {0, 0, 0x1000000u | '+', |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2127 |
0x1000000u | ' '}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2128 |
prefix = prefixes[sign]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2129 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2130 |
return {abs_value, prefix}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2131 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2132 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2133 |
template <typename Char = char> struct loc_writer { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2134 |
basic_appender<Char> out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2135 |
const format_specs& specs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2136 |
std::basic_string<Char> sep; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2137 |
std::string grouping; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2138 |
std::basic_string<Char> decimal_point; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2139 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2140 |
template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2141 |
auto operator()(T value) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2142 |
auto arg = make_write_int_arg(value, specs.sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2143 |
write_int(out, static_cast<uint64_or_128_t<T>>(arg.abs_value), arg.prefix, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2144 |
specs, digit_grouping<Char>(grouping, sep)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2145 |
return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2146 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2147 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2148 |
template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2149 |
auto operator()(T) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2150 |
return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2151 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2152 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2153 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2154 |
template <typename Char, typename OutputIt, typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2155 |
FMT_CONSTEXPR FMT_INLINE auto write_int(OutputIt out, write_int_arg<T> arg, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2156 |
const format_specs& specs, locale_ref) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2157 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2158 |
static_assert(std::is_same<T, uint32_or_64_or_128_t<T>>::value, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2159 |
auto abs_value = arg.abs_value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2160 |
auto prefix = arg.prefix; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2161 |
switch (specs.type) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2162 |
default: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2163 |
FMT_ASSERT(false, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2164 |
FMT_FALLTHROUGH; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2165 |
case presentation_type::none: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2166 |
case presentation_type::dec: { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2167 |
int num_digits = count_digits(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2168 |
return write_int<Char>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2169 |
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2170 |
return format_decimal<Char>(it, abs_value, num_digits).end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2171 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2172 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2173 |
case presentation_type::hex: { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2174 |
if (specs.alt) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2175 |
prefix_append(prefix, unsigned(specs.upper ? 'X' : 'x') << 8 | '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2176 |
int num_digits = count_digits<4>(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2177 |
return write_int<Char>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2178 |
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2179 |
return format_uint<4, Char>(it, abs_value, num_digits, specs.upper); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2180 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2181 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2182 |
case presentation_type::oct: { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2183 |
int num_digits = count_digits<3>(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2184 |
// Octal prefix '0' is counted as a digit, so only add it if precision |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2185 |
// is not greater than the number of digits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2186 |
if (specs.alt && specs.precision <= num_digits && abs_value != 0) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2187 |
prefix_append(prefix, '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2188 |
return write_int<Char>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2189 |
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2190 |
return format_uint<3, Char>(it, abs_value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2191 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2192 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2193 |
case presentation_type::bin: { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2194 |
if (specs.alt) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2195 |
prefix_append(prefix, unsigned(specs.upper ? 'B' : 'b') << 8 | '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2196 |
int num_digits = count_digits<1>(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2197 |
return write_int<Char>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2198 |
out, num_digits, prefix, specs, [=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2199 |
return format_uint<1, Char>(it, abs_value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2200 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2201 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2202 |
case presentation_type::chr: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2203 |
return write_char<Char>(out, static_cast<Char>(abs_value), specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2204 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2205 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2206 |
template <typename Char, typename OutputIt, typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2207 |
FMT_CONSTEXPR FMT_NOINLINE auto write_int_noinline(OutputIt out, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2208 |
write_int_arg<T> arg, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2209 |
const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2210 |
locale_ref loc) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2211 |
return write_int<Char>(out, arg, specs, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2212 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2213 |
template <typename Char, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2214 |
FMT_ENABLE_IF(is_integral<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2215 |
!std::is_same<T, bool>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2216 |
!std::is_same<T, Char>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2217 |
FMT_CONSTEXPR FMT_INLINE auto write(basic_appender<Char> out, T value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2218 |
const format_specs& specs, locale_ref loc) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2219 |
-> basic_appender<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2220 |
if (specs.localized && write_loc(out, value, specs, loc)) return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2221 |
return write_int_noinline<Char>(out, make_write_int_arg(value, specs.sign), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2222 |
specs, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2223 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2224 |
// An inlined version of write used in format string compilation. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2225 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2226 |
FMT_ENABLE_IF(is_integral<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2227 |
!std::is_same<T, bool>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2228 |
!std::is_same<T, Char>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2229 |
!std::is_same<OutputIt, basic_appender<Char>>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2230 |
FMT_CONSTEXPR FMT_INLINE auto write(OutputIt out, T value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2231 |
const format_specs& specs, locale_ref loc) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2232 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2233 |
if (specs.localized && write_loc(out, value, specs, loc)) return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2234 |
return write_int<Char>(out, make_write_int_arg(value, specs.sign), specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2235 |
loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2236 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2237 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2238 |
// An output iterator that counts the number of objects written to it and |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2239 |
// discards them. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2240 |
class counting_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2241 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2242 |
size_t count_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2243 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2244 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2245 |
using iterator_category = std::output_iterator_tag; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2246 |
using difference_type = std::ptrdiff_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2247 |
using pointer = void; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2248 |
using reference = void; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2249 |
FMT_UNCHECKED_ITERATOR(counting_iterator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2250 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2251 |
struct value_type { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2252 |
template <typename T> FMT_CONSTEXPR void operator=(const T&) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2253 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2254 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2255 |
FMT_CONSTEXPR counting_iterator() : count_(0) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2256 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2257 |
FMT_CONSTEXPR auto count() const -> size_t { return count_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2258 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2259 |
FMT_CONSTEXPR auto operator++() -> counting_iterator& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2260 |
++count_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2261 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2262 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2263 |
FMT_CONSTEXPR auto operator++(int) -> counting_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2264 |
auto it = *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2265 |
++*this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2266 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2267 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2268 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2269 |
FMT_CONSTEXPR friend auto operator+(counting_iterator it, difference_type n) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2270 |
-> counting_iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2271 |
it.count_ += static_cast<size_t>(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2272 |
return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2273 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2274 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2275 |
FMT_CONSTEXPR auto operator*() const -> value_type { return {}; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2276 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2277 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2278 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2279 |
FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> s, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2280 |
const format_specs& specs) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2281 |
auto data = s.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2282 |
auto size = s.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2283 |
if (specs.precision >= 0 && to_unsigned(specs.precision) < size) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2284 |
size = code_point_index(s, to_unsigned(specs.precision)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2285 |
bool is_debug = specs.type == presentation_type::debug; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2286 |
size_t width = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2287 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2288 |
if (is_debug) size = write_escaped_string(counting_iterator{}, s).count(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2289 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2290 |
if (specs.width != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2291 |
if (is_debug) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2292 |
width = size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2293 |
else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2294 |
width = compute_width(basic_string_view<Char>(data, size)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2295 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2296 |
return write_padded<Char>(out, specs, size, width, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2297 |
[=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2298 |
if (is_debug) return write_escaped_string(it, s); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2299 |
return copy<Char>(data, data + size, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2300 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2301 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2302 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2303 |
FMT_CONSTEXPR auto write(OutputIt out, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2304 |
basic_string_view<type_identity_t<Char>> s, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2305 |
const format_specs& specs, locale_ref) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2306 |
return write<Char>(out, s, specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2307 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2308 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2309 |
FMT_CONSTEXPR auto write(OutputIt out, const Char* s, const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2310 |
locale_ref) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2311 |
if (specs.type == presentation_type::pointer) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2312 |
return write_ptr<Char>(out, bit_cast<uintptr_t>(s), &specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2313 |
if (!s) report_error("string pointer is null"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2314 |
return write<Char>(out, basic_string_view<Char>(s), specs, {}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2315 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2316 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2317 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2318 |
FMT_ENABLE_IF(is_integral<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2319 |
!std::is_same<T, bool>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2320 |
!std::is_same<T, Char>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2321 |
FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2322 |
auto abs_value = static_cast<uint32_or_64_or_128_t<T>>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2323 |
bool negative = is_negative(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2324 |
// Don't do -abs_value since it trips unsigned-integer-overflow sanitizer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2325 |
if (negative) abs_value = ~abs_value + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2326 |
int num_digits = count_digits(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2327 |
auto size = (negative ? 1 : 0) + static_cast<size_t>(num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2328 |
if (auto ptr = to_pointer<Char>(out, size)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2329 |
if (negative) *ptr++ = static_cast<Char>('-'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2330 |
format_decimal<Char>(ptr, abs_value, num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2331 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2332 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2333 |
if (negative) *out++ = static_cast<Char>('-'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2334 |
return format_decimal<Char>(out, abs_value, num_digits).end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2335 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2336 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2337 |
// DEPRECATED! |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2338 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2339 |
FMT_CONSTEXPR auto parse_align(const Char* begin, const Char* end, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2340 |
format_specs& specs) -> const Char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2341 |
FMT_ASSERT(begin != end, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2342 |
auto align = align::none; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2343 |
auto p = begin + code_point_length(begin); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2344 |
if (end - p <= 0) p = begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2345 |
for (;;) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2346 |
switch (to_ascii(*p)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2347 |
case '<': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2348 |
align = align::left; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2349 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2350 |
case '>': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2351 |
align = align::right; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2352 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2353 |
case '^': |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2354 |
align = align::center; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2355 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2356 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2357 |
if (align != align::none) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2358 |
if (p != begin) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2359 |
auto c = *begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2360 |
if (c == '}') return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2361 |
if (c == '{') { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2362 |
report_error("invalid fill character '{'"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2363 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2364 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2365 |
specs.fill = basic_string_view<Char>(begin, to_unsigned(p - begin)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2366 |
begin = p + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2367 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2368 |
++begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2369 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2370 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2371 |
} else if (p == begin) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2372 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2373 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2374 |
p = begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2375 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2376 |
specs.align = align; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2377 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2378 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2379 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2380 |
// A floating-point presentation format. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2381 |
enum class float_format : unsigned char { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2382 |
general, // General: exponent notation or fixed point based on magnitude. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2383 |
exp, // Exponent notation with the default precision of 6, e.g. 1.2e-3. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2384 |
fixed // Fixed point with the default precision of 6, e.g. 0.0012. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2385 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2386 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2387 |
struct float_specs { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2388 |
int precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2389 |
float_format format : 8; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2390 |
sign_t sign : 8; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2391 |
bool locale : 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2392 |
bool binary32 : 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2393 |
bool showpoint : 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2394 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2395 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2396 |
// DEPRECATED! |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2397 |
FMT_CONSTEXPR inline auto parse_float_type_spec(const format_specs& specs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2398 |
-> float_specs { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2399 |
auto result = float_specs(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2400 |
result.showpoint = specs.alt; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2401 |
result.locale = specs.localized; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2402 |
switch (specs.type) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2403 |
default: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2404 |
FMT_FALLTHROUGH; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2405 |
case presentation_type::none: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2406 |
result.format = float_format::general; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2407 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2408 |
case presentation_type::exp: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2409 |
result.format = float_format::exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2410 |
result.showpoint |= specs.precision != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2411 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2412 |
case presentation_type::fixed: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2413 |
result.format = float_format::fixed; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2414 |
result.showpoint |= specs.precision != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2415 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2416 |
case presentation_type::general: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2417 |
result.format = float_format::general; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2418 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2419 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2420 |
return result; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2421 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2422 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2423 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2424 |
FMT_CONSTEXPR20 auto write_nonfinite(OutputIt out, bool isnan, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2425 |
format_specs specs, sign_t sign) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2426 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2427 |
auto str = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2428 |
isnan ? (specs.upper ? "NAN" : "nan") : (specs.upper ? "INF" : "inf"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2429 |
constexpr size_t str_size = 3; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2430 |
auto size = str_size + (sign ? 1 : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2431 |
// Replace '0'-padding with space for non-finite values. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2432 |
const bool is_zero_fill = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2433 |
specs.fill.size() == 1 && specs.fill.template get<Char>() == '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2434 |
if (is_zero_fill) specs.fill = ' '; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2435 |
return write_padded<Char>(out, specs, size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2436 |
[=](reserve_iterator<OutputIt> it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2437 |
if (sign) *it++ = detail::sign<Char>(sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2438 |
return copy<Char>(str, str + str_size, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2439 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2440 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2441 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2442 |
// A decimal floating-point number significand * pow(10, exp). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2443 |
struct big_decimal_fp { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2444 |
const char* significand; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2445 |
int significand_size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2446 |
int exponent; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2447 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2448 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2449 |
constexpr auto get_significand_size(const big_decimal_fp& f) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2450 |
return f.significand_size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2451 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2452 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2453 |
inline auto get_significand_size(const dragonbox::decimal_fp<T>& f) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2454 |
return count_digits(f.significand); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2455 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2456 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2457 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2458 |
constexpr auto write_significand(OutputIt out, const char* significand, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2459 |
int significand_size) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2460 |
return copy<Char>(significand, significand + significand_size, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2461 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2462 |
template <typename Char, typename OutputIt, typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2463 |
inline auto write_significand(OutputIt out, UInt significand, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2464 |
int significand_size) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2465 |
return format_decimal<Char>(out, significand, significand_size).end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2466 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2467 |
template <typename Char, typename OutputIt, typename T, typename Grouping> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2468 |
FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2469 |
int significand_size, int exponent, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2470 |
const Grouping& grouping) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2471 |
if (!grouping.has_separator()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2472 |
out = write_significand<Char>(out, significand, significand_size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2473 |
return detail::fill_n(out, exponent, static_cast<Char>('0')); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2474 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2475 |
auto buffer = memory_buffer(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2476 |
write_significand<char>(appender(buffer), significand, significand_size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2477 |
detail::fill_n(appender(buffer), exponent, '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2478 |
return grouping.apply(out, string_view(buffer.data(), buffer.size())); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2479 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2480 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2481 |
template <typename Char, typename UInt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2482 |
FMT_ENABLE_IF(std::is_integral<UInt>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2483 |
inline auto write_significand(Char* out, UInt significand, int significand_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2484 |
int integral_size, Char decimal_point) -> Char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2485 |
if (!decimal_point) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2486 |
return format_decimal(out, significand, significand_size).end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2487 |
out += significand_size + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2488 |
Char* end = out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2489 |
int floating_size = significand_size - integral_size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2490 |
for (int i = floating_size / 2; i > 0; --i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2491 |
out -= 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2492 |
copy2(out, digits2(static_cast<std::size_t>(significand % 100))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2493 |
significand /= 100; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2494 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2495 |
if (floating_size % 2 != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2496 |
*--out = static_cast<Char>('0' + significand % 10); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2497 |
significand /= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2498 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2499 |
*--out = decimal_point; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2500 |
format_decimal(out - integral_size, significand, integral_size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2501 |
return end; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2502 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2503 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2504 |
template <typename OutputIt, typename UInt, typename Char, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2505 |
FMT_ENABLE_IF(!std::is_pointer<remove_cvref_t<OutputIt>>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2506 |
inline auto write_significand(OutputIt out, UInt significand, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2507 |
int significand_size, int integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2508 |
Char decimal_point) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2509 |
// Buffer is large enough to hold digits (digits10 + 1) and a decimal point. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2510 |
Char buffer[digits10<UInt>() + 2]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2511 |
auto end = write_significand(buffer, significand, significand_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2512 |
integral_size, decimal_point); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2513 |
return detail::copy_noinline<Char>(buffer, end, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2514 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2515 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2516 |
template <typename OutputIt, typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2517 |
FMT_CONSTEXPR auto write_significand(OutputIt out, const char* significand, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2518 |
int significand_size, int integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2519 |
Char decimal_point) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2520 |
out = detail::copy_noinline<Char>(significand, significand + integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2521 |
out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2522 |
if (!decimal_point) return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2523 |
*out++ = decimal_point; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2524 |
return detail::copy_noinline<Char>(significand + integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2525 |
significand + significand_size, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2526 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2527 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2528 |
template <typename OutputIt, typename Char, typename T, typename Grouping> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2529 |
FMT_CONSTEXPR20 auto write_significand(OutputIt out, T significand, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2530 |
int significand_size, int integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2531 |
Char decimal_point, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2532 |
const Grouping& grouping) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2533 |
if (!grouping.has_separator()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2534 |
return write_significand(out, significand, significand_size, integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2535 |
decimal_point); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2536 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2537 |
auto buffer = basic_memory_buffer<Char>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2538 |
write_significand(basic_appender<Char>(buffer), significand, significand_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2539 |
integral_size, decimal_point); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2540 |
grouping.apply( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2541 |
out, basic_string_view<Char>(buffer.data(), to_unsigned(integral_size))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2542 |
return detail::copy_noinline<Char>(buffer.data() + integral_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2543 |
buffer.end(), out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2544 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2545 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2546 |
template <typename Char, typename OutputIt, typename DecimalFP, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2547 |
typename Grouping = digit_grouping<Char>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2548 |
FMT_CONSTEXPR20 auto do_write_float(OutputIt out, const DecimalFP& f, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2549 |
const format_specs& specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2550 |
float_specs fspecs, locale_ref loc) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2551 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2552 |
auto significand = f.significand; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2553 |
int significand_size = get_significand_size(f); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2554 |
const Char zero = static_cast<Char>('0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2555 |
auto sign = fspecs.sign; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2556 |
size_t size = to_unsigned(significand_size) + (sign ? 1 : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2557 |
using iterator = reserve_iterator<OutputIt>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2558 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2559 |
Char decimal_point = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2560 |
fspecs.locale ? detail::decimal_point<Char>(loc) : static_cast<Char>('.'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2561 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2562 |
int output_exp = f.exponent + significand_size - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2563 |
auto use_exp_format = [=]() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2564 |
if (fspecs.format == float_format::exp) return true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2565 |
if (fspecs.format != float_format::general) return false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2566 |
// Use the fixed notation if the exponent is in [exp_lower, exp_upper), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2567 |
// e.g. 0.0001 instead of 1e-04. Otherwise use the exponent notation. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2568 |
const int exp_lower = -4, exp_upper = 16; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2569 |
return output_exp < exp_lower || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2570 |
output_exp >= (fspecs.precision > 0 ? fspecs.precision : exp_upper); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2571 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2572 |
if (use_exp_format()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2573 |
int num_zeros = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2574 |
if (fspecs.showpoint) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2575 |
num_zeros = fspecs.precision - significand_size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2576 |
if (num_zeros < 0) num_zeros = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2577 |
size += to_unsigned(num_zeros); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2578 |
} else if (significand_size == 1) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2579 |
decimal_point = Char(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2580 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2581 |
auto abs_output_exp = output_exp >= 0 ? output_exp : -output_exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2582 |
int exp_digits = 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2583 |
if (abs_output_exp >= 100) exp_digits = abs_output_exp >= 1000 ? 4 : 3; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2584 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2585 |
size += to_unsigned((decimal_point ? 1 : 0) + 2 + exp_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2586 |
char exp_char = specs.upper ? 'E' : 'e'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2587 |
auto write = [=](iterator it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2588 |
if (sign) *it++ = detail::sign<Char>(sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2589 |
// Insert a decimal point after the first digit and add an exponent. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2590 |
it = write_significand(it, significand, significand_size, 1, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2591 |
decimal_point); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2592 |
if (num_zeros > 0) it = detail::fill_n(it, num_zeros, zero); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2593 |
*it++ = static_cast<Char>(exp_char); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2594 |
return write_exponent<Char>(output_exp, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2595 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2596 |
return specs.width > 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2597 |
? write_padded<Char, align::right>(out, specs, size, write) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2598 |
: base_iterator(out, write(reserve(out, size))); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2599 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2600 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2601 |
int exp = f.exponent + significand_size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2602 |
if (f.exponent >= 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2603 |
// 1234e5 -> 123400000[.0+] |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2604 |
size += to_unsigned(f.exponent); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2605 |
int num_zeros = fspecs.precision - exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2606 |
abort_fuzzing_if(num_zeros > 5000); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2607 |
if (fspecs.showpoint) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2608 |
++size; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2609 |
if (num_zeros <= 0 && fspecs.format != float_format::fixed) num_zeros = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2610 |
if (num_zeros > 0) size += to_unsigned(num_zeros); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2611 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2612 |
auto grouping = Grouping(loc, fspecs.locale); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2613 |
size += to_unsigned(grouping.count_separators(exp)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2614 |
return write_padded<Char, align::right>(out, specs, size, [&](iterator it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2615 |
if (sign) *it++ = detail::sign<Char>(sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2616 |
it = write_significand<Char>(it, significand, significand_size, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2617 |
f.exponent, grouping); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2618 |
if (!fspecs.showpoint) return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2619 |
*it++ = decimal_point; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2620 |
return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2621 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2622 |
} else if (exp > 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2623 |
// 1234e-2 -> 12.34[0+] |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2624 |
int num_zeros = fspecs.showpoint ? fspecs.precision - significand_size : 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2625 |
size += 1 + to_unsigned(num_zeros > 0 ? num_zeros : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2626 |
auto grouping = Grouping(loc, fspecs.locale); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2627 |
size += to_unsigned(grouping.count_separators(exp)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2628 |
return write_padded<Char, align::right>(out, specs, size, [&](iterator it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2629 |
if (sign) *it++ = detail::sign<Char>(sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2630 |
it = write_significand(it, significand, significand_size, exp, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2631 |
decimal_point, grouping); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2632 |
return num_zeros > 0 ? detail::fill_n(it, num_zeros, zero) : it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2633 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2634 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2635 |
// 1234e-6 -> 0.001234 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2636 |
int num_zeros = -exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2637 |
if (significand_size == 0 && fspecs.precision >= 0 && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2638 |
fspecs.precision < num_zeros) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2639 |
num_zeros = fspecs.precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2640 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2641 |
bool pointy = num_zeros != 0 || significand_size != 0 || fspecs.showpoint; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2642 |
size += 1 + (pointy ? 1 : 0) + to_unsigned(num_zeros); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2643 |
return write_padded<Char, align::right>(out, specs, size, [&](iterator it) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2644 |
if (sign) *it++ = detail::sign<Char>(sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2645 |
*it++ = zero; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2646 |
if (!pointy) return it; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2647 |
*it++ = decimal_point; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2648 |
it = detail::fill_n(it, num_zeros, zero); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2649 |
return write_significand<Char>(it, significand, significand_size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2650 |
}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2651 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2652 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2653 |
template <typename Char> class fallback_digit_grouping { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2654 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2655 |
constexpr fallback_digit_grouping(locale_ref, bool) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2656 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2657 |
constexpr auto has_separator() const -> bool { return false; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2658 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2659 |
constexpr auto count_separators(int) const -> int { return 0; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2660 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2661 |
template <typename Out, typename C> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2662 |
constexpr auto apply(Out out, basic_string_view<C>) const -> Out { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2663 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2664 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2665 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2666 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2667 |
template <typename Char, typename OutputIt, typename DecimalFP> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2668 |
FMT_CONSTEXPR20 auto write_float(OutputIt out, const DecimalFP& f, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2669 |
const format_specs& specs, float_specs fspecs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2670 |
locale_ref loc) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2671 |
if (is_constant_evaluated()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2672 |
return do_write_float<Char, OutputIt, DecimalFP, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2673 |
fallback_digit_grouping<Char>>(out, f, specs, fspecs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2674 |
loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2675 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2676 |
return do_write_float<Char>(out, f, specs, fspecs, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2677 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2678 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2679 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2680 |
template <typename T> constexpr auto isnan(T value) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2681 |
return value != value; // std::isnan doesn't support __float128. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2682 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2683 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2684 |
template <typename T, typename Enable = void> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2685 |
struct has_isfinite : std::false_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2686 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2687 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2688 |
struct has_isfinite<T, enable_if_t<sizeof(std::isfinite(T())) != 0>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2689 |
: std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2690 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2691 |
template <typename T, FMT_ENABLE_IF(std::is_floating_point<T>::value&& |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2692 |
has_isfinite<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2693 |
FMT_CONSTEXPR20 auto isfinite(T value) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2694 |
constexpr T inf = T(std::numeric_limits<double>::infinity()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2695 |
if (is_constant_evaluated()) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2696 |
return !detail::isnan(value) && value < inf && value > -inf; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2697 |
return std::isfinite(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2698 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2699 |
template <typename T, FMT_ENABLE_IF(!has_isfinite<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2700 |
FMT_CONSTEXPR auto isfinite(T value) -> bool { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2701 |
T inf = T(std::numeric_limits<double>::infinity()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2702 |
// std::isfinite doesn't support __float128. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2703 |
return !detail::isnan(value) && value < inf && value > -inf; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2704 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2705 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2706 |
template <typename T, FMT_ENABLE_IF(is_floating_point<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2707 |
FMT_INLINE FMT_CONSTEXPR bool signbit(T value) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2708 |
if (is_constant_evaluated()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2709 |
#ifdef __cpp_if_constexpr |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2710 |
if constexpr (std::numeric_limits<double>::is_iec559) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2711 |
auto bits = detail::bit_cast<uint64_t>(static_cast<double>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2712 |
return (bits >> (num_bits<uint64_t>() - 1)) != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2713 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2714 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2715 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2716 |
return std::signbit(static_cast<double>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2717 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2718 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2719 |
inline FMT_CONSTEXPR20 void adjust_precision(int& precision, int exp10) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2720 |
// Adjust fixed precision by exponent because it is relative to decimal |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2721 |
// point. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2722 |
if (exp10 > 0 && precision > max_value<int>() - exp10) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2723 |
FMT_THROW(format_error("number is too big")); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2724 |
precision += exp10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2725 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2726 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2727 |
class bigint { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2728 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2729 |
// A bigint is stored as an array of bigits (big digits), with bigit at index |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2730 |
// 0 being the least significant one. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2731 |
using bigit = uint32_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2732 |
using double_bigit = uint64_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2733 |
enum { bigits_capacity = 32 }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2734 |
basic_memory_buffer<bigit, bigits_capacity> bigits_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2735 |
int exp_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2736 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2737 |
FMT_CONSTEXPR20 auto operator[](int index) const -> bigit { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2738 |
return bigits_[to_unsigned(index)]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2739 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2740 |
FMT_CONSTEXPR20 auto operator[](int index) -> bigit& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2741 |
return bigits_[to_unsigned(index)]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2742 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2743 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2744 |
static constexpr const int bigit_bits = num_bits<bigit>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2745 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2746 |
friend struct formatter<bigint>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2747 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2748 |
FMT_CONSTEXPR20 void subtract_bigits(int index, bigit other, bigit& borrow) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2749 |
auto result = static_cast<double_bigit>((*this)[index]) - other - borrow; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2750 |
(*this)[index] = static_cast<bigit>(result); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2751 |
borrow = static_cast<bigit>(result >> (bigit_bits * 2 - 1)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2752 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2753 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2754 |
FMT_CONSTEXPR20 void remove_leading_zeros() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2755 |
int num_bigits = static_cast<int>(bigits_.size()) - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2756 |
while (num_bigits > 0 && (*this)[num_bigits] == 0) --num_bigits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2757 |
bigits_.resize(to_unsigned(num_bigits + 1)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2758 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2759 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2760 |
// Computes *this -= other assuming aligned bigints and *this >= other. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2761 |
FMT_CONSTEXPR20 void subtract_aligned(const bigint& other) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2762 |
FMT_ASSERT(other.exp_ >= exp_, "unaligned bigints"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2763 |
FMT_ASSERT(compare(*this, other) >= 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2764 |
bigit borrow = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2765 |
int i = other.exp_ - exp_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2766 |
for (size_t j = 0, n = other.bigits_.size(); j != n; ++i, ++j) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2767 |
subtract_bigits(i, other.bigits_[j], borrow); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2768 |
while (borrow > 0) subtract_bigits(i, 0, borrow); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2769 |
remove_leading_zeros(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2770 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2771 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2772 |
FMT_CONSTEXPR20 void multiply(uint32_t value) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2773 |
const double_bigit wide_value = value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2774 |
bigit carry = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2775 |
for (size_t i = 0, n = bigits_.size(); i < n; ++i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2776 |
double_bigit result = bigits_[i] * wide_value + carry; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2777 |
bigits_[i] = static_cast<bigit>(result); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2778 |
carry = static_cast<bigit>(result >> bigit_bits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2779 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2780 |
if (carry != 0) bigits_.push_back(carry); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2781 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2782 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2783 |
template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2784 |
std::is_same<UInt, uint128_t>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2785 |
FMT_CONSTEXPR20 void multiply(UInt value) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2786 |
using half_uint = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2787 |
conditional_t<std::is_same<UInt, uint128_t>::value, uint64_t, uint32_t>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2788 |
const int shift = num_bits<half_uint>() - bigit_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2789 |
const UInt lower = static_cast<half_uint>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2790 |
const UInt upper = value >> num_bits<half_uint>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2791 |
UInt carry = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2792 |
for (size_t i = 0, n = bigits_.size(); i < n; ++i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2793 |
UInt result = lower * bigits_[i] + static_cast<bigit>(carry); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2794 |
carry = (upper * bigits_[i] << shift) + (result >> bigit_bits) + |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2795 |
(carry >> bigit_bits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2796 |
bigits_[i] = static_cast<bigit>(result); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2797 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2798 |
while (carry != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2799 |
bigits_.push_back(static_cast<bigit>(carry)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2800 |
carry >>= bigit_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2801 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2802 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2803 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2804 |
template <typename UInt, FMT_ENABLE_IF(std::is_same<UInt, uint64_t>::value || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2805 |
std::is_same<UInt, uint128_t>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2806 |
FMT_CONSTEXPR20 void assign(UInt n) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2807 |
size_t num_bigits = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2808 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2809 |
bigits_[num_bigits++] = static_cast<bigit>(n); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2810 |
n >>= bigit_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2811 |
} while (n != 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2812 |
bigits_.resize(num_bigits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2813 |
exp_ = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2814 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2815 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2816 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2817 |
FMT_CONSTEXPR20 bigint() : exp_(0) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2818 |
explicit bigint(uint64_t n) { assign(n); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2819 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2820 |
bigint(const bigint&) = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2821 |
void operator=(const bigint&) = delete; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2822 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2823 |
FMT_CONSTEXPR20 void assign(const bigint& other) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2824 |
auto size = other.bigits_.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2825 |
bigits_.resize(size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2826 |
auto data = other.bigits_.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2827 |
copy<bigit>(data, data + size, bigits_.data()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2828 |
exp_ = other.exp_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2829 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2830 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2831 |
template <typename Int> FMT_CONSTEXPR20 void operator=(Int n) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2832 |
FMT_ASSERT(n > 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2833 |
assign(uint64_or_128_t<Int>(n)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2834 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2835 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2836 |
FMT_CONSTEXPR20 auto num_bigits() const -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2837 |
return static_cast<int>(bigits_.size()) + exp_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2838 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2839 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2840 |
FMT_NOINLINE FMT_CONSTEXPR20 auto operator<<=(int shift) -> bigint& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2841 |
FMT_ASSERT(shift >= 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2842 |
exp_ += shift / bigit_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2843 |
shift %= bigit_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2844 |
if (shift == 0) return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2845 |
bigit carry = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2846 |
for (size_t i = 0, n = bigits_.size(); i < n; ++i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2847 |
bigit c = bigits_[i] >> (bigit_bits - shift); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2848 |
bigits_[i] = (bigits_[i] << shift) + carry; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2849 |
carry = c; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2850 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2851 |
if (carry != 0) bigits_.push_back(carry); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2852 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2853 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2854 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2855 |
template <typename Int> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2856 |
FMT_CONSTEXPR20 auto operator*=(Int value) -> bigint& { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2857 |
FMT_ASSERT(value > 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2858 |
multiply(uint32_or_64_or_128_t<Int>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2859 |
return *this; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2860 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2861 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2862 |
friend FMT_CONSTEXPR20 auto compare(const bigint& lhs, const bigint& rhs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2863 |
-> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2864 |
int num_lhs_bigits = lhs.num_bigits(), num_rhs_bigits = rhs.num_bigits(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2865 |
if (num_lhs_bigits != num_rhs_bigits) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2866 |
return num_lhs_bigits > num_rhs_bigits ? 1 : -1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2867 |
int i = static_cast<int>(lhs.bigits_.size()) - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2868 |
int j = static_cast<int>(rhs.bigits_.size()) - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2869 |
int end = i - j; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2870 |
if (end < 0) end = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2871 |
for (; i >= end; --i, --j) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2872 |
bigit lhs_bigit = lhs[i], rhs_bigit = rhs[j]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2873 |
if (lhs_bigit != rhs_bigit) return lhs_bigit > rhs_bigit ? 1 : -1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2874 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2875 |
if (i != j) return i > j ? 1 : -1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2876 |
return 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2877 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2878 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2879 |
// Returns compare(lhs1 + lhs2, rhs). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2880 |
friend FMT_CONSTEXPR20 auto add_compare(const bigint& lhs1, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2881 |
const bigint& lhs2, const bigint& rhs) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2882 |
-> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2883 |
auto minimum = [](int a, int b) { return a < b ? a : b; }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2884 |
auto maximum = [](int a, int b) { return a > b ? a : b; }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2885 |
int max_lhs_bigits = maximum(lhs1.num_bigits(), lhs2.num_bigits()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2886 |
int num_rhs_bigits = rhs.num_bigits(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2887 |
if (max_lhs_bigits + 1 < num_rhs_bigits) return -1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2888 |
if (max_lhs_bigits > num_rhs_bigits) return 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2889 |
auto get_bigit = [](const bigint& n, int i) -> bigit { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2890 |
return i >= n.exp_ && i < n.num_bigits() ? n[i - n.exp_] : 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2891 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2892 |
double_bigit borrow = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2893 |
int min_exp = minimum(minimum(lhs1.exp_, lhs2.exp_), rhs.exp_); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2894 |
for (int i = num_rhs_bigits - 1; i >= min_exp; --i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2895 |
double_bigit sum = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2896 |
static_cast<double_bigit>(get_bigit(lhs1, i)) + get_bigit(lhs2, i); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2897 |
bigit rhs_bigit = get_bigit(rhs, i); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2898 |
if (sum > rhs_bigit + borrow) return 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2899 |
borrow = rhs_bigit + borrow - sum; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2900 |
if (borrow > 1) return -1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2901 |
borrow <<= bigit_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2902 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2903 |
return borrow != 0 ? -1 : 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2904 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2905 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2906 |
// Assigns pow(10, exp) to this bigint. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2907 |
FMT_CONSTEXPR20 void assign_pow10(int exp) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2908 |
FMT_ASSERT(exp >= 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2909 |
if (exp == 0) return *this = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2910 |
// Find the top bit. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2911 |
int bitmask = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2912 |
while (exp >= bitmask) bitmask <<= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2913 |
bitmask >>= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2914 |
// pow(10, exp) = pow(5, exp) * pow(2, exp). First compute pow(5, exp) by |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2915 |
// repeated squaring and multiplication. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2916 |
*this = 5; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2917 |
bitmask >>= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2918 |
while (bitmask != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2919 |
square(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2920 |
if ((exp & bitmask) != 0) *this *= 5; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2921 |
bitmask >>= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2922 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2923 |
*this <<= exp; // Multiply by pow(2, exp) by shifting. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2924 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2925 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2926 |
FMT_CONSTEXPR20 void square() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2927 |
int num_bigits = static_cast<int>(bigits_.size()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2928 |
int num_result_bigits = 2 * num_bigits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2929 |
basic_memory_buffer<bigit, bigits_capacity> n(std::move(bigits_)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2930 |
bigits_.resize(to_unsigned(num_result_bigits)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2931 |
auto sum = uint128_t(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2932 |
for (int bigit_index = 0; bigit_index < num_bigits; ++bigit_index) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2933 |
// Compute bigit at position bigit_index of the result by adding |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2934 |
// cross-product terms n[i] * n[j] such that i + j == bigit_index. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2935 |
for (int i = 0, j = bigit_index; j >= 0; ++i, --j) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2936 |
// Most terms are multiplied twice which can be optimized in the future. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2937 |
sum += static_cast<double_bigit>(n[i]) * n[j]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2938 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2939 |
(*this)[bigit_index] = static_cast<bigit>(sum); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2940 |
sum >>= num_bits<bigit>(); // Compute the carry. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2941 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2942 |
// Do the same for the top half. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2943 |
for (int bigit_index = num_bigits; bigit_index < num_result_bigits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2944 |
++bigit_index) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2945 |
for (int j = num_bigits - 1, i = bigit_index - j; i < num_bigits;) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2946 |
sum += static_cast<double_bigit>(n[i++]) * n[j--]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2947 |
(*this)[bigit_index] = static_cast<bigit>(sum); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2948 |
sum >>= num_bits<bigit>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2949 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2950 |
remove_leading_zeros(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2951 |
exp_ *= 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2952 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2953 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2954 |
// If this bigint has a bigger exponent than other, adds trailing zero to make |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2955 |
// exponents equal. This simplifies some operations such as subtraction. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2956 |
FMT_CONSTEXPR20 void align(const bigint& other) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2957 |
int exp_difference = exp_ - other.exp_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2958 |
if (exp_difference <= 0) return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2959 |
int num_bigits = static_cast<int>(bigits_.size()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2960 |
bigits_.resize(to_unsigned(num_bigits + exp_difference)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2961 |
for (int i = num_bigits - 1, j = i + exp_difference; i >= 0; --i, --j) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2962 |
bigits_[j] = bigits_[i]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2963 |
memset(bigits_.data(), 0, to_unsigned(exp_difference) * sizeof(bigit)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2964 |
exp_ -= exp_difference; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2965 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2966 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2967 |
// Divides this bignum by divisor, assigning the remainder to this and |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2968 |
// returning the quotient. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2969 |
FMT_CONSTEXPR20 auto divmod_assign(const bigint& divisor) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2970 |
FMT_ASSERT(this != &divisor, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2971 |
if (compare(*this, divisor) < 0) return 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2972 |
FMT_ASSERT(divisor.bigits_[divisor.bigits_.size() - 1u] != 0, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2973 |
align(divisor); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2974 |
int quotient = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2975 |
do { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2976 |
subtract_aligned(divisor); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2977 |
++quotient; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2978 |
} while (compare(*this, divisor) >= 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2979 |
return quotient; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2980 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2981 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2982 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2983 |
// format_dragon flags. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2984 |
enum dragon { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2985 |
predecessor_closer = 1, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2986 |
fixup = 2, // Run fixup to correct exp10 which can be off by one. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2987 |
fixed = 4, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2988 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2989 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2990 |
// Formats a floating-point number using a variation of the Fixed-Precision |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2991 |
// Positive Floating-Point Printout ((FPP)^2) algorithm by Steele & White: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2992 |
// https://fmt.dev/papers/p372-steele.pdf. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2993 |
FMT_CONSTEXPR20 inline void format_dragon(basic_fp<uint128_t> value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2994 |
unsigned flags, int num_digits, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2995 |
buffer<char>& buf, int& exp10) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2996 |
bigint numerator; // 2 * R in (FPP)^2. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2997 |
bigint denominator; // 2 * S in (FPP)^2. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2998 |
// lower and upper are differences between value and corresponding boundaries. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
2999 |
bigint lower; // (M^- in (FPP)^2). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3000 |
bigint upper_store; // upper's value if different from lower. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3001 |
bigint* upper = nullptr; // (M^+ in (FPP)^2). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3002 |
// Shift numerator and denominator by an extra bit or two (if lower boundary |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3003 |
// is closer) to make lower and upper integers. This eliminates multiplication |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3004 |
// by 2 during later computations. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3005 |
bool is_predecessor_closer = (flags & dragon::predecessor_closer) != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3006 |
int shift = is_predecessor_closer ? 2 : 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3007 |
if (value.e >= 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3008 |
numerator = value.f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3009 |
numerator <<= value.e + shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3010 |
lower = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3011 |
lower <<= value.e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3012 |
if (is_predecessor_closer) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3013 |
upper_store = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3014 |
upper_store <<= value.e + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3015 |
upper = &upper_store; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3016 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3017 |
denominator.assign_pow10(exp10); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3018 |
denominator <<= shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3019 |
} else if (exp10 < 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3020 |
numerator.assign_pow10(-exp10); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3021 |
lower.assign(numerator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3022 |
if (is_predecessor_closer) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3023 |
upper_store.assign(numerator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3024 |
upper_store <<= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3025 |
upper = &upper_store; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3026 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3027 |
numerator *= value.f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3028 |
numerator <<= shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3029 |
denominator = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3030 |
denominator <<= shift - value.e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3031 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3032 |
numerator = value.f; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3033 |
numerator <<= shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3034 |
denominator.assign_pow10(exp10); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3035 |
denominator <<= shift - value.e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3036 |
lower = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3037 |
if (is_predecessor_closer) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3038 |
upper_store = 1ULL << 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3039 |
upper = &upper_store; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3040 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3041 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3042 |
int even = static_cast<int>((value.f & 1) == 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3043 |
if (!upper) upper = &lower; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3044 |
bool shortest = num_digits < 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3045 |
if ((flags & dragon::fixup) != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3046 |
if (add_compare(numerator, *upper, denominator) + even <= 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3047 |
--exp10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3048 |
numerator *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3049 |
if (num_digits < 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3050 |
lower *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3051 |
if (upper != &lower) *upper *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3052 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3053 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3054 |
if ((flags & dragon::fixed) != 0) adjust_precision(num_digits, exp10 + 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3055 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3056 |
// Invariant: value == (numerator / denominator) * pow(10, exp10). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3057 |
if (shortest) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3058 |
// Generate the shortest representation. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3059 |
num_digits = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3060 |
char* data = buf.data(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3061 |
for (;;) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3062 |
int digit = numerator.divmod_assign(denominator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3063 |
bool low = compare(numerator, lower) - even < 0; // numerator <[=] lower. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3064 |
// numerator + upper >[=] pow10: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3065 |
bool high = add_compare(numerator, *upper, denominator) + even > 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3066 |
data[num_digits++] = static_cast<char>('0' + digit); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3067 |
if (low || high) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3068 |
if (!low) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3069 |
++data[num_digits - 1]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3070 |
} else if (high) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3071 |
int result = add_compare(numerator, numerator, denominator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3072 |
// Round half to even. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3073 |
if (result > 0 || (result == 0 && (digit % 2) != 0)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3074 |
++data[num_digits - 1]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3075 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3076 |
buf.try_resize(to_unsigned(num_digits)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3077 |
exp10 -= num_digits - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3078 |
return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3079 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3080 |
numerator *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3081 |
lower *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3082 |
if (upper != &lower) *upper *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3083 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3084 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3085 |
// Generate the given number of digits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3086 |
exp10 -= num_digits - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3087 |
if (num_digits <= 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3088 |
auto digit = '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3089 |
if (num_digits == 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3090 |
denominator *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3091 |
digit = add_compare(numerator, numerator, denominator) > 0 ? '1' : '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3092 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3093 |
buf.push_back(digit); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3094 |
return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3095 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3096 |
buf.try_resize(to_unsigned(num_digits)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3097 |
for (int i = 0; i < num_digits - 1; ++i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3098 |
int digit = numerator.divmod_assign(denominator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3099 |
buf[i] = static_cast<char>('0' + digit); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3100 |
numerator *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3101 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3102 |
int digit = numerator.divmod_assign(denominator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3103 |
auto result = add_compare(numerator, numerator, denominator); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3104 |
if (result > 0 || (result == 0 && (digit % 2) != 0)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3105 |
if (digit == 9) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3106 |
const auto overflow = '0' + 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3107 |
buf[num_digits - 1] = overflow; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3108 |
// Propagate the carry. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3109 |
for (int i = num_digits - 1; i > 0 && buf[i] == overflow; --i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3110 |
buf[i] = '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3111 |
++buf[i - 1]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3112 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3113 |
if (buf[0] == overflow) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3114 |
buf[0] = '1'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3115 |
if ((flags & dragon::fixed) != 0) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3116 |
buf.push_back('0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3117 |
else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3118 |
++exp10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3119 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3120 |
return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3121 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3122 |
++digit; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3123 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3124 |
buf[num_digits - 1] = static_cast<char>('0' + digit); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3125 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3126 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3127 |
// Formats a floating-point number using the hexfloat format. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3128 |
template <typename Float, FMT_ENABLE_IF(!is_double_double<Float>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3129 |
FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3130 |
buffer<char>& buf) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3131 |
// float is passed as double to reduce the number of instantiations and to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3132 |
// simplify implementation. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3133 |
static_assert(!std::is_same<Float, float>::value, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3134 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3135 |
using info = dragonbox::float_info<Float>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3136 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3137 |
// Assume Float is in the format [sign][exponent][significand]. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3138 |
using carrier_uint = typename info::carrier_uint; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3139 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3140 |
constexpr auto num_float_significand_bits = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3141 |
detail::num_significand_bits<Float>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3142 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3143 |
basic_fp<carrier_uint> f(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3144 |
f.e += num_float_significand_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3145 |
if (!has_implicit_bit<Float>()) --f.e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3146 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3147 |
constexpr auto num_fraction_bits = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3148 |
num_float_significand_bits + (has_implicit_bit<Float>() ? 1 : 0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3149 |
constexpr auto num_xdigits = (num_fraction_bits + 3) / 4; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3150 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3151 |
constexpr auto leading_shift = ((num_xdigits - 1) * 4); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3152 |
const auto leading_mask = carrier_uint(0xF) << leading_shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3153 |
const auto leading_xdigit = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3154 |
static_cast<uint32_t>((f.f & leading_mask) >> leading_shift); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3155 |
if (leading_xdigit > 1) f.e -= (32 - countl_zero(leading_xdigit) - 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3156 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3157 |
int print_xdigits = num_xdigits - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3158 |
if (specs.precision >= 0 && print_xdigits > specs.precision) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3159 |
const int shift = ((print_xdigits - specs.precision - 1) * 4); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3160 |
const auto mask = carrier_uint(0xF) << shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3161 |
const auto v = static_cast<uint32_t>((f.f & mask) >> shift); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3162 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3163 |
if (v >= 8) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3164 |
const auto inc = carrier_uint(1) << (shift + 4); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3165 |
f.f += inc; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3166 |
f.f &= ~(inc - 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3167 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3168 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3169 |
// Check long double overflow |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3170 |
if (!has_implicit_bit<Float>()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3171 |
const auto implicit_bit = carrier_uint(1) << num_float_significand_bits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3172 |
if ((f.f & implicit_bit) == implicit_bit) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3173 |
f.f >>= 4; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3174 |
f.e += 4; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3175 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3176 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3177 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3178 |
print_xdigits = specs.precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3179 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3180 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3181 |
char xdigits[num_bits<carrier_uint>() / 4]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3182 |
detail::fill_n(xdigits, sizeof(xdigits), '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3183 |
format_uint<4>(xdigits, f.f, num_xdigits, specs.upper); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3184 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3185 |
// Remove zero tail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3186 |
while (print_xdigits > 0 && xdigits[print_xdigits] == '0') --print_xdigits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3187 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3188 |
buf.push_back('0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3189 |
buf.push_back(specs.upper ? 'X' : 'x'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3190 |
buf.push_back(xdigits[0]); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3191 |
if (specs.alt || print_xdigits > 0 || print_xdigits < specs.precision) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3192 |
buf.push_back('.'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3193 |
buf.append(xdigits + 1, xdigits + 1 + print_xdigits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3194 |
for (; print_xdigits < specs.precision; ++print_xdigits) buf.push_back('0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3195 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3196 |
buf.push_back(specs.upper ? 'P' : 'p'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3197 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3198 |
uint32_t abs_e; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3199 |
if (f.e < 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3200 |
buf.push_back('-'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3201 |
abs_e = static_cast<uint32_t>(-f.e); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3202 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3203 |
buf.push_back('+'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3204 |
abs_e = static_cast<uint32_t>(f.e); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3205 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3206 |
format_decimal<char>(appender(buf), abs_e, detail::count_digits(abs_e)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3207 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3208 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3209 |
template <typename Float, FMT_ENABLE_IF(is_double_double<Float>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3210 |
FMT_CONSTEXPR20 void format_hexfloat(Float value, format_specs specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3211 |
buffer<char>& buf) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3212 |
format_hexfloat(static_cast<double>(value), specs, buf); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3213 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3214 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3215 |
constexpr auto fractional_part_rounding_thresholds(int index) -> uint32_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3216 |
// For checking rounding thresholds. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3217 |
// The kth entry is chosen to be the smallest integer such that the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3218 |
// upper 32-bits of 10^(k+1) times it is strictly bigger than 5 * 10^k. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3219 |
// It is equal to ceil(2^31 + 2^32/10^(k + 1)). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3220 |
// These are stored in a string literal because we cannot have static arrays |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3221 |
// in constexpr functions and non-static ones are poorly optimized. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3222 |
return U"\x9999999a\x828f5c29\x80418938\x80068db9\x8000a7c6\x800010c7" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3223 |
U"\x800001ae\x8000002b"[index]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3224 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3225 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3226 |
template <typename Float> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3227 |
FMT_CONSTEXPR20 auto format_float(Float value, int precision, float_specs specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3228 |
buffer<char>& buf) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3229 |
// float is passed as double to reduce the number of instantiations. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3230 |
static_assert(!std::is_same<Float, float>::value, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3231 |
FMT_ASSERT(value >= 0, "value is negative"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3232 |
auto converted_value = convert_float(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3233 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3234 |
const bool fixed = specs.format == float_format::fixed; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3235 |
if (value <= 0) { // <= instead of == to silence a warning. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3236 |
if (precision <= 0 || !fixed) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3237 |
buf.push_back('0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3238 |
return 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3239 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3240 |
buf.try_resize(to_unsigned(precision)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3241 |
fill_n(buf.data(), precision, '0'); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3242 |
return -precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3243 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3244 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3245 |
int exp = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3246 |
bool use_dragon = true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3247 |
unsigned dragon_flags = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3248 |
if (!is_fast_float<Float>() || is_constant_evaluated()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3249 |
const auto inv_log2_10 = 0.3010299956639812; // 1 / log2(10) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3250 |
using info = dragonbox::float_info<decltype(converted_value)>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3251 |
const auto f = basic_fp<typename info::carrier_uint>(converted_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3252 |
// Compute exp, an approximate power of 10, such that |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3253 |
// 10^(exp - 1) <= value < 10^exp or 10^exp <= value < 10^(exp + 1). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3254 |
// This is based on log10(value) == log2(value) / log2(10) and approximation |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3255 |
// of log2(value) by e + num_fraction_bits idea from double-conversion. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3256 |
auto e = (f.e + count_digits<1>(f.f) - 1) * inv_log2_10 - 1e-10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3257 |
exp = static_cast<int>(e); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3258 |
if (e > exp) ++exp; // Compute ceil. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3259 |
dragon_flags = dragon::fixup; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3260 |
} else if (precision < 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3261 |
// Use Dragonbox for the shortest format. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3262 |
if (specs.binary32) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3263 |
auto dec = dragonbox::to_decimal(static_cast<float>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3264 |
write<char>(appender(buf), dec.significand); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3265 |
return dec.exponent; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3266 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3267 |
auto dec = dragonbox::to_decimal(static_cast<double>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3268 |
write<char>(appender(buf), dec.significand); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3269 |
return dec.exponent; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3270 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3271 |
// Extract significand bits and exponent bits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3272 |
using info = dragonbox::float_info<double>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3273 |
auto br = bit_cast<uint64_t>(static_cast<double>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3274 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3275 |
const uint64_t significand_mask = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3276 |
(static_cast<uint64_t>(1) << num_significand_bits<double>()) - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3277 |
uint64_t significand = (br & significand_mask); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3278 |
int exponent = static_cast<int>((br & exponent_mask<double>()) >> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3279 |
num_significand_bits<double>()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3280 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3281 |
if (exponent != 0) { // Check if normal. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3282 |
exponent -= exponent_bias<double>() + num_significand_bits<double>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3283 |
significand |= |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3284 |
(static_cast<uint64_t>(1) << num_significand_bits<double>()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3285 |
significand <<= 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3286 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3287 |
// Normalize subnormal inputs. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3288 |
FMT_ASSERT(significand != 0, "zeros should not appear here"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3289 |
int shift = countl_zero(significand); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3290 |
FMT_ASSERT(shift >= num_bits<uint64_t>() - num_significand_bits<double>(), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3291 |
""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3292 |
shift -= (num_bits<uint64_t>() - num_significand_bits<double>() - 2); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3293 |
exponent = (std::numeric_limits<double>::min_exponent - |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3294 |
num_significand_bits<double>()) - |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3295 |
shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3296 |
significand <<= shift; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3297 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3298 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3299 |
// Compute the first several nonzero decimal significand digits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3300 |
// We call the number we get the first segment. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3301 |
const int k = info::kappa - dragonbox::floor_log10_pow2(exponent); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3302 |
exp = -k; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3303 |
const int beta = exponent + dragonbox::floor_log2_pow10(k); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3304 |
uint64_t first_segment; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3305 |
bool has_more_segments; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3306 |
int digits_in_the_first_segment; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3307 |
{ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3308 |
const auto r = dragonbox::umul192_upper128( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3309 |
significand << beta, dragonbox::get_cached_power(k)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3310 |
first_segment = r.high(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3311 |
has_more_segments = r.low() != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3312 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3313 |
// The first segment can have 18 ~ 19 digits. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3314 |
if (first_segment >= 1000000000000000000ULL) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3315 |
digits_in_the_first_segment = 19; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3316 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3317 |
// When it is of 18-digits, we align it to 19-digits by adding a bogus |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3318 |
// zero at the end. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3319 |
digits_in_the_first_segment = 18; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3320 |
first_segment *= 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3321 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3322 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3323 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3324 |
// Compute the actual number of decimal digits to print. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3325 |
if (fixed) adjust_precision(precision, exp + digits_in_the_first_segment); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3326 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3327 |
// Use Dragon4 only when there might be not enough digits in the first |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3328 |
// segment. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3329 |
if (digits_in_the_first_segment > precision) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3330 |
use_dragon = false; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3331 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3332 |
if (precision <= 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3333 |
exp += digits_in_the_first_segment; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3334 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3335 |
if (precision < 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3336 |
// Nothing to do, since all we have are just leading zeros. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3337 |
buf.try_resize(0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3338 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3339 |
// We may need to round-up. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3340 |
buf.try_resize(1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3341 |
if ((first_segment | static_cast<uint64_t>(has_more_segments)) > |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3342 |
5000000000000000000ULL) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3343 |
buf[0] = '1'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3344 |
} else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3345 |
buf[0] = '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3346 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3347 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3348 |
} // precision <= 0 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3349 |
else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3350 |
exp += digits_in_the_first_segment - precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3351 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3352 |
// When precision > 0, we divide the first segment into three |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3353 |
// subsegments, each with 9, 9, and 0 ~ 1 digits so that each fits |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3354 |
// in 32-bits which usually allows faster calculation than in |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3355 |
// 64-bits. Since some compiler (e.g. MSVC) doesn't know how to optimize |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3356 |
// division-by-constant for large 64-bit divisors, we do it here |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3357 |
// manually. The magic number 7922816251426433760 below is equal to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3358 |
// ceil(2^(64+32) / 10^10). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3359 |
const uint32_t first_subsegment = static_cast<uint32_t>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3360 |
dragonbox::umul128_upper64(first_segment, 7922816251426433760ULL) >> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3361 |
32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3362 |
const uint64_t second_third_subsegments = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3363 |
first_segment - first_subsegment * 10000000000ULL; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3364 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3365 |
uint64_t prod; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3366 |
uint32_t digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3367 |
bool should_round_up; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3368 |
int number_of_digits_to_print = precision > 9 ? 9 : precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3369 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3370 |
// Print a 9-digits subsegment, either the first or the second. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3371 |
auto print_subsegment = [&](uint32_t subsegment, char* buffer) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3372 |
int number_of_digits_printed = 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3373 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3374 |
// If we want to print an odd number of digits from the subsegment, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3375 |
if ((number_of_digits_to_print & 1) != 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3376 |
// Convert to 64-bit fixed-point fractional form with 1-digit |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3377 |
// integer part. The magic number 720575941 is a good enough |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3378 |
// approximation of 2^(32 + 24) / 10^8; see |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3379 |
// https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3380 |
// for details. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3381 |
prod = ((subsegment * static_cast<uint64_t>(720575941)) >> 24) + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3382 |
digits = static_cast<uint32_t>(prod >> 32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3383 |
*buffer = static_cast<char>('0' + digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3384 |
number_of_digits_printed++; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3385 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3386 |
// If we want to print an even number of digits from the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3387 |
// first_subsegment, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3388 |
else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3389 |
// Convert to 64-bit fixed-point fractional form with 2-digits |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3390 |
// integer part. The magic number 450359963 is a good enough |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3391 |
// approximation of 2^(32 + 20) / 10^7; see |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3392 |
// https://jk-jeon.github.io/posts/2022/12/fixed-precision-formatting/#fixed-length-case |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3393 |
// for details. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3394 |
prod = ((subsegment * static_cast<uint64_t>(450359963)) >> 20) + 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3395 |
digits = static_cast<uint32_t>(prod >> 32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3396 |
copy2(buffer, digits2(digits)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3397 |
number_of_digits_printed += 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3398 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3399 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3400 |
// Print all digit pairs. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3401 |
while (number_of_digits_printed < number_of_digits_to_print) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3402 |
prod = static_cast<uint32_t>(prod) * static_cast<uint64_t>(100); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3403 |
digits = static_cast<uint32_t>(prod >> 32); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3404 |
copy2(buffer + number_of_digits_printed, digits2(digits)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3405 |
number_of_digits_printed += 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3406 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3407 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3408 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3409 |
// Print first subsegment. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3410 |
print_subsegment(first_subsegment, buf.data()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3411 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3412 |
// Perform rounding if the first subsegment is the last subsegment to |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3413 |
// print. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3414 |
if (precision <= 9) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3415 |
// Rounding inside the subsegment. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3416 |
// We round-up if: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3417 |
// - either the fractional part is strictly larger than 1/2, or |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3418 |
// - the fractional part is exactly 1/2 and the last digit is odd. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3419 |
// We rely on the following observations: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3420 |
// - If fractional_part >= threshold, then the fractional part is |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3421 |
// strictly larger than 1/2. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3422 |
// - If the MSB of fractional_part is set, then the fractional part |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3423 |
// must be at least 1/2. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3424 |
// - When the MSB of fractional_part is set, either |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3425 |
// second_third_subsegments being nonzero or has_more_segments |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3426 |
// being true means there are further digits not printed, so the |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3427 |
// fractional part is strictly larger than 1/2. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3428 |
if (precision < 9) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3429 |
uint32_t fractional_part = static_cast<uint32_t>(prod); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3430 |
should_round_up = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3431 |
fractional_part >= fractional_part_rounding_thresholds( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3432 |
8 - number_of_digits_to_print) || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3433 |
((fractional_part >> 31) & |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3434 |
((digits & 1) | (second_third_subsegments != 0) | |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3435 |
has_more_segments)) != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3436 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3437 |
// Rounding at the subsegment boundary. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3438 |
// In this case, the fractional part is at least 1/2 if and only if |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3439 |
// second_third_subsegments >= 5000000000ULL, and is strictly larger |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3440 |
// than 1/2 if we further have either second_third_subsegments > |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3441 |
// 5000000000ULL or has_more_segments == true. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3442 |
else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3443 |
should_round_up = second_third_subsegments > 5000000000ULL || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3444 |
(second_third_subsegments == 5000000000ULL && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3445 |
((digits & 1) != 0 || has_more_segments)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3446 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3447 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3448 |
// Otherwise, print the second subsegment. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3449 |
else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3450 |
// Compilers are not aware of how to leverage the maximum value of |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3451 |
// second_third_subsegments to find out a better magic number which |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3452 |
// allows us to eliminate an additional shift. 1844674407370955162 = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3453 |
// ceil(2^64/10) < ceil(2^64*(10^9/(10^10 - 1))). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3454 |
const uint32_t second_subsegment = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3455 |
static_cast<uint32_t>(dragonbox::umul128_upper64( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3456 |
second_third_subsegments, 1844674407370955162ULL)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3457 |
const uint32_t third_subsegment = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3458 |
static_cast<uint32_t>(second_third_subsegments) - |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3459 |
second_subsegment * 10; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3460 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3461 |
number_of_digits_to_print = precision - 9; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3462 |
print_subsegment(second_subsegment, buf.data() + 9); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3463 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3464 |
// Rounding inside the subsegment. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3465 |
if (precision < 18) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3466 |
// The condition third_subsegment != 0 implies that the segment was |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3467 |
// of 19 digits, so in this case the third segment should be |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3468 |
// consisting of a genuine digit from the input. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3469 |
uint32_t fractional_part = static_cast<uint32_t>(prod); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3470 |
should_round_up = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3471 |
fractional_part >= fractional_part_rounding_thresholds( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3472 |
8 - number_of_digits_to_print) || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3473 |
((fractional_part >> 31) & |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3474 |
((digits & 1) | (third_subsegment != 0) | |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3475 |
has_more_segments)) != 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3476 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3477 |
// Rounding at the subsegment boundary. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3478 |
else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3479 |
// In this case, the segment must be of 19 digits, thus |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3480 |
// the third subsegment should be consisting of a genuine digit from |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3481 |
// the input. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3482 |
should_round_up = third_subsegment > 5 || |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3483 |
(third_subsegment == 5 && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3484 |
((digits & 1) != 0 || has_more_segments)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3485 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3486 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3487 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3488 |
// Round-up if necessary. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3489 |
if (should_round_up) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3490 |
++buf[precision - 1]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3491 |
for (int i = precision - 1; i > 0 && buf[i] > '9'; --i) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3492 |
buf[i] = '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3493 |
++buf[i - 1]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3494 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3495 |
if (buf[0] > '9') { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3496 |
buf[0] = '1'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3497 |
if (fixed) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3498 |
buf[precision++] = '0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3499 |
else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3500 |
++exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3501 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3502 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3503 |
buf.try_resize(to_unsigned(precision)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3504 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3505 |
} // if (digits_in_the_first_segment > precision) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3506 |
else { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3507 |
// Adjust the exponent for its use in Dragon4. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3508 |
exp += digits_in_the_first_segment - 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3509 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3510 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3511 |
if (use_dragon) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3512 |
auto f = basic_fp<uint128_t>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3513 |
bool is_predecessor_closer = specs.binary32 |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3514 |
? f.assign(static_cast<float>(value)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3515 |
: f.assign(converted_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3516 |
if (is_predecessor_closer) dragon_flags |= dragon::predecessor_closer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3517 |
if (fixed) dragon_flags |= dragon::fixed; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3518 |
// Limit precision to the maximum possible number of significant digits in |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3519 |
// an IEEE754 double because we don't need to generate zeros. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3520 |
const int max_double_digits = 767; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3521 |
if (precision > max_double_digits) precision = max_double_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3522 |
format_dragon(f, dragon_flags, precision, buf, exp); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3523 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3524 |
if (!fixed && !specs.showpoint) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3525 |
// Remove trailing zeros. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3526 |
auto num_digits = buf.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3527 |
while (num_digits > 0 && buf[num_digits - 1] == '0') { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3528 |
--num_digits; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3529 |
++exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3530 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3531 |
buf.try_resize(num_digits); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3532 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3533 |
return exp; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3534 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3535 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3536 |
template <typename Char, typename OutputIt, typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3537 |
FMT_CONSTEXPR20 auto write_float(OutputIt out, T value, format_specs specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3538 |
locale_ref loc) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3539 |
sign_t sign = specs.sign; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3540 |
if (detail::signbit(value)) { // value < 0 is false for NaN so use signbit. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3541 |
sign = sign::minus; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3542 |
value = -value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3543 |
} else if (sign == sign::minus) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3544 |
sign = sign::none; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3545 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3546 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3547 |
if (!detail::isfinite(value)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3548 |
return write_nonfinite<Char>(out, detail::isnan(value), specs, sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3549 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3550 |
if (specs.align == align::numeric && sign) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3551 |
auto it = reserve(out, 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3552 |
*it++ = detail::sign<Char>(sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3553 |
out = base_iterator(out, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3554 |
sign = sign::none; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3555 |
if (specs.width != 0) --specs.width; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3556 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3557 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3558 |
memory_buffer buffer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3559 |
if (specs.type == presentation_type::hexfloat) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3560 |
if (sign) buffer.push_back(detail::sign<char>(sign)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3561 |
format_hexfloat(convert_float(value), specs, buffer); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3562 |
return write_bytes<Char, align::right>(out, {buffer.data(), buffer.size()}, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3563 |
specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3564 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3565 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3566 |
int precision = specs.precision >= 0 || specs.type == presentation_type::none |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3567 |
? specs.precision |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3568 |
: 6; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3569 |
if (specs.type == presentation_type::exp) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3570 |
if (precision == max_value<int>()) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3571 |
report_error("number is too big"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3572 |
else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3573 |
++precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3574 |
} else if (specs.type != presentation_type::fixed && precision == 0) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3575 |
precision = 1; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3576 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3577 |
float_specs fspecs = parse_float_type_spec(specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3578 |
fspecs.sign = sign; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3579 |
if (const_check(std::is_same<T, float>())) fspecs.binary32 = true; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3580 |
int exp = format_float(convert_float(value), precision, fspecs, buffer); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3581 |
fspecs.precision = precision; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3582 |
auto f = big_decimal_fp{buffer.data(), static_cast<int>(buffer.size()), exp}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3583 |
return write_float<Char>(out, f, specs, fspecs, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3584 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3585 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3586 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3587 |
FMT_ENABLE_IF(is_floating_point<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3588 |
FMT_CONSTEXPR20 auto write(OutputIt out, T value, format_specs specs, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3589 |
locale_ref loc = {}) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3590 |
if (const_check(!is_supported_floating_point(value))) return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3591 |
return specs.localized && write_loc(out, value, specs, loc) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3592 |
? out |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3593 |
: write_float<Char>(out, value, specs, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3594 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3595 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3596 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3597 |
FMT_ENABLE_IF(is_fast_float<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3598 |
FMT_CONSTEXPR20 auto write(OutputIt out, T value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3599 |
if (is_constant_evaluated()) return write<Char>(out, value, format_specs()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3600 |
if (const_check(!is_supported_floating_point(value))) return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3601 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3602 |
auto sign = sign_t::none; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3603 |
if (detail::signbit(value)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3604 |
sign = sign::minus; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3605 |
value = -value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3606 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3607 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3608 |
constexpr auto specs = format_specs(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3609 |
using floaty = conditional_t<std::is_same<T, long double>::value, double, T>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3610 |
using floaty_uint = typename dragonbox::float_info<floaty>::carrier_uint; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3611 |
floaty_uint mask = exponent_mask<floaty>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3612 |
if ((bit_cast<floaty_uint>(value) & mask) == mask) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3613 |
return write_nonfinite<Char>(out, std::isnan(value), specs, sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3614 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3615 |
auto fspecs = float_specs(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3616 |
fspecs.sign = sign; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3617 |
auto dec = dragonbox::to_decimal(static_cast<floaty>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3618 |
return write_float<Char>(out, dec, specs, fspecs, {}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3619 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3620 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3621 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3622 |
FMT_ENABLE_IF(is_floating_point<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3623 |
!is_fast_float<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3624 |
inline auto write(OutputIt out, T value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3625 |
return write<Char>(out, value, format_specs()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3626 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3627 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3628 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3629 |
auto write(OutputIt out, monostate, format_specs = {}, locale_ref = {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3630 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3631 |
FMT_ASSERT(false, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3632 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3633 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3634 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3635 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3636 |
FMT_CONSTEXPR auto write(OutputIt out, basic_string_view<Char> value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3637 |
-> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3638 |
return copy_noinline<Char>(value.begin(), value.end(), out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3639 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3640 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3641 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3642 |
FMT_ENABLE_IF(has_to_string_view<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3643 |
constexpr auto write(OutputIt out, const T& value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3644 |
return write<Char>(out, to_string_view(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3645 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3646 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3647 |
// FMT_ENABLE_IF() condition separated to workaround an MSVC bug. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3648 |
template < |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3649 |
typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3650 |
bool check = |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3651 |
std::is_enum<T>::value && !std::is_same<T, Char>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3652 |
mapped_type_constant<T, basic_format_context<OutputIt, Char>>::value != |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3653 |
type::custom_type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3654 |
FMT_ENABLE_IF(check)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3655 |
FMT_CONSTEXPR auto write(OutputIt out, T value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3656 |
return write<Char>(out, static_cast<underlying_t<T>>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3657 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3658 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3659 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3660 |
FMT_ENABLE_IF(std::is_same<T, bool>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3661 |
FMT_CONSTEXPR auto write(OutputIt out, T value, const format_specs& specs = {}, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3662 |
locale_ref = {}) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3663 |
return specs.type != presentation_type::none && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3664 |
specs.type != presentation_type::string |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3665 |
? write<Char>(out, value ? 1 : 0, specs, {}) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3666 |
: write_bytes<Char>(out, value ? "true" : "false", specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3667 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3668 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3669 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3670 |
FMT_CONSTEXPR auto write(OutputIt out, Char value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3671 |
auto it = reserve(out, 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3672 |
*it++ = value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3673 |
return base_iterator(out, it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3674 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3675 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3676 |
template <typename Char, typename OutputIt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3677 |
FMT_CONSTEXPR20 auto write(OutputIt out, const Char* value) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3678 |
if (value) return write(out, basic_string_view<Char>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3679 |
report_error("string pointer is null"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3680 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3681 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3682 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3683 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3684 |
FMT_ENABLE_IF(std::is_same<T, void>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3685 |
auto write(OutputIt out, const T* value, const format_specs& specs = {}, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3686 |
locale_ref = {}) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3687 |
return write_ptr<Char>(out, bit_cast<uintptr_t>(value), &specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3688 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3689 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3690 |
// A write overload that handles implicit conversions. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3691 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3692 |
typename Context = basic_format_context<OutputIt, Char>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3693 |
FMT_CONSTEXPR auto write(OutputIt out, const T& value) -> enable_if_t< |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3694 |
std::is_class<T>::value && !has_to_string_view<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3695 |
!is_floating_point<T>::value && !std::is_same<T, Char>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3696 |
!std::is_same<T, remove_cvref_t<decltype(arg_mapper<Context>().map( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3697 |
value))>>::value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3698 |
OutputIt> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3699 |
return write<Char>(out, arg_mapper<Context>().map(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3700 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3701 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3702 |
template <typename Char, typename OutputIt, typename T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3703 |
typename Context = basic_format_context<OutputIt, Char>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3704 |
FMT_CONSTEXPR auto write(OutputIt out, const T& value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3705 |
-> enable_if_t<mapped_type_constant<T, Context>::value == |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3706 |
type::custom_type && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3707 |
!std::is_fundamental<T>::value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3708 |
OutputIt> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3709 |
auto formatter = typename Context::template formatter_type<T>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3710 |
auto parse_ctx = typename Context::parse_context_type({}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3711 |
formatter.parse(parse_ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3712 |
auto ctx = Context(out, {}, {}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3713 |
return formatter.format(value, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3714 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3715 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3716 |
// An argument visitor that formats the argument and writes it via the output |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3717 |
// iterator. It's a class and not a generic lambda for compatibility with C++11. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3718 |
template <typename Char> struct default_arg_formatter { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3719 |
using iterator = basic_appender<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3720 |
using context = buffered_context<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3721 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3722 |
iterator out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3723 |
basic_format_args<context> args; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3724 |
locale_ref loc; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3725 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3726 |
template <typename T> auto operator()(T value) -> iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3727 |
return write<Char>(out, value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3728 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3729 |
auto operator()(typename basic_format_arg<context>::handle h) -> iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3730 |
basic_format_parse_context<Char> parse_ctx({}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3731 |
context format_ctx(out, args, loc); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3732 |
h.format(parse_ctx, format_ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3733 |
return format_ctx.out(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3734 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3735 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3736 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3737 |
template <typename Char> struct arg_formatter { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3738 |
using iterator = basic_appender<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3739 |
using context = buffered_context<Char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3740 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3741 |
iterator out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3742 |
const format_specs& specs; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3743 |
locale_ref locale; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3744 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3745 |
template <typename T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3746 |
FMT_CONSTEXPR FMT_INLINE auto operator()(T value) -> iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3747 |
return detail::write<Char>(out, value, specs, locale); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3748 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3749 |
auto operator()(typename basic_format_arg<context>::handle) -> iterator { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3750 |
// User-defined types are handled separately because they require access |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3751 |
// to the parse context. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3752 |
return out; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3753 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3754 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3755 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3756 |
struct width_checker { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3757 |
template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3758 |
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3759 |
if (is_negative(value)) report_error("negative width"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3760 |
return static_cast<unsigned long long>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3761 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3762 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3763 |
template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3764 |
FMT_CONSTEXPR auto operator()(T) -> unsigned long long { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3765 |
report_error("width is not integer"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3766 |
return 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3767 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3768 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3769 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3770 |
struct precision_checker { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3771 |
template <typename T, FMT_ENABLE_IF(is_integer<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3772 |
FMT_CONSTEXPR auto operator()(T value) -> unsigned long long { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3773 |
if (is_negative(value)) report_error("negative precision"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3774 |
return static_cast<unsigned long long>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3775 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3776 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3777 |
template <typename T, FMT_ENABLE_IF(!is_integer<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3778 |
FMT_CONSTEXPR auto operator()(T) -> unsigned long long { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3779 |
report_error("precision is not integer"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3780 |
return 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3781 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3782 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3783 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3784 |
template <typename Handler, typename FormatArg> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3785 |
FMT_CONSTEXPR auto get_dynamic_spec(FormatArg arg) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3786 |
unsigned long long value = arg.visit(Handler()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3787 |
if (value > to_unsigned(max_value<int>())) report_error("number is too big"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3788 |
return static_cast<int>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3789 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3790 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3791 |
template <typename Context, typename ID> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3792 |
FMT_CONSTEXPR auto get_arg(Context& ctx, ID id) -> decltype(ctx.arg(id)) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3793 |
auto arg = ctx.arg(id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3794 |
if (!arg) report_error("argument not found"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3795 |
return arg; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3796 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3797 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3798 |
template <typename Handler, typename Context> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3799 |
FMT_CONSTEXPR void handle_dynamic_spec(int& value, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3800 |
arg_ref<typename Context::char_type> ref, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3801 |
Context& ctx) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3802 |
switch (ref.kind) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3803 |
case arg_id_kind::none: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3804 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3805 |
case arg_id_kind::index: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3806 |
value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.index)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3807 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3808 |
case arg_id_kind::name: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3809 |
value = detail::get_dynamic_spec<Handler>(get_arg(ctx, ref.val.name)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3810 |
break; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3811 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3812 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3813 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3814 |
#if FMT_USE_USER_DEFINED_LITERALS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3815 |
# if FMT_USE_NONTYPE_TEMPLATE_ARGS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3816 |
template <typename T, typename Char, size_t N, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3817 |
fmt::detail_exported::fixed_string<Char, N> Str> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3818 |
struct statically_named_arg : view { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3819 |
static constexpr auto name = Str.data; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3820 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3821 |
const T& value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3822 |
statically_named_arg(const T& v) : value(v) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3823 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3824 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3825 |
template <typename T, typename Char, size_t N, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3826 |
fmt::detail_exported::fixed_string<Char, N> Str> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3827 |
struct is_named_arg<statically_named_arg<T, Char, N, Str>> : std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3828 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3829 |
template <typename T, typename Char, size_t N, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3830 |
fmt::detail_exported::fixed_string<Char, N> Str> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3831 |
struct is_statically_named_arg<statically_named_arg<T, Char, N, Str>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3832 |
: std::true_type {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3833 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3834 |
template <typename Char, size_t N, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3835 |
fmt::detail_exported::fixed_string<Char, N> Str> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3836 |
struct udl_arg { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3837 |
template <typename T> auto operator=(T&& value) const { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3838 |
return statically_named_arg<T, Char, N, Str>(std::forward<T>(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3839 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3840 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3841 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3842 |
template <typename Char> struct udl_arg { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3843 |
const Char* str; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3844 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3845 |
template <typename T> auto operator=(T&& value) const -> named_arg<Char, T> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3846 |
return {str, std::forward<T>(value)}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3847 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3848 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3849 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3850 |
#endif // FMT_USE_USER_DEFINED_LITERALS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3851 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3852 |
template <typename Locale, typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3853 |
auto vformat(const Locale& loc, basic_string_view<Char> fmt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3854 |
typename detail::vformat_args<Char>::type args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3855 |
-> std::basic_string<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3856 |
auto buf = basic_memory_buffer<Char>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3857 |
detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3858 |
return {buf.data(), buf.size()}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3859 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3860 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3861 |
using format_func = void (*)(detail::buffer<char>&, int, const char*); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3862 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3863 |
FMT_API void format_error_code(buffer<char>& out, int error_code, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3864 |
string_view message) noexcept; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3865 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3866 |
using fmt::report_error; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3867 |
FMT_API void report_error(format_func func, int error_code, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3868 |
const char* message) noexcept; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3869 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3870 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3871 |
FMT_BEGIN_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3872 |
FMT_API auto vsystem_error(int error_code, string_view format_str, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3873 |
format_args args) -> std::system_error; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3874 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3875 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3876 |
* Constructs `std::system_error` with a message formatted with |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3877 |
* `fmt::format(fmt, args...)`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3878 |
* `error_code` is a system error code as given by `errno`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3879 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3880 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3881 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3882 |
* // This throws std::system_error with the description |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3883 |
* // cannot open file 'madeup': No such file or directory |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3884 |
* // or similar (system message may vary). |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3885 |
* const char* filename = "madeup"; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3886 |
* std::FILE* file = std::fopen(filename, "r"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3887 |
* if (!file) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3888 |
* throw fmt::system_error(errno, "cannot open file '{}'", filename); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3889 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3890 |
template <typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3891 |
auto system_error(int error_code, format_string<T...> fmt, T&&... args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3892 |
-> std::system_error { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3893 |
return vsystem_error(error_code, fmt, fmt::make_format_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3894 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3895 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3896 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3897 |
* Formats an error message for an error returned by an operating system or a |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3898 |
* language runtime, for example a file opening error, and writes it to `out`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3899 |
* The format is the same as the one used by `std::system_error(ec, message)` |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3900 |
* where `ec` is `std::error_code(error_code, std::generic_category())`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3901 |
* It is implementation-defined but normally looks like: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3902 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3903 |
* <message>: <system-message> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3904 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3905 |
* where `<message>` is the passed message and `<system-message>` is the system |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3906 |
* message corresponding to the error code. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3907 |
* `error_code` is a system error code as given by `errno`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3908 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3909 |
FMT_API void format_system_error(detail::buffer<char>& out, int error_code, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3910 |
const char* message) noexcept; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3911 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3912 |
// Reports a system error without throwing an exception. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3913 |
// Can be used to report errors from destructors. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3914 |
FMT_API void report_system_error(int error_code, const char* message) noexcept; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3915 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3916 |
/// A fast integer formatter. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3917 |
class format_int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3918 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3919 |
// Buffer should be large enough to hold all digits (digits10 + 1), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3920 |
// a sign and a null character. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3921 |
enum { buffer_size = std::numeric_limits<unsigned long long>::digits10 + 3 }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3922 |
mutable char buffer_[buffer_size]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3923 |
char* str_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3924 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3925 |
template <typename UInt> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3926 |
FMT_CONSTEXPR20 auto format_unsigned(UInt value) -> char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3927 |
auto n = static_cast<detail::uint32_or_64_or_128_t<UInt>>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3928 |
return detail::format_decimal(buffer_, n, buffer_size - 1).begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3929 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3930 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3931 |
template <typename Int> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3932 |
FMT_CONSTEXPR20 auto format_signed(Int value) -> char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3933 |
auto abs_value = static_cast<detail::uint32_or_64_or_128_t<Int>>(value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3934 |
bool negative = value < 0; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3935 |
if (negative) abs_value = 0 - abs_value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3936 |
auto begin = format_unsigned(abs_value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3937 |
if (negative) *--begin = '-'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3938 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3939 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3940 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3941 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3942 |
explicit FMT_CONSTEXPR20 format_int(int value) : str_(format_signed(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3943 |
explicit FMT_CONSTEXPR20 format_int(long value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3944 |
: str_(format_signed(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3945 |
explicit FMT_CONSTEXPR20 format_int(long long value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3946 |
: str_(format_signed(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3947 |
explicit FMT_CONSTEXPR20 format_int(unsigned value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3948 |
: str_(format_unsigned(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3949 |
explicit FMT_CONSTEXPR20 format_int(unsigned long value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3950 |
: str_(format_unsigned(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3951 |
explicit FMT_CONSTEXPR20 format_int(unsigned long long value) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3952 |
: str_(format_unsigned(value)) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3953 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3954 |
/// Returns the number of characters written to the output buffer. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3955 |
FMT_CONSTEXPR20 auto size() const -> size_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3956 |
return detail::to_unsigned(buffer_ - str_ + buffer_size - 1); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3957 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3958 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3959 |
/// Returns a pointer to the output buffer content. No terminating null |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3960 |
/// character is appended. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3961 |
FMT_CONSTEXPR20 auto data() const -> const char* { return str_; } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3962 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3963 |
/// Returns a pointer to the output buffer content with terminating null |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3964 |
/// character appended. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3965 |
FMT_CONSTEXPR20 auto c_str() const -> const char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3966 |
buffer_[buffer_size - 1] = '\0'; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3967 |
return str_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3968 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3969 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3970 |
/// Returns the content of the output buffer as an `std::string`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3971 |
auto str() const -> std::string { return std::string(str_, size()); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3972 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3973 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3974 |
template <typename T, typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3975 |
struct formatter<T, Char, enable_if_t<detail::has_format_as<T>::value>> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3976 |
: formatter<detail::format_as_t<T>, Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3977 |
template <typename FormatContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3978 |
auto format(const T& value, FormatContext& ctx) const -> decltype(ctx.out()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3979 |
auto&& val = format_as(value); // Make an lvalue reference for format. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3980 |
return formatter<detail::format_as_t<T>, Char>::format(val, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3981 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3982 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3983 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3984 |
#define FMT_FORMAT_AS(Type, Base) \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3985 |
template <typename Char> \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3986 |
struct formatter<Type, Char> : formatter<Base, Char> { \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3987 |
template <typename FormatContext> \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3988 |
auto format(Type value, FormatContext& ctx) const -> decltype(ctx.out()) { \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3989 |
return formatter<Base, Char>::format(value, ctx); \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3990 |
} \ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3991 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3992 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3993 |
FMT_FORMAT_AS(signed char, int); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3994 |
FMT_FORMAT_AS(unsigned char, unsigned); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3995 |
FMT_FORMAT_AS(short, int); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3996 |
FMT_FORMAT_AS(unsigned short, unsigned); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3997 |
FMT_FORMAT_AS(long, detail::long_type); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3998 |
FMT_FORMAT_AS(unsigned long, detail::ulong_type); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
3999 |
FMT_FORMAT_AS(Char*, const Char*); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4000 |
FMT_FORMAT_AS(std::nullptr_t, const void*); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4001 |
FMT_FORMAT_AS(detail::std_string_view<Char>, basic_string_view<Char>); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4002 |
FMT_FORMAT_AS(void*, const void*); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4003 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4004 |
template <typename Char, typename Traits, typename Allocator> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4005 |
class formatter<std::basic_string<Char, Traits, Allocator>, Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4006 |
: public formatter<basic_string_view<Char>, Char> {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4007 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4008 |
template <typename Char, size_t N> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4009 |
struct formatter<Char[N], Char> : formatter<basic_string_view<Char>, Char> {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4010 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4011 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4012 |
* Converts `p` to `const void*` for pointer formatting. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4013 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4014 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4015 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4016 |
* auto s = fmt::format("{}", fmt::ptr(p)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4017 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4018 |
template <typename T> auto ptr(T p) -> const void* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4019 |
static_assert(std::is_pointer<T>::value, ""); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4020 |
return detail::bit_cast<const void*>(p); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4021 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4022 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4023 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4024 |
* Converts `e` to the underlying type. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4025 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4026 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4027 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4028 |
* enum class color { red, green, blue }; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4029 |
* auto s = fmt::format("{}", fmt::underlying(color::red)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4030 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4031 |
template <typename Enum> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4032 |
constexpr auto underlying(Enum e) noexcept -> underlying_t<Enum> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4033 |
return static_cast<underlying_t<Enum>>(e); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4034 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4035 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4036 |
namespace enums { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4037 |
template <typename Enum, FMT_ENABLE_IF(std::is_enum<Enum>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4038 |
constexpr auto format_as(Enum e) noexcept -> underlying_t<Enum> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4039 |
return static_cast<underlying_t<Enum>>(e); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4040 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4041 |
} // namespace enums |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4042 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4043 |
class bytes { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4044 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4045 |
string_view data_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4046 |
friend struct formatter<bytes>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4047 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4048 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4049 |
explicit bytes(string_view data) : data_(data) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4050 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4051 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4052 |
template <> struct formatter<bytes> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4053 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4054 |
detail::dynamic_format_specs<> specs_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4055 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4056 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4057 |
template <typename ParseContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4058 |
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4059 |
return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4060 |
detail::type::string_type); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4061 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4062 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4063 |
template <typename FormatContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4064 |
auto format(bytes b, FormatContext& ctx) const -> decltype(ctx.out()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4065 |
auto specs = specs_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4066 |
detail::handle_dynamic_spec<detail::width_checker>(specs.width, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4067 |
specs.width_ref, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4068 |
detail::handle_dynamic_spec<detail::precision_checker>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4069 |
specs.precision, specs.precision_ref, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4070 |
return detail::write_bytes<char>(ctx.out(), b.data_, specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4071 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4072 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4073 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4074 |
// group_digits_view is not derived from view because it copies the argument. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4075 |
template <typename T> struct group_digits_view { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4076 |
T value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4077 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4078 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4079 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4080 |
* Returns a view that formats an integer value using ',' as a |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4081 |
* locale-independent thousands separator. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4082 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4083 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4084 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4085 |
* fmt::print("{}", fmt::group_digits(12345)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4086 |
* // Output: "12,345" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4087 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4088 |
template <typename T> auto group_digits(T value) -> group_digits_view<T> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4089 |
return {value}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4090 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4091 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4092 |
template <typename T> struct formatter<group_digits_view<T>> : formatter<T> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4093 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4094 |
detail::dynamic_format_specs<> specs_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4095 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4096 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4097 |
template <typename ParseContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4098 |
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> const char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4099 |
return parse_format_specs(ctx.begin(), ctx.end(), specs_, ctx, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4100 |
detail::type::int_type); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4101 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4102 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4103 |
template <typename FormatContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4104 |
auto format(group_digits_view<T> t, FormatContext& ctx) const |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4105 |
-> decltype(ctx.out()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4106 |
auto specs = specs_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4107 |
detail::handle_dynamic_spec<detail::width_checker>(specs.width, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4108 |
specs.width_ref, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4109 |
detail::handle_dynamic_spec<detail::precision_checker>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4110 |
specs.precision, specs.precision_ref, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4111 |
auto arg = detail::make_write_int_arg(t.value, specs.sign); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4112 |
return detail::write_int( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4113 |
ctx.out(), static_cast<detail::uint64_or_128_t<T>>(arg.abs_value), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4114 |
arg.prefix, specs, detail::digit_grouping<char>("\3", ",")); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4115 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4116 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4117 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4118 |
template <typename T, typename Char> struct nested_view { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4119 |
const formatter<T, Char>* fmt; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4120 |
const T* value; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4121 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4122 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4123 |
template <typename T, typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4124 |
struct formatter<nested_view<T, Char>, Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4125 |
template <typename ParseContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4126 |
FMT_CONSTEXPR auto parse(ParseContext& ctx) -> decltype(ctx.begin()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4127 |
return ctx.begin(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4128 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4129 |
template <typename FormatContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4130 |
auto format(nested_view<T, Char> view, FormatContext& ctx) const |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4131 |
-> decltype(ctx.out()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4132 |
return view.fmt->format(*view.value, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4133 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4134 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4135 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4136 |
template <typename T, typename Char = char> struct nested_formatter { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4137 |
private: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4138 |
int width_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4139 |
detail::fill_t fill_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4140 |
align_t align_ : 4; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4141 |
formatter<T, Char> formatter_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4142 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4143 |
public: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4144 |
constexpr nested_formatter() : width_(0), align_(align_t::none) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4145 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4146 |
FMT_CONSTEXPR auto parse(basic_format_parse_context<Char>& ctx) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4147 |
-> decltype(ctx.begin()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4148 |
auto specs = detail::dynamic_format_specs<Char>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4149 |
auto it = parse_format_specs(ctx.begin(), ctx.end(), specs, ctx, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4150 |
detail::type::none_type); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4151 |
width_ = specs.width; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4152 |
fill_ = specs.fill; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4153 |
align_ = specs.align; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4154 |
ctx.advance_to(it); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4155 |
return formatter_.parse(ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4156 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4157 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4158 |
template <typename FormatContext, typename F> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4159 |
auto write_padded(FormatContext& ctx, F write) const -> decltype(ctx.out()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4160 |
if (width_ == 0) return write(ctx.out()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4161 |
auto buf = basic_memory_buffer<Char>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4162 |
write(basic_appender<Char>(buf)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4163 |
auto specs = format_specs(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4164 |
specs.width = width_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4165 |
specs.fill = fill_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4166 |
specs.align = align_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4167 |
return detail::write<Char>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4168 |
ctx.out(), basic_string_view<Char>(buf.data(), buf.size()), specs); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4169 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4170 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4171 |
auto nested(const T& value) const -> nested_view<T, Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4172 |
return nested_view<T, Char>{&formatter_, &value}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4173 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4174 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4175 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4176 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4177 |
* Converts `value` to `std::string` using the default format for type `T`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4178 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4179 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4180 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4181 |
* std::string answer = fmt::to_string(42); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4182 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4183 |
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4184 |
!detail::has_format_as<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4185 |
inline auto to_string(const T& value) -> std::string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4186 |
auto buffer = memory_buffer(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4187 |
detail::write<char>(appender(buffer), value); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4188 |
return {buffer.data(), buffer.size()}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4189 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4190 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4191 |
template <typename T, FMT_ENABLE_IF(std::is_integral<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4192 |
FMT_NODISCARD inline auto to_string(T value) -> std::string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4193 |
// The buffer should be large enough to store the number including the sign |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4194 |
// or "false" for bool. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4195 |
constexpr int max_size = detail::digits10<T>() + 2; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4196 |
char buffer[max_size > 5 ? static_cast<unsigned>(max_size) : 5]; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4197 |
char* begin = buffer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4198 |
return std::string(begin, detail::write<char>(begin, value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4199 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4200 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4201 |
template <typename Char, size_t SIZE> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4202 |
FMT_NODISCARD auto to_string(const basic_memory_buffer<Char, SIZE>& buf) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4203 |
-> std::basic_string<Char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4204 |
auto size = buf.size(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4205 |
detail::assume(size < std::basic_string<Char>().max_size()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4206 |
return std::basic_string<Char>(buf.data(), size); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4207 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4208 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4209 |
template <typename T, FMT_ENABLE_IF(!std::is_integral<T>::value && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4210 |
detail::has_format_as<T>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4211 |
inline auto to_string(const T& value) -> std::string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4212 |
return to_string(format_as(value)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4213 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4214 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4215 |
FMT_END_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4216 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4217 |
namespace detail { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4218 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4219 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4220 |
void vformat_to(buffer<Char>& buf, basic_string_view<Char> fmt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4221 |
typename vformat_args<Char>::type args, locale_ref loc) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4222 |
auto out = basic_appender<Char>(buf); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4223 |
if (fmt.size() == 2 && equal2(fmt.data(), "{}")) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4224 |
auto arg = args.get(0); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4225 |
if (!arg) report_error("argument not found"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4226 |
arg.visit(default_arg_formatter<Char>{out, args, loc}); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4227 |
return; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4228 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4229 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4230 |
struct format_handler { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4231 |
basic_format_parse_context<Char> parse_context; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4232 |
buffered_context<Char> context; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4233 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4234 |
format_handler(basic_appender<Char> p_out, basic_string_view<Char> str, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4235 |
basic_format_args<buffered_context<Char>> p_args, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4236 |
locale_ref p_loc) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4237 |
: parse_context(str), context(p_out, p_args, p_loc) {} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4238 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4239 |
void on_text(const Char* begin, const Char* end) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4240 |
auto text = basic_string_view<Char>(begin, to_unsigned(end - begin)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4241 |
context.advance_to(write<Char>(context.out(), text)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4242 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4243 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4244 |
FMT_CONSTEXPR auto on_arg_id() -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4245 |
return parse_context.next_arg_id(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4246 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4247 |
FMT_CONSTEXPR auto on_arg_id(int id) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4248 |
parse_context.check_arg_id(id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4249 |
return id; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4250 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4251 |
FMT_CONSTEXPR auto on_arg_id(basic_string_view<Char> id) -> int { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4252 |
parse_context.check_arg_id(id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4253 |
int arg_id = context.arg_id(id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4254 |
if (arg_id < 0) report_error("argument not found"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4255 |
return arg_id; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4256 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4257 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4258 |
FMT_INLINE void on_replacement_field(int id, const Char*) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4259 |
auto arg = get_arg(context, id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4260 |
context.advance_to(arg.visit(default_arg_formatter<Char>{ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4261 |
context.out(), context.args(), context.locale()})); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4262 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4263 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4264 |
auto on_format_specs(int id, const Char* begin, const Char* end) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4265 |
-> const Char* { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4266 |
auto arg = get_arg(context, id); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4267 |
// Not using a visitor for custom types gives better codegen. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4268 |
if (arg.format_custom(begin, parse_context, context)) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4269 |
return parse_context.begin(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4270 |
auto specs = detail::dynamic_format_specs<Char>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4271 |
begin = parse_format_specs(begin, end, specs, parse_context, arg.type()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4272 |
detail::handle_dynamic_spec<detail::width_checker>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4273 |
specs.width, specs.width_ref, context); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4274 |
detail::handle_dynamic_spec<detail::precision_checker>( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4275 |
specs.precision, specs.precision_ref, context); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4276 |
if (begin == end || *begin != '}') |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4277 |
report_error("missing '}' in format string"); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4278 |
context.advance_to(arg.visit( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4279 |
arg_formatter<Char>{context.out(), specs, context.locale()})); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4280 |
return begin; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4281 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4282 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4283 |
FMT_NORETURN void on_error(const char* message) { report_error(message); } |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4284 |
}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4285 |
detail::parse_format_string<false>(fmt, format_handler(out, fmt, args, loc)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4286 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4287 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4288 |
FMT_BEGIN_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4289 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4290 |
#ifndef FMT_HEADER_ONLY |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4291 |
extern template FMT_API void vformat_to(buffer<char>&, string_view, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4292 |
typename vformat_args<>::type, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4293 |
locale_ref); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4294 |
extern template FMT_API auto thousands_sep_impl<char>(locale_ref) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4295 |
-> thousands_sep_result<char>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4296 |
extern template FMT_API auto thousands_sep_impl<wchar_t>(locale_ref) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4297 |
-> thousands_sep_result<wchar_t>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4298 |
extern template FMT_API auto decimal_point_impl(locale_ref) -> char; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4299 |
extern template FMT_API auto decimal_point_impl(locale_ref) -> wchar_t; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4300 |
#endif // FMT_HEADER_ONLY |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4301 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4302 |
FMT_END_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4303 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4304 |
template <typename T, typename Char, type TYPE> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4305 |
template <typename FormatContext> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4306 |
FMT_CONSTEXPR FMT_INLINE auto native_formatter<T, Char, TYPE>::format( |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4307 |
const T& val, FormatContext& ctx) const -> decltype(ctx.out()) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4308 |
if (specs_.width_ref.kind == arg_id_kind::none && |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4309 |
specs_.precision_ref.kind == arg_id_kind::none) { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4310 |
return write<Char>(ctx.out(), val, specs_, ctx.locale()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4311 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4312 |
auto specs = specs_; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4313 |
handle_dynamic_spec<width_checker>(specs.width, specs.width_ref, ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4314 |
handle_dynamic_spec<precision_checker>(specs.precision, specs.precision_ref, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4315 |
ctx); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4316 |
return write<Char>(ctx.out(), val, specs, ctx.locale()); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4317 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4318 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4319 |
} // namespace detail |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4320 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4321 |
FMT_BEGIN_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4322 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4323 |
template <typename Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4324 |
struct formatter<detail::float128, Char> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4325 |
: detail::native_formatter<detail::float128, Char, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4326 |
detail::type::float_type> {}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4327 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4328 |
#if FMT_USE_USER_DEFINED_LITERALS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4329 |
inline namespace literals { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4330 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4331 |
* User-defined literal equivalent of `fmt::arg`. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4332 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4333 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4334 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4335 |
* using namespace fmt::literals; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4336 |
* fmt::print("The answer is {answer}.", "answer"_a=42); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4337 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4338 |
# if FMT_USE_NONTYPE_TEMPLATE_ARGS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4339 |
template <detail_exported::fixed_string Str> constexpr auto operator""_a() { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4340 |
using char_t = remove_cvref_t<decltype(Str.data[0])>; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4341 |
return detail::udl_arg<char_t, sizeof(Str.data) / sizeof(char_t), Str>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4342 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4343 |
# else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4344 |
constexpr auto operator""_a(const char* s, size_t) -> detail::udl_arg<char> { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4345 |
return {s}; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4346 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4347 |
# endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4348 |
} // namespace literals |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4349 |
#endif // FMT_USE_USER_DEFINED_LITERALS |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4350 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4351 |
FMT_API auto vformat(string_view fmt, format_args args) -> std::string; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4352 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4353 |
/** |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4354 |
* Formats `args` according to specifications in `fmt` and returns the result |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4355 |
* as a string. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4356 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4357 |
* **Example**: |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4358 |
* |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4359 |
* #include <fmt/format.h> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4360 |
* std::string message = fmt::format("The answer is {}.", 42); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4361 |
*/ |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4362 |
template <typename... T> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4363 |
FMT_NODISCARD FMT_INLINE auto format(format_string<T...> fmt, T&&... args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4364 |
-> std::string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4365 |
return vformat(fmt, fmt::make_format_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4366 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4367 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4368 |
template <typename Locale, FMT_ENABLE_IF(detail::is_locale<Locale>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4369 |
inline auto vformat(const Locale& loc, string_view fmt, format_args args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4370 |
-> std::string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4371 |
return detail::vformat(loc, fmt, args); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4372 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4373 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4374 |
template <typename Locale, typename... T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4375 |
FMT_ENABLE_IF(detail::is_locale<Locale>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4376 |
inline auto format(const Locale& loc, format_string<T...> fmt, T&&... args) |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4377 |
-> std::string { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4378 |
return fmt::vformat(loc, string_view(fmt), fmt::make_format_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4379 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4380 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4381 |
template <typename OutputIt, typename Locale, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4382 |
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&& |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4383 |
detail::is_locale<Locale>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4384 |
auto vformat_to(OutputIt out, const Locale& loc, string_view fmt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4385 |
format_args args) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4386 |
using detail::get_buffer; |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4387 |
auto&& buf = get_buffer<char>(out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4388 |
detail::vformat_to(buf, fmt, args, detail::locale_ref(loc)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4389 |
return detail::get_iterator(buf, out); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4390 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4391 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4392 |
template <typename OutputIt, typename Locale, typename... T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4393 |
FMT_ENABLE_IF(detail::is_output_iterator<OutputIt, char>::value&& |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4394 |
detail::is_locale<Locale>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4395 |
FMT_INLINE auto format_to(OutputIt out, const Locale& loc, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4396 |
format_string<T...> fmt, T&&... args) -> OutputIt { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4397 |
return vformat_to(out, loc, fmt, fmt::make_format_args(args...)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4398 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4399 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4400 |
template <typename Locale, typename... T, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4401 |
FMT_ENABLE_IF(detail::is_locale<Locale>::value)> |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4402 |
FMT_NODISCARD FMT_INLINE auto formatted_size(const Locale& loc, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4403 |
format_string<T...> fmt, |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4404 |
T&&... args) -> size_t { |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4405 |
auto buf = detail::counting_buffer<>(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4406 |
detail::vformat_to<char>(buf, fmt, fmt::make_format_args(args...), |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4407 |
detail::locale_ref(loc)); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4408 |
return buf.count(); |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4409 |
} |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4410 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4411 |
FMT_END_EXPORT |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4412 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4413 |
FMT_END_NAMESPACE |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4414 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4415 |
#ifdef FMT_HEADER_ONLY |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4416 |
# define FMT_FUNC inline |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4417 |
# include "format-inl.h" |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4418 |
#else |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4419 |
# define FMT_FUNC |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4420 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4421 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4422 |
// Restore _LIBCPP_REMOVE_TRANSITIVE_INCLUDES. |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4423 |
#ifdef FMT_REMOVE_TRANSITIVE_INCLUDES |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4424 |
# undef _LIBCPP_REMOVE_TRANSITIVE_INCLUDES |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4425 |
#endif |
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4426 |
|
| 47fd5c32 |
Poul Sander |
2024-10-05 08:44 |
4427 |
#endif // FMT_FORMAT_H_ |
|
|
1970-01-01 00:00 |
4428 |
|