]> git.lizzy.rs Git - rust.git/commitdiff
rollup merge of #23951: alexcrichton/splitn
authorAlex Crichton <alex@alexcrichton.com>
Wed, 1 Apr 2015 20:30:08 +0000 (13:30 -0700)
committerAlex Crichton <alex@alexcrichton.com>
Wed, 1 Apr 2015 20:30:08 +0000 (13:30 -0700)
This commit is an implementation of [RFC 979][rfc] which changes the meaning of
the count parameter to the `splitn` function on strings and slices. The
parameter now means the number of items that are returned from the iterator, not
the number of splits that are made.

[rfc]: https://github.com/rust-lang/rfcs/pull/979

Closes #23911
[breaking-change]

14 files changed:
src/compiletest/header.rs
src/libcollections/slice.rs
src/libcollections/str.rs
src/libcollectionstest/slice.rs
src/libcollectionstest/str.rs
src/libcore/slice.rs
src/libcore/str/mod.rs
src/libcoretest/str.rs
src/librustc/session/config.rs
src/librustc_driver/pretty.rs
src/librustdoc/lib.rs
src/libstd/net/addr.rs
src/libstd/path.rs
src/libstd/sys/unix/os.rs

index 9612c0e06a34d7b311fb08db18b5181e7ac2fe7f..f5505b6e83a6738dd073b68513a4ef5755a339e4 100644 (file)
@@ -311,7 +311,7 @@ fn parse_exec_env(line: &str) -> Option<(String, String)> {
     parse_name_value_directive(line, "exec-env").map(|nv| {
         // nv is either FOO or FOO=BAR
         let mut strs: Vec<String> = nv
-                                      .splitn(1, '=')
+                                      .splitn(2, '=')
                                       .map(|s| s.to_string())
                                       .collect();
 
index 4599aff000df5f48e98fa41f08126faad183620b..d35173cbebf4cfd3d48b9d9c278ebb218058afa3 100644 (file)
@@ -328,9 +328,12 @@ pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool {
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to splitting at most `n` times.  The matched element is
+    /// `pred`, limited to returning at most `n` items.  The matched element is
     /// not contained in the subslices.
     ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
     /// # Examples
     ///
     /// Print the slice split once by numbers divisible by 3 (i.e. `[10, 40]`,
@@ -338,7 +341,7 @@ pub fn split<F>(&self, pred: F) -> Split<T, F> where F: FnMut(&T) -> bool {
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.splitn(1, |num| *num % 3 == 0) {
+    /// for group in v.splitn(2, |num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
     /// ```
@@ -349,10 +352,13 @@ pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) ->
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to splitting at most `n` times. This starts at the end of
+    /// `pred` limited to returning at most `n` items. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
     ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
+    ///
     /// # Examples
     ///
     /// Print the slice split once, starting from the end, by numbers divisible
@@ -360,7 +366,7 @@ pub fn splitn<F>(&self, n: usize, pred: F) -> SplitN<T, F> where F: FnMut(&T) ->
     ///
     /// ```
     /// let v = [10, 40, 30, 20, 60, 50];
-    /// for group in v.rsplitn(1, |num| *num % 3 == 0) {
+    /// for group in v.rsplitn(2, |num| *num % 3 == 0) {
     ///     println!("{:?}", group);
     /// }
     /// ```
@@ -626,8 +632,11 @@ pub fn split_mut<F>(&mut self, pred: F) -> SplitMut<T, F> where F: FnMut(&T) ->
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred`, limited to splitting at most `n` times.  The matched element is
+    /// `pred`, limited to returning at most `n` items.  The matched element is
     /// not contained in the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
@@ -636,9 +645,12 @@ pub fn splitn_mut<F>(&mut self, n: usize, pred: F) -> SplitNMut<T, F>
     }
 
     /// Returns an iterator over subslices separated by elements that match
-    /// `pred` limited to splitting at most `n` times. This starts at the end of
+    /// `pred` limited to returning at most `n` items. This starts at the end of
     /// the slice and works backwards.  The matched element is not contained in
     /// the subslices.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// slice.
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
     pub fn rsplitn_mut<F>(&mut self,  n: usize, pred: F) -> RSplitNMut<T, F>
index f8f2909291f3e0402fd70fb5e49972459657e06b..c22b6fb9286d192382c9dd8c7ec1f112677aaa6b 100644 (file)
@@ -610,24 +610,27 @@ pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
         core_str::StrExt::split(&self[..], pat)
     }
 
-    /// An iterator over substrings of `self`, separated by characters matched by a pattern,
-    /// restricted to splitting at most `count` times.
+    /// An iterator over substrings of `self`, separated by characters matched
+    /// by a pattern, returning most `count` items.
     ///
     /// The pattern can be a simple `&str`, or a closure that determines
     /// the split.
     ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// string.
+    ///
     /// # Examples
     ///
     /// Simple `&str` patterns:
     ///
     /// ```
     /// let v: Vec<&str> = "Mary had a little lambda".splitn(2, ' ').collect();
-    /// assert_eq!(v, ["Mary", "had", "a little lambda"]);
+    /// assert_eq!(v, ["Mary", "had a little lambda"]);
     ///
     /// let v: Vec<&str> = "lionXXtigerXleopard".splitn(2, 'X').collect();
-    /// assert_eq!(v, ["lion", "", "tigerXleopard"]);
+    /// assert_eq!(v, ["lion", "XtigerXleopard"]);
     ///
-    /// let v: Vec<&str> = "abcXdef".splitn(0, 'X').collect();
+    /// let v: Vec<&str> = "abcXdef".splitn(1, 'X').collect();
     /// assert_eq!(v, ["abcXdef"]);
     ///
     /// let v: Vec<&str> = "".splitn(1, 'X').collect();
@@ -637,7 +640,7 @@ pub fn split<'a, P: Pattern<'a>>(&'a self, pat: P) -> Split<'a, P> {
     /// More complex patterns with a lambda:
     ///
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".splitn(1, |c: char| c.is_numeric()).collect();
+    /// let v: Vec<&str> = "abc1def2ghi".splitn(2, |c: char| c.is_numeric()).collect();
     /// assert_eq!(v, ["abc", "def2ghi"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -705,25 +708,28 @@ pub fn rsplit<'a, P: Pattern<'a>>(&'a self, pat: P) -> RSplit<'a, P>
     }
 
     /// An iterator over substrings of `self`, separated by a pattern,
-    /// starting from the end of the string, restricted to splitting
-    /// at most `count` times.
+    /// starting from the end of the string, restricted to returning
+    /// at most `count` items.
+    ///
+    /// The last element returned, if any, will contain the remainder of the
+    /// string.
     ///
     /// # Examples
     ///
     /// Simple patterns:
     ///
     /// ```
-    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(2, ' ').collect();
+    /// let v: Vec<&str> = "Mary had a little lamb".rsplitn(3, ' ').collect();
     /// assert_eq!(v, ["lamb", "little", "Mary had a"]);
     ///
-    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(1, "::").collect();
+    /// let v: Vec<&str> = "lion::tiger::leopard".rsplitn(2, "::").collect();
     /// assert_eq!(v, ["leopard", "lion::tiger"]);
     /// ```
     ///
     /// More complex patterns with a lambda:
     ///
     /// ```
-    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(1, |c: char| c.is_numeric()).collect();
+    /// let v: Vec<&str> = "abc1def2ghi".rsplitn(2, |c: char| c.is_numeric()).collect();
     /// assert_eq!(v, ["ghi", "abc1def"]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
index 041d9fba57cc35169b0e4921e7a3af053e69d9ad..9dc12aa5bd9b4956e5e076047fcc596de144245e 100644 (file)
@@ -867,18 +867,18 @@ fn test_splitnator() {
     let xs = &[1,2,3,4,5];
 
     let splits: &[&[_]] = &[&[1,2,3,4,5]];
-    assert_eq!(xs.splitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[1], &[3,4,5]];
-    assert_eq!(xs.splitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[], &[], &[], &[4,5]];
-    assert_eq!(xs.splitn(3, |_| true).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn(4, |_| true).collect::<Vec<_>>(),
                splits);
 
     let xs: &[i32] = &[];
     let splits: &[&[i32]] = &[&[]];
-    assert_eq!(xs.splitn(1, |x| *x == 5).collect::<Vec<_>>(), splits);
+    assert_eq!(xs.splitn(2, |x| *x == 5).collect::<Vec<_>>(), splits);
 }
 
 #[test]
@@ -886,18 +886,18 @@ fn test_splitnator_mut() {
     let xs = &mut [1,2,3,4,5];
 
     let splits: &[&mut[_]] = &[&mut [1,2,3,4,5]];
-    assert_eq!(xs.splitn_mut(0, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&mut[_]] = &[&mut [1], &mut [3,4,5]];
-    assert_eq!(xs.splitn_mut(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&mut[_]] = &[&mut [], &mut [], &mut [], &mut [4,5]];
-    assert_eq!(xs.splitn_mut(3, |_| true).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(4, |_| true).collect::<Vec<_>>(),
                splits);
 
     let xs: &mut [i32] = &mut [];
     let splits: &[&mut[i32]] = &[&mut []];
-    assert_eq!(xs.splitn_mut(1, |x| *x == 5).collect::<Vec<_>>(),
+    assert_eq!(xs.splitn_mut(2, |x| *x == 5).collect::<Vec<_>>(),
                splits);
 }
 
@@ -928,18 +928,19 @@ fn test_rsplitnator() {
     let xs = &[1,2,3,4,5];
 
     let splits: &[&[_]] = &[&[1,2,3,4,5]];
-    assert_eq!(xs.rsplitn(0, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[5], &[1,2,3]];
-    assert_eq!(xs.rsplitn(1, |x| *x % 2 == 0).collect::<Vec<_>>(),
+    assert_eq!(xs.rsplitn(2, |x| *x % 2 == 0).collect::<Vec<_>>(),
                splits);
     let splits: &[&[_]] = &[&[], &[], &[], &[1,2]];
-    assert_eq!(xs.rsplitn(3, |_| true).collect::<Vec<_>>(),
+    assert_eq!(xs.rsplitn(4, |_| true).collect::<Vec<_>>(),
                splits);
 
     let xs: &[i32]  = &[];
     let splits: &[&[i32]] = &[&[]];
-    assert_eq!(xs.rsplitn(1, |x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+    assert_eq!(xs.rsplitn(2, |x| *x == 5).collect::<Vec<&[i32]>>(), splits);
+    assert!(xs.rsplitn(0, |x| *x % 2 == 0).next().is_none());
 }
 
 #[test]
index ed9ee0206b74f1f724fc434a8ff379694ebdcd5c..495a961fa360e2564bb72cbf7a8d91e717c4f20e 100644 (file)
@@ -885,17 +885,17 @@ fn test_char_indices_revator() {
 fn test_splitn_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
-    let split: Vec<&str> = data.splitn(3, ' ').collect();
+    let split: Vec<&str> = data.splitn(4, ' ').collect();
     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
-    let split: Vec<&str> = data.splitn(3, |c: char| c == ' ').collect();
+    let split: Vec<&str> = data.splitn(4, |c: char| c == ' ').collect();
     assert_eq!(split, ["\nMäry", "häd", "ä", "little lämb\nLittle lämb\n"]);
 
     // Unicode
-    let split: Vec<&str> = data.splitn(3, 'ä').collect();
+    let split: Vec<&str> = data.splitn(4, 'ä').collect();
     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
 
-    let split: Vec<&str> = data.splitn(3, |c: char| c == 'ä').collect();
+    let split: Vec<&str> = data.splitn(4, |c: char| c == 'ä').collect();
     assert_eq!(split, ["\nM", "ry h", "d ", " little lämb\nLittle lämb\n"]);
 }
 
@@ -928,13 +928,13 @@ fn test_rsplit() {
 fn test_rsplitn() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
-    let split: Vec<&str> = data.rsplitn(1, ' ').collect();
+    let split: Vec<&str> = data.rsplitn(2, ' ').collect();
     assert_eq!(split, ["lämb\n", "\nMäry häd ä little lämb\nLittle"]);
 
-    let split: Vec<&str> = data.rsplitn(1, "lämb").collect();
+    let split: Vec<&str> = data.rsplitn(2, "lämb").collect();
     assert_eq!(split, ["\n", "\nMäry häd ä little lämb\nLittle "]);
 
-    let split: Vec<&str> = data.rsplitn(1, |c: char| c == 'ä').collect();
+    let split: Vec<&str> = data.rsplitn(2, |c: char| c == 'ä').collect();
     assert_eq!(split, ["mb\n", "\nMäry häd ä little lämb\nLittle l"]);
 }
 
index d8856130fab33b1d794ede0a0a6f966f73196701..70e60adf64c2a3649b9d2256a7eadd8a46ff7346 100644 (file)
@@ -1126,18 +1126,20 @@ impl<T, I: SplitIter<Item=T>> Iterator for GenericSplitN<I> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        if self.count == 0 {
-            self.iter.finish()
-        } else {
-            self.count -= 1;
-            if self.invert { self.iter.next_back() } else { self.iter.next() }
+        match self.count {
+            0 => None,
+            1 => { self.count -= 1; self.iter.finish() }
+            _ => {
+                self.count -= 1;
+                if self.invert {self.iter.next_back()} else {self.iter.next()}
+            }
         }
     }
 
     #[inline]
     fn size_hint(&self) -> (usize, Option<usize>) {
         let (lower, upper_opt) = self.iter.size_hint();
-        (lower, upper_opt.map(|upper| cmp::min(self.count + 1, upper)))
+        (lower, upper_opt.map(|upper| cmp::min(self.count, upper)))
     }
 }
 
index 4c366d327187e5a2771f55d54c1b348bd99c8001..f07c988c2b4eec29f8ba6683de8e88e9eca316bb 100644 (file)
@@ -489,7 +489,7 @@ struct CharSplits<'a, P: Pattern<'a>> {
 /// splitting at most `count` times.
 struct CharSplitsN<'a, P: Pattern<'a>> {
     iter: CharSplits<'a, P>,
-    /// The number of splits remaining
+    /// The number of items remaining
     count: usize,
 }
 
@@ -596,11 +596,10 @@ impl<'a, P: Pattern<'a>> Iterator for CharSplitsN<'a, P> {
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
-        if self.count != 0 {
-            self.count -= 1;
-            self.iter.next()
-        } else {
-            self.iter.get_end()
+        match self.count {
+            0 => None,
+            1 => { self.count = 0; self.iter.get_end() }
+            _ => { self.count -= 1; self.iter.next() }
         }
     }
 }
@@ -650,11 +649,10 @@ impl<'a, P: Pattern<'a>> Iterator for RCharSplitsN<'a, P>
 
     #[inline]
     fn next(&mut self) -> Option<&'a str> {
-        if self.count != 0 {
-            self.count -= 1;
-            self.iter.next()
-        } else {
-            self.iter.get_remainder()
+        match self.count {
+            0 => None,
+            1 => { self.count -= 1; self.iter.get_remainder() }
+            _ => { self.count -= 1; self.iter.next() }
         }
     }
 }
index c935b5545740c6d8c6b8b8ba438fb069f93ede75..5fce527d9798df979a3183c2d3a433f191d05234 100644 (file)
@@ -65,20 +65,20 @@ fn test_strslice_contains() {
 fn test_rsplitn_char_iterator() {
     let data = "\nMäry häd ä little lämb\nLittle lämb\n";
 
-    let mut split: Vec<&str> = data.rsplitn(3, ' ').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, ' ').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
-    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == ' ').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == ' ').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ä", "little", "lämb\nLittle", "lämb\n"]);
 
     // Unicode
-    let mut split: Vec<&str> = data.rsplitn(3, 'ä').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, 'ä').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 
-    let mut split: Vec<&str> = data.rsplitn(3, |c: char| c == 'ä').collect();
+    let mut split: Vec<&str> = data.rsplitn(4, |c: char| c == 'ä').collect();
     split.reverse();
     assert_eq!(split, ["\nMäry häd ", " little l", "mb\nLittle l", "mb\n"]);
 }
index c67819ab7e3c42751c327342ed53ab86f73f8bf1..5a5989211952913ea800c291818e7576510006ed 100644 (file)
@@ -304,7 +304,7 @@ pub fn $buildfn(matches: &getopts::Matches) -> $struct_name
     {
         let mut op = $defaultfn();
         for option in matches.opt_strs($prefix) {
-            let mut iter = option.splitn(1, '=');
+            let mut iter = option.splitn(2, '=');
             let key = iter.next().unwrap();
             let value = iter.next();
             let option_to_lookup = key.replace("-", "_");
@@ -958,7 +958,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
     }
 
     let libs = matches.opt_strs("l").into_iter().map(|s| {
-        let mut parts = s.splitn(1, '=');
+        let mut parts = s.splitn(2, '=');
         let kind = parts.next().unwrap();
         let (name, kind) = match (parts.next(), kind) {
             (None, name) |
@@ -1010,7 +1010,7 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
 
     let mut externs = HashMap::new();
     for arg in &matches.opt_strs("extern") {
-        let mut parts = arg.splitn(1, '=');
+        let mut parts = arg.splitn(2, '=');
         let name = match parts.next() {
             Some(s) => s,
             None => early_error("--extern value must not be empty"),
index 37c9647c92b77df43fcdb94aaab1d5d5d270028b..e5847400496833a6cf7274019d4fba7076ccdc53 100644 (file)
@@ -74,7 +74,7 @@ pub enum PpMode {
 pub fn parse_pretty(sess: &Session,
                     name: &str,
                     extended: bool) -> (PpMode, Option<UserIdentifiedItem>) {
-    let mut split = name.splitn(1, '=');
+    let mut split = name.splitn(2, '=');
     let first = split.next().unwrap();
     let opt_second = split.next();
     let first = match (first, extended) {
index 1ff3411f8fc14368809ab1f5339c68dbc4421b5e..d1dcfc26008686624e92cdd22ce8085caf612980 100644 (file)
@@ -333,7 +333,7 @@ fn acquire_input(input: &str,
 fn parse_externs(matches: &getopts::Matches) -> Result<core::Externs, String> {
     let mut externs = HashMap::new();
     for arg in &matches.opt_strs("extern") {
-        let mut parts = arg.splitn(1, '=');
+        let mut parts = arg.splitn(2, '=');
         let name = match parts.next() {
             Some(s) => s,
             None => {
index c45230e91ba9ea9b8e17b23657836934dd210cbf..886f252fb192672b086bc347b87f8b0acae2d130 100644 (file)
@@ -441,7 +441,7 @@ macro_rules! try_opt {
         }
 
         // split the string by ':' and convert the second part to u16
-        let mut parts_iter = self.rsplitn(1, ':');
+        let mut parts_iter = self.rsplitn(2, ':');
         let port_str = try_opt!(parts_iter.next(), "invalid socket address");
         let host = try_opt!(parts_iter.next(), "invalid socket address");
         let port: u16 = try_opt!(port_str.parse().ok(), "invalid port value");
index 889381da28e92c74f3d438d5a93e1e84b60c45fd..4471b5afa84c888b600cd0def724eca4013466c8 100644 (file)
@@ -415,7 +415,7 @@ fn split_file_at_dot(file: &OsStr) -> (Option<&OsStr>, Option<&OsStr>) {
         // contents of the encoding and (2) new &OsStr values are produced
         // only from ASCII-bounded slices of existing &OsStr values.
 
-        let mut iter = os_str_as_u8_slice(file).rsplitn(1, |b| *b == b'.');
+        let mut iter = os_str_as_u8_slice(file).rsplitn(2, |b| *b == b'.');
         let after = iter.next();
         let before = iter.next();
         if before == Some(b"") {
index 7b13e951b9b3315203bdf294a51bb1172828d084..d2220bdec32b78fa1f054a720742c900ac7a6e63 100644 (file)
@@ -409,7 +409,7 @@ pub fn env() -> Env {
     };
 
     fn parse(input: &[u8]) -> (OsString, OsString) {
-        let mut it = input.splitn(1, |b| *b == b'=');
+        let mut it = input.splitn(2, |b| *b == b'=');
         let key = it.next().unwrap().to_vec();
         let default: &[u8] = &[];
         let val = it.next().unwrap_or(default).to_vec();