(index<- )        ./libstd/num/strconv.rs

    git branch:    * master           5200215 auto merge of #14035 : alexcrichton/rust/experimental, r=huonw
    modified:    Fri May  9 13:02:28 2014
   1  // Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
   2  // file at the top-level directory of this distribution and at
   3  // http://rust-lang.org/COPYRIGHT.
   4  //
   5  // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
   6  // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
   7  // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
   8  // option. This file may not be copied, modified, or distributed
   9  // except according to those terms.
  10  
  11  #![allow(missing_doc)]
  12  
  13  use char;
  14  use clone::Clone;
  15  use container::Container;
  16  use iter::Iterator;
  17  use num::{NumCast, Zero, One, cast, Int};
  18  use num::{Float, FPNaN, FPInfinite, ToPrimitive};
  19  use num;
  20  use ops::{Add, Sub, Mul, Div, Rem, Neg};
  21  use option::{None, Option, Some};
  22  use slice::{CloneableVector, ImmutableVector, MutableVector};
  23  use std::cmp::{Ord, Eq};
  24  use str::{StrAllocating, StrSlice};
  25  use strbuf::StrBuf;
  26  use vec::Vec;
  27  
  28  /// A flag that specifies whether to use exponential (scientific) notation.
  29  pub enum ExponentFormat {
  30      /// Do not use exponential notation.
  31      ExpNone,
  32      /// Use exponential notation with the exponent having a base of 10 and the
  33      /// exponent sign being `e` or `E`. For example, 1000 would be printed
  34      /// 1e3.
  35      ExpDec,
  36      /// Use exponential notation with the exponent having a base of 2 and the
  37      /// exponent sign being `p` or `P`. For example, 8 would be printed 1p3.
  38      ExpBin,
  39  }
  40  
  41  /// The number of digits used for emitting the fractional part of a number, if
  42  /// any.
  43  pub enum SignificantDigits {
  44      /// All calculable digits will be printed.
  45      ///
  46      /// Note that bignums or fractions may cause a surprisingly large number
  47      /// of digits to be printed.
  48      DigAll,
  49  
  50      /// At most the given number of digits will be printed, truncating any
  51      /// trailing zeroes.
  52      DigMax(uint),
  53  
  54      /// Precisely the given number of digits will be printed.
  55      DigExact(uint)
  56  }
  57  
  58  /// How to emit the sign of a number.
  59  pub enum SignFormat {
  60      /// No sign will be printed. The exponent sign will also be emitted.
  61      SignNone,
  62      /// `-` will be printed for negative values, but no sign will be emitted
  63      /// for positive numbers.
  64      SignNeg,
  65      /// `+` will be printed for positive values, and `-` will be printed for
  66      /// negative values.
  67      SignAll,
  68  }
  69  
  70  /// Encompasses functions used by the string converter.
  71  pub trait NumStrConv {
  72      /// Returns the NaN value.
  73      fn nan()      -> Option<Self>;
  74  
  75      /// Returns the infinite value.
  76      fn inf()      -> Option<Self>;
  77  
  78      /// Returns the negative infinite value.
  79      fn neg_inf()  -> Option<Self>;
  80  
  81      /// Returns -0.0.
  82      fn neg_zero() -> Option<Self>;
  83  
  84      /// Rounds the number toward zero.
  85      fn round_to_zero(&self)   -> Self;
  86  
  87      /// Returns the fractional part of the number.
  88      fn fractional_part(&self) -> Self;
  89  }
  90  
  91  macro_rules! impl_NumStrConv_Floating (($t:ty) => (
  92      impl NumStrConv for $t {
  93          #[inline]
  94          fn nan()      -> Option<$t> { Some( 0.0 / 0.0) }
  95          #[inline]
  96          fn inf()      -> Option<$t> { Some( 1.0 / 0.0) }
  97          #[inline]
  98          fn neg_inf()  -> Option<$t> { Some(-1.0 / 0.0) }
  99          #[inline]
 100          fn neg_zero() -> Option<$t> { Some(-0.0      ) }
 101  
 102          #[inline]
 103          fn round_to_zero(&self) -> $t { self.trunc() }
 104          #[inline]
 105          fn fractional_part(&self) -> $t { self.fract() }
 106      }
 107  ))
 108  
 109  macro_rules! impl_NumStrConv_Integer (($t:ty) => (
 110      impl NumStrConv for $t {
 111          #[inline] fn nan()      -> Option<$t> { None }
 112          #[inline] fn inf()      -> Option<$t> { None }
 113          #[inline] fn neg_inf()  -> Option<$t> { None }
 114          #[inline] fn neg_zero() -> Option<$t> { None }
 115  
 116          #[inline] fn round_to_zero(&self)   -> $t { *self }
 117          #[inline] fn fractional_part(&self) -> $t {     0 }
 118      }
 119  ))
 120  
 121  // FIXME: #4955
 122  // Replace by two generic impls for traits 'Integral' and 'Floating'
 123  impl_NumStrConv_Floating!(f32)
 124  impl_NumStrConv_Floating!(f64)
 125  
 126  impl_NumStrConv_Integer!(int)
 127  impl_NumStrConv_Integer!(i8)
 128  impl_NumStrConv_Integer!(i16)
 129  impl_NumStrConv_Integer!(i32)
 130  impl_NumStrConv_Integer!(i64)
 131  
 132  impl_NumStrConv_Integer!(uint)
 133  impl_NumStrConv_Integer!(u8)
 134  impl_NumStrConv_Integer!(u16)
 135  impl_NumStrConv_Integer!(u32)
 136  impl_NumStrConv_Integer!(u64)
 137  
 138  
 139  // Special value strings as [u8] consts.
 140  static INF_BUF:          [u8, ..3] = ['i' as u8, 'n' as u8, 'f' as u8];
 141  static POS_INF_BUF: [u8, ..4] = ['+' as u8, 'i' as u8, 'n' as u8,
 142                                        'f' as u8];
 143  static NEG_INF_BUF: [u8, ..4] = ['-' as u8, 'i' as u8, 'n' as u8,
 144                                        'f' as u8];
 145  static NAN_BUF:          [u8, ..3] = ['N' as u8, 'a' as u8, 'N' as u8];
 146  
 147  /**
 148   * Converts an integral number to its string representation as a byte vector.
 149   * This is meant to be a common base implementation for all integral string
 150   * conversion functions like `to_str()` or `to_str_radix()`.
 151   *
 152   * # Arguments
 153   * - `num`           - The number to convert. Accepts any number that
 154   *                     implements the numeric traits.
 155   * - `radix`         - Base to use. Accepts only the values 2-36.
 156   * - `sign`          - How to emit the sign. Options are:
 157   *     - `SignNone`: No sign at all. Basically emits `abs(num)`.
 158   *     - `SignNeg`:  Only `-` on negative values.
 159   *     - `SignAll`:  Both `+` on positive, and `-` on negative numbers.
 160   * - `f`             - a callback which will be invoked for each ascii character
 161   *                     which composes the string representation of this integer
 162   *
 163   * # Return value
 164   * A tuple containing the byte vector, and a boolean flag indicating
 165   * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
 166   * It returns a tuple because there can be ambiguity between a special value
 167   * and a number representation at higher bases.
 168   *
 169   * # Failure
 170   * - Fails if `radix` < 2 or `radix` > 36.
 171   */
 172  pub fn int_to_str_bytes_common<T: Int>(numT, radix: uint, signSignFormat, f: |u8|) {
 173      assert!(2 <= radix && radix <= 36);
 174  
 175      let _0T = Zero::zero();
 176  
 177      let neg = num < _0;
 178      let radix_genT = cast(radix).unwrap();
 179  
 180      let mut deccum = num;
 181      // This is just for integral types, the largest of which is a u64. The
 182      // smallest base that we can have is 2, so the most number of digits we're
 183      // ever going to have is 64
 184      let mut buf = [0u8, ..64];
 185      let mut cur = 0;
 186  
 187      // Loop at least once to make sure at least a `0` gets emitted.
 188      loop {
 189          // Calculate the absolute value of each digit instead of only
 190          // doing it once for the whole number because a
 191          // representable negative number doesn't necessary have an
 192          // representable additive inverse of the same type
 193          // (See twos complement). But we assume that for the
 194          // numbers [-35 .. 0] we always have [0 .. 35].
 195          let current_digit_signed = deccum % radix_gen;
 196          let current_digit = if current_digit_signed < _0 {
 197              -current_digit_signed
 198          } else {
 199              current_digit_signed
 200          };
 201          buf[cur] = match current_digit.to_u8().unwrap() {
 202              i @ 0..9 => '0' as u8 + i,
 203              i        => 'a' as u8 + (i - 10),
 204          };
 205          cur += 1;
 206  
 207          deccum = deccum / radix_gen;
 208          // No more digits to calculate for the non-fractional part -> break
 209          if deccum == _0 { break; }
 210      }
 211  
 212      // Decide what sign to put in front
 213      match sign {
 214          SignNeg | SignAll if neg => { f('-' as u8); }
 215          SignAll => { f('+' as u8); }
 216          _ => ()
 217      }
 218  
 219      // We built the number in reverse order, so un-reverse it here
 220      while cur > 0 {
 221          cur -= 1;
 222          f(buf[cur]);
 223      }
 224  }
 225  
 226  /**
 227   * Converts a number to its string representation as a byte vector.
 228   * This is meant to be a common base implementation for all numeric string
 229   * conversion functions like `to_str()` or `to_str_radix()`.
 230   *
 231   * # Arguments
 232   * - `num`           - The number to convert. Accepts any number that
 233   *                     implements the numeric traits.
 234   * - `radix`         - Base to use. Accepts only the values 2-36. If the exponential notation
 235   *                     is used, then this base is only used for the significand. The exponent
 236   *                     itself always printed using a base of 10.
 237   * - `negative_zero` - Whether to treat the special value `-0` as
 238   *                     `-0` or as `+0`.
 239   * - `sign`          - How to emit the sign. See `SignFormat`.
 240   * - `digits`        - The amount of digits to use for emitting the fractional
 241   *                     part, if any. See `SignificantDigits`.
 242   * - `exp_format`   - Whether or not to use the exponential (scientific) notation.
 243   *                    See `ExponentFormat`.
 244   * - `exp_capital`   - Whether or not to use a capital letter for the exponent sign, if
 245   *                     exponential notation is desired.
 246   *
 247   * # Return value
 248   * A tuple containing the byte vector, and a boolean flag indicating
 249   * whether it represents a special value like `inf`, `-inf`, `NaN` or not.
 250   * It returns a tuple because there can be ambiguity between a special value
 251   * and a number representation at higher bases.
 252   *
 253   * # Failure
 254   * - Fails if `radix` < 2 or `radix` > 36.
 255   * - Fails if `radix` > 14 and `exp_format` is `ExpDec` due to conflict
 256   *   between digit and exponent sign `'e'`.
 257   * - Fails if `radix` > 25 and `exp_format` is `ExpBin` due to conflict
 258   *   between digit and exponent sign `'p'`.
 259   */
 260  pub fn float_to_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Float+
 261                                    Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
 262          numT, radix: uint, negative_zero: bool,
 263          signSignFormat, digitsSignificantDigits, exp_formatExponentFormat, exp_upper: bool
 264          ) -> (Vec<u8>, bool) {
 265      assert!(2 <= radix && radix <= 36);
 266      match exp_format {
 267          ExpDec if radix >= DIGIT_E_RADIX       // decimal exponent 'e'
 268            => fail!("float_to_str_bytes_common: radix {} incompatible with \
 269                      use of 'e' as decimal exponent", radix),
 270          ExpBin if radix >= DIGIT_P_RADIX       // binary exponent 'p'
 271            => fail!("float_to_str_bytes_common: radix {} incompatible with \
 272                      use of 'p' as binary exponent", radix),
 273          _ => ()
 274      }
 275  
 276      let _0T = Zero::zero();
 277      let _1T = One::one();
 278  
 279      match num.classify() {
 280          FPNaN => { return (Vec::from_slice("NaN".as_bytes()), true); }
 281          FPInfinite if num > _0 => {
 282              return match sign {
 283                  SignAll => (Vec::from_slice("+inf".as_bytes()), true),
 284                  _       => (Vec::from_slice("inf".as_bytes()), true)
 285              };
 286          }
 287          FPInfinite if num < _0 => {
 288              return match sign {
 289                  SignNone => (Vec::from_slice("inf".as_bytes()), true),
 290                  _        => (Vec::from_slice("-inf".as_bytes()), true),
 291              };
 292          }
 293          _ => {}
 294      }
 295  
 296      let neg = num < _0 || (negative_zero && _1 / num == Float::neg_infinity());
 297      let mut buf = Vec::new();
 298      let radix_genT   = cast(radix as int).unwrap();
 299  
 300      let (num, exp) = match exp_format {
 301          ExpNone => (num, 0i32),
 302          ExpDec | ExpBin => {
 303              if num == _0 {
 304                  (num, 0i32)
 305              } else {
 306                  let (exp, exp_base) = match exp_format {
 307                      ExpDec => (num.abs().log10().floor(), cast::<f64, T>(10.0f64).unwrap()),
 308                      ExpBin => (num.abs().log2().floor(), cast::<f64, T>(2.0f64).unwrap()),
 309                      ExpNone => unreachable!()
 310                  };
 311  
 312                  (num / exp_base.powf(exp), cast::<T, i32>(exp).unwrap())
 313              }
 314          }
 315      };
 316  
 317      // First emit the non-fractional part, looping at least once to make
 318      // sure at least a `0` gets emitted.
 319      let mut deccum = num.trunc();
 320      loop {
 321          // Calculate the absolute value of each digit instead of only
 322          // doing it once for the whole number because a
 323          // representable negative number doesn't necessary have an
 324          // representable additive inverse of the same type
 325          // (See twos complement). But we assume that for the
 326          // numbers [-35 .. 0] we always have [0 .. 35].
 327          let current_digit = (deccum % radix_gen).abs();
 328  
 329          // Decrease the deccumulator one digit at a time
 330          deccum = deccum / radix_gen;
 331          deccum = deccum.trunc();
 332  
 333          buf.push(char::from_digit(current_digit.to_int().unwrap() as uint, radix)
 334               .unwrap() as u8);
 335  
 336          // No more digits to calculate for the non-fractional part -> break
 337          if deccum == _0 { break; }
 338      }
 339  
 340      // If limited digits, calculate one digit more for rounding.
 341      let (limit_digits, digit_count, exact) = match digits {
 342          DigAll          => (false, 0u,      false),
 343          DigMax(count)   => (true,  count+1, false),
 344          DigExact(count) => (true,  count+1, true)
 345      };
 346  
 347      // Decide what sign to put in front
 348      match sign {
 349          SignNeg | SignAll if neg => {
 350              buf.push('-' as u8);
 351          }
 352          SignAll => {
 353              buf.push('+' as u8);
 354          }
 355          _ => ()
 356      }
 357  
 358      buf.reverse();
 359  
 360      // Remember start of the fractional digits.
 361      // Points one beyond end of buf if none get generated,
 362      // or at the '.' otherwise.
 363      let start_fractional_digits = buf.len();
 364  
 365      // Now emit the fractional part, if any
 366      deccum = num.fract();
 367      if deccum != _0 || (limit_digits && exact && digit_count > 0) {
 368          buf.push('.' as u8);
 369          let mut dig = 0u;
 370  
 371          // calculate new digits while
 372          // - there is no limit and there are digits left
 373          // - or there is a limit, it's not reached yet and
 374          //   - it's exact
 375          //   - or it's a maximum, and there are still digits left
 376          while (!limit_digits && deccum != _0)
 377             || (limit_digits && dig < digit_count && (
 378                     exact
 379                  || (!exact && deccum != _0)
 380                )
 381          ) {
 382              // Shift first fractional digit into the integer part
 383              deccum = deccum * radix_gen;
 384  
 385              // Calculate the absolute value of each digit.
 386              // See note in first loop.
 387              let current_digit = deccum.trunc().abs();
 388  
 389              buf.push(char::from_digit(
 390                  current_digit.to_int().unwrap() as uint, radix).unwrap() as u8);
 391  
 392              // Decrease the deccumulator one fractional digit at a time
 393              deccum = deccum.fract();
 394              dig += 1u;
 395          }
 396  
 397          // If digits are limited, and that limit has been reached,
 398          // cut off the one extra digit, and depending on its value
 399          // round the remaining ones.
 400          if limit_digits && dig == digit_count {
 401              let ascii2value = |chru8{
 402                  char::to_digit(chr as char, radix).unwrap()
 403              };
 404              let value2ascii = |valuint{
 405                  char::from_digit(val, radix).unwrap() as u8
 406              };
 407  
 408              let extra_digit = ascii2value(buf.pop().unwrap());
 409              if extra_digit >= radix / 2 { // -> need to round
 410                  let mut iint = buf.len() as int - 1;
 411                  loop {
 412                      // If reached left end of number, have to
 413                      // insert additional digit:
 414                      if i < 0
 415                      || *buf.get(i as uint) == '-' as u8
 416                      || *buf.get(i as uint) == '+' as u8 {
 417                          buf.insert((i + 1) as uint, value2ascii(1));
 418                          break;
 419                      }
 420  
 421                      // Skip the '.'
 422                      if *buf.get(i as uint) == '.' as u8 { i -= 1; continue; }
 423  
 424                      // Either increment the digit,
 425                      // or set to 0 if max and carry the 1.
 426                      let current_digit = ascii2value(*buf.get(i as uint));
 427                      if current_digit < (radix - 1) {
 428                          *buf.get_mut(i as uint) = value2ascii(current_digit+1);
 429                          break;
 430                      } else {
 431                          *buf.get_mut(i as uint) = value2ascii(0);
 432                          i -= 1;
 433                      }
 434                  }
 435              }
 436          }
 437      }
 438  
 439      // if number of digits is not exact, remove all trailing '0's up to
 440      // and including the '.'
 441      if !exact {
 442          let buf_max_i = buf.len() - 1;
 443  
 444          // index to truncate from
 445          let mut i = buf_max_i;
 446  
 447          // discover trailing zeros of fractional part
 448          while i > start_fractional_digits && *buf.get(i) == '0' as u8 {
 449              i -= 1;
 450          }
 451  
 452          // Only attempt to truncate digits if buf has fractional digits
 453          if i >= start_fractional_digits {
 454              // If buf ends with '.', cut that too.
 455              if *buf.get(i) == '.' as u8 { i -= 1 }
 456  
 457              // only resize buf if we actually remove digits
 458              if i < buf_max_i {
 459                  buf = Vec::from_slice(buf.slice(0, i + 1));
 460              }
 461          }
 462      } // If exact and trailing '.', just cut that
 463      else {
 464          let max_i = buf.len() - 1;
 465          if *buf.get(max_i) == '.' as u8 {
 466              buf = Vec::from_slice(buf.slice(0, max_i));
 467          }
 468      }
 469  
 470      match exp_format {
 471          ExpNone => (),
 472          _ => {
 473              buf.push(match exp_format {
 474                  ExpDec if exp_upper => 'E',
 475                  ExpDec if !exp_upper => 'e',
 476                  ExpBin if exp_upper => 'P',
 477                  ExpBin if !exp_upper => 'p',
 478                  _ => unreachable!()
 479              } as u8);
 480  
 481              int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
 482          }
 483      }
 484  
 485      (buf, false)
 486  }
 487  
 488  /**
 489   * Converts a number to its string representation. This is a wrapper for
 490   * `to_str_bytes_common()`, for details see there.
 491   */
 492  #[inline]
 493  pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+
 494                               Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
 495          numT, radix: uint, negative_zero: bool,
 496          signSignFormat, digitsSignificantDigits, exp_formatExponentFormat, exp_capital: bool
 497          ) -> (~str, bool) {
 498      let (bytes, special) = float_to_str_bytes_common(num, radix,
 499                                 negative_zero, sign, digits, exp_format, exp_capital);
 500      (StrBuf::from_utf8(bytes).unwrap().into_owned(), special)
 501  }
 502  
 503  // Some constants for from_str_bytes_common's input validation,
 504  // they define minimum radix values for which the character is a valid digit.
 505  static DIGIT_P_RADIX: uint = ('p' as uint) - ('a' as uint) + 11u;
 506  static DIGIT_I_RADIX: uint = ('i' as uint) - ('a' as uint) + 11u;
 507  static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
 508  
 509  /**
 510   * Parses a byte slice as a number. This is meant to
 511   * be a common base implementation for all numeric string conversion
 512   * functions like `from_str()` or `from_str_radix()`.
 513   *
 514   * # Arguments
 515   * - `buf`        - The byte slice to parse.
 516   * - `radix`      - Which base to parse the number as. Accepts 2-36.
 517   * - `negative`   - Whether to accept negative numbers.
 518   * - `fractional` - Whether to accept numbers with fractional parts.
 519   * - `special`    - Whether to accept special values like `inf`
 520   *                  and `NaN`. Can conflict with `radix`, see Failure.
 521   * - `exponent`   - Which exponent format to accept. Options are:
 522   *     - `ExpNone`: No Exponent, accepts just plain numbers like `42` or
 523   *                  `-8.2`.
 524   *     - `ExpDec`:  Accepts numbers with a decimal exponent like `42e5` or
 525   *                  `8.2E-2`. The exponent string itself is always base 10.
 526   *                  Can conflict with `radix`, see Failure.
 527   *     - `ExpBin`:  Accepts numbers with a binary exponent like `42P-8` or
 528   *                  `FFp128`. The exponent string itself is always base 10.
 529   *                  Can conflict with `radix`, see Failure.
 530   * - `empty_zero` - Whether to accept an empty `buf` as a 0 or not.
 531   * - `ignore_underscores` - Whether all underscores within the string should
 532   *                          be ignored.
 533   *
 534   * # Return value
 535   * Returns `Some(n)` if `buf` parses to a number n without overflowing, and
 536   * `None` otherwise, depending on the constraints set by the remaining
 537   * arguments.
 538   *
 539   * # Failure
 540   * - Fails if `radix` < 2 or `radix` > 36.
 541   * - Fails if `radix` > 14 and `exponent` is `ExpDec` due to conflict
 542   *   between digit and exponent sign `'e'`.
 543   * - Fails if `radix` > 25 and `exponent` is `ExpBin` due to conflict
 544   *   between digit and exponent sign `'p'`.
 545   * - Fails if `radix` > 18 and `special == true` due to conflict
 546   *   between digit and lowest first character in `inf` and `NaN`, the `'i'`.
 547   */
 548  pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
 549                                      Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
 550                                      NumStrConv+Clone>(
 551          buf: &[u8], radix: uint, negative: bool, fractional: bool,
 552          special: bool, exponentExponentFormat, empty_zero: bool,
 553          ignore_underscores: bool
 554          ) -> Option<T> {
 555      match exponent {
 556          ExpDec if radix >= DIGIT_E_RADIX       // decimal exponent 'e'
 557            => fail!("from_str_bytes_common: radix {} incompatible with \
 558                      use of 'e' as decimal exponent", radix),
 559          ExpBin if radix >= DIGIT_P_RADIX       // binary exponent 'p'
 560            => fail!("from_str_bytes_common: radix {} incompatible with \
 561                      use of 'p' as binary exponent", radix),
 562          _ if special && radix >= DIGIT_I_RADIX // first digit of 'inf'
 563            => fail!("from_str_bytes_common: radix {} incompatible with \
 564                      special values 'inf' and 'NaN'", radix),
 565          _ if (radix as int) < 2
 566            => fail!("from_str_bytes_common: radix {} to low, \
 567                      must lie in the range [2, 36]", radix),
 568          _ if (radix as int) > 36
 569            => fail!("from_str_bytes_common: radix {} to high, \
 570                      must lie in the range [2, 36]", radix),
 571          _ => ()
 572      }
 573  
 574      let _0T = Zero::zero();
 575      let _1T = One::one();
 576      let radix_genT = cast(radix as int).unwrap();
 577  
 578      let len = buf.len();
 579  
 580      if len == 0 {
 581          if empty_zero {
 582              return Some(_0);
 583          } else {
 584              return None;
 585          }
 586      }
 587  
 588      if special {
 589          if buf == INF_BUF || buf == POS_INF_BUF {
 590              return NumStrConv::inf();
 591          } else if buf == NEG_INF_BUF {
 592              if negative {
 593                  return NumStrConv::neg_inf();
 594              } else {
 595                  return None;
 596              }
 597          } else if buf == NAN_BUF {
 598              return NumStrConv::nan();
 599          }
 600      }
 601  
 602      let (start, accum_positive) = match buf[0] as char {
 603        '-' if !negative => return None,
 604        '-' => (1u, false),
 605        '+' => (1u, true),
 606         _  => (0u, true)
 607      };
 608  
 609      // Initialize accumulator with signed zero for floating point parsing to
 610      // work
 611      let mut accum      = if accum_positive { _0.clone() } else { -_1 * _0};
 612      let mut last_accum = accum.clone(); // Necessary to detect overflow
 613      let mut i          = start;
 614      let mut exp_found  = false;
 615  
 616      // Parse integer part of number
 617      while i < len {
 618          let c = buf[i] as char;
 619  
 620          match char::to_digit(c, radix) {
 621              Some(digit) => {
 622                  // shift accum one digit left
 623                  accum = accum * radix_gen.clone();
 624  
 625                  // add/subtract current digit depending on sign
 626                  if accum_positive {
 627                      accum = accum + cast(digit as int).unwrap();
 628                  } else {
 629                      accum = accum - cast(digit as int).unwrap();
 630                  }
 631  
 632                  // Detect overflow by comparing to last value, except
 633                  // if we've not seen any non-zero digits.
 634                  if last_accum != _0 {
 635                      if accum_positive && accum <= last_accum { return NumStrConv::inf(); }
 636                      if !accum_positive && accum >= last_accum { return NumStrConv::neg_inf(); }
 637  
 638                      // Detect overflow by reversing the shift-and-add proccess
 639                      if accum_positive &&
 640                          (last_accum != ((accum - cast(digit as int).unwrap())/radix_gen.clone())) {
 641                          return NumStrConv::inf();
 642                      }
 643                      if !accum_positive &&
 644                          (last_accum != ((accum + cast(digit as int).unwrap())/radix_gen.clone())) {
 645                          return NumStrConv::neg_inf();
 646                      }
 647                  }
 648                  last_accum = accum.clone();
 649              }
 650              None => match c {
 651                  '_' if ignore_underscores => {}
 652                  'e' | 'E' | 'p' | 'P' => {
 653                      exp_found = true;
 654                      break;                       // start of exponent
 655                  }
 656                  '.' if fractional => {
 657                      i += 1u;                     // skip the '.'
 658                      break;                       // start of fractional part
 659                  }
 660                  _ => return None                 // invalid number
 661              }
 662          }
 663  
 664          i += 1u;
 665      }
 666  
 667      // Parse fractional part of number
 668      // Skip if already reached start of exponent
 669      if !exp_found {
 670          let mut power = _1.clone();
 671  
 672          while i < len {
 673              let c = buf[i] as char;
 674  
 675              match char::to_digit(c, radix) {
 676                  Some(digit) => {
 677                      // Decrease power one order of magnitude
 678                      power = power / radix_gen;
 679  
 680                      let digit_tT = cast(digit).unwrap();
 681  
 682                      // add/subtract current digit depending on sign
 683                      if accum_positive {
 684                          accum = accum + digit_t * power;
 685                      } else {
 686                          accum = accum - digit_t * power;
 687                      }
 688  
 689                      // Detect overflow by comparing to last value
 690                      if accum_positive && accum < last_accum { return NumStrConv::inf(); }
 691                      if !accum_positive && accum > last_accum { return NumStrConv::neg_inf(); }
 692                      last_accum = accum.clone();
 693                  }
 694                  None => match c {
 695                      '_' if ignore_underscores => {}
 696                      'e' | 'E' | 'p' | 'P' => {
 697                          exp_found = true;
 698                          break;                   // start of exponent
 699                      }
 700                      _ => return None             // invalid number
 701                  }
 702              }
 703  
 704              i += 1u;
 705          }
 706      }
 707  
 708      // Special case: buf not empty, but does not contain any digit in front
 709      // of the exponent sign -> number is empty string
 710      if i == start {
 711          if empty_zero {
 712              return Some(_0);
 713          } else {
 714              return None;
 715          }
 716      }
 717  
 718      let mut multiplier = _1.clone();
 719  
 720      if exp_found {
 721          let c = buf[i] as char;
 722          let baseT = match (c, exponent) {
 723              // c is never _ so don't need to handle specially
 724              ('e', ExpDec) | ('E', ExpDec) => cast(10u).unwrap(),
 725              ('p', ExpBin) | ('P', ExpBin) => cast(2u).unwrap(),
 726              _ => return None // char doesn't fit given exponent format
 727          };
 728  
 729          // parse remaining bytes as decimal integer,
 730          // skipping the exponent char
 731          let expOption<int> = from_str_bytes_common(
 732              buf.slice(i+1, len), 10, true, false, false, ExpNone, false,
 733              ignore_underscores);
 734  
 735          match exp {
 736              Some(exp_pow) => {
 737                  multiplier = if exp_pow < 0 {
 738                      _1 / num::pow(base, (-exp_pow.to_int().unwrap()) as uint)
 739                  } else {
 740                      num::pow(base, exp_pow.to_int().unwrap() as uint)
 741                  }
 742              }
 743              None => return None // invalid exponent -> invalid number
 744          }
 745      }
 746  
 747      Some(accum * multiplier)
 748  }
 749  
 750  /**
 751   * Parses a string as a number. This is a wrapper for
 752   * `from_str_bytes_common()`, for details see there.
 753   */
 754  #[inline]
 755  pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+Mul<T,T>+
 756                                Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
 757          buf: &str, radix: uint, negative: bool, fractional: bool,
 758          special: bool, exponentExponentFormat, empty_zero: bool,
 759          ignore_underscores: bool
 760          ) -> Option<T> {
 761      from_str_bytes_common(buf.as_bytes(), radix, negative,
 762                            fractional, special, exponent, empty_zero,
 763                            ignore_underscores)
 764  }
 765  
 766  #[cfg(test)]
 767  mod test {
 768      use super::*;
 769      use option::*;
 770  
 771      #[test]
 772      fn from_str_ignore_underscores() {
 773          let s : Option<u8> = from_str_common("__1__", 2, false, false, false,
 774                                               ExpNone, false, true);
 775          assert_eq!(s, Some(1u8));
 776  
 777          let n : Option<u8> = from_str_common("__1__", 2, false, false, false,
 778                                               ExpNone, false, false);
 779          assert_eq!(n, None);
 780  
 781          let f : Option<f32> = from_str_common("_1_._5_e_1_", 10, false, true, false,
 782                                                ExpDec, false, true);
 783          assert_eq!(f, Some(1.5e1f32));
 784      }
 785  
 786      #[test]
 787      fn from_str_issue5770() {
 788          // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems
 789          // since 255*2+1 == 255 (mod 256) so the overflow wasn't
 790          // detected.
 791          let n : Option<u8> = from_str_common("111111111", 2, false, false, false,
 792                                               ExpNone, false, false);
 793          assert_eq!(n, None);
 794      }
 795  
 796      #[test]
 797      fn from_str_issue7588() {
 798          let u : Option<u8> = from_str_common("1000", 10, false, false, false,
 799                                              ExpNone, false, false);
 800          assert_eq!(u, None);
 801          let s : Option<i16> = from_str_common("80000", 10, false, false, false,
 802                                               ExpNone, false, false);
 803          assert_eq!(s, None);
 804          let f : Option<f32> = from_str_common(
 805              "10000000000000000000000000000000000000000", 10, false, false, false,
 806              ExpNone, false, false);
 807          assert_eq!(f, NumStrConv::inf())
 808          let fe : Option<f32> = from_str_common("1e40", 10, false, false, false,
 809                                              ExpDec, false, false);
 810          assert_eq!(fe, NumStrConv::inf())
 811      }
 812  }
 813  
 814  #[cfg(test)]
 815  mod bench {
 816      extern crate test;
 817  
 818      mod uint {
 819          use super::test::Bencher;
 820          use rand::{XorShiftRng, Rng};
 821          use num::ToStrRadix;
 822          use realstd::result::ResultUnwrap;
 823  
 824          #[bench]
 825          fn to_str_bin(b: &mut Bencher) {
 826              let mut rng = XorShiftRng::new().unwrap();
 827              b.iter(|| { rng.gen::<uint>().to_str_radix(2); })
 828          }
 829  
 830          #[bench]
 831          fn to_str_oct(b: &mut Bencher) {
 832              let mut rng = XorShiftRng::new().unwrap();
 833              b.iter(|| { rng.gen::<uint>().to_str_radix(8); })
 834          }
 835  
 836          #[bench]
 837          fn to_str_dec(b: &mut Bencher) {
 838              let mut rng = XorShiftRng::new().unwrap();
 839              b.iter(|| { rng.gen::<uint>().to_str_radix(10); })
 840          }
 841  
 842          #[bench]
 843          fn to_str_hex(b: &mut Bencher) {
 844              let mut rng = XorShiftRng::new().unwrap();
 845              b.iter(|| { rng.gen::<uint>().to_str_radix(16); })
 846          }
 847  
 848          #[bench]
 849          fn to_str_base_36(b: &mut Bencher) {
 850              let mut rng = XorShiftRng::new().unwrap();
 851              b.iter(|| { rng.gen::<uint>().to_str_radix(36); })
 852          }
 853      }
 854  
 855      mod int {
 856          use super::test::Bencher;
 857          use rand::{XorShiftRng, Rng};
 858          use num::ToStrRadix;
 859          use realstd::result::ResultUnwrap;
 860  
 861          #[bench]
 862          fn to_str_bin(b: &mut Bencher) {
 863              let mut rng = XorShiftRng::new().unwrap();
 864              b.iter(|| { rng.gen::<int>().to_str_radix(2); })
 865          }
 866  
 867          #[bench]
 868          fn to_str_oct(b: &mut Bencher) {
 869              let mut rng = XorShiftRng::new().unwrap();
 870              b.iter(|| { rng.gen::<int>().to_str_radix(8); })
 871          }
 872  
 873          #[bench]
 874          fn to_str_dec(b: &mut Bencher) {
 875              let mut rng = XorShiftRng::new().unwrap();
 876              b.iter(|| { rng.gen::<int>().to_str_radix(10); })
 877          }
 878  
 879          #[bench]
 880          fn to_str_hex(b: &mut Bencher) {
 881              let mut rng = XorShiftRng::new().unwrap();
 882              b.iter(|| { rng.gen::<int>().to_str_radix(16); })
 883          }
 884  
 885          #[bench]
 886          fn to_str_base_36(b: &mut Bencher) {
 887              let mut rng = XorShiftRng::new().unwrap();
 888              b.iter(|| { rng.gen::<int>().to_str_radix(36); })
 889          }
 890      }
 891  
 892      mod f64 {
 893          use super::test::Bencher;
 894          use rand::{XorShiftRng, Rng};
 895          use f64;
 896          use realstd::result::ResultUnwrap;
 897  
 898          #[bench]
 899          fn float_to_str(b: &mut Bencher) {
 900              let mut rng = XorShiftRng::new().unwrap();
 901              b.iter(|| { f64::to_str(rng.gen()); })
 902          }
 903      }
 904  }


