libcore: from_str_common: provide option to ignore underscores.
Implement the possible improvement listed in the comment on from_str_bytes_common.
This commit is contained in:
parent
49cdf36d2b
commit
41c6f67109
@ -507,7 +507,7 @@ impl num::ToStrRadix for f32 {
|
||||
#[inline(always)]
|
||||
pub fn from_str(num: &str) -> Option<f32> {
|
||||
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<f32> {
|
||||
#[inline(always)]
|
||||
pub fn from_str_hex(num: &str) -> Option<f32> {
|
||||
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<f32> {
|
||||
#[inline(always)]
|
||||
pub fn from_str_radix(num: &str, rdx: uint) -> Option<f32> {
|
||||
strconv::from_str_common(num, rdx, true, true, false,
|
||||
strconv::ExpNone, false)
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
impl from_str::FromStr for f32 {
|
||||
|
@ -529,7 +529,7 @@ impl num::ToStrRadix for f64 {
|
||||
#[inline(always)]
|
||||
pub fn from_str(num: &str) -> Option<f64> {
|
||||
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<f64> {
|
||||
#[inline(always)]
|
||||
pub fn from_str_hex(num: &str) -> Option<f64> {
|
||||
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<f64> {
|
||||
#[inline(always)]
|
||||
pub fn from_str_radix(num: &str, rdx: uint) -> Option<f64> {
|
||||
strconv::from_str_common(num, rdx, true, true, false,
|
||||
strconv::ExpNone, false)
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
impl from_str::FromStr for f64 {
|
||||
|
@ -242,7 +242,7 @@ impl num::ToStrRadix for float {
|
||||
#[inline(always)]
|
||||
pub fn from_str(num: &str) -> Option<float> {
|
||||
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<float> {
|
||||
#[inline(always)]
|
||||
pub fn from_str_hex(num: &str) -> Option<float> {
|
||||
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<float> {
|
||||
#[inline(always)]
|
||||
pub fn from_str_radix(num: &str, radix: uint) -> Option<float> {
|
||||
strconv::from_str_common(num, radix, true, true, false,
|
||||
strconv::ExpNone, false)
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
impl from_str::FromStr for float {
|
||||
|
@ -202,21 +202,21 @@ impl ops::Neg<T> for T {
|
||||
#[inline(always)]
|
||||
pub fn from_str(s: &str) -> Option<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
strconv::from_str_bytes_common(buf, radix, true, false, false,
|
||||
strconv::ExpNone, false)
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
impl FromStr for T {
|
||||
|
@ -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<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
|
||||
Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
|
||||
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<T> {
|
||||
match exponent {
|
||||
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
|
||||
@ -540,6 +539,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
|
||||
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<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
|
||||
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<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
|
||||
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<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
|
||||
// parse remaining bytes as decimal integer,
|
||||
// skipping the exponent char
|
||||
let exp: Option<int> = 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<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
|
||||
pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+Mul<T,T>+
|
||||
Sub<T,T>+Neg<T>+Add<T,T>+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<T> {
|
||||
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<u8> = from_str_common("__1__", 2, false, false, false,
|
||||
ExpNone, false, true);
|
||||
assert_eq!(s, Some(1u8));
|
||||
|
||||
let n : Option<u8> = from_str_common("__1__", 2, false, false, false,
|
||||
ExpNone, false, false);
|
||||
assert_eq!(n, None);
|
||||
|
||||
let f : Option<f32> = 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<u8> = from_str_common("111111111", 2, false, false, false,
|
||||
ExpNone, false);
|
||||
ExpNone, false, false);
|
||||
assert_eq!(n, None);
|
||||
}
|
||||
}
|
||||
|
@ -168,21 +168,21 @@ impl ops::Neg<T> for T {
|
||||
#[inline(always)]
|
||||
pub fn from_str(s: &str) -> Option<T> {
|
||||
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<T> {
|
||||
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<T> {
|
||||
strconv::from_str_bytes_common(buf, radix, false, false, false,
|
||||
strconv::ExpNone, false)
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
impl FromStr for T {
|
||||
|
Loading…
x
Reference in New Issue
Block a user