diff --git a/src/coral/stack.zig b/src/coral/stack.zig index f49b8a2..156181d 100644 --- a/src/coral/stack.zig +++ b/src/coral/stack.zig @@ -61,17 +61,17 @@ fn Generic(comptime Item: type, comptime Storage: type) type { pub fn pushAll(self: *Self, items: []const Item) bool { const new_len = self.items.len + items.len; - if (new_len < self.cap) { - const index = self.items.len; - - self.items.len = new_len; - - std.debug.assert(self.items.sliced(index, self.items.len).copy(items)); - - return true; + if (new_len > self.items.cap) { + return false; } - return false; + const index = self.items.len; + + self.items.len = new_len; + + std.debug.assert(self.items.sliced(index, self.items.len).copy(items)); + + return true; } pub fn pushGrow(self: *Self, allocator: std.mem.Allocator, item: Item) std.mem.Allocator.Error!void { @@ -99,6 +99,16 @@ fn Generic(comptime Item: type, comptime Storage: type) type { return true; } + + pub fn set(self: *Self, item: Item) bool { + if (self.isEmpty()) { + return false; + } + + std.debug.assert(self.items.set(self.items.len - 1, item)); + + return true; + } }; } @@ -109,8 +119,7 @@ pub fn Parallel(comptime Item: type) type { }; const item_align = @alignOf(Item); - const item_size = @sizeOf(usize); - const byte_size = @sizeOf(u8); + const item_size = @sizeOf(Item); return Generic(Item, struct { ptr: [*]align(item_align) u8 = undefined, @@ -130,7 +139,7 @@ pub fn Parallel(comptime Item: type) type { } pub fn get(self: Self, index: usize) ?Item { - if (index >= self.cap) { + if (index >= self.len) { return null; } @@ -139,29 +148,52 @@ pub fn Parallel(comptime Item: type) type { inline for (item_fields) |item_field| { @field(item, item_field.name) = @as([*]item_field.type, @ptrCast(@alignCast(ptr)))[index]; - ptr += @sizeOf(item_field.type) * self.len; + ptr += @sizeOf(item_field.type) * self.cap; } return item; } pub fn grow(self: *Self, allocator: std.mem.Allocator, amount: usize) std.mem.Allocator.Error!void { - const new_cap = std.math.cast(u32, @as(usize, self.cap + amount)) orelse { + const old_cap = self.cap; + + const new_cap = std.math.cast(u32, @as(usize, old_cap) + amount) orelse { return error.OutOfMemory; }; - const reallocation = try allocator.alignedAlloc(u8, item_align, byte_size * new_cap); - const len_in_bytes = byte_size * self.len; + if (new_cap != 0) { + const new_allocation = try allocator.alignedAlloc(u8, item_align, item_size * new_cap); - @memcpy(reallocation[0..len_in_bytes], self.ptr[0..len_in_bytes]); - allocator.free(self.ptr[0 .. byte_size * self.cap]); + errdefer { + allocator.free(new_allocation); + } - self.ptr = reallocation.ptr; - self.cap = @intCast(new_cap); + if (old_cap != 0) { + var old_ptr_offset: usize = 0; + var new_ptr_offset: usize = 0; + + inline for (item_fields) |field| { + const FieldType = field.type; + const old_field_ptr: [*]const FieldType = @ptrCast(@alignCast(self.ptr + old_ptr_offset)); + const new_field_ptr: [*]FieldType = @ptrCast(@alignCast(new_allocation.ptr + new_ptr_offset)); + + @memcpy(new_field_ptr[0..self.len], old_field_ptr[0..self.len]); + + old_ptr_offset += @sizeOf(FieldType) * old_cap; + new_ptr_offset += @sizeOf(FieldType) * new_cap; + } + + // Free the old allocation + allocator.free(self.ptr[0 .. item_size * old_cap]); + } + + self.ptr = new_allocation.ptr; + self.cap = new_cap; + } } pub fn set(self: Self, index: usize, item: Item) bool { - if (index >= self.cap) { + if (index >= self.len) { return false; } @@ -169,7 +201,7 @@ pub fn Parallel(comptime Item: type) type { inline for (item_fields) |item_field| { @as([*]item_field.type, @ptrCast(@alignCast(ptr)))[index] = @field(item, item_field.name); - ptr += @sizeOf(item_field.type) * self.len; + ptr += @sizeOf(item_field.type) * self.cap; } return true; @@ -180,7 +212,7 @@ pub fn Parallel(comptime Item: type) type { var ptr: [*]u8 = self.ptr; inline for (item_fields[0..field_index]) |item_field| { - ptr += @sizeOf(item_field.type) * self.len; + ptr += @sizeOf(item_field.type) * self.cap; } return @as([*]item_fields[field_index].type, @ptrCast(@alignCast(ptr)))[0..self.len];