Simplify deinit existence check and improve code format.

This commit is contained in:
Madeorsk 2024-10-15 21:59:45 +02:00
parent f0f6c32267
commit 9a8268c8e2
Signed by: Madeorsk
GPG key ID: 677E51CA765BB79F

View file

@ -2,8 +2,7 @@ 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();
@ -15,8 +14,7 @@ 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 .{ return .{
.allocator = allocator, .allocator = allocator,
// Store given values in items slice. // Store given values in items slice.
@ -25,35 +23,29 @@ pub fn Collection(comptime T: anytype) type
} }
/// 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.
.Struct, .Enum, .Union, .Opaque => { .Pointer => self.freeAnyValue(pointer.*),
// If type is a container with a deinit, run deinit.
if (@hasDecl(@TypeOf(pointer.*), "deinit"))
{ // The container has a specific deinit, running it.
pointer.deinit();
//TODO implement something like that.
//switch (@TypeOf(pointer.deinit).@"fn".return_type)
//{
// .ErrorUnion => {
// try pointer.deinit();
// },
// else => {
// pointer.deinit();
// },
//}
}
},
.Pointer => {
// It's a simple pointer, freeing its value recursively.
self.freeAnyValue(pointer.*);
},
else => { else => {
// If type is a container with a deinit, run deinit.
if (std.meta.hasFn(@TypeOf(pointer.*), "deinit")) {
// The container has a specific deinit, running it.
pointer.deinit();
//TODO implement something like that.
//switch (@TypeOf(pointer.deinit).@"fn".return_type)
//{
// .ErrorUnion => {
// try pointer.deinit();
// },
// else => {
// pointer.deinit();
// },
//}
}
// 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.
}, },
} }
@ -63,39 +55,35 @@ 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.