37
37
slice,
38
38
split, splitn, split_nonempty,
39
39
split_char, splitn_char, split_char_nonempty,
40
- split_str,
40
+ split_str, split_str_nonempty ,
41
41
lines,
42
42
lines_any,
43
43
words,
@@ -494,31 +494,20 @@ fn split_inner(s: str, sepfn: fn(cc: char) -> bool, count: uint,
494
494
result
495
495
}
496
496
497
- /*
498
- Function: split_str
499
-
500
- Splits a string into a vector of the substrings separated by a given string
501
-
502
- Note that this has recently been changed. For example:
503
- > assert ["", "XXX", "YYY", ""] == split_str(".XXX.YYY.", ".")
504
-
505
- FIXME: Boyer-Moore should be faster
506
- */
507
- fn split_str ( s : str , sep : str ) -> [ str ] unsafe {
497
+ // FIXME use Boyer-Moore
498
+ fn iter_matches ( s : str , sep : str , f : fn ( uint , uint ) ) {
508
499
let sep_len = len ( sep) , l = len ( s) ;
509
500
assert sep_len > 0 u;
510
- let result = [ ] , i = 0 u, start = 0 u;
511
- let match_start = 0 u, match_i = 0 u;
501
+ let i = 0 u, match_start = 0 u, match_i = 0 u;
512
502
513
503
while i < l {
514
504
if s[ i] == sep[ match_i] {
515
505
if match_i == 0 u { match_start = i; }
516
506
match_i += 1 u;
517
507
// Found a match
518
508
if match_i == sep_len {
519
- result += [ unsafe :: slice_bytes ( s , start , match_start ) ] ;
509
+ f ( match_start , i + 1 u ) ;
520
510
match_i = 0 u;
521
- start = i + 1 u;
522
511
}
523
512
i += 1 u;
524
513
} else {
@@ -531,7 +520,40 @@ fn split_str(s: str, sep: str) -> [str] unsafe {
531
520
}
532
521
}
533
522
}
534
- result += [ unsafe :: slice_bytes ( s, start, l) ] ;
523
+ }
524
+
525
+ fn iter_between_matches ( s : str , sep : str , f : fn ( uint , uint ) ) {
526
+ let last_end = 0 u;
527
+ iter_matches ( s, sep) { |from, to|
528
+ f ( last_end, from) ;
529
+ last_end = to;
530
+ }
531
+ f ( last_end, len ( s) ) ;
532
+ }
533
+
534
+ /*
535
+ Function: split_str
536
+
537
+ Splits a string into a vector of the substrings separated by a given string
538
+
539
+ Note that this has recently been changed. For example:
540
+ > assert ["", "XXX", "YYY", ""] == split_str(".XXX.YYY.", ".")
541
+ */
542
+ fn split_str ( s : str , sep : str ) -> [ str ] {
543
+ let result = [ ] ;
544
+ iter_between_matches ( s, sep) { |from, to|
545
+ unsafe { result += [ unsafe :: slice_bytes ( s, from, to) ] ; }
546
+ }
547
+ result
548
+ }
549
+
550
+ fn split_str_nonempty ( s : str , sep : str ) -> [ str ] {
551
+ let result = [ ] ;
552
+ iter_between_matches ( s, sep) { |from, to|
553
+ if to > from {
554
+ unsafe { result += [ unsafe :: slice_bytes ( s, from, to) ] ; }
555
+ }
556
+ }
535
557
result
536
558
}
537
559
@@ -587,7 +609,6 @@ fn to_upper(s: str) -> str {
587
609
map ( s, char:: to_upper)
588
610
}
589
611
590
- // FIXME: This is super-inefficient: stop the extra slicing copies
591
612
/*
592
613
Function: replace
593
614
@@ -604,24 +625,12 @@ Returns:
604
625
The original string with all occurances of `from` replaced with `to`
605
626
*/
606
627
fn replace ( s : str , from : str , to : str ) -> str unsafe {
607
- assert is_not_empty ( from) ;
608
- if len ( s) == 0 u {
609
- ret "" ;
610
- } else if starts_with ( s, from) {
611
- ret to + replace (
612
- unsafe :: slice_bytes ( s, len ( from) , len ( s) ) ,
613
- from, to) ;
614
- } else {
615
- let idx;
616
- alt find( s, from) {
617
- some ( x) { idx = x; }
618
- none { ret s; }
619
- }
620
- let before = unsafe :: slice_bytes ( s, 0 u, idx as uint ) ;
621
- let after = unsafe :: slice_bytes ( s, idx as uint + len ( from) ,
622
- len ( s) ) ;
623
- ret before + to + replace ( after, from, to) ;
628
+ let result = "" , first = true ;
629
+ iter_between_matches ( s, from) { |start, end|
630
+ if first { first = false ; } else { result += to; }
631
+ unsafe { result += unsafe :: slice_bytes ( s, start, end) ; }
624
632
}
633
+ result
625
634
}
626
635
627
636
/*
@@ -1911,12 +1920,12 @@ mod tests {
1911
1920
#[ test]
1912
1921
fn test_replace ( ) {
1913
1922
let a = "a" ;
1914
- assert ( replace ( "" , a, "b" ) == "" ) ;
1915
- assert ( replace ( "a" , a, "b" ) == "b" ) ;
1916
- assert ( replace ( "ab" , a, "b" ) == "bb" ) ;
1923
+ assert replace( "" , a, "b" ) == "" ;
1924
+ assert replace( "a" , a, "b" ) == "b" ;
1925
+ assert replace( "ab" , a, "b" ) == "bb" ;
1917
1926
let test = "test" ;
1918
- assert ( replace ( " test test " , test, "toast" ) == " toast toast " ) ;
1919
- assert ( replace ( " test test " , test, "" ) == " " ) ;
1927
+ assert replace( " test test " , test, "toast" ) == " toast toast " ;
1928
+ assert replace( " test test " , test, "" ) == " " ;
1920
1929
}
1921
1930
1922
1931
#[ test]
0 commit comments