fix cast string to double bug
This commit is contained in:
parent
1317b808b5
commit
594d0b1b47
93
deps/oblib/src/lib/charset/ob_dtoa.cc
vendored
93
deps/oblib/src/lib/charset/ob_dtoa.cc
vendored
@ -388,60 +388,73 @@ inline bool is_whitespace(const char& c) {
|
||||
return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' || c == '\r';
|
||||
}
|
||||
|
||||
static std::errc ob_fast_strtod(const char *str, char **end, double *result)
|
||||
{
|
||||
std::errc ret = std::errc();
|
||||
if (!(NULL != result
|
||||
&& end != NULL
|
||||
&& ((str != NULL && *end != NULL) || (str == NULL && *end == NULL)))) {
|
||||
ret = std::errc::invalid_argument;
|
||||
} else {
|
||||
*result = 0.0;
|
||||
int len = *end - str;
|
||||
// skip leading and back spaces
|
||||
int i = 0;
|
||||
for (; i < len; ++i) {
|
||||
if (!is_whitespace(str[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= len || (i == len-1 && ('+' == str[i] || '-' == str[i]))) {
|
||||
*end = (char *)str;
|
||||
} else {
|
||||
int j = len - 1;
|
||||
for (; j >= i; j--) {
|
||||
if (!is_whitespace(str[j])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
fast_float::from_chars_result ff_ret = fast_float::from_chars(str + i, str + j + 1, *result);
|
||||
if (ff_ret.ec == std::errc()) {
|
||||
*end = const_cast<char *>(ff_ret.ptr);
|
||||
if (__builtin_isnan(*result) || __builtin_isinf(*result) || __builtin_isinf(-*result)) {
|
||||
*end = (char *)str;
|
||||
*result = 0.0;
|
||||
}
|
||||
} else {
|
||||
ret = ff_ret.ec;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
double ob_strtod(const char *str, char **end, int *error)
|
||||
{
|
||||
char buf[DTOA_BUF_MAX_SIZE];
|
||||
double res = 0.0;
|
||||
if (!(end != NULL && ((str != NULL && *end != NULL) ||
|
||||
(str == NULL && *end == NULL)) &&
|
||||
error != NULL)) {
|
||||
return 0.0;
|
||||
}
|
||||
int len = *end - str;
|
||||
// skip leading and back spaces
|
||||
int i = 0;
|
||||
for (; i < len; ++i) {
|
||||
if (!is_whitespace(str[i])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i >= len || (i == len-1 && ('+' == str[i] || '-' == str[i]))) {
|
||||
*end = (char *)str;
|
||||
} else {
|
||||
int j = len - 1;
|
||||
for (; j >= i; j--) {
|
||||
if (!is_whitespace(str[j])) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// The fast_float::from_chars function cannot handle leading '+' signs.
|
||||
// For example, ObXmlUtil::to_number() might include a '+' for extract_xml expression.
|
||||
if (i < len && '+' == str[i]) {
|
||||
i ++;
|
||||
}
|
||||
fast_float::from_chars_result ret = fast_float::from_chars(str + i, str + j + 1, res);
|
||||
*end = const_cast<char *>(ret.ptr);
|
||||
if (ret.ec == std::errc::result_out_of_range) {
|
||||
res= ob_strtod_int(str, end, error, buf, sizeof(buf));
|
||||
if (std::errc() != ob_fast_strtod(str, end, &res)) {
|
||||
//rollback to call ob_strtod_int if failed to call fast strtod
|
||||
if (!(end != NULL
|
||||
&& ((str != NULL && *end != NULL) || (str == NULL && *end == NULL))
|
||||
&& error != NULL)) {
|
||||
// do nothing
|
||||
} else {
|
||||
char buf[DTOA_BUF_MAX_SIZE];
|
||||
res = ob_strtod_int(str, end, error, buf, sizeof(buf));
|
||||
if (*error != 0) {
|
||||
res = (res < 0 ? -DBL_MAX : DBL_MAX);
|
||||
}
|
||||
// *error = EOVERFLOW;
|
||||
// res = (res < 0 ? -DBL_MAX : DBL_MAX);
|
||||
}
|
||||
if (__builtin_isnan(res) || __builtin_isinf(res) || __builtin_isinf(-res)) {
|
||||
*end = (char *)str;
|
||||
res = 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
double ob_atof(const char *nptr)
|
||||
{
|
||||
int error;
|
||||
const char *end= nptr+65535;
|
||||
const char *end= nptr+65535;
|
||||
return (ob_strtod(nptr, (char**) &end, &error));
|
||||
}
|
||||
|
||||
|
@ -664,4 +664,19 @@ select cast(a as double) from t1;
|
||||
| 0 |
|
||||
| -0 |
|
||||
+-------------------------+
|
||||
select cast('+-4' as double) from dual;
|
||||
+-----------------------+
|
||||
| cast('+-4' as double) |
|
||||
+-----------------------+
|
||||
| 0 |
|
||||
+-----------------------+
|
||||
Warnings:
|
||||
Warning 1292 Truncated incorrect DOUBLE value: '+-4'
|
||||
select cast('+4' as double) from dual;
|
||||
+----------------------+
|
||||
| cast('+4' as double) |
|
||||
+----------------------+
|
||||
| 4 |
|
||||
+----------------------+
|
||||
|
||||
drop table t1;
|
||||
|
@ -178,4 +178,7 @@ select cast(a as float) from t1;
|
||||
select cast(a as double) from t1;
|
||||
--enable_warnings
|
||||
|
||||
select cast('+-4' as double) from dual;
|
||||
select cast('+4' as double) from dual;
|
||||
|
||||
drop table t1;
|
||||
|
Loading…
x
Reference in New Issue
Block a user