Create some infrastructure for building up @-vectors. Work on #2921.

This commit is contained in:
Michael Sullivan
2012-07-17 16:31:19 -07:00
parent 8e6d66280f
commit aa5b5ab886
9 changed files with 295 additions and 14 deletions

View File

@@ -17,6 +17,7 @@ export capacity;
export len;
export from_fn;
export from_elem;
export build, build_sized;
export to_mut;
export from_mut;
export head;
@@ -211,6 +212,47 @@ pure fn from_elem<T: copy>(n_elts: uint, t: T) -> ~[T] {
ret v;
}
/**
* Builds a vector by calling a provided function with an argument
* function that pushes an element to the back of a vector.
* This version takes an initial size for the vector.
*
* # Arguments
*
* * size - An initial size of the vector to reserve
* * builder - A function that will construct the vector. It recieves
* as an argument a function that will push an element
* onto the vector being constructed.
*/
#[inline(always)]
pure fn build_sized<A>(size: uint, builder: fn(push: pure fn(+A))) -> ~[A] {
let mut vec = ~[];
unsafe {
reserve(vec, size);
// This is an awful hack to be able to make the push function
// pure. Is there a better way?
::unsafe::reinterpret_cast::
<fn(push: pure fn(+A)), fn(push: fn(+A))>
(builder)(|+x| push(vec, x));
}
ret vec;
}
/**
* Builds a vector by calling a provided function with an argument
* function that pushes an element to the back of a vector.
*
* # Arguments
*
* * builder - A function that will construct the vector. It recieves
* as an argument a function that will push an element
* onto the vector being constructed.
*/
#[inline(always)]
pure fn build<A>(builder: fn(push: pure fn(+A))) -> ~[A] {
build_sized(4, builder)
}
/// Produces a mut vector from an immutable vector.
pure fn to_mut<T>(+v: ~[T]) -> ~[mut T] {
unsafe { ::unsafe::transmute(v) }
@@ -444,8 +486,7 @@ fn push<T>(&v: ~[const T], +initval: T) {
let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
let fill = (**repr).fill;
if (**repr).alloc > fill {
let sz = sys::size_of::<T>();
(**repr).fill += sz;
(**repr).fill += sys::size_of::<T>();
let p = ptr::addr_of((**repr).data);
let p = ptr::offset(p, fill) as *mut T;
rusti::move_val_init(*p, initval);
@@ -457,17 +498,8 @@ fn push<T>(&v: ~[const T], +initval: T) {
}
fn push_slow<T>(&v: ~[const T], +initval: T) {
unsafe {
let ln = v.len();
reserve_at_least(v, ln + 1u);
let repr: **unsafe::vec_repr = ::unsafe::reinterpret_cast(addr_of(v));
let fill = (**repr).fill;
let sz = sys::size_of::<T>();
(**repr).fill += sz;
let p = ptr::addr_of((**repr).data);
let p = ptr::offset(p, fill) as *mut T;
rusti::move_val_init(*p, initval);
}
reserve_at_least(v, v.len() + 1u);
push(v, initval);
}
// Unchecked vector indexing