diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 6361a6a5cb75..fa82001151e2 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -507,7 +507,7 @@ impl num::ToStrRadix for f32 { #[inline(always)] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, - strconv::ExpDec, false) + strconv::ExpDec, false, false) } /** @@ -540,7 +540,7 @@ pub fn from_str(num: &str) -> Option { #[inline(always)] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, - strconv::ExpBin, false) + strconv::ExpBin, false, false) } /** @@ -565,7 +565,7 @@ pub fn from_str_hex(num: &str) -> Option { #[inline(always)] pub fn from_str_radix(num: &str, rdx: uint) -> Option { strconv::from_str_common(num, rdx, true, true, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl from_str::FromStr for f32 { diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 9e731e61ec49..67dfabacd0b0 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -529,7 +529,7 @@ impl num::ToStrRadix for f64 { #[inline(always)] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, - strconv::ExpDec, false) + strconv::ExpDec, false, false) } /** @@ -562,7 +562,7 @@ pub fn from_str(num: &str) -> Option { #[inline(always)] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, - strconv::ExpBin, false) + strconv::ExpBin, false, false) } /** @@ -587,7 +587,7 @@ pub fn from_str_hex(num: &str) -> Option { #[inline(always)] pub fn from_str_radix(num: &str, rdx: uint) -> Option { strconv::from_str_common(num, rdx, true, true, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl from_str::FromStr for f64 { diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index c80d52f496b4..250829297030 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -242,7 +242,7 @@ impl num::ToStrRadix for float { #[inline(always)] pub fn from_str(num: &str) -> Option { strconv::from_str_common(num, 10u, true, true, true, - strconv::ExpDec, false) + strconv::ExpDec, false, false) } /** @@ -275,7 +275,7 @@ pub fn from_str(num: &str) -> Option { #[inline(always)] pub fn from_str_hex(num: &str) -> Option { strconv::from_str_common(num, 16u, true, true, true, - strconv::ExpBin, false) + strconv::ExpBin, false, false) } /** @@ -300,7 +300,7 @@ pub fn from_str_hex(num: &str) -> Option { #[inline(always)] pub fn from_str_radix(num: &str, radix: uint) -> Option { strconv::from_str_common(num, radix, true, true, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl from_str::FromStr for float { diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index a3cbd9fe7e3a..db90ec794653 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -202,21 +202,21 @@ impl ops::Neg for T { #[inline(always)] pub fn from_str(s: &str) -> Option { strconv::from_str_common(s, 10u, true, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. #[inline(always)] pub fn from_str_radix(s: &str, radix: uint) -> Option { strconv::from_str_common(s, radix, true, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { strconv::from_str_bytes_common(buf, radix, true, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl FromStr for T { diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs index 687b6344b39b..95da5bc29f5d 100644 --- a/src/libcore/num/strconv.rs +++ b/src/libcore/num/strconv.rs @@ -429,6 +429,8 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * `FFp128`. The exponent string itself is always base 10. * Can conflict with `radix`, see Failure. * - `empty_zero` - Whether to accept a empty `buf` as a 0 or not. + * - `ignore_underscores` - Whether all underscores within the string should + * be ignored. * * # Return value * Returns `Some(n)` if `buf` parses to a number n without overflowing, and @@ -443,16 +445,13 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; * between digit and exponent sign `'p'`. * - Fails if `radix` > 18 and `special == true` due to conflict * between digit and lowest first character in `inf` and `NaN`, the `'i'`. - * - * # Possible improvements - * - Could accept option to allow ignoring underscores, allowing for numbers - * formated like `FF_AE_FF_FF`. */ pub fn from_str_bytes_common+ Mul+Sub+Neg+Add+ NumStrConv>( buf: &[u8], radix: uint, negative: bool, fractional: bool, - special: bool, exponent: ExponentFormat, empty_zero: bool + special: bool, exponent: ExponentFormat, empty_zero: bool, + ignore_underscores: bool ) -> Option { match exponent { ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' @@ -540,6 +539,7 @@ pub fn from_str_bytes_common+ last_accum = accum; } None => match c { + '_' if ignore_underscores => {} 'e' | 'E' | 'p' | 'P' => { exp_found = true; break; // start of exponent @@ -583,6 +583,7 @@ pub fn from_str_bytes_common+ last_accum = accum; } None => match c { + '_' if ignore_underscores => {} 'e' | 'E' | 'p' | 'P' => { exp_found = true; break; // start of exponent @@ -610,6 +611,7 @@ pub fn from_str_bytes_common+ if exp_found { let c = buf[i] as char; let base = match (c, exponent) { + // c is never _ so don't need to handle specially ('e', ExpDec) | ('E', ExpDec) => 10u, ('p', ExpBin) | ('P', ExpBin) => 2u, _ => return None // char doesn't fit given exponent format @@ -618,7 +620,8 @@ pub fn from_str_bytes_common+ // parse remaining bytes as decimal integer, // skipping the exponent char let exp: Option = from_str_bytes_common( - buf.slice(i+1, len), 10, true, false, false, ExpNone, false); + buf.slice(i+1, len), 10, true, false, false, ExpNone, false, + ignore_underscores); match exp { Some(exp_pow) => { @@ -643,10 +646,12 @@ pub fn from_str_bytes_common+ pub fn from_str_common+Mul+ Sub+Neg+Add+NumStrConv>( buf: &str, radix: uint, negative: bool, fractional: bool, - special: bool, exponent: ExponentFormat, empty_zero: bool + special: bool, exponent: ExponentFormat, empty_zero: bool, + ignore_underscores: bool ) -> Option { from_str_bytes_common(str::to_bytes(buf), radix, negative, - fractional, special, exponent, empty_zero) + fractional, special, exponent, empty_zero, + ignore_underscores) } #[cfg(test)] @@ -654,13 +659,28 @@ mod test { use super::*; use option::*; + #[test] + fn from_str_ignore_underscores() { + let s : Option = from_str_common("__1__", 2, false, false, false, + ExpNone, false, true); + assert_eq!(s, Some(1u8)); + + let n : Option = from_str_common("__1__", 2, false, false, false, + ExpNone, false, false); + assert_eq!(n, None); + + let f : Option = from_str_common("_1_._1_e_1_", 10, false, true, false, + ExpDec, false, true); + assert_eq!(f, Some(1.1e1f32)); + } + #[test] fn from_str_issue5770() { // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems // since 255*2+1 == 255 (mod 256) so the overflow wasn't // detected. let n : Option = from_str_common("111111111", 2, false, false, false, - ExpNone, false); + ExpNone, false, false); assert_eq!(n, None); } } diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index 400417284a27..39af025217c9 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -168,21 +168,21 @@ impl ops::Neg for T { #[inline(always)] pub fn from_str(s: &str) -> Option { strconv::from_str_common(s, 10u, false, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a string as a number in the given base. #[inline(always)] pub fn from_str_radix(s: &str, radix: uint) -> Option { strconv::from_str_common(s, radix, false, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] pub fn parse_bytes(buf: &[u8], radix: uint) -> Option { strconv::from_str_bytes_common(buf, radix, false, false, false, - strconv::ExpNone, false) + strconv::ExpNone, false, false) } impl FromStr for T {