turbonss/lib/Group.zig

69 lines
2.0 KiB
Zig
Raw Normal View History

const std = @import("std");
const mem = std.mem;
const Allocator = mem.Allocator;
const Group = @This();
gid: u32,
name: [:0]const u8,
// should be [:null]const ?[:0]const u8, but it crashes the compiler. See
// https://github.com/ziglang/zig/issues/7517.
// members[members.len] is always null for cloned groups. Once the bug
// in the compiler is fixed, we should update the return type here.
members: []const ?[:0]const u8,
pub fn clone(self: *const Group, allocator: Allocator) Allocator.Error!Group {
var members = try allocator.alloc(?[:0]const u8, self.members.len + 1);
2022-03-26 12:06:07 +02:00
errdefer allocator.free(members);
members.len = self.members.len + 1;
2022-03-26 12:06:07 +02:00
for (self.members) |member, i| {
members[i] = try allocator.dupeZ(u8, member.?);
errdefer allocator.free(members[i]);
2022-03-26 12:06:07 +02:00
}
2022-04-07 12:23:50 +03:00
// workaround to include a null value at the end, even for
// non-sentinel-terminated slice type.
members[self.members.len] = null;
members.len = self.members.len;
2022-03-26 12:06:07 +02:00
return Group{
.gid = self.gid,
.name = try allocator.dupeZ(u8, self.name),
2022-03-26 12:06:07 +02:00
.members = members,
};
}
pub fn deinit(self: *Group, allocator: Allocator) void {
allocator.free(self.name);
for (self.members) |member| {
allocator.free(member.?);
}
2022-03-26 12:06:07 +02:00
allocator.free(self.members);
self.* = undefined;
}
const testing = std.testing;
test "Group.clone" {
2022-03-26 12:06:07 +02:00
// TODO: how to do this on stack?
var member1 = try testing.allocator.dupeZ(u8, "member1");
2022-03-26 12:06:07 +02:00
defer testing.allocator.free(member1);
2022-03-26 12:06:07 +02:00
var group = Group{
.gid = 1,
.name = "foo",
.members = &[_:null]?[:0]const u8{ member1, "member2" },
2022-03-26 12:06:07 +02:00
};
2022-03-26 12:06:07 +02:00
var cloned = try group.clone(testing.allocator);
defer cloned.deinit(testing.allocator);
2022-03-26 12:06:07 +02:00
group.gid = 2;
group.name = "bar";
member1[0] = 'x';
try testing.expectEqual(cloned.gid, 1);
try testing.expectEqualSlices(u8, cloned.name, "foo");
try testing.expectEqualSlices(u8, cloned.members[0].?, "member1");
}