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, 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 { @compileError("Unimplemented!"); } }; }