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