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 __to_chars_result
45__to_chars_itoa(char* __first, char* __last, _Tp __value, false_type);
46
47template <typename _Tp>
48inline _LIBCPP_CONSTEXPR_SINCE_CXX23 __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 __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
74__to_chars_result __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(v: __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
94__to_chars_result __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 __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 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 static __to_chars_result __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], 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
147template <>
148struct _LIBCPP_HIDDEN __integral<8> {
149 template <typename _Tp>
150 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 static __to_chars_result __to_chars(char* __first, char* __last, _Tp __value) {
158 ptrdiff_t __cap = __last - __first;
159 int __n = __width(__value);
160 if (__n > __cap)
161 return {__last, errc::value_too_large};
162
163 __last = __first + __n;
164 char* __p = __last;
165 unsigned __divisor = 64;
166 while (__value > __divisor) {
167 unsigned __c = __value % __divisor;
168 __value /= __divisor;
169 __p -= 2;
170 std::copy_n(first: &__base_8_lut[2 * __c], n: 2, result: __p);
171 }
172 do {
173 unsigned __c = __value % 8;
174 __value /= 8;
175 *--__p = "01234567"[__c];
176 } while (__value != 0);
177 return {__last, errc(0)};
178 }
179};
180
181template <>
182struct _LIBCPP_HIDDEN __integral<16> {
183 template <typename _Tp>
184 static _LIBCPP_CONSTEXPR int __width(_Tp __value) _NOEXCEPT {
185 // If value == 0 still need one digit. If the value != this has no
186 // effect since the code scans for the most significat bit set.
187 return (numeric_limits<_Tp>::digits - std::__countl_zero(__value | 1) + 3) / 4;
188 }
189
190 template <typename _Tp>
191 _LIBCPP_CONSTEXPR_SINCE_CXX23 static __to_chars_result __to_chars(char* __first, char* __last, _Tp __value) {
192 ptrdiff_t __cap = __last - __first;
193 int __n = __width(__value);
194 if (__n > __cap)
195 return {__last, errc::value_too_large};
196
197 __last = __first + __n;
198 char* __p = __last;
199 unsigned __divisor = 256;
200 while (__value > __divisor) {
201 unsigned __c = __value % __divisor;
202 __value /= __divisor;
203 __p -= 2;
204 std::copy_n(first: &__base_16_lut[2 * __c], n: 2, result: __p);
205 }
206 if (__first != __last)
207 do {
208 unsigned __c = __value % 16;
209 __value /= 16;
210 *--__p = "0123456789abcdef"[__c];
211 } while (__value != 0);
212 return {__last, errc(0)};
213 }
214};
215
216} // namespace __itoa
217
218template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) >= sizeof(unsigned)), int> = 0>
219_LIBCPP_CONSTEXPR_SINCE_CXX23 __to_chars_result __to_chars_integral(char* __first, char* __last, _Tp __value) {
220 return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);
221}
222
223template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>
224_LIBCPP_CONSTEXPR_SINCE_CXX23 __to_chars_result __to_chars_integral(char* __first, char* __last, _Tp __value) {
225 return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));
226}
227
228template <typename _Tp>
229_LIBCPP_CONSTEXPR_SINCE_CXX23 int __to_chars_integral_width(_Tp __value, unsigned __base) {
230 _LIBCPP_ASSERT_INTERNAL(__value >= 0, "The function requires a non-negative value.");
231
232 unsigned __base_2 = __base * __base;
233 unsigned __base_3 = __base_2 * __base;
234 unsigned __base_4 = __base_2 * __base_2;
235
236 int __r = 0;
237 while (true) {
238 if (__value < __base)
239 return __r + 1;
240 if (__value < __base_2)
241 return __r + 2;
242 if (__value < __base_3)
243 return __r + 3;
244 if (__value < __base_4)
245 return __r + 4;
246
247 __value /= __base_4;
248 __r += 4;
249 }
250
251 __libcpp_unreachable();
252}
253
254template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> >
255inline _LIBCPP_CONSTEXPR_SINCE_CXX23 __to_chars_result
256__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {
257 if (__base == 10) [[likely]]
258 return std::__to_chars_itoa(__first, __last, __value, false_type());
259
260 switch (__base) {
261 case 2:
262 return std::__to_chars_integral<2>(__first, __last, __value);
263 case 8:
264 return std::__to_chars_integral<8>(__first, __last, __value);
265 case 16:
266 return std::__to_chars_integral<16>(__first, __last, __value);
267 }
268
269 ptrdiff_t __cap = __last - __first;
270 int __n = std::__to_chars_integral_width(__value, __base);
271 if (__n > __cap)
272 return {__last, errc::value_too_large};
273
274 __last = __first + __n;
275 char* __p = __last;
276 do {
277 unsigned __c = __value % __base;
278 __value /= __base;
279 *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];
280 } while (__value != 0);
281 return {__last, errc(0)};
282}
283
284inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) {
285 switch (__c) {
286 case 'a':
287 return 'A';
288 case 'b':
289 return 'B';
290 case 'c':
291 return 'C';
292 case 'd':
293 return 'D';
294 case 'e':
295 return 'E';
296 case 'f':
297 return 'F';
298 }
299 return __c;
300}
301
302#if _LIBCPP_STD_VER >= 17
303
304to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
305
306template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
307inline _LIBCPP_CONSTEXPR_SINCE_CXX23 to_chars_result 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>());
311}
312
313template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
314inline _LIBCPP_CONSTEXPR_SINCE_CXX23 to_chars_result to_chars(char* __first, char* __last, _Tp __value, int __base) {
315 _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
316
317 using _Type = __make_32_64_or_128_bit_t<_Tp>;
318 return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base);
319}
320
321#endif // _LIBCPP_STD_VER >= 17
322
323_LIBCPP_END_NAMESPACE_STD
324
325_LIBCPP_POP_MACROS
326
327#endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
328