about summary refs log tree commit diff
path: root/src/libstd
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2013-06-02 21:37:38 -0700
committerbors <bors@rust-lang.org>2013-06-02 21:37:38 -0700
commit9b60ecc30ea9f8b951a4114971e190891fa97a91 (patch)
tree3aa30be1b0a9c189719f9210ac1f3f796786f05a /src/libstd
parentc40baf68cb3306f1beaf1d5443bb2433043b7da7 (diff)
parentdee7c5af6991b02c86e6a84b57551fd5cc71caaf (diff)
downloadrust-9b60ecc30ea9f8b951a4114971e190891fa97a91.tar.gz
rust-9b60ecc30ea9f8b951a4114971e190891fa97a91.zip
auto merge of #6908 : bjz/rust/concat-connect, r=Aatch
This adds the following traits to `prelude`:

In `std::str`, impled on `&[~[T]]` and `&[&[T]]`:
~~~rust
pub trait StrVector {
    pub fn concat(&self) -> ~str;
    pub fn connect(&self, sep: &str) -> ~str;
}
~~~

In `std::vec`, impled on `&[~str]` and `&[&str]`:
~~~rust
pub trait VectorVector<T> {
    pub fn concat(&self) -> ~[T];
    pub fn connect(&self, sep: &T) -> ~[T];
}
~~~
Diffstat (limited to 'src/libstd')
-rw-r--r--src/libstd/prelude.rs4
-rw-r--r--src/libstd/str.rs212
-rw-r--r--src/libstd/vec.rs78
3 files changed, 204 insertions, 90 deletions
diff --git a/src/libstd/prelude.rs b/src/libstd/prelude.rs
index 5a5efa0781a..87430e3390a 100644
--- a/src/libstd/prelude.rs
+++ b/src/libstd/prelude.rs
@@ -45,7 +45,7 @@ pub use path::PosixPath;
 pub use path::WindowsPath;
 pub use ptr::Ptr;
 pub use ascii::{Ascii, AsciiCast, OwnedAsciiCast, AsciiStr};
-pub use str::{StrSlice, OwnedStr, StrUtil};
+pub use str::{StrVector, StrSlice, OwnedStr, StrUtil};
 pub use from_str::{FromStr};
 pub use to_bytes::IterBytes;
 pub use to_str::{ToStr, ToStrConsume};
@@ -56,7 +56,7 @@ pub use tuple::{CloneableTuple10, CloneableTuple11, CloneableTuple12};
 pub use tuple::{ImmutableTuple2, ImmutableTuple3, ImmutableTuple4, ImmutableTuple5};
 pub use tuple::{ImmutableTuple6, ImmutableTuple7, ImmutableTuple8, ImmutableTuple9};
 pub use tuple::{ImmutableTuple10, ImmutableTuple11, ImmutableTuple12};
-pub use vec::{CopyableVector, ImmutableVector};
+pub use vec::{VectorVector, CopyableVector, ImmutableVector};
 pub use vec::{ImmutableEqVector, ImmutableCopyableVector};
 pub use vec::{OwnedVector, OwnedCopyableVector, MutableVector};
 pub use io::{Reader, ReaderUtil, Writer, WriterUtil};
diff --git a/src/libstd/str.rs b/src/libstd/str.rs
index c9452ed5433..961d93823ad 100644
--- a/src/libstd/str.rs
+++ b/src/libstd/str.rs
@@ -241,110 +241,165 @@ pub fn append(lhs: ~str, rhs: &str) -> ~str {
 }
 
 /// Concatenate a vector of strings
-pub fn concat(v: &[~str]) -> ~str {
-    if v.is_empty() { return ~""; }
+pub fn concat(v: &[~str]) -> ~str { v.concat() }
 
-    let mut len = 0;
-    for v.each |ss| {
-        len += ss.len();
-    }
-    let mut s = ~"";
-
-    reserve(&mut s, len);
+/// Concatenate a vector of strings
+pub fn concat_slices(v: &[&str]) -> ~str { v.concat() }
 
-    unsafe {
-        do as_buf(s) |buf, _len| {
-            let mut buf = ::cast::transmute_mut_unsafe(buf);
-            for v.each |ss| {
-                do as_buf(*ss) |ssbuf, sslen| {
-                    let sslen = sslen - 1;
-                    ptr::copy_memory(buf, ssbuf, sslen);
-                    buf = buf.offset(sslen);
-                }
-            }
-        }
-        raw::set_len(&mut s, len);
-    }
-    s
-}
+/// Concatenate a vector of strings, placing a given separator between each
+pub fn connect(v: &[~str], sep: &str) -> ~str { v.connect(sep) }
 
 /// Concatenate a vector of strings, placing a given separator between each
