1#ifndef MSTL_CORE_STRING_TO_NUMERICS_HPP__
2#define MSTL_CORE_STRING_TO_NUMERICS_HPP__
3#include "../string/string_view.hpp"
6#include "../config/undef_cmacro.hpp"
11template <
typename T, enable_if_t<is_
signed_v<T>,
int> = 0>
12constexpr T str_to_ints(
const string_view sv,
char** endptr,
int base) {
13 const char* start = sv.data();
14 const size_t len = sv.size();
15 const char*
end = start + len;
18 if (endptr) *endptr =
const_cast<char*
>(start);
22 const char* p = start;
24 const char* start_conversion = p;
27 if (p !=
end && *p ==
'+') {
29 }
else if (p !=
end && *p ==
'-') {
34 if (base != 0 && (base < 2 || base > 36)) {
35 if (endptr) *endptr =
const_cast<char*
>(start_conversion);
40 if (p !=
end && *p ==
'0') {
41 if (p + 1 !=
end && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
52 if (base == 16 && p + 1 <
end && *p ==
'0' && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
59 bool any_converted =
false;
60 bool overflow =
false;
65 if (c >=
'0' && c <=
'9') {
67 }
else if (c >=
'a' && c <=
'z') {
69 }
else if (c >=
'A' && c <=
'Z') {
74 if (digit >= base)
break;
78 if (result < cutoff || (result == cutoff && digit > -cutlim)) {
81 result = result * base - digit;
88 *endptr = any_converted ?
const_cast<char*
>(p) : const_cast<char*>(start_conversion);
91 if (!any_converted)
return 0;
103template <
typename T, enable_if_t<is_
unsigned_v<T>,
int> = 0>
104constexpr T str_to_uints(
const string_view sv,
char** endptr,
int base) {
105 const char* start = sv.data();
106 const size_t len = sv.size();
107 const char*
end = start + len;
110 if (endptr) *endptr =
const_cast<char*
>(start);
114 const char* p = start;
116 const char* start_conversion = p;
119 if (p !=
end && *p ==
'+') {
121 }
else if (p !=
end && *p ==
'-') {
126 if (base != 0 && (base < 2 || base > 36)) {
127 if (endptr) *endptr =
const_cast<char*
>(start_conversion);
132 if (p !=
end && *p ==
'0') {
133 if (p + 1 !=
end && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
144 if (base == 16 && p + 1 <
end && *p ==
'0' && (*(p + 1) ==
'x' || *(p + 1) ==
'X')) {
151 bool any_converted =
false;
152 bool overflow =
false;
155 unsigned int digit = 0;
157 if (c >=
'0' && c <=
'9') {
159 }
else if (c >=
'a' && c <=
'z') {
160 digit = c -
'a' + 10;
161 }
else if (c >=
'A' && c <=
'Z') {
162 digit = c -
'A' + 10;
166 if (digit >=
static_cast<unsigned int>(base))
break;
168 any_converted =
true;
170 if (result > cutoff || (result == cutoff && digit > cutlim)) {
173 result = result * base + digit;
180 *endptr = any_converted ?
const_cast<char*
>(p) : const_cast<char*>(start_conversion);
183 if (!any_converted)
return 0;
196MSTL_CONST_FUNCTION
constexpr T fast_pow10(
int exp) {
197 constexpr T pow10_table[] = {
198 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9,
199 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19,
200 1e20, 1e21, 1e22, 1e23, 1e24, 1e25, 1e26, 1e27, 1e28, 1e29,
204 constexpr T neg_pow10_table[] = {
205 1e0, 1e-1, 1e-2, 1e-3, 1e-4, 1e-5, 1e-6, 1e-7, 1e-8, 1e-9,
206 1e-10, 1e-11, 1e-12, 1e-13, 1e-14, 1e-15, 1e-16, 1e-17, 1e-18, 1e-19,
207 1e-20, 1e-21, 1e-22, 1e-23, 1e-24, 1e-25, 1e-26, 1e-27, 1e-28, 1e-29,
210 constexpr int max_table_exp = 32;
212 if (exp >= 0 && exp <= max_table_exp) {
213 return pow10_table[exp];
215 if (exp < 0 && -exp <= max_table_exp) {
216 return neg_pow10_table[-exp];
218 return static_cast<T
>(
_MSTL power(10.0, exp));
222constexpr T str_to_floats(
const string_view sv,
char** endptr) {
223 const char* start = sv.data();
224 const size_t len = sv.size();
225 const char*
end = start + len;
228 if (endptr) *endptr =
const_cast<char*
>(start);
229 return static_cast<T
>(0);
232 const char* p = start;
234 const char* start_conversion = p;
237 if (p !=
end && *p ==
'+') {
239 }
else if (p !=
end && *p ==
'-') {
244 const char* p_start = p;
246 if (p !=
end && (p[0] ==
'i' || p[0] ==
'I')) {
248 const char c1 = p[1], c2 = p[2];
249 if ((c1 ==
'n' || c1 ==
'N') && (c2 ==
'f' || c2 ==
'F')) {
253 if (endptr) *endptr =
const_cast<char*
>(p);
254 return (
sign < 0) ? -inf_val : inf_val;
260 if (p !=
end && (p[0] ==
'n' || p[0] ==
'N')) {
262 const char c1 = p[1], c2 = p[2];
263 if ((c1 ==
'a' || c1 ==
'A') && (c2 ==
'n' || c2 ==
'N')) {
266 if (p !=
end && *p ==
'(') {
268 while (p !=
end && *p !=
')') ++p;
269 if (p !=
end && *p ==
')') ++p;
271 if (endptr) *endptr =
const_cast<char*
>(p);
282 int digits_count = 0;
283 bool has_digits =
false;
285 while (p !=
end && *p >=
'0' && *p <=
'9') {
288 significand = significand * 10 + (*p -
'0');
296 if (p !=
end && *p ==
'.') {
298 while (p !=
end && *p >=
'0' && *p <=
'9') {
301 significand = significand * 10 + (*p -
'0');
310 if (endptr) *endptr =
const_cast<char*
>(start_conversion);
311 return static_cast<T
>(0);
314 if (p !=
end && (*p ==
'e' || *p ==
'E')) {
317 if (p !=
end && *p ==
'+') {
319 }
else if (p !=
end && *p ==
'-') {
324 if (p !=
end && *p >=
'0' && *p <=
'9') {
326 while (p !=
end && *p >=
'0' && *p <=
'9') {
327 if (exp_val < 10000) {
328 exp_val = exp_val * 10 + (*p -
'0');
332 exponent += exp_sign * exp_val;
335 if (p != start_conversion && (p[-1] ==
'+' || p[-1] ==
'-')) --p;
339 T result = significand;
342 if (exponent > 400) {
343 if (endptr) *endptr =
const_cast<char*
>(p);
345 }
else if (exponent < -400) {
346 if (endptr) *endptr =
const_cast<char*
>(p);
349 result *= fast_pow10<T>(exponent);
355 if (result == inf || result == -inf) {
359 if (endptr) *endptr =
const_cast<char*
>(p);
365constexpr int64_t strtoll(
const string_view sv,
char** endptr,
const int base) {
366 return _INNER str_to_ints<int64_t>(sv, endptr, base);
368constexpr long strtol(
const string_view sv,
char** endptr,
const int base) {
369 return _INNER str_to_ints<long>(sv, endptr, base);
372constexpr uint64_t strtoull(
const string_view sv,
char** endptr,
const int base) {
373 return _INNER str_to_uints<uint64_t>(sv, endptr, base);
375constexpr unsigned long strtoul(
const string_view sv,
char** endptr,
const int base) {
376 return _INNER str_to_uints<unsigned long>(sv, endptr, base);
379constexpr float strtof(
const string_view sv,
char** endptr) {
380 return _INNER str_to_floats<float>(sv, endptr);
382constexpr double strtod(
const string_view sv,
char** endptr) {
383 return _INNER str_to_floats<double>(sv, endptr);
385constexpr long double strtold(
const string_view sv,
char** endptr) {
386 return _INNER str_to_floats<long double>(sv, endptr);
391to_float32(
const string_view sv,
size_t* idx =
nullptr) {
392 char* endptr =
nullptr;
394 if (sv.data() == endptr) {
397 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
402to_float64(
const string_view sv,
size_t* idx =
nullptr) {
403 char* endptr =
nullptr;
405 if (sv.data() == endptr) {
408 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
413to_decimal(
const string_view sv,
size_t* idx =
nullptr) {
414 char* endptr =
nullptr;
416 if (sv.data() == endptr) {
419 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
423MSTL_NODISCARD
constexpr int64_t
424to_int64(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
425 char* endptr =
nullptr;
427 if (sv.data() == endptr) {
430 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
435to_uint64(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
436 char* endptr =
nullptr;
438 if (sv.data() == endptr) {
441 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
445MSTL_NODISCARD
constexpr int32_t
446to_int32(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
447 char* endptr =
nullptr;
449 if (sv.data() == endptr) {
452 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
457to_uint32(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
458 char* endptr =
nullptr;
460 if (sv.data() == endptr) {
463 if (idx) *idx =
static_cast<size_t>(endptr - sv.data());
467MSTL_NODISCARD
constexpr int16_t
468to_int16(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
469 return static_cast<int16_t>(to_int32(sv, idx, base));
473to_uint16(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
474 return static_cast<uint16_t>(to_uint32(sv, idx, base));
477MSTL_NODISCARD
constexpr int8_t
478to_int8(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
479 return static_cast<int8_t>(to_int32(sv, idx, base));
482MSTL_NODISCARD
constexpr uint8_t
483to_uint8(
const string_view sv,
size_t* idx =
nullptr,
const int base = 10) {
484 return static_cast<uint8_t>(to_uint32(sv, idx, base));
static MSTL_NODISCARD constexpr T infinity() noexcept
获取正无穷大表示
static MSTL_NODISCARD constexpr T quiet_nan() noexcept
获取安静nan表示
static MSTL_NODISCARD constexpr T min() noexcept
获取类型的最小值
static MSTL_NODISCARD constexpr T max() noexcept
获取类型的最大值
MSTL_PURE_FUNCTION MSTL_CONSTEXPR14 bool is_space(const CharT c) noexcept
检查字符是否为空白字符
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 bool is_alpha_or_digit(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位有符号整数类型
MSTL_CONSTEXPR14 int sign(const T &value) noexcept
获取数值的符号
MSTL_CONST_FUNCTION MSTL_CONSTEXPR14 T power(const T &x, uint32_t n) noexcept
幂运算
#define _MSTL
全局命名空间MSTL前缀
#define MSTL_END_INNER__
结束inner命名空间
#define _INNER
inner命名空间前缀
#define MSTL_END_NAMESPACE__
结束全局命名空间MSTL
#define MSTL_BEGIN_NAMESPACE__
开始全局命名空间MSTL
#define MSTL_BEGIN_INNER__
开始inner命名空间
typename make_signed< T >::type make_signed_t
make_signed的便捷别名
MSTL_NODISCARD MSTL_ALWAYS_INLINE constexpr decltype(auto) end(Container &cont) noexcept(noexcept(cont.end()))
获取容器的结束迭代器