libstd/num/strconv.rs:42:9-42:9 -enum- definition:
/// any.
pub enum SignificantDigits {
    /// All calculable digits will be printed.
references:- 2
495:         num: T, radix: uint, negative_zero: bool,
496:         sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
497:         ) -> (~str, bool) {


libstd/num/strconv.rs:547:4-547:4 -fn- definition:
 */
pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+
                                    Mul<T,T>+Sub<T,T>+Neg<T>+Add<T,T>+
references:- 12
760:         ) -> Option<T> {
761:     from_str_bytes_common(buf.as_bytes(), radix, negative,
762:                           fractional, special, exponent, empty_zero,
libstd/num/int_macros.rs:
29: pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
30:     strconv::from_str_bytes_common(buf, radix, true, false, false,
31:                                strconv::ExpNone, false, false)
libstd/num/uint_macros.rs:
30: pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
31:     strconv::from_str_bytes_common(buf, radix, false, false, false,
32:                                    strconv::ExpNone, false, false)
libstd/num/int_macros.rs:
29: pub fn parse_bytes(buf: &[u8], radix: uint) -> Option<$T> {
30:     strconv::from_str_bytes_common(buf, radix, true, false, false,
31:                                strconv::ExpNone, false, false)


libstd/num/strconv.rs:28:76-28:76 -enum- definition:
/// A flag that specifies whether to use exponential (scientific) notation.
pub enum ExponentFormat {
    /// Do not use exponential notation.
references:- 4
262:         num: T, radix: uint, negative_zero: bool,
263:         sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_upper: bool
264:         ) -> (Vec<u8>, bool) {
--
495:         num: T, radix: uint, negative_zero: bool,
496:         sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
497:         ) -> (~str, bool) {
--
551:         buf: &[u8], radix: uint, negative: bool, fractional: bool,
552:         special: bool, exponent: ExponentFormat, empty_zero: bool,
553:         ignore_underscores: bool
--
757:         buf: &str, radix: uint, negative: bool, fractional: bool,
758:         special: bool, exponent: ExponentFormat, empty_zero: bool,
759:         ignore_underscores: bool


libstd/num/strconv.rs:58:38-58:38 -enum- definition:
/// How to emit the sign of a number.
pub enum SignFormat {
    /// No sign will be printed. The exponent sign will also be emitted.
references:- 3
171:  */
172: pub fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
173:     assert!(2 <= radix && radix <= 36);
--
495:         num: T, radix: uint, negative_zero: bool,
496:         sign: SignFormat, digits: SignificantDigits, exp_format: ExponentFormat, exp_capital: bool
497:         ) -> (~str, bool) {


libstd/num/strconv.rs:171:4-171:4 -fn- definition:
 */
pub fn int_to_str_bytes_common<T: Int>(num: T, radix: uint, sign: SignFormat, f: |u8|) {
    assert!(2 <= radix && radix <= 36);
references:- 21
481:             int_to_str_bytes_common(exp, 10, sign, |c| buf.push(c));
482:         }
libstd/num/int_macros.rs:
68:     let mut cur = 0;
69:     strconv::int_to_str_bytes_common(n, radix, strconv::SignNeg, |i| {
70:         buf[cur] = i;
--
83:         let mut buf = ::vec::Vec::new();
84:         strconv::int_to_str_bytes_common(*self, radix, strconv::SignNeg, |i| {
85:             buf.push(i);
libstd/num/uint_macros.rs:
69:     let mut cur = 0;
70:     strconv::int_to_str_bytes_common(n, radix, strconv::SignNone, |i| {
71:         buf[cur] = i;
--
84:         let mut buf = ::vec::Vec::new();
85:         strconv::int_to_str_bytes_common(*self, radix, strconv::SignNone, |i| {
86:             buf.push(i);
libstd/num/int_macros.rs:
68:     let mut cur = 0;
69:     strconv::int_to_str_bytes_common(n, radix, strconv::SignNeg, |i| {
70:         buf[cur] = i;


libstd/num/strconv.rs:70:56-70:56 -trait- definition:
/// Encompasses functions used by the string converter.
pub trait NumStrConv {
    /// Returns the NaN value.
references:- 21
91: macro_rules! impl_NumStrConv_Floating (($t:ty) => (
92:     impl NumStrConv for $t {
93:         #[inline]
--
493: pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+
494:                              Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
--
755: pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+Mul<T,T>+
756:                               Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
757:         buf: &str, radix: uint, negative: bool, fractional: bool,


libstd/num/strconv.rs:754:10-754:10 -fn- definition:
pub fn from_str_common<T:NumCast+Zero+One+Eq+Ord+Div<T,T>+Mul<T,T>+
                              Sub<T,T>+Neg<T>+Add<T,T>+NumStrConv+Clone>(
        buf: &str, radix: uint, negative: bool, fractional: bool,
references:- 26
libstd/num/int_macros.rs:
36:     fn from_str(s: &str) -> Option<$T> {
37:         strconv::from_str_common(s, 10u, true, false, false,
38:                              strconv::ExpNone, false, false)
--
44:     fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
45:         strconv::from_str_common(s, radix, true, false, false,
46:                              strconv::ExpNone, false, false)
libstd/num/uint_macros.rs:
45:     fn from_str_radix(s: &str, radix: uint) -> Option<$T> {
46:         strconv::from_str_common(s, radix, false, false, false,
47:                                  strconv::ExpNone, false, false)
libstd/num/f32.rs:
650: pub fn from_str_hex(num: &str) -> Option<f32> {
651:     strconv::from_str_common(num, 16u, true, true, true,
652:                              strconv::ExpBin, false, false)
--
707:     fn from_str_radix(val: &str, rdx: uint) -> Option<f32> {
708:         strconv::from_str_common(val, rdx, true, true, false,
709:                                  strconv::ExpNone, false, false)
libstd/num/f64.rs:
691:     fn from_str(val: &str) -> Option<f64> {
692:         strconv::from_str_common(val, 10u, true, true, true,
693:                                  strconv::ExpDec, false, false)
--
716:     fn from_str_radix(val: &str, rdx: uint) -> Option<f64> {
717:         strconv::from_str_common(val, rdx, true, true, false,
718:                                  strconv::ExpNone, false, false)
libstd/num/uint_macros.rs:
37:     fn from_str(s: &str) -> Option<$T> {
38:         strconv::from_str_common(s, 10u, false, false, false,
39:                                  strconv::ExpNone, false, false)


libstd/num/strconv.rs:492:10-492:10 -fn- definition:
pub fn float_to_str_common<T:NumCast+Zero+One+Eq+Ord+NumStrConv+Float+
                             Div<T,T>+Neg<T>+Rem<T,T>+Mul<T,T>>(
        num: T, radix: uint, negative_zero: bool,
references:- 16
libstd/num/f32.rs:
595: pub fn to_str_exp_digits(num: f32, dig: uint, upper: bool) -> ~str {
596:     let (r, _) = strconv::float_to_str_common(
597:         num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpDec, upper);
--
615:     fn to_str_radix(&self, rdx: uint) -> ~str {
616:         let (r, special) = strconv::float_to_str_common(
617:             *self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
libstd/num/f64.rs:
521: pub fn to_str(num: f64) -> ~str {
522:     let (r, _) = strconv::float_to_str_common(
523:         num, 10u, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
--
547: pub fn to_str_radix_special(num: f64, rdx: uint) -> (~str, bool) {
548:     strconv::float_to_str_common(num, rdx, true,
549:                            strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)
--
604: pub fn to_str_exp_digits(num: f64, dig: uint, upper: bool) -> ~str {
605:     let (r, _) = strconv::float_to_str_common(
606:         num, 10u, true, strconv::SignNeg, strconv::DigMax(dig), strconv::ExpDec, upper);
--
624:     fn to_str_radix(&self, rdx: uint) -> ~str {
625:         let (r, special) = strconv::float_to_str_common(
626:             *self, rdx, true, strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false);
libstd/num/f32.rs:
538: pub fn to_str_radix_special(num: f32, rdx: uint) -> (~str, bool) {
539:     strconv::float_to_str_common(num, rdx, true,
540:                            strconv::SignNeg, strconv::DigAll, strconv::ExpNone, false)