2016-08-12 13:25:13 +08:00
|
|
|
const debug = @import("debug.zig");
|
|
|
|
const assert = debug.assert;
|
2016-05-08 16:34:00 +08:00
|
|
|
const mem = @import("mem.zig");
|
|
|
|
const Allocator = mem.Allocator;
|
|
|
|
|
2016-08-08 11:08:37 +08:00
|
|
|
pub fn List(inline T: type) -> type {
|
2016-08-12 13:25:13 +08:00
|
|
|
SmallList(T, @sizeof(usize))
|
2016-05-08 16:34:00 +08:00
|
|
|
}
|
|
|
|
|
2016-08-12 13:25:13 +08:00
|
|
|
// TODO: make sure that setting STATIC_SIZE to 0 codegens to the same code
|
|
|
|
// as if this were programmed without STATIC_SIZE at all.
|
2016-07-27 11:40:11 +08:00
|
|
|
pub struct SmallList(T: type, STATIC_SIZE: usize) {
|
2016-07-25 09:35:50 +08:00
|
|
|
const Self = SmallList(T, STATIC_SIZE);
|
|
|
|
|
2016-05-08 16:34:00 +08:00
|
|
|
items: []T,
|
2016-08-12 13:25:13 +08:00
|
|
|
len: usize,
|
2016-05-08 16:34:00 +08:00
|
|
|
prealloc_items: [STATIC_SIZE]T,
|
|
|
|
allocator: &Allocator,
|
|
|
|
|
2016-07-25 09:35:50 +08:00
|
|
|
pub fn init(l: &Self, allocator: &Allocator) {
|
2016-05-08 16:34:00 +08:00
|
|
|
l.items = l.prealloc_items[0...];
|
2016-08-12 13:25:13 +08:00
|
|
|
l.len = 0;
|
2016-05-08 16:34:00 +08:00
|
|
|
l.allocator = allocator;
|
|
|
|
}
|
|
|
|
|
2016-07-25 09:35:50 +08:00
|
|
|
pub fn deinit(l: &Self) {
|
2016-05-10 06:07:38 +08:00
|
|
|
if (l.items.ptr != &l.prealloc_items[0]) {
|
2016-07-25 09:35:50 +08:00
|
|
|
l.allocator.free(T, l.items);
|
2016-05-08 16:34:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-07-25 09:35:50 +08:00
|
|
|
pub fn append(l: &Self, item: T) -> %void {
|
2016-08-12 13:25:13 +08:00
|
|
|
const new_length = l.len + 1;
|
2016-05-08 16:34:00 +08:00
|
|
|
%return l.ensure_capacity(new_length);
|
2016-08-12 13:25:13 +08:00
|
|
|
l.items[l.len] = item;
|
|
|
|
l.len = new_length;
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn resize(l: &Self, new_len: usize) -> %void {
|
|
|
|
%return l.ensure_capacity(new_len);
|
|
|
|
l.len = new_len;
|
2016-05-08 16:34:00 +08:00
|
|
|
}
|
|
|
|
|
2016-07-27 11:40:11 +08:00
|
|
|
pub fn ensure_capacity(l: &Self, new_capacity: usize) -> %void {
|
2016-05-08 16:34:00 +08:00
|
|
|
const old_capacity = l.items.len;
|
|
|
|
var better_capacity = old_capacity;
|
|
|
|
while (better_capacity < new_capacity) {
|
|
|
|
better_capacity *= 2;
|
|
|
|
}
|
|
|
|
if (better_capacity != old_capacity) {
|
|
|
|
if (l.items.ptr == &l.prealloc_items[0]) {
|
2016-07-25 09:35:50 +08:00
|
|
|
l.items = %return l.allocator.alloc(T, better_capacity);
|
|
|
|
mem.copy(T, l.items, l.prealloc_items[0...old_capacity]);
|
2016-05-08 16:34:00 +08:00
|
|
|
} else {
|
2016-07-25 09:35:50 +08:00
|
|
|
l.items = %return l.allocator.realloc(T, l.items, better_capacity);
|
2016-05-08 16:34:00 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#attribute("test")
|
|
|
|
fn basic_list_test() {
|
2016-08-08 11:08:37 +08:00
|
|
|
var list: List(i32) = undefined;
|
2016-08-12 13:25:13 +08:00
|
|
|
list.init(&debug.global_allocator);
|
2016-05-08 16:34:00 +08:00
|
|
|
defer list.deinit();
|
|
|
|
|
2016-07-27 11:40:11 +08:00
|
|
|
{var i: usize = 0; while (i < 10; i += 1) {
|
2016-05-08 16:34:00 +08:00
|
|
|
%%list.append(i32(i + 1));
|
|
|
|
}}
|
|
|
|
|
2016-07-27 11:40:11 +08:00
|
|
|
{var i: usize = 0; while (i < 10; i += 1) {
|
2016-05-08 16:34:00 +08:00
|
|
|
assert(list.items[i] == i32(i + 1));
|
|
|
|
}}
|
|
|
|
}
|