1#ifndef NEFORCE_CORE_STRING_TO_NUMERICS_HPP__
2#define NEFORCE_CORE_STRING_TO_NUMERICS_HPP__
20NEFORCE_BEGIN_NAMESPACE__
40 const char* start = sv.
data();
41 const size_t len = sv.
size();
42 const char*
end = start + len;
45 if (endptr !=
nullptr) {
46 *endptr =
const_cast<char*
>(start);
51 const char* p = start;
55 const char* start_conversion = p;
58 if (p !=
end && *p ==
'+') {
60 }
else if (p !=
end && *p ==
'-') {
65 if (base != 0 && (base < 2 || base > 36)) {
66 if (endptr !=
nullptr) {
67 *endptr =
const_cast<char*
>(start_conversion);
73 if (p !=
end && *p ==
'0') {
74 if (p + 1 !=
end && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
83 }
else if (base == 16 && p + 1 <
end && *p ==
'0' && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
89 const UT limit = (
sign > 0) ? umax : umin_abs;
90 const UT cutoff = limit /
static_cast<UT
>(base);
91 const UT cutlim = limit %
static_cast<UT
>(base);
94 bool any_converted =
false;
95 bool overflow =
false;
100 if (c >=
'0' && c <=
'9') {
101 digit =
static_cast<UT
>(c -
'0');
102 }
else if (c >=
'a' && c <=
'z') {
103 digit =
static_cast<UT
>(c -
'a') +
static_cast<UT
>(10);
104 }
else if (c >=
'A' && c <=
'Z') {
105 digit =
static_cast<UT
>(c -
'A') +
static_cast<UT
>(10);
109 if (digit >=
static_cast<UT
>(base)) {
113 any_converted =
true;
115 if (result > cutoff || (result == cutoff && digit > cutlim)) {
118 result = result *
static_cast<UT
>(base) + digit;
124 if (endptr !=
nullptr) {
125 *endptr = any_converted ?
const_cast<char*
>(p) : const_cast<char*>(start_conversion);
128 if (!any_converted) {
137 return static_cast<T
>(result);
139 if (result == umin_abs) {
142 return static_cast<T
>(~result +
static_cast<UT
>(1));
158 const char* start = sv.
data();
159 const size_t len = sv.
size();
160 const char*
end = start + len;
163 if (endptr !=
nullptr) {
164 *endptr =
const_cast<char*
>(start);
169 const char* p = start;
173 const char* start_conversion = p;
176 if (p !=
end && *p ==
'+') {
178 }
else if (p !=
end && *p ==
'-') {
183 if (base != 0 && (base < 2 || base > 36)) {
184 if (endptr !=
nullptr) {
185 *endptr =
const_cast<char*
>(start_conversion);
191 if (p !=
end && *p ==
'0') {
192 if (p + 1 !=
end && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
203 if (base == 16 && p + 1 <
end && *p ==
'0' && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
210 bool any_converted =
false;
211 bool overflow =
false;
216 if (c >=
'0' && c <=
'9') {
217 digit =
static_cast<T
>(c -
'0');
218 }
else if (c >=
'a' && c <=
'z') {
219 digit =
static_cast<T
>(c -
'a') +
static_cast<T
>(10);
220 }
else if (c >=
'A' && c <=
'Z') {
221 digit =
static_cast<T
>(c -
'A') +
static_cast<T
>(10);
225 if (digit >=
static_cast<T
>(base)) {
229 any_converted =
true;
231 if (result > cutoff || (result == cutoff && digit > cutlim)) {
234 result = result *
static_cast<T
>(base) + digit;
240 if (endptr !=
nullptr) {
241 *endptr = any_converted ?
const_cast<char*
>(p) : const_cast<char*>(start_conversion);
244 if (!any_converted) {
245 return static_cast<T
>(0);
255 return static_cast<T
>(-
static_cast<typename make_signed<T>::type
>(result));
269NEFORCE_CONST_FUNCTION
constexpr T fast_pow10(
int exp) {
270 constexpr T pow10_table[] = {1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10,
271 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21,
272 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29, 1e30, 1e31, 1e32};
273 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,
274 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19, 1e-20, 1e-21,
275 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29, 1e-30, 1e-31, 1e-32};
276 constexpr int max_table_exp = 32;
278 if (exp >= 0 && exp <= max_table_exp) {
280 return pow10_table[exp];
282 if (exp < 0 && -exp <= max_table_exp) {
284 return neg_pow10_table[-exp];
288 return static_cast<T
>(_NEFORCE
power(T(10),
static_cast<uint32_t>(exp)));
290 return static_cast<T
>(1) /
static_cast<T
>(_NEFORCE
power(T(10),
static_cast<uint32_t>(-exp)));
305 const char* start = sv.
data();
306 const size_t len = sv.
size();
307 const char*
end = start + len;
311 *endptr =
const_cast<char*
>(start);
313 return static_cast<T
>(0);
316 const char* p = start;
320 const char* start_conversion = p;
323 if (p !=
end && *p ==
'+') {
325 }
else if (p !=
end && *p ==
'-') {
330 const char* p_start = p;
332 if (p !=
end && (p[0] ==
'i' || p[0] ==
'I')) {
336 if ((p[1] ==
'n' || p[1] ==
'N') && (p[2] ==
'f' || p[2] ==
'F') && (p[3] ==
'i' || p[3] ==
'I') &&
337 (p[4] ==
'n' || p[4] ==
'N') && (p[5] ==
'i' || p[5] ==
'I') && (p[6] ==
't' || p[6] ==
'T') &&
338 (p[7] ==
'y' || p[7] ==
'Y')) {
346 if (!is_inf && p + 3 <=
end) {
347 if ((p[1] ==
'n' || p[1] ==
'N') && (p[2] ==
'f' || p[2] ==
'F')) {
357 *endptr =
const_cast<char*
>(p);
360 return (
sign < 0) ? -inf_val : inf_val;
364 if (p !=
end && (p[0] ==
'n' || p[0] ==
'N')) {
366 const char c1 = p[1], c2 = p[2];
367 if ((c1 ==
'a' || c1 ==
'A') && (c2 ==
'n' || c2 ==
'N')) {
371 if (p !=
end && *p ==
'(') {
373 while (p !=
end && *p !=
')') {
376 if (p !=
end && *p ==
')') {
381 *endptr =
const_cast<char*
>(p);
393 int digits_count = 0;
394 bool has_digits =
false;
396 while (p !=
end && *p >=
'0' && *p <=
'9') {
399 significand = significand *
static_cast<T
>(10) +
static_cast<T
>(*p -
'0');
407 if (p !=
end && *p ==
'.') {
409 while (p !=
end && *p >=
'0' && *p <=
'9') {
412 significand = significand *
static_cast<T
>(10) +
static_cast<T
>(*p -
'0');
422 *endptr =
const_cast<char*
>(start_conversion);
424 return static_cast<T
>(0);
427 if (p !=
end && (*p ==
'e' || *p ==
'E')) {
428 const char* e_pos = p;
432 if (p !=
end && *p ==
'+') {
434 }
else if (p !=
end && *p ==
'-') {
439 if (p !=
end && *p >=
'0' && *p <=
'9') {
441 while (p !=
end && *p >=
'0' && *p <=
'9') {
442 if (exp_val < 100000) {
443 exp_val = exp_val * 10 + (*p -
'0');
447 exponent += exp_sign * exp_val;
453 T result = significand;
458 constexpr int max_table_exp = 32;
460 if (exponent > max_exp || exponent > max_table_exp) {
462 *endptr =
const_cast<char*
>(p);
465 }
else if (exponent < min_exp || exponent < -max_table_exp) {
467 *endptr =
const_cast<char*
>(p);
469 return static_cast<T
>(0);
471 result *= fast_pow10<T>(exponent);
476 if (result == inf || result == -inf) {
478 *endptr =
const_cast<char*
>(p);
480 return (
sign > 0) ? inf : -inf;
483 result = (
sign > 0) ? result : -result;
486 *endptr =
const_cast<char*
>(p);
508 char* endptr =
nullptr;
509 const float32_t num = inner::str_to_floats<float32_t>(sv, &endptr);
510 if (sv.
data() == endptr) {
513 if (idx !=
nullptr) {
514 *idx =
static_cast<size_t>(endptr - sv.
data());
527 char* endptr =
nullptr;
528 const float64_t num = inner::str_to_floats<float64_t>(sv, &endptr);
529 if (sv.
data() == endptr) {
532 if (idx !=
nullptr) {
533 *idx =
static_cast<size_t>(endptr - sv.
data());
546 char* endptr =
nullptr;
547 const decimal_t num = inner::str_to_floats<decimal_t>(sv, &endptr);
548 if (sv.
data() == endptr) {
551 if (idx !=
nullptr) {
552 *idx =
static_cast<size_t>(endptr - sv.
data());
566 char* endptr =
nullptr;
567 const int64_t num = inner::str_to_ints<int64_t>(sv, &endptr, base);
568 if (sv.
data() == endptr) {
571 if (idx !=
nullptr) {
572 *idx =
static_cast<size_t>(endptr - sv.
data());
586 char* endptr =
nullptr;
587 const uint64_t num = inner::str_to_uints<uint64_t>(sv, &endptr, base);
588 if (sv.
data() == endptr) {
591 if (idx !=
nullptr) {
592 *idx =
static_cast<size_t>(endptr - sv.
data());
606 char* endptr =
nullptr;
607 const int32_t num = inner::str_to_ints<int32_t>(sv, &endptr, base);
608 if (sv.
data() == endptr) {
611 if (idx !=
nullptr) {
612 *idx =
static_cast<size_t>(endptr - sv.
data());
626 char* endptr =
nullptr;
627 const uint32_t num = inner::str_to_uints<uint32_t>(sv, &endptr, base);
628 if (sv.
data() == endptr) {
631 if (idx !=
nullptr) {
632 *idx =
static_cast<size_t>(endptr - sv.
data());
651 return static_cast<int16_t>(val);
684 return static_cast<int8_t>(val);
700 return static_cast<uint8_t>(val);
705NEFORCE_END_NAMESPACE__
constexpr size_type size() const noexcept
获取字符串长度
constexpr const_pointer data() const noexcept
获取底层数据指针
static constexpr T infinity() noexcept
获取正无穷大表示
static constexpr T max() noexcept
获取类型的最大值
static constexpr T quiet_nan() noexcept
获取安静nan表示
static constexpr T min() noexcept
获取类型的最小值
constexpr bool is_alpha_or_digit(const CharT c) noexcept
检查字符是否为字母或数字
constexpr 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位有符号整数类型
constexpr int sign(const T &value) noexcept
获取数值的符号
constexpr T power(const T &x, uint32_t n) noexcept
幂运算
typename make_unsigned< T >::type make_unsigned_t
make_unsigned的便捷别名
constexpr int16_t to_int16(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为16位有符号整数
constexpr decimal_t to_decimal(const string_view sv, size_t *idx=nullptr)
将字符串转换为decimal浮点数
constexpr float64_t to_float64(const string_view sv, size_t *idx=nullptr)
将字符串转换为64位浮点数
constexpr int32_t to_int32(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为32位有符号整数
constexpr uint64_t to_uint64(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为64位无符号整数
constexpr uint32_t to_uint32(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为32位无符号整数
constexpr float32_t to_float32(const string_view sv, size_t *idx=nullptr)
将字符串转换为32位浮点数
constexpr int8_t to_int8(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为8位有符号整数
constexpr uint16_t to_uint16(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为16位无符号整数
constexpr int64_t to_int64(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为64位有符号整数
constexpr uint8_t to_uint8(const string_view sv, size_t *idx=nullptr, const int base=10)
将字符串转换为8位无符号整数
basic_string_view< char > string_view
字符字符串视图
constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器
typename enable_if< Test, T >::type enable_if_t
enable_if的便捷别名