2011-06-16 18:08:26 -05:00
|
|
|
// Interior vector utility functions.
|
|
|
|
|
|
|
|
import option::none;
|
|
|
|
import option::some;
|
2011-06-19 20:02:37 -05:00
|
|
|
import uint::next_power_of_two;
|
2011-07-11 19:26:34 -05:00
|
|
|
import ptr::addr_of;
|
2011-06-16 18:08:26 -05:00
|
|
|
|
|
|
|
type operator2[T,U,V] = fn(&T, &U) -> V;
|
|
|
|
|
|
|
|
native "rust-intrinsic" mod rusti {
|
2011-07-10 03:20:18 -05:00
|
|
|
fn ivec_len[T](&T[] v) -> uint;
|
2011-06-16 18:08:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
native "rust" mod rustrt {
|
2011-07-06 00:55:41 -05:00
|
|
|
fn ivec_reserve_shared[T](&mutable T[mutable?] v, uint n);
|
2011-07-05 17:34:22 -05:00
|
|
|
fn ivec_on_heap[T](&T[] v) -> uint;
|
2011-06-16 19:06:24 -05:00
|
|
|
fn ivec_to_ptr[T](&T[] v) -> *T;
|
2011-07-06 00:55:41 -05:00
|
|
|
fn ivec_copy_from_buf_shared[T](&mutable T[mutable?] v,
|
|
|
|
*T ptr, uint count);
|
2011-06-16 18:08:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/// Reserves space for `n` elements in the given vector.
|
2011-06-17 21:16:03 -05:00
|
|
|
fn reserve[T](&mutable T[mutable?] v, uint n) {
|
2011-07-06 00:55:41 -05:00
|
|
|
rustrt::ivec_reserve_shared(v, n);
|
2011-06-16 18:08:26 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
fn on_heap[T](&T[] v) -> bool {
|
2011-07-05 17:34:22 -05:00
|
|
|
ret rustrt::ivec_on_heap(v) != 0u;
|
2011-06-16 18:08:26 -05:00
|
|
|
}
|
|
|
|
|
2011-06-16 19:06:24 -05:00
|
|
|
fn to_ptr[T](&T[] v) -> *T {
|
|
|
|
ret rustrt::ivec_to_ptr(v);
|
|
|
|
}
|
|
|
|
|
2011-06-18 18:41:09 -05:00
|
|
|
fn len[T](&T[mutable?] v) -> uint {
|
2011-07-10 03:20:18 -05:00
|
|
|
ret rusti::ivec_len(v);
|
2011-06-16 19:06:24 -05:00
|
|
|
}
|
|
|
|
|
2011-06-16 19:47:28 -05:00
|
|
|
type init_op[T] = fn(uint) -> T;
|
|
|
|
|
|
|
|
fn init_fn[T](&init_op[T] op, uint n_elts) -> T[] {
|
|
|
|
auto v = ~[];
|
|
|
|
reserve(v, n_elts);
|
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n_elts) { v += ~[op(i)]; i += 1u; }
|
|
|
|
ret v;
|
|
|
|
}
|
|
|
|
|
2011-06-17 21:16:03 -05:00
|
|
|
// TODO: Remove me once we have slots.
|
|
|
|
fn init_fn_mut[T](&init_op[T] op, uint n_elts) -> T[mutable] {
|
|
|
|
auto v = ~[mutable];
|
|
|
|
reserve(v, n_elts);
|
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n_elts) { v += ~[mutable op(i)]; i += 1u; }
|
|
|
|
ret v;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn init_elt[T](&T t, uint n_elts) -> T[] {
|
|
|
|
auto v = ~[];
|
|
|
|
reserve(v, n_elts);
|
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n_elts) { v += ~[t]; i += 1u; }
|
|
|
|
ret v;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Remove me once we have slots.
|
|
|
|
fn init_elt_mut[T](&T t, uint n_elts) -> T[mutable] {
|
|
|
|
auto v = ~[mutable];
|
|
|
|
reserve(v, n_elts);
|
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n_elts) { v += ~[mutable t]; i += 1u; }
|
|
|
|
ret v;
|
|
|
|
}
|
|
|
|
|
2011-07-14 17:32:37 -05:00
|
|
|
// Predicates
|
|
|
|
pred is_empty[T](&T[mutable?] v) -> bool {
|
|
|
|
// FIXME: This would be easier if we could just call len
|
|
|
|
for (T t in v) {
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
|
|
|
|
pred is_not_empty[T](&T[mutable?] v) -> bool {
|
|
|
|
ret !is_empty(v);
|
|
|
|
}
|
2011-06-17 21:16:03 -05:00
|
|
|
|
|
|
|
// Accessors
|
|
|
|
|
2011-07-14 17:40:43 -05:00
|
|
|
/// Returns the first element of a vector
|
|
|
|
fn head[T](&T[mutable?] v) : is_not_empty(v) -> T {
|
|
|
|
ret v.(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns all but the first element of a vector
|
|
|
|
fn tail[T](&T[mutable?] v) : is_not_empty(v) -> T[mutable?] {
|
|
|
|
ret slice(v, 1u, len(v));
|
|
|
|
}
|
|
|
|
|
2011-06-17 21:16:03 -05:00
|
|
|
/// Returns the last element of `v`.
|
|
|
|
fn last[T](&T[mutable?] v) -> option::t[T] {
|
|
|
|
if (len(v) == 0u) { ret none; }
|
|
|
|
ret some(v.(len(v) - 1u));
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Returns a copy of the elements from [`start`..`end`) from `v`.
|
|
|
|
fn slice[T](&T[mutable?] v, uint start, uint end) -> T[] {
|
|
|
|
assert (start <= end);
|
|
|
|
assert (end <= len(v));
|
|
|
|
auto result = ~[];
|
|
|
|
reserve(result, end - start);
|
|
|
|
auto i = start;
|
|
|
|
while (i < end) { result += ~[v.(i)]; i += 1u; }
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: Remove me once we have slots.
|
|
|
|
fn slice_mut[T](&T[mutable?] v, uint start, uint end) -> T[mutable] {
|
|
|
|
assert (start <= end);
|
|
|
|
assert (end <= len(v));
|
|
|
|
auto result = ~[mutable];
|
|
|
|
reserve(result, end - start);
|
|
|
|
auto i = start;
|
|
|
|
while (i < end) { result += ~[mutable v.(i)]; i += 1u; }
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// Mutators
|
|
|
|
|
2011-07-04 23:20:18 -05:00
|
|
|
// TODO: Write this, unsafely, in a way that's not O(n).
|
|
|
|
fn pop[T](&mutable T[mutable?] v) -> T {
|
|
|
|
auto ln = len(v);
|
|
|
|
assert (ln > 0u);
|
|
|
|
ln -= 1u;
|
|
|
|
auto e = v.(ln);
|
|
|
|
v = slice(v, 0u, ln);
|
|
|
|
ret e;
|
|
|
|
}
|
|
|
|
|
|
|
|
// TODO: More.
|
2011-06-17 21:16:03 -05:00
|
|
|
|
|
|
|
|
2011-06-18 18:29:45 -05:00
|
|
|
// Appending
|
|
|
|
|
|
|
|
/// Expands the given vector in-place by appending `n` copies of `initval`.
|
|
|
|
fn grow[T](&mutable T[] v, uint n, &T initval) {
|
2011-06-19 20:02:37 -05:00
|
|
|
reserve(v, next_power_of_two(len(v) + n));
|
2011-06-18 18:29:45 -05:00
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n) {
|
|
|
|
v += ~[initval];
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-18 18:41:09 -05:00
|
|
|
// TODO: Remove me once we have slots.
|
|
|
|
fn grow_mut[T](&mutable T[mutable] v, uint n, &T initval) {
|
2011-06-19 20:02:37 -05:00
|
|
|
reserve(v, next_power_of_two(len(v) + n));
|
2011-06-18 18:41:09 -05:00
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n) {
|
|
|
|
v += ~[mutable initval];
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-18 18:29:45 -05:00
|
|
|
/// Calls `f` `n` times and appends the results of these calls to the given
|
|
|
|
/// vector.
|
|
|
|
fn grow_fn[T](&mutable T[] v, uint n, fn(uint)->T init_fn) {
|
2011-06-19 20:02:37 -05:00
|
|
|
reserve(v, next_power_of_two(len(v) + n));
|
2011-06-18 18:29:45 -05:00
|
|
|
let uint i = 0u;
|
|
|
|
while (i < n) {
|
|
|
|
v += ~[init_fn(i)];
|
|
|
|
i += 1u;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-18 18:41:09 -05:00
|
|
|
/// Sets the element at position `index` to `val`. If `index` is past the end
|
|
|
|
/// of the vector, expands the vector by replicating `initval` to fill the
|
|
|
|
/// intervening space.
|
|
|
|
fn grow_set[T](&mutable T[mutable] v, uint index, &T initval, &T val) {
|
|
|
|
if (index >= len(v)) { grow_mut(v, index - len(v) + 1u, initval); }
|
|
|
|
v.(index) = val;
|
|
|
|
}
|
2011-06-18 18:29:45 -05:00
|
|
|
|
2011-07-05 00:48:42 -05:00
|
|
|
|
|
|
|
// Functional utilities
|
|
|
|
|
2011-07-05 18:27:31 -05:00
|
|
|
fn map[T,U](fn(&T)->U f, &T[mutable?] v) -> U[] {
|
2011-07-05 00:48:42 -05:00
|
|
|
auto result = ~[];
|
|
|
|
reserve(result, len(v));
|
|
|
|
for (T elem in v) {
|
|
|
|
auto elem2 = elem; // satisfies alias checker
|
|
|
|
result += ~[f(elem2)];
|
|
|
|
}
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
2011-07-05 19:22:02 -05:00
|
|
|
fn filter_map[T,U](fn(&T)->option::t[U] f, &T[mutable?] v) -> U[] {
|
|
|
|
auto result = ~[];
|
|
|
|
for (T elem in v) {
|
|
|
|
auto elem2 = elem; // satisfies alias checker
|
|
|
|
alt (f(elem2)) {
|
|
|
|
case (none) { /* no-op */ }
|
|
|
|
case (some(?result_elem)) { result += ~[result_elem]; }
|
|
|
|
}
|
|
|
|
}
|
|
|
|
ret result;
|
|
|
|
}
|
|
|
|
|
2011-07-05 20:29:18 -05:00
|
|
|
fn foldl[T,U](fn(&U,&T)->U p, &U z, &T[mutable?] v) -> U {
|
|
|
|
auto sz = len(v);
|
|
|
|
if (sz == 0u) { ret z; }
|
|
|
|
auto first = v.(0);
|
|
|
|
auto rest = slice(v, 1u, sz);
|
|
|
|
ret p(foldl[T,U](p, z, rest), first);
|
|
|
|
}
|
|
|
|
|
2011-07-05 01:52:47 -05:00
|
|
|
fn any[T](fn(&T)->bool f, &T[] v) -> bool {
|
|
|
|
for (T elem in v) { if (f(elem)) { ret true; } }
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
|
|
|
|
fn all[T](fn(&T)->bool f, &T[] v) -> bool {
|
|
|
|
for (T elem in v) { if (!f(elem)) { ret false; } }
|
|
|
|
ret true;
|
|
|
|
}
|
|
|
|
|
2011-07-08 09:27:55 -05:00
|
|
|
fn member[T](&T x, &T[] v) -> bool {
|
|
|
|
for (T elt in v) { if (x == elt) { ret true; } }
|
|
|
|
ret false;
|
|
|
|
}
|
|
|
|
|
2011-07-12 19:00:25 -05:00
|
|
|
fn count[T](&T x, &T[mutable?] v) -> uint {
|
|
|
|
auto cnt = 0u;
|
|
|
|
for (T elt in v) { if (x == elt) { cnt += 1u; } }
|
|
|
|
ret cnt;
|
|
|
|
}
|
|
|
|
|
2011-07-08 09:27:55 -05:00
|
|
|
fn find[T](fn(&T) -> bool f, &T[] v) -> option::t[T] {
|
|
|
|
for (T elt in v) { if (f(elt)) { ret some[T](elt); } }
|
|
|
|
ret none[T];
|
|
|
|
}
|
2011-07-05 00:48:42 -05:00
|
|
|
|
2011-07-16 19:35:20 -05:00
|
|
|
fn unzip[T, U](&tup(T, U)[] v) -> tup(T[], U[]) {
|
|
|
|
auto sz = len[tup(T, U)](v);
|
|
|
|
if (sz == 0u) {
|
|
|
|
ret tup(~[], ~[]);
|
|
|
|
} else {
|
|
|
|
auto rest = slice[tup(T, U)](v, 1u, sz);
|
|
|
|
auto tl = unzip[T, U](rest);
|
|
|
|
auto a = ~[v.(0)._0];
|
|
|
|
auto b = ~[v.(0)._1];
|
|
|
|
ret tup(a + tl._0, b + tl._1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// FIXME make the lengths being equal a constraint
|
|
|
|
fn zip[T, U](&T[] v, &U[] u) -> tup(T, U)[] {
|
|
|
|
auto sz = len[T](v);
|
|
|
|
assert (sz == len[U](u));
|
|
|
|
if (sz == 0u) {
|
|
|
|
ret ~[];
|
|
|
|
} else {
|
|
|
|
auto rest = zip[T, U](slice[T](v, 1u, sz), slice[U](u, 1u, sz));
|
|
|
|
ret ~[tup(v.(0), u.(0))] + rest;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2011-06-16 19:06:24 -05:00
|
|
|
mod unsafe {
|
2011-07-11 19:26:34 -05:00
|
|
|
type ivec_repr = rec(mutable uint fill,
|
|
|
|
mutable uint alloc,
|
|
|
|
*mutable ivec_heap_part heap_part);
|
|
|
|
type ivec_heap_part = rec(mutable uint fill);
|
|
|
|
|
2011-06-16 19:06:24 -05:00
|
|
|
fn copy_from_buf[T](&mutable T[] v, *T ptr, uint count) {
|
2011-07-06 00:55:41 -05:00
|
|
|
ret rustrt::ivec_copy_from_buf_shared(v, ptr, count);
|
2011-06-16 19:06:24 -05:00
|
|
|
}
|
2011-07-10 04:05:52 -05:00
|
|
|
|
|
|
|
fn from_buf[T](*T ptr, uint bytes) -> T[] {
|
|
|
|
auto v = ~[];
|
|
|
|
copy_from_buf(v, ptr, bytes);
|
|
|
|
ret v;
|
|
|
|
}
|
2011-07-11 19:26:34 -05:00
|
|
|
|
|
|
|
fn set_len[T](&mutable T[] v, uint new_len) {
|
|
|
|
auto new_fill = new_len * sys::size_of[T]();
|
|
|
|
let *mutable ivec_repr stack_part =
|
|
|
|
::unsafe::reinterpret_cast(addr_of(v));
|
|
|
|
if ((*stack_part).fill == 0u) {
|
|
|
|
(*(*stack_part).heap_part).fill = new_fill; // On heap.
|
|
|
|
} else {
|
|
|
|
(*stack_part).fill = new_fill; // On stack.
|
|
|
|
}
|
|
|
|
}
|
2011-06-16 19:06:24 -05:00
|
|
|
}
|
|
|
|
|
2011-07-14 17:32:37 -05:00
|
|
|
// Local Variables:
|
|
|
|
// mode: rust;
|
|
|
|
// fill-column: 78;
|
|
|
|
// indent-tabs-mode: nil
|
|
|
|
// c-basic-offset: 4
|
|
|
|
// buffer-file-coding-system: utf-8-unix
|
|
|
|
// compile-command: "make -k -C .. 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
|
|
|
|
// End:
|