diff options
Diffstat (limited to 'src/hooks.zig')
| -rw-r--r-- | src/hooks.zig | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/src/hooks.zig b/src/hooks.zig new file mode 100644 index 0000000..549d871 --- /dev/null +++ b/src/hooks.zig @@ -0,0 +1,115 @@ +const std = @import("std"); + +pub const Kind = enum { + none, + breakpoint, +}; +const Self = @This(); +pub const Hook = @This(); + +// pub fn init(comptime kind: Kind, comptime alloc: std.mem.Allocator) type { +// return struct { +// alloc: std.mem.Allocator = alloc, + +// pub fn malloc(size: usize) callconv(.c) ?*anyopaque { +// if (kind == .breakpoint) @breakpoint(); +// return std.c.malloc(size); +// } + +// pub fn calloc(n: usize, size: usize) callconv(.c) ?*anyopaque { +// if (kind == .breakpoint) @breakpoint(); +// return std.c.calloc(n, size); +// } +// pub fn realloc(ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque { +// if (kind == .breakpoint) @breakpoint(); +// return std.c.realloc(ptr, size); +// } +// pub fn free(ptr: ?*anyopaque) callconv(.c) void { +// if (kind == .breakpoint) @breakpoint(); +// return std.c.free(ptr); +// } +// pub fn vsnprintf(_: [*c]u8, _: usize, _: [*c]const u8, _: [*c]u8) callconv(.c) ?*anyopaque { +// if (kind == .breakpoint) @breakpoint(); +// return null; +// } +// }; +// } +// + +pub fn init(comptime kind: Kind, comptime alloc: std.mem.Allocator, comptime uselibc: bool) type { + return struct { + alloc: std.mem.Allocator = alloc, + + const Header = struct { + len: usize, + }; + const header_size = std.mem.alignForward(usize, @sizeOf(Header), @alignOf(std.c.max_align_t)); + const alignment: std.mem.Alignment = .fromByteUnits(@alignOf(std.c.max_align_t)); + + inline fn ptrFromRaw(raw: []u8) ?*anyopaque { + const h: *Header = @ptrCast(@alignCast(raw.ptr)); + h.* = .{ .len = raw.len }; + return @ptrFromInt(@intFromPtr(raw.ptr) + header_size); + } + + inline fn rawFromPtr(ptr: *anyopaque) []u8 { + const base = @intFromPtr(ptr) - header_size; + const h: *Header = @ptrFromInt(base); + return @as([*]u8, @ptrFromInt(base))[0..h.len]; + } + + pub fn malloc(size: usize) callconv(.c) ?*anyopaque { + if (kind == .breakpoint) @breakpoint(); + if (uselibc) return std.c.malloc(size); + const total = header_size + size; + const raw = alloc.alignedAlloc(u8, alignment, total) catch return null; + return ptrFromRaw(raw); + } + + pub fn calloc(n: usize, size: usize) callconv(.c) ?*anyopaque { + if (kind == .breakpoint) @breakpoint(); + if (uselibc) return std.c.calloc(n, size); + const total_data = std.math.mul(usize, n, size) catch return null; + const total = header_size + total_data; + const raw = alloc.alignedAlloc(u8, alignment, total) catch return null; + @memset(raw[header_size..], 0); + return ptrFromRaw(raw); + } + + pub fn realloc(ptr: ?*anyopaque, size: usize) callconv(.c) ?*anyopaque { + if (kind == .breakpoint) @breakpoint(); + if (uselibc) return std.c.realloc(ptr, size); + if (ptr) |p| { + const old_raw = rawFromPtr(p); + const total = header_size + size; + if (alloc.resize(old_raw, total)) { + const h: *Header = @ptrCast(@alignCast(old_raw.ptr)); + h.* = .{ .len = total }; + return p; + } + const new_raw = alloc.alignedAlloc(u8, alignment, total) catch return null; + const old_data = old_raw[header_size..]; + const copy_len = @min(old_data.len, size); + @memcpy(new_raw[header_size..][0..copy_len], old_data[0..copy_len]); + alloc.free(old_raw); + return ptrFromRaw(new_raw); + } else { + return malloc(size); + } + } + + pub fn free(ptr: ?*anyopaque) callconv(.c) void { + if (kind == .breakpoint) @breakpoint(); + if (uselibc) return std.c.free(ptr); + if (ptr) |p| { + const raw = rawFromPtr(p); + alloc.free(raw); + } + } + + pub fn vsnprintf(_: [*c]u8, _: usize, _: [*c]const u8, _: [*c]u8) callconv(.c) ?*anyopaque { + if (kind == .breakpoint) @breakpoint(); + return null; + } + }; +} |
