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(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 _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 __to_chars_result
223__to_chars_integral(char* __first, char* __last, _Tp __value) {
224 return __itoa::__integral<_Base>::__to_chars(__first, __last, __value);
225}
226
227template <unsigned _Base, typename _Tp, __enable_if_t<(sizeof(_Tp) < sizeof(unsigned)), int> = 0>
228_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
229__to_chars_integral(char* __first, char* __last, _Tp __value) {
230 return std::__to_chars_integral<_Base>(__first, __last, static_cast<unsigned>(__value));
231}
232
233template <typename _Tp>
234_LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI int __to_chars_integral_width(_Tp __value, unsigned __base) {
235 _LIBCPP_ASSERT_INTERNAL(__value >= 0, "The function requires a non-negative value.");
236
237 unsigned __base_2 = __base * __base;
238 unsigned __base_3 = __base_2 * __base;
239 unsigned __base_4 = __base_2 * __base_2;
240
241 int __r = 0;
242 while (true) {
243 if (__value < __base)
244 return __r + 1;
245 if (__value < __base_2)
246 return __r + 2;
247 if (__value < __base_3)
248 return __r + 3;
249 if (__value < __base_4)
250 return __r + 4;
251
252 __value /= __base_4;
253 __r += 4;
254 }
255
256 __libcpp_unreachable();
257}
258
259template <class _Tp, __enable_if_t<!is_signed<_Tp>::value, int> >
260inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __to_chars_result
261__to_chars_integral(char* __first, char* __last, _Tp __value, int __base) {
262 if (__base == 10) [[likely]]
263 return std::__to_chars_itoa(__first, __last, __value, false_type());
264
265 switch (__base) {
266 case 2:
267 return std::__to_chars_integral<2>(__first, __last, __value);
268 case 8:
269 return std::__to_chars_integral<8>(__first, __last, __value);
270 case 16:
271 return std::__to_chars_integral<16>(__first, __last, __value);
272 }
273
274 ptrdiff_t __cap = __last - __first;
275 int __n = std::__to_chars_integral_width(__value, __base);
276 if (__n > __cap)
277 return {__last, errc::value_too_large};
278
279 __last = __first + __n;
280 char* __p = __last;
281 do {
282 unsigned __c = __value % __base;
283 __value /= __base;
284 *--__p = "0123456789abcdefghijklmnopqrstuvwxyz"[__c];
285 } while (__value != 0);
286 return {__last, errc(0)};
287}
288
289_LIBCPP_HIDE_FROM_ABI inline _LIBCPP_CONSTEXPR_SINCE_CXX14 char __hex_to_upper(char __c) {
290 switch (__c) {
291 case 'a':
292 return 'A';
293 case 'b':
294 return 'B';
295 case 'c':
296 return 'C';
297 case 'd':
298 return 'D';
299 case 'e':
300 return 'E';
301 case 'f':
302 return 'F';
303 }
304 return __c;
305}
306
307#if _LIBCPP_STD_VER >= 17
308
309to_chars_result to_chars(char*, char*, bool, int = 10) = delete;
310
311template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
312inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
313to_chars(char* __first, char* __last, _Tp __value) {
314 using _Type = __make_32_64_or_128_bit_t<_Tp>;
315 static_assert(!is_same<_Type, void>::value, "unsupported integral type used in to_chars");
316 return std::__to_chars_itoa(__first, __last, static_cast<_Type>(__value), is_signed<_Tp>());
317}
318
319template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
320inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI to_chars_result
321to_chars(char* __first, char* __last, _Tp __value, int __base) {
322 _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
323
324 using _Type = __make_32_64_or_128_bit_t<_Tp>;
325 return std::__to_chars_integral(__first, __last, static_cast<_Type>(__value), __base);
326}
327
328#endif // _LIBCPP_STD_VER >= 17
329
330_LIBCPP_END_NAMESPACE_STD
331
332_LIBCPP_POP_MACROS
333
334#endif // _LIBCPP___CHARCONV_TO_CHARS_INTEGRAL_H
335