2012-05-09 19:30:31 -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.
|
|
|
|
|
|
|
|
import dvec_iter::extensions;
|
|
|
|
import unsafe::reinterpret_cast;
|
|
|
|
import ptr::{null, extensions};
|
|
|
|
|
|
|
|
export dvec;
|
|
|
|
export from_vec;
|
|
|
|
export extensions;
|
|
|
|
export unwrap;
|
|
|
|
|
|
|
|
#[doc = "
|
|
|
|
|
|
|
|
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-06-25 22:00:46 -05:00
|
|
|
unsafe code. In particular, this innocent looking `[mut A]/~` pointer
|
2012-05-09 19:30:31 -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
|
|
|
|
the dvec is dropped. The reason that I did not use an `option<T>`
|
|
|
|
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.
|
|
|
|
|
|
|
|
"]
|
|
|
|
type dvec<A> = {
|
2012-06-25 22:00:46 -05:00
|
|
|
mut data: [mut A]/~
|
2012-05-09 19:30:31 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
#[doc = "Creates a new, empty dvec"]
|
|
|
|
fn dvec<A>() -> dvec<A> {
|
2012-06-25 22:00:46 -05:00
|
|
|
{mut data: [mut]/~}
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
|
|
|
|
2012-06-04 09:59:02 -05:00
|
|
|
#[doc = "Creates a new dvec with a single element"]
|
|
|
|
fn from_elt<A>(+e: A) -> dvec<A> {
|
2012-06-25 22:00:46 -05:00
|
|
|
{mut data: [mut e]/~}
|
2012-06-04 09:59:02 -05:00
|
|
|
}
|
|
|
|
|
2012-05-09 19:30:31 -05:00
|
|
|
#[doc = "Creates a new dvec with the contents of a vector"]
|
2012-06-25 22:00:46 -05:00
|
|
|
fn from_vec<A>(+v: [mut A]/~) -> dvec<A> {
|
2012-05-09 19:30:31 -05:00
|
|
|
{mut data: v}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Consumes the vector and returns its contents"]
|
2012-06-25 22:00:46 -05:00
|
|
|
fn unwrap<A>(-d: dvec<A>) -> [mut A]/~ {
|
2012-05-09 19:30:31 -05:00
|
|
|
let {data: v} <- d;
|
|
|
|
ret v;
|
|
|
|
}
|
|
|
|
|
|
|
|
impl private_methods<A> for dvec<A> {
|
|
|
|
fn check_not_borrowed() {
|
|
|
|
unsafe {
|
|
|
|
let data: *() = unsafe::reinterpret_cast(self.data);
|
|
|
|
if data.is_null() {
|
|
|
|
fail "Recursive use of dvec";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2012-06-25 22:00:46 -05:00
|
|
|
fn borrow<B>(f: fn(-[mut A]/~) -> B) -> B {
|
2012-05-09 19:30:31 -05:00
|
|
|
unsafe {
|
|
|
|
let mut data = unsafe::reinterpret_cast(null::<()>());
|
|
|
|
data <-> self.data;
|
|
|
|
let data_ptr: *() = unsafe::reinterpret_cast(data);
|
|
|
|
if data_ptr.is_null() { fail "Recursive use of dvec"; }
|
|
|
|
ret f(data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[inline(always)]
|
2012-06-25 22:00:46 -05:00
|
|
|
fn return(-data: [mut A]/~) {
|
2012-05-09 19:30:31 -05:00
|
|
|
unsafe {
|
|
|
|
self.data <- data;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// In theory, most everything should work with any A, but in practice
|
|
|
|
// almost nothing works without the copy bound due to limitations
|
|
|
|
// around closures.
|
|
|
|
impl extensions<A> for dvec<A> {
|
|
|
|
#[doc = "
|
|
|
|
|
|
|
|
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-06-25 22:00:46 -05:00
|
|
|
fn swap(f: fn(-[mut A]/~) -> [mut A]/~) {
|
2012-05-09 19:30:31 -05:00
|
|
|
self.borrow { |v| self.return(f(v)) }
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Returns the number of elements currently in the dvec"]
|
|
|
|
fn len() -> uint {
|
|
|
|
self.borrow { |v|
|
|
|
|
let l = v.len();
|
|
|
|
self.return(v);
|
|
|
|
l
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Overwrite the current contents"]
|
2012-06-25 22:00:46 -05:00
|
|
|
fn set(+w: [mut 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
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Remove and return the last element"]
|
|
|
|
fn pop() -> A {
|
|
|
|
self.borrow { |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);
|
|
|
|
self.return(v);
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-07 14:18:34 -05:00
|
|
|
#[doc = "Insert a single item at the front of the list"]
|
|
|
|
fn unshift(-t: A) {
|
|
|
|
unsafe {
|
|
|
|
let mut data = unsafe::reinterpret_cast(null::<()>());
|
|
|
|
data <-> self.data;
|
|
|
|
let data_ptr: *() = unsafe::reinterpret_cast(data);
|
|
|
|
if data_ptr.is_null() { fail "Recursive use of dvec"; }
|
|
|
|
log(error, "a");
|
2012-06-27 17:21:50 -05:00
|
|
|
self.data <- [mut t]/~;
|
|
|
|
vec::push_all_move(self.data, data);
|
2012-06-07 14:18:34 -05:00
|
|
|
log(error, "b");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Append a single item to the end of the list"]
|
|
|
|
fn push(+t: A) {
|
|
|
|
self.check_not_borrowed();
|
|
|
|
vec::push(self.data, t);
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Remove and return the first element"]
|
|
|
|
fn shift() -> A {
|
|
|
|
self.borrow { |v|
|
|
|
|
let mut v = vec::from_mut(v);
|
|
|
|
let result = vec::shift(v);
|
|
|
|
self.return(vec::to_mut(v));
|
|
|
|
result
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
impl extensions<A:copy> for dvec<A> {
|
2012-05-09 19:30:31 -05:00
|
|
|
#[doc = "
|
|
|
|
Append all elements of a vector to the end of the list
|
|
|
|
|
|
|
|
Equivalent to `append_iter()` but potentially more efficient.
|
|
|
|
"]
|
|
|
|
fn push_all(ts: [const A]/&) {
|
|
|
|
self.push_slice(ts, 0u, vec::len(ts));
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "
|
|
|
|
Appends elements from `from_idx` to `to_idx` (exclusive)
|
|
|
|
"]
|
|
|
|
fn push_slice(ts: [const A]/&, from_idx: uint, to_idx: uint) {
|
|
|
|
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;
|
|
|
|
vec::reserve(v, new_len);
|
|
|
|
let mut i = from_idx;
|
|
|
|
while i < to_idx {
|
2012-06-13 18:14:01 -05:00
|
|
|
vec::push(v, ts[i]);
|
2012-05-09 19:30:31 -05:00
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
v
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2012-06-14 18:24:21 -05:00
|
|
|
#[doc = "
|
|
|
|
Append all elements of an iterable.
|
2012-06-14 18:30:18 -05:00
|
|
|
|
2012-06-14 18:24:21 -05:00
|
|
|
Failure will occur if the iterable's `each()` method
|
|
|
|
attempts to access this vector.
|
|
|
|
"]
|
|
|
|
fn append_iter<A, I:iter::base_iter<A>>(ts: I) {
|
|
|
|
self.swap { |v|
|
|
|
|
let mut v = alt ts.size_hint() {
|
|
|
|
none { v }
|
|
|
|
some(h) {
|
|
|
|
let len = v.len() + h;
|
|
|
|
let mut v <- v;
|
|
|
|
vec::reserve(v, len);
|
|
|
|
v
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2012-06-26 02:39:18 -05:00
|
|
|
for ts.each { |t| vec::push(v, t) };
|
2012-06-14 18:24:21 -05:00
|
|
|
v
|
|
|
|
}
|
|
|
|
}
|
2012-05-09 19:30:31 -05:00
|
|
|
|
|
|
|
#[doc = "
|
|
|
|
Gets a copy of the current contents.
|
|
|
|
|
|
|
|
See `unwrap()` if you do not wish to copy the contents.
|
|
|
|
"]
|
2012-06-25 22:00:46 -05:00
|
|
|
fn get() -> [A]/~ {
|
2012-05-09 19:30:31 -05:00
|
|
|
self.borrow { |v|
|
|
|
|
let w = vec::from_mut(copy v);
|
|
|
|
self.return(v);
|
|
|
|
w
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Copy out an individual element"]
|
2012-05-15 15:41:15 -05:00
|
|
|
#[inline(always)]
|
2012-05-09 19:30:31 -05:00
|
|
|
fn [](idx: uint) -> A {
|
|
|
|
self.get_elt(idx)
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Copy out an individual element"]
|
2012-05-15 15:41:15 -05:00
|
|
|
#[inline(always)]
|
2012-05-09 19:30:31 -05:00
|
|
|
fn get_elt(idx: uint) -> A {
|
|
|
|
self.check_not_borrowed();
|
|
|
|
ret self.data[idx];
|
|
|
|
}
|
|
|
|
|
|
|
|
#[doc = "Overwrites the contents of the element at `idx` with `a`"]
|
|
|
|
fn set_elt(idx: uint, a: A) {
|
|
|
|
self.check_not_borrowed();
|
|
|
|
self.data[idx] = a;
|
|
|
|
}
|
|
|
|
|
2012-06-04 09:59:02 -05:00
|
|
|
#[doc = "Overwrites the contents of the element at `idx` with `a`,
|
|
|
|
growing the vector if necessary. New elements will be initialized
|
|
|
|
with `initval`"]
|
2012-05-09 19:30:31 -05:00
|
|
|
fn grow_set_elt(idx: uint, initval: A, val: A) {
|
2012-05-29 17:37:50 -05:00
|
|
|
self.swap { |v|
|
|
|
|
let mut v <- v;
|
|
|
|
vec::grow_set(v, idx, initval, val);
|
|
|
|
v
|
|
|
|
}
|
2012-05-09 19:30:31 -05:00
|
|
|
}
|
2012-06-04 09:59:02 -05:00
|
|
|
|
|
|
|
#[doc = "Returns the last element, failing if the vector is empty"]
|
|
|
|
fn last() -> A {
|
|
|
|
self.get_elt(self.len() - 1u)
|
|
|
|
}
|
2012-06-25 22:00:46 -05:00
|
|
|
}
|