iovec
This commit is contained in:
parent
787fbcf375
commit
b220dd92e3
@ -46,7 +46,7 @@ pub const Header = packed struct {
|
||||
nblocks_groupmembers: u64,
|
||||
nblocks_additional_gids: u64,
|
||||
|
||||
pub fn fromBytes(blob: [header_size]u8) InvalidHeader!Header {
|
||||
pub fn fromBytes(blob: []const u8) InvalidHeader!Header {
|
||||
const self = mem.bytesAsValue(Header, blob);
|
||||
|
||||
if (!mem.eql(magic, blob[0..4]))
|
||||
@ -64,7 +64,7 @@ pub const Header = packed struct {
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn asBytes(self: *const Header) [header_size]u8 {
|
||||
pub fn asBytes(self: *const Header) []const u8 {
|
||||
return mem.asBytes(self);
|
||||
}
|
||||
};
|
||||
|
@ -12,31 +12,31 @@ pub fn roundUp(comptime T: type, comptime nbits: u8, n: T) T {
|
||||
|
||||
// rounds up an integer to the nearest factor of nbits and returns the
|
||||
// difference (padding)
|
||||
pub fn roundUpPadding(comptime T: type, comptime nbits: u8, n: T) T {
|
||||
pub fn until(comptime T: type, comptime nbits: u8, n: T) T {
|
||||
return roundUp(T, nbits, n) - n;
|
||||
}
|
||||
|
||||
// arrayList adds padding to an ArrayList(u8) for a given number of nbits
|
||||
pub fn arrayList(arr: *ArrayList(u8), comptime nbits: u8) Allocator.Error!void {
|
||||
const padding = roundUpPadding(u64, nbits, arr.items.len);
|
||||
const padding = until(u64, nbits, arr.items.len);
|
||||
try arr.*.appendNTimes(0, padding);
|
||||
}
|
||||
|
||||
const testing = std.testing;
|
||||
|
||||
test "padding" {
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 0), 0);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 1), 3);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 2), 2);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 3), 1);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 4), 0);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 40), 0);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 41), 3);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 42), 2);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 43), 1);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 44), 0);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 4091), 1);
|
||||
try testing.expectEqual(roundUpPadding(u12, 2, 4092), 0);
|
||||
try testing.expectEqual(until(u12, 2, 0), 0);
|
||||
try testing.expectEqual(until(u12, 2, 1), 3);
|
||||
try testing.expectEqual(until(u12, 2, 2), 2);
|
||||
try testing.expectEqual(until(u12, 2, 3), 1);
|
||||
try testing.expectEqual(until(u12, 2, 4), 0);
|
||||
try testing.expectEqual(until(u12, 2, 40), 0);
|
||||
try testing.expectEqual(until(u12, 2, 41), 3);
|
||||
try testing.expectEqual(until(u12, 2, 42), 2);
|
||||
try testing.expectEqual(until(u12, 2, 43), 1);
|
||||
try testing.expectEqual(until(u12, 2, 44), 0);
|
||||
try testing.expectEqual(until(u12, 2, 4091), 1);
|
||||
try testing.expectEqual(until(u12, 2, 4092), 0);
|
||||
}
|
||||
|
||||
test "arrayList" {
|
||||
|
@ -1,4 +1,5 @@
|
||||
const std = @import("std");
|
||||
const os = std.os;
|
||||
const fmt = std.fmt;
|
||||
const mem = std.mem;
|
||||
const math = std.math;
|
||||
@ -6,6 +7,7 @@ const sort = std.sort;
|
||||
const assert = std.debug.assert;
|
||||
const unicode = std.unicode;
|
||||
const Allocator = std.mem.Allocator;
|
||||
const ArenaAllocator = std.heap.ArenaAllocator;
|
||||
const ArrayListUnmanaged = std.ArrayListUnmanaged;
|
||||
const ArrayList = std.ArrayList;
|
||||
const MultiArrayList = std.MultiArrayList;
|
||||
@ -30,8 +32,10 @@ const section_length = @import("header.zig").section_length;
|
||||
const cmph = @import("cmph.zig");
|
||||
const bdz = @import("bdz.zig");
|
||||
|
||||
const zeroes = &[_]u8{0} ** section_length;
|
||||
|
||||
const Corpus = struct {
|
||||
arena: std.heap.ArenaAllocator,
|
||||
arena: ArenaAllocator,
|
||||
|
||||
// sorted by name, by unicode codepoint
|
||||
users: MultiArrayList(User),
|
||||
@ -48,7 +52,7 @@ const Corpus = struct {
|
||||
usersConst: []const User,
|
||||
groupsConst: []const Group,
|
||||
) error{ OutOfMemory, InvalidUtf8, Duplicate, NotFound }!Corpus {
|
||||
var arena = std.heap.ArenaAllocator.init(baseAllocator);
|
||||
var arena = ArenaAllocator.init(baseAllocator);
|
||||
var allocator = arena.allocator();
|
||||
errdefer arena.deinit();
|
||||
|
||||
@ -100,8 +104,8 @@ const Corpus = struct {
|
||||
members.len = 0;
|
||||
|
||||
var it = groupmembers.iterator();
|
||||
while (it.next()) |memberName| {
|
||||
if (name2user.get(memberName.*)) |user_idx| {
|
||||
while (it.next()) |member_name| {
|
||||
if (name2user.get(member_name.*)) |user_idx| {
|
||||
members.len += 1;
|
||||
members[members.len - 1] = user_idx;
|
||||
try user2groups[user_idx].append(allocator, @intCast(u32, i));
|
||||
@ -429,7 +433,7 @@ pub const AllSections = struct {
|
||||
idx_groupname2group: []const u32,
|
||||
idx_uid2user: []const u32,
|
||||
idx_name2user: []const u32,
|
||||
header: Header,
|
||||
header: []const u8,
|
||||
|
||||
pub fn init(
|
||||
allocator: Allocator,
|
||||
@ -452,13 +456,13 @@ pub const AllSections = struct {
|
||||
const bdz_username = try cmph.packStr(allocator, unames);
|
||||
errdefer allocator.free(bdz_username);
|
||||
|
||||
var shell_sections = try shellSections(allocator, corpus);
|
||||
errdefer shell_sections.deinit();
|
||||
var shell = try shellSections(allocator, corpus);
|
||||
errdefer shell.deinit();
|
||||
|
||||
var additional_gids = try userGids(allocator, corpus);
|
||||
errdefer additional_gids.deinit(allocator);
|
||||
|
||||
var users = try usersSection(allocator, corpus, &additional_gids, &shell_sections);
|
||||
var users = try usersSection(allocator, corpus, &additional_gids, &shell);
|
||||
errdefer users.deinit(allocator);
|
||||
|
||||
var groupmembers = try groupMembers(allocator, corpus, users.idx2offset);
|
||||
@ -480,8 +484,8 @@ pub const AllSections = struct {
|
||||
errdefer allocator.free(idx_name2user);
|
||||
|
||||
const header = Header{
|
||||
.nblocks_shell_blob = nblocks(u8, shell_sections.blob.constSlice()),
|
||||
.num_shells = shell_sections.len,
|
||||
.nblocks_shell_blob = nblocks(u8, shell.blob.constSlice()),
|
||||
.num_shells = shell.len,
|
||||
.num_groups = groups.len,
|
||||
.num_users = users.len,
|
||||
.nblocks_bdz_gid = nblocks(u32, bdz_gid),
|
||||
@ -500,10 +504,10 @@ pub const AllSections = struct {
|
||||
.bdz_groupname = bdz_groupname,
|
||||
.bdz_uid = bdz_uid,
|
||||
.bdz_username = bdz_username,
|
||||
.shell_sections = shell_sections,
|
||||
.shell_sections = shell,
|
||||
.shell_reader = ShellReader.init(
|
||||
mem.sliceAsBytes(shell_sections.index.constSlice()),
|
||||
mem.sliceAsBytes(shell_sections.blob.constSlice()),
|
||||
mem.sliceAsBytes(shell.index.constSlice()),
|
||||
mem.sliceAsBytes(shell.blob.constSlice()),
|
||||
),
|
||||
.additional_gids = additional_gids,
|
||||
.users = users,
|
||||
@ -513,10 +517,50 @@ pub const AllSections = struct {
|
||||
.idx_groupname2group = idx_groupname2group,
|
||||
.idx_uid2user = idx_uid2user,
|
||||
.idx_name2user = idx_name2user,
|
||||
.header = header,
|
||||
.header = header.asBytes(),
|
||||
};
|
||||
}
|
||||
|
||||
pub fn iov(self: *const AllSections) error{OutOfMemory}![]os.iovec_const {
|
||||
const sections = &[_][]const u8{
|
||||
self.header,
|
||||
self.bdz_gid,
|
||||
self.bdz_groupname,
|
||||
self.bdz_uid,
|
||||
self.bdz_username,
|
||||
mem.sliceAsBytes(self.idx_gid2group),
|
||||
mem.sliceAsBytes(self.idx_groupname2group),
|
||||
mem.sliceAsBytes(self.idx_uid2user),
|
||||
mem.sliceAsBytes(self.idx_name2user),
|
||||
mem.sliceAsBytes(self.shell_sections.index.constSlice()),
|
||||
mem.sliceAsBytes(self.shell_sections.blob.constSlice()),
|
||||
self.groups.blob,
|
||||
self.users.blob,
|
||||
self.groupmembers.blob,
|
||||
self.additional_gids.blob,
|
||||
};
|
||||
var result = try ArrayList(os.iovec_const).initCapacity(
|
||||
self.allocator,
|
||||
sections.len * 2,
|
||||
);
|
||||
errdefer result.deinit();
|
||||
|
||||
for (sections) |section| {
|
||||
result.appendAssumeCapacity(os.iovec_const{
|
||||
.iov_base = section.ptr,
|
||||
.iov_len = section.len,
|
||||
});
|
||||
const padding = pad.until(usize, section_length_bits, section.len);
|
||||
if (padding != 0)
|
||||
result.appendAssumeCapacity(.{
|
||||
.iov_base = zeroes,
|
||||
.iov_len = padding,
|
||||
});
|
||||
}
|
||||
|
||||
return result.toOwnedSlice();
|
||||
}
|
||||
|
||||
pub fn deinit(self: *AllSections) void {
|
||||
self.allocator.free(self.bdz_gid);
|
||||
self.allocator.free(self.bdz_groupname);
|
||||
@ -689,6 +733,9 @@ test "test groups, group members and users" {
|
||||
try testing.expectEqualStrings(user.home, got.home());
|
||||
try testing.expectEqualStrings(user.shell, got.shell(sections.shell_reader));
|
||||
}
|
||||
|
||||
var iovec = try sections.iov();
|
||||
allocator.free(iovec);
|
||||
}
|
||||
|
||||
test "userGids" {
|
||||
@ -738,7 +785,7 @@ test "pack gids" {
|
||||
}
|
||||
|
||||
fn testUser(name: []const u8) User {
|
||||
var result = std.mem.zeroes(User);
|
||||
var result = mem.zeroes(User);
|
||||
result.name = name;
|
||||
return result;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user