2 //===----------------------------------------------------------------------===//
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
8 //===----------------------------------------------------------------------===//
10 #ifndef _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
11 #define _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
13 #include <__algorithm/copy_n.h>
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>
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>
33 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
34 # pragma GCC system_header
38 #include <__undef_macros>
40 _LIBCPP_BEGIN_NAMESPACE_STD
42 #if _LIBCPP_STD_VER >= 17
44 to_chars_result
to_chars(char*, char*, bool, int = 10) = delete;
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
, false_type
);
50 template <typename _Tp
>
51 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
52 __to_chars_itoa(char* __first
, char* __last
, _Tp __value
, true_type
) {
53 auto __x
= std::__to_unsigned_like(__value
);
54 if (__value
< 0 && __first
!= __last
) {
56 __x
= std::__complement(__x
);
59 return std::__to_chars_itoa(__first
, __last
, __x
, false_type());
62 template <typename _Tp
>
63 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
64 __to_chars_itoa(char* __first
, char* __last
, _Tp __value
, false_type
) {
65 using __tx
= __itoa::__traits
<_Tp
>;
66 auto __diff
= __last
- __first
;
68 if (__tx::digits
<= __diff
|| __tx::__width(__value
) <= __diff
)
69 return {__tx::__convert(__first
, __value
), errc(0)};
71 return {__last
, errc::value_too_large
};
74 # if _LIBCPP_HAS_INT128
76 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
77 __to_chars_itoa(char* __first
, char* __last
, __uint128_t __value
, false_type
) {
78 // When the value fits in 64-bits use the 64-bit code path. This reduces
79 // the number of expensive calculations on 128-bit values.
81 // NOTE the 128-bit code path requires this optimization.
82 if (__value
<= numeric_limits
<uint64_t>::max())
83 return __to_chars_itoa(__first
, __last
, static_cast<uint64_t>(__value
), false_type());
85 using __tx
= __itoa::__traits
<__uint128_t
>;
86 auto __diff
= __last
- __first
;
88 if (__tx::digits
<= __diff
|| __tx::__width(__value
) <= __diff
)
89 return {__tx::__convert(__first
, __value
), errc(0)};
91 return {__last
, errc::value_too_large
};
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
, false_type
);
99 template <typename _Tp
>
100 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
101 __to_chars_integral(char* __first
, char* __last
, _Tp __value
, int __base
, true_type
) {
102 auto __x
= std::__to_unsigned_like(__value
);
103 if (__value
< 0 && __first
!= __last
) {
105 __x
= std::__complement(__x
);
108 return std::__to_chars_integral(__first
, __last
, __x
, __base
, false_type());
113 template <unsigned _Base
>
114 struct _LIBCPP_HIDDEN __integral
;
117 struct _LIBCPP_HIDDEN __integral
<2> {
118 template <typename _Tp
>
119 _LIBCPP_HIDE_FROM_ABI
static constexpr int __width(_Tp __value
) noexcept
{
120 // If value == 0 still need one digit. If the value != this has no
121 // effect since the code scans for the most significant bit set. (Note
122 // that __libcpp_clz doesn't work for 0.)
123 return numeric_limits
<_Tp
>::digits
- std::__libcpp_clz(__value
| 1);
126 template <typename _Tp
>
127 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
static to_chars_result
128 __to_chars(char* __first
, char* __last
, _Tp __value
) {
129 ptrdiff_t __cap
= __last
- __first
;
130 int __n
= __width(__value
);
132 return {__last
, errc::value_too_large
};
134 __last
= __first
+ __n
;
136 const unsigned __divisor
= 16;
137 while (__value
> __divisor
) {
138 unsigned __c
= __value
% __divisor
;
139 __value
/= __divisor
;
141 std::copy_n(&__base_2_lut
[4 * __c
], 4, __p
);
144 unsigned __c
= __value
% 2;
147 } while (__value
!= 0);
148 return {__last
, errc(0)};
153 struct _LIBCPP_HIDDEN __integral
<8> {
154 template <typename _Tp
>
155 _LIBCPP_HIDE_FROM_ABI
static constexpr int __width(_Tp __value
) noexcept
{
156 // If value == 0 still need one digit. If the value != this has no
157 // effect since the code scans for the most significat bit set. (Note
158 // that __libcpp_clz doesn't work for 0.)
159 return ((numeric_limits
<_Tp
>::digits
- std::__libcpp_clz(__value
| 1)) + 2) / 3;
162 template <typename _Tp
>
163 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
static to_chars_result
164 __to_chars(char* __first
, char* __last
, _Tp __value
) {
165 ptrdiff_t __cap
= __last
- __first
;
166 int __n
= __width(__value
);
168 return {__last
, errc::value_too_large
};
170 __last
= __first
+ __n
;
172 unsigned __divisor
= 64;
173 while (__value
> __divisor
) {
174 unsigned __c
= __value
% __divisor
;
175 __value
/= __divisor
;
177 std::copy_n(&__base_8_lut
[2 * __c
], 2, __p
);
180 unsigned __c
= __value
% 8;
182 *--__p
= "01234567"[__c
];
183 } while (__value
!= 0);
184 return {__last
, errc(0)};
189 struct _LIBCPP_HIDDEN __integral
<16> {
190 template <typename _Tp
>
191 _LIBCPP_HIDE_FROM_ABI
static constexpr int __width(_Tp __value
) noexcept
{
192 // If value == 0 still need one digit. If the value != this has no
193 // effect since the code scans for the most significat bit set. (Note
194 // that __libcpp_clz doesn't work for 0.)
195 return (numeric_limits
<_Tp
>::digits
- std::__libcpp_clz(__value
| 1) + 3) / 4;
198 template <typename _Tp
>
199 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
static to_chars_result
200 __to_chars(char* __first
, char* __last
, _Tp __value
) {
201 ptrdiff_t __cap
= __last
- __first
;
202 int __n
= __width(__value
);
204 return {__last
, errc::value_too_large
};
206 __last
= __first
+ __n
;
208 unsigned __divisor
= 256;
209 while (__value
> __divisor
) {
210 unsigned __c
= __value
% __divisor
;
211 __value
/= __divisor
;
213 std::copy_n(&__base_16_lut
[2 * __c
], 2, __p
);
215 if (__first
!= __last
)
217 unsigned __c
= __value
% 16;
219 *--__p
= "0123456789abcdef"[__c
];
220 } while (__value
!= 0);
221 return {__last
, errc(0)};
225 } // namespace __itoa
227 template <unsigned _Base
, typename _Tp
, __enable_if_t
<(sizeof(_Tp
) >= sizeof(unsigned)), int> = 0>
228 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
int __to_chars_integral_width(_Tp __value
) {
229 return __itoa::__integral
<_Base
>::__width(__value
);
232 template <unsigned _Base
, typename _Tp
, __enable_if_t
<(sizeof(_Tp
) < sizeof(unsigned)), int> = 0>
233 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
int __to_chars_integral_width(_Tp __value
) {
234 return std::__to_chars_integral_width
<_Base
>(static_cast<unsigned>(__value
));
237 template <unsigned _Base
, typename _Tp
, __enable_if_t
<(sizeof(_Tp
) >= sizeof(unsigned)), int> = 0>
238 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
239 __to_chars_integral(char* __first
, char* __last
, _Tp __value
) {
240 return __itoa::__integral
<_Base
>::__to_chars(__first
, __last
, __value
);
243 template <unsigned _Base
, typename _Tp
, __enable_if_t
<(sizeof(_Tp
) < sizeof(unsigned)), int> = 0>
244 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
245 __to_chars_integral(char* __first
, char* __last
, _Tp __value
) {
246 return std::__to_chars_integral
<_Base
>(__first
, __last
, static_cast<unsigned>(__value
));
249 template <typename _Tp
>
250 _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI
int __to_chars_integral_width(_Tp __value
, unsigned __base
) {
251 _LIBCPP_ASSERT_INTERNAL(__value
>= 0, "The function requires a non-negative value.");
253 unsigned __base_2
= __base
* __base
;
254 unsigned __base_3
= __base_2
* __base
;
255 unsigned __base_4
= __base_2
* __base_2
;
259 if (__value
< __base
)
261 if (__value
< __base_2
)
263 if (__value
< __base_3
)
265 if (__value
< __base_4
)
272 __libcpp_unreachable();
275 template <typename _Tp
>
276 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
277 __to_chars_integral(char* __first
, char* __last
, _Tp __value
, int __base
, false_type
) {
278 if (__base
== 10) [[likely
]]
279 return std::__to_chars_itoa(__first
, __last
, __value
, false_type());
283 return std::__to_chars_integral
<2>(__first
, __last
, __value
);
285 return std::__to_chars_integral
<8>(__first
, __last
, __value
);
287 return std::__to_chars_integral
<16>(__first
, __last
, __value
);
290 ptrdiff_t __cap
= __last
- __first
;
291 int __n
= std::__to_chars_integral_width(__value
, __base
);
293 return {__last
, errc::value_too_large
};
295 __last
= __first
+ __n
;
298 unsigned __c
= __value
% __base
;
300 *--__p
= "0123456789abcdefghijklmnopqrstuvwxyz"[__c
];
301 } while (__value
!= 0);
302 return {__last
, errc(0)};
305 template <typename _Tp
, __enable_if_t
<is_integral
<_Tp
>::value
, int> = 0>
306 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
307 to_chars(char* __first
, char* __last
, _Tp __value
) {
308 using _Type
= __make_32_64_or_128_bit_t
<_Tp
>;
309 static_assert(!is_same
<_Type
, void>::value
, "unsupported integral type used in to_chars");
310 return std::__to_chars_itoa(__first
, __last
, static_cast<_Type
>(__value
), is_signed
<_Tp
>());
313 template <typename _Tp
, __enable_if_t
<is_integral
<_Tp
>::value
, int> = 0>
314 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
315 to_chars(char* __first
, char* __last
, _Tp __value
, int __base
) {
316 _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base
&& __base
<= 36, "base not in [2, 36]");
318 using _Type
= __make_32_64_or_128_bit_t
<_Tp
>;
319 return std::__to_chars_integral(__first
, __last
, static_cast<_Type
>(__value
), __base
, is_signed
<_Tp
>());
322 #endif // _LIBCPP_STD_VER >= 17
324 _LIBCPP_END_NAMESPACE_STD
328 #endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H