Compare commits

..

No commits in common. "main" and "v0.1.0" have entirely different histories.
main ... v0.1.0

4 changed files with 64 additions and 47 deletions

View file

@ -28,7 +28,7 @@ _Zollections_ is a collections library for Zig. It's made to ease memory managem
## Versions ## Versions
Zollections 0.1.1 is made and tested with zig 0.13.0. Zollections 0.1.0 is made and tested with zig 0.13.0.
## How to use ## How to use
@ -37,7 +37,7 @@ Zollections 0.1.1 is made and tested with zig 0.13.0.
In your project directory: In your project directory:
```shell ```shell
$ zig fetch --save https://code.zeptotech.net/zedd/zollections/archive/v0.1.1.tar.gz $ zig fetch --save https://code.zeptotech.net/zedd/zollections/archive/v0.1.0.tar.gz
``` ```
In `build.zig`: In `build.zig`:

View file

@ -1,6 +1,6 @@
.{ .{
.name = "zollections", .name = "zollections",
.version = "0.1.1", .version = "0.1.0",
.minimum_zig_version = "0.13.0", .minimum_zig_version = "0.13.0",
@ -11,7 +11,5 @@
"build.zig", "build.zig",
"build.zig.zon", "build.zig.zon",
"src", "src",
"README.md",
"LICENSE",
}, },
} }

View file

@ -2,7 +2,8 @@ const std = @import("std");
/// Collection of pointers of a certain type. /// Collection of pointers of a certain type.
/// A collection manages memory of the contained type. /// A collection manages memory of the contained type.
pub fn Collection(comptime T: anytype) type { pub fn Collection(comptime T: anytype) type
{
return struct { return struct {
const Self = @This(); const Self = @This();
@ -14,38 +15,49 @@ pub fn Collection(comptime T: anytype) type {
/// Initialize a new collection of values. /// Initialize a new collection of values.
/// Values are now owned by the collection and will free them when it is deinitialized. /// Values are now owned by the collection and will free them when it is deinitialized.
/// The allocator must be the one that manages the slice and its items. /// The allocator must be the one that manages the slice and its items.
pub fn init(allocator: std.mem.Allocator, values: []*T) Self { pub fn init(allocator: std.mem.Allocator, values: []*T) !*Self
return .{ {
const self = try allocator.create(Self);
self.* = .{
.allocator = allocator, .allocator = allocator,
// Store given values in items slice. // Store given values in items slice.
.items = values, .items = values,
}; };
return self;
} }
/// Free any pointer value. /// Free any pointer value.
fn freeAnyPointer(self: *Self, pointer: anytype) void { fn freeAnyPointer(self: *Self, pointer: anytype) void
{
// Get type info of the current pointer. // Get type info of the current pointer.
const pointedTypeInfo = @typeInfo(@TypeOf(pointer.*)); const pointedTypeInfo = @typeInfo(@TypeOf(pointer.*));
switch (pointedTypeInfo) { switch (pointedTypeInfo)
// It's a simple pointer, freeing its value recursively. {
.Pointer => self.freeAnyValue(pointer.*), .Struct, .Enum, .Union, .Opaque => {
else => {
// If type is a container with a deinit, run deinit. // If type is a container with a deinit, run deinit.
if (std.meta.hasFn(@TypeOf(pointer.*), "deinit")) { if (@hasDecl(@TypeOf(pointer.*), "deinit"))
// The container has a specific deinit, running it. { // The container has a specific deinit, running it.
pointer.deinit(); pointer.deinit();
//TODO implement something like that. //TODO implement something like that.
//switch (@TypeOf(pointer.deinit).@"fn".return_type) //switch (@TypeOf(pointer.deinit).@"fn".return_type)
//{ //{
// .ErrorUnion => { // .ErrorUnion => {
// try pointer.deinit(); // try pointer.deinit();
// }, // },
// else => { // else => {
// pointer.deinit(); // pointer.deinit();
// }, // },
//} //}
} }
},
.Pointer => {
// It's a simple pointer, freeing its value recursively.
self.freeAnyValue(pointer.*);
},
else => {
// Otherwise, we consider it as a simple value, there is nothing to free. // Otherwise, we consider it as a simple value, there is nothing to free.
}, },
} }
@ -55,35 +67,39 @@ pub fn Collection(comptime T: anytype) type {
} }
/// Free any value. /// Free any value.
fn freeAnyValue(self: *Self, value: anytype) void { fn freeAnyValue(self: *Self, value: anytype) void
{
// Get type info of the current pointer. // Get type info of the current pointer.
const typeInfo = @typeInfo(@TypeOf(value)); const typeInfo = @typeInfo(@TypeOf(value));
switch (typeInfo) { switch (typeInfo)
{
.Pointer => |pointerInfo| { .Pointer => |pointerInfo| {
// Can be a slice or a simple pointer. // Can be a slice or a simple pointer.
if (pointerInfo.size == .One) { if (pointerInfo.size == .One)
// It's a simple pointer, freeing its value recursively. { // It's a simple pointer, freeing its value recursively.
self.freeAnyPointer(value); self.freeAnyPointer(value);
}
else {
// It's a slice, free every item then free it.
for (value) |item| {
// Free each item recursively.
self.freeAnyValue(item);
} }
else
{ // It's a slice, free every item then free it.
for (value) |item|
{ // For each item, free it recursively.
self.freeAnyValue(item);
}
// Free the current pointer. // Free the current pointer.
self.allocator.free(value); self.allocator.free(value);
} }
},
else => {
// Otherwise, we consider it as a simple value, nothing to free.
}, },
// Otherwise, we consider it as a simple value, nothing to free.
else => {},
} }
} }
/// Deinitialize the collection of values and all its values. /// Deinitialize the collection of values and all its values.
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void
{
// Deinitialize all items. // Deinitialize all items.
for (self.items) |item| for (self.items) |item|
{ // For each items, try to free it. { // For each items, try to free it.
@ -92,6 +108,9 @@ pub fn Collection(comptime T: anytype) type {
// Free items slice. // Free items slice.
self.allocator.free(self.items); self.allocator.free(self.items);
// Destroy the current collection.
self.allocator.destroy(self);
} }
}; };
} }

