1 | // -*- C++ -*- |
2 | //===----------------------------------------------------------------------===// |
3 | // |
4 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
5 | // See https://llvm.org/LICENSE.txt for license information. |
6 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
7 | // |
8 | //===----------------------------------------------------------------------===// |
9 | |
10 | #ifndef _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H |
11 | #define _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H |
12 | |
13 | #include <__algorithm/copy_n.h> |
14 | #include <__assert> |
15 | #include <__bit/countl.h> |
16 | #include <__charconv/tables.h> |
17 | #include <__charconv/to_chars_base_10.h> |
18 | #include <__charconv/to_chars_result.h> |
19 | #include <__charconv/traits.h> |
20 | #include <__config> |
21 | #include <__cstddef/ptrdiff_t.h> |
22 | #include <__system_error/errc.h> |
23 | #include <__type_traits/enable_if.h> |
24 | #include <__type_traits/integral_constant.h> |
25 | #include <__type_traits/is_integral.h> |
26 | #include <__type_traits/is_same.h> |
27 | #include <__type_traits/make_32_64_or_128_bit.h> |
28 | #include <__type_traits/make_unsigned.h> |
29 | #include <__utility/unreachable.h> |
30 | #include <cstdint> |
31 | #include <limits> |
32 | |
33 | #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER) |
34 | # pragma GCC system_header |
35 | #endif |
36 | |
37 | _LIBCPP_PUSH_MACROS |
38 | #include <__undef_macros> |
39 | |
40 | _LIBCPP_BEGIN_NAMESPACE_STD |
41 | |
42 | template <typename _Tp> |
43 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
44 | __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type); |
45 | |
46 | template <typename _Tp> |
47 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
48 | __to_chars_itoa(char* __first, char* __last, _Tp __value, true_type) { |
49 | auto __x = std::__to_unsigned_like(__value); |
50 | if (__value < 0 && __first != __last) { |
51 | *__first++ = '-'; |
52 | __x = std::__complement(__x); |
53 | } |
54 | |
55 | return std::__to_chars_itoa(__first, __last, __x, false_type()); |
56 | } |
57 | |
58 | template <typename _Tp> |
59 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
60 | __to_chars_itoa(char* __first, char* __last, _Tp __value, false_type) { |
61 | using __tx = __itoa::__traits<_Tp>; |
62 | auto __diff = __last - __first; |
63 | |
64 | if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) |
65 | return {__tx::__convert(__first, __value), errc(0)}; |
66 | else |
67 | return {__last, errc::value_too_large}; |
68 | } |
69 | |
70 | # if _LIBCPP_HAS_INT128 |
71 | template <> |
72 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
73 | __to_chars_itoa(char* __first, char* __last, __uint128_t __value, false_type) { |
74 | // When the value fits in 64-bits use the 64-bit code path. This reduces |
75 | // the number of expensive calculations on 128-bit values. |
76 | // |
77 | // NOTE the 128-bit code path requires this optimization. |
78 | if (__value <= numeric_limits<uint64_t>::max()) |
79 | return __to_chars_itoa(__first, __last, value: static_cast<uint64_t>(__value), false_type()); |
80 | |
81 | using __tx = __itoa::__traits<__uint128_t>; |
82 | auto __diff = __last - __first; |
83 | |
84 | if (__tx::digits <= __diff || __tx::__width(__value) <= __diff) |
85 | return {__tx::__convert(p: __first, v: __value), errc(0)}; |
86 | else |
87 | return {__last, errc::value_too_large}; |
88 | } |
89 | # endif |
90 | |
91 | template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> = 0> |
92 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
93 | __to_chars_integral(char* __first, char* __last, _Tp __value, int __base); |
94 | |
95 | template <class _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0> |
96 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
97 | __to_chars_integral(char* __first, char* __last, _Tp __value, int __base) { |
98 | auto __x = std::__to_unsigned_like(__value); |
99 | if (__value < 0 && __first != __last) { |
100 | *__first++ = '-'; |
101 | __x = std::__complement(__x); |
102 | } |
103 | |
104 | return std::__to_chars_integral(__first, __last, __x, __base); |
105 | } |
106 | |
107 | namespace __itoa { |
108 | |
109 | template <unsigned _Base> |
110 | struct _LIBCPP_HIDDEN __integral; |
111 | |
112 | template <> |
113 | struct _LIBCPP_HIDDEN __integral<2> { |
114 | template <typename _Tp> |
115 | _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT { |
116 | // If value == 0 still need one digit. If the value != this has no |
117 | // effect since the code scans for the most significant bit set. |
118 | return numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1); |
119 | } |
120 | |
121 | template <typename _Tp> |
122 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result |
123 | __to_chars(char* __first, char* __last, _Tp __value) { |
124 | ptrdiff_t __cap = __last - __first; |
125 | int __n = __width(__value); |
126 | if (__n > __cap) |
127 | return {__last, errc::value_too_large}; |
128 | |
129 | __last = __first + __n; |
130 | char* __p = __last; |
131 | const unsigned __divisor = 16; |
132 | while (__value > __divisor) { |
133 | unsigned __c = __value % __divisor; |
134 | __value /= __divisor; |
135 | __p -= 4; |
136 | std::copy_n(first: &__base_2_lut[4 * __c], orig_n: 4, result: __p); |
137 | } |
138 | do { |
139 | unsigned __c = __value % 2; |
140 | __value /= 2; |
141 | *--__p = "01" [__c]; |
142 | } while (__value != 0); |
143 | return {__last, errc(0)}; |
144 | } |
145 | }; |
146 | |
147 | template <> |
148 | struct _LIBCPP_HIDDEN __integral<8> { |
149 | template <typename _Tp> |
150 | _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT { |
151 | // If value == 0 still need one digit. If the value != this has no |
152 | // effect since the code scans for the most significat bit set. |
153 | return ((numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1)) + 2) / 3; |
154 | } |
155 | |
156 | template <typename _Tp> |
157 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result |
158 | __to_chars(char* __first, char* __last, _Tp __value) { |
159 | ptrdiff_t __cap = __last - __first; |
160 | int __n = __width(__value); |
161 | if (__n > __cap) |
162 | return {__last, errc::value_too_large}; |
163 | |
164 | __last = __first + __n; |
165 | char* __p = __last; |
166 | unsigned __divisor = 64; |
167 | while (__value > __divisor) { |
168 | unsigned __c = __value % __divisor; |
169 | __value /= __divisor; |
170 | __p -= 2; |
171 | std::copy_n(first: &__base_8_lut[2 * __c], orig_n: 2, result: __p); |
172 | } |
173 | do { |
174 | unsigned __c = __value % 8; |
175 | __value /= 8; |
176 | *--__p = "01234567" [__c]; |
177 | } while (__value != 0); |
178 | return {__last, errc(0)}; |
179 | } |
180 | }; |
181 | |
182 | template <> |
183 | struct _LIBCPP_HIDDEN __integral<16> { |
184 | template <typename _Tp> |
185 | _LIBCPP_HIDE_FROM_ABI static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT { |
186 | // If value == 0 still need one digit. If the value != this has no |
187 | // effect since the code scans for the most significat bit set. |
188 | return (numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1) + 3) / 4; |
189 | } |
190 | |
191 | template <typename _Tp> |
192 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI static __to_chars_result |
193 | __to_chars(char* __first, char* __last, _Tp __value) { |
194 | ptrdiff_t __cap = __last - __first; |
195 | int __n = __width(__value); |
196 | if (__n > __cap) |
197 | return {__last, errc::value_too_large}; |
198 | |
199 | __last = __first + __n; |
200 | char* __p = __last; |
201 | unsigned __divisor = 256; |
202 | while (__value > __divisor) { |
203 | unsigned __c = __value % __divisor; |
204 | __value /= __divisor; |
205 | __p -= 2; |
206 | std::copy_n(first: &__base_16_lut[2 * __c], orig_n: 2, result: __p); |
207 | } |
208 | if (__first != __last) |
209 | do { |
210 | unsigned __c = __value % 16; |
211 | __value /= 16; |
212 | *--__p = "0123456789abcdef" [__c]; |
213 | } while (__value != 0); |
214 | return {__last, errc(0)}; |
215 | } |
216 | }; |
217 | |
218 | } // namespace __itoa |
219 | |
220 | template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0> |
221 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) { |
222 | return __itoa::__integral<_Base>::__width(__value); |
223 | } |
224 | |
225 | template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0> |
226 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value) { |
227 | return std::__to_chars_integral_width<_Base>(static_cast<unsigned>(__value)); |
228 | } |
229 | |
230 | template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0> |
231 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
232 | __to_chars_integral(char* __first, char* __last, _Tp __value) { |
233 | return __itoa::__integral<_Base>::__to_chars(__first, __last, __value); |
234 | } |
235 | |
236 | template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0> |
237 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
238 | __to_chars_integral(char* __first, char* __last, _Tp __value) { |
239 | return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value)); |
240 | } |
241 | |
242 | template <typename _Tp> |
243 | _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value, unsigned __base) { |
244 | _LIBCPP_ASSERT_INTERNAL(__value >= 0, "The function requires a non-negative value." ); |
245 | |
246 | unsigned __base_2 = __base * __base; |
247 | unsigned __base_3 = __base_2 * __base; |
248 | unsigned __base_4 = __base_2 * __base_2; |
249 | |
250 | int __r = 0; |
251 | while (true) { |
252 | if (__value < __base) |
253 | return __r + 1; |
254 | if (__value < __base_2) |
255 | return __r + 2; |
256 | if (__value < __base_3) |
257 | return __r + 3; |
258 | if (__value < __base_4) |
259 | return __r + 4; |
260 | |
261 | __value /= __base_4; |
262 | __r += 4; |
263 | } |
264 | |
265 | __libcpp_unreachable(); |
266 | } |
267 | |
268 | template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> > |
269 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result |
270 | __to_chars_integral(char* __first, char* __last, _Tp __value, int __base) { |
271 | if (__base == 10) [[likely]] |
272 | return std::__to_chars_itoa(__first, __last, __value, false_type()); |
273 | |
274 | switch (__base) { |
275 | case 2: |
276 | return std::__to_chars_integral<2>(__first, __last, __value); |
277 | case 8: |
278 | return std::__to_chars_integral<8>(__first, __last, __value); |
279 | case 16: |
280 | return std::__to_chars_integral<16>(__first, __last, __value); |
281 | } |
282 | |
283 | ptrdiff_t __cap = __last - __first; |
284 | int __n = std::__to_chars_integral_width(__value, __base); |
285 | if (__n > __cap) |
286 | return {__last, errc::value_too_large}; |
287 | |
288 | __last = __first + __n; |
289 | char* __p = __last; |
290 | do { |
291 | unsigned __c = __value % __base; |
292 | __value /= __base; |
293 | *--__p = "0123456789abcdefghijklmnopqrstuvwxyz" [__c]; |
294 | } while (__value != 0); |
295 | return {__last, errc(0)}; |
296 | } |
297 | |
298 | _LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) { |
299 | switch (__c) { |
300 | case 'a': |
301 | return 'A'; |
302 | case 'b': |
303 | return 'B'; |
304 | case 'c': |
305 | return 'C'; |
306 | case 'd': |
307 | return 'D'; |
308 | case 'e': |
309 | return 'E'; |
310 | case 'f': |
311 | return 'F'; |
312 | } |
313 | return __c; |
314 | } |
315 | |
316 | #if _LIBCPP_STD_VER >= 17 |
317 | |
318 | to_chars_result to_chars(char*, char*, bool, int = 10) = delete; |
319 | |
320 | template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0> |
321 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result |
322 | to_chars(char* __first, char* __last, _Tp __value) { |
323 | using _Type = __make_32_64_or_128_bit_t<_Tp>; |
324 | static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars" ); |
325 | return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>()); |
326 | } |
327 | |
328 | template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0> |
329 | inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result |
330 | to_chars(char* __first, char* __last, _Tp __value, int __base) { |
331 | _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]" ); |
332 | |
333 | using _Type = __make_32_64_or_128_bit_t<_Tp>; |
334 | return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base); |
335 | } |
336 | |
337 | #endif // _LIBCPP_STD_VER >= 17 |
338 | |
339 | _LIBCPP_END_NAMESPACE_STD |
340 | |
341 | _LIBCPP_POP_MACROS |
342 | |
343 | #endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H |
344 | |