1#ifndef NEFORCE_CORE_STRING_TO_NUMERICS_HPP__
2#define NEFORCE_CORE_STRING_TO_NUMERICS_HPP__
21NEFORCE_BEGIN_NAMESPACE__
41 const char* start = sv.
data();
42 const size_t len = sv.
size();
43 const char*
end = start + len;
47 *endptr =
const_cast<char*
>(start);
52 const char* p = start;
56 const char* start_conversion = p;
59 if (p !=
end && *p ==
'+') {
61 }
else if (p !=
end && *p ==
'-') {
66 if (base != 0 && (base < 2 || base > 36)) {
68 *endptr =
const_cast<char*
>(start_conversion);
74 if (p !=
end && *p ==
'0') {
75 if (p + 1 !=
end && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
84 }
else if (base == 16 && p + 1 <
end && *p ==
'0' && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
90 const UT limit = (
sign > 0) ? umax : umin_abs;
91 const UT cutoff = limit /
static_cast<UT
>(base);
92 const UT cutlim = limit %
static_cast<UT
>(base);
95 bool any_converted =
false;
96 bool overflow =
false;
101 if (c >=
'0' && c <=
'9') {
102 digit =
static_cast<uint32_t>(c -
'0');
103 }
else if (c >=
'a' && c <=
'z') {
104 digit =
static_cast<uint32_t>(c -
'a' + 10);
105 }
else if (c >=
'A' && c <=
'Z') {
106 digit =
static_cast<uint32_t>(c -
'A' + 10);
110 if (digit >=
static_cast<uint32_t>(base)) {
114 any_converted =
true;
116 if (result > cutoff || (result == cutoff &&
static_cast<UT
>(digit) > cutlim)) {
119 result = result *
static_cast<UT
>(base) +
static_cast<UT
>(digit);
126 *endptr = any_converted ?
const_cast<char*
>(p) : const_cast<char*>(start_conversion);
129 if (!any_converted) {
138 return static_cast<T
>(result);
140 if (result == umin_abs) {
143 return static_cast<T
>(~result +
static_cast<UT
>(1));
160 const char* start = sv.
data();
161 const size_t len = sv.
size();
162 const char*
end = start + len;
166 *endptr =
const_cast<char*
>(start);
171 const char* p = start;
175 const char* start_conversion = p;
178 if (p !=
end && *p ==
'+') {
180 }
else if (p !=
end && *p ==
'-') {
185 if (base != 0 && (base < 2 || base > 36)) {
187 *endptr =
const_cast<char*
>(start_conversion);
193 if (p !=
end && *p ==
'0') {
194 if (p + 1 !=
end && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
205 if (base == 16 && p + 1 <
end && *p ==
'0' && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
212 bool any_converted =
false;
213 bool overflow =
false;
216 unsigned int digit = 0;
218 if (c >=
'0' && c <=
'9') {
220 }
else if (c >=
'a' && c <=
'z') {
221 digit = c -
'a' + 10;
222 }
else if (c >=
'A' && c <=
'Z') {
223 digit = c -
'A' + 10;
227 if (digit >=
static_cast<unsigned int>(base)) {
231 any_converted =
true;
233 if (result > cutoff || (result == cutoff && digit > cutlim)) {
236 result = result * base + digit;
243 *endptr = any_converted ?
const_cast<char*
>(p) : const_cast<char*>(start_conversion);
246 if (!any_converted) {
271NEFORCE_CONST_FUNCTION
constexpr T fast_pow10(
int exp) {
272 constexpr T pow10_table[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
273 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21,
274 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32};
275 constexpr T neg_pow10_table[] = {1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9, 1e-10,
276 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19, 1e-20, 1e-21,
277 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29, 1e-30, 1e-31, 1e-32};
278 constexpr int max_table_exp = 32;
280 if (exp >= 0 && exp <= max_table_exp) {
281 return pow10_table[exp];
283 if (exp < 0 && -exp <= max_table_exp) {
284 return neg_pow10_table[-exp];
286 return static_cast<T
>(
power(10.0, exp));
301 const char* start = sv.
data();
302 const size_t len = sv.
size();
303 const char*
end = start + len;
307 *endptr =
const_cast<char*
>(start);
309 return static_cast<T
>(0);
312 const char* p = start;
316 const char* start_conversion = p;
319 if (p !=
end && *p ==
'+') {
321 }
else if (p !=
end && *p ==
'-') {
326 const char* p_start = p;
328 if (p !=
end && (p[0] ==
'i' || p[0] ==
'I')) {
330 const char c1 = p[1], c2 = p[2];
331 if ((c1 ==
'n' || c1 ==
'N') && (c2 ==
'f' || c2 ==
'F')) {
336 *endptr =
const_cast<char*
>(p);
339 return (
sign < 0) ? -inf_val : inf_val;
345 if (p !=
end && (p[0] ==
'n' || p[0] ==
'N')) {
347 const char c1 = p[1], c2 = p[2];
348 if ((c1 ==
'a' || c1 ==
'A') && (c2 ==
'n' || c2 ==
'N')) {
352 if (p !=
end && *p ==
'(') {
354 while (p !=
end && *p !=
')') {
357 if (p !=
end && *p ==
')') {
362 *endptr =
const_cast<char*
>(p);
374 int digits_count = 0;
375 bool has_digits =
false;
377 while (p !=
end && *p >=
'0' && *p <=
'9') {
380 significand = significand *
static_cast<T
>(10) +
static_cast<T
>(*p -
'0');
388 if (p !=
end && *p ==
'.') {
390 while (p !=
end && *p >=
'0' && *p <=
'9') {
393 significand = significand *
static_cast<T
>(10) +
static_cast<T
>(*p -
'0');
403 *endptr =
const_cast<char*
>(start_conversion);
405 return static_cast<T
>(0);
408 if (p !=
end && (*p ==
'e' || *p ==
'E')) {
409 const char* e_pos = p;
413 if (p !=
end && *p ==
'+') {
415 }
else if (p !=
end && *p ==
'-') {
420 if (p !=
end && *p >=
'0' && *p <=
'9') {
422 while (p !=
end && *p >=
'0' && *p <=
'9') {
423 if (exp_val < 100000) {
424 exp_val = exp_val * 10 + (*p -
'0');
428 exponent += exp_sign * exp_val;
434 T result = significand;
440 if (exponent > max_exp) {
442 *endptr =
const_cast<char*
>(p);
445 }
else if (exponent < min_exp) {
447 *endptr =
const_cast<char*
>(p);
449 return static_cast<T
>(0);
451 result *= fast_pow10<T>(exponent);
456 if (result == inf || result == -inf) {
458 *endptr =
const_cast<char*
>(p);
460 return (
sign > 0) ? inf : -inf;
463 result = (
sign > 0) ? result : -result;
466 *endptr =
const_cast<char*
>(p);
488 char* endptr =
nullptr;
489 const float32_t num = inner::str_to_floats<float>(sv, &endptr);
490 if (sv.
data() == endptr) {
494 *idx =
static_cast<size_t>(endptr - sv.
data());
507 char* endptr =
nullptr;
508 const float64_t num = inner::str_to_floats<double>(sv, &endptr);
509 if (sv.
data() == endptr) {
513 *idx =
static_cast<size_t>(endptr - sv.
data());
526 char* endptr =
nullptr;
527 const decimal_t num = inner::str_to_floats<long double>(sv, &endptr);
528 if (sv.
data() == endptr) {
532 *idx =
static_cast<size_t>(endptr - sv.
data());
546 char* endptr =
nullptr;
547 const int64_t num = inner::str_to_ints<int64_t>(sv, &endptr, base);
548 if (sv.
data() == endptr) {
552 *idx =
static_cast<size_t>(endptr - sv.
data());
566 char* endptr =
nullptr;
567 const uint64_t num = inner::str_to_uints<uint64_t>(sv, &endptr, base);
568 if (sv.
data() == endptr) {
572 *idx =
static_cast<size_t>(endptr - sv.
data());
586 char* endptr =
nullptr;
587 const int32_t num = inner::str_to_ints<int>(sv, &endptr, base);
588 if (sv.
data() == endptr) {
592 *idx =
static_cast<size_t>(endptr - sv.
data());
606 char* endptr =
nullptr;
607 const uint32_t num = inner::str_to_uints<uint32_t>(sv, &endptr, base);
608 if (sv.
data() == endptr) {
612 *idx =
static_cast<size_t>(endptr - sv.
data());
631 return static_cast<int16_t>(val);
664 return static_cast<int8_t>(val);
680 return static_cast<uint8_t>(val);
685NEFORCE_END_NAMESPACE__
NEFORCE_NODISCARD constexpr size_type size() const noexcept
获取字符串长度
NEFORCE_NODISCARD constexpr const_pointer data() const noexcept
获取底层数据指针
static NEFORCE_NODISCARD constexpr T quiet_nan() noexcept
获取安静nan表示
static NEFORCE_NODISCARD constexpr T min() noexcept
获取类型的最小值
static NEFORCE_NODISCARD constexpr T max() noexcept
获取类型的最大值
static NEFORCE_NODISCARD constexpr T infinity() noexcept
获取正无穷大表示
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 bool is_alpha_or_digit(const CharT c) noexcept
检查字符是否为字母或数字
NEFORCE_PURE_FUNCTION NEFORCE_CONSTEXPR14 bool is_space(const CharT c) noexcept
检查字符是否为空白字符
constexpr const T & min(const T &a, const T &b, Compare comp) noexcept(noexcept(comp(b, a)))
返回两个值中的较小者
unsigned char uint8_t
8位无符号整数类型
float float32_t
32位单精度浮点数类型
unsigned int uint32_t
32位无符号整数类型
long double decimal_t
扩展精度浮点数类型
long long int64_t
64位有符号整数类型
double float64_t
64位双精度浮点数类型
unsigned short uint16_t
16位无符号整数类型
unsigned long long uint64_t
64位无符号整数类型
signed char int8_t
8位有符号整数类型
NEFORCE_CONST_FUNCTION NEFORCE_CONSTEXPR14 T power(const T &x, uint32_t n) noexcept
幂运算
NEFORCE_CONSTEXPR14 int sign(const T &value) noexcept
获取数值的符号
typename make_unsigned< T >::type make_unsigned_t
make_unsigned的便捷别名
typename make_signed< T >::type make_signed_t
make_signed的便捷别名
NEFORCE_NODISCARD constexpr decimal_t to_decimal(const string_view sv, size_t *idx=nullptr)
将字符串转换为decimal浮点数
NEFORCE_NODISCARD constexpr uint16_t to_uint16(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为16位无符号整数
NEFORCE_NODISCARD constexpr float64_t to_float64(const string_view sv, size_t *idx=nullptr)
将字符串转换为64位浮点数
NEFORCE_NODISCARD constexpr float32_t to_float32(const string_view sv, size_t *idx=nullptr)
将字符串转换为32位浮点数
NEFORCE_NODISCARD constexpr uint32_t to_uint32(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为32位无符号整数
NEFORCE_NODISCARD constexpr int64_t to_int64(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为64位有符号整数
NEFORCE_NODISCARD constexpr int8_t to_int8(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为8位有符号整数
NEFORCE_NODISCARD constexpr int16_t to_int16(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为16位有符号整数
NEFORCE_NODISCARD constexpr int32_t to_int32(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为32位有符号整数
NEFORCE_NODISCARD constexpr uint64_t to_uint64(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为64位无符号整数
NEFORCE_NODISCARD constexpr uint8_t to_uint8(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为8位无符号整数
basic_string_view< char > string_view
字符字符串视图
NEFORCE_NODISCARD NEFORCE_ALWAYS_INLINE constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名