2022-07-30 05:46:00 +00:00
|
|
|
const std = @import("std");
|
|
|
|
|
2022-06-09 05:54:41 +00:00
|
|
|
pub const ciutf8 = @import("./ciutf8.zig");
|
|
|
|
pub const Uuid = @import("./Uuid.zig");
|
2022-07-18 07:03:29 +00:00
|
|
|
pub const DateTime = @import("./DateTime.zig");
|
2022-06-02 18:33:16 +00:00
|
|
|
pub const PathIter = @import("./PathIter.zig");
|
2022-09-10 22:29:08 +00:00
|
|
|
pub const Url = @import("./Url.zig");
|
2022-06-09 05:54:41 +00:00
|
|
|
|
2022-09-29 21:52:01 +00:00
|
|
|
fn comptimeJoinSlice(comptime separator: []const u8, comptime slices: []const []const u8) []u8 {
|
|
|
|
comptime {
|
|
|
|
var size: usize = 1; // 1 for null terminator
|
|
|
|
for (slices) |s| size += s.len + separator.len;
|
|
|
|
if (slices.len != 0) size -= separator.len;
|
|
|
|
|
|
|
|
var buf = std.mem.zeroes([size]u8);
|
|
|
|
var fba = std.heap.fixedBufferAllocator(&buf);
|
|
|
|
|
|
|
|
return std.mem.join(fba.allocator(), separator, slices);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn comptimeJoin(comptime separator: []const u8, comptime slices: []const []const u8) *const [comptimeJoinSlice(separator, slices):0]u8 {
|
|
|
|
const slice = comptimeJoinSlice(separator, slices);
|
|
|
|
return slice[0..slice.len];
|
2022-09-08 06:56:29 +00:00
|
|
|
}
|
|
|
|
|
2022-09-11 11:38:46 +00:00
|
|
|
pub fn deepFree(alloc: ?std.mem.Allocator, val: anytype) void {
|
2022-09-10 22:29:22 +00:00
|
|
|
const T = @TypeOf(val);
|
|
|
|
switch (@typeInfo(T)) {
|
|
|
|
.Pointer => |ptr| switch (ptr.size) {
|
2022-09-11 11:38:46 +00:00
|
|
|
.One => alloc.?.destroy(val),
|
2022-09-10 22:29:22 +00:00
|
|
|
.Slice => {
|
|
|
|
for (val) |v| deepFree(alloc, v);
|
2022-09-11 11:38:46 +00:00
|
|
|
alloc.?.free(val);
|
2022-09-10 22:29:22 +00:00
|
|
|
},
|
|
|
|
else => @compileError("Many and C-style pointers not supported by deepfree"),
|
|
|
|
},
|
|
|
|
.Optional => if (val) |v| deepFree(alloc, v) else {},
|
2022-09-15 01:12:07 +00:00
|
|
|
.Struct => |struct_info| inline for (struct_info.fields) |field| deepFree(alloc, @field(val, field.name)),
|
2022-09-10 22:29:22 +00:00
|
|
|
.Union, .ErrorUnion => @compileError("TODO: Unions not yet supported by deepFree"),
|
|
|
|
.Array => for (val) |v| deepFree(alloc, v),
|
|
|
|
|
2022-09-15 01:12:07 +00:00
|
|
|
.Enum, .Int, .Float, .Bool, .Void, .Type => {},
|
2022-09-10 22:29:22 +00:00
|
|
|
|
|
|
|
else => @compileError("Type " ++ @typeName(T) ++ " not supported by deepFree"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// deepClone assumes the value owns any pointers inside it
|
2022-09-11 08:55:20 +00:00
|
|
|
pub fn deepClone(alloc: std.mem.Allocator, val: anytype) !@TypeOf(val) {
|
2022-09-10 22:29:22 +00:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
},
|
2022-09-15 01:12:07 +00:00
|
|
|
.Enum, .Int, .Float, .Bool, .Void, .Type => {
|
2022-09-10 22:29:22 +00:00
|
|
|
result = val;
|
|
|
|
},
|
|
|
|
else => @compileError("Type " ++ @typeName(T) ++ " not supported"),
|
|
|
|
}
|
|
|
|
|
|
|
|
return result;
|
|
|
|
}
|
|
|
|
|
2022-06-09 05:54:41 +00:00
|
|
|
test {
|
|
|
|
_ = ciutf8;
|
|
|
|
_ = Uuid;
|
2022-06-02 18:33:16 +00:00
|
|
|
_ = PathIter;
|
2022-07-18 07:03:29 +00:00
|
|
|
_ = DateTime;
|
2022-06-09 05:54:41 +00:00
|
|
|
}
|