Add utility alloc/clone functions
This commit is contained in:
parent
994c9e8cf2
commit
c8641247fe
1 changed files with 84 additions and 0 deletions
|
@ -12,6 +12,90 @@ pub fn cloneStr(str: []const u8, alloc: std.mem.Allocator) ![]const u8 {
|
|||
return new;
|
||||
}
|
||||
|
||||
pub fn deepFree(alloc: std.mem.Allocator, val: anytype) void {
|
||||
const T = @TypeOf(val);
|
||||
switch (@typeInfo(T)) {
|
||||
.Pointer => |ptr| switch (ptr.size) {
|
||||
.One => alloc.destroy(val),
|
||||
.Slice => {
|
||||
for (val) |v| deepFree(alloc, v);
|
||||
alloc.free(val);
|
||||
},
|
||||
else => @compileError("Many and C-style pointers not supported by deepfree"),
|
||||
},
|
||||
.Optional => if (val) |v| deepFree(alloc, v) else {},
|
||||
.Struct => |struct_info| for (struct_info.fields) |field| deepFree(alloc, @field(val, field.name)),
|
||||
.Union, .ErrorUnion => @compileError("TODO: Unions not yet supported by deepFree"),
|
||||
.Array => for (val) |v| deepFree(alloc, v),
|
||||
|
||||
.Error, .Int, .Float, .Bool, .Void, .Type => {},
|
||||
|
||||
else => @compileError("Type " ++ @typeName(T) ++ " not supported by deepFree"),
|
||||
}
|
||||
}
|
||||
|
||||
// deepClone assumes the value owns any pointers inside it
|
||||
pub fn deepClone(alloc: std.mem.Allocator, val: anytype) !void {
|
||||
const T = @TypeOf(val);
|
||||
var result: T = undefined;
|
||||
switch (@typeInfo(T)) {
|
||||
.Pointer => |ptr| switch (ptr.size) {
|
||||
.One => {
|
||||
result = try alloc.create(ptr.child);
|
||||
errdefer alloc.free(result);
|
||||
result.* = try deepClone(alloc, val.*);
|
||||
},
|
||||
.Slice => {
|
||||
const slice = try alloc.alloc(ptr.child, val.len);
|
||||
errdefer alloc.free(slice);
|
||||
|
||||
var count: usize = 0;
|
||||
errdefer for (slice[0..count]) |v| deepFree(alloc, v);
|
||||
|
||||
for (val) |v, i| {
|
||||
slice[i] = try deepClone(alloc, v);
|
||||
count += 1;
|
||||
}
|
||||
|
||||
result = slice;
|
||||
},
|
||||
else => @compileError("Many and C-style pointers not supported"),
|
||||
},
|
||||
.Optional => {
|
||||
result = if (val) |v| try deepClone(alloc, v) else null;
|
||||
},
|
||||
.Struct => {
|
||||
const fields = std.meta.fields(T);
|
||||
var count: usize = 0;
|
||||
errdefer {
|
||||
inline for (fields) |f, i| {
|
||||
if (i < count) deepFree(alloc, @field(result, f.name));
|
||||
}
|
||||
}
|
||||
|
||||
inline for (fields) |f| {
|
||||
@field(result, f.name) = try deepClone(alloc, @field(val, f.name));
|
||||
count += 1;
|
||||
}
|
||||
},
|
||||
.Array => {
|
||||
var count: usize = 0;
|
||||
errdefer for (result[0..count]) |v| deepFree(alloc, v);
|
||||
|
||||
for (val) |v, i| {
|
||||
result[i] = try deepClone(alloc, v);
|
||||
count += 1;
|
||||
}
|
||||
},
|
||||
.Error, .Int, .Float, .Bool, .Void, .Type => {
|
||||
result = val;
|
||||
},
|
||||
else => @compileError("Type " ++ @typeName(T) ++ " not supported"),
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
test {
|
||||
_ = ciutf8;
|
||||
_ = Uuid;
|
||||
|
|
Loading…
Reference in a new issue