Skip to content

Commit

Permalink
atoi implementation based on i64 on Spytheman\'s request. Also add mo…
Browse files Browse the repository at this point in the history
…re specific errors messages. Use min_int and max_int defined in builtin.
  • Loading branch information
Bruno-Vdr committed Feb 16, 2025
1 parent 99f759f commit 52c6265
Show file tree
Hide file tree
Showing 2 changed files with 2 additions and 75 deletions.
75 changes: 1 addition & 74 deletions vlib/strconv/atoi.v
Original file line number Diff line number Diff line change
Expand Up @@ -219,55 +219,7 @@ pub fn parse_int(_s string, base int, _bit_size int) !i64 {

// atoi is equivalent to parse_int(s, 10, 0), converted to type int.
// It follows V scanner as much as observed.
@[direct_array_access]
pub fn atoi32(s string) !int {
if s == '' {
return error('strconv.atoi: parsing "": empty string')
}

mut start_idx := 0
mut sign := 1

if s[0] == `-` || s[0] == `+` {
start_idx++
if s[0] == `-` {
sign = -1
}
}

if s.len - start_idx < 1 {
return error('strconv.atoi: parsing "${s}": invalid syntax')
}

if s[start_idx] == `_` || s[s.len - 1] == `_` {
return error('strconv.atoi: parsing "${s}": invalid syntax')
}

mut x := int(0)
mut underscored := false
for i in start_idx .. s.len {
c := s[i] - `0`
if c == 47 { // 47 = Ascii(`_`) - ascii(`0`) = 95 - 48.
if underscored == true { // Two consecutives underscore
return error('strconv.atoi: parsing "${s}": consecutives underscores are not allowed')
}
underscored = true
continue // Skip underscore
} else {
if c > 9 {
return error('strconv.atoi: parsing "${s}": invalid radix 10 character')
}
underscored = false
x = safe_mul10_32bits(x) or { return error('strconv.atoi: parsing "${s}": ${err}') }
x = safe_add_32bits(x, int(c * sign)) or {
return error('strconv.atoi: parsing "${s}": ${err}')
}
}
}
println('Final = ${int(x)}')
return int(x)
}

// @[direct_array_access]
@[direct_array_access]
pub fn atoi(s string) !int {
if s == '' {
Expand Down Expand Up @@ -319,28 +271,3 @@ pub fn atoi(s string) !int {
}
return int(x)
}

// safe_add32 performs a signed 32 bits addition and returns an error
// in case of overflow or underflow.
@[inline]
fn safe_add_32bits(a int, b int) !int {
if a > 0 && b > (max_int - a) {
return error('integer overflow')
} else if a < 0 && b < (min_int - a) {
return error('integer underflow')
}
return int(a + b)
}

// safe_mul10 performs a * 10 multiplication and returns an error
// in case of overflow or underflow.
@[inline]
fn safe_mul10_32bits(a int) !int {
if a > 0 && a > (max_int / 10) {
return error('integer overflow')
}
if a < 0 && a < (min_int / 10) {
return error('integer underflow')
}
return int(a * 10)
}
2 changes: 1 addition & 1 deletion vlib/strconv/atoi_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ fn test_atoi() {

// Check that extracted int value matches its string.
for v in ok {
println('Parsing ${v.str_value} should equals ${v.int_value}')
// println('Parsing ${v.str_value} should equals ${v.int_value}')
assert strconv.atoi(v.str_value)! == v.int_value
}

Expand Down

0 comments on commit 52c6265

Please sign in to comment.