Skip to content

Commit 1798de7

Browse files
committed
add new vector representation as a library
1 parent 17d23b8 commit 1798de7

File tree

3 files changed

+233
-1
lines changed

3 files changed

+233
-1
lines changed

src/libstd/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ pub mod char;
110110
pub mod tuple;
111111

112112
pub mod vec;
113+
pub mod vec_ng;
113114
pub mod at_vec;
114115
pub mod str;
115116

src/libstd/rt/global_heap.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ pub unsafe fn realloc_raw(ptr: *mut u8, size: uint) -> *mut u8 {
5252
// `realloc(ptr, 0)` may allocate, but it may also return a null pointer
5353
// http://pubs.opengroup.org/onlinepubs/9699919799/functions/realloc.html
5454
if size == 0 {
55-
free(ptr);
55+
free(ptr as *mut c_void);
5656
mut_null()
5757
} else {
5858
let p = realloc(ptr as *mut c_void, size as size_t);

src/libstd/vec_ng.rs

Lines changed: 231 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,231 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// Migrate documentation over from `std::vec` when it is removed.
12+
#[doc(hidden)];
13+
14+
use prelude::*;
15+
use container::Container;
16+
use mem::size_of;
17+
use cast::{forget, transmute};
18+
use rt::global_heap::{malloc_raw, realloc_raw};
19+
use vec::Items;
20+
use unstable::raw::Slice;
21+
use ptr::{offset, read_ptr};
22+
use libc::{free, c_void};
23+
use unstable::intrinsics::move_val_init;
24+
25+
pub struct Vec<T> {
26+
priv len: uint,
27+
priv cap: uint,
28+
priv ptr: *mut T
29+
}
30+
31+
impl<T> Vec<T> {
32+
#[inline]
33+
pub fn new() -> Vec<T> {
34+
Vec { len: 0, cap: 0, ptr: 0 as *mut T }
35+
}
36+
37+
pub fn with_capacity(capacity: uint) -> Vec<T> {
38+
if capacity == 0 {
39+
Vec::new()
40+
} else {
41+
let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
42+
let ptr = unsafe { malloc_raw(size) };
43+
Vec { len: 0, cap: capacity, ptr: ptr as *mut T }
44+
}
45+
}
46+
47+
pub fn from_fn(length: uint, op: |uint| -> T) -> Vec<T> {
48+
unsafe {
49+
let mut xs = Vec::with_capacity(length);
50+
while xs.len < length {
51+
move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len), op(xs.len));
52+
xs.len += 1;
53+
}
54+
xs
55+
}
56+
}
57+
}
58+
59+
impl<T: Clone> Vec<T> {
60+
pub fn from_elem(length: uint, value: T) -> Vec<T> {
61+
unsafe {
62+
let mut xs = Vec::with_capacity(length);
63+
while xs.len < length {
64+
move_val_init(xs.as_mut_slice().unsafe_mut_ref(xs.len), value.clone());
65+
xs.len += 1;
66+
}
67+
xs
68+
}
69+
}
70+
}
71+
72+
impl<T> Container for Vec<T> {
73+
#[inline]
74+
fn len(&self) -> uint {
75+
self.len
76+
}
77+
}
78+
79+
impl<T> Vec<T> {
80+
#[inline]
81+
pub fn capacity(&self) -> uint {
82+
self.cap
83+
}
84+
85+
pub fn reserve_exact(&mut self, capacity: uint) {
86+
if capacity >= self.len {
87+
let size = capacity.checked_mul(&size_of::<T>()).expect("capacity overflow");
88+
self.cap = capacity;
89+
unsafe {
90+
self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T;
91+
}
92+
}
93+
}
94+
95+
pub fn shrink_to_fit(&mut self) {
96+
if self.len == 0 {
97+
unsafe { free(self.ptr as *mut c_void) };
98+
self.cap = 0;
99+
self.ptr = 0 as *mut T;
100+
} else {
101+
unsafe {
102+
// Overflow check is unnecessary as the vector is already at least this large.
103+
self.ptr = realloc_raw(self.ptr as *mut u8, self.len * size_of::<T>()) as *mut T;
104+
}
105+
self.cap = self.len;
106+
}
107+
}
108+
109+
#[inline]
110+
pub fn pop(&mut self) -> Option<T> {
111+
if self.len == 0 {
112+
None
113+
} else {
114+
unsafe {
115+
self.len -= 1;
116+
Some(read_ptr(self.as_slice().unsafe_ref(self.len())))
117+
}
118+
}
119+
}
120+
121+
#[inline]
122+
pub fn push(&mut self, value: T) {
123+
if self.len == self.cap {
124+
if self.cap == 0 { self.cap += 2 }
125+
let old_size = self.cap * size_of::<T>();
126+
self.cap = self.cap * 2;
127+
let size = old_size * 2;
128+
if old_size > size { fail!("capacity overflow") }
129+
unsafe {
130+
self.ptr = realloc_raw(self.ptr as *mut u8, size) as *mut T;
131+
}
132+
}
133+
134+
unsafe {
135+
let end = offset(self.ptr as *T, self.len as int) as *mut T;
136+
move_val_init(&mut *end, value);
137+
self.len += 1;
138+
}
139+
}
140+
141+
pub fn truncate(&mut self, len: uint) {
142+
unsafe {
143+
let mut i = len;
144+
// drop any extra elements
145+
while i < self.len {
146+
read_ptr(self.as_slice().unsafe_ref(i));
147+
i += 1;
148+
}
149+
}
150+
self.len = len;
151+
}
152+
153+
#[inline]
154+
pub fn as_slice<'a>(&'a self) -> &'a [T] {
155+
let slice = Slice { data: self.ptr as *T, len: self.len };
156+
unsafe { transmute(slice) }
157+
}
158+
159+
#[inline]
160+
pub fn as_mut_slice<'a>(&'a mut self) -> &'a mut [T] {
161+
let slice = Slice { data: self.ptr as *T, len: self.len };
162+
unsafe { transmute(slice) }
163+
}
164+
165+
#[inline]
166+
pub fn move_iter(self) -> MoveItems<T> {
167+
unsafe {
168+
let iter = transmute(self.as_slice().iter());
169+
let ptr = self.ptr as *mut c_void;
170+
forget(self);
171+
MoveItems { allocation: ptr, iter: iter }
172+
}
173+
}
174+
175+
#[inline]
176+
pub unsafe fn set_len(&mut self, len: uint) {
177+
self.len = len;
178+
}
179+
}
180+
181+
182+
#[unsafe_destructor]
183+
impl<T> Drop for Vec<T> {
184+
fn drop(&mut self) {
185+
unsafe {
186+
for x in self.as_mut_slice().iter() {
187+
read_ptr(x);
188+
}
189+
free(self.ptr as *mut c_void)
190+
}
191+
}
192+
}
193+
194+
pub struct MoveItems<T> {
195+
priv allocation: *mut c_void, // the block of memory allocated for the vector
196+
priv iter: Items<'static, T>
197+
}
198+
199+
impl<T> Iterator<T> for MoveItems<T> {
200+
#[inline]
201+
fn next(&mut self) -> Option<T> {
202+
unsafe {
203+
self.iter.next().map(|x| read_ptr(x))
204+
}
205+
}
206+
207+
#[inline]
208+
fn size_hint(&self) -> (uint, Option<uint>) {
209+
self.iter.size_hint()
210+
}
211+
}
212+
213+
impl<T> DoubleEndedIterator<T> for MoveItems<T> {
214+
#[inline]
215+
fn next_back(&mut self) -> Option<T> {
216+
unsafe {
217+
self.iter.next_back().map(|x| read_ptr(x))
218+
}
219+
}
220+
}
221+
222+
#[unsafe_destructor]
223+
impl<T> Drop for MoveItems<T> {
224+
fn drop(&mut self) {
225+
// destroy the remaining elements
226+
for _x in *self {}
227+
unsafe {
228+
free(self.allocation)
229+
}
230+
}
231+
}

0 commit comments

Comments
 (0)