(zig) extended vector.rs

This commit is contained in:
scbj
2025-10-06 17:42:53 +02:00
committed by zegonix
parent 42f5119f42
commit 5900789ce4
+80 -20
View File
@@ -1,11 +1,15 @@
const std = @import("std"); 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 pub fn vector(comptime T: type) type
{ {
return struct return struct
{ {
const Self: type = @This(); const Vector: type = @This();
const VectorType: type = T; const VectorType: type = T;
const DEFAULT_SIZE: usize = 16;
const VectorError: type = error { const VectorError: type = error {
OutOfBounds, OutOfBounds,
@@ -16,52 +20,73 @@ pub fn vector(comptime T: type) type
array: []VectorType, array: []VectorType,
length: usize, 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 Vector
return Self
{ {
.allocator = allocator, .allocator = allocator,
.array = try allocator.alloc(VectorType, DEFAULT_SIZE), .array = allocator.alloc(VectorType, DEFAULT_SIZE) catch return VectorError.FailedToAllocateMemory,
.length = 0, .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, .allocator = allocator,
.array = try allocator.alloc(VectorType, capacity), .array = allocator.alloc(VectorType, size) catch return VectorError.FailedToAllocateMemory,
.length = 0, .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; 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) return self.array.len;
{ }
const new_buffer: []VectorType = try self.allocator.alloc(VectorType, 2 * self.array.len);
@memcpy(new_buffer, self.array); /// add one item at the end of the vector
self.allocator.free(self.array); pub fn push(self: *Vector, item: VectorType) VectorError!void
self.array = new_buffer; {
} if (self.length >= self.array.len) try self.double_capacity();
self.array[self.length] = item; self.array[self.length] = item;
self.length += 1; 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; self.length -= 1;
return self.array[self.length]; 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 if (2 != range.len
or range[1] <= range[0] or range[1] <= range[0]
@@ -80,11 +105,46 @@ pub fn vector(comptime T: type) type
// TODO: return array instead of pointer // TODO: return array instead of pointer
@memcpy(slice.ptr, self.array[range[0]..range[1] + 1]); @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; self.length -= slice_length;
return slice; 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;
}
}; };
} }