Last active
March 30, 2017 05:47
-
-
Save andrewrk/bda1f80514903b7b7fe1b618c8bf4975 to your computer and use it in GitHub Desktop.
data structure in zig that simultaneously supports an allocator supplied at compile time or at runtime
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const debug = @import("debug.zig"); | |
const assert = debug.assert; | |
const mem = @import("mem.zig"); | |
const Allocator = mem.Allocator; | |
pub fn List(comptime T: type, comptime ct_allocator: ?&Allocator) -> type { | |
struct { | |
const Self = this; | |
const RuntimeAllocatorType = if (ct_allocator == null) &Allocator else void; | |
/// Use toSlice instead of slicing this directly, because if you don't | |
/// specify the end position of the slice, this will potentially give | |
/// you uninitialized memory. | |
items: []T, | |
len: usize, | |
allocator: RuntimeAllocatorType, | |
pub fn init(allocator: RuntimeAllocatorType) -> Self { | |
Self { | |
.items = []T{}, | |
.len = 0, | |
.allocator = allocator, | |
} | |
} | |
pub fn deinit(l: &Self) { | |
l.allocator().free(l.items); | |
} | |
pub fn toSlice(l: &Self) -> []T { | |
return l.items[0...l.len]; | |
} | |
pub fn toSliceConst(l: &const Self) -> []const T { | |
return l.items[0...l.len]; | |
} | |
pub fn append(l: &Self, item: &const T) -> %void { | |
const new_item_ptr = %return l.addOne(); | |
*new_item_ptr = *item; | |
} | |
pub fn resize(l: &Self, new_len: usize) -> %void { | |
%return l.ensureCapacity(new_len); | |
l.len = new_len; | |
} | |
pub fn ensureCapacity(l: &Self, new_capacity: usize) -> %void { | |
var better_capacity = l.items.len; | |
if (better_capacity >= new_capacity) return; | |
while (true) { | |
better_capacity += better_capacity / 2 + 8; | |
if (better_capacity >= new_capacity) break; | |
} | |
l.items = %return l.allocator().realloc(T, l.items, better_capacity); | |
} | |
pub fn addOne(l: &Self) -> %&T { | |
const new_length = l.len + 1; | |
%return l.ensureCapacity(new_length); | |
const result = &l.items[l.len]; | |
l.len = new_length; | |
return result; | |
} | |
pub fn allocator(l: &Self) -> &Allocator { | |
return ct_allocator ?? l.allocator; | |
} | |
} | |
} | |
test "runtime supplied allocator" { | |
var list = List(i32, null).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)); | |
}} | |
} | |
test "comptime supplied allocator" { | |
var list = List(i32, &debug.global_allocator).init({}); | |
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)); | |
}} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment