diff --git a/zig/src/vector.zig b/zig/src/vector.zig index 1d002b3..bb088ab 100644 --- a/zig/src/vector.zig +++ b/zig/src/vector.zig @@ -1,11 +1,15 @@ const std = @import("std"); +/// return empty instance of `Vector` +/// use `new()` or `new_with_capacity()` to +/// get an initialised instance of `Vector` pub fn vector(comptime T: type) type { return struct { - const Self: type = @This(); + const Vector: type = @This(); const VectorType: type = T; + const DEFAULT_SIZE: usize = 16; const VectorError: type = error { OutOfBounds, @@ -16,52 +20,73 @@ pub fn vector(comptime T: type) type array: []VectorType, length: usize, - pub fn new(allocator: std.mem.Allocator) !Self + /// create new vector with the default capacity + /// + /// returns initialised instance of `Vector` + pub fn new(allocator: std.mem.Allocator) !Vector { - const DEFAULT_SIZE: usize = 16; - return Self + return Vector { .allocator = allocator, - .array = try allocator.alloc(VectorType, DEFAULT_SIZE), + .array = allocator.alloc(VectorType, DEFAULT_SIZE) catch return VectorError.FailedToAllocateMemory, .length = 0, }; } - pub fn new_with_capacity(allocator: std.mem.Allocator, capacity: usize) !Self + /// create new vector with the given capacity + /// + /// returns initialised instance of `Vector` + pub fn new_with_capacity(allocator: std.mem.Allocator, size: usize) VectorError!Vector { - return Self + return Vector { .allocator = allocator, - .array = try allocator.alloc(VectorType, capacity), + .array = allocator.alloc(VectorType, size) catch return VectorError.FailedToAllocateMemory, .length = 0, }; } - pub fn len(self: *Self) usize + /// get the vectors length + /// + /// **note:** length != capacity + /// length = number of items in the vector + /// capacity = maximum number of items the vector can hold + pub fn len(self: *Vector) usize { return self.length; } - pub fn push(self: *Self, item: VectorType) !void + /// get the vectors capacity + /// + /// **note:** length != capacity + /// length = number of items in the vector + /// capacity = maximum number of items the vector can hold + pub fn capacity(self: *Vector) usize { - if (self.length >= self.array.len) - { - const new_buffer: []VectorType = try self.allocator.alloc(VectorType, 2 * self.array.len); - @memcpy(new_buffer, self.array); - self.allocator.free(self.array); - self.array = new_buffer; - } + return self.array.len; + } + + /// add one item at the end of the vector + pub fn push(self: *Vector, item: VectorType) VectorError!void + { + if (self.length >= self.array.len) try self.double_capacity(); + self.array[self.length] = item; self.length += 1; } - pub fn pop(self: *Self) VectorType + /// remove and return last item of the vector + pub fn pop(self: *Vector) VectorType { self.length -= 1; return self.array[self.length]; } - pub fn drain(self: *Self, range: [2]usize) VectorError![]VectorType + /// remove and return a range of elements + /// + /// range[0] has to be less than range[1] + /// the range bounds are **both** included + pub fn drain(self: *Vector, range: [2]usize) VectorError![]VectorType { if (2 != range.len or range[1] <= range[0] @@ -80,11 +105,46 @@ pub fn vector(comptime T: type) type // TODO: return array instead of pointer @memcpy(slice.ptr, self.array[range[0]..range[1] + 1]); - @memmove(self.array.ptr + range[0], self.array[range[1]..self.length]); + @memmove(self.array.ptr + range[0], self.array[range[1] + 1..self.length]); self.length -= slice_length; return slice; } + + /// add slice of `VectorType` to the end of the vector + pub fn extend(self: *Vector, slice: []VectorType) VectorError!void + { + if (slice.len == 0) return; + + if (slice.len > self.capacity()) { + try self.increase_capacity(slice.len + self.capacity()); + } + else if (slice.len > self.capacity() - self.length) + { + try self.double_capacity(); + } + + @memcpy(self.array.ptr + self.length, slice); + } + + /// double the vectors capacity + fn double_capacity(self: *Vector) VectorError!void + { + try self.increase_capacity(2 * self.capacity()); + } + + /// increase the vectors capacity to given size + fn increase_capacity(self: *Vector, size: usize) VectorError!void + { + const new_buffer: []VectorType = self.allocator.alloc(VectorType, size) + catch + { + return VectorError.FailedToAllocateMemory; + }; + @memcpy(new_buffer, self.array); + self.allocator.free(self.array); + self.array = new_buffer; + } }; }