File indexing completed on 2026-05-03 08:13:23
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef _LIBCPP___CXX03___CHARCONV_FROM_CHARS_INTEGRAL_H
0011 #define _LIBCPP___CXX03___CHARCONV_FROM_CHARS_INTEGRAL_H
0012
0013 #include <__cxx03/__algorithm/copy_n.h>
0014 #include <__cxx03/__assert>
0015 #include <__cxx03/__charconv/from_chars_result.h>
0016 #include <__cxx03/__charconv/traits.h>
0017 #include <__cxx03/__config>
0018 #include <__cxx03/__memory/addressof.h>
0019 #include <__cxx03/__system_error/errc.h>
0020 #include <__cxx03/__type_traits/enable_if.h>
0021 #include <__cxx03/__type_traits/integral_constant.h>
0022 #include <__cxx03/__type_traits/is_integral.h>
0023 #include <__cxx03/__type_traits/is_unsigned.h>
0024 #include <__cxx03/__type_traits/make_unsigned.h>
0025 #include <__cxx03/limits>
0026
0027 #if !defined(_LIBCPP_HAS_NO_PRAGMA_SYSTEM_HEADER)
0028 # pragma GCC system_header
0029 #endif
0030
0031 _LIBCPP_PUSH_MACROS
0032 #include <__cxx03/__undef_macros>
0033
0034 _LIBCPP_BEGIN_NAMESPACE_STD
0035
0036 #if _LIBCPP_STD_VER >= 17
0037
0038 from_chars_result from_chars(const char*, const char*, bool, int = 10) = delete;
0039
0040 template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
0041 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0042 __sign_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) {
0043 using __tl = numeric_limits<_Tp>;
0044 decltype(std::__to_unsigned_like(__value)) __x;
0045
0046 bool __neg = (__first != __last && *__first == '-');
0047 auto __r = __f(__neg ? __first + 1 : __first, __last, __x, __args...);
0048 switch (__r.ec) {
0049 case errc::invalid_argument:
0050 return {__first, __r.ec};
0051 case errc::result_out_of_range:
0052 return __r;
0053 default:
0054 break;
0055 }
0056
0057 if (__neg) {
0058 if (__x <= std::__complement(std::__to_unsigned_like(__tl::min()))) {
0059 __x = std::__complement(__x);
0060 std::copy_n(std::addressof(__x), 1, std::addressof(__value));
0061 return __r;
0062 }
0063 } else {
0064 if (__x <= std::__to_unsigned_like(__tl::max())) {
0065 __value = __x;
0066 return __r;
0067 }
0068 }
0069
0070 return {__r.ptr, errc::result_out_of_range};
0071 }
0072
0073 template <typename _Tp>
0074 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI bool __in_pattern(_Tp __c) {
0075 return '0' <= __c && __c <= '9';
0076 }
0077
0078 struct _LIBCPP_HIDDEN __in_pattern_result {
0079 bool __ok;
0080 int __val;
0081
0082 explicit _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI operator bool() const { return __ok; }
0083 };
0084
0085 template <typename _Tp>
0086 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI __in_pattern_result __in_pattern(_Tp __c, int __base) {
0087 if (__base <= 10)
0088 return {'0' <= __c && __c < '0' + __base, __c - '0'};
0089 else if (std::__in_pattern(__c))
0090 return {true, __c - '0'};
0091 else if ('a' <= __c && __c < 'a' + __base - 10)
0092 return {true, __c - 'a' + 10};
0093 else
0094 return {'A' <= __c && __c < 'A' + __base - 10, __c - 'A' + 10};
0095 }
0096
0097 template <typename _It, typename _Tp, typename _Fn, typename... _Ts>
0098 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0099 __subject_seq_combinator(_It __first, _It __last, _Tp& __value, _Fn __f, _Ts... __args) {
0100 auto __find_non_zero = [](_It __firstit, _It __lastit) {
0101 for (; __firstit != __lastit; ++__firstit)
0102 if (*__firstit != '0')
0103 break;
0104 return __firstit;
0105 };
0106
0107 auto __p = __find_non_zero(__first, __last);
0108 if (__p == __last || !std::__in_pattern(*__p, __args...)) {
0109 if (__p == __first)
0110 return {__first, errc::invalid_argument};
0111 else {
0112 __value = 0;
0113 return {__p, {}};
0114 }
0115 }
0116
0117 auto __r = __f(__p, __last, __value, __args...);
0118 if (__r.ec == errc::result_out_of_range) {
0119 for (; __r.ptr != __last; ++__r.ptr) {
0120 if (!std::__in_pattern(*__r.ptr, __args...))
0121 break;
0122 }
0123 }
0124
0125 return __r;
0126 }
0127
0128 template <typename _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
0129 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0130 __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) {
0131 using __tx = __itoa::__traits<_Tp>;
0132 using __output_type = typename __tx::type;
0133
0134 return std::__subject_seq_combinator(
0135 __first, __last, __value, [](const char* __f, const char* __l, _Tp& __val) -> from_chars_result {
0136 __output_type __a, __b;
0137 auto __p = __tx::__read(__f, __l, __a, __b);
0138 if (__p == __l || !std::__in_pattern(*__p)) {
0139 __output_type __m = numeric_limits<_Tp>::max();
0140 if (__m >= __a && __m - __a >= __b) {
0141 __val = __a + __b;
0142 return {__p, {}};
0143 }
0144 }
0145 return {__p, errc::result_out_of_range};
0146 });
0147 }
0148
0149 template <typename _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
0150 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0151 __from_chars_atoi(const char* __first, const char* __last, _Tp& __value) {
0152 using __t = decltype(std::__to_unsigned_like(__value));
0153 return std::__sign_combinator(__first, __last, __value, __from_chars_atoi<__t>);
0154 }
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165
0166
0167
0168 inline constexpr float __from_chars_log2f_lut[35] = {
0169 1, 1.5849625, 2, 2.321928, 2.5849626, 2.807355, 3, 3.169925, 3.321928,
0170 3.4594316, 3.5849626, 3.7004397, 3.807355, 3.9068906, 4, 4.087463, 4.169925, 4.2479277,
0171 4.321928, 4.3923173, 4.4594316, 4.523562, 4.5849624, 4.643856, 4.70044, 4.7548876, 4.807355,
0172 4.857981, 4.9068904, 4.9541965, 5, 5.044394, 5.087463, 5.129283, 5.169925};
0173
0174 template <typename _Tp, __enable_if_t<is_unsigned<_Tp>::value, int> = 0>
0175 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0176 __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) {
0177 if (__base == 10)
0178 return std::__from_chars_atoi(__first, __last, __value);
0179
0180 return std::__subject_seq_combinator(
0181 __first,
0182 __last,
0183 __value,
0184 [](const char* __p, const char* __lastp, _Tp& __val, int __b) -> from_chars_result {
0185 using __tl = numeric_limits<_Tp>;
0186
0187 auto __digits = __tl::digits / __from_chars_log2f_lut[__b - 2];
0188 _Tp __x = __in_pattern(*__p++, __b).__val, __y = 0;
0189
0190 for (int __i = 1; __p != __lastp; ++__i, ++__p) {
0191 if (auto __c = __in_pattern(*__p, __b)) {
0192 if (__i < __digits - 1)
0193 __x = __x * __b + __c.__val;
0194 else {
0195 if (!__itoa::__mul_overflowed(__x, __b, __x))
0196 ++__p;
0197 __y = __c.__val;
0198 break;
0199 }
0200 } else
0201 break;
0202 }
0203
0204 if (__p == __lastp || !__in_pattern(*__p, __b)) {
0205 if (__tl::max() - __x >= __y) {
0206 __val = __x + __y;
0207 return {__p, {}};
0208 }
0209 }
0210 return {__p, errc::result_out_of_range};
0211 },
0212 __base);
0213 }
0214
0215 template <typename _Tp, __enable_if_t<is_signed<_Tp>::value, int> = 0>
0216 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0217 __from_chars_integral(const char* __first, const char* __last, _Tp& __value, int __base) {
0218 using __t = decltype(std::__to_unsigned_like(__value));
0219 return std::__sign_combinator(__first, __last, __value, __from_chars_integral<__t>, __base);
0220 }
0221
0222 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
0223 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0224 from_chars(const char* __first, const char* __last, _Tp& __value) {
0225 return std::__from_chars_atoi(__first, __last, __value);
0226 }
0227
0228 template <typename _Tp, __enable_if_t<is_integral<_Tp>::value, int> = 0>
0229 inline _LIBCPP_CONSTEXPR_SINCE_CXX23 _LIBCPP_HIDE_FROM_ABI from_chars_result
0230 from_chars(const char* __first, const char* __last, _Tp& __value, int __base) {
0231 _LIBCPP_ASSERT_UNCATEGORIZED(2 <= __base && __base <= 36, "base not in [2, 36]");
0232 return std::__from_chars_integral(__first, __last, __value, __base);
0233 }
0234 #endif
0235
0236 _LIBCPP_END_NAMESPACE_STD
0237
0238 _LIBCPP_POP_MACROS
0239
0240 #endif