}
/// 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
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] = [];
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");
t([~"hi"], " ", "hi");
}
+ #[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");
}
}
-/**
- * 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
}
/**
#[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]
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]