zig/std/list.zig

74 lines
2.0 KiB
Zig
Raw Normal View History

const debug = @import("debug.zig");
const assert = debug.assert;
const mem = @import("mem.zig");
const Allocator = mem.Allocator;
pub fn List(inline T: type) -> type {
2016-08-17 13:42:50 +08:00
SmallList(T, @sizeOf(usize))
}
2016-08-17 13:42:50 +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.
pub struct SmallList(T: type, static_size: usize) {
const Self = SmallList(T, static_size);
items: []T,
len: usize,
2016-08-17 13:42:50 +08:00
prealloc_items: [static_size]T,
allocator: &Allocator,
pub fn init(l: &Self, allocator: &Allocator) {
l.items = l.prealloc_items[0...];
l.len = 0;
l.allocator = allocator;
}
pub fn deinit(l: &Self) {
if (l.items.ptr != &l.prealloc_items[0]) {
l.allocator.free(T, l.items);
}
}
pub fn append(l: &Self, item: T) -> %void {
const new_length = l.len + 1;
2016-08-17 13:42:50 +08:00
%return l.ensureCapacity(new_length);
l.items[l.len] = item;
l.len = new_length;
}
pub fn resize(l: &Self, new_len: usize) -> %void {
2016-08-17 13:42:50 +08:00
%return l.ensureCapacity(new_len);
l.len = new_len;
}
2016-08-17 13:42:50 +08:00
pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void {
var better_capacity = l.items.len;
while (better_capacity < new_capacity) {
better_capacity *= 2;
}
if (better_capacity != l.items.len) {
if (l.items.ptr == &l.prealloc_items[0]) {
l.items = %return l.allocator.alloc(T, better_capacity);
mem.copy(T, l.items, l.prealloc_items[0...l.len]);
} else {
l.items = %return l.allocator.realloc(T, l.items, better_capacity);
}
}
}
}
#attribute("test")
2016-08-17 13:42:50 +08:00
fn basicListTest() {
var list: List(i32) = undefined;
list.init(&debug.global_allocator);
defer list.deinit();
{var i: usize = 0; while (i < 10; i += 1) {
%%list.append(i32(i + 1));
}}
{var i: usize = 0; while (i < 10; i += 1) {
assert(list.items[i] == i32(i + 1));
}}
}