aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/galloc.zig77
-rw-r--r--src/root.zig53
2 files changed, 122 insertions, 8 deletions
diff --git a/src/galloc.zig b/src/galloc.zig
new file mode 100644
index 0000000..7cb4480
--- /dev/null
+++ b/src/galloc.zig
@@ -0,0 +1,77 @@
+const std = @import("std");
+const testing = std.testing;
+
+pub const GitAllocator = struct {
+ mutex: std.Thread.Mutex,
+ alloc: std.mem.Allocator,
+ allocs: std.AutoArrayHashMap(*anyopaque, []u8) = undefined,
+
+ pub fn init(alloc: std.mem.Allocator) GitAllocator {
+ return GitAllocator{
+ .alloc = alloc,
+ .allocs = std.AutoArrayHashMap(*anyopaque, []u8).init(alloc),
+ .mutex = std.Thread.Mutex{},
+ };
+ }
+
+ fn nalloc(self: *GitAllocator, size: usize) ?*anyopaque {
+ const frame = self.alloc.alloc(u8, size) catch return null;
+ self.allocs.put(frame.ptr, frame) catch return null;
+ return frame.ptr;
+ }
+
+ pub fn malloc(self: *GitAllocator, size: usize) ?*anyopaque {
+ self.mutex.lock();
+ defer self.mutex.unlock();
+ return self.nalloc(size);
+ }
+
+ pub fn realloc(self: *GitAllocator, nptr: ?*anyopaque, size: usize) ?*anyopaque {
+ self.mutex.lock();
+ defer self.mutex.unlock();
+
+ const ptr = nptr orelse return self.nalloc(size);
+
+ const frame = self.allocs.get(ptr) orelse return null;
+ if (!self.allocs.swapRemove(ptr)) {
+ @panic("failed to remove");
+ }
+
+ const new_frame = self.alloc.realloc(frame, size) catch return null;
+
+ self.allocs.put(new_frame.ptr, new_frame) catch return null;
+ return new_frame.ptr;
+ }
+
+ pub fn free(self: *GitAllocator, nptr: ?*anyopaque) void {
+ self.mutex.lock();
+ defer self.mutex.unlock();
+
+ const ptr = nptr orelse return;
+
+ const frame = self.allocs.get(ptr) orelse return;
+
+ defer self.alloc.free(frame);
+ if (!self.allocs.swapRemove(ptr)) {
+ @panic("failed to remove");
+ }
+ }
+
+ pub fn deinit(self: *GitAllocator) void {
+ self.allocs.deinit();
+ }
+};
+
+test "test git allocator" {
+ var gitAlloc = GitAllocator.init(testing.allocator);
+ defer gitAlloc.deinit();
+
+ var ptr = gitAlloc.malloc(2_000);
+
+ try testing.expect(ptr != null);
+
+ ptr = gitAlloc.realloc(ptr, 4_000);
+ ptr = gitAlloc.realloc(ptr, 1_000);
+
+ gitAlloc.free(ptr);
+}
diff --git a/src/root.zig b/src/root.zig
index 73222be..9552bc5 100644
--- a/src/root.zig
+++ b/src/root.zig
@@ -1,6 +1,7 @@
const std = @import("std");
const testing = std.testing;
const Allocator = std.mem.Allocator;
+const galloc = @import("galloc.zig");
const git = @cImport({
@cInclude("git2.h");
@@ -12,7 +13,41 @@ const GitError = error{
OpenError,
};
-pub fn initGit() GitError!void {
+const git_allocator = extern struct {
+ gmalloc: ?*const fn (size: usize, payload: ?*anyopaque) callconv(.C) ?*anyopaque,
+ grealloc: ?*const fn (ptr: ?*anyopaque, size: usize, payload: ?*anyopaque) callconv(.C) ?*anyopaque,
+ gfree: ?*const fn (ptr: ?*anyopaque) callconv(.C) void,
+};
+
+pub var alloc: galloc.GitAllocator = undefined;
+
+fn malloc(size: usize, _: ?*anyopaque) callconv(.C) ?*anyopaque {
+ std.debug.print("MALLOC {}\n", .{size});
+ return alloc.malloc(size);
+}
+
+fn relloc(ptr: ?*anyopaque, size: usize, _: ?*anyopaque) callconv(.C) ?*anyopaque {
+ std.debug.print("REALLOC {} {?}\n", .{ size, ptr });
+ const new_ptr = alloc.realloc(ptr, size);
+ return new_ptr;
+}
+
+fn free(ptr: ?*anyopaque) callconv(.C) void {
+ std.debug.print("FREE\n", .{});
+ alloc.free(ptr);
+}
+
+pub fn initGit(a: std.mem.Allocator) GitError!void {
+ alloc = galloc.GitAllocator.init(a);
+
+ const cAlloc = git_allocator{
+ .gmalloc = malloc,
+ .grealloc = relloc,
+ .gfree = free,
+ };
+
+ _ = git.git_libgit2_opts(git.GIT_OPT_SET_ALLOCATOR, &cAlloc);
+
const code = git.git_libgit2_init();
if (code < 0) {
return GitError.InitError;
@@ -20,6 +55,7 @@ pub fn initGit() GitError!void {
}
pub fn deInitGit() !void {
+ defer alloc.deinit();
const code = git.git_libgit2_shutdown();
if (code < 0) {
return GitError.DeinitError;
@@ -30,20 +66,20 @@ pub const Repository = struct {
allocator: Allocator = undefined,
repository: ?*git.git_repository = null,
- pub fn init(alloc: Allocator) !Repository {
+ pub fn init(a: Allocator) !Repository {
return Repository{
- .allocator = alloc,
+ .allocator = a,
};
}
- pub fn open(self: Repository, path: []const u8) GitError!void {
- const code = git.git_repository_open(@constCast(&self.repository), path.ptr);
+ pub fn open(self: *Repository, path: []const u8) GitError!void {
+ const code = git.git_repository_open(@ptrCast(&self.repository), path.ptr);
if (code < 0) {
return GitError.OpenError;
}
}
- pub fn deinit(self: Repository) !void {
+ pub fn deinit(self: *Repository) void {
if (self.repository) |repo| {
git.git_repository_free(repo);
}
@@ -51,15 +87,16 @@ pub const Repository = struct {
};
test "init deinit" {
- try initGit();
+ try initGit(testing.allocator);
try deInitGit();
}
test "open repository" {
- try initGit();
+ try initGit(testing.allocator);
var repository = try Repository.init(std.testing.allocator);
try repository.open(".");
+ repository.deinit();
try deInitGit();
}