mirror of
https://github.com/rust-lang/rust.git
synced 2024-11-25 16:24:46 +00:00
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]; } ~~~
This commit is contained in:
commit
9b60ecc30e
@ -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};
|
||||
|
@ -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);
|
||||
|
||||
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
|
||||
pub fn concat_slices(v: &[&str]) -> ~str { v.concat() }
|
||||
|
||||
/// 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(v: &[~str], sep: &str) -> ~str { v.connect(sep) }
|
||||
|
||||
// concat is faster
|
||||
if sep.is_empty() { return concat(v); }
|
||||
/// Concatenate a vector of strings, placing a given separator between each
|
||||
pub fn connect_slices(v: &[&str], sep: &str) -> ~str { v.connect(sep) }
|
||||
|
||||
// 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;
|
||||
#[allow(missing_doc)]
|
||||
pub trait StrVector {
|
||||
pub fn concat(&self) -> ~str;
|
||||
pub fn connect(&self, sep: &str) -> ~str;
|
||||
}
|
||||
|
||||
reserve(&mut s, len);
|
||||
impl<'self> StrVector for &'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 {
|
||||
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
|
||||
}
|
||||
|
||||
/// 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 ~""; }
|
||||
impl<'self> StrVector for &'self [&'self str] {
|
||||
/// Concatenate a vector of strings.
|
||||
pub fn concat(&self) -> ~str {
|
||||
if self.is_empty() { return ~""; }
|
||||
|
||||
// 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;
|
||||
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 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");
|
||||
@ -3203,10 +3260,23 @@ mod tests {
|
||||
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");
|
||||
|
@ -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] {
|
||||
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<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_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]
|
||||
|
Loading…
Reference in New Issue
Block a user