replace users_arr and groups_arr with smaller arrays

RSS savings are trivial, it was not worth it.
This commit is contained in:
Motiejus Jakštys 2022-07-06 12:32:49 +03:00
parent 86d5c026be
commit 6c6d9d9c2c

View File

@ -40,35 +40,76 @@ pub fn init(
if (usersConst.len >= math.maxInt(u32)) return error.TooMany; if (usersConst.len >= math.maxInt(u32)) return error.TooMany;
if (groupsConst.len >= math.maxInt(u32)) return error.TooMany; if (groupsConst.len >= math.maxInt(u32)) return error.TooMany;
var users = MultiArrayList(User){};
var groups = MultiArrayList(Group){};
var getgr_bufsize: usize = 0;
var getpw_bufsize: usize = 0;
var arena = ArenaAllocator.init(baseAllocator); var arena = ArenaAllocator.init(baseAllocator);
var allocator = arena.allocator(); var allocator = arena.allocator();
errdefer arena.deinit(); errdefer arena.deinit();
var groups_arr = try allocator.alloc(Group, groupsConst.len); const NameIdx = struct {
var users_arr = try allocator.alloc(User, usersConst.len); name: []const u8,
idx: usize,
};
var getgr_bufsize: usize = 0; const GidIdx = struct {
for (groupsConst) |*group, i| { gid: u32,
groups_arr[i] = try group.clone(allocator); idx: usize,
getgr_bufsize = math.max(getgr_bufsize, group.strlenZ()); };
}
var getpw_bufsize: usize = 0; const Compare = struct {
for (usersConst) |*user, i| { fn name(_: void, a: NameIdx, b: NameIdx) bool {
users_arr[i] = try user.clone(allocator); var utf8_a = (unicode.Utf8View.init(a.name) catch unreachable).iterator();
getpw_bufsize = math.max(getpw_bufsize, user.strlenZ()); var utf8_b = (unicode.Utf8View.init(b.name) catch unreachable).iterator();
while (utf8_a.nextCodepoint()) |codepoint_a| {
if (utf8_b.nextCodepoint()) |codepoint_b| {
if (codepoint_a == codepoint_b) {
continue;
} else return codepoint_a < codepoint_b;
}
// a is a prefix of b. It is thus shorter.
return true;
}
// b is a prefix of a
return false;
}
fn gid(_: void, a: GidIdx, b: GidIdx) bool {
return a.gid < b.gid;
}
};
{
var name_idx = try baseAllocator.alloc(NameIdx, usersConst.len);
defer baseAllocator.free(name_idx);
for (usersConst) |user, i|
name_idx[i] = NameIdx{ .name = user.name, .idx = i };
sort.sort(NameIdx, name_idx, {}, Compare.name);
try users.ensureTotalCapacity(allocator, usersConst.len);
for (name_idx) |entry| {
const user = try usersConst[entry.idx].clone(allocator);
users.appendAssumeCapacity(user);
getpw_bufsize = math.max(getpw_bufsize, user.strlenZ());
}
} }
sort.sort(User, users_arr, {}, cmpUser); {
sort.sort(Group, groups_arr, {}, cmpGroup); var gid_idx = try baseAllocator.alloc(GidIdx, groupsConst.len);
defer baseAllocator.free(gid_idx);
for (groupsConst) |group, i|
gid_idx[i] = GidIdx{ .gid = group.gid, .idx = i };
sort.sort(GidIdx, gid_idx, {}, Compare.gid);
var users = MultiArrayList(User){}; try groups.ensureTotalCapacity(allocator, groupsConst.len);
try users.ensureTotalCapacity(allocator, users_arr.len); for (gid_idx) |entry| {
for (users_arr) |user| const group = try groupsConst[entry.idx].clone(allocator);
users.appendAssumeCapacity(user); groups.appendAssumeCapacity(group);
var groups = MultiArrayList(Group){}; getgr_bufsize = math.max(getgr_bufsize, group.strlenZ());
try groups.ensureTotalCapacity(allocator, groups_arr.len); }
for (groups_arr) |group| }
groups.appendAssumeCapacity(group);
// verify whatever comes to cmph are unique: user names // verify whatever comes to cmph are unique: user names
var name2user = StringHashMap(u32).init(allocator); var name2user = StringHashMap(u32).init(allocator);
@ -167,28 +208,6 @@ pub fn deinit(self: *Corpus) void {
self.* = undefined; self.* = undefined;
} }
// cmpUser compares two users for sorting. By username's utf8 codepoints, ascending.
fn cmpUser(_: void, a: User, b: User) bool {
var utf8_a = (unicode.Utf8View.init(a.name) catch unreachable).iterator();
var utf8_b = (unicode.Utf8View.init(b.name) catch unreachable).iterator();
while (utf8_a.nextCodepoint()) |codepoint_a| {
if (utf8_b.nextCodepoint()) |codepoint_b| {
if (codepoint_a == codepoint_b) {
continue;
} else return codepoint_a < codepoint_b;
}
// a is a prefix of b. It is thus shorter.
return true;
}
// b is a prefix of a
return false;
}
fn cmpGroup(_: void, a: Group, b: Group) bool {
return a.gid < b.gid;
}
fn testUser(name: []const u8) User { fn testUser(name: []const u8) User {
var result = mem.zeroes(User); var result = mem.zeroes(User);
result.name = name; result.name = name;
@ -198,18 +217,6 @@ fn testUser(name: []const u8) User {
const testing = std.testing; const testing = std.testing;
const someMembers = @import("Group.zig").someMembers; const someMembers = @import("Group.zig").someMembers;
test "users compare function" {
const a = testUser("a");
const b = testUser("b");
const bb = testUser("bb");
try testing.expect(cmpUser({}, a, b));
try testing.expect(!cmpUser({}, b, a));
try testing.expect(cmpUser({}, a, bb));
try testing.expect(!cmpUser({}, bb, a));
try testing.expect(cmpUser({}, bb, b));
try testing.expect(!cmpUser({}, b, bb));
}
pub fn testCorpus(allocator: Allocator) !Corpus { pub fn testCorpus(allocator: Allocator) !Corpus {
const users = [_]User{ User{ const users = [_]User{ User{
.uid = 0, .uid = 0,