atoi.v: add common_parse_uint2 with error code return values (#6550)
parent
d93b0f047a
commit
c5e46c9e55
|
@ -19,11 +19,23 @@ pub fn byte_to_lower(c byte) byte {
|
||||||
// common_parse_uint is called by parse_uint and allows the parsing
|
// common_parse_uint is called by parse_uint and allows the parsing
|
||||||
// to stop on non or invalid digit characters and return the result so far
|
// to stop on non or invalid digit characters and return the result so far
|
||||||
pub fn common_parse_uint(s string, _base int, _bit_size int, error_on_non_digit bool, error_on_high_digit bool) u64 {
|
pub fn common_parse_uint(s string, _base int, _bit_size int, error_on_non_digit bool, error_on_high_digit bool) u64 {
|
||||||
|
result, error := common_parse_uint2(s, _base, _bit_size)
|
||||||
|
if error != 0 {
|
||||||
|
if error > 0 && (error_on_non_digit || error_on_high_digit) {
|
||||||
|
return u64(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// the first returned value contains the parsed value,
|
||||||
|
// the second returned value contains the error code (0 = OK, >1 = index of first non-parseable character + 1, -1 = wrong base, -2 = wrong bit size, -3 = overflow)
|
||||||
|
pub fn common_parse_uint2(s string, _base int, _bit_size int) (u64, int) {
|
||||||
mut bit_size := _bit_size
|
mut bit_size := _bit_size
|
||||||
mut base := _base
|
mut base := _base
|
||||||
if s.len < 1 || !underscore_ok(s) {
|
if s.len < 1 || !underscore_ok(s) {
|
||||||
// return error('parse_uint: syntax error $s')
|
// return error('parse_uint: syntax error $s')
|
||||||
return u64(0)
|
return u64(0), 1
|
||||||
}
|
}
|
||||||
base0 := base == 0
|
base0 := base == 0
|
||||||
mut start_index := 0
|
mut start_index := 0
|
||||||
|
@ -59,14 +71,14 @@ pub fn common_parse_uint(s string, _base int, _bit_size int, error_on_non_digit
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// return error('parse_uint: base error $s - $base')
|
// return error('parse_uint: base error $s - $base')
|
||||||
return u64(0)
|
return u64(0), -1
|
||||||
}
|
}
|
||||||
if bit_size == 0 {
|
if bit_size == 0 {
|
||||||
bit_size = int_size
|
bit_size = int_size
|
||||||
}
|
}
|
||||||
else if bit_size < 0 || bit_size > 64 {
|
else if bit_size < 0 || bit_size > 64 {
|
||||||
// return error('parse_uint: bitsize error $s - $bit_size')
|
// return error('parse_uint: bitsize error $s - $bit_size')
|
||||||
return u64(0)
|
return u64(0), -2
|
||||||
}
|
}
|
||||||
// Cutoff is the smallest number such that cutoff*base > maxUint64.
|
// Cutoff is the smallest number such that cutoff*base > maxUint64.
|
||||||
// Use compile-time constants for common cases.
|
// Use compile-time constants for common cases.
|
||||||
|
@ -90,42 +102,26 @@ pub fn common_parse_uint(s string, _base int, _bit_size int, error_on_non_digit
|
||||||
d = cl - `a` + 10
|
d = cl - `a` + 10
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if error_on_non_digit {
|
return n, i + 1
|
||||||
// return error('parse_uint: syntax error $s')
|
|
||||||
return u64(0)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if d >= byte(base) {
|
if d >= byte(base) {
|
||||||
if error_on_high_digit {
|
return n, i + 1
|
||||||
// return error('parse_uint: syntax error $s')
|
|
||||||
return u64(0)
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if n >= cutoff {
|
if n >= cutoff {
|
||||||
// n*base overflows
|
// n*base overflows
|
||||||
// return error('parse_uint: range error $s')
|
// return error('parse_uint: range error $s')
|
||||||
return max_val
|
return max_val, -3
|
||||||
}
|
}
|
||||||
n *= u64(base)
|
n *= u64(base)
|
||||||
n1 := n + u64(d)
|
n1 := n + u64(d)
|
||||||
if n1 < n || n1 > max_val {
|
if n1 < n || n1 > max_val {
|
||||||
// n+v overflows
|
// n+v overflows
|
||||||
// return error('parse_uint: range error $s')
|
// return error('parse_uint: range error $s')
|
||||||
return max_val
|
return max_val, -3
|
||||||
}
|
}
|
||||||
n = n1
|
n = n1
|
||||||
}
|
}
|
||||||
if underscores && !underscore_ok(s) {
|
return n, 0
|
||||||
// return error('parse_uint: syntax error $s')
|
|
||||||
return u64(0)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse_uint is like parse_int but for unsigned numbers.
|
// parse_uint is like parse_int but for unsigned numbers.
|
||||||
|
|
|
@ -26,3 +26,37 @@ fn test_parse_int() {
|
||||||
assert strconv.parse_int('123', 10, 65) == 0
|
assert strconv.parse_int('123', 10, 65) == 0
|
||||||
assert strconv.parse_int('123', 10, -1) == 0
|
assert strconv.parse_int('123', 10, -1) == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn test_common_parse_uint2() {
|
||||||
|
mut result, mut error := strconv.common_parse_uint2('1', 10, 8)
|
||||||
|
assert result == 1
|
||||||
|
assert error == 0
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('123', 10, 8)
|
||||||
|
assert result == 123
|
||||||
|
assert error == 0
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('123', 10, 65)
|
||||||
|
assert result == 0
|
||||||
|
assert error == -2
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('123', 10, -1)
|
||||||
|
assert result == 0
|
||||||
|
assert error == -2
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('', 10, 8)
|
||||||
|
assert result == 0
|
||||||
|
assert error == 1
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('1a', 10, 8)
|
||||||
|
assert result == 1
|
||||||
|
assert error == 2
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('12a', 10, 8)
|
||||||
|
assert result == 12
|
||||||
|
assert error == 3
|
||||||
|
|
||||||
|
result, error = strconv.common_parse_uint2('123a', 10, 8)
|
||||||
|
assert result == 123
|
||||||
|
assert error == 4
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue