2012-09-19 18:52:32 -05:00
|
|
|
/*!
|
|
|
|
|
|
|
|
Dynamic vector
|
|
|
|
|
|
|
|
A growable vector that makes use of unique pointers so that the
|
|
|
|
result can be sent between tasks and so forth.
|
|
|
|
|
|
|
|
Note that recursive use is not permitted.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
2012-08-13 19:11:33 -05:00
|
|
|
// NB: transitionary, de-mode-ing.
|
|
|
|
#[forbid(deprecated_mode)];
|
|
|
|
#[forbid(deprecated_pattern)];
|
|
|
|
|
2012-09-18 19:34:08 -05:00
|
|
|
use cast::reinterpret_cast;
|
2012-09-04 13:12:17 -05:00
|
|
|
use ptr::null;
|
2012-05-09 19:30:31 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* A growable, modifiable vector type that accumulates elements into a
|
|
|
|
* unique vector.
|
|
|
|
*
|
|
|
|
* # Limitations on recursive use
|
|
|
|
*
|
|
|
|
* This class works by swapping the unique vector out of the data
|
|
|
|
* structure whenever it is to be used. Therefore, recursive use is not
|
|
|
|
* permitted. That is, while iterating through a vector, you cannot
|
|
|
|
* access the vector in any other way or else the program will fail. If
|
|
|
|
* you wish, you can use the `swap()` method to gain access to the raw
|
|
|
|
* vector and transform it or use it any way you like. Eventually, we
|
|
|
|
* may permit read-only access during iteration or other use.
|
|
|
|
*
|
|
|
|
* # WARNING
|
|
|
|
*
|
|
|
|
* For maximum performance, this type is implemented using some rather
|
2012-07-11 18:49:02 -05:00
|
|
|
* unsafe code. In particular, this innocent looking `~[mut A]` pointer
|
2012-07-04 16:53:12 -05:00
|
|
|
* *may be null!* Therefore, it is important you not reach into the
|
|
|
|
* data structure manually but instead use the provided extensions.
|
|
|
|
*
|
|
|
|
* The reason that I did not use an unsafe pointer in the structure
|
|
|
|
* itself is that I wanted to ensure that the vector would be freed when
|
2012-08-20 14:23:37 -05:00
|
|
|
* the dvec is dropped. The reason that I did not use an `Option<T>`
|
2012-07-04 16:53:12 -05:00
|
|
|
* instead of a nullable pointer is that I found experimentally that it
|
|
|
|
* becomes approximately 50% slower. This can probably be improved
|
|
|
|
* through optimization. You can run your own experiments using
|
|
|
|
* `src/test/bench/vec-append.rs`. My own tests found that using null
|
|
|
|
* pointers achieved about 103 million pushes/second. Using an option
|
|
|
|
* type could only produce 47 million pushes/second.
|
|
|
|
*/
|
2012-08-14 18:54:13 -05:00
|
|
|
type DVec_<A> = {
|
2012-09-12 12:38:17 -05:00
|
|
|
mut data: ~[A]
|
2012-05-09 19:30:31 -05:00
|
|
|
};
|
|
|
|
|
2012-09-26 18:01:40 -05:00
|
|
|
pub enum DVec<A> {
|
2012-08-14 18:54:13 -05:00
|
|
|
DVec_(DVec_<A>)
|
2012-07-11 14:45:54 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new, empty dvec
|
2012-09-26 18:01:40 -05:00
|
|
|
pub fn DVec<A>() -> DVec<A> {
|
2012-09-12 12:38:17 -05:00
|
|
|
DVec_({mut data: ~[]})
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new dvec with a single element
|
2012-09-26 18:01:40 -05:00
|
|
|
pub fn from_elem<A>(+e: A) -> DVec<A> {
|
2012-09-12 12:38:17 -05:00
|
|
|
DVec_({mut data: ~[move e]})
|
2012-06-04 09:59:02 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Creates a new dvec with the contents of a vector
|
2012-09-26 18:01:40 -05:00
|
|
|
pub fn from_vec<A>(+v: ~[A]) -> DVec<A> {
|
2012-09-10 14:14:14 -05:00
|
|
|
DVec_({mut data: move v})
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Consumes the vector and returns its contents
|
2012-09-26 18:01:40 -05:00
|
|
|
pub fn unwrap<A>(+d: DVec<A>) -> ~[A] {
|
2012-08-14 18:54:13 -05:00
|
|
|
let DVec_({data: v}) <- d;
|
2012-09-10 14:14:14 -05:00
|
|
|
move v
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-08-14 18:54:13 -05:00
|
|
|
priv impl<A> DVec<A> {
|
2012-07-17 12:24:04 -05:00
|
|
|
pure fn check_not_borrowed() {
|
2012-05-09 19:30:31 -05:00
|
|
|
unsafe {
|
2012-09-18 19:34:08 -05:00
|
|
|
let data: *() = cast::reinterpret_cast(&self.data);
|
2012-05-09 19:30:31 -05:00
|
|
|
if data.is_null() {
|
2012-07-14 00:57:48 -05:00
|
|
|
fail ~"Recursive use of dvec";
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2012-09-25 20:27:45 -05:00
|
|
|
fn check_out<B>(f: &fn(+v: ~[A]) -> B) -> B {
|
2012-05-09 19:30:31 -05:00
|
|
|
unsafe {
|
2012-09-18 19:34:08 -05:00
|
|
|
let mut data = cast::reinterpret_cast(&null::<()>());
|
2012-05-09 19:30:31 -05:00
|
|
|
data <-> self.data;
|
2012-09-18 19:34:08 -05:00
|
|
|
let data_ptr: *() = cast::reinterpret_cast(&data);
|
2012-07-14 00:57:48 -05:00
|
|
|
if data_ptr.is_null() { fail ~"Recursive use of dvec"; }
|
2012-09-11 19:17:54 -05:00
|
|
|
return f(move data);
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2012-09-12 12:38:17 -05:00
|
|
|
fn give_back(+data: ~[A]) {
|
2012-05-09 19:30:31 -05:00
|
|
|
unsafe {
|
2012-09-12 12:38:17 -05:00
|
|
|
self.data = move data;
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// In theory, most everything should work with any A, but in practice
|
|
|
|
// almost nothing works without the copy bound due to limitations
|
|
|
|
// around closures.
|
2012-08-14 18:54:13 -05:00
|
|
|
impl<A> DVec<A> {
|
2012-07-25 19:29:34 -05:00
|
|
|
/// Reserves space for N elements
|
|
|
|
fn reserve(count: uint) {
|
2012-09-21 20:43:30 -05:00
|
|
|
vec::reserve(&mut self.data, count)
|
2012-07-25 19:29:34 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Swaps out the current vector and hands it off to a user-provided
|
|
|
|
* function `f`. The function should transform it however is desired
|
|
|
|
* and return a new vector to replace it with.
|
|
|
|
*/
|
2012-06-14 13:38:45 -05:00
|
|
|
#[inline(always)]
|
2012-09-25 20:27:45 -05:00
|
|
|
fn swap(f: &fn(+v: ~[A]) -> ~[A]) {
|
2012-09-11 19:17:54 -05:00
|
|
|
self.check_out(|v| self.give_back(f(move v)))
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-09-12 12:38:17 -05:00
|
|
|
/**
|
|
|
|
* Swaps out the current vector and hands it off to a user-provided
|
|
|
|
* function `f`. The function should transform it however is desired
|
|
|
|
* and return a new vector to replace it with.
|
|
|
|
*/
|
|
|
|
#[inline(always)]
|
2012-09-25 20:27:45 -05:00
|
|
|
fn swap_mut(f: &fn(-v: ~[mut A]) -> ~[mut A]) {
|
2012-09-12 12:38:17 -05:00
|
|
|
do self.swap |v| {
|
|
|
|
vec::from_mut(f(vec::to_mut(move v)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the number of elements currently in the dvec
|
2012-07-17 12:24:04 -05:00
|
|
|
pure fn len() -> uint {
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-08-13 17:06:13 -05:00
|
|
|
do self.check_out |v| {
|
2012-07-17 12:24:04 -05:00
|
|
|
let l = v.len();
|
2012-09-11 19:17:54 -05:00
|
|
|
self.give_back(move v);
|
2012-07-17 12:24:04 -05:00
|
|
|
l
|
|
|
|
}
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Overwrite the current contents
|
2012-09-12 12:38:17 -05:00
|
|
|
fn set(+w: ~[A]) {
|
2012-05-09 19:30:31 -05:00
|
|
|
self.check_not_borrowed();
|
2012-06-15 08:23:58 -05:00
|
|
|
self.data <- w;
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Remove and return the last element
|
2012-05-09 19:30:31 -05:00
|
|
|
fn pop() -> A {
|
2012-08-13 17:06:13 -05:00
|
|
|
do self.check_out |v| {
|
2012-05-29 17:37:50 -05:00
|
|
|
let mut v <- v;
|
2012-05-09 19:30:31 -05:00
|
|
|
let result = vec::pop(v);
|
2012-09-11 19:17:54 -05:00
|
|
|
self.give_back(move v);
|
2012-09-10 14:14:14 -05:00
|
|
|
move result
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Insert a single item at the front of the list
|
2012-09-25 20:27:45 -05:00
|
|
|
fn unshift(+t: A) {
|
2012-06-07 14:18:34 -05:00
|
|
|
unsafe {
|
2012-09-18 19:34:08 -05:00
|
|
|
let mut data = cast::reinterpret_cast(&null::<()>());
|
2012-06-07 14:18:34 -05:00
|
|
|
data <-> self.data;
|
2012-09-18 19:34:08 -05:00
|
|
|
let data_ptr: *() = cast::reinterpret_cast(&data);
|
2012-07-14 00:57:48 -05:00
|
|
|
if data_ptr.is_null() { fail ~"Recursive use of dvec"; }
|
|
|
|
log(error, ~"a");
|
2012-09-12 12:38:17 -05:00
|
|
|
self.data <- ~[move t];
|
2012-09-26 19:33:34 -05:00
|
|
|
self.data.push_all_move(move data);
|
2012-07-14 00:57:48 -05:00
|
|
|
log(error, ~"b");
|
2012-06-07 14:18:34 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Append a single item to the end of the list
|
2012-06-07 14:18:34 -05:00
|
|
|
fn push(+t: A) {
|
|
|
|
self.check_not_borrowed();
|
2012-09-26 19:33:34 -05:00
|
|
|
self.data.push(move t);
|
2012-06-07 14:18:34 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Remove and return the first element
|
2012-06-07 14:18:34 -05:00
|
|
|
fn shift() -> A {
|
2012-08-13 17:06:13 -05:00
|
|
|
do self.check_out |v| {
|
2012-09-12 12:38:17 -05:00
|
|
|
let mut v = move v;
|
2012-06-07 14:18:34 -05:00
|
|
|
let result = vec::shift(v);
|
2012-09-12 12:38:17 -05:00
|
|
|
self.give_back(move v);
|
2012-09-10 14:14:14 -05:00
|
|
|
move result
|
2012-06-07 14:18:34 -05:00
|
|
|
}
|
|
|
|
}
|
2012-07-17 12:24:04 -05:00
|
|
|
|
2012-08-13 17:06:13 -05:00
|
|
|
/// Reverse the elements in the list, in place
|
2012-07-17 12:24:04 -05:00
|
|
|
fn reverse() {
|
2012-08-13 17:06:13 -05:00
|
|
|
do self.check_out |v| {
|
2012-09-12 12:38:17 -05:00
|
|
|
let mut v = move v;
|
2012-07-17 12:24:04 -05:00
|
|
|
vec::reverse(v);
|
2012-09-11 19:17:54 -05:00
|
|
|
self.give_back(move v);
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gives access to the vector as a slice with immutable contents
|
|
|
|
fn borrow<R>(op: fn(x: &[A]) -> R) -> R {
|
|
|
|
do self.check_out |v| {
|
|
|
|
let result = op(v);
|
2012-09-11 19:17:54 -05:00
|
|
|
self.give_back(move v);
|
2012-09-10 14:14:14 -05:00
|
|
|
move result
|
2012-08-13 17:06:13 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Gives access to the vector as a slice with mutable contents
|
|
|
|
fn borrow_mut<R>(op: fn(x: &[mut A]) -> R) -> R {
|
|
|
|
do self.check_out |v| {
|
2012-09-12 12:38:17 -05:00
|
|
|
let mut v = move v;
|
2012-08-13 17:06:13 -05:00
|
|
|
let result = op(v);
|
2012-09-11 19:17:54 -05:00
|
|
|
self.give_back(move v);
|
2012-09-10 14:14:14 -05:00
|
|
|
move result
|
2012-07-17 12:24:04 -05:00
|
|
|
}
|
|
|
|
}
|
2012-06-07 14:18:34 -05:00
|
|
|
}
|
|
|
|
|
2012-09-07 16:52:28 -05:00
|
|
|
impl<A: Copy> DVec<A> {
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Append all elements of a vector to the end of the list
|
|
|
|
*
|
|
|
|
* Equivalent to `append_iter()` but potentially more efficient.
|
|
|
|
*/
|
2012-06-29 18:26:56 -05:00
|
|
|
fn push_all(ts: &[const A]) {
|
2012-05-09 19:30:31 -05:00
|
|
|
self.push_slice(ts, 0u, vec::len(ts));
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Appends elements from `from_idx` to `to_idx` (exclusive)
|
2012-06-29 18:26:56 -05:00
|
|
|
fn push_slice(ts: &[const A], from_idx: uint, to_idx: uint) {
|
2012-06-30 18:19:07 -05:00
|
|
|
do self.swap |v| {
|
2012-05-29 17:37:50 -05:00
|
|
|
let mut v <- v;
|
2012-05-09 19:30:31 -05:00
|
|
|
let new_len = vec::len(v) + to_idx - from_idx;
|
2012-09-21 20:43:30 -05:00
|
|
|
vec::reserve(&mut v, new_len);
|
2012-05-09 19:30:31 -05:00
|
|
|
let mut i = from_idx;
|
|
|
|
while i < to_idx {
|
2012-09-26 19:33:34 -05:00
|
|
|
v.push(ts[i]);
|
2012-05-09 19:30:31 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
2012-09-10 14:14:14 -05:00
|
|
|
move v
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Append all elements of an iterable.
|
|
|
|
*
|
|
|
|
* Failure will occur if the iterable's `each()` method
|
|
|
|
* attempts to access this vector.
|
|
|
|
*/
|
2012-09-07 18:58:27 -05:00
|
|
|
/*
|
2012-06-14 18:24:21 -05:00
|
|
|
fn append_iter<A, I:iter::base_iter<A>>(ts: I) {
|
2012-06-30 18:19:07 -05:00
|
|
|
do self.swap |v| {
|
2012-08-06 14:34:08 -05:00
|
|
|
let mut v = match ts.size_hint() {
|
2012-06-14 18:24:21 -05:00
|
|
|
none { v }
|
2012-08-20 14:23:37 -05:00
|
|
|
Some(h) {
|
2012-06-14 18:24:21 -05:00
|
|
|
let len = v.len() + h;
|
|
|
|
let mut v <- v;
|
|
|
|
vec::reserve(v, len);
|
|
|
|
v
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-09-26 19:33:34 -05:00
|
|
|
for ts.each |t| { v.push(*t) };
|
2012-06-14 18:24:21 -05:00
|
|
|
v
|
|
|
|
}
|
|
|
|
}
|
2012-05-22 12:54:12 -05:00
|
|
|
*/
|
2012-05-09 19:30:31 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Gets a copy of the current contents.
|
|
|
|
*
|
|
|
|
* See `unwrap()` if you do not wish to copy the contents.
|
|
|
|
*/
|
2012-07-17 12:24:04 -05:00
|
|
|
pure fn get() -> ~[A] {
|
2012-09-18 13:17:40 -05:00
|
|
|
unsafe {
|
2012-08-13 17:06:13 -05:00
|
|
|
do self.check_out |v| {
|
2012-09-12 12:38:17 -05:00
|
|
|
let w = copy v;
|
2012-09-11 19:17:54 -05:00
|
|
|
self.give_back(move v);
|
2012-09-10 14:14:14 -05:00
|
|
|
move w
|
2012-07-17 12:24:04 -05:00
|
|
|
}
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Copy out an individual element
|
2012-05-15 15:41:15 -05:00
|
|
|
#[inline(always)]
|
2012-07-17 12:24:04 -05:00
|
|
|
pure fn get_elt(idx: uint) -> A {
|
2012-05-09 19:30:31 -05:00
|
|
|
self.check_not_borrowed();
|
2012-08-01 19:30:05 -05:00
|
|
|
return self.data[idx];
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Overwrites the contents of the element at `idx` with `a`
|
2012-09-25 20:27:45 -05:00
|
|
|
fn set_elt(idx: uint, +a: A) {
|
2012-05-09 19:30:31 -05:00
|
|
|
self.check_not_borrowed();
|
|
|
|
self.data[idx] = a;
|
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/**
|
|
|
|
* Overwrites the contents of the element at `idx` with `a`,
|
|
|
|
* growing the vector if necessary. New elements will be initialized
|
|
|
|
* with `initval`
|
|
|
|
*/
|
2012-09-25 20:27:45 -05:00
|
|
|
fn grow_set_elt(idx: uint, initval: A, +val: A) {
|
2012-06-30 18:19:07 -05:00
|
|
|
do self.swap |v| {
|
2012-09-21 20:43:30 -05:00
|
|
|
let mut v = move v;
|
2012-05-29 17:37:50 -05:00
|
|
|
vec::grow_set(v, idx, initval, val);
|
2012-09-21 20:43:30 -05:00
|
|
|
move v
|
2012-05-29 17:37:50 -05:00
|
|
|
}
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
2012-06-04 09:59:02 -05:00
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Returns the last element, failing if the vector is empty
|
2012-05-22 12:54:12 -05:00
|
|
|
#[inline(always)]
|
2012-07-17 12:24:04 -05:00
|
|
|
pure fn last() -> A {
|
2012-05-22 12:54:12 -05:00
|
|
|
self.check_not_borrowed();
|
|
|
|
|
|
|
|
let length = self.len();
|
2012-09-25 20:27:45 -05:00
|
|
|
if length == 0 {
|
2012-07-14 00:57:48 -05:00
|
|
|
fail ~"attempt to retrieve the last element of an empty vector";
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-09-25 20:27:45 -05:00
|
|
|
return self.data[length - 1];
|
2012-05-22 12:54:12 -05:00
|
|
|
}
|
|
|
|
|
2012-07-04 16:53:12 -05:00
|
|
|
/// Iterates over the elements in reverse order
|
2012-05-22 12:54:12 -05:00
|
|
|
#[inline(always)]
|
2012-09-21 20:43:30 -05:00
|
|
|
fn rev_each(f: fn(v: &A) -> bool) {
|
|
|
|
do self.swap |v| {
|
|
|
|
// FIXME(#2263)---we should be able to write
|
|
|
|
// `vec::rev_each(v, f);` but we cannot write now
|
|
|
|
for vec::rev_each(v) |e| {
|
|
|
|
if !f(e) { break; }
|
|
|
|
}
|
|
|
|
move v
|
|
|
|
}
|
2012-07-17 12:24:04 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Iterates over the elements and indices in reverse order
|
|
|
|
#[inline(always)]
|
2012-09-21 20:43:30 -05:00
|
|
|
fn rev_eachi(f: fn(uint, v: &A) -> bool) {
|
|
|
|
do self.swap |v| {
|
|
|
|
// FIXME(#2263)---we should be able to write
|
|
|
|
// `vec::rev_eachi(v, f);` but we cannot write now
|
|
|
|
for vec::rev_eachi(v) |i, e| {
|
|
|
|
if !f(i, e) { break; }
|
|
|
|
}
|
|
|
|
move v
|
|
|
|
}
|
2012-06-04 09:59:02 -05:00
|
|
|
}
|
2012-06-25 22:00:46 -05:00
|
|
|
}
|
2012-07-27 16:51:19 -05:00
|
|
|
|
2012-09-07 16:52:28 -05:00
|
|
|
impl<A:Copy> DVec<A>: Index<uint,A> {
|
2012-09-25 20:27:45 -05:00
|
|
|
pure fn index(+idx: uint) -> A {
|
2012-07-27 16:51:19 -05:00
|
|
|
self.get_elt(idx)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|