View file

@ -37,7 +37,7 @@ test "simple collection" {
slice[2] = try allocator.create(u8); slice[2] = try allocator.create(u8);
// Create a collection with your slice of elements. // Create a collection with your slice of elements.
var collection = zollections.Collection(u8).init(allocator, slice); const collection = try zollections.Collection(u8).init(allocator, slice);
// Free your collection: your slice and all your elements will be freed. // Free your collection: your slice and all your elements will be freed.
defer collection.deinit(); defer collection.deinit();
} }
@ -60,7 +60,7 @@ test "recursive free" {
slice[0] = slicePointer; slice[0] = slicePointer;
// Create a collection with your slice of elements. // Create a collection with your slice of elements.
var collection = zollections.Collection([]*u8).init(allocator, slice); const collection = try zollections.Collection([]*u8).init(allocator, slice);
// Free your collection: your slice and all your slices and their elements will be freed. // Free your collection: your slice and all your slices and their elements will be freed.
defer collection.deinit(); defer collection.deinit();
} }
@ -79,7 +79,7 @@ test "custom struct deinit" {
slice[2].* = try ExampleStruct.init(16); slice[2].* = try ExampleStruct.init(16);
// Create a collection with your slice of elements. // Create a collection with your slice of elements.
var collection = zollections.Collection(ExampleStruct).init(allocator, slice); const collection = try zollections.Collection(ExampleStruct).init(allocator, slice);
// Free your collection: your slice and all your elements will be deinitialized and freed. // Free your collection: your slice and all your elements will be deinitialized and freed.
defer collection.deinit(); defer collection.deinit();
} }