-pub fn connect(v: &[~str], sep: &str) -> ~str {
-    if v.is_empty() { return ~""; }
+pub fn connect_slices(v: &[&str], sep: &str) -> ~str { v.connect(sep) }
 
-    // concat is faster
-    if sep.is_empty() { return concat(v); }
+#[allow(missing_doc)]
+pub trait StrVector {
+    pub fn concat(&self) -> ~str;
+    pub fn connect(&self, sep: &str) -> ~str;
+}
 
-    // this is wrong without the guarantee that v is non-empty
-    let mut len = sep.len() * (v.len() - 1);
-    for v.each |ss| {
-        len += ss.len();
-    }
-    let mut s = ~"", first = true;
+impl<'self> StrVector for &'self [~str] {
+    /// Concatenate a vector of strings.
+    pub fn concat(&self) -> ~str {
+        if self.is_empty() { return ~""; }
+
+        let mut len = 0;
+        for self.each |ss| {
+            len += ss.len();
+        }
+        let mut s = ~"";
 
-    reserve(&mut s, len);
+        reserve(&mut s, len);
 
-    unsafe {
-        do as_buf(s) |buf, _len| {
-            do as_buf(sep) |sepbuf, seplen| {
-                let seplen = seplen - 1;
+        unsafe {
+            do as_buf(s) |buf, _| {
                 let mut buf = ::cast::transmute_mut_unsafe(buf);
-                for v.each |ss| {
+                for self.each |ss| {
                     do as_buf(*ss) |ssbuf, sslen| {
                         let sslen = sslen - 1;
-                        if first {
-                            first = false;
-                        } else {
-                            ptr::copy_memory(buf, sepbuf, seplen);
-                            buf = buf.offset(seplen);
-                        }
                         ptr::copy_memory(buf, ssbuf, sslen);
                         buf = buf.offset(sslen);
                     }
                 }
             }
+            raw::set_len(&mut s, len);
         }
-        raw::set_len(&mut s, len);
+        s
     }
-    s
-}
 
-/// Concatenate a vector of strings, placing a given separator between each
-pub fn connect_slices(v: &[&str], sep: &str) -> ~str {
-    if v.is_empty() { return ~""; }
+    /// Concatenate a vector of strings, placing a given separator between each.
+    pub fn connect(&self, sep: &str) -> ~str {
+        if self.is_empty() { return ~""; }
+
+        // concat is faster
+        if sep.is_empty() { return self.concat(); }
 
-    // this is wrong without the guarantee that v is non-empty
-    let mut len = sep.len() * (v.len() - 1);
-    for v.each |ss| {
-        len += ss.len();
+        // this is wrong without the guarantee that `self` is non-empty
+        let mut len = sep.len() * (self.len() - 1);
+        for self.each |ss| {
+            len += ss.len();
+        }
+        let mut s = ~"";
+        let mut first = true;
+
+        reserve(&mut s, len);
+
+        unsafe {
+            do as_buf(s) |buf, _| {
+                do as_buf(sep) |sepbuf, seplen| {
+                    let seplen = seplen - 1;
+                    let mut buf = ::cast::transmute_mut_unsafe(buf);
+                    for self.each |ss| {
+                        do as_buf(*ss) |ssbuf, sslen| {
+                            let sslen = sslen - 1;
+                            if first {
+                                first = false;
+                            } else {
+                                ptr::copy_memory(buf, sepbuf, seplen);
+                                buf = buf.offset(seplen);
+                            }
+                            ptr::copy_memory(buf, ssbuf, sslen);
+                            buf = buf.offset(sslen);
+                        }
+                    }
+                }
+            }
+            raw::set_len(&mut s, len);
+        }
+        s
     }
-    let mut s = ~"", first = true;
+}
 
-    reserve(&mut s, len);
+impl<'self> StrVector for &'self [&'self str] {
+    /// Concatenate a vector of strings.
+    pub fn concat(&self) -> ~str {
+        if self.is_empty() { return ~""; }
 
-    unsafe {
-        do as_buf(s) |buf, _len| {
-            do as_buf(sep) |sepbuf, seplen| {
-                let seplen = seplen - 1;
+        let mut len = 0;
+        for self.each |ss| {
+            len += ss.len();
+        }
+        let mut s = ~"";
+
+        reserve(&mut s, len);
+
+        unsafe {
+            do as_buf(s) |buf, _| {
                 let mut buf = ::cast::transmute_mut_unsafe(buf);
-                for v.each |ss| {
+                for self.each |ss| {
                     do as_buf(*ss) |ssbuf, sslen| {
                         let sslen = sslen - 1;
-                        if first {
-                            first = false;
-                        } else if seplen > 0 {
-                            ptr::copy_memory(buf, sepbuf, seplen);
-                            buf = buf.offset(seplen);
-                        }
                         ptr::copy_memory(buf, ssbuf, sslen);
                         buf = buf.offset(sslen);
                     }
                 }
             }
+            raw::set_len(&mut s, len);
         }
-        raw::set_len(&mut s, len);
+        s
+    }
+
+    /// Concatenate a vector of strings, placing a given separator between each.
+    pub fn connect(&self, sep: &str) -> ~str {
+        if self.is_empty() { return ~""; }
+
+        // concat is faster
+        if sep.is_empty() { return self.concat(); }
+
+        // this is wrong without the guarantee that `self` is non-empty
+        let mut len = sep.len() * (self.len() - 1);
+        for self.each |ss| {
+            len += ss.len();
+        }
+        let mut s = ~"";
+        let mut first = true;
+
+        reserve(&mut s, len);
+
+        unsafe {
+            do as_buf(s) |buf, _| {
+                do as_buf(sep) |sepbuf, seplen| {
+                    let seplen = seplen - 1;
+                    let mut buf = ::cast::transmute_mut_unsafe(buf);
+                    for self.each |ss| {
+                        do as_buf(*ss) |ssbuf, sslen| {
+                            let sslen = sslen - 1;
+                            if first {
+                                first = false;
+                            } else {
+                                ptr::copy_memory(buf, sepbuf, seplen);
+                                buf = buf.offset(seplen);
+                            }
+                            ptr::copy_memory(buf, ssbuf, sslen);
+                            buf = buf.offset(sslen);
+                        }
+                    }
+                }
+            }
+            raw::set_len(&mut s, len);
+        }
+        s
     }
-    s
 }
 
 /// Given a string, make a new string with repeated copies of it
@@ -3184,6 +3239,7 @@ mod tests {
     fn test_concat() {
         fn t(v: &[~str], s: &str) {
             assert_eq!(concat(v), s.to_str());
+            assert_eq!(v.concat(), s.to_str());
         }
         t([~"you", ~"know", ~"I'm", ~"no", ~"good"], "youknowI'mnogood");
         let v: &[~str] = [];
@@ -3195,6 +3251,7 @@ mod tests {
     fn test_connect() {
         fn t(v: &[~str], sep: &str, s: &str) {
             assert_eq!(connect(v, sep), s.to_str());
+            assert_eq!(v.connect(sep), s.to_str());
         }
         t([~"you", ~"know", ~"I'm", ~"no", ~"good"],
           " ", "you know I'm no good");
@@ -3204,9 +3261,22 @@ mod tests {
     }
 
     #[test]
+    fn test_concat_slices() {
+        fn t(v: &[&str], s: &str) {
+            assert_eq!(concat_slices(v), s.to_str());
+            assert_eq!(v.concat(), s.to_str());
+        }
+        t(["you", "know", "I'm", "no", "good"], "youknowI'mnogood");
+        let v: &[&str] = [];
+        t(v, "");
+        t(["hi"], "hi");
+    }
+
+    #[test]
     fn test_connect_slices() {
         fn t(v: &[&str], sep: &str, s: &str) {
             assert_eq!(connect_slices(v, sep), s.to_str());
+            assert_eq!(v.connect(sep), s.to_str());
         }
         t(["you", "know", "I'm", "no", "good"],
           " ", "you know I'm no good");
diff --git a/src/libstd/vec.rs b/src/libstd/vec.rs
index 8eedb70b3a6..b748ca54cf4 100644
--- a/src/libstd/vec.rs
+++ b/src/libstd/vec.rs
@@ -1011,26 +1011,58 @@ pub fn retain<T>(v: &mut ~[T], f: &fn(t: &T) -> bool) {
     }
 }
 
-/**
- * Concatenate a vector of vectors.
- *
- * Flattens a vector of vectors of T into a single vector of T.
- */
-pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] {
-    let mut r = ~[];
-    for each(v) |inner| { r.push_all(*inner); }
-    r
-}
+/// Flattens a vector of vectors of T into a single vector of T.
+pub fn concat<T:Copy>(v: &[~[T]]) -> ~[T] { v.concat() }
+
+/// Concatenate a vector of vectors, placing a given separator between each
+pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] { v.connect(sep) }
+
+/// Flattens a vector of vectors of T into a single vector of T.
+pub fn concat_slices<T:Copy>(v: &[&[T]]) -> ~[T] { v.concat() }
 
 /// Concatenate a vector of vectors, placing a given separator between each
-pub fn connect<T:Copy>(v: &[~[T]], sep: &T) -> ~[T] {
-    let mut r: ~[T] = ~[];
-    let mut first = true;
-    for each(v) |inner| {
-        if first { first = false; } else { r.push(*sep); }
-        r.push_all(*inner);
+pub fn connect_slices<T:Copy>(v: &[&[T]], sep: &T) -> ~[T] { v.connect(sep) }
+
+#[allow(missing_doc)]
+pub trait VectorVector<T> {
+    pub fn concat(&self) -> ~[T];
+    pub fn connect(&self, sep: &T) -> ~[T];
+}
+
+impl<'self, T:Copy> VectorVector<T> for &'self [~[T]] {
+    /// Flattens a vector of slices of T into a single vector of T.
+    pub fn concat(&self) -> ~[T] {
+        self.flat_map(|&inner| inner)
+    }
+
+    /// Concatenate a vector of vectors, placing a given separator between each.
+    pub fn connect(&self, sep: &T) -> ~[T] {
+        let mut r = ~[];
+        let mut first = true;
+        for self.each |&inner| {
+            if first { first = false; } else { r.push(*sep); }
+            r.push_all(inner);
+        }
+        r
+    }
+}
+
+impl<'self, T:Copy> VectorVector<T> for &'self [&'self [T]] {
+    /// Flattens a vector of slices of T into a single vector of T.
+    pub fn concat(&self) -> ~[T] {
+        self.flat_map(|&inner| inner.to_owned())
+    }
+
+    /// Concatenate a vector of slices, placing a given separator between each.
+    pub fn connect(&self, sep: &T) -> ~[T] {
+        let mut r = ~[];
+        let mut first = true;
+        for self.each |&inner| {
+            if first { first = false; } else { r.push(*sep); }
+            r.push_all(inner);
+        }
+        r
     }
-    r
 }
 
 /**
@@ -3941,6 +3973,10 @@ mod tests {
     #[test]
     fn test_concat() {
         assert_eq!(concat([~[1], ~[2,3]]), ~[1, 2, 3]);
+        assert_eq!([~[1], ~[2,3]].concat(), ~[1, 2, 3]);
+
+        assert_eq!(concat_slices([&[1], &[2,3]]), ~[1, 2, 3]);
+        assert_eq!([&[1], &[2,3]].concat(), ~[1, 2, 3]);
     }
 
     #[test]
@@ -3948,6 +3984,14 @@ mod tests {
         assert_eq!(connect([], &0), ~[]);
         assert_eq!(connect([~[1], ~[2, 3]], &0), ~[1, 0, 2, 3]);
         assert_eq!(connect([~[1], ~[2], ~[3]], &0), ~[1, 0, 2, 0, 3]);
+        assert_eq!([~[1], ~[2, 3]].connect(&0), ~[1, 0, 2, 3]);
+        assert_eq!([~[1], ~[2], ~[3]].connect(&0), ~[1, 0, 2, 0, 3]);
+
+        assert_eq!(connect_slices([], &0), ~[]);
+        assert_eq!(connect_slices([&[1], &[2, 3]], &0), ~[1, 0, 2, 3]);
+        assert_eq!(connect_slices([&[1], &[2], &[3]], &0), ~[1, 0, 2, 0, 3]);
+        assert_eq!([&[1], &[2, 3]].connect(&0), ~[1, 0, 2, 3]);
+        assert_eq!([&[1], &[2], &[3]].connect(&0), ~[1, 0, 2, 0, 3]);
     }
 
     #[test]