rollup merge of #18536 : bjz/strconv
This commit is contained in:
commit
ee5d238389
8 changed files with 280 additions and 549 deletions
|
|
@ -36,7 +36,7 @@ use std::io::extensions::u64_from_be_bytes;
|
|||
use std::io;
|
||||
use std::collections::hash_map::HashMap;
|
||||
use std::rc::Rc;
|
||||
use std::u64;
|
||||
use std::str;
|
||||
use rbml::reader;
|
||||
use rbml;
|
||||
use serialize::Decodable;
|
||||
|
|
@ -215,7 +215,9 @@ fn each_reexport(d: rbml::Doc, f: |rbml::Doc| -> bool) -> bool {
|
|||
|
||||
fn variant_disr_val(d: rbml::Doc) -> Option<ty::Disr> {
|
||||
reader::maybe_get_doc(d, tag_disr_val).and_then(|val_doc| {
|
||||
reader::with_doc_data(val_doc, |data| u64::parse_bytes(data, 10u))
|
||||
reader::with_doc_data(val_doc, |data| {
|
||||
str::from_utf8(data).and_then(from_str)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,7 +23,6 @@ use middle::ty;
|
|||
use std::rc::Rc;
|
||||
use std::str;
|
||||
use std::string::String;
|
||||
use std::uint;
|
||||
use syntax::abi;
|
||||
use syntax::ast;
|
||||
use syntax::ast::*;
|
||||
|
|
@ -615,12 +614,12 @@ pub fn parse_def_id(buf: &[u8]) -> ast::DefId {
|
|||
let crate_part = buf[0u..colon_idx];
|
||||
let def_part = buf[colon_idx + 1u..len];
|
||||
|
||||
let crate_num = match uint::parse_bytes(crate_part, 10u) {
|
||||
let crate_num = match str::from_utf8(crate_part).and_then(from_str::<uint>) {
|
||||
Some(cn) => cn as ast::CrateNum,
|
||||
None => panic!("internal error: parse_def_id: crate number expected, found {}",
|
||||
crate_part)
|
||||
};
|
||||
let def_num = match uint::parse_bytes(def_part, 10u) {
|
||||
let def_num = match str::from_utf8(def_part).and_then(from_str::<uint>) {
|
||||
Some(dn) => dn as ast::NodeId,
|
||||
None => panic!("internal error: parse_def_id: id expected, found {}",
|
||||
def_part)
|
||||
|
|
|
|||
|
|
@ -333,35 +333,10 @@ pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String {
|
|||
r
|
||||
}
|
||||
|
||||
/// Convert a string in base 16 to a float.
|
||||
/// Accepts an optional binary exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * 'a4.fe'
|
||||
/// * '+a4.fe', equivalent to 'a4.fe'
|
||||
/// * '-a4.fe'
|
||||
/// * '2b.aP128', or equivalently, '2b.ap128'
|
||||
/// * '2b.aP-128'
|
||||
/// * '.' (understood as 0)
|
||||
/// * 'c.'
|
||||
/// * '.c', or, equivalently, '0.c'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `None` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
#[inline]
|
||||
pub fn from_str_hex(num: &str) -> Option<f32> {
|
||||
strconv::from_str_common(num, 16u, true, true, true,
|
||||
strconv::ExpBin, false, false)
|
||||
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
|
||||
pub fn from_str_hex(src: &str) -> Option<f32> {
|
||||
strconv::from_str_radix_float(src, 16)
|
||||
}
|
||||
|
||||
impl FromStr for f32 {
|
||||
|
|
@ -384,16 +359,15 @@ impl FromStr for f32 {
|
|||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * src - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `None` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `src`.
|
||||
#[inline]
|
||||
fn from_str(val: &str) -> Option<f32> {
|
||||
strconv::from_str_common(val, 10u, true, true, true,
|
||||
strconv::ExpDec, false, false)
|
||||
fn from_str(src: &str) -> Option<f32> {
|
||||
strconv::from_str_radix_float(src, 10u)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -408,17 +382,16 @@ impl num::FromStrRadix for f32 {
|
|||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * src - A string
|
||||
/// * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `None` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `src`.
|
||||
#[inline]
|
||||
fn from_str_radix(val: &str, rdx: uint) -> Option<f32> {
|
||||
strconv::from_str_common(val, rdx, true, true, false,
|
||||
strconv::ExpNone, false, false)
|
||||
fn from_str_radix(src: &str, radix: uint) -> Option<f32> {
|
||||
strconv::from_str_radix_float(src, radix)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -710,8 +683,8 @@ mod tests {
|
|||
fn test_ldexp() {
|
||||
// We have to use from_str until base-2 exponents
|
||||
// are supported in floating-point literals
|
||||
let f1: f32 = from_str_hex("1p-123").unwrap();
|
||||
let f2: f32 = from_str_hex("1p-111").unwrap();
|
||||
let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
|
||||
let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
|
||||
assert_eq!(FloatMath::ldexp(1f32, -123), f1);
|
||||
assert_eq!(FloatMath::ldexp(1f32, -111), f2);
|
||||
|
||||
|
|
@ -730,8 +703,8 @@ mod tests {
|
|||
fn test_frexp() {
|
||||
// We have to use from_str until base-2 exponents
|
||||
// are supported in floating-point literals
|
||||
let f1: f32 = from_str_hex("1p-123").unwrap();
|
||||
let f2: f32 = from_str_hex("1p-111").unwrap();
|
||||
let f1: f32 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
|
||||
let f2: f32 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
|
||||
let (x1, exp1) = f1.frexp();
|
||||
let (x2, exp2) = f2.frexp();
|
||||
assert_eq!((x1, exp1), (0.5f32, -122));
|
||||
|
|
|
|||
|
|
@ -341,92 +341,60 @@ pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String {
|
|||
r
|
||||
}
|
||||
|
||||
/// Convert a string in base 16 to a float.
|
||||
/// Accepts an optional binary exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
///
|
||||
/// * 'a4.fe'
|
||||
/// * '+a4.fe', equivalent to 'a4.fe'
|
||||
/// * '-a4.fe'
|
||||
/// * '2b.aP128', or equivalently, '2b.ap128'
|
||||
/// * '2b.aP-128'
|
||||
/// * '.' (understood as 0)
|
||||
/// * 'c.'
|
||||
/// * '.c', or, equivalently, '0.c'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `None` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `[num]`.
|
||||
#[inline]
|
||||
pub fn from_str_hex(num: &str) -> Option<f64> {
|
||||
strconv::from_str_common(num, 16u, true, true, true,
|
||||
strconv::ExpBin, false, false)
|
||||
#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"]
|
||||
pub fn from_str_hex(src: &str) -> Option<f64> {
|
||||
strconv::from_str_radix_float(src, 16)
|
||||
}
|
||||
|
||||
impl FromStr for f64 {
|
||||
/// Convert a string in base 10 to a float.
|
||||
/// Accepts an optional decimal exponent.
|
||||
///
|
||||
/// This function accepts strings such as
|
||||
/// This function accepts strings such as:
|
||||
///
|
||||
/// * '3.14'
|
||||
/// * '+3.14', equivalent to '3.14'
|
||||
/// * '-3.14'
|
||||
/// * '2.5E10', or equivalently, '2.5e10'
|
||||
/// * '2.5E-10'
|
||||
/// * '.' (understood as 0)
|
||||
/// * '5.'
|
||||
/// * '.5', or, equivalently, '0.5'
|
||||
/// * '+inf', 'inf', '-inf', 'NaN'
|
||||
/// * inf', '-inf', 'NaN'
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * src - A string
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `none` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `src`.
|
||||
#[inline]
|
||||
fn from_str(val: &str) -> Option<f64> {
|
||||
strconv::from_str_common(val, 10u, true, true, true,
|
||||
strconv::ExpDec, false, false)
|
||||
fn from_str(src: &str) -> Option<f64> {
|
||||
strconv::from_str_radix_float(src, 10u)
|
||||
}
|
||||
}
|
||||
|
||||
impl num::FromStrRadix for f64 {
|
||||
/// Convert a string in a given base to a float.
|
||||
///
|
||||
/// Due to possible conflicts, this function does **not** accept
|
||||
/// the special values `inf`, `-inf`, `+inf` and `NaN`, **nor**
|
||||
/// does it recognize exponents of any kind.
|
||||
///
|
||||
/// Leading and trailing whitespace represent an error.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * num - A string
|
||||
/// * src - A string
|
||||
/// * radix - The base to use. Must lie in the range [2 .. 36]
|
||||
///
|
||||
/// # Return value
|
||||
///
|
||||
/// `None` if the string did not represent a valid number. Otherwise,
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `num`.
|
||||
/// `Some(n)` where `n` is the floating-point number represented by `src`.
|
||||
#[inline]
|
||||
fn from_str_radix(val: &str, rdx: uint) -> Option<f64> {
|
||||
strconv::from_str_common(val, rdx, true, true, false,
|
||||
strconv::ExpNone, false, false)
|
||||
fn from_str_radix(src: &str, radix: uint) -> Option<f64> {
|
||||
strconv::from_str_radix_float(src, radix)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -712,8 +680,8 @@ mod tests {
|
|||
fn test_ldexp() {
|
||||
// We have to use from_str until base-2 exponents
|
||||
// are supported in floating-point literals
|
||||
let f1: f64 = from_str_hex("1p-123").unwrap();
|
||||
let f2: f64 = from_str_hex("1p-111").unwrap();
|
||||
let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
|
||||
let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
|
||||
assert_eq!(FloatMath::ldexp(1f64, -123), f1);
|
||||
assert_eq!(FloatMath::ldexp(1f64, -111), f2);
|
||||
|
||||
|
|
@ -732,8 +700,8 @@ mod tests {
|
|||
fn test_frexp() {
|
||||
// We have to use from_str until base-2 exponents
|
||||
// are supported in floating-point literals
|
||||
let f1: f64 = from_str_hex("1p-123").unwrap();
|
||||
let f2: f64 = from_str_hex("1p-111").unwrap();
|
||||
let f1: f64 = FromStrRadix::from_str_radix("1p-123", 16).unwrap();
|
||||
let f2: f64 = FromStrRadix::from_str_radix("1p-111", 16).unwrap();
|
||||
let (x1, exp1) = f1.frexp();
|
||||
let (x2, exp2) = f2.frexp();
|
||||
assert_eq!((x1, exp1), (0.5f64, -122));
|
||||
|
|
|
|||
|
|
@ -14,31 +14,11 @@
|
|||
|
||||
macro_rules! int_module (($T:ty) => (
|
||||
|
||||
// String conversion functions and impl str -> num
|
||||
|
||||
/// Parse a byte slice as a number in the given base
|
||||
///
|
||||
/// Yields an `Option` because `buf` may or may not actually be parseable.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let num = std::i64::parse_bytes([49,50,51,52,53,54,55,56,57], 10);
|
||||
/// assert!(num == Some(123456789));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[experimental = "might need to return Result"]
|
||||
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
|
||||
strconv::from_str_bytes_common(buf, radix, true, false, false,
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
#[experimental = "might need to return Result"]
|
||||
impl FromStr for $T {
|
||||
#[inline]
|
||||
fn from_str(s: &str) -> Option<$T> {
|
||||
strconv::from_str_common(s, 10u, true, false, false,
|
||||
strconv::ExpNone, false, false)
|
||||
strconv::from_str_radix_int(s, 10)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -46,18 +26,14 @@ impl FromStr for $T {
|
|||
impl FromStrRadix for $T {
|
||||
#[inline]
|
||||
fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
|
||||
strconv::from_str_common(s, radix, true, false, false,
|
||||
strconv::ExpNone, false, false)
|
||||
strconv::from_str_radix_int(s, radix)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::*;
|
||||
use super::*;
|
||||
|
||||
use i32;
|
||||
use str::StrSlice;
|
||||
use num::FromStrRadix;
|
||||
|
||||
#[test]
|
||||
fn test_from_str() {
|
||||
|
|
@ -73,33 +49,33 @@ mod tests {
|
|||
assert_eq!(from_str::<i32>("-123456789"), Some(-123456789 as i32));
|
||||
assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T));
|
||||
|
||||
assert!(from_str::<$T>(" ").is_none());
|
||||
assert!(from_str::<$T>("x").is_none());
|
||||
assert_eq!(from_str::<$T>(""), None);
|
||||
assert_eq!(from_str::<$T>(" "), None);
|
||||
assert_eq!(from_str::<$T>("x"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_parse_bytes() {
|
||||
use str::StrSlice;
|
||||
assert_eq!(parse_bytes("123".as_bytes(), 10u), Some(123 as $T));
|
||||
assert_eq!(parse_bytes("1001".as_bytes(), 2u), Some(9 as $T));
|
||||
assert_eq!(parse_bytes("123".as_bytes(), 8u), Some(83 as $T));
|
||||
assert_eq!(i32::parse_bytes("123".as_bytes(), 16u), Some(291 as i32));
|
||||
assert_eq!(i32::parse_bytes("ffff".as_bytes(), 16u), Some(65535 as i32));
|
||||
assert_eq!(i32::parse_bytes("FFFF".as_bytes(), 16u), Some(65535 as i32));
|
||||
assert_eq!(parse_bytes("z".as_bytes(), 36u), Some(35 as $T));
|
||||
assert_eq!(parse_bytes("Z".as_bytes(), 36u), Some(35 as $T));
|
||||
fn test_from_str_radix() {
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("FFFF", 16), Some(65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("Z", 36), Some(35 as $T));
|
||||
|
||||
assert_eq!(parse_bytes("-123".as_bytes(), 10u), Some(-123 as $T));
|
||||
assert_eq!(parse_bytes("-1001".as_bytes(), 2u), Some(-9 as $T));
|
||||
assert_eq!(parse_bytes("-123".as_bytes(), 8u), Some(-83 as $T));
|
||||
assert_eq!(i32::parse_bytes("-123".as_bytes(), 16u), Some(-291 as i32));
|
||||
assert_eq!(i32::parse_bytes("-ffff".as_bytes(), 16u), Some(-65535 as i32));
|
||||
assert_eq!(i32::parse_bytes("-FFFF".as_bytes(), 16u), Some(-65535 as i32));
|
||||
assert_eq!(parse_bytes("-z".as_bytes(), 36u), Some(-35 as $T));
|
||||
assert_eq!(parse_bytes("-Z".as_bytes(), 36u), Some(-35 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-123", 10), Some(-123 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-1001", 2), Some(-9 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-123", 8), Some(-83 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-123", 16), Some(-291 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-ffff", 16), Some(-65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-FFFF", 16), Some(-65535 as i32));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-z", 36), Some(-35 as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("-Z", 36), Some(-35 as $T));
|
||||
|
||||
assert!(parse_bytes("Z".as_bytes(), 35u).is_none());
|
||||
assert!(parse_bytes("-9".as_bytes(), 2u).is_none());
|
||||
assert_eq!(FromStrRadix::from_str_radix("Z", 35), None::<$T>);
|
||||
assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -133,35 +109,35 @@ mod tests {
|
|||
fn test_int_from_str_overflow() {
|
||||
let mut i8_val: i8 = 127_i8;
|
||||
assert_eq!(from_str::<i8>("127"), Some(i8_val));
|
||||
assert!(from_str::<i8>("128").is_none());
|
||||
assert_eq!(from_str::<i8>("128"), None);
|
||||
|
||||
i8_val += 1 as i8;
|
||||
assert_eq!(from_str::<i8>("-128"), Some(i8_val));
|
||||
assert!(from_str::<i8>("-129").is_none());
|
||||
assert_eq!(from_str::<i8>("-129"), None);
|
||||
|
||||
let mut i16_val: i16 = 32_767_i16;
|
||||
assert_eq!(from_str::<i16>("32767"), Some(i16_val));
|
||||
assert!(from_str::<i16>("32768").is_none());
|
||||
assert_eq!(from_str::<i16>("32768"), None);
|
||||
|
||||
i16_val += 1 as i16;
|
||||
assert_eq!(from_str::<i16>("-32768"), Some(i16_val));
|
||||
assert!(from_str::<i16>("-32769").is_none());
|
||||
assert_eq!(from_str::<i16>("-32769"), None);
|
||||
|
||||
let mut i32_val: i32 = 2_147_483_647_i32;
|
||||
assert_eq!(from_str::<i32>("2147483647"), Some(i32_val));
|
||||
assert!(from_str::<i32>("2147483648").is_none());
|
||||
assert_eq!(from_str::<i32>("2147483648"), None);
|
||||
|
||||
i32_val += 1 as i32;
|
||||
assert_eq!(from_str::<i32>("-2147483648"), Some(i32_val));
|
||||
assert!(from_str::<i32>("-2147483649").is_none());
|
||||
assert_eq!(from_str::<i32>("-2147483649"), None);
|
||||
|
||||
let mut i64_val: i64 = 9_223_372_036_854_775_807_i64;
|
||||
assert_eq!(from_str::<i64>("9223372036854775807"), Some(i64_val));
|
||||
assert!(from_str::<i64>("9223372036854775808").is_none());
|
||||
assert_eq!(from_str::<i64>("9223372036854775808"), None);
|
||||
|
||||
i64_val += 1 as i64;
|
||||
assert_eq!(from_str::<i64>("-9223372036854775808"), Some(i64_val));
|
||||
assert!(from_str::<i64>("-9223372036854775809").is_none());
|
||||
assert_eq!(from_str::<i64>("-9223372036854775809"), None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,14 +13,14 @@
|
|||
#![allow(missing_docs)]
|
||||
|
||||
use char;
|
||||
use clone::Clone;
|
||||
use num::{NumCast, Zero, One, cast, Int};
|
||||
use num::{Float, FPNaN, FPInfinite, ToPrimitive};
|
||||
use char::Char;
|
||||
use from_str::from_str;
|
||||
use iter::Iterator;
|
||||
use num;
|
||||
use ops::{Add, Sub, Mul, Div, Rem, Neg};
|
||||
use num::{Int, Bounded};
|
||||
use num::{Float, FPNaN, FPInfinite, ToPrimitive};
|
||||
use option::{None, Option, Some};
|
||||
use slice::{ImmutableSlice, MutableSlice, CloneableVector};
|
||||
use std::cmp::{PartialOrd, PartialEq};
|
||||
use str::StrSlice;
|
||||
use string::String;
|
||||
use vec::Vec;
|
||||
|
|
@ -67,81 +67,6 @@ pub enum SignFormat {
|
|||
SignAll,
|
||||
}
|
||||
|
||||
/// Encompasses functions used by the string converter.
|
||||
pub trait NumStrConv {
|
||||
/// Returns the NaN value.
|
||||
fn nan() -> Option<Self>;
|
||||
|
||||
/// Returns the infinite value.
|
||||
fn inf() -> Option<Self>;
|
||||
|
||||
/// Returns the negative infinite value.
|
||||
fn neg_inf() -> Option<Self>;
|
||||
|
||||
/// Returns -0.0.
|
||||
fn neg_zero() -> Option<Self>;
|
||||
|
||||
/// Rounds the number toward zero.
|
||||
fn round_to_zero(&self) -> Self;
|
||||
|
||||
/// Returns the fractional part of the number.
|
||||
fn fractional_part(&self) -> Self;
|
||||
}
|
||||
|
||||
macro_rules! impl_NumStrConv_Floating (($t:ty) => (
|
||||
impl NumStrConv for $t {
|
||||
#[inline]
|
||||
fn nan() -> Option<$t> { Some( 0.0 / 0.0) }
|
||||
#[inline]
|
||||
fn inf() -> Option<$t> { Some( 1.0 / 0.0) }
|
||||
#[inline]
|
||||
fn neg_inf() -> Option<$t> { Some(-1.0 / 0.0) }
|
||||
#[inline]
|
||||
fn neg_zero() -> Option<$t> { Some(-0.0 ) }
|
||||
|
||||
#[inline]
|
||||
fn round_to_zero(&self) -> $t { self.trunc() }
|
||||
#[inline]
|
||||
fn fractional_part(&self) -> $t { self.fract() }
|
||||
}
|
||||
))
|
||||
|
||||
macro_rules! impl_NumStrConv_Integer (($t:ty) => (
|
||||
impl NumStrConv for $t {
|
||||
#[inline] fn nan() -> Option<$t> { None }
|
||||
#[inline] fn inf() -> Option<$t> { None }
|
||||
#[inline] fn neg_inf() -> Option<$t> { None }
|
||||
#[inline] fn neg_zero() -> Option<$t> { None }
|
||||
|
||||
#[inline] fn round_to_zero(&self) -> $t { *self }
|
||||
#[inline] fn fractional_part(&self) -> $t { 0 }
|
||||
}
|
||||
))
|
||||
|
||||
// FIXME: #4955
|
||||
// Replace by two generic impls for traits 'Integral' and 'Floating'
|
||||
impl_NumStrConv_Floating!(f32)
|
||||
impl_NumStrConv_Floating!(f64)
|
||||
|
||||
impl_NumStrConv_Integer!(int)
|
||||
impl_NumStrConv_Integer!(i8)
|
||||
impl_NumStrConv_Integer!(i16)
|
||||
impl_NumStrConv_Integer!(i32)
|
||||
impl_NumStrConv_Integer!(i64)
|
||||
|
||||
impl_NumStrConv_Integer!(uint)
|
||||
impl_NumStrConv_Integer!(u8)
|
||||
impl_NumStrConv_Integer!(u16)
|
||||
impl_NumStrConv_Integer!(u32)
|
||||
impl_NumStrConv_Integer!(u64)
|
||||
|
||||
|
||||
// Special value strings as [u8] consts.
|
||||
static INF_BUF: [u8, ..3] = [b'i', b'n', b'f'];
|
||||
static POS_INF_BUF: [u8, ..4] = [b'+', b'i', b'n', b'f'];
|
||||
static NEG_INF_BUF: [u8, ..4] = [b'-', b'i', b'n', b'f'];
|
||||
static NAN_BUF: [u8, ..3] = [b'N', b'a', b'N'];
|
||||
|
||||
/**
|
||||
* Converts an integral number to its string representation as a byte vector.
|
||||
* This is meant to be a common base implementation for all integral string
|
||||
|
|
@ -170,10 +95,10 @@ static NAN_BUF: [u8, ..3] = [b'N', b'a', b'N'];
|
|||
fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
|
||||
assert!(2 <= radix && radix <= 36);
|
||||
|
||||
let _0: T = Zero::zero();
|
||||
let _0: T = num::zero();
|
||||
|
||||
let neg = num < _0;
|
||||
let radix_gen: T = cast(radix).unwrap();
|
||||
let radix_gen: T = num::cast(radix).unwrap();
|
||||
|
||||
let mut deccum = num;
|
||||
// This is just for integral types, the largest of which is a u64. The
|
||||
|
|
@ -255,8 +180,7 @@ fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8
|
|||
* - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
|
||||
* between digit and exponent sign `'p'`.
|
||||
*/
|
||||
pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
|
||||
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
|
||||
pub fn float_to_str_bytes_common<T: Float>(
|
||||
num: T, radix: uint, negative_zero: bool,
|
||||
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
|
||||
) -> (Vec<u8>, bool) {
|
||||
|
|
@ -271,8 +195,8 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
|
|||
_ => ()
|
||||
}
|
||||
|
||||
let _0: T = Zero::zero();
|
||||
let _1: T = One::one();
|
||||
let _0: T = num::zero();
|
||||
let _1: T = num::one();
|
||||
|
||||
match num.classify() {
|
||||
FPNaN => { return (b"NaN".to_vec(), true); }
|
||||
|
|
@ -293,7 +217,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
|
|||
|
||||
let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
|
||||
let mut buf = Vec::new();
|
||||
let radix_gen: T = cast(radix as int).unwrap();
|
||||
let radix_gen: T = num::cast(radix as int).unwrap();
|
||||
|
||||
let (num, exp) = match exp_format {
|
||||
ExpNone => (num, 0i32),
|
||||
|
|
@ -302,12 +226,12 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
|
|||
(num, 0i32)
|
||||
} else {
|
||||
let (exp, exp_base) = match exp_format {
|
||||
ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
|
||||
ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
|
||||
ExpDec => (num.abs().log10().floor(), num::cast::<f64, T>(10.0f64).unwrap()),
|
||||
ExpBin => (num.abs().log2().floor(), num::cast::<f64, T>(2.0f64).unwrap()),
|
||||
ExpNone => unreachable!()
|
||||
};
|
||||
|
||||
(num / exp_base.powf(exp), cast::<T, i32>(exp).unwrap())
|
||||
(num / exp_base.powf(exp), num::cast::<T, i32>(exp).unwrap())
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -488,8 +412,7 @@ pub fn float_to_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Float+
|
|||
* `to_str_bytes_common()`, for details see there.
|
||||
*/
|
||||
#[inline]
|
||||
pub fn float_to_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+NumStrConv+Float+
|
||||
Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
|
||||
pub fn float_to_str_common<T: Float>(
|
||||
num: T, radix: uint, negative_zero: bool,
|
||||
sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
|
||||
) -> (String, bool) {
|
||||
|
|
@ -501,311 +424,228 @@ pub fn float_to_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+NumStrConv+Fl
|
|||
// Some constants for from_str_bytes_common's input validation,
|
||||
// they define minimum radix values for which the character is a valid digit.
|
||||
static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
|
||||
static DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u;
|
||||
static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
|
||||
|
||||
/**
|
||||
* Parses a byte slice as a number. This is meant to
|
||||
* be a common base implementation for all numeric string conversion
|
||||
* functions like `from_str()` or `from_str_radix()`.
|
||||
*
|
||||
* # Arguments
|
||||
* - `buf` - The byte slice to parse.
|
||||
* - `radix` - Which base to parse the number as. Accepts 2-36.
|
||||
* - `negative` - Whether to accept negative numbers.
|
||||
* - `fractional` - Whether to accept numbers with fractional parts.
|
||||
* - `special` - Whether to accept special values like `inf`
|
||||
* and `NaN`. Can conflict with `radix`, see Failure.
|
||||
* - `exponent` - Which exponent format to accept. Options are:
|
||||
* - `ExpNone`: No Exponent, accepts just plain numbers like `42` or
|
||||
* `-8.2`.
|
||||
* - `ExpDec`: Accepts numbers with a decimal exponent like `42e5` or
|
||||
* `8.2E-2`. The exponent string itself is always base 10.
|
||||
* Can conflict with `radix`, see Failure.
|
||||
* - `ExpBin`: Accepts numbers with a binary exponent like `42P-8` or
|
||||
* `FFp128`. The exponent string itself is always base 10.
|
||||
* Can conflict with `radix`, see Failure.
|
||||
* - `empty_zero` - Whether to accept an 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
|
||||
* `None` otherwise, depending on the constraints set by the remaining
|
||||
* arguments.
|
||||
*
|
||||
* # Failure
|
||||
* - Fails if `radix` < 2 or `radix` > 36.
|
||||
* - Fails if `radix` > 14 and `exponent` is `ExpDec` due to conflict
|
||||
* between digit and exponent sign `'e'`.
|
||||
* - Fails if `radix` > 25 and `exponent` is `ExpBin` due to conflict
|
||||
* 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'`.
|
||||
*/
|
||||
pub fn from_str_bytes_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Div<T,T>+
|
||||
Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
|
||||
NumStrConv+Clone>(
|
||||
buf: &[u8], radix: uint, negative: bool, fractional: bool,
|
||||
special: bool, exponent: ExponentFormat, empty_zero: bool,
|
||||
ignore_underscores: bool
|
||||
) -> Option<T> {
|
||||
match exponent {
|
||||
ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
|
||||
=> panic!("from_str_bytes_common: radix {} incompatible with \
|
||||
use of 'e' as decimal exponent", radix),
|
||||
ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p'
|
||||
=> panic!("from_str_bytes_common: radix {} incompatible with \
|
||||
use of 'p' as binary exponent", radix),
|
||||
_ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
|
||||
=> panic!("from_str_bytes_common: radix {} incompatible with \
|
||||
special values 'inf' and 'NaN'", radix),
|
||||
_ if (radix as int) < 2
|
||||
=> panic!("from_str_bytes_common: radix {} to low, \
|
||||
must lie in the range [2, 36]", radix),
|
||||
_ if (radix as int) > 36
|
||||
=> panic!("from_str_bytes_common: radix {} to high, \
|
||||
must lie in the range [2, 36]", radix),
|
||||
_ => ()
|
||||
pub fn from_str_radix_float<T: Float>(src: &str, radix: uint) -> Option<T> {
|
||||
assert!(radix >= 2 && radix <= 36,
|
||||
"from_str_radix_float: must lie in the range `[2, 36]` - found {}",
|
||||
radix);
|
||||
|
||||
let _0: T = num::zero();
|
||||
let _1: T = num::one();
|
||||
let radix_t: T = num::cast(radix as int).unwrap();
|
||||
|
||||
// Special values
|
||||
match src {
|
||||
"inf" => return Some(Float::infinity()),
|
||||
"-inf" => return Some(Float::neg_infinity()),
|
||||
"NaN" => return Some(Float::nan()),
|
||||
_ => {},
|
||||
}
|
||||
|
||||
let _0: T = Zero::zero();
|
||||
let _1: T = One::one();
|
||||
let radix_gen: T = cast(radix as int).unwrap();
|
||||
|
||||
let len = buf.len();
|
||||
|
||||
if len == 0 {
|
||||
if empty_zero {
|
||||
return Some(_0);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
|
||||
if special {
|
||||
if buf == INF_BUF || buf == POS_INF_BUF {
|
||||
return NumStrConv::inf();
|
||||
} else if buf == NEG_INF_BUF {
|
||||
if negative {
|
||||
return NumStrConv::neg_inf();
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
} else if buf == NAN_BUF {
|
||||
return NumStrConv::nan();
|
||||
}
|
||||
}
|
||||
|
||||
let (start, accum_positive) = match buf[0] as char {
|
||||
'-' if !negative => return None,
|
||||
'-' => (1u, false),
|
||||
'+' => (1u, true),
|
||||
_ => (0u, true)
|
||||
let (is_positive, src) = match src.slice_shift_char() {
|
||||
(None, _) => return None,
|
||||
(Some('-'), "") => return None,
|
||||
(Some('-'), src) => (false, src),
|
||||
(Some(_), _) => (true, src),
|
||||
};
|
||||
|
||||
// Initialize accumulator with signed zero for floating point parsing to
|
||||
// work
|
||||
let mut accum = if accum_positive { _0.clone() } else { -_1 * _0};
|
||||
let mut last_accum = accum.clone(); // Necessary to detect overflow
|
||||
let mut i = start;
|
||||
let mut exp_found = false;
|
||||
// The significand to accumulate
|
||||
let mut sig = if is_positive { _0 } else { -_1 };
|
||||
// Necessary to detect overflow
|
||||
let mut prev_sig = sig;
|
||||
let mut cs = src.chars().enumerate();
|
||||
// Exponent prefix and exponent index offset
|
||||
let mut exp_info = None::<(char, uint)>;
|
||||
|
||||
// Parse integer part of number
|
||||
while i < len {
|
||||
let c = buf[i] as char;
|
||||
|
||||
match char::to_digit(c, radix) {
|
||||
// Parse the integer part of the significand
|
||||
for (i, c) in cs {
|
||||
match c.to_digit(radix) {
|
||||
Some(digit) => {
|
||||
// shift accum one digit left
|
||||
accum = accum * radix_gen.clone();
|
||||
// shift significand one digit left
|
||||
sig = sig * radix_t;
|
||||
|
||||
// add/subtract current digit depending on sign
|
||||
if accum_positive {
|
||||
accum = accum + cast(digit as int).unwrap();
|
||||
if is_positive {
|
||||
sig = sig + num::cast(digit as int).unwrap();
|
||||
} else {
|
||||
accum = accum - cast(digit as int).unwrap();
|
||||
sig = sig - num::cast(digit as int).unwrap();
|
||||
}
|
||||
|
||||
// Detect overflow by comparing to last value, except
|
||||
// if we've not seen any non-zero digits.
|
||||
if last_accum != _0 {
|
||||
if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
|
||||
if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
|
||||
if prev_sig != _0 {
|
||||
if is_positive && sig <= prev_sig
|
||||
{ return Some(Float::infinity()); }
|
||||
if !is_positive && sig >= prev_sig
|
||||
{ return Some(Float::neg_infinity()); }
|
||||
|
||||
// Detect overflow by reversing the shift-and-add process
|
||||
if accum_positive &&
|
||||
(last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
|
||||
return NumStrConv::inf();
|
||||
}
|
||||
if !accum_positive &&
|
||||
(last_accum != ((accum + cast(digit as int).unwrap())/radix_gen.clone())) {
|
||||
return NumStrConv::neg_inf();
|
||||
}
|
||||
let digit: T = num::cast(digit as int).unwrap();
|
||||
if is_positive && (prev_sig != ((sig - digit) / radix_t))
|
||||
{ return Some(Float::infinity()); }
|
||||
if !is_positive && (prev_sig != ((sig + digit) / radix_t))
|
||||
{ return Some(Float::neg_infinity()); }
|
||||
}
|
||||
last_accum = accum.clone();
|
||||
}
|
||||
prev_sig = sig;
|
||||
},
|
||||
None => match c {
|
||||
'_' if ignore_underscores => {}
|
||||
'e' | 'E' | 'p' | 'P' => {
|
||||
exp_found = true;
|
||||
break; // start of exponent
|
||||
}
|
||||
'.' if fractional => {
|
||||
i += 1u; // skip the '.'
|
||||
break; // start of fractional part
|
||||
}
|
||||
_ => return None // invalid number
|
||||
}
|
||||
exp_info = Some((c, i + 1));
|
||||
break; // start of exponent
|
||||
},
|
||||
'.' => {
|
||||
break; // start of fractional part
|
||||
},
|
||||
_ => {
|
||||
return None;
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
// Parse fractional part of number
|
||||
// Skip if already reached start of exponent
|
||||
if !exp_found {
|
||||
let mut power = _1.clone();
|
||||
|
||||
while i < len {
|
||||
let c = buf[i] as char;
|
||||
|
||||
match char::to_digit(c, radix) {
|
||||
// If we are not yet at the exponent parse the fractional
|
||||
// part of the significand
|
||||
if exp_info.is_none() {
|
||||
let mut power = _1;
|
||||
for (i, c) in cs {
|
||||
match c.to_digit(radix) {
|
||||
Some(digit) => {
|
||||
let digit: T = num::cast(digit).unwrap();
|
||||
// Decrease power one order of magnitude
|
||||
power = power / radix_gen;
|
||||
|
||||
let digit_t: T = cast(digit).unwrap();
|
||||
|
||||
power = power / radix_t;
|
||||
// add/subtract current digit depending on sign
|
||||
if accum_positive {
|
||||
accum = accum + digit_t * power;
|
||||
sig = if is_positive {
|
||||
sig + digit * power
|
||||
} else {
|
||||
accum = accum - digit_t * power;
|
||||
}
|
||||
|
||||
sig - digit * power
|
||||
};
|
||||
// Detect overflow by comparing to last value
|
||||
if accum_positive && accum < last_accum { return NumStrConv::inf(); }
|
||||
if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
|
||||
last_accum = accum.clone();
|
||||
}
|
||||
if is_positive && sig < prev_sig
|
||||
{ return Some(Float::infinity()); }
|
||||
if !is_positive && sig > prev_sig
|
||||
{ return Some(Float::neg_infinity()); }
|
||||
prev_sig = sig;
|
||||
},
|
||||
None => match c {
|
||||
'_' if ignore_underscores => {}
|
||||
'e' | 'E' | 'p' | 'P' => {
|
||||
exp_found = true;
|
||||
break; // start of exponent
|
||||
}
|
||||
_ => return None // invalid number
|
||||
}
|
||||
exp_info = Some((c, i + 1));
|
||||
break; // start of exponent
|
||||
},
|
||||
_ => {
|
||||
return None; // invalid number
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
|
||||
// Special case: buf not empty, but does not contain any digit in front
|
||||
// of the exponent sign -> number is empty string
|
||||
if i == start {
|
||||
if empty_zero {
|
||||
return Some(_0);
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
// Parse and calculate the exponent
|
||||
let exp = match exp_info {
|
||||
Some((c, offset)) => {
|
||||
let base: T = match c {
|
||||
'E' | 'e' if radix == 10 => num::cast(10u).unwrap(),
|
||||
'P' | 'p' if radix == 16 => num::cast(2u).unwrap(),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
let mut multiplier = _1.clone();
|
||||
// Parse the exponent as decimal integer
|
||||
let src = src[offset..];
|
||||
let (is_positive, exp) = match src.slice_shift_char() {
|
||||
(Some('-'), src) => (false, from_str::<uint>(src)),
|
||||
(Some('+'), src) => (true, from_str::<uint>(src)),
|
||||
(Some(_), _) => (true, from_str::<uint>(src)),
|
||||
(None, _) => return None,
|
||||
};
|
||||
|
||||
if exp_found {
|
||||
let c = buf[i] as char;
|
||||
let base: T = match (c, exponent) {
|
||||
// c is never _ so don't need to handle specially
|
||||
('e', ExpDec) | ('E', ExpDec) => cast(10u).unwrap(),
|
||||
('p', ExpBin) | ('P', ExpBin) => cast(2u).unwrap(),
|
||||
_ => return None // char doesn't fit given exponent format
|
||||
};
|
||||
|
||||
// parse remaining bytes as decimal integer,
|
||||
// skipping the exponent char
|
||||
let exp: Option<int> = from_str_bytes_common(
|
||||
buf[i+1..len], 10, true, false, false, ExpNone, false,
|
||||
ignore_underscores);
|
||||
|
||||
match exp {
|
||||
Some(exp_pow) => {
|
||||
multiplier = if exp_pow < 0 {
|
||||
_1 / num::pow(base, (-exp_pow.to_int().unwrap()) as uint)
|
||||
} else {
|
||||
num::pow(base, exp_pow.to_int().unwrap() as uint)
|
||||
}
|
||||
match (is_positive, exp) {
|
||||
(true, Some(exp)) => num::pow(base, exp),
|
||||
(false, Some(exp)) => _1 / num::pow(base, exp),
|
||||
(_, None) => return None,
|
||||
}
|
||||
None => return None // invalid exponent -> invalid number
|
||||
}
|
||||
}
|
||||
},
|
||||
None => _1, // no exponent
|
||||
};
|
||||
|
||||
Some(accum * multiplier)
|
||||
Some(sig * exp)
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a string as a number. This is a wrapper for
|
||||
* `from_str_bytes_common()`, for details see there.
|
||||
*/
|
||||
#[inline]
|
||||
pub fn from_str_common<T:NumCast+Zero+One+PartialEq+PartialOrd+Div<T,T>+Mul<T,T>+
|
||||
Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
|
||||
buf: &str, radix: uint, negative: bool, fractional: bool,
|
||||
special: bool, exponent: ExponentFormat, empty_zero: bool,
|
||||
ignore_underscores: bool
|
||||
) -> Option<T> {
|
||||
from_str_bytes_common(buf.as_bytes(), radix, negative,
|
||||
fractional, special, exponent, empty_zero,
|
||||
ignore_underscores)
|
||||
pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
|
||||
assert!(radix >= 2 && radix <= 36,
|
||||
"from_str_radix_int: must lie in the range `[2, 36]` - found {}",
|
||||
radix);
|
||||
|
||||
fn cast<T: Int>(x: uint) -> T {
|
||||
num::cast(x).unwrap()
|
||||
}
|
||||
|
||||
let _0: T = num::zero();
|
||||
let _1: T = num::one();
|
||||
let is_signed = _0 > Bounded::min_value();
|
||||
|
||||
let (is_positive, src) = match src.slice_shift_char() {
|
||||
(Some('-'), src) if is_signed => (false, src),
|
||||
(Some(_), _) => (true, src),
|
||||
(None, _) => return None,
|
||||
};
|
||||
|
||||
let mut xs = src.chars().map(|c| {
|
||||
c.to_digit(radix).map(cast)
|
||||
});
|
||||
let radix = cast(radix);
|
||||
let mut result = _0;
|
||||
|
||||
if is_positive {
|
||||
for x in xs {
|
||||
let x = match x {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_mul(&radix) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_add(&x) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
}
|
||||
} else {
|
||||
for x in xs {
|
||||
let x = match x {
|
||||
Some(x) => x,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_mul(&radix) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
result = match result.checked_sub(&x) {
|
||||
Some(result) => result,
|
||||
None => return None,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
Some(result)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
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_._5_e_1_", 10, false, true, false,
|
||||
ExpDec, false, true);
|
||||
assert_eq!(f, Some(1.5e1f32));
|
||||
}
|
||||
|
||||
#[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, false);
|
||||
assert_eq!(n, None);
|
||||
}
|
||||
use num::Float;
|
||||
|
||||
#[test]
|
||||
fn from_str_issue7588() {
|
||||
let u : Option<u8> = from_str_common("1000", 10, false, false, false,
|
||||
ExpNone, false, false);
|
||||
let u : Option<u8> = from_str_radix_int("1000", 10);
|
||||
assert_eq!(u, None);
|
||||
let s : Option<i16> = from_str_common("80000", 10, false, false, false,
|
||||
ExpNone, false, false);
|
||||
let s : Option<i16> = from_str_radix_int("80000", 10);
|
||||
assert_eq!(s, None);
|
||||
let f : Option<f32> = from_str_common(
|
||||
"10000000000000000000000000000000000000000", 10, false, false, false,
|
||||
ExpNone, false, false);
|
||||
assert_eq!(f, NumStrConv::inf())
|
||||
let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
|
||||
ExpDec, false, false);
|
||||
assert_eq!(fe, NumStrConv::inf())
|
||||
let f : Option<f32> = from_str_radix_float("10000000000000000000000000000000000000000", 10);
|
||||
assert_eq!(f, Some(Float::infinity()))
|
||||
let fe : Option<f32> = from_str_radix_float("1e40", 10);
|
||||
assert_eq!(fe, Some(Float::infinity()))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -15,31 +15,11 @@
|
|||
|
||||
macro_rules! uint_module (($T:ty) => (
|
||||
|
||||
// String conversion functions and impl str -> num
|
||||
|
||||
/// Parse a byte slice as a number in the given base
|
||||
///
|
||||
/// Yields an `Option` because `buf` may or may not actually be parseable.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```
|
||||
/// let num = std::uint::parse_bytes([49,50,51,52,53,54,55,56,57], 10);
|
||||
/// assert!(num == Some(123456789));
|
||||
/// ```
|
||||
#[inline]
|
||||
#[experimental = "might need to return Result"]
|
||||
pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
|
||||
strconv::from_str_bytes_common(buf, radix, false, false, false,
|
||||
strconv::ExpNone, false, false)
|
||||
}
|
||||
|
||||
#[experimental = "might need to return Result"]
|
||||
impl FromStr for $T {
|
||||
#[inline]
|
||||
fn from_str(s: &str) -> Option<$T> {
|
||||
strconv::from_str_common(s, 10u, false, false, false,
|
||||
strconv::ExpNone, false, false)
|
||||
strconv::from_str_radix_int(s, 10)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -47,8 +27,7 @@ impl FromStr for $T {
|
|||
impl FromStrRadix for $T {
|
||||
#[inline]
|
||||
fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
|
||||
strconv::from_str_common(s, radix, false, false, false,
|
||||
strconv::ExpNone, false, false)
|
||||
strconv::from_str_radix_int(s, radix)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -85,10 +64,7 @@ pub fn to_str_bytes<U>(n: $T, radix: uint, f: |v: &[u8]| -> U) -> U {
|
|||
#[cfg(test)]
|
||||
mod tests {
|
||||
use prelude::*;
|
||||
use super::*;
|
||||
|
||||
use str::StrSlice;
|
||||
use u16;
|
||||
use num::FromStrRadix;
|
||||
|
||||
#[test]
|
||||
pub fn test_from_str() {
|
||||
|
|
@ -98,23 +74,22 @@ mod tests {
|
|||
assert_eq!(from_str::<u32>("123456789"), Some(123456789 as u32));
|
||||
assert_eq!(from_str::<$T>("00100"), Some(100u as $T));
|
||||
|
||||
assert!(from_str::<$T>("").is_none());
|
||||
assert!(from_str::<$T>(" ").is_none());
|
||||
assert!(from_str::<$T>("x").is_none());
|
||||
assert_eq!(from_str::<$T>(""), None);
|
||||
assert_eq!(from_str::<$T>(" "), None);
|
||||
assert_eq!(from_str::<$T>("x"), None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
pub fn test_parse_bytes() {
|
||||
use str::StrSlice;
|
||||
assert_eq!(parse_bytes("123".as_bytes(), 10u), Some(123u as $T));
|
||||
assert_eq!(parse_bytes("1001".as_bytes(), 2u), Some(9u as $T));
|
||||
assert_eq!(parse_bytes("123".as_bytes(), 8u), Some(83u as $T));
|
||||
assert_eq!(u16::parse_bytes("123".as_bytes(), 16u), Some(291u as u16));
|
||||
assert_eq!(u16::parse_bytes("ffff".as_bytes(), 16u), Some(65535u as u16));
|
||||
assert_eq!(parse_bytes("z".as_bytes(), 36u), Some(35u as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 10), Some(123u as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("1001", 2), Some(9u as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 8), Some(83u as $T));
|
||||
assert_eq!(FromStrRadix::from_str_radix("123", 16), Some(291u as u16));
|
||||
assert_eq!(FromStrRadix::from_str_radix("ffff", 16), Some(65535u as u16));
|
||||
assert_eq!(FromStrRadix::from_str_radix("z", 36), Some(35u as $T));
|
||||
|
||||
assert!(parse_bytes("Z".as_bytes(), 10u).is_none());
|
||||
assert!(parse_bytes("_".as_bytes(), 2u).is_none());
|
||||
assert_eq!(FromStrRadix::from_str_radix("Z", 10), None::<$T>);
|
||||
assert_eq!(FromStrRadix::from_str_radix("_", 2), None::<$T>);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
@ -148,35 +123,35 @@ mod tests {
|
|||
fn test_uint_from_str_overflow() {
|
||||
let mut u8_val: u8 = 255_u8;
|
||||
assert_eq!(from_str::<u8>("255"), Some(u8_val));
|
||||
assert!(from_str::<u8>("256").is_none());
|
||||
assert_eq!(from_str::<u8>("256"), None);
|
||||
|
||||
u8_val += 1 as u8;
|
||||
assert_eq!(from_str::<u8>("0"), Some(u8_val));
|
||||
assert!(from_str::<u8>("-1").is_none());
|
||||
assert_eq!(from_str::<u8>("-1"), None);
|
||||
|
||||
let mut u16_val: u16 = 65_535_u16;
|
||||
assert_eq!(from_str::<u16>("65535"), Some(u16_val));
|
||||
assert!(from_str::<u16>("65536").is_none());
|
||||
assert_eq!(from_str::<u16>("65536"), None);
|
||||
|
||||
u16_val += 1 as u16;
|
||||
assert_eq!(from_str::<u16>("0"), Some(u16_val));
|
||||
assert!(from_str::<u16>("-1").is_none());
|
||||
assert_eq!(from_str::<u16>("-1"), None);
|
||||
|
||||
let mut u32_val: u32 = 4_294_967_295_u32;
|
||||
assert_eq!(from_str::<u32>("4294967295"), Some(u32_val));
|
||||
assert!(from_str::<u32>("4294967296").is_none());
|
||||
assert_eq!(from_str::<u32>("4294967296"), None);
|
||||
|
||||
u32_val += 1 as u32;
|
||||
assert_eq!(from_str::<u32>("0"), Some(u32_val));
|
||||
assert!(from_str::<u32>("-1").is_none());
|
||||
assert_eq!(from_str::<u32>("-1"), None);
|
||||
|
||||
let mut u64_val: u64 = 18_446_744_073_709_551_615_u64;
|
||||
assert_eq!(from_str::<u64>("18446744073709551615"), Some(u64_val));
|
||||
assert!(from_str::<u64>("18446744073709551616").is_none());
|
||||
assert_eq!(from_str::<u64>("18446744073709551616"), None);
|
||||
|
||||
u64_val += 1 as u64;
|
||||
assert_eq!(from_str::<u64>("0"), Some(u64_val));
|
||||
assert!(from_str::<u64>("-1").is_none());
|
||||
assert_eq!(from_str::<u64>("-1"), None);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,6 @@ extern crate time;
|
|||
use std::os;
|
||||
use std::result::{Ok, Err};
|
||||
use std::task;
|
||||
use std::uint;
|
||||
|
||||
fn fib(n: int) -> int {
|
||||
fn pfib(tx: &Sender<int>, n: int) {
|
||||
|
|
@ -102,8 +101,7 @@ fn main() {
|
|||
if opts.stress {
|
||||
stress(2);
|
||||
} else {
|
||||
let max = uint::parse_bytes(args[1].as_bytes(), 10u).unwrap() as
|
||||
int;
|
||||
let max = from_str::<uint>(args[1].as_slice()).unwrap() as int;
|
||||
|
||||
let num_trials = 10;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue