diff --git a/src/compiletest/common.rs b/src/compiletest/common.rs index 2c917f7aefe..b7d4596b0fe 100644 --- a/src/compiletest/common.rs +++ b/src/compiletest/common.rs @@ -8,8 +8,8 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::from_str::FromStr; use std::fmt; +use std::str::FromStr; use regex::Regex; #[deriving(Clone, PartialEq)] diff --git a/src/compiletest/compiletest.rs b/src/compiletest/compiletest.rs index caf1c8c314d..d49ff0258ab 100644 --- a/src/compiletest/compiletest.rs +++ b/src/compiletest/compiletest.rs @@ -22,7 +22,7 @@ extern crate regex; use std::os; use std::io; use std::io::fs; -use std::from_str::FromStr; +use std::str::FromStr; use getopts::{optopt, optflag, reqopt}; use common::Config; use common::{Pretty, DebugInfoGdb, DebugInfoLldb, Codegen}; diff --git a/src/compiletest/header.rs b/src/compiletest/header.rs index b7b94ca6d0d..60ef76528e8 100644 --- a/src/compiletest/header.rs +++ b/src/compiletest/header.rs @@ -12,8 +12,6 @@ use common::Config; use common; use util; -use std::from_str::FromStr; - pub struct TestProps { // Lines that should be expected, in order, on standard out pub error_patterns: Vec , @@ -353,8 +351,8 @@ pub fn gdb_version_to_int(version_string: &str) -> int { panic!("{}", error_string); } - let major: int = FromStr::from_str(components[0]).expect(error_string); - let minor: int = FromStr::from_str(components[1]).expect(error_string); + let major: int = from_str(components[0]).expect(error_string); + let minor: int = from_str(components[1]).expect(error_string); return major * 1000 + minor; } @@ -364,6 +362,6 @@ pub fn lldb_version_to_int(version_string: &str) -> int { "Encountered LLDB version string with unexpected format: {}", version_string); let error_string = error_string.as_slice(); - let major: int = FromStr::from_str(version_string).expect(error_string); + let major: int = from_str(version_string).expect(error_string); return major; } diff --git a/src/doc/reference.md b/src/doc/reference.md index d05705562d2..b3bf554f30c 100644 --- a/src/doc/reference.md +++ b/src/doc/reference.md @@ -3108,11 +3108,10 @@ then the expression completes. Some examples of call expressions: ``` -# use std::from_str::FromStr; # fn add(x: int, y: int) -> int { 0 } let x: int = add(1, 2); -let pi: Option = FromStr::from_str("3.14"); +let pi: Option = from_str("3.14"); ``` ### Lambda expressions diff --git a/src/libcollections/str.rs b/src/libcollections/str.rs index 20aa29fbb3d..a2f89dfecbc 100644 --- a/src/libcollections/str.rs +++ b/src/libcollections/str.rs @@ -73,6 +73,7 @@ pub use core::str::{CharSplitsN, AnyLines, MatchIndices, StrSplits}; pub use core::str::{Utf16CodeUnits, eq_slice, is_utf8, is_utf16, Utf16Items}; pub use core::str::{Utf16Item, ScalarValue, LoneSurrogate, utf16_items}; pub use core::str::{truncate_utf16_at_nul, utf8_char_width, CharRange}; +pub use core::str::{FromStr, from_str}; pub use core::str::{Str, StrPrelude}; pub use unicode::str::{UnicodeStrPrelude, Words, Graphemes, GraphemeIndices}; diff --git a/src/libcollections/string.rs b/src/libcollections/string.rs index 5872afc6fde..c1e093436c3 100644 --- a/src/libcollections/string.rs +++ b/src/libcollections/string.rs @@ -25,7 +25,7 @@ use core::raw::Slice as RawSlice; use hash; use slice::CloneSliceAllocPrelude; use str; -use str::{CharRange, StrAllocating, MaybeOwned, Owned}; +use str::{CharRange, FromStr, StrAllocating, MaybeOwned, Owned}; use str::Slice as MaybeOwnedSlice; // So many `Slice`s... use vec::{DerefVec, Vec, as_vec}; @@ -795,6 +795,13 @@ pub fn as_string<'a>(x: &'a str) -> DerefString<'a> { DerefString { x: as_vec(x.as_bytes()) } } +impl FromStr for String { + #[inline] + fn from_str(s: &str) -> Option { + Some(String::from_str(s)) + } +} + /// Unsafe operations #[unstable = "waiting on raw module conventions"] pub mod raw { diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index ba03bb8f3d5..c674a806836 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -17,7 +17,9 @@ use intrinsics; use mem; use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; -use num::Float; +use num::{Float, FromStrRadix}; +use num::strconv; +use str::FromStr; use option::Option; pub const RADIX: uint = 2u; @@ -424,3 +426,66 @@ impl Float for f32 { self * (value / 180.0f32) } } + +#[inline] +#[allow(missing_docs)] +#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] +pub fn from_str_hex(src: &str) -> Option { + strconv::from_str_radix_float(src, 16) +} + +impl FromStr for f32 { + /// Convert a string in base 10 to a float. + /// Accepts an optional decimal exponent. + /// + /// 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' + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * 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 `src`. + #[inline] + fn from_str(src: &str) -> Option { + strconv::from_str_radix_float(src, 10u) + } +} + +impl FromStrRadix for f32 { + /// 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 + /// + /// * 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 `src`. + #[inline] + fn from_str_radix(src: &str, radix: uint) -> Option { + strconv::from_str_radix_float(src, radix) + } +} diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index f1af4f0272c..2abd6c237c8 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -17,7 +17,9 @@ use intrinsics; use mem; use num::{FPNormal, FPCategory, FPZero, FPSubnormal, FPInfinite, FPNaN}; -use num::Float; +use num::{Float, FromStrRadix}; +use num::strconv; +use str::FromStr; use option::Option; // FIXME(#5527): These constants should be deprecated once associated @@ -430,3 +432,61 @@ impl Float for f64 { self * (value / 180.0) } } + +#[inline] +#[allow(missing_docs)] +#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] +pub fn from_str_hex(src: &str) -> Option { + 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: + /// + /// * '3.14' + /// * '-3.14' + /// * '2.5E10', or equivalently, '2.5e10' + /// * '2.5E-10' + /// * '.' (understood as 0) + /// * '5.' + /// * '.5', or, equivalently, '0.5' + /// * inf', '-inf', 'NaN' + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * 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 `src`. + #[inline] + fn from_str(src: &str) -> Option { + strconv::from_str_radix_float(src, 10u) + } +} + +impl FromStrRadix for f64 { + /// Convert a string in a given base to a float. + /// + /// Leading and trailing whitespace represent an error. + /// + /// # Arguments + /// + /// * 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 `src`. + #[inline] + fn from_str_radix(src: &str, radix: uint) -> Option { + strconv::from_str_radix_float(src, radix) + } +} diff --git a/src/libcore/num/int_macros.rs b/src/libcore/num/int_macros.rs index 0f8950344c8..dc60a0c9764 100644 --- a/src/libcore/num/int_macros.rs +++ b/src/libcore/num/int_macros.rs @@ -32,4 +32,20 @@ pub const MIN: $T = (-1 as $T) << (BITS - 1); #[unstable] pub const MAX: $T = !MIN; +#[experimental = "might need to return Result"] +impl ::str::FromStr for $T { + #[inline] + fn from_str(s: &str) -> ::option::Option<$T> { + ::num::strconv::from_str_radix_int(s, 10) + } +} + +#[experimental = "might need to return Result"] +impl ::num::FromStrRadix for $T { + #[inline] + fn from_str_radix(s: &str, radix: uint) -> ::option::Option<$T> { + ::num::strconv::from_str_radix_int(s, radix) + } +} + )) diff --git a/src/libcore/num/mod.rs b/src/libcore/num/mod.rs index 216d140ac48..391ccce568b 100644 --- a/src/libcore/num/mod.rs +++ b/src/libcore/num/mod.rs @@ -27,6 +27,8 @@ use ops::{Add, Sub, Mul, Div, Rem, Neg}; use ops::{Not, BitAnd, BitOr, BitXor, Shl, Shr}; use option::{Option, Some, None}; +pub mod strconv; + /// Simultaneous division and remainder #[inline] pub fn div_rem + Rem>(x: T, y: T) -> (T, T) { @@ -1372,6 +1374,18 @@ pub trait Float fn to_radians(self) -> Self; } +/// A generic trait for converting a string with a radix (base) to a value +#[experimental = "might need to return Result"] +pub trait FromStrRadix { + fn from_str_radix(str: &str, radix: uint) -> Option; +} + +/// A utility function that just calls FromStrRadix::from_str_radix. +#[experimental = "might need to return Result"] +pub fn from_str_radix(str: &str, radix: uint) -> Option { + FromStrRadix::from_str_radix(str, radix) +} + // DEPRECATED macro_rules! trait_impl { diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs new file mode 100644 index 00000000000..daa2a8e2343 --- /dev/null +++ b/src/libcore/num/strconv.rs @@ -0,0 +1,259 @@ +// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution and at +// http://rust-lang.org/COPYRIGHT. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. +// +// ignore-lexer-test FIXME #15679 + +#![allow(missing_docs)] + +use char::Char; +use iter::Iterator; +use num; +use num::{Int, Float}; +use option::{None, Option, Some}; +use str::{from_str, StrPrelude}; + +pub fn from_str_radix_float(src: &str, radix: uint) -> Option { + assert!(radix >= 2 && radix <= 36, + "from_str_radix_float: must lie in the range `[2, 36]` - found {}", + radix); + + let _0: T = Float::zero(); + let _1: T = Float::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 (is_positive, src) = match src.slice_shift_char() { + (None, _) => return None, + (Some('-'), "") => return None, + (Some('-'), src) => (false, src), + (Some(_), _) => (true, src), + }; + + // The significand to accumulate + let mut sig = if is_positive { _0 } else { -_0 }; + // 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 the integer part of the significand + for (i, c) in cs { + match c.to_digit(radix) { + Some(digit) => { + // shift significand one digit left + sig = sig * radix_t; + + // add/subtract current digit depending on sign + if is_positive { + sig = sig + num::cast(digit as int).unwrap(); + } else { + 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 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 + 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()); } + } + prev_sig = sig; + }, + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + '.' => { + break; // start of fractional part + }, + _ => { + return None; + }, + }, + } + } + + // 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_t; + // add/subtract current digit depending on sign + sig = if is_positive { + sig + digit * power + } else { + sig - digit * power + }; + // Detect overflow by comparing to last value + 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 { + 'e' | 'E' | 'p' | 'P' => { + exp_info = Some((c, i + 1)); + break; // start of exponent + }, + _ => { + return None; // invalid number + }, + }, + } + } + } + + // 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, + }; + + // Parse the exponent as decimal integer + let src = src[offset..]; + let (is_positive, exp) = match src.slice_shift_char() { + (Some('-'), src) => (false, from_str::(src)), + (Some('+'), src) => (true, from_str::(src)), + (Some(_), _) => (true, from_str::(src)), + (None, _) => return None, + }; + + match (is_positive, exp) { + (true, Some(exp)) => base.powi(exp as i32), + (false, Some(exp)) => _1 / base.powi(exp as i32), + (_, None) => return None, + } + }, + None => _1, // no exponent + }; + + Some(sig * exp) +} + +pub fn from_str_radix_int(src: &str, radix: uint) -> Option { + assert!(radix >= 2 && radix <= 36, + "from_str_radix_int: must lie in the range `[2, 36]` - found {}", + radix); + + fn cast(x: uint) -> T { + num::cast(x).unwrap() + } + + let _0: T = Int::zero(); + let _1: T = Int::one(); + let is_signed = _0 > Int::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::*; + use num::Float; + + #[test] + fn from_str_issue7588() { + let u : Option = from_str_radix_int("1000", 10); + assert_eq!(u, None); + let s : Option = from_str_radix_int("80000", 10); + assert_eq!(s, None); + let f : Option = from_str_radix_float("10000000000000000000000000000000000000000", 10); + assert_eq!(f, Some(Float::infinity())) + let fe : Option = from_str_radix_float("1e40", 10); + assert_eq!(fe, Some(Float::infinity())) + } + + #[test] + fn test_from_str_radix_float() { + let x1 : Option = from_str_radix_float("-123.456", 10); + assert_eq!(x1, Some(-123.456)); + let x2 : Option = from_str_radix_float("123.456", 10); + assert_eq!(x2, Some(123.456)); + let x3 : Option = from_str_radix_float("-0.0", 10); + assert_eq!(x3, Some(-0.0)); + let x4 : Option = from_str_radix_float("0.0", 10); + assert_eq!(x4, Some(0.0)); + let x4 : Option = from_str_radix_float("1.0", 10); + assert_eq!(x4, Some(1.0)); + let x5 : Option = from_str_radix_float("-1.0", 10); + assert_eq!(x5, Some(-1.0)); + } +} diff --git a/src/libcore/num/uint_macros.rs b/src/libcore/num/uint_macros.rs index 2a94f851646..4977e5d6680 100644 --- a/src/libcore/num/uint_macros.rs +++ b/src/libcore/num/uint_macros.rs @@ -23,4 +23,20 @@ pub const MIN: $T = 0 as $T; #[unstable] pub const MAX: $T = 0 as $T - 1 as $T; +#[experimental = "might need to return Result"] +impl ::str::FromStr for $T { + #[inline] + fn from_str(s: &str) -> ::option::Option<$T> { + ::num::strconv::from_str_radix_int(s, 10) + } +} + +#[experimental = "might need to return Result"] +impl ::num::FromStrRadix for $T { + #[inline] + fn from_str_radix(s: &str, radix: uint) -> ::option::Option<$T> { + ::num::strconv::from_str_radix_int(s, radix) + } +} + )) diff --git a/src/libcore/prelude.rs b/src/libcore/prelude.rs index 60012ab149f..101eb7ac74c 100644 --- a/src/libcore/prelude.rs +++ b/src/libcore/prelude.rs @@ -41,6 +41,7 @@ pub use ops::{Fn, FnMut, FnOnce}; // Reexported functions pub use iter::{range, repeat}; pub use mem::drop; +pub use str::from_str; // Reexported types and traits diff --git a/src/libcore/str.rs b/src/libcore/str.rs index 745de5f179e..ab4e50c58d9 100644 --- a/src/libcore/str.rs +++ b/src/libcore/str.rs @@ -31,6 +31,42 @@ use raw::Repr; use slice::{mod, SlicePrelude}; use uint; +/// A trait to abstract the idea of creating a new instance of a type from a +/// string. +#[experimental = "might need to return Result"] +pub trait FromStr { + /// Parses a string `s` to return an optional value of this type. If the + /// string is ill-formatted, the None is returned. + fn from_str(s: &str) -> Option; +} + +/// A utility function that just calls FromStr::from_str +pub fn from_str(s: &str) -> Option { + FromStr::from_str(s) +} + +impl FromStr for bool { + /// Parse a `bool` from a string. + /// + /// Yields an `Option`, because `s` may or may not actually be parseable. + /// + /// # Examples + /// + /// ```rust + /// assert_eq!(from_str::("true"), Some(true)); + /// assert_eq!(from_str::("false"), Some(false)); + /// assert_eq!(from_str::("not even a boolean"), None); + /// ``` + #[inline] + fn from_str(s: &str) -> Option { + match s { + "true" => Some(true), + "false" => Some(false), + _ => None, + } + } +} + /* Section: Creating a string */ diff --git a/src/libcoretest/num/int_macros.rs b/src/libcoretest/num/int_macros.rs index 5e2530ef2a9..e25f10bd0da 100644 --- a/src/libcoretest/num/int_macros.rs +++ b/src/libcoretest/num/int_macros.rs @@ -15,7 +15,8 @@ macro_rules! int_module (($T:ty, $T_i:ident) => ( mod tests { use core::$T_i::*; use core::int; - use core::num::{Int, SignedInt}; + use core::num::{FromStrRadix, Int, SignedInt}; + use core::str::from_str; use num; #[test] @@ -156,6 +157,49 @@ mod tests { assert!(5i.checked_div(0) == None); assert!(int::MIN.checked_div(-1) == None); } + + #[test] + fn test_from_str() { + assert_eq!(from_str::<$T>("0"), Some(0 as $T)); + assert_eq!(from_str::<$T>("3"), Some(3 as $T)); + assert_eq!(from_str::<$T>("10"), Some(10 as $T)); + assert_eq!(from_str::("123456789"), Some(123456789 as i32)); + assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); + + assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); + assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); + assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); + assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); + assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); + + assert_eq!(from_str::<$T>(""), None); + assert_eq!(from_str::<$T>(" "), None); + assert_eq!(from_str::<$T>("x"), None); + } + + #[test] + 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!(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!(FromStrRadix::from_str_radix("Z", 35), None::<$T>); + assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>); + } } )) diff --git a/src/libcoretest/num/mod.rs b/src/libcoretest/num/mod.rs index 38502321c1d..0cd1ded21d6 100644 --- a/src/libcoretest/num/mod.rs +++ b/src/libcoretest/num/mod.rs @@ -45,3 +45,73 @@ pub fn test_num(ten: T, two: T) where assert_eq!(ten.div(&two), ten / two); assert_eq!(ten.rem(&two), ten % two); } + +#[cfg(test)] +mod test { + use core::option::{Option, Some, None}; + use core::num::Float; + use core::num::from_str_radix; + + #[test] + fn from_str_issue7588() { + let u : Option = from_str_radix("1000", 10); + assert_eq!(u, None); + let s : Option = from_str_radix("80000", 10); + assert_eq!(s, None); + let f : Option = from_str_radix("10000000000000000000000000000000000000000", 10); + assert_eq!(f, Some(Float::infinity())) + let fe : Option = from_str_radix("1e40", 10); + assert_eq!(fe, Some(Float::infinity())) + } + + #[test] + fn test_from_str_radix_float() { + let x1 : Option = from_str_radix("-123.456", 10); + assert_eq!(x1, Some(-123.456)); + let x2 : Option = from_str_radix("123.456", 10); + assert_eq!(x2, Some(123.456)); + let x3 : Option = from_str_radix("-0.0", 10); + assert_eq!(x3, Some(-0.0)); + let x4 : Option = from_str_radix("0.0", 10); + assert_eq!(x4, Some(0.0)); + let x4 : Option = from_str_radix("1.0", 10); + assert_eq!(x4, Some(1.0)); + let x5 : Option = from_str_radix("-1.0", 10); + assert_eq!(x5, Some(-1.0)); + } + + #[test] + fn test_int_from_str_overflow() { + let mut i8_val: i8 = 127_i8; + assert_eq!(from_str::("127"), Some(i8_val)); + assert_eq!(from_str::("128"), None); + + i8_val += 1 as i8; + assert_eq!(from_str::("-128"), Some(i8_val)); + assert_eq!(from_str::("-129"), None); + + let mut i16_val: i16 = 32_767_i16; + assert_eq!(from_str::("32767"), Some(i16_val)); + assert_eq!(from_str::("32768"), None); + + i16_val += 1 as i16; + assert_eq!(from_str::("-32768"), Some(i16_val)); + assert_eq!(from_str::("-32769"), None); + + let mut i32_val: i32 = 2_147_483_647_i32; + assert_eq!(from_str::("2147483647"), Some(i32_val)); + assert_eq!(from_str::("2147483648"), None); + + i32_val += 1 as i32; + assert_eq!(from_str::("-2147483648"), Some(i32_val)); + assert_eq!(from_str::("-2147483649"), None); + + let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + assert_eq!(from_str::("9223372036854775807"), Some(i64_val)); + assert_eq!(from_str::("9223372036854775808"), None); + + i64_val += 1 as i64; + assert_eq!(from_str::("-9223372036854775808"), Some(i64_val)); + assert_eq!(from_str::("-9223372036854775809"), None); + } +} diff --git a/src/libcoretest/str.rs b/src/libcoretest/str.rs index d3f77c47c44..5f44fd807cc 100644 --- a/src/libcoretest/str.rs +++ b/src/libcoretest/str.rs @@ -8,6 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +#[test] +fn test_bool_from_str() { + assert_eq!(from_str::("true"), Some(true)); + assert_eq!(from_str::("false"), Some(false)); + assert_eq!(from_str::("not even a boolean"), None); +} + fn check_contains_all_substrings(s: &str) { assert!(s.contains("")); for i in range(0, s.len()) { diff --git a/src/libregex/re.rs b/src/libregex/re.rs index df5bfccd18d..c7540852970 100644 --- a/src/libregex/re.rs +++ b/src/libregex/re.rs @@ -10,7 +10,6 @@ use std::collections::HashMap; use std::fmt; -use std::from_str::from_str; use std::str::{MaybeOwned, Owned, Slice}; use compile::Program; diff --git a/src/librustc/driver/config.rs b/src/librustc/driver/config.rs index 8c1d7c839ac..10cf92e32c3 100644 --- a/src/librustc/driver/config.rs +++ b/src/librustc/driver/config.rs @@ -334,8 +334,7 @@ macro_rules! cgoptions( } fn parse_uint(slot: &mut uint, v: Option<&str>) -> bool { - use std::from_str::FromStr; - match v.and_then(FromStr::from_str) { + match v.and_then(from_str) { Some(i) => { *slot = i; true }, None => false } diff --git a/src/librustc/driver/pretty.rs b/src/librustc/driver/pretty.rs index 0a7cfdeeadc..7b6de088319 100644 --- a/src/librustc/driver/pretty.rs +++ b/src/librustc/driver/pretty.rs @@ -31,8 +31,8 @@ use syntax::print::{pp, pprust}; use graphviz as dot; use std::io::{mod, MemReader}; -use std::from_str::FromStr; use std::option; +use std::str::FromStr; use arena::TypedArena; #[deriving(PartialEq, Show)] diff --git a/src/libserialize/json.rs b/src/libserialize/json.rs index 524638155ac..56e90da533c 100644 --- a/src/libserialize/json.rs +++ b/src/libserialize/json.rs @@ -200,7 +200,7 @@ use std::{char, f64, fmt, io, num, str}; use std::io::MemWriter; use std::mem::{swap, transmute}; use std::num::{Float, FPNaN, FPInfinite, Int}; -use std::str::ScalarValue; +use std::str::{FromStr, ScalarValue}; use std::string; use std::vec::Vec; use std::ops; @@ -1988,7 +1988,7 @@ macro_rules! read_primitive { String(s) => { // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. - match std::from_str::from_str(s.as_slice()) { + match std::str::from_str(s.as_slice()) { Some(f) => Ok(f), None => Err(ExpectedError("Number".to_string(), s)), } @@ -2027,7 +2027,7 @@ impl ::Decoder for Decoder { String(s) => { // re: #12967.. a type w/ numeric keys (ie HashMap etc) // is going to have a string here, as per JSON spec. - match std::from_str::from_str(s.as_slice()) { + match std::str::from_str(s.as_slice()) { Some(f) => Ok(f), None => Err(ExpectedError("Number".to_string(), s)), } @@ -2395,7 +2395,7 @@ impl fmt::Show for Json { } } -impl std::from_str::FromStr for Json { +impl FromStr for Json { fn from_str(s: &str) -> Option { from_str(s).ok() } @@ -2480,7 +2480,7 @@ mod tests { #[test] fn test_from_str_trait() { let s = "null"; - assert!(::std::from_str::from_str::(s).unwrap() == from_str(s).unwrap()); + assert!(::std::str::from_str::(s).unwrap() == from_str(s).unwrap()); } #[test] diff --git a/src/libstd/from_str.rs b/src/libstd/from_str.rs deleted file mode 100644 index 21b1e0560a5..00000000000 --- a/src/libstd/from_str.rs +++ /dev/null @@ -1,71 +0,0 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! The `FromStr` trait for types that can be created from strings - -#![experimental] - -use option::{Option, Some, None}; -use string::String; - -/// A trait to abstract the idea of creating a new instance of a type from a -/// string. -#[experimental = "might need to return Result"] -pub trait FromStr { - /// Parses a string `s` to return an optional value of this type. If the - /// string is ill-formatted, the None is returned. - fn from_str(s: &str) -> Option; -} - -/// A utility function that just calls FromStr::from_str -pub fn from_str(s: &str) -> Option { - FromStr::from_str(s) -} - -impl FromStr for bool { - /// Parse a `bool` from a string. - /// - /// Yields an `Option`, because `s` may or may not actually be parseable. - /// - /// # Examples - /// - /// ```rust - /// assert_eq!(from_str::("true"), Some(true)); - /// assert_eq!(from_str::("false"), Some(false)); - /// assert_eq!(from_str::("not even a boolean"), None); - /// ``` - #[inline] - fn from_str(s: &str) -> Option { - match s { - "true" => Some(true), - "false" => Some(false), - _ => None, - } - } -} - -impl FromStr for String { - #[inline] - fn from_str(s: &str) -> Option { - Some(String::from_str(s)) - } -} - -#[cfg(test)] -mod test { - use prelude::*; - - #[test] - fn test_bool_from_str() { - assert_eq!(from_str::("true"), Some(true)); - assert_eq!(from_str::("false"), Some(false)); - assert_eq!(from_str::("not even a boolean"), None); - } -} diff --git a/src/libstd/io/net/ip.rs b/src/libstd/io/net/ip.rs index 2a2d978ef49..7ba5e173182 100644 --- a/src/libstd/io/net/ip.rs +++ b/src/libstd/io/net/ip.rs @@ -16,13 +16,12 @@ #![allow(missing_docs)] use fmt; -use from_str::FromStr; use io::{mod, IoResult, IoError}; use io::net; use iter::Iterator; use option::{Option, None, Some}; use result::{Ok, Err}; -use str::StrPrelude; +use str::{FromStr, StrPrelude}; use slice::{CloneSlicePrelude, SlicePrelude}; use vec::Vec; @@ -540,7 +539,7 @@ impl<'a> ToSocketAddr for &'a str { mod test { use prelude::*; use super::*; - use from_str::FromStr; + use str::FromStr; #[test] fn test_from_str_ipv4() { diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs index 3940d7db66e..4e063223329 100644 --- a/src/libstd/lib.rs +++ b/src/libstd/lib.rs @@ -54,7 +54,7 @@ //! //! For converting to strings use the [`format!`](fmt/index.html) //! macro, and for converting from strings use the -//! [`FromStr`](from_str/index.html) trait. +//! [`FromStr`](str/trait.FromStr.html) trait. //! //! ## Platform abstractions //! @@ -219,7 +219,6 @@ pub mod time; /* Common traits */ pub mod error; -pub mod from_str; pub mod num; pub mod to_string; diff --git a/src/libstd/num/f32.rs b/src/libstd/num/f32.rs index 3f46cc8af50..207fa649930 100644 --- a/src/libstd/num/f32.rs +++ b/src/libstd/num/f32.rs @@ -17,12 +17,10 @@ use prelude::*; -use from_str::FromStr; use intrinsics; use libc::c_int; use num::{Float, FloatMath}; use num::strconv; -use num; pub use core::f32::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; pub use core::f32::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; @@ -339,68 +337,6 @@ pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> String { r } -#[inline] -#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] -pub fn from_str_hex(src: &str) -> Option { - strconv::from_str_radix_float(src, 16) -} - -impl FromStr for f32 { - /// Convert a string in base 10 to a float. - /// Accepts an optional decimal exponent. - /// - /// 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' - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * 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 `src`. - #[inline] - fn from_str(src: &str) -> Option { - strconv::from_str_radix_float(src, 10u) - } -} - -impl num::FromStrRadix for f32 { - /// 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 - /// - /// * 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 `src`. - #[inline] - fn from_str_radix(src: &str, radix: uint) -> Option { - strconv::from_str_radix_float(src, radix) - } -} - #[cfg(test)] mod tests { use f32::*; diff --git a/src/libstd/num/f64.rs b/src/libstd/num/f64.rs index 4d691fc9676..543d50596e8 100644 --- a/src/libstd/num/f64.rs +++ b/src/libstd/num/f64.rs @@ -16,12 +16,10 @@ use prelude::*; -use from_str::FromStr; use intrinsics; use libc::c_int; use num::{Float, FloatMath}; use num::strconv; -use num; pub use core::f64::{RADIX, MANTISSA_DIGITS, DIGITS, EPSILON, MIN_VALUE}; pub use core::f64::{MIN_POS_VALUE, MAX_VALUE, MIN_EXP, MAX_EXP, MIN_10_EXP}; @@ -347,63 +345,6 @@ pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> String { r } -#[inline] -#[deprecated="Use `FromStrRadix::from_str_radix(src, 16)`"] -pub fn from_str_hex(src: &str) -> Option { - 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: - /// - /// * '3.14' - /// * '-3.14' - /// * '2.5E10', or equivalently, '2.5e10' - /// * '2.5E-10' - /// * '.' (understood as 0) - /// * '5.' - /// * '.5', or, equivalently, '0.5' - /// * inf', '-inf', 'NaN' - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * 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 `src`. - #[inline] - fn from_str(src: &str) -> Option { - strconv::from_str_radix_float(src, 10u) - } -} - -impl num::FromStrRadix for f64 { - /// Convert a string in a given base to a float. - /// - /// Leading and trailing whitespace represent an error. - /// - /// # Arguments - /// - /// * 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 `src`. - #[inline] - fn from_str_radix(src: &str, radix: uint) -> Option { - strconv::from_str_radix_float(src, radix) - } -} - #[cfg(test)] mod tests { use f64::*; diff --git a/src/libstd/num/i16.rs b/src/libstd/num/i16.rs index d7732b474db..6455c10736a 100644 --- a/src/libstd/num/i16.rs +++ b/src/libstd/num/i16.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i16")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i16::{BITS, BYTES, MIN, MAX}; int_module!(i16) diff --git a/src/libstd/num/i32.rs b/src/libstd/num/i32.rs index 778f1c6748c..39b179c8274 100644 --- a/src/libstd/num/i32.rs +++ b/src/libstd/num/i32.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i32")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i32::{BITS, BYTES, MIN, MAX}; int_module!(i32) diff --git a/src/libstd/num/i64.rs b/src/libstd/num/i64.rs index ae3d57eeac6..a0c474c479a 100644 --- a/src/libstd/num/i64.rs +++ b/src/libstd/num/i64.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i64")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i64::{BITS, BYTES, MIN, MAX}; int_module!(i64) diff --git a/src/libstd/num/i8.rs b/src/libstd/num/i8.rs index 8a3f379893c..e911ed1de9a 100644 --- a/src/libstd/num/i8.rs +++ b/src/libstd/num/i8.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "i8")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::i8::{BITS, BYTES, MIN, MAX}; int_module!(i8) diff --git a/src/libstd/num/int.rs b/src/libstd/num/int.rs index 51af04b32d4..36c021efe0a 100644 --- a/src/libstd/num/int.rs +++ b/src/libstd/num/int.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "int")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::int::{BITS, BYTES, MIN, MAX}; int_module!(int) diff --git a/src/libstd/num/int_macros.rs b/src/libstd/num/int_macros.rs index 9ae146c840a..2f1162d28e5 100644 --- a/src/libstd/num/int_macros.rs +++ b/src/libstd/num/int_macros.rs @@ -14,131 +14,4 @@ macro_rules! int_module (($T:ty) => ( -#[experimental = "might need to return Result"] -impl FromStr for $T { - #[inline] - fn from_str(s: &str) -> Option<$T> { - strconv::from_str_radix_int(s, 10) - } -} - -#[experimental = "might need to return Result"] -impl FromStrRadix for $T { - #[inline] - fn from_str_radix(s: &str, radix: uint) -> Option<$T> { - strconv::from_str_radix_int(s, radix) - } -} - -#[cfg(test)] -mod tests { - use prelude::*; - use num::FromStrRadix; - - #[test] - fn test_from_str() { - assert_eq!(from_str::<$T>("0"), Some(0 as $T)); - assert_eq!(from_str::<$T>("3"), Some(3 as $T)); - assert_eq!(from_str::<$T>("10"), Some(10 as $T)); - assert_eq!(from_str::("123456789"), Some(123456789 as i32)); - assert_eq!(from_str::<$T>("00100"), Some(100 as $T)); - - assert_eq!(from_str::<$T>("-1"), Some(-1 as $T)); - assert_eq!(from_str::<$T>("-3"), Some(-3 as $T)); - assert_eq!(from_str::<$T>("-10"), Some(-10 as $T)); - assert_eq!(from_str::("-123456789"), Some(-123456789 as i32)); - assert_eq!(from_str::<$T>("-00100"), Some(-100 as $T)); - - assert_eq!(from_str::<$T>(""), None); - assert_eq!(from_str::<$T>(" "), None); - assert_eq!(from_str::<$T>("x"), None); - } - - #[test] - 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!(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!(FromStrRadix::from_str_radix("Z", 35), None::<$T>); - assert_eq!(FromStrRadix::from_str_radix("-9", 2), None::<$T>); - } - - #[test] - fn test_int_to_str_overflow() { - let mut i8_val: i8 = 127_i8; - assert_eq!(i8_val.to_string(), "127".to_string()); - - i8_val += 1 as i8; - assert_eq!(i8_val.to_string(), "-128".to_string()); - - let mut i16_val: i16 = 32_767_i16; - assert_eq!(i16_val.to_string(), "32767".to_string()); - - i16_val += 1 as i16; - assert_eq!(i16_val.to_string(), "-32768".to_string()); - - let mut i32_val: i32 = 2_147_483_647_i32; - assert_eq!(i32_val.to_string(), "2147483647".to_string()); - - i32_val += 1 as i32; - assert_eq!(i32_val.to_string(), "-2147483648".to_string()); - - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert_eq!(i64_val.to_string(), "9223372036854775807".to_string()); - - i64_val += 1 as i64; - assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string()); - } - - #[test] - fn test_int_from_str_overflow() { - let mut i8_val: i8 = 127_i8; - assert_eq!(from_str::("127"), Some(i8_val)); - assert_eq!(from_str::("128"), None); - - i8_val += 1 as i8; - assert_eq!(from_str::("-128"), Some(i8_val)); - assert_eq!(from_str::("-129"), None); - - let mut i16_val: i16 = 32_767_i16; - assert_eq!(from_str::("32767"), Some(i16_val)); - assert_eq!(from_str::("32768"), None); - - i16_val += 1 as i16; - assert_eq!(from_str::("-32768"), Some(i16_val)); - assert_eq!(from_str::("-32769"), None); - - let mut i32_val: i32 = 2_147_483_647_i32; - assert_eq!(from_str::("2147483647"), Some(i32_val)); - assert_eq!(from_str::("2147483648"), None); - - i32_val += 1 as i32; - assert_eq!(from_str::("-2147483648"), Some(i32_val)); - assert_eq!(from_str::("-2147483649"), None); - - let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; - assert_eq!(from_str::("9223372036854775807"), Some(i64_val)); - assert_eq!(from_str::("9223372036854775808"), None); - - i64_val += 1 as i64; - assert_eq!(from_str::("-9223372036854775808"), Some(i64_val)); - assert_eq!(from_str::("-9223372036854775809"), None); - } -} - )) diff --git a/src/libstd/num/mod.rs b/src/libstd/num/mod.rs index 0afc8ce0452..73fd2ccd2d3 100644 --- a/src/libstd/num/mod.rs +++ b/src/libstd/num/mod.rs @@ -16,8 +16,6 @@ #![experimental] #![allow(missing_docs)] -use option::Option; - #[cfg(test)] use cmp::PartialEq; #[cfg(test)] use fmt::Show; #[cfg(test)] use ops::{Add, Sub, Mul, Div, Rem}; @@ -31,6 +29,7 @@ pub use core::num::{checked_next_power_of_two}; pub use core::num::{from_int, from_i8, from_i16, from_i32, from_i64}; pub use core::num::{from_uint, from_u8, from_u16, from_u32, from_u64}; pub use core::num::{from_f32, from_f64}; +pub use core::num::{FromStrRadix, from_str_radix}; pub use core::num::{FPCategory, FPNaN, FPInfinite, FPZero, FPSubnormal}; pub use core::num::{FPNormal, Float}; @@ -115,18 +114,6 @@ pub trait FloatMath: Float { fn atanh(self) -> Self; } -/// A generic trait for converting a string with a radix (base) to a value -#[experimental = "might need to return Result"] -pub trait FromStrRadix { - fn from_str_radix(str: &str, radix: uint) -> Option; -} - -/// A utility function that just calls FromStrRadix::from_str_radix. -#[experimental = "might need to return Result"] -pub fn from_str_radix(str: &str, radix: uint) -> Option { - FromStrRadix::from_str_radix(str, radix) -} - // DEPRECATED #[deprecated = "Use `FloatMath::abs_sub`"] diff --git a/src/libstd/num/strconv.rs b/src/libstd/num/strconv.rs index fff31b332e1..31096c0aa46 100644 --- a/src/libstd/num/strconv.rs +++ b/src/libstd/num/strconv.rs @@ -13,12 +13,8 @@ #![allow(missing_docs)] use char; -use char::Char; -use from_str::from_str; -use iter::Iterator; use num; use num::{Int, Float, FPNaN, FPInfinite, ToPrimitive}; -use option::{None, Option, Some}; use slice::{SlicePrelude, CloneSliceAllocPrelude}; use str::StrPrelude; use string::String; @@ -425,242 +421,35 @@ pub fn float_to_str_common( static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u; static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u; -pub fn from_str_radix_float(src: &str, radix: uint) -> Option { - assert!(radix >= 2 && radix <= 36, - "from_str_radix_float: must lie in the range `[2, 36]` - found {}", - radix); - - let _0: T = Float::zero(); - let _1: T = Float::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 (is_positive, src) = match src.slice_shift_char() { - (None, _) => return None, - (Some('-'), "") => return None, - (Some('-'), src) => (false, src), - (Some(_), _) => (true, src), - }; - - // The significand to accumulate - let mut sig = if is_positive { _0 } else { -_0 }; - // 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 the integer part of the significand - for (i, c) in cs { - match c.to_digit(radix) { - Some(digit) => { - // shift significand one digit left - sig = sig * radix_t; - - // add/subtract current digit depending on sign - if is_positive { - sig = sig + num::cast(digit as int).unwrap(); - } else { - 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 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 - 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()); } - } - prev_sig = sig; - }, - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - '.' => { - break; // start of fractional part - }, - _ => { - return None; - }, - }, - } - } - - // 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_t; - // add/subtract current digit depending on sign - sig = if is_positive { - sig + digit * power - } else { - sig - digit * power - }; - // Detect overflow by comparing to last value - 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 { - 'e' | 'E' | 'p' | 'P' => { - exp_info = Some((c, i + 1)); - break; // start of exponent - }, - _ => { - return None; // invalid number - }, - }, - } - } - } - - // 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, - }; - - // Parse the exponent as decimal integer - let src = src[offset..]; - let (is_positive, exp) = match src.slice_shift_char() { - (Some('-'), src) => (false, from_str::(src)), - (Some('+'), src) => (true, from_str::(src)), - (Some(_), _) => (true, from_str::(src)), - (None, _) => return None, - }; - - match (is_positive, exp) { - (true, Some(exp)) => base.powi(exp as i32), - (false, Some(exp)) => _1 / base.powi(exp as i32), - (_, None) => return None, - } - }, - None => _1, // no exponent - }; - - Some(sig * exp) -} - -pub fn from_str_radix_int(src: &str, radix: uint) -> Option { - assert!(radix >= 2 && radix <= 36, - "from_str_radix_int: must lie in the range `[2, 36]` - found {}", - radix); - - fn cast(x: uint) -> T { - num::cast(x).unwrap() - } - - let _0: T = Int::zero(); - let _1: T = Int::one(); - let is_signed = _0 > Int::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::*; - use num::Float; +mod tests { + use to_string::ToString; #[test] - fn from_str_issue7588() { - let u : Option = from_str_radix_int("1000", 10); - assert_eq!(u, None); - let s : Option = from_str_radix_int("80000", 10); - assert_eq!(s, None); - let f : Option = from_str_radix_float("10000000000000000000000000000000000000000", 10); - assert_eq!(f, Some(Float::infinity())) - let fe : Option = from_str_radix_float("1e40", 10); - assert_eq!(fe, Some(Float::infinity())) - } + fn test_int_to_str_overflow() { + let mut i8_val: i8 = 127_i8; + assert_eq!(i8_val.to_string(), "127".to_string()); - #[test] - fn test_from_str_radix_float() { - let x1 : Option = from_str_radix_float("-123.456", 10); - assert_eq!(x1, Some(-123.456)); - let x2 : Option = from_str_radix_float("123.456", 10); - assert_eq!(x2, Some(123.456)); - let x3 : Option = from_str_radix_float("-0.0", 10); - assert_eq!(x3, Some(-0.0)); - let x4 : Option = from_str_radix_float("0.0", 10); - assert_eq!(x4, Some(0.0)); - let x4 : Option = from_str_radix_float("1.0", 10); - assert_eq!(x4, Some(1.0)); - let x5 : Option = from_str_radix_float("-1.0", 10); - assert_eq!(x5, Some(-1.0)); + i8_val += 1 as i8; + assert_eq!(i8_val.to_string(), "-128".to_string()); + + let mut i16_val: i16 = 32_767_i16; + assert_eq!(i16_val.to_string(), "32767".to_string()); + + i16_val += 1 as i16; + assert_eq!(i16_val.to_string(), "-32768".to_string()); + + let mut i32_val: i32 = 2_147_483_647_i32; + assert_eq!(i32_val.to_string(), "2147483647".to_string()); + + i32_val += 1 as i32; + assert_eq!(i32_val.to_string(), "-2147483648".to_string()); + + let mut i64_val: i64 = 9_223_372_036_854_775_807_i64; + assert_eq!(i64_val.to_string(), "9223372036854775807".to_string()); + + i64_val += 1 as i64; + assert_eq!(i64_val.to_string(), "-9223372036854775808".to_string()); } } diff --git a/src/libstd/num/u16.rs b/src/libstd/num/u16.rs index bb619b5b2f5..246224ddb2b 100644 --- a/src/libstd/num/u16.rs +++ b/src/libstd/num/u16.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u16")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u16::{BITS, BYTES, MIN, MAX}; uint_module!(u16) diff --git a/src/libstd/num/u32.rs b/src/libstd/num/u32.rs index 754103ba5da..143b45010c2 100644 --- a/src/libstd/num/u32.rs +++ b/src/libstd/num/u32.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u32")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u32::{BITS, BYTES, MIN, MAX}; uint_module!(u32) diff --git a/src/libstd/num/u64.rs b/src/libstd/num/u64.rs index da497d2cbe4..92c5380f980 100644 --- a/src/libstd/num/u64.rs +++ b/src/libstd/num/u64.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u64")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u64::{BITS, BYTES, MIN, MAX}; uint_module!(u64) diff --git a/src/libstd/num/u8.rs b/src/libstd/num/u8.rs index bdfcdb2c5a5..faa6d167065 100644 --- a/src/libstd/num/u8.rs +++ b/src/libstd/num/u8.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "u8")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::u8::{BITS, BYTES, MIN, MAX}; uint_module!(u8) diff --git a/src/libstd/num/uint.rs b/src/libstd/num/uint.rs index 5090219d3de..a425aab3aa1 100644 --- a/src/libstd/num/uint.rs +++ b/src/libstd/num/uint.rs @@ -13,11 +13,6 @@ #![unstable] #![doc(primitive = "uint")] -use from_str::FromStr; -use num::FromStrRadix; -use num::strconv; -use option::Option; - pub use core::uint::{BITS, BYTES, MIN, MAX}; uint_module!(uint) diff --git a/src/libstd/num/uint_macros.rs b/src/libstd/num/uint_macros.rs index aa8e58bab02..ef9e809ed2b 100644 --- a/src/libstd/num/uint_macros.rs +++ b/src/libstd/num/uint_macros.rs @@ -15,22 +15,6 @@ macro_rules! uint_module (($T:ty) => ( -#[experimental = "might need to return Result"] -impl FromStr for $T { - #[inline] - fn from_str(s: &str) -> Option<$T> { - strconv::from_str_radix_int(s, 10) - } -} - -#[experimental = "might need to return Result"] -impl FromStrRadix for $T { - #[inline] - fn from_str_radix(s: &str, radix: uint) -> Option<$T> { - strconv::from_str_radix_int(s, radix) - } -} - // String conversion functions and impl num -> str /// Convert to a string as a byte slice in a given base. diff --git a/src/libstd/path/posix.rs b/src/libstd/path/posix.rs index 794f6978642..e2ff824a7c9 100644 --- a/src/libstd/path/posix.rs +++ b/src/libstd/path/posix.rs @@ -13,12 +13,11 @@ use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use from_str::FromStr; use hash; use io::Writer; use iter::{DoubleEndedIterator, AdditiveIterator, Extend, Iterator, Map}; use option::{Option, None, Some}; -use str::Str; +use str::{FromStr, Str}; use str; use slice::{CloneSliceAllocPrelude, Splits, AsSlice, VectorVector, PartialEqSlicePrelude, SlicePrelude}; diff --git a/src/libstd/path/windows.rs b/src/libstd/path/windows.rs index 2da2159653e..b8016e3e8f4 100644 --- a/src/libstd/path/windows.rs +++ b/src/libstd/path/windows.rs @@ -16,14 +16,13 @@ use ascii::AsciiCast; use c_str::{CString, ToCStr}; use clone::Clone; use cmp::{PartialEq, Eq, PartialOrd, Ord, Ordering}; -use from_str::FromStr; use hash; use io::Writer; use iter::{AdditiveIterator, DoubleEndedIterator, Extend, Iterator, Map}; use mem; use option::{Option, Some, None}; use slice::{AsSlice, SlicePrelude}; -use str::{CharSplits, Str, StrAllocating, StrVector, StrPrelude}; +use str::{CharSplits, FromStr, Str, StrAllocating, StrVector, StrPrelude}; use string::String; use unicode::char::UnicodeChar; use vec::Vec; diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs index 158e7a59f6d..4ab09a2a864 100644 --- a/src/libstd/prelude.rs +++ b/src/libstd/prelude.rs @@ -50,9 +50,9 @@ #[doc(no_inline)] pub use ops::{Fn, FnMut, FnOnce}; // Reexported functions -#[doc(no_inline)] pub use from_str::from_str; #[doc(no_inline)] pub use iter::{range, repeat}; #[doc(no_inline)] pub use mem::drop; +#[doc(no_inline)] pub use str::from_str; // Reexported types and traits diff --git a/src/libstd/rt/backtrace.rs b/src/libstd/rt/backtrace.rs index b08b92b8587..8b457d1639d 100644 --- a/src/libstd/rt/backtrace.rs +++ b/src/libstd/rt/backtrace.rs @@ -12,13 +12,12 @@ #![allow(non_camel_case_types)] -use from_str::from_str; use io::{IoResult, Writer}; use iter::Iterator; use option::{Some, None}; use os; use result::{Ok, Err}; -use str::StrPrelude; +use str::{StrPrelude, from_str}; use sync::atomic; use unicode::char::UnicodeChar; diff --git a/src/libstd/rt/util.rs b/src/libstd/rt/util.rs index 56f2dbf667a..92657d1b59b 100644 --- a/src/libstd/rt/util.rs +++ b/src/libstd/rt/util.rs @@ -8,12 +8,10 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use from_str::FromStr; -use from_str::from_str; use libc::uintptr_t; use option::{Some, None, Option}; use os; -use str::Str; +use str::{FromStr, from_str, Str}; use sync::atomic; /// Dynamically inquire about whether we're running under V. diff --git a/src/libtest/lib.rs b/src/libtest/lib.rs index 986f90389e7..ff96f806fac 100644 --- a/src/libtest/lib.rs +++ b/src/libtest/lib.rs @@ -53,13 +53,13 @@ use std::cmp; use std::f64; use std::fmt::Show; use std::fmt; -use std::from_str::FromStr; use std::io::fs::PathExtensions; use std::io::stdio::StdWriter; use std::io::{File, ChanReader, ChanWriter}; use std::io; use std::num::{Float, FloatMath, Int}; use std::os; +use std::str::FromStr; use std::string::String; use std::task::TaskBuilder; use std::time::Duration;