Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/libcxx/include/__charconv/from_chars_integral.h
35262 views
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_FROM_CHARS_INTEGRAL_H
11
#define _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H
12
13
#include <__algorithm/copy_n.h>
14
#include <__assert>
15
#include <__charconv/from_chars_result.h>
16
#include <__charconv/traits.h>
17
#include <__config>
18
#include <__memory/addressof.h>
19
#include <__system_error/errc.h>
20
#include <__type_traits/enable_if.h>
21
#include <__type_traits/integral_constant.h>
22
#include <__type_traits/is_integral.h>
23
#include <__type_traits/is_unsigned.h>
24
#include <__type_traits/make_unsigned.h>
25
#include <limits>
26
27
#if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
28
# pragma GCC system_header
29
#endif
30
31
_LIBCPP_PUSH_MACROS
32
#include <__undef_macros>
33
34
_LIBCPP_BEGIN_NAMESPACE_STD
35
36
#if _LIBCPP_STD_VER >= 17
37
38
from_chars_result from_chars(const char*, const char*, bool, int = 10) = delete;
39
40
template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
41
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
42
__sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) {
43
using __tl = numeric_limits<_Tp>;
44
decltype(std::__to_unsigned_like(__value)) __x;
45
46
bool __neg = (__first != __last && *__first == '-');
47
auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...);
48
switch (__r.ec) {
49
case errc::invalid_argument:
50
return {__first, __r.ec};
51
case errc::result_out_of_range:
52
return __r;
53
default:
54
break;
55
}
56
57
if (__neg) {
58
if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) {
59
__x = std::__complement(__x);
60
std::copy_n(std::addressof(__x), 1, std::addressof(__value));
61
return __r;
62
}
63
} else {
64
if (__x <= std::__to_unsigned_like(__tl::max())) {
65
__value = __x;
66
return __r;
67
}
68
}
69
70
return {__r.ptr, errc::result_out_of_range};
71
}
72
73
template <typename _Tp>
74
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __in_pattern(_Tp __c) {
75
return '0' <= __c && __c <= '9';
76
}
77
78
struct _LIBCPP_HIDDEN __in_pattern_result {
79
bool __ok;
80
int __val;
81
82
explicit _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; }
83
};
84
85
template <typename _Tp>
86
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __in_pattern_result __in_pattern(_Tp __c, int __base) {
87
if (__base <= 10)
88
return {'0' <= __c && __c < '0' + __base, __c - '0'};
89
else if (std::__in_pattern(__c))
90
return {true, __c - '0'};
91
else if ('a' <= __c && __c < 'a' + __base - 10)
92
return {true, __c - 'a' + 10};
93
else
94
return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10};
95
}
96
97
template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
98
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
99
__subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) {
100
auto __find_non_zero = [](_It __firstit, _It __lastit) {
101
for (; __firstit != __lastit; ++__firstit)
102
if (*__firstit != '0')
103
break;
104
return __firstit;
105
};
106
107
auto __p = __find_non_zero(__first, __last);
108
if (__p == __last || !std::__in_pattern(*__p, __args...)) {
109
if (__p == __first)
110
return {__first, errc::invalid_argument};
111
else {
112
__value = 0;
113
return {__p, {}};
114
}
115
}
116
117
auto __r = __f(__p, __last, __value, __args...);
118
if (__r.ec == errc::result_out_of_range) {
119
for (; __r.ptr != __last; ++__r.ptr) {
120
if (!std::__in_pattern(*__r.ptr, __args...))
121
break;
122
}
123
}
124
125
return __r;
126
}
127
128
template <typename _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
129
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
130
__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) {
131
using __tx = __itoa::__traits<_Tp>;
132
using __output_type = typename __tx::type;
133
134
return std::__subject_seq_combinator(
135
__first, __last, __value, [](const char* __f, const char* __l, _Tp& __val) -> from_chars_result {
136
__output_type __a, __b;
137
auto __p = __tx::__read(__f, __l, __a, __b);
138
if (__p == __l || !std::__in_pattern(*__p)) {
139
__output_type __m = numeric_limits<_Tp>::max();
140
if (__m >= __a && __m - __a >= __b) {
141
__val = __a + __b;
142
return {__p, {}};
143
}
144
}
145
return {__p, errc::result_out_of_range};
146
});
147
}
148
149
template <typename _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
150
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
151
__from_chars_atoi(const char* __first, const char* __last, _Tp& __value) {
152
using __t = decltype(std::__to_unsigned_like(__value));
153
return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>);
154
}
155
156
/*
157
// Code used to generate __from_chars_log2f_lut.
158
#include <cmath>
159
#include <format>
160
#include <iostream>
161
162
int main() {
163
for (int i = 2; i <= 36; ++i)
164
std::cout << std::format("{},\n", log2f(i));
165
}
166
*/
167
/// log2f table for bases [2, 36].
168
inline constexpr float __from_chars_log2f_lut[35] = {
169
1, 1.5849625, 2, 2.321928, 2.5849626, 2.807355, 3, 3.169925, 3.321928,
170
3.4594316, 3.5849626, 3.7004397, 3.807355, 3.9068906, 4, 4.087463, 4.169925, 4.2479277,
171
4.321928, 4.3923173, 4.4594316, 4.523562, 4.5849624, 4.643856, 4.70044, 4.7548876, 4.807355,
172
4.857981, 4.9068904, 4.9541965, 5, 5.044394, 5.087463, 5.129283, 5.169925};
173
174
template <typename _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
175
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
176
__from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) {
177
if (__base == 10)
178
return std::__from_chars_atoi(__first, __last, __value);
179
180
return std::__subject_seq_combinator(
181
__first,
182
__last,
183
__value,
184
[](const char* __p, const char* __lastp, _Tp& __val, int __b) -> from_chars_result {
185
using __tl = numeric_limits<_Tp>;
186
// __base is always between 2 and 36 inclusive.
187
auto __digits = __tl::digits / __from_chars_log2f_lut[__b - 2];
188
_Tp __x = __in_pattern(*__p++, __b).__val, __y = 0;
189
190
for (int __i = 1; __p != __lastp; ++__i, ++__p) {
191
if (auto __c = __in_pattern(*__p, __b)) {
192
if (__i < __digits - 1)
193
__x = __x * __b + __c.__val;
194
else {
195
if (!__itoa::__mul_overflowed(__x, __b, __x))
196
++__p;
197
__y = __c.__val;
198
break;
199
}
200
} else
201
break;
202
}
203
204
if (__p == __lastp || !__in_pattern(*__p, __b)) {
205
if (__tl::max() - __x >= __y) {
206
__val = __x + __y;
207
return {__p, {}};
208
}
209
}
210
return {__p, errc::result_out_of_range};
211
},
212
__base);
213
}
214
215
template <typename _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
216
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
217
__from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) {
218
using __t = decltype(std::__to_unsigned_like(__value));
219
return std::__sign_combinator(__first, __last, __value, __from_chars_integral<__t>, __base);
220
}
221
222
template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
223
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
224
from_chars(const char* __first, const char* __last, _Tp& __value) {
225
return std::__from_chars_atoi(__first, __last, __value);
226
}
227
228
template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
229
inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
230
from_chars(const char* __first, const char* __last, _Tp& __value, int __base) {
231
_LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
232
return std::__from_chars_integral(__first, __last, __value, __base);
233
}
234
#endif // _LIBCPP_STD_VER >= 17
235
236
_LIBCPP_END_NAMESPACE_STD
237
238
_LIBCPP_POP_MACROS
239
240
#endif // _LIBCPP___CHARCONV_FROM_CHARS_INTEGRAL_H
241
242