const std = @import("std"); const mem = std.mem; const err = @import("libvirt-error.zig"); // Helper struct for allocating null-terminated strings pub const String = struct { allocator: mem.Allocator, slice: []u8, str: [:0]const u8, pub fn init(allocator: mem.Allocator, in_str: []const u8) !String { const str = try allocator.alloc(u8, in_str.len + 1); @memcpy(str[0..in_str.len], in_str); str[str.len - 1] = 0; return .{ .allocator = allocator, .slice = str, .str = @ptrCast(str), }; } pub fn deinit(self: *const String) void { self.allocator.free(self.slice); } }; fn string(str: [*c]const u8) []const u8 { return mem.span(str); } fn intFromFlags(comptime T: type, flags: []const T) c_uint { var flags_int: c_uint = 0; for (flags) |f| flags_int |= @intFromEnum(f); return flags_int; } fn Iterator(comptime T: type, comptime Ptr: type, comptime freeFn: *const fn (Ptr) callconv(.C) c_int) type { return struct { allocator: mem.Allocator, list: [*]Ptr, num: c_int, curr: usize, pub fn init( comptime PP: type, // Parent Pointer comptime P: type, // Parent comptime F: type, // Flags parent: *const P, flags: []const F, allocator: mem.Allocator, initFn: *const fn (?*PP, [*c][*c]Ptr, c_uint) callconv(.C) c_int, ) !Self { var list: [*]Ptr = undefined; const num = initFn(parent.ptr, @ptrCast(&list), intFromFlags(F, flags)); return if (num < 0) err.handleError() else .{ .allocator = allocator, .list = list, .num = num, .curr = 0, }; } pub fn deinit(self: *Self) void { var i: usize = 0; while (i < self.num) : (i += 1) _ = freeFn(self.list[i]); } pub fn first(self: *Self) T { self.curr = 0; // return .{ .ptr = self.list[self.curr], .arena = heap.ArenaAllocator.init(self.allocator) }; return T.init(self.list[self.curr], self.allocator); } pub fn next(self: *Self) ?T { if (self.curr >= self.num) return null; const ptr = self.list[self.curr]; self.curr += 1; // return .{ .ptr = ptr, .arena = heap.ArenaAllocator.init(self.allocator) }; return T.init(ptr, self.allocator); } const Self = @This(); }; } fn numOf( comptime P: type, ptr: P, fnPtr: *const fn (P) callconv(.C) c_int, ) !u32 { const num = fnPtr(ptr); return if (num < 0) err.handleError() else @intCast(num); }