strconv: make string.int() stop parsing on invalid digit
parent
9374168b26
commit
f6ec1b29f9
|
@ -61,7 +61,7 @@ pub:
|
||||||
|
|
||||||
pub fn vstrlen(s byteptr) int {
|
pub fn vstrlen(s byteptr) int {
|
||||||
return C.strlen(*char(s))
|
return C.strlen(*char(s))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Converts a C string to a V string.
|
// Converts a C string to a V string.
|
||||||
// String data is reused, not copied.
|
// String data is reused, not copied.
|
||||||
|
@ -187,11 +187,11 @@ pub fn (s string) replace(rep, with string) string {
|
||||||
|
|
||||||
|
|
||||||
pub fn (s string) int() int {
|
pub fn (s string) int() int {
|
||||||
return int(strconv.parse_int(s,0,32))
|
return int(strconv.common_parse_int(s,0,32, false, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) i64() i64 {
|
pub fn (s string) i64() i64 {
|
||||||
return strconv.parse_int(s, 0, 64)
|
return strconv.common_parse_int(s, 0, 64, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) f32() f32 {
|
pub fn (s string) f32() f32 {
|
||||||
|
@ -203,11 +203,11 @@ pub fn (s string) f64() f64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) u32() u32 {
|
pub fn (s string) u32() u32 {
|
||||||
return u32(strconv.parse_uint(s, 0, 32))
|
return u32(strconv.common_parse_uint(s, 0, 32, false, false))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (s string) u64() u64 {
|
pub fn (s string) u64() u64 {
|
||||||
return strconv.parse_uint(s, 0, 64)
|
return strconv.common_parse_uint(s, 0, 64, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ==
|
// ==
|
||||||
|
@ -614,7 +614,7 @@ pub fn (s string) title() string {
|
||||||
}
|
}
|
||||||
title := tit.join(' ')
|
title := tit.join(' ')
|
||||||
|
|
||||||
return title
|
return title
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'hey [man] how you doin'
|
// 'hey [man] how you doin'
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
fn test_common_atoi() {
|
||||||
|
assert "70zzz".int() == 70
|
||||||
|
assert "2901issue".int() == 2901
|
||||||
|
assert '234232w'.int() == 234232
|
||||||
|
assert '-9009x'.int() == -9009
|
||||||
|
assert '0y'.int() == 0
|
||||||
|
for n in -10000 .. 100000 {
|
||||||
|
s := n.str()+"z"
|
||||||
|
assert s.int() == n
|
||||||
|
}
|
||||||
|
}
|
|
@ -19,8 +19,9 @@ fn byte_to_lower(c byte) byte {
|
||||||
return c | (`x` - `X`)
|
return c | (`x` - `X`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse_uint is like parse_int but for unsigned numbers.
|
// common_parse_uint is called by parse_uint and allows the parsing
|
||||||
pub fn parse_uint(s string, _base int, _bit_size int) u64 {
|
// 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 {
|
||||||
mut bit_size := _bit_size
|
mut bit_size := _bit_size
|
||||||
mut base := _base
|
mut base := _base
|
||||||
|
|
||||||
|
@ -28,7 +29,7 @@ pub fn parse_uint(s string, _base int, _bit_size int) u64 {
|
||||||
// return error('parse_uint: syntax error $s')
|
// return error('parse_uint: syntax error $s')
|
||||||
return u64(0)
|
return u64(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
base0 := base == 0
|
base0 := base == 0
|
||||||
mut start_index := 0
|
mut start_index := 0
|
||||||
if 2 <= base && base <= 36 {
|
if 2 <= base && base <= 36 {
|
||||||
|
@ -89,12 +90,20 @@ pub fn parse_uint(s string, _base int, _bit_size int) u64 {
|
||||||
else if `0` <= c && c <= `9` { d = c - `0` }
|
else if `0` <= c && c <= `9` { d = c - `0` }
|
||||||
else if `a` <= cl && cl <= `z` { d = cl - `a` + 10 }
|
else if `a` <= cl && cl <= `z` { d = cl - `a` + 10 }
|
||||||
else {
|
else {
|
||||||
// return error('parse_uint: syntax error $s')
|
if error_on_non_digit {
|
||||||
return u64(0)
|
// return error('parse_uint: syntax error $s')
|
||||||
|
return u64(0)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if d >= byte(base) {
|
if d >= byte(base) {
|
||||||
// return error('parse_uint: syntax error $s')
|
if error_on_high_digit {
|
||||||
return u64(0)
|
// return error('parse_uint: syntax error $s')
|
||||||
|
return u64(0)
|
||||||
|
} else {
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if n >= cutoff {
|
if n >= cutoff {
|
||||||
// n*base overflows
|
// n*base overflows
|
||||||
|
@ -114,23 +123,17 @@ pub fn parse_uint(s string, _base int, _bit_size int) u64 {
|
||||||
// return error('parse_uint: syntax error $s')
|
// return error('parse_uint: syntax error $s')
|
||||||
return u64(0)
|
return u64(0)
|
||||||
}
|
}
|
||||||
|
return n
|
||||||
return n
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// parse_int interprets a string s in the given base (0, 2 to 36) and
|
// parse_uint is like parse_int but for unsigned numbers.
|
||||||
// bit size (0 to 64) and returns the corresponding value i.
|
pub fn parse_uint(s string, _base int, _bit_size int) u64 {
|
||||||
//
|
return common_parse_uint(s, _base, _bit_size, true, true)
|
||||||
// If the base argument is 0, the true base is implied by the string's
|
}
|
||||||
// prefix: 2 for "0b", 8 for "0" or "0o", 16 for "0x", and 10 otherwise.
|
|
||||||
// Also, for argument base 0 only, underscore characters are permitted
|
// common_parse_int is called by parse int and allows the parsing
|
||||||
// as defined by the Go syntax for integer literals.
|
// to stop on non or invalid digit characters and return the result so far
|
||||||
//
|
pub fn common_parse_int(_s string, base int, _bit_size int, error_on_non_digit bool, error_on_high_digit bool) i64 {
|
||||||
// The bitSize argument specifies the integer type
|
|
||||||
// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
|
|
||||||
// correspond to int, int8, int16, int32, and int64.
|
|
||||||
// If bitSize is below 0 or above 64, an error is returned.
|
|
||||||
pub fn parse_int(_s string, base int, _bit_size int) i64 {
|
|
||||||
mut s := _s
|
mut s := _s
|
||||||
mut bit_size := _bit_size
|
mut bit_size := _bit_size
|
||||||
|
|
||||||
|
@ -151,7 +154,7 @@ pub fn parse_int(_s string, base int, _bit_size int) i64 {
|
||||||
// un := parse_uint(s, base, bit_size) or {
|
// un := parse_uint(s, base, bit_size) or {
|
||||||
// return i64(0)
|
// return i64(0)
|
||||||
// }
|
// }
|
||||||
un := parse_uint(s, base, bit_size)
|
un := common_parse_uint(s, base, bit_size, error_on_non_digit, error_on_high_digit)
|
||||||
if un == 0 {
|
if un == 0 {
|
||||||
return i64(0)
|
return i64(0)
|
||||||
}
|
}
|
||||||
|
@ -173,7 +176,21 @@ pub fn parse_int(_s string, base int, _bit_size int) i64 {
|
||||||
|
|
||||||
return if neg { -i64(un) } else { i64(un) }
|
return if neg { -i64(un) } else { i64(un) }
|
||||||
}
|
}
|
||||||
|
// parse_int interprets a string s in the given base (0, 2 to 36) and
|
||||||
|
// bit size (0 to 64) and returns the corresponding value i.
|
||||||
|
//
|
||||||
|
// If the base argument is 0, the true base is implied by the string's
|
||||||
|
// prefix: 2 for "0b", 8 for "0" or "0o", 16 for "0x", and 10 otherwise.
|
||||||
|
// Also, for argument base 0 only, underscore characters are permitted
|
||||||
|
// as defined by the Go syntax for integer literals.
|
||||||
|
//
|
||||||
|
// The bitSize argument specifies the integer type
|
||||||
|
// that the result must fit into. Bit sizes 0, 8, 16, 32, and 64
|
||||||
|
// correspond to int, int8, int16, int32, and int64.
|
||||||
|
// If bitSize is below 0 or above 64, an error is returned.
|
||||||
|
pub fn parse_int(_s string, base int, _bit_size int) i64 {
|
||||||
|
return common_parse_int(_s, base, _bit_size, true, true)
|
||||||
|
}
|
||||||
|
|
||||||
// atoi is equivalent to parse_int(s, 10, 0), converted to type int.
|
// atoi is equivalent to parse_int(s, 10, 0), converted to type int.
|
||||||
pub fn atoi(s string) int {
|
pub fn atoi(s string) int {
|
||||||
|
|
Loading…
Reference in New Issue