Skip to content

Commit fd1dd76

Browse files
committed
stdlib: Add a str::split_str() to split on a delimiter string of any length
1 parent 1f8f605 commit fd1dd76

File tree

2 files changed

+55
-5
lines changed

2 files changed

+55
-5
lines changed

src/libcore/str.rs

Lines changed: 41 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,11 @@ String manipulation.
66

77
export eq, lteq, hash, is_empty, is_not_empty, is_whitespace, byte_len,
88
byte_len_range, index,
9-
rindex, find, starts_with, ends_with, substr, slice, split, concat,
10-
connect, to_upper, replace, char_slice, trim_left, trim_right, trim,
11-
unshift_char, shift_char, pop_char, push_char, is_utf8, from_chars,
12-
to_chars, char_len, char_len_range, char_at, bytes, is_ascii,
13-
shift_byte, pop_byte,
9+
rindex, find, starts_with, ends_with, substr, slice, split, split_str,
10+
concat, connect, to_upper, replace, char_slice, trim_left, trim_right,
11+
trim, unshift_char, shift_char, pop_char, push_char, is_utf8,
12+
from_chars, to_chars, char_len, char_len_range, char_at, bytes,
13+
is_ascii, shift_byte, pop_byte,
1414
unsafe_from_byte, unsafe_from_bytes, from_char, char_range_at,
1515
str_from_cstr, sbuf, as_buf, push_byte, utf8_char_width, safe_slice,
1616
contains, iter_chars, loop_chars, loop_chars_sub,
@@ -744,6 +744,42 @@ fn split(s: str, sep: u8) -> [str] {
744744
ret v;
745745
}
746746

747+
/*
748+
Function: split_str
749+
750+
Splits a string at each occurrence of the given separator string. Empty
751+
leading fields are suppressed, and empty trailing fields are preserved.
752+
753+
Returns:
754+
755+
A vector containing all the strings between each occurrence of the separator.
756+
*/
757+
fn split_str(s: str, sep: str) -> [str] {
758+
assert byte_len(sep) > 0u;
759+
let v: [str] = [], accum = "", sep_match = 0u, leading = true;
760+
for c: u8 in s {
761+
// Did we match the entire separator?
762+
if sep_match == byte_len(sep) {
763+
if !leading { v += [accum]; }
764+
accum = "";
765+
sep_match = 0u;
766+
}
767+
768+
if c == sep[sep_match] {
769+
sep_match += 1u;
770+
} else {
771+
sep_match = 0u;
772+
accum += unsafe_from_byte(c);
773+
leading = false;
774+
}
775+
}
776+
777+
if byte_len(accum) > 0u { v += [accum]; }
778+
if sep_match == byte_len(sep) { v += [""]; }
779+
780+
ret v;
781+
}
782+
747783
/*
748784
Function: concat
749785

src/test/stdtest/str.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ fn test_split() {
5959
t("...hello.there.", '.', 5, "");
6060
}
6161

62+
#[test]
63+
fn test_split_str() {
64+
fn t(s: str, sep: str, i: int, k: str) {
65+
let v = str::split_str(s, sep);
66+
assert str::eq(v[i], k);
67+
}
68+
t("abc::hello::there", "::", 0, "abc");
69+
t("abc::hello::there", "::", 1, "hello");
70+
t("abc::hello::there", "::", 2, "there");
71+
t("::hello::there", "::", 0, "hello");
72+
t("hello::there::", "::", 2, "");
73+
t("::hello::there::", "::", 2, "");
74+
}
75+
6276
#[test]
6377
fn test_find() {
6478
fn t(haystack: str, needle: str, i: int) {

0 commit comments

Comments
 (0)