14
14
15
15
use char;
16
16
use char:: Char ;
17
- use clone:: Clone ;
18
17
use from_str:: from_str;
19
18
use iter:: Iterator ;
20
19
use num;
21
- use num:: { Zero , One , cast , Int , Bounded } ;
20
+ use num:: { Int , Bounded } ;
22
21
use num:: { Float , FPNaN , FPInfinite , ToPrimitive } ;
23
22
use option:: { None , Option , Some } ;
24
23
use slice:: { ImmutableSlice , MutableSlice , CloneableVector } ;
25
- use str:: { Str , StrSlice } ;
24
+ use str:: StrSlice ;
26
25
use string:: String ;
27
26
use vec:: Vec ;
28
27
@@ -68,12 +67,6 @@ pub enum SignFormat {
68
67
SignAll ,
69
68
}
70
69
71
- // Special value strings as [u8] consts.
72
- static INF_BUF : [ u8 , ..3 ] = [ b'i' , b'n' , b'f' ] ;
73
- static POS_INF_BUF : [ u8 , ..4 ] = [ b'+' , b'i' , b'n' , b'f' ] ;
74
- static NEG_INF_BUF : [ u8 , ..4 ] = [ b'-' , b'i' , b'n' , b'f' ] ;
75
- static NAN_BUF : [ u8 , ..3 ] = [ b'N' , b'a' , b'N' ] ;
76
-
77
70
/**
78
71
* Converts an integral number to its string representation as a byte vector.
79
72
* This is meant to be a common base implementation for all integral string
@@ -102,10 +95,10 @@ static NAN_BUF: [u8, ..3] = [b'N', b'a', b'N'];
102
95
fn int_to_str_bytes_common < T : Int > ( num : T , radix : uint , sign : SignFormat , f: |u8|) {
103
96
assert ! ( 2 <= radix && radix <= 36 ) ;
104
97
105
- let _0: T = Zero :: zero ( ) ;
98
+ let _0: T = num :: zero ( ) ;
106
99
107
100
let neg = num < _0;
108
- let radix_gen: T = cast ( radix) . unwrap ( ) ;
101
+ let radix_gen: T = num :: cast ( radix) . unwrap ( ) ;
109
102
110
103
let mut deccum = num;
111
104
// This is just for integral types, the largest of which is a u64. The
@@ -202,8 +195,8 @@ pub fn float_to_str_bytes_common<T: Float>(
202
195
_ => ( )
203
196
}
204
197
205
- let _0: T = Zero :: zero ( ) ;
206
- let _1: T = One :: one ( ) ;
198
+ let _0: T = num :: zero ( ) ;
199
+ let _1: T = num :: one ( ) ;
207
200
208
201
match num. classify ( ) {
209
202
FPNaN => { return ( b"NaN" . to_vec ( ) , true ) ; }
@@ -224,7 +217,7 @@ pub fn float_to_str_bytes_common<T: Float>(
224
217
225
218
let neg = num < _0 || ( negative_zero && _1 / num == Float :: neg_infinity ( ) ) ;
226
219
let mut buf = Vec :: new ( ) ;
227
- let radix_gen: T = cast ( radix as int ) . unwrap ( ) ;
220
+ let radix_gen: T = num :: cast ( radix as int ) . unwrap ( ) ;
228
221
229
222
let ( num, exp) = match exp_format {
230
223
ExpNone => ( num, 0i32 ) ,
@@ -233,12 +226,12 @@ pub fn float_to_str_bytes_common<T: Float>(
233
226
( num, 0i32 )
234
227
} else {
235
228
let ( exp, exp_base) = match exp_format {
236
- ExpDec => ( num. abs ( ) . log10 ( ) . floor ( ) , cast :: < f64 , T > ( 10.0f64 ) . unwrap ( ) ) ,
237
- ExpBin => ( num. abs ( ) . log2 ( ) . floor ( ) , cast :: < f64 , T > ( 2.0f64 ) . unwrap ( ) ) ,
229
+ ExpDec => ( num. abs ( ) . log10 ( ) . floor ( ) , num :: cast :: < f64 , T > ( 10.0f64 ) . unwrap ( ) ) ,
230
+ ExpBin => ( num. abs ( ) . log2 ( ) . floor ( ) , num :: cast :: < f64 , T > ( 2.0f64 ) . unwrap ( ) ) ,
238
231
ExpNone => unreachable ! ( )
239
232
} ;
240
233
241
- ( num / exp_base. powf ( exp) , cast :: < T , i32 > ( exp) . unwrap ( ) )
234
+ ( num / exp_base. powf ( exp) , num :: cast :: < T , i32 > ( exp) . unwrap ( ) )
242
235
}
243
236
}
244
237
} ;
@@ -490,163 +483,139 @@ pub fn from_str_float<T: Float>(
490
483
_ => ( )
491
484
}
492
485
493
- let _0: T = Zero :: zero ( ) ;
494
- let _1: T = One :: one ( ) ;
495
- let radix_gen: T = cast ( radix as int ) . unwrap ( ) ;
496
- let buf = src. as_bytes ( ) ;
497
-
498
- let len = buf. len ( ) ;
499
-
500
- if len == 0 {
501
- return None ;
502
- }
486
+ let _0: T = num:: zero ( ) ;
487
+ let _1: T = num:: one ( ) ;
488
+ let radix_gen: T = num:: cast ( radix as int ) . unwrap ( ) ;
503
489
504
- if special {
505
- if buf == INF_BUF || buf == POS_INF_BUF {
506
- return Some ( Float :: infinity ( ) ) ;
507
- } else if buf == NEG_INF_BUF {
508
- return Some ( Float :: neg_infinity ( ) ) ;
509
- } else if buf == NAN_BUF {
510
- return Some ( Float :: nan ( ) ) ;
511
- }
490
+ match src {
491
+ "inf" => return Some ( Float :: infinity ( ) ) ,
492
+ "-inf" => return Some ( Float :: neg_infinity ( ) ) ,
493
+ "NaN" => return Some ( Float :: nan ( ) ) ,
494
+ _ => { } ,
512
495
}
513
496
514
- let ( start, accum_positive) = match buf[ 0 ] as char {
515
- '-' => ( 1 u, false ) ,
516
- '+' => ( 1 u, true ) ,
517
- _ => ( 0 u, true )
497
+ let ( is_positive, src) = match src. slice_shift_char ( ) {
498
+ ( None , _) => return None ,
499
+ ( Some ( '-' ) , "" ) => return None ,
500
+ ( Some ( '-' ) , src) => ( false , src) ,
501
+ ( Some ( _) , _) => ( true , src) ,
518
502
} ;
519
503
520
504
// Initialize accumulator with signed zero for floating point parsing to
521
505
// work
522
- let mut accum = if accum_positive { _0. clone ( ) } else { -_1 * _0 } ;
523
- let mut last_accum = accum. clone ( ) ; // Necessary to detect overflow
524
- let mut i = start ;
525
- let mut exp_found = false ;
506
+ let mut accum = if is_positive { _0 } else { -_1 } ;
507
+ let mut last_accum = accum; // Necessary to detect overflow
508
+ let mut cs = src . chars ( ) . enumerate ( ) ;
509
+ let mut exp = None :: < ( char , uint ) > ;
526
510
527
511
// Parse integer part of number
528
- while i < len {
529
- let c = buf[ i] as char ;
530
-
531
- match char:: to_digit ( c, radix) {
532
- Some ( digit) => {
533
- // shift accum one digit left
534
- accum = accum * radix_gen. clone ( ) ;
535
-
536
- // add/subtract current digit depending on sign
537
- if accum_positive {
538
- accum = accum + cast ( digit as int ) . unwrap ( ) ;
539
- } else {
540
- accum = accum - cast ( digit as int ) . unwrap ( ) ;
541
- }
542
-
543
- // Detect overflow by comparing to last value, except
544
- // if we've not seen any non-zero digits.
545
- if last_accum != _0 {
546
- if accum_positive && accum <= last_accum { return Some ( Float :: infinity ( ) ) ; }
547
- if !accum_positive && accum >= last_accum { return Some ( Float :: neg_infinity ( ) ) ; }
548
-
549
- // Detect overflow by reversing the shift-and-add process
550
- if accum_positive &&
551
- ( last_accum != ( ( accum - cast ( digit as int ) . unwrap ( ) ) /radix_gen. clone ( ) ) ) {
552
- return Some ( Float :: infinity ( ) ) ;
553
- }
554
- if !accum_positive &&
555
- ( last_accum != ( ( accum + cast ( digit as int ) . unwrap ( ) ) /radix_gen. clone ( ) ) ) {
556
- return Some ( Float :: neg_infinity ( ) ) ;
557
- }
558
- }
559
- last_accum = accum. clone ( ) ;
560
- }
561
- None => match c {
562
- 'e' | 'E' | 'p' | 'P' => {
563
- exp_found = true ;
564
- break ; // start of exponent
565
- }
566
- '.' => {
567
- i += 1 u; // skip the '.'
568
- break ; // start of fractional part
569
- }
570
- _ => return None // invalid number
571
- }
572
- }
573
-
574
- i += 1 u;
575
- }
576
-
577
- // Parse fractional part of number
578
- // Skip if already reached start of exponent
579
- if !exp_found {
580
- let mut power = _1. clone ( ) ;
581
-
582
- while i < len {
583
- let c = buf[ i] as char ;
584
-
585
- match char:: to_digit ( c, radix) {
512
+ for ( i, c) in cs {
513
+ match c {
514
+ 'e' | 'E' | 'p' | 'P' => {
515
+ exp = Some ( ( c, i + 1 ) ) ;
516
+ break ; // start of exponent
517
+ } ,
518
+ '.' => {
519
+ break ; // start of fractional part
520
+ } ,
521
+ c => match c. to_digit ( radix) {
586
522
Some ( digit) => {
587
- // Decrease power one order of magnitude
588
- power = power / radix_gen;
589
-
590
- let digit_t: T = cast ( digit) . unwrap ( ) ;
523
+ // shift accum one digit left
524
+ accum = accum * radix_gen;
591
525
592
526
// add/subtract current digit depending on sign
593
- if accum_positive {
594
- accum = accum + digit_t * power ;
527
+ if is_positive {
528
+ accum = accum + num :: cast ( digit as int ) . unwrap ( ) ;
595
529
} else {
596
- accum = accum - digit_t * power ;
530
+ accum = accum - num :: cast ( digit as int ) . unwrap ( ) ;
597
531
}
598
532
599
- // Detect overflow by comparing to last value
600
- if accum_positive && accum < last_accum { return Some ( Float :: infinity ( ) ) ; }
601
- if !accum_positive && accum > last_accum { return Some ( Float :: neg_infinity ( ) ) ; }
602
- last_accum = accum. clone ( ) ;
603
- }
604
- None => match c {
605
- 'e' | 'E' | 'p' | 'P' => {
606
- exp_found = true ;
607
- break ; // start of exponent
533
+ // Detect overflow by comparing to last value, except
534
+ // if we've not seen any non-zero digits.
535
+ if last_accum != _0 {
536
+ if is_positive && accum <= last_accum { return Some ( Float :: infinity ( ) ) ; }
537
+ if !is_positive && accum >= last_accum { return Some ( Float :: neg_infinity ( ) ) ; }
538
+
539
+ // Detect overflow by reversing the shift-and-add process
540
+ if is_positive &&
541
+ ( last_accum != ( ( accum - num:: cast ( digit as int ) . unwrap ( ) ) / radix_gen) ) {
542
+ return Some ( Float :: infinity ( ) ) ;
543
+ }
544
+ if !is_positive &&
545
+ ( last_accum != ( ( accum + num:: cast ( digit as int ) . unwrap ( ) ) / radix_gen) ) {
546
+ return Some ( Float :: neg_infinity ( ) ) ;
547
+ }
608
548
}
609
- _ => return None // invalid number
610
- }
611
- }
612
-
613
- i += 1 u;
549
+ last_accum = accum;
550
+ } ,
551
+ None => {
552
+ return None ; // invalid number
553
+ } ,
554
+ } ,
614
555
}
615
556
}
616
557
617
- // Special case: buf not empty, but does not contain any digit in front
618
- // of the exponent sign -> number is empty string
619
- if i == start {
620
- return None ;
558
+ // Parse fractional part of number
559
+ // Skip if already reached start of exponent
560
+ if exp. is_none ( ) {
561
+ let mut power = _1;
562
+ for ( i, c) in cs {
563
+ match c {
564
+ 'e' | 'E' | 'p' | 'P' => {
565
+ exp = Some ( ( c, i + 1 ) ) ;
566
+ break ; // start of exponent
567
+ } ,
568
+ c => match c. to_digit ( radix) {
569
+ Some ( digit) => {
570
+ let digit: T = num:: cast ( digit) . unwrap ( ) ;
571
+
572
+ // Decrease power one order of magnitude
573
+ power = power / radix_gen;
574
+ // add/subtract current digit depending on sign
575
+ accum = if is_positive {
576
+ accum + digit * power
577
+ } else {
578
+ accum - digit * power
579
+ } ;
580
+ // Detect overflow by comparing to last value
581
+ if is_positive && accum < last_accum { return Some ( Float :: infinity ( ) ) ; }
582
+ if !is_positive && accum > last_accum { return Some ( Float :: neg_infinity ( ) ) ; }
583
+ last_accum = accum;
584
+ } ,
585
+ None => {
586
+ return None ; // invalid number
587
+ } ,
588
+ } ,
589
+ }
590
+ }
621
591
}
622
592
623
- let mut multiplier = _1. clone ( ) ;
624
-
625
- if exp_found {
626
- let c = buf[ i] as char ;
627
- let base: T = match ( c, exponent) {
628
- // c is never _ so don't need to handle specially
629
- ( 'e' , ExpDec ) | ( 'E' , ExpDec ) => cast ( 10 u) . unwrap ( ) ,
630
- ( 'p' , ExpBin ) | ( 'P' , ExpBin ) => cast ( 2 u) . unwrap ( ) ,
631
- _ => return None // char doesn't fit given exponent format
632
- } ;
633
-
634
- // parse remaining bytes as decimal integer,
635
- // skipping the exponent char
636
- let exp = from_str :: < int > ( String :: from_utf8_lossy ( buf[ i+1 ..len] ) . as_slice ( ) ) ;
637
-
638
- match exp {
639
- Some ( exp_pow) => {
640
- multiplier = if exp_pow < 0 {
593
+ let multiplier = match exp {
594
+ None => {
595
+ _1 // no exponent
596
+ } ,
597
+ Some ( ( c, offset) ) => {
598
+ let base: T = match ( c, exponent) {
599
+ // c is never _ so don't need to handle specially
600
+ ( 'e' , ExpDec ) | ( 'E' , ExpDec ) => num:: cast ( 10 u) . unwrap ( ) ,
601
+ ( 'p' , ExpBin ) | ( 'P' , ExpBin ) => num:: cast ( 2 u) . unwrap ( ) ,
602
+ _ => return None , // char doesn't fit given exponent format
603
+ } ;
604
+ // parse remaining string as decimal integer
605
+ let exp = from_str :: < int > ( src[ offset..] ) ;
606
+ match exp {
607
+ Some ( exp_pow) if exp_pow < 0 => {
641
608
_1 / num:: pow ( base, ( -exp_pow. to_int ( ) . unwrap ( ) ) as uint )
642
- } else {
609
+ } ,
610
+ Some ( exp_pow) => {
643
611
num:: pow ( base, exp_pow. to_int ( ) . unwrap ( ) as uint )
644
- }
612
+ } ,
613
+ None => {
614
+ return None ; // invalid exponent
615
+ } ,
645
616
}
646
- None => return None // invalid exponent -> invalid number
647
- }
648
- }
649
-
617
+ } ,
618
+ } ;
650
619
Some ( accum * multiplier)
651
620
}
652
621
@@ -659,9 +628,9 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
659
628
let _1: T = num:: one ( ) ;
660
629
let is_signed = _0 > Bounded :: min_value ( ) ;
661
630
662
- let ( is_negative , src) = match src. slice_shift_char ( ) {
663
- ( Some ( '-' ) , src) if is_signed => ( true , src) ,
664
- ( Some ( _) , _) => ( false , src) ,
631
+ let ( is_positive , src) = match src. slice_shift_char ( ) {
632
+ ( Some ( '-' ) , src) if is_signed => ( false , src) ,
633
+ ( Some ( _) , _) => ( true , src) ,
665
634
( None , _) => return None ,
666
635
} ;
667
636
@@ -671,7 +640,7 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
671
640
let radix = cast ( radix) ;
672
641
let mut result = _0;
673
642
674
- if is_negative {
643
+ if is_positive {
675
644
for x in xs {
676
645
let x = match x {
677
646
Some ( x) => x,
@@ -681,7 +650,7 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
681
650
Some ( result) => result,
682
651
None => return None ,
683
652
} ;
684
- result = match result. checked_sub ( & x) {
653
+ result = match result. checked_add ( & x) {
685
654
Some ( result) => result,
686
655
None => return None ,
687
656
} ;
@@ -696,7 +665,7 @@ pub fn from_str_radix_int<T: Int>(src: &str, radix: uint) -> Option<T> {
696
665
Some ( result) => result,
697
666
None => return None ,
698
667
} ;
699
- result = match result. checked_add ( & x) {
668
+ result = match result. checked_sub ( & x) {
700
669
Some ( result) => result,
701
670
None => return None ,
702
671
} ;
0 commit comments