Skip to content

Commit 768a017

Browse files
committed
perf_string_to_int
1 parent 42a6d64 commit 768a017

File tree

1 file changed

+17
-29
lines changed
  • native/spark-expr/src/conversion_funcs

1 file changed

+17
-29
lines changed

native/spark-expr/src/conversion_funcs/cast.rs

Lines changed: 17 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1983,29 +1983,23 @@ fn do_cast_string_to_int<
19831983
let trimmed_str = &str[start..end];
19841984
let len = trimmed_str.len();
19851985
let trimmed_bytes = trimmed_str.as_bytes();
1986-
19871986
let mut result: T = T::zero();
1988-
let mut negative = false;
1987+
let mut idx = 0;
1988+
let first_char = trimmed_bytes[0];
1989+
let negative = first_char == b'-';
1990+
if negative || first_char == b'+' {
1991+
idx = 1;
1992+
if len == 1{
1993+
return none_or_err(eval_mode, type_name, str);
1994+
}
1995+
}
1996+
19891997
let radix = T::from(10);
19901998
let stop_value = min_value / radix;
19911999
let mut parse_sign_and_digits = true;
19922000

1993-
for i in 0..len {
1994-
let ch = trimmed_bytes[i];
2001+
for &ch in &trimmed_bytes[idx..] {
19952002
if parse_sign_and_digits {
1996-
if i == 0 {
1997-
negative = ch == b'-';
1998-
let positive = ch == b'+';
1999-
if negative || positive {
2000-
if i + 1 == len {
2001-
// input string is just "+" or "-"
2002-
return none_or_err(eval_mode, type_name, str);
2003-
}
2004-
// consume this char
2005-
continue;
2006-
}
2007-
}
2008-
20092003
if ch == b'.' {
20102004
if eval_mode == EvalMode::Legacy {
20112005
// truncate decimal in legacy mode
@@ -2016,11 +2010,11 @@ fn do_cast_string_to_int<
20162010
}
20172011
}
20182012

2019-
let digit = if ch.is_ascii_digit() {
2020-
(ch as u32) - ('0' as u32)
2021-
} else {
2013+
if !ch.is_ascii_digit() {
20222014
return none_or_err(eval_mode, type_name, str);
2023-
};
2015+
}
2016+
let digit = T::from((ch - b'0') as i32);
2017+
result = result * radix - digit;
20242018

20252019
// We are going to process the new digit and accumulate the result. However, before
20262020
// doing this, if the result is already smaller than the
@@ -2029,17 +2023,11 @@ fn do_cast_string_to_int<
20292023
if result < stop_value {
20302024
return none_or_err(eval_mode, type_name, str);
20312025
}
2032-
20332026
// Since the previous result is greater than or equal to stopValue(Integer.MIN_VALUE /
20342027
// radix), we can just use `result > 0` to check overflow. If result
20352028
// overflows, we should stop
2036-
let v = result * radix;
2037-
let digit = (digit as i32).into();
2038-
match v.checked_sub(&digit) {
2039-
Some(x) if x <= T::zero() => result = x,
2040-
_ => {
2041-
return none_or_err(eval_mode, type_name, str);
2042-
}
2029+
if result > T::zero() {
2030+
return none_or_err(eval_mode, type_name, str);
20432031
}
20442032
} else {
20452033
// make sure fractional digits are valid digits but ignore them

0 commit comments

Comments
 (0)