diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs index 8350ba42591..3c5de1b703b 100644 --- a/src/libcore/num/f32.rs +++ b/src/libcore/num/f32.rs @@ -14,6 +14,7 @@ use cmath; use cmp; use libc::{c_float, c_int}; use num::NumCast; +use num::strconv; use num; use ops; use option::Option; @@ -376,8 +377,8 @@ impl num::Round for f32 { */ #[inline(always)] pub pure fn to_str(num: f32) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigAll); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigAll); r } @@ -390,8 +391,8 @@ pub pure fn to_str(num: f32) -> ~str { */ #[inline(always)] pub pure fn to_str_hex(num: f32) -> ~str { - let (r, _) = num::to_str_common( - &num, 16u, true, true, num::SignNeg, num::DigAll); + let (r, _) = strconv::to_str_common( + &num, 16u, true, true, strconv::SignNeg, strconv::DigAll); r } @@ -411,8 +412,8 @@ pub pure fn to_str_hex(num: f32) -> ~str { */ #[inline(always)] pub pure fn to_str_radix(num: f32, rdx: uint) -> ~str { - let (r, special) = num::to_str_common( - &num, rdx, true, true, num::SignNeg, num::DigAll); + let (r, special) = strconv::to_str_common( + &num, rdx, true, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ try to_str_radix_special() if those are expected") } r @@ -429,7 +430,8 @@ pub pure fn to_str_radix(num: f32, rdx: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { - num::to_str_common(&num, rdx, true, true, num::SignNeg, num::DigAll) + strconv::to_str_common(&num, rdx, true, true, + strconv::SignNeg, strconv::DigAll) } /** @@ -443,8 +445,8 @@ pub pure fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) { */ #[inline(always)] pub pure fn to_str_exact(num: f32, dig: uint) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigExact(dig)); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigExact(dig)); r } @@ -459,8 +461,8 @@ pub pure fn to_str_exact(num: f32, dig: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_digits(num: f32, dig: uint) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigMax(dig)); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigMax(dig)); r } @@ -505,7 +507,8 @@ impl num::ToStrRadix for f32 { */ #[inline(always)] pub pure fn from_str(num: &str) -> Option { - num::from_str_common(num, 10u, true, true, true, num::ExpDec, false) + strconv::from_str_common(num, 10u, true, true, true, + strconv::ExpDec, false) } /** @@ -537,7 +540,8 @@ pub pure fn from_str(num: &str) -> Option { */ #[inline(always)] pub pure fn from_str_hex(num: &str) -> Option { - num::from_str_common(num, 16u, true, true, true, num::ExpBin, false) + strconv::from_str_common(num, 16u, true, true, true, + strconv::ExpBin, false) } /** @@ -561,7 +565,8 @@ pub pure fn from_str_hex(num: &str) -> Option { */ #[inline(always)] pub pure fn from_str_radix(num: &str, rdx: uint) -> Option { - num::from_str_common(num, rdx, true, true, false, num::ExpNone, false) + strconv::from_str_common(num, rdx, true, true, false, + strconv::ExpNone, false) } impl from_str::FromStr for f32 { diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs index 474067a1860..0bd6e0e9d77 100644 --- a/src/libcore/num/f64.rs +++ b/src/libcore/num/f64.rs @@ -15,6 +15,7 @@ use cmp; use libc::{c_double, c_int}; use libc; use num::NumCast; +use num::strconv; use num; use ops; use option::Option; @@ -401,8 +402,8 @@ impl num::Round for f64 { */ #[inline(always)] pub pure fn to_str(num: f64) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigAll); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigAll); r } @@ -415,8 +416,8 @@ pub pure fn to_str(num: f64) -> ~str { */ #[inline(always)] pub pure fn to_str_hex(num: f64) -> ~str { - let (r, _) = num::to_str_common( - &num, 16u, true, true, num::SignNeg, num::DigAll); + let (r, _) = strconv::to_str_common( + &num, 16u, true, true, strconv::SignNeg, strconv::DigAll); r } @@ -436,8 +437,8 @@ pub pure fn to_str_hex(num: f64) -> ~str { */ #[inline(always)] pub pure fn to_str_radix(num: f64, rdx: uint) -> ~str { - let (r, special) = num::to_str_common( - &num, rdx, true, true, num::SignNeg, num::DigAll); + let (r, special) = strconv::to_str_common( + &num, rdx, true, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ try to_str_radix_special() if those are expected") } r @@ -454,7 +455,8 @@ pub pure fn to_str_radix(num: f64, rdx: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { - num::to_str_common(&num, rdx, true, true, num::SignNeg, num::DigAll) + strconv::to_str_common(&num, rdx, true, true, + strconv::SignNeg, strconv::DigAll) } /** @@ -468,8 +470,8 @@ pub pure fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) { */ #[inline(always)] pub pure fn to_str_exact(num: f64, dig: uint) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigExact(dig)); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigExact(dig)); r } @@ -484,8 +486,8 @@ pub pure fn to_str_exact(num: f64, dig: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_digits(num: f64, dig: uint) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigMax(dig)); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigMax(dig)); r } @@ -530,7 +532,8 @@ impl num::ToStrRadix for f64 { */ #[inline(always)] pub pure fn from_str(num: &str) -> Option { - num::from_str_common(num, 10u, true, true, true, num::ExpDec, false) + strconv::from_str_common(num, 10u, true, true, true, + strconv::ExpDec, false) } /** @@ -562,7 +565,8 @@ pub pure fn from_str(num: &str) -> Option { */ #[inline(always)] pub pure fn from_str_hex(num: &str) -> Option { - num::from_str_common(num, 16u, true, true, true, num::ExpBin, false) + strconv::from_str_common(num, 16u, true, true, true, + strconv::ExpBin, false) } /** @@ -586,7 +590,8 @@ pub pure fn from_str_hex(num: &str) -> Option { */ #[inline(always)] pub pure fn from_str_radix(num: &str, rdx: uint) -> Option { - num::from_str_common(num, rdx, true, true, false, num::ExpNone, false) + strconv::from_str_common(num, rdx, true, true, false, + strconv::ExpNone, false) } impl from_str::FromStr for f64 { diff --git a/src/libcore/num/float.rs b/src/libcore/num/float.rs index 0f0b721e462..87879f6d7ad 100644 --- a/src/libcore/num/float.rs +++ b/src/libcore/num/float.rs @@ -26,6 +26,7 @@ use cmp::{Eq, Ord}; use cmp; use f64; use num::NumCast; +use num::strconv; use num; use ops; use option::{None, Option, Some}; @@ -107,8 +108,8 @@ pub mod consts { */ #[inline(always)] pub pure fn to_str(num: float) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigAll); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigAll); r } @@ -121,8 +122,8 @@ pub pure fn to_str(num: float) -> ~str { */ #[inline(always)] pub pure fn to_str_hex(num: float) -> ~str { - let (r, _) = num::to_str_common( - &num, 16u, true, true, num::SignNeg, num::DigAll); + let (r, _) = strconv::to_str_common( + &num, 16u, true, true, strconv::SignNeg, strconv::DigAll); r } @@ -142,8 +143,8 @@ pub pure fn to_str_hex(num: float) -> ~str { */ #[inline(always)] pub pure fn to_str_radix(num: float, radix: uint) -> ~str { - let (r, special) = num::to_str_common( - &num, radix, true, true, num::SignNeg, num::DigAll); + let (r, special) = strconv::to_str_common( + &num, radix, true, true, strconv::SignNeg, strconv::DigAll); if special { fail!(~"number has a special value, \ try to_str_radix_special() if those are expected") } r @@ -160,7 +161,8 @@ pub pure fn to_str_radix(num: float, radix: uint) -> ~str { */ #[inline(always)] pub pure fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { - num::to_str_common(&num, radix, true, true, num::SignNeg, num::DigAll) + strconv::to_str_common(&num, radix, true, true, + strconv::SignNeg, strconv::DigAll) } /** @@ -174,8 +176,8 @@ pub pure fn to_str_radix_special(num: float, radix: uint) -> (~str, bool) { */ #[inline(always)] pub pure fn to_str_exact(num: float, digits: uint) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigExact(digits)); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigExact(digits)); r } @@ -196,8 +198,8 @@ pub fn test_to_str_exact_do_decimal() { */ #[inline(always)] pub pure fn to_str_digits(num: float, digits: uint) -> ~str { - let (r, _) = num::to_str_common( - &num, 10u, true, true, num::SignNeg, num::DigMax(digits)); + let (r, _) = strconv::to_str_common( + &num, 10u, true, true, strconv::SignNeg, strconv::DigMax(digits)); r } @@ -242,7 +244,8 @@ impl num::ToStrRadix for float { */ #[inline(always)] pub pure fn from_str(num: &str) -> Option { - num::from_str_common(num, 10u, true, true, true, num::ExpDec, false) + strconv::from_str_common(num, 10u, true, true, true, + strconv::ExpDec, false) } /** @@ -274,7 +277,8 @@ pub pure fn from_str(num: &str) -> Option { */ #[inline(always)] pub pure fn from_str_hex(num: &str) -> Option { - num::from_str_common(num, 16u, true, true, true, num::ExpBin, false) + strconv::from_str_common(num, 16u, true, true, true, + strconv::ExpBin, false) } /** @@ -298,7 +302,8 @@ pub pure fn from_str_hex(num: &str) -> Option { */ #[inline(always)] pub pure fn from_str_radix(num: &str, radix: uint) -> Option { - num::from_str_common(num, radix, true, true, false, num::ExpNone, false) + strconv::from_str_common(num, radix, true, true, false, + strconv::ExpNone, false) } impl from_str::FromStr for float { diff --git a/src/libcore/num/int-template.rs b/src/libcore/num/int-template.rs index eaaa78b84f8..df9756423ef 100644 --- a/src/libcore/num/int-template.rs +++ b/src/libcore/num/int-template.rs @@ -16,6 +16,7 @@ use cmp; use to_str::ToStr; use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; +use num::strconv; use num; use prelude::*; use str; @@ -218,22 +219,22 @@ impl ops::Neg for T { /// Parse a string as a number in base 10. #[inline(always)] pub pure fn from_str(s: &str) -> Option { - num::from_str_common(s, 10u, true, false, false, - num::ExpNone, false) + strconv::from_str_common(s, 10u, true, false, false, + strconv::ExpNone, false) } /// Parse a string as a number in the given base. #[inline(always)] pub pure fn from_str_radix(s: &str, radix: uint) -> Option { - num::from_str_common(s, radix, true, false, false, - num::ExpNone, false) + strconv::from_str_common(s, radix, true, false, false, + strconv::ExpNone, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] pub pure fn parse_bytes(buf: &[u8], radix: uint) -> Option { - num::from_str_bytes_common(buf, radix, true, false, false, - num::ExpNone, false) + strconv::from_str_bytes_common(buf, radix, true, false, false, + strconv::ExpNone, false) } impl FromStr for T { @@ -255,24 +256,24 @@ impl FromStrRadix for T { /// Convert to a string as a byte slice in a given base. #[inline(always)] pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { - let (buf, _) = num::to_str_bytes_common(&n, radix, false, false, - num::SignNeg, num::DigAll); + let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, false, + strconv::SignNeg, strconv::DigAll); f(buf) } /// Convert to a string in base 10. #[inline(always)] pub pure fn to_str(num: T) -> ~str { - let (buf, _) = num::to_str_common(&num, 10u, false, false, - num::SignNeg, num::DigAll); + let (buf, _) = strconv::to_str_common(&num, 10u, false, false, + strconv::SignNeg, strconv::DigAll); buf } /// Convert to a string in a given base. #[inline(always)] pub pure fn to_str_radix(num: T, radix: uint) -> ~str { - let (buf, _) = num::to_str_common(&num, radix, false, false, - num::SignNeg, num::DigAll); + let (buf, _) = strconv::to_str_common(&num, radix, false, false, + strconv::SignNeg, strconv::DigAll); buf } diff --git a/src/libcore/num/num.rs b/src/libcore/num/num.rs index 44cd66363fb..af322e9b6c6 100644 --- a/src/libcore/num/num.rs +++ b/src/libcore/num/num.rs @@ -1,4 +1,4 @@ -// Copyright 2012 The Rust Project Developers. See the COPYRIGHT +// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT // file at the top-level directory of this distribution and at // http://rust-lang.org/COPYRIGHT. // @@ -17,6 +17,8 @@ use str; use kinds::Copy; use vec; +pub mod strconv; + pub trait IntConvertible { pure fn to_int(&self) -> int; static pure fn from_int(n: int) -> Self; @@ -186,540 +188,3 @@ pub pure fn pow_with_uint+Mul>( total } -pub enum ExponentFormat { - ExpNone, - ExpDec, - ExpBin -} - -pub enum SignificantDigits { - DigAll, - DigMax(uint), - DigExact(uint) -} - -pub enum SignFormat { - SignNone, - SignNeg, - SignAll -} - -/** - * Converts a number to its string representation as a byte vector. - * This is meant to be a common base implementation for all numeric string - * conversion functions like `to_str()` or `to_str_radix()`. - * - * # Arguments - * - `num` - The number to convert. Accepts any number that - * implements the numeric traits. - * - `radix` - Base to use. Accepts only the values 2-36. - * - `special` - Whether to attempt to compare to special values like - * `inf` or `NaN`. Also needed to detect negative 0. - * Can fail if it doesn't match `num`s type - * (see safety note). - * - `negative_zero` - Whether to treat the special value `-0` as - * `-0` or as `+0`. - * - `sign` - How to emit the sign. Options are: - * - `SignNone`: No sign at all. Basically emits `abs(num)`. - * - `SignNeg`: Only `-` on negative values. - * - `SignAll`: Both `+` on positive, and `-` on negative numbers. - * - `digits` - The amount of digits to use for emitting the - * fractional part, if any. Options are: - * - `DigAll`: All calculatable digits. Beware of bignums or - * fractions! - * - `DigMax(uint)`: Maximum N digits, truncating any trailing zeros. - * - `DigExact(uint)`: Exactly N digits. - * - * # Return value - * A tuple containing the byte vector, and a boolean flag indicating - * whether it represents a special value like `inf`, `-inf`, `NaN` or not. - * It returns a tuple because there can be ambiguity between a special value - * and a number representation at higher bases. - * - * # Failure - * - Fails if `radix` < 2 or `radix` > 36. - * - Fails on wrong value for `special` (see safety note). - * - * # Safety note - * The function detects the special values `inf`, `-inf` and `NaN` by - * dynamically comparing `num` to `1 / 0`, `-1 / 0` and `0 / 0` - * (each of type T) if `special` is `true`. This will fail on integer types - * with a 'divide by zero'. Likewise, it will fail if `num` **is** one of - * those special values, and `special` is `false`, because then the - * algorithm just does normal calculations on them. - */ -pub pure fn to_str_bytes_common+ - Neg+Modulo+Mul>( - num: &T, radix: uint, special: bool, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) { - if radix as int < 2 { - fail!(fmt!("to_str_bytes_common: radix %? to low, \ - must lie in the range [2, 36]", radix)); - } else if radix as int > 36 { - fail!(fmt!("to_str_bytes_common: radix %? to high, \ - must lie in the range [2, 36]", radix)); - } - - let _0: T = Zero::zero(); - let _1: T = One::one(); - - if special { - if is_NaN(num) { - return (str::to_bytes("NaN"), true); - } else if is_infinity(num){ - return match sign { - SignAll => (str::to_bytes("+inf"), true), - _ => (str::to_bytes("inf"), true) - } - } else if is_neg_infinity(num) { - return match sign { - SignNone => (str::to_bytes("inf"), true), - _ => (str::to_bytes("-inf"), true), - } - } - } - - let neg = *num < _0 || (negative_zero && *num == _0 - && special && is_neg_zero(num)); - let mut buf: ~[u8] = ~[]; - let radix_gen: T = cast(radix as int); - - let mut deccum; - - // First emit the non-fractional part, looping at least once to make - // sure at least a `0` gets emitted. - deccum = num.round(RoundToZero); - loop { - // Calculate the absolute value of each digit instead of only - // doing it once for the whole number because a - // representable negative number doesn't necessary have an - // representable additive inverse of the same type - // (See twos complement). But we assume that for the - // numbers [-35 .. 0] we always have [0 .. 35]. - let current_digit_signed = deccum % radix_gen; - let current_digit = if current_digit_signed < _0 { - -current_digit_signed - } else { - current_digit_signed - }; - - // Decrease the deccumulator one digit at a time - deccum /= radix_gen; - deccum = deccum.round(RoundToZero); - - unsafe { // FIXME: Pureness workaround (#4568) - buf.push(char::from_digit(current_digit.to_int() as uint, radix) - .unwrap() as u8); - } - - // No more digits to calculate for the non-fractional part -> break - if deccum == _0 { break; } - } - - // If limited digits, calculate one digit more for rounding. - let (limit_digits, digit_count, exact) = match digits { - DigAll => (false, 0u, false), - DigMax(count) => (true, count+1, false), - DigExact(count) => (true, count+1, true) - }; - - // Decide what sign to put in front - match sign { - SignNeg | SignAll if neg => { - unsafe { // FIXME: Pureness workaround (#4568) - buf.push('-' as u8); - } - } - SignAll => { - unsafe { // FIXME: Pureness workaround (#4568) - buf.push('+' as u8); - } - } - _ => () - } - - unsafe { // FIXME: Pureness workaround (#4568) - vec::reverse(buf); - } - - // Remember start of the fractional digits. - // Points one beyond end of buf if none get generated, - // or at the '.' otherwise. - let start_fractional_digits = buf.len(); - - // Now emit the fractional part, if any - deccum = num.fract(); - if deccum != _0 || (limit_digits && exact && digit_count > 0) { - unsafe { // FIXME: Pureness workaround (#4568) - buf.push('.' as u8); - } - let mut dig = 0u; - - // calculate new digits while - // - there is no limit and there are digits left - // - or there is a limit, it's not reached yet and - // - it's exact - // - or it's a maximum, and there are still digits left - while (!limit_digits && deccum != _0) - || (limit_digits && dig < digit_count && ( - exact - || (!exact && deccum != _0) - ) - ) { - // Shift first fractional digit into the integer part - deccum *= radix_gen; - - // Calculate the absolute value of each digit. - // See note in first loop. - let current_digit_signed = deccum.round(RoundToZero); - let current_digit = if current_digit_signed < _0 { - -current_digit_signed - } else { - current_digit_signed - }; - - unsafe { // FIXME: Pureness workaround (#4568) - buf.push(char::from_digit( - current_digit.to_int() as uint, radix).unwrap() as u8); - } - - // Decrease the deccumulator one fractional digit at a time - deccum = deccum.fract(); - dig += 1u; - } - - // If digits are limited, and that limit has been reached, - // cut off the one extra digit, and depending on its value - // round the remaining ones. - if limit_digits && dig == digit_count { - let ascii2value = |chr: u8| { - char::to_digit(chr as char, radix).unwrap() as uint - }; - let value2ascii = |val: uint| { - char::from_digit(val, radix).unwrap() as u8 - }; - - unsafe { // FIXME: Pureness workaround (#4568) - let extra_digit = ascii2value(buf.pop()); - if extra_digit >= radix / 2 { // -> need to round - let mut i: int = buf.len() as int - 1; - loop { - // If reached left end of number, have to - // insert additional digit: - if i < 0 - || buf[i] == '-' as u8 - || buf[i] == '+' as u8 { - buf.insert((i + 1) as uint, value2ascii(1)); - break; - } - - // Skip the '.' - if buf[i] == '.' as u8 { i -= 1; loop; } - - // Either increment the digit, - // or set to 0 if max and carry the 1. - let current_digit = ascii2value(buf[i]); - if current_digit < (radix - 1) { - buf[i] = value2ascii(current_digit+1); - break; - } else { - buf[i] = value2ascii(0); - i -= 1; - } - } - } - } - } - } - - // if number of digits is not exact, remove all trailing '0's up to - // and including the '.' - if !exact { - let buf_max_i = buf.len() - 1; - - // index to truncate from - let mut i = buf_max_i; - - // discover trailing zeros of fractional part - while i > start_fractional_digits && buf[i] == '0' as u8 { - i -= 1; - } - - // Only attempt to truncate digits if buf has fractional digits - if i >= start_fractional_digits { - // If buf ends with '.', cut that too. - if buf[i] == '.' as u8 { i -= 1 } - - // only resize buf if we actually remove digits - if i < buf_max_i { - buf = buf.slice(0, i + 1); - } - } - } // If exact and trailing '.', just cut that - else { - let max_i = buf.len() - 1; - if buf[max_i] == '.' as u8 { - buf = buf.slice(0, max_i); - } - } - - (buf, false) -} - -/** - * Converts a number to its string representation. This is a wrapper for - * `to_str_bytes_common()`, for details see there. - */ -#[inline(always)] -pub pure fn to_str_common+Neg - +Modulo+Mul>( - num: &T, radix: uint, special: bool, negative_zero: bool, - sign: SignFormat, digits: SignificantDigits) -> (~str, bool) { - let (bytes, special) = to_str_bytes_common(num, radix, special, - negative_zero, sign, digits); - (str::from_bytes(bytes), special) -} - -// Some constants for from_str_bytes_common's input validation, -// they define minimum radix values for which the character is a valid digit. -priv const DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u; -priv const DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u; -priv const 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 a empty `buf` as a 0 or not. - * - * # 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'`. - * - * # Possible improvements - * - Could accept option to allow ignoring underscores, allowing for numbers - * formated like `FF_AE_FF_FF`. - */ -pub pure fn from_str_bytes_common+ - Mul+Sub+Neg+Add>( - buf: &[u8], radix: uint, negative: bool, fractional: bool, - special: bool, exponent: ExponentFormat, empty_zero: bool - ) -> Option { - match exponent { - ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' - => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \ - use of 'e' as decimal exponent", radix)), - ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p' - => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \ - use of 'p' as binary exponent", radix)), - _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf' - => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \ - special values 'inf' and 'NaN'", radix)), - _ if radix as int < 2 - => fail!(fmt!("from_str_bytes_common: radix %? to low, \ - must lie in the range [2, 36]", radix)), - _ if radix as int > 36 - => fail!(fmt!("from_str_bytes_common: radix %? to high, \ - must lie in the range [2, 36]", radix)), - _ => () - } - - let _0: T = Zero::zero(); - let _1: T = One::one(); - let radix_gen: T = cast(radix as int); - - let len = buf.len(); - - if len == 0 { - if empty_zero { - return Some(_0); - } else { - return None; - } - } - - if special { - if buf == str::to_bytes("inf") || buf == str::to_bytes("+inf") { - return Some(infinity()); - } else if buf == str::to_bytes("-inf") { - if negative { - return Some(neg_infinity()); - } else { - return None; - } - } else if buf == str::to_bytes("NaN") { - return Some(NaN()); - } - } - - let (start, accum_positive) = match buf[0] { - '-' as u8 if !negative => return None, - '-' as u8 => (1u, false), - '+' as u8 => (1u, true), - _ => (0u, true) - }; - - // Initialize accumulator with signed zero for floating point parsing to - // work - let mut accum = if accum_positive { _0 } else { -_1 * _0}; - let mut last_accum = accum; // Necessary to detect overflow - let mut i = start; - let mut exp_found = false; - - // Parse integer part of number - while i < len { - let c = buf[i] as char; - - match char::to_digit(c, radix) { - Some(digit) => { - // shift accum one digit left - accum *= radix_gen; - - // add/subtract current digit depending on sign - if accum_positive { - accum += cast(digit as int); - } else { - accum -= cast(digit as int); - } - - // Detect overflow by comparing to last value - if accum_positive && accum < last_accum { return None; } - if !accum_positive && accum > last_accum { return None; } - last_accum = accum; - } - None => match c { - '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 - } - } - - i += 1u; - } - - // Parse fractional part of number - // Skip if already reached start of exponent - if !exp_found { - let mut power = _1; - - while i < len { - let c = buf[i] as char; - - match char::to_digit(c, radix) { - Some(digit) => { - // Decrease power one order of magnitude - power /= radix_gen; - - let digit_t: T = cast(digit); - - // add/subtract current digit depending on sign - if accum_positive { - accum += digit_t * power; - } else { - accum -= digit_t * power; - } - - // Detect overflow by comparing to last value - if accum_positive && accum < last_accum { return None; } - if !accum_positive && accum > last_accum { return None; } - last_accum = accum; - } - None => match c { - 'e' | 'E' | 'p' | 'P' => { - exp_found = true; - 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; - } - } - - let mut multiplier = _1; - - if exp_found { - let c = buf[i] as char; - let base = match (c, exponent) { - ('e', ExpDec) | ('E', ExpDec) => 10u, - ('p', ExpBin) | ('P', ExpBin) => 2u, - _ => return None // char doesn't fit given exponent format - }; - - // parse remaining bytes as decimal integer, - // skipping the exponent char - let exp: Option = from_str_bytes_common( - buf.view(i+1, len), 10, true, false, false, ExpNone, false); - - match exp { - Some(exp_pow) => { - multiplier = if exp_pow < 0 { - _1 / pow_with_uint::(base, (-exp_pow.to_int()) as uint) - } else { - pow_with_uint::(base, exp_pow.to_int() as uint) - } - } - None => return None // invalid exponent -> invalid number - } - } - - Some(accum * multiplier) -} - -/** - * Parses a string as a number. This is a wrapper for - * `from_str_bytes_common()`, for details see there. - */ -#[inline(always)] -pub pure fn from_str_common+Mul+ - Sub+Neg+Add>( - buf: &str, radix: uint, negative: bool, fractional: bool, - special: bool, exponent: ExponentFormat, empty_zero: bool - ) -> Option { - from_str_bytes_common(str::to_bytes(buf), radix, negative, - fractional, special, exponent, empty_zero) -} diff --git a/src/libcore/num/strconv.rs b/src/libcore/num/strconv.rs new file mode 100644 index 00000000000..6aa933ffbed --- /dev/null +++ b/src/libcore/num/strconv.rs @@ -0,0 +1,556 @@ +// Copyright 2013 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. + +use core::cmp::{Ord, Eq}; +use ops::{Add, Div, Modulo, Mul, Neg, Sub}; +use option::{None, Option, Some}; +use char; +use str; +use kinds::Copy; +use vec; +use num::*; + +pub enum ExponentFormat { + ExpNone, + ExpDec, + ExpBin +} + +pub enum SignificantDigits { + DigAll, + DigMax(uint), + DigExact(uint) +} + +pub enum SignFormat { + SignNone, + SignNeg, + SignAll +} + +/** + * Converts a number to its string representation as a byte vector. + * This is meant to be a common base implementation for all numeric string + * conversion functions like `to_str()` or `to_str_radix()`. + * + * # Arguments + * - `num` - The number to convert. Accepts any number that + * implements the numeric traits. + * - `radix` - Base to use. Accepts only the values 2-36. + * - `special` - Whether to attempt to compare to special values like + * `inf` or `NaN`. Also needed to detect negative 0. + * Can fail if it doesn't match `num`s type + * (see safety note). + * - `negative_zero` - Whether to treat the special value `-0` as + * `-0` or as `+0`. + * - `sign` - How to emit the sign. Options are: + * - `SignNone`: No sign at all. Basically emits `abs(num)`. + * - `SignNeg`: Only `-` on negative values. + * - `SignAll`: Both `+` on positive, and `-` on negative numbers. + * - `digits` - The amount of digits to use for emitting the + * fractional part, if any. Options are: + * - `DigAll`: All calculatable digits. Beware of bignums or + * fractions! + * - `DigMax(uint)`: Maximum N digits, truncating any trailing zeros. + * - `DigExact(uint)`: Exactly N digits. + * + * # Return value + * A tuple containing the byte vector, and a boolean flag indicating + * whether it represents a special value like `inf`, `-inf`, `NaN` or not. + * It returns a tuple because there can be ambiguity between a special value + * and a number representation at higher bases. + * + * # Failure + * - Fails if `radix` < 2 or `radix` > 36. + * - Fails on wrong value for `special` (see safety note). + * + * # Safety note + * The function detects the special values `inf`, `-inf` and `NaN` by + * dynamically comparing `num` to `1 / 0`, `-1 / 0` and `0 / 0` + * (each of type T) if `special` is `true`. This will fail on integer types + * with a 'divide by zero'. Likewise, it will fail if `num` **is** one of + * those special values, and `special` is `false`, because then the + * algorithm just does normal calculations on them. + */ +pub pure fn to_str_bytes_common+ + Neg+Modulo+Mul>( + num: &T, radix: uint, special: bool, negative_zero: bool, + sign: SignFormat, digits: SignificantDigits) -> (~[u8], bool) { + if radix as int < 2 { + fail!(fmt!("to_str_bytes_common: radix %? to low, \ + must lie in the range [2, 36]", radix)); + } else if radix as int > 36 { + fail!(fmt!("to_str_bytes_common: radix %? to high, \ + must lie in the range [2, 36]", radix)); + } + + let _0: T = Zero::zero(); + let _1: T = One::one(); + + if special { + if is_NaN(num) { + return (str::to_bytes("NaN"), true); + } else if is_infinity(num){ + return match sign { + SignAll => (str::to_bytes("+inf"), true), + _ => (str::to_bytes("inf"), true) + } + } else if is_neg_infinity(num) { + return match sign { + SignNone => (str::to_bytes("inf"), true), + _ => (str::to_bytes("-inf"), true), + } + } + } + + let neg = *num < _0 || (negative_zero && *num == _0 + && special && is_neg_zero(num)); + let mut buf: ~[u8] = ~[]; + let radix_gen: T = cast(radix as int); + + let mut deccum; + + // First emit the non-fractional part, looping at least once to make + // sure at least a `0` gets emitted. + deccum = num.round(RoundToZero); + loop { + // Calculate the absolute value of each digit instead of only + // doing it once for the whole number because a + // representable negative number doesn't necessary have an + // representable additive inverse of the same type + // (See twos complement). But we assume that for the + // numbers [-35 .. 0] we always have [0 .. 35]. + let current_digit_signed = deccum % radix_gen; + let current_digit = if current_digit_signed < _0 { + -current_digit_signed + } else { + current_digit_signed + }; + + // Decrease the deccumulator one digit at a time + deccum /= radix_gen; + deccum = deccum.round(RoundToZero); + + unsafe { // FIXME: Pureness workaround (#4568) + buf.push(char::from_digit(current_digit.to_int() as uint, radix) + .unwrap() as u8); + } + + // No more digits to calculate for the non-fractional part -> break + if deccum == _0 { break; } + } + + // If limited digits, calculate one digit more for rounding. + let (limit_digits, digit_count, exact) = match digits { + DigAll => (false, 0u, false), + DigMax(count) => (true, count+1, false), + DigExact(count) => (true, count+1, true) + }; + + // Decide what sign to put in front + match sign { + SignNeg | SignAll if neg => { + unsafe { // FIXME: Pureness workaround (#4568) + buf.push('-' as u8); + } + } + SignAll => { + unsafe { // FIXME: Pureness workaround (#4568) + buf.push('+' as u8); + } + } + _ => () + } + + unsafe { // FIXME: Pureness workaround (#4568) + vec::reverse(buf); + } + + // Remember start of the fractional digits. + // Points one beyond end of buf if none get generated, + // or at the '.' otherwise. + let start_fractional_digits = buf.len(); + + // Now emit the fractional part, if any + deccum = num.fract(); + if deccum != _0 || (limit_digits && exact && digit_count > 0) { + unsafe { // FIXME: Pureness workaround (#4568) + buf.push('.' as u8); + } + let mut dig = 0u; + + // calculate new digits while + // - there is no limit and there are digits left + // - or there is a limit, it's not reached yet and + // - it's exact + // - or it's a maximum, and there are still digits left + while (!limit_digits && deccum != _0) + || (limit_digits && dig < digit_count && ( + exact + || (!exact && deccum != _0) + ) + ) { + // Shift first fractional digit into the integer part + deccum *= radix_gen; + + // Calculate the absolute value of each digit. + // See note in first loop. + let current_digit_signed = deccum.round(RoundToZero); + let current_digit = if current_digit_signed < _0 { + -current_digit_signed + } else { + current_digit_signed + }; + + unsafe { // FIXME: Pureness workaround (#4568) + buf.push(char::from_digit( + current_digit.to_int() as uint, radix).unwrap() as u8); + } + + // Decrease the deccumulator one fractional digit at a time + deccum = deccum.fract(); + dig += 1u; + } + + // If digits are limited, and that limit has been reached, + // cut off the one extra digit, and depending on its value + // round the remaining ones. + if limit_digits && dig == digit_count { + let ascii2value = |chr: u8| { + char::to_digit(chr as char, radix).unwrap() as uint + }; + let value2ascii = |val: uint| { + char::from_digit(val, radix).unwrap() as u8 + }; + + unsafe { // FIXME: Pureness workaround (#4568) + let extra_digit = ascii2value(buf.pop()); + if extra_digit >= radix / 2 { // -> need to round + let mut i: int = buf.len() as int - 1; + loop { + // If reached left end of number, have to + // insert additional digit: + if i < 0 + || buf[i] == '-' as u8 + || buf[i] == '+' as u8 { + buf.insert((i + 1) as uint, value2ascii(1)); + break; + } + + // Skip the '.' + if buf[i] == '.' as u8 { i -= 1; loop; } + + // Either increment the digit, + // or set to 0 if max and carry the 1. + let current_digit = ascii2value(buf[i]); + if current_digit < (radix - 1) { + buf[i] = value2ascii(current_digit+1); + break; + } else { + buf[i] = value2ascii(0); + i -= 1; + } + } + } + } + } + } + + // if number of digits is not exact, remove all trailing '0's up to + // and including the '.' + if !exact { + let buf_max_i = buf.len() - 1; + + // index to truncate from + let mut i = buf_max_i; + + // discover trailing zeros of fractional part + while i > start_fractional_digits && buf[i] == '0' as u8 { + i -= 1; + } + + // Only attempt to truncate digits if buf has fractional digits + if i >= start_fractional_digits { + // If buf ends with '.', cut that too. + if buf[i] == '.' as u8 { i -= 1 } + + // only resize buf if we actually remove digits + if i < buf_max_i { + buf = buf.slice(0, i + 1); + } + } + } // If exact and trailing '.', just cut that + else { + let max_i = buf.len() - 1; + if buf[max_i] == '.' as u8 { + buf = buf.slice(0, max_i); + } + } + + (buf, false) +} + +/** + * Converts a number to its string representation. This is a wrapper for + * `to_str_bytes_common()`, for details see there. + */ +#[inline(always)] +pub pure fn to_str_common+Neg + +Modulo+Mul>( + num: &T, radix: uint, special: bool, negative_zero: bool, + sign: SignFormat, digits: SignificantDigits) -> (~str, bool) { + let (bytes, special) = to_str_bytes_common(num, radix, special, + negative_zero, sign, digits); + (str::from_bytes(bytes), special) +} + +// Some constants for from_str_bytes_common's input validation, +// they define minimum radix values for which the character is a valid digit. +priv const DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u; +priv const DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u; +priv const 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 a empty `buf` as a 0 or not. + * + * # 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'`. + * + * # Possible improvements + * - Could accept option to allow ignoring underscores, allowing for numbers + * formated like `FF_AE_FF_FF`. + */ +pub pure fn from_str_bytes_common+ + Mul+Sub+Neg+Add>( + buf: &[u8], radix: uint, negative: bool, fractional: bool, + special: bool, exponent: ExponentFormat, empty_zero: bool + ) -> Option { + match exponent { + ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e' + => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \ + use of 'e' as decimal exponent", radix)), + ExpBin if radix >= DIGIT_P_RADIX // binary exponent 'p' + => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \ + use of 'p' as binary exponent", radix)), + _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf' + => fail!(fmt!("from_str_bytes_common: radix %? incompatible with \ + special values 'inf' and 'NaN'", radix)), + _ if radix as int < 2 + => fail!(fmt!("from_str_bytes_common: radix %? to low, \ + must lie in the range [2, 36]", radix)), + _ if radix as int > 36 + => fail!(fmt!("from_str_bytes_common: radix %? to high, \ + must lie in the range [2, 36]", radix)), + _ => () + } + + let _0: T = Zero::zero(); + let _1: T = One::one(); + let radix_gen: T = cast(radix as int); + + let len = buf.len(); + + if len == 0 { + if empty_zero { + return Some(_0); + } else { + return None; + } + } + + if special { + if buf == str::to_bytes("inf") || buf == str::to_bytes("+inf") { + return Some(infinity()); + } else if buf == str::to_bytes("-inf") { + if negative { + return Some(neg_infinity()); + } else { + return None; + } + } else if buf == str::to_bytes("NaN") { + return Some(NaN()); + } + } + + let (start, accum_positive) = match buf[0] { + '-' as u8 if !negative => return None, + '-' as u8 => (1u, false), + '+' as u8 => (1u, true), + _ => (0u, true) + }; + + // Initialize accumulator with signed zero for floating point parsing to + // work + let mut accum = if accum_positive { _0 } else { -_1 * _0}; + let mut last_accum = accum; // Necessary to detect overflow + let mut i = start; + let mut exp_found = false; + + // Parse integer part of number + while i < len { + let c = buf[i] as char; + + match char::to_digit(c, radix) { + Some(digit) => { + // shift accum one digit left + accum *= radix_gen; + + // add/subtract current digit depending on sign + if accum_positive { + accum += cast(digit as int); + } else { + accum -= cast(digit as int); + } + + // Detect overflow by comparing to last value + if accum_positive && accum < last_accum { return None; } + if !accum_positive && accum > last_accum { return None; } + last_accum = accum; + } + None => match c { + '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 + } + } + + i += 1u; + } + + // Parse fractional part of number + // Skip if already reached start of exponent + if !exp_found { + let mut power = _1; + + while i < len { + let c = buf[i] as char; + + match char::to_digit(c, radix) { + Some(digit) => { + // Decrease power one order of magnitude + power /= radix_gen; + + let digit_t: T = cast(digit); + + // add/subtract current digit depending on sign + if accum_positive { + accum += digit_t * power; + } else { + accum -= digit_t * power; + } + + // Detect overflow by comparing to last value + if accum_positive && accum < last_accum { return None; } + if !accum_positive && accum > last_accum { return None; } + last_accum = accum; + } + None => match c { + 'e' | 'E' | 'p' | 'P' => { + exp_found = true; + 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; + } + } + + let mut multiplier = _1; + + if exp_found { + let c = buf[i] as char; + let base = match (c, exponent) { + ('e', ExpDec) | ('E', ExpDec) => 10u, + ('p', ExpBin) | ('P', ExpBin) => 2u, + _ => return None // char doesn't fit given exponent format + }; + + // parse remaining bytes as decimal integer, + // skipping the exponent char + let exp: Option = from_str_bytes_common( + buf.view(i+1, len), 10, true, false, false, ExpNone, false); + + match exp { + Some(exp_pow) => { + multiplier = if exp_pow < 0 { + _1 / pow_with_uint::(base, (-exp_pow.to_int()) as uint) + } else { + pow_with_uint::(base, exp_pow.to_int() as uint) + } + } + None => return None // invalid exponent -> invalid number + } + } + + Some(accum * multiplier) +} + +/** + * Parses a string as a number. This is a wrapper for + * `from_str_bytes_common()`, for details see there. + */ +#[inline(always)] +pub pure fn from_str_common+Mul+ + Sub+Neg+Add>( + buf: &str, radix: uint, negative: bool, fractional: bool, + special: bool, exponent: ExponentFormat, empty_zero: bool + ) -> Option { + from_str_bytes_common(str::to_bytes(buf), radix, negative, + fractional, special, exponent, empty_zero) +} diff --git a/src/libcore/num/uint-template.rs b/src/libcore/num/uint-template.rs index b1ef3f11fa4..9829bf9d9e0 100644 --- a/src/libcore/num/uint-template.rs +++ b/src/libcore/num/uint-template.rs @@ -17,6 +17,7 @@ use cmp; use to_str::ToStr; use from_str::FromStr; use num::{ToStrRadix, FromStrRadix}; +use num::strconv; use num; use option::{None, Option, Some}; use prelude::*; @@ -182,22 +183,22 @@ impl ops::Neg for T { /// Parse a string as a number in base 10. #[inline(always)] pub pure fn from_str(s: &str) -> Option { - num::from_str_common(s, 10u, false, false, false, - num::ExpNone, false) + strconv::from_str_common(s, 10u, false, false, false, + strconv::ExpNone, false) } /// Parse a string as a number in the given base. #[inline(always)] pub pure fn from_str_radix(s: &str, radix: uint) -> Option { - num::from_str_common(s, radix, false, false, false, - num::ExpNone, false) + strconv::from_str_common(s, radix, false, false, false, + strconv::ExpNone, false) } /// Parse a byte slice as a number in the given base. #[inline(always)] pub pure fn parse_bytes(buf: &[u8], radix: uint) -> Option { - num::from_str_bytes_common(buf, radix, false, false, false, - num::ExpNone, false) + strconv::from_str_bytes_common(buf, radix, false, false, false, + strconv::ExpNone, false) } impl FromStr for T { @@ -219,24 +220,24 @@ impl FromStrRadix for T { /// Convert to a string as a byte slice in a given base. #[inline(always)] pub pure fn to_str_bytes(n: T, radix: uint, f: fn(v: &[u8]) -> U) -> U { - let (buf, _) = num::to_str_bytes_common(&n, radix, false, false, - num::SignNeg, num::DigAll); + let (buf, _) = strconv::to_str_bytes_common(&n, radix, false, false, + strconv::SignNeg, strconv::DigAll); f(buf) } /// Convert to a string in base 10. #[inline(always)] pub pure fn to_str(num: T) -> ~str { - let (buf, _) = num::to_str_common(&num, 10u, false, false, - num::SignNeg, num::DigAll); + let (buf, _) = strconv::to_str_common(&num, 10u, false, false, + strconv::SignNeg, strconv::DigAll); buf } /// Convert to a string in a given base. #[inline(always)] pub pure fn to_str_radix(num: T, radix: uint) -> ~str { - let (buf, _) = num::to_str_common(&num, radix, false, false, - num::SignNeg, num::DigAll); + let (buf, _) = strconv::to_str_common(&num, radix, false, false, + strconv::SignNeg, strconv::DigAll); buf }