@@ -429,6 +429,8 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
429429 * `FFp128`. The exponent string itself is always base 10.
430430 * Can conflict with `radix`, see Failure.
431431 * - `empty_zero` - Whether to accept a empty `buf` as a 0 or not.
432+ * - `ignore_underscores` - Whether all underscores within the string should
433+ * be ignored.
432434 *
433435 * # Return value
434436 * Returns `Some(n)` if `buf` parses to a number n without overflowing, and
@@ -443,16 +445,13 @@ priv static DIGIT_E_RADIX: uint = ('e' as uint) - ('a' as uint) + 11u;
443445 * between digit and exponent sign `'p'`.
444446 * - Fails if `radix` > 18 and `special == true` due to conflict
445447 * between digit and lowest first character in `inf` and `NaN`, the `'i'`.
446- *
447- * # Possible improvements
448- * - Could accept option to allow ignoring underscores, allowing for numbers
449- * formated like `FF_AE_FF_FF`.
450448 */
451449pub fn from_str_bytes_common < T : NumCast +Zero +One +Eq +Ord +Copy +Div < T , T > +
452450 Mul < T , T > +Sub < T , T > +Neg < T > +Add < T , T > +
453451 NumStrConv > (
454452 buf : & [ u8 ] , radix : uint , negative : bool , fractional : bool ,
455- special : bool , exponent : ExponentFormat , empty_zero : bool
453+ special : bool , exponent : ExponentFormat , empty_zero : bool ,
454+ ignore_underscores : bool
456455 ) -> Option < T > {
457456 match exponent {
458457 ExpDec if radix >= DIGIT_E_RADIX // decimal exponent 'e'
@@ -540,6 +539,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
540539 last_accum = accum;
541540 }
542541 None => match c {
542+ '_' if ignore_underscores => { }
543543 'e' | 'E' | 'p' | 'P' => {
544544 exp_found = true ;
545545 break ; // start of exponent
@@ -583,6 +583,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
583583 last_accum = accum;
584584 }
585585 None => match c {
586+ '_' if ignore_underscores => { }
586587 'e' | 'E' | 'p' | 'P' => {
587588 exp_found = true ;
588589 break ; // start of exponent
@@ -610,6 +611,7 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
610611 if exp_found {
611612 let c = buf[ i] as char ;
612613 let base = match ( c, exponent) {
614+ // c is never _ so don't need to handle specially
613615 ( 'e' , ExpDec ) | ( 'E' , ExpDec ) => 10 u,
614616 ( 'p' , ExpBin ) | ( 'P' , ExpBin ) => 2 u,
615617 _ => return None // char doesn't fit given exponent format
@@ -618,7 +620,8 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
618620 // parse remaining bytes as decimal integer,
619621 // skipping the exponent char
620622 let exp: Option < int > = from_str_bytes_common (
621- buf. slice ( i+1 , len) , 10 , true , false , false , ExpNone , false ) ;
623+ buf. slice ( i+1 , len) , 10 , true , false , false , ExpNone , false ,
624+ ignore_underscores) ;
622625
623626 match exp {
624627 Some ( exp_pow) => {
@@ -643,24 +646,41 @@ pub fn from_str_bytes_common<T:NumCast+Zero+One+Eq+Ord+Copy+Div<T,T>+
643646pub fn from_str_common < T : NumCast +Zero +One +Eq +Ord +Copy +Div < T , T > +Mul < T , T > +
644647 Sub < T , T > +Neg < T > +Add < T , T > +NumStrConv > (
645648 buf : & str , radix : uint , negative : bool , fractional : bool ,
646- special : bool , exponent : ExponentFormat , empty_zero : bool
649+ special : bool , exponent : ExponentFormat , empty_zero : bool ,
650+ ignore_underscores : bool
647651 ) -> Option < T > {
648652 from_str_bytes_common ( str:: to_bytes ( buf) , radix, negative,
649- fractional, special, exponent, empty_zero)
653+ fractional, special, exponent, empty_zero,
654+ ignore_underscores)
650655}
651656
652657#[ cfg( test) ]
653658mod test {
654659 use super :: * ;
655660 use option:: * ;
656661
662+ #[ test]
663+ fn from_str_ignore_underscores ( ) {
664+ let s : Option < u8 > = from_str_common ( "__1__" , 2 , false , false , false ,
665+ ExpNone , false , true ) ;
666+ assert_eq ! ( s, Some ( 1u8 ) ) ;
667+
668+ let n : Option < u8 > = from_str_common ( "__1__" , 2 , false , false , false ,
669+ ExpNone , false , false ) ;
670+ assert_eq ! ( n, None ) ;
671+
672+ let f : Option < f32 > = from_str_common ( "_1_._1_e_1_" , 10 , false , true , false ,
673+ ExpDec , false , true ) ;
674+ assert_eq ! ( f, Some ( 1.1e1f32 ) ) ;
675+ }
676+
657677 #[ test]
658678 fn from_str_issue5770 ( ) {
659679 // try to parse 0b1_1111_1111 = 511 as a u8. Caused problems
660680 // since 255*2+1 == 255 (mod 256) so the overflow wasn't
661681 // detected.
662682 let n : Option < u8 > = from_str_common ( "111111111" , 2 , false , false , false ,
663- ExpNone , false ) ;
683+ ExpNone , false , false ) ;
664684 assert_eq ! ( n, None ) ;
665685 }
666686}
0 commit comments