make Group.members an array with sentinel

Triggers a bug in the compiler, similar to
https://github.com/ziglang/zig/issues/7517
This commit is contained in:
Motiejus Jakštys 2022-04-03 14:48:53 +03:00 committed by Motiejus Jakštys
parent 34049d13f0
commit 5704deb6b3
2 changed files with 18 additions and 28 deletions

View File

@ -86,7 +86,7 @@ pub fn init(
members.len = 0; members.len = 0;
for (groupmembers) |member_name| { for (groupmembers) |member_name| {
if (name2user.get(member_name)) |user_idx| { if (name2user.get(member_name.?)) |user_idx| {
members.len += 1; members.len += 1;
members[members.len - 1] = user_idx; members[members.len - 1] = user_idx;
try user2groups[user_idx].append(allocator, @intCast(u32, i)); try user2groups[user_idx].append(allocator, @intCast(u32, i));
@ -203,10 +203,10 @@ pub fn testCorpus(allocator: Allocator) !Corpus {
.shell = "/usr/sbin/nologin", .shell = "/usr/sbin/nologin",
} }; } };
var members0 = &[_][]const u8{"root"}; var members0 = &[_:null]?[:0]const u8{"root"};
var members1 = &[_][]const u8{"vidmantas"}; var members1 = &[_:null]?[:0]const u8{"vidmantas"};
var members2 = &[_][]const u8{ "svc-bar", "vidmantas" }; var members2 = &[_:null]?[:0]const u8{ "svc-bar", "vidmantas" };
var members3 = &[_][]const u8{ "svc-bar", "Name" ** 8, "vidmantas", "root" }; var members3 = &[_:null]?[:0]const u8{ "svc-bar", "Name" ** 8, "vidmantas", "root" };
const groups = [_]Group{ const groups = [_]Group{
Group{ .gid = 0, .name = "root", .members = members0 }, Group{ .gid = 0, .name = "root", .members = members0 },

View File

@ -6,43 +6,33 @@ const Allocator = mem.Allocator;
const Group = @This(); const Group = @This();
gid: u32, gid: u32,
name: []const u8, name: [:0]const u8,
members: []const []const u8, //
_members_buf: []const u8 = undefined, members: [:null]const ?[:0]const u8,
pub fn clone(self: *const Group, allocator: Allocator) Allocator.Error!Group { pub fn clone(self: *const Group, allocator: Allocator) Allocator.Error!Group {
const total_members_len = blk: { var members = try allocator.allocSentinel(?[:0]const u8, self.members.len, null);
var sum: usize = 0;
for (self.members) |member| sum += member.len;
break :blk sum;
};
var members = try allocator.alloc([]const u8, self.members.len);
errdefer allocator.free(members); errdefer allocator.free(members);
members.len = self.members.len; members.len = self.members.len;
var buf = try allocator.alloc(u8, total_members_len);
errdefer allocator.free(buf);
buf.len = 0;
for (self.members) |member, i| { for (self.members) |member, i| {
const old_len = buf.len; const member_name = member.?;
buf.len += member.len; members[i] = try allocator.dupeZ(u8, member_name);
mem.copy(u8, buf[old_len..], member);
members[i] = buf[old_len..buf.len];
} }
return Group{ return Group{
.gid = self.gid, .gid = self.gid,
.name = try allocator.dupe(u8, self.name), .name = try allocator.dupeZ(u8, self.name),
.members = members, .members = members,
._members_buf = buf,
}; };
} }
pub fn deinit(self: *Group, allocator: Allocator) void { pub fn deinit(self: *Group, allocator: Allocator) void {
allocator.free(self.name); allocator.free(self.name);
for (self.members) |member| {
allocator.free(member.?);
}
allocator.free(self.members); allocator.free(self.members);
allocator.free(self._members_buf);
self.* = undefined; self.* = undefined;
} }
@ -50,13 +40,13 @@ const testing = std.testing;
test "Group.clone" { test "Group.clone" {
// TODO: how to do this on stack? // TODO: how to do this on stack?
var member1 = try testing.allocator.dupe(u8, "member1"); var member1 = try testing.allocator.dupeZ(u8, "member1");
defer testing.allocator.free(member1); defer testing.allocator.free(member1);
var group = Group{ var group = Group{
.gid = 1, .gid = 1,
.name = "foo", .name = "foo",
.members = &[_][]const u8{ member1, "member2" }, .members = &[_:null]?[:0]const u8{ member1, "member2", null },
}; };
var cloned = try group.clone(testing.allocator); var cloned = try group.clone(testing.allocator);
@ -67,5 +57,5 @@ test "Group.clone" {
member1[0] = 'x'; member1[0] = 'x';
try testing.expectEqual(cloned.gid, 1); try testing.expectEqual(cloned.gid, 1);
try testing.expectEqualSlices(u8, cloned.name, "foo"); try testing.expectEqualSlices(u8, cloned.name, "foo");
try testing.expectEqualSlices(u8, cloned.members[0], "member1"); try testing.expectEqualSlices(u8, cloned.members[0].?, "member1");
} }