2012-12-03 18:48:01 -06:00
|
|
|
// Copyright 2012 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2012-09-20 17:33:52 -05:00
|
|
|
//! Managed vectors
|
2012-07-17 18:31:19 -05:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
use clone::Clone;
|
2013-05-12 19:34:15 -05:00
|
|
|
use container::Container;
|
2013-06-21 07:29:53 -05:00
|
|
|
use iterator::IteratorUtil;
|
2013-01-08 21:37:25 -06:00
|
|
|
use option::Option;
|
2012-12-23 16:41:37 -06:00
|
|
|
use sys;
|
|
|
|
use uint;
|
2013-07-21 19:20:52 -05:00
|
|
|
use unstable::raw::Repr;
|
2013-07-01 10:26:44 -05:00
|
|
|
use vec::{ImmutableVector, OwnedVector};
|
2012-07-17 18:31:19 -05:00
|
|
|
|
|
|
|
/// Code for dealing with @-vectors. This is pretty incomplete, and
|
|
|
|
/// contains a bunch of duplication from the code for ~-vectors.
|
|
|
|
|
|
|
|
/// Returns the number of elements the vector can hold without reallocating
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-22 19:58:50 -05:00
|
|
|
pub fn capacity<T>(v: @[T]) -> uint {
|
2012-07-17 18:31:19 -05:00
|
|
|
unsafe {
|
2013-07-21 19:20:52 -05:00
|
|
|
let box = v.repr();
|
|
|
|
(*box).data.alloc / sys::size_of::<T>()
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* 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
|
2013-05-08 12:34:47 -05:00
|
|
|
* * builder - A function that will construct the vector. It receives
|
2012-07-17 18:31:19 -05:00
|
|
|
* as an argument a function that will push an element
|
|
|
|
* onto the vector being constructed.
|
|
|
|
*/
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn build_sized<A>(size: uint, builder: &fn(push: &fn(v: A))) -> @[A] {
|
2013-07-21 19:20:52 -05:00
|
|
|
let mut vec = @[];
|
2012-09-26 14:28:30 -05:00
|
|
|
unsafe { raw::reserve(&mut vec, size); }
|
2013-05-07 16:20:56 -05:00
|
|
|
builder(|x| unsafe { raw::push(&mut vec, x) });
|
2013-07-21 19:20:52 -05:00
|
|
|
vec
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Builds a vector by calling a provided function with an argument
|
|
|
|
* function that pushes an element to the back of a vector.
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
2013-05-08 12:34:47 -05:00
|
|
|
* * builder - A function that will construct the vector. It receives
|
2012-07-17 18:31:19 -05:00
|
|
|
* as an argument a function that will push an element
|
|
|
|
* onto the vector being constructed.
|
|
|
|
*/
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn build<A>(builder: &fn(push: &fn(v: A))) -> @[A] {
|
2012-07-17 18:31:19 -05:00
|
|
|
build_sized(4, builder)
|
|
|
|
}
|
|
|
|
|
2012-08-23 12:22:14 -05:00
|
|
|
/**
|
|
|
|
* 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 option, maybe containing initial size of the vector to reserve
|
2013-05-08 12:34:47 -05:00
|
|
|
* * builder - A function that will construct the vector. It receives
|
2012-08-23 12:22:14 -05:00
|
|
|
* as an argument a function that will push an element
|
|
|
|
* onto the vector being constructed.
|
|
|
|
*/
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn build_sized_opt<A>(size: Option<uint>,
|
|
|
|
builder: &fn(push: &fn(v: A)))
|
|
|
|
-> @[A] {
|
2013-01-04 18:01:26 -06:00
|
|
|
build_sized(size.get_or_default(4), builder)
|
2012-08-23 12:22:14 -05:00
|
|
|
}
|
|
|
|
|
2012-08-08 16:30:30 -05:00
|
|
|
// Appending
|
2013-05-28 16:35:52 -05:00
|
|
|
|
|
|
|
/// Iterates over the `rhs` vector, copying each element and appending it to the
|
|
|
|
/// `lhs`. Afterwards, the `lhs` is then returned for use again.
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-07-02 14:47:32 -05:00
|
|
|
pub fn append<T:Clone>(lhs: @[T], rhs: &[T]) -> @[T] {
|
2012-08-08 16:30:30 -05:00
|
|
|
do build_sized(lhs.len() + rhs.len()) |push| {
|
2013-07-02 14:47:32 -05:00
|
|
|
for lhs.iter().advance |x| {
|
|
|
|
push((*x).clone());
|
|
|
|
}
|
|
|
|
for uint::range(0, rhs.len()) |i| {
|
|
|
|
push(rhs[i].clone());
|
|
|
|
}
|
2012-08-08 16:30:30 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2012-07-17 18:31:19 -05:00
|
|
|
/// Apply a function to each element of a vector and return the results
|
2013-03-21 23:20:48 -05:00
|
|
|
pub fn map<T, U>(v: &[T], f: &fn(x: &T) -> U) -> @[U] {
|
2012-07-17 18:31:19 -05:00
|
|
|
do build_sized(v.len()) |push| {
|
2013-06-21 07:29:53 -05:00
|
|
|
for v.iter().advance |elem| {
|
2012-09-26 12:33:55 -05:00
|
|
|
push(f(elem));
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates and initializes an immutable vector.
|
|
|
|
*
|
|
|
|
* Creates an immutable vector of size `n_elts` and initializes the elements
|
|
|
|
* to the value returned by the function `op`.
|
|
|
|
*/
|
2013-06-23 16:57:39 -05:00
|
|
|
pub fn from_fn<T>(n_elts: uint, op: &fn(uint) -> T) -> @[T] {
|
2012-07-17 18:31:19 -05:00
|
|
|
do build_sized(n_elts) |push| {
|
|
|
|
let mut i: uint = 0u;
|
|
|
|
while i < n_elts { push(op(i)); i += 1u; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates and initializes an immutable vector.
|
|
|
|
*
|
|
|
|
* Creates an immutable vector of size `n_elts` and initializes the elements
|
|
|
|
* to the value `t`.
|
|
|
|
*/
|
2013-07-02 14:47:32 -05:00
|
|
|
pub fn from_elem<T:Clone>(n_elts: uint, t: T) -> @[T] {
|
2012-07-17 18:31:19 -05:00
|
|
|
do build_sized(n_elts) |push| {
|
|
|
|
let mut i: uint = 0u;
|
2013-07-02 14:47:32 -05:00
|
|
|
while i < n_elts {
|
|
|
|
push(t.clone());
|
|
|
|
i += 1u;
|
|
|
|
}
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-01-22 16:52:20 -06:00
|
|
|
/**
|
|
|
|
* Creates and initializes an immutable managed vector by moving all the
|
|
|
|
* elements from an owned vector.
|
|
|
|
*/
|
2013-05-15 10:33:54 -05:00
|
|
|
pub fn to_managed_consume<T>(v: ~[T]) -> @[T] {
|
2013-01-22 16:52:20 -06:00
|
|
|
let mut av = @[];
|
|
|
|
unsafe {
|
|
|
|
raw::reserve(&mut av, v.len());
|
2013-07-01 10:26:44 -05:00
|
|
|
for v.consume_iter().advance |x| {
|
2013-01-22 16:52:20 -06:00
|
|
|
raw::push(&mut av, x);
|
|
|
|
}
|
2013-07-21 19:20:52 -05:00
|
|
|
av
|
2013-01-22 16:52:20 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Creates and initializes an immutable managed vector by copying all the
|
|
|
|
* elements of a slice.
|
|
|
|
*/
|
2013-07-02 14:47:32 -05:00
|
|
|
pub fn to_managed<T:Clone>(v: &[T]) -> @[T] {
|
|
|
|
from_fn(v.len(), |i| v[i].clone())
|
|
|
|
}
|
|
|
|
|
|
|
|
impl<T> Clone for @[T] {
|
|
|
|
fn clone(&self) -> @[T] {
|
|
|
|
*self
|
|
|
|
}
|
2013-01-22 16:52:20 -06:00
|
|
|
}
|
|
|
|
|
2013-05-08 06:11:23 -05:00
|
|
|
#[cfg(not(test))]
|
2012-09-26 16:23:27 -05:00
|
|
|
pub mod traits {
|
2013-01-08 21:37:25 -06:00
|
|
|
use at_vec::append;
|
2013-07-02 14:47:32 -05:00
|
|
|
use clone::Clone;
|
2013-01-08 21:37:25 -06:00
|
|
|
use ops::Add;
|
2013-07-02 14:47:32 -05:00
|
|
|
use vec::Vector;
|
2013-01-08 21:37:25 -06:00
|
|
|
|
2013-07-02 14:47:32 -05:00
|
|
|
impl<'self,T:Clone, V: Vector<T>> Add<V,@[T]> for @[T] {
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-07-02 21:13:00 -05:00
|
|
|
fn add(&self, rhs: &V) -> @[T] {
|
|
|
|
append(*self, rhs.as_slice())
|
2012-11-28 15:51:50 -06:00
|
|
|
}
|
|
|
|
}
|
2012-08-08 16:30:30 -05:00
|
|
|
}
|
|
|
|
|
2012-09-19 20:00:26 -05:00
|
|
|
#[cfg(test)]
|
2012-11-03 15:23:01 -05:00
|
|
|
pub mod traits {}
|
2012-07-17 18:31:19 -05:00
|
|
|
|
2012-09-25 19:52:46 -05:00
|
|
|
pub mod raw {
|
2013-06-21 21:40:00 -05:00
|
|
|
use at_vec::capacity;
|
2013-07-02 19:36:58 -05:00
|
|
|
use cast;
|
2013-04-22 19:34:42 -05:00
|
|
|
use cast::{transmute, transmute_copy};
|
2012-12-23 16:41:37 -06:00
|
|
|
use libc;
|
|
|
|
use ptr;
|
|
|
|
use sys;
|
|
|
|
use uint;
|
2013-07-02 19:36:58 -05:00
|
|
|
use unstable::intrinsics::{move_val_init, TyDesc};
|
2013-07-21 19:20:52 -05:00
|
|
|
use unstable::intrinsics;
|
|
|
|
use unstable::raw::{Box, Vec};
|
2012-07-17 18:31:19 -05:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Sets the length of a vector
|
|
|
|
*
|
|
|
|
* This will explicitly set the size of the vector, without actually
|
|
|
|
* modifing its buffers, so it is up to the caller to ensure that
|
|
|
|
* the vector is actually the specified size.
|
|
|
|
*/
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-07-21 19:20:52 -05:00
|
|
|
pub unsafe fn set_len<T>(v: &mut @[T], new_len: uint) {
|
|
|
|
let repr: *mut Box<Vec<T>> = cast::transmute_copy(v);
|
|
|
|
(*repr).data.fill = new_len * sys::size_of::<T>();
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
/**
|
|
|
|
* Pushes a new value onto this vector.
|
|
|
|
*/
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline]
|
2013-03-22 19:58:50 -05:00
|
|
|
pub unsafe fn push<T>(v: &mut @[T], initval: T) {
|
2013-07-21 19:20:52 -05:00
|
|
|
let full = {
|
|
|
|
let repr: *Box<Vec<T>> = cast::transmute_copy(v);
|
|
|
|
(*repr).data.alloc > (*repr).data.fill
|
|
|
|
};
|
|
|
|
if full {
|
2012-12-12 17:38:50 -06:00
|
|
|
push_fast(v, initval);
|
2013-04-22 19:34:42 -05:00
|
|
|
} else {
|
2012-12-12 17:38:50 -06:00
|
|
|
push_slow(v, initval);
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
}
|
2012-10-05 16:58:42 -05:00
|
|
|
|
2013-06-18 16:45:18 -05:00
|
|
|
#[inline] // really pretty please
|
2013-05-28 16:35:52 -05:00
|
|
|
unsafe fn push_fast<T>(v: &mut @[T], initval: T) {
|
2013-07-21 19:20:52 -05:00
|
|
|
let repr: *mut Box<Vec<T>> = cast::transmute_copy(v);
|
|
|
|
let amt = v.len();
|
|
|
|
(*repr).data.fill += sys::size_of::<T>();
|
|
|
|
let p = ptr::offset(&(*repr).data.data as *T, amt) as *mut T;
|
2013-02-20 10:57:15 -06:00
|
|
|
move_val_init(&mut(*p), initval);
|
2012-10-05 16:58:42 -05:00
|
|
|
}
|
2012-07-30 13:21:40 -05:00
|
|
|
|
2013-05-28 16:35:52 -05:00
|
|
|
unsafe fn push_slow<T>(v: &mut @[T], initval: T) {
|
2013-07-21 19:20:52 -05:00
|
|
|
reserve_at_least(v, v.len() + 1u);
|
2013-02-15 02:51:28 -06:00
|
|
|
push_fast(v, initval);
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
2012-07-30 13:21:40 -05:00
|
|
|
|
2012-07-17 18:31:19 -05:00
|
|
|
/**
|
|
|
|
* Reserves capacity for exactly `n` elements in the given vector.
|
|
|
|
*
|
|
|
|
* If the capacity for `v` is already equal to or greater than the
|
|
|
|
* requested capacity, then no action is taken.
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
|
|
|
* * v - A vector
|
|
|
|
* * n - The number of elements to reserve space for
|
|
|
|
*/
|
2013-03-22 19:58:50 -05:00
|
|
|
pub unsafe fn reserve<T>(v: &mut @[T], n: uint) {
|
2012-07-17 18:31:19 -05:00
|
|
|
// Only make the (slow) call into the runtime if we have to
|
2012-09-26 14:28:30 -05:00
|
|
|
if capacity(*v) < n {
|
2013-07-21 19:20:52 -05:00
|
|
|
let ptr: *mut *mut Box<Vec<()>> = transmute(v);
|
2013-07-02 19:36:58 -05:00
|
|
|
let ty = intrinsics::get_tydesc::<T>();
|
|
|
|
// XXX transmute shouldn't be necessary
|
|
|
|
let ty = cast::transmute(ty);
|
2013-06-21 21:40:00 -05:00
|
|
|
return reserve_raw(ty, ptr, n);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Implementation detail. Shouldn't be public
|
|
|
|
#[allow(missing_doc)]
|
2013-07-21 19:20:52 -05:00
|
|
|
pub fn reserve_raw(ty: *TyDesc, ptr: *mut *mut Box<Vec<()>>, n: uint) {
|
2013-06-21 21:40:00 -05:00
|
|
|
|
|
|
|
unsafe {
|
|
|
|
let size_in_bytes = n * (*ty).size;
|
2013-07-21 19:20:52 -05:00
|
|
|
if size_in_bytes > (**ptr).data.alloc {
|
|
|
|
let total_size = size_in_bytes + sys::size_of::<Vec<()>>();
|
|
|
|
(*ptr) = local_realloc(*ptr as *(), total_size) as *mut Box<Vec<()>>;
|
|
|
|
(**ptr).data.alloc = size_in_bytes;
|
2013-06-21 21:40:00 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
fn local_realloc(ptr: *(), size: uint) -> *() {
|
|
|
|
use rt;
|
|
|
|
use rt::OldTaskContext;
|
|
|
|
use rt::local::Local;
|
|
|
|
use rt::task::Task;
|
|
|
|
|
|
|
|
if rt::context() == OldTaskContext {
|
|
|
|
unsafe {
|
|
|
|
return rust_local_realloc(ptr, size as libc::size_t);
|
|
|
|
}
|
|
|
|
|
|
|
|
extern {
|
|
|
|
#[fast_ffi]
|
|
|
|
fn rust_local_realloc(ptr: *(), size: libc::size_t) -> *();
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
do Local::borrow::<Task, *()> |task| {
|
|
|
|
task.heap.realloc(ptr as *libc::c_void, size) as *()
|
|
|
|
}
|
|
|
|
}
|
2012-07-17 18:31:19 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Reserves capacity for at least `n` elements in the given vector.
|
|
|
|
*
|
|
|
|
* This function will over-allocate in order to amortize the
|
|
|
|
* allocation costs in scenarios where the caller may need to
|
|
|
|
* repeatedly reserve additional space.
|
|
|
|
*
|
|
|
|
* If the capacity for `v` is already equal to or greater than the
|
|
|
|
* requested capacity, then no action is taken.
|
|
|
|
*
|
|
|
|
* # Arguments
|
|
|
|
*
|
|
|
|
* * v - A vector
|
|
|
|
* * n - The number of elements to reserve space for
|
|
|
|
*/
|
2013-03-22 19:58:50 -05:00
|
|
|
pub unsafe fn reserve_at_least<T>(v: &mut @[T], n: uint) {
|
2012-07-17 18:31:19 -05:00
|
|
|
reserve(v, uint::next_power_of_two(n));
|
|
|
|
}
|
|
|
|
}
|
2012-07-31 19:30:38 -05:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[cfg(test)]
|
|
|
|
mod test {
|
|
|
|
use super::*;
|
2013-05-24 21:35:29 -05:00
|
|
|
use uint;
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
fn test() {
|
|
|
|
// Some code that could use that, then:
|
|
|
|
fn seq_range(lo: uint, hi: uint) -> @[uint] {
|
|
|
|
do build |push| {
|
|
|
|
for uint::range(lo, hi) |i| {
|
|
|
|
push(i);
|
|
|
|
}
|
2012-07-31 19:30:38 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
assert_eq!(seq_range(10, 15), @[10, 11, 12, 13, 14]);
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(from_fn(5, |x| x+1), @[1, 2, 3, 4, 5]);
|
|
|
|
assert_eq!(from_elem(5, 3.14), @[3.14, 3.14, 3.14, 3.14, 3.14]);
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-01-22 16:52:20 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
|
|
|
fn append_test() {
|
2013-07-02 21:13:00 -05:00
|
|
|
assert_eq!(@[1,2,3] + &[4,5,6], @[1,2,3,4,5,6]);
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-01-22 16:52:20 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
2013-05-15 10:33:54 -05:00
|
|
|
fn test_to_managed_consume() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(to_managed_consume::<int>(~[]), @[]);
|
|
|
|
assert_eq!(to_managed_consume(~[true]), @[true]);
|
|
|
|
assert_eq!(to_managed_consume(~[1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]);
|
|
|
|
assert_eq!(to_managed_consume(~[~"abc", ~"123"]), @[~"abc", ~"123"]);
|
|
|
|
assert_eq!(to_managed_consume(~[~[42]]), @[~[42]]);
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-01-22 16:52:20 -06:00
|
|
|
|
2013-04-15 10:08:52 -05:00
|
|
|
#[test]
|
2013-05-15 10:33:54 -05:00
|
|
|
fn test_to_managed() {
|
2013-05-18 21:02:45 -05:00
|
|
|
assert_eq!(to_managed::<int>([]), @[]);
|
|
|
|
assert_eq!(to_managed([true]), @[true]);
|
|
|
|
assert_eq!(to_managed([1, 2, 3, 4, 5]), @[1, 2, 3, 4, 5]);
|
|
|
|
assert_eq!(to_managed([@"abc", @"123"]), @[@"abc", @"123"]);
|
|
|
|
assert_eq!(to_managed([@[42]]), @[@[42]]);
|
2013-04-15 10:08:52 -05:00
|
|
|
}
|
2013-04-20 09:27:16 -05:00
|
|
|
}
|