mirror of
https://code.blicky.net/yorhel/ncdu.git
synced 2026-01-13 01:08:41 -09:00
Slightly less hacky Entry struct allocation and initialization
This commit is contained in:
parent
91281ef11f
commit
890e5a4af7
2 changed files with 52 additions and 56 deletions
|
|
@ -33,8 +33,8 @@ pub const Blocks = u60;
|
||||||
// performance.
|
// performance.
|
||||||
pub const Entry = extern struct {
|
pub const Entry = extern struct {
|
||||||
pack: Packed align(1),
|
pack: Packed align(1),
|
||||||
size: u64 align(1),
|
size: u64 align(1) = 0,
|
||||||
next: ?*Entry align(1),
|
next: ?*Entry align(1) = null,
|
||||||
|
|
||||||
pub const Packed = packed struct(u64) {
|
pub const Packed = packed struct(u64) {
|
||||||
etype: EType,
|
etype: EType,
|
||||||
|
|
@ -43,8 +43,8 @@ pub const Entry = extern struct {
|
||||||
// Counting of Link entries is deferred until the scan/delete operation has
|
// Counting of Link entries is deferred until the scan/delete operation has
|
||||||
// completed, so for those entries this flag indicates an intention to be
|
// completed, so for those entries this flag indicates an intention to be
|
||||||
// counted.
|
// counted.
|
||||||
counted: bool,
|
counted: bool = false,
|
||||||
blocks: Blocks, // 512-byte blocks
|
blocks: Blocks = 0, // 512-byte blocks
|
||||||
};
|
};
|
||||||
|
|
||||||
const Self = @This();
|
const Self = @This();
|
||||||
|
|
@ -67,17 +67,13 @@ pub const Entry = extern struct {
|
||||||
return if (self.file()) |f| f.pack.other_fs or f.pack.kernfs else self.pack.etype == .dir;
|
return if (self.file()) |f| f.pack.other_fs or f.pack.kernfs else self.pack.etype == .dir;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn nameOffset(etype: EType) usize {
|
|
||||||
return switch (etype) {
|
|
||||||
.dir => @offsetOf(Dir, "name"),
|
|
||||||
.link => @offsetOf(Link, "name"),
|
|
||||||
.file => @offsetOf(File, "name"),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn name(self: *const Self) [:0]const u8 {
|
pub fn name(self: *const Self) [:0]const u8 {
|
||||||
const ptr = @ptrCast([*:0]const u8, self) + nameOffset(self.pack.etype); // TODO: ptrCast the 'name' field instead.
|
const ptr = switch (self.pack.etype) {
|
||||||
return std.mem.sliceTo(ptr, 0);
|
.dir => &@ptrCast(*const Dir, self).name,
|
||||||
|
.link => &@ptrCast(*const Link, self).name,
|
||||||
|
.file => &@ptrCast(*const File, self).name,
|
||||||
|
};
|
||||||
|
return std.mem.sliceTo(@ptrCast([*:0]const u8, ptr), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ext(self: *Self) ?*Ext {
|
pub fn ext(self: *Self) ?*Ext {
|
||||||
|
|
@ -85,24 +81,31 @@ pub const Entry = extern struct {
|
||||||
return @ptrCast(*Ext, @ptrCast([*]Ext, self) - 1);
|
return @ptrCast(*Ext, @ptrCast([*]Ext, self) - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(etype: EType, isext: bool, ename: []const u8) *Entry {
|
fn alloc(comptime T: type, etype: EType, isext: bool, ename: []const u8) *Entry {
|
||||||
const extsize = if (isext) @as(usize, @sizeOf(Ext)) else 0;
|
const size = (if (isext) @as(usize, @sizeOf(Ext)) else 0) + @sizeOf(T) + ename.len + 1;
|
||||||
const size = nameOffset(etype) + ename.len + 1 + extsize;
|
var ptr = blk: while (true) {
|
||||||
var ptr = blk: {
|
if (allocator.allocWithOptions(u8, size, 1, null)) |p| break :blk p
|
||||||
while (true) {
|
|
||||||
if (allocator.allocWithOptions(u8, size, 1, null)) |p|
|
|
||||||
break :blk p
|
|
||||||
else |_| {}
|
else |_| {}
|
||||||
ui.oom();
|
ui.oom();
|
||||||
}
|
|
||||||
};
|
};
|
||||||
std.mem.set(u8, ptr, 0); // kind of ugly, but does the trick
|
if (isext) {
|
||||||
var e = @ptrCast(*Entry, ptr.ptr + extsize);
|
@ptrCast(*Ext, ptr).* = .{};
|
||||||
e.pack.etype = etype;
|
ptr = ptr[@sizeOf(Ext)..];
|
||||||
e.pack.isext = isext;
|
}
|
||||||
var name_ptr = @ptrCast([*]u8, e) + nameOffset(etype);
|
const e = @ptrCast(*T, ptr);
|
||||||
std.mem.copy(u8, name_ptr[0..ename.len], ename);
|
e.* = .{ .entry = .{ .pack = .{ .etype = etype, .isext = isext } } };
|
||||||
return e;
|
const n = @ptrCast([*]u8, &e.name)[0..ename.len+1];
|
||||||
|
std.mem.copy(u8, n, ename);
|
||||||
|
n[ename.len] = 0;
|
||||||
|
return &e.entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn create(etype: EType, isext: bool, ename: []const u8) *Entry {
|
||||||
|
return switch (etype) {
|
||||||
|
.dir => alloc(Dir, etype, isext, ename),
|
||||||
|
.file => alloc(File, etype, isext, ename),
|
||||||
|
.link => alloc(Link, etype, isext, ename),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the 'err' flag on Dirs and Files, propagating 'suberr' to parents.
|
// Set the 'err' flag on Dirs and Files, propagating 'suberr' to parents.
|
||||||
|
|
@ -219,29 +222,29 @@ const DevId = u30; // Can be reduced to make room for more flags in Dir.Packed.
|
||||||
pub const Dir = extern struct {
|
pub const Dir = extern struct {
|
||||||
entry: Entry,
|
entry: Entry,
|
||||||
|
|
||||||
sub: ?*Entry align(1),
|
sub: ?*Entry align(1) = null,
|
||||||
parent: ?*Dir align(1),
|
parent: ?*Dir align(1) = null,
|
||||||
|
|
||||||
// entry.{blocks,size}: Total size of all unique files + dirs. Non-shared hardlinks are counted only once.
|
// entry.{blocks,size}: Total size of all unique files + dirs. Non-shared hardlinks are counted only once.
|
||||||
// (i.e. the space you'll need if you created a filesystem with only this dir)
|
// (i.e. the space you'll need if you created a filesystem with only this dir)
|
||||||
// shared_*: Unique hardlinks that still have references outside of this directory.
|
// shared_*: Unique hardlinks that still have references outside of this directory.
|
||||||
// (i.e. the space you won't reclaim by deleting this dir)
|
// (i.e. the space you won't reclaim by deleting this dir)
|
||||||
// (space reclaimed by deleting a dir =~ entry. - shared_)
|
// (space reclaimed by deleting a dir =~ entry. - shared_)
|
||||||
shared_blocks: u64 align(1),
|
shared_blocks: u64 align(1) = 0,
|
||||||
shared_size: u64 align(1),
|
shared_size: u64 align(1) = 0,
|
||||||
items: u32 align(1),
|
items: u32 align(1) = 0,
|
||||||
|
|
||||||
pack: Packed align(1),
|
pack: Packed align(1) = .{},
|
||||||
|
|
||||||
// Only used to find the @offsetOff, the name is written at this point as a 0-terminated string.
|
// Only used to find the @offsetOff, the name is written at this point as a 0-terminated string.
|
||||||
// (Old C habits die hard)
|
// (Old C habits die hard)
|
||||||
name: [0]u8,
|
name: [0]u8 = undefined,
|
||||||
|
|
||||||
pub const Packed = packed struct {
|
pub const Packed = packed struct {
|
||||||
// Indexes into the global 'devices.list' array
|
// Indexes into the global 'devices.list' array
|
||||||
dev: DevId,
|
dev: DevId = 0,
|
||||||
err: bool,
|
err: bool = false,
|
||||||
suberr: bool,
|
suberr: bool = false,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn fmtPath(self: *const @This(), withRoot: bool, out: *std.ArrayList(u8)) void {
|
pub fn fmtPath(self: *const @This(), withRoot: bool, out: *std.ArrayList(u8)) void {
|
||||||
|
|
@ -266,11 +269,11 @@ pub const Dir = extern struct {
|
||||||
// File that's been hardlinked (i.e. nlink > 1)
|
// File that's been hardlinked (i.e. nlink > 1)
|
||||||
pub const Link = extern struct {
|
pub const Link = extern struct {
|
||||||
entry: Entry,
|
entry: Entry,
|
||||||
parent: *Dir align(1),
|
parent: *Dir align(1) = undefined,
|
||||||
next: *Link align(1), // Singly circular linked list of all *Link nodes with the same dev,ino.
|
next: *Link align(1) = undefined, // Singly circular linked list of all *Link nodes with the same dev,ino.
|
||||||
// dev is inherited from the parent Dir
|
// dev is inherited from the parent Dir
|
||||||
ino: u64 align(1),
|
ino: u64 align(1) = undefined,
|
||||||
name: [0]u8,
|
name: [0]u8 = undefined,
|
||||||
|
|
||||||
// Return value should be freed with main.allocator.
|
// Return value should be freed with main.allocator.
|
||||||
pub fn path(self: @This(), withRoot: bool) [:0]const u8 {
|
pub fn path(self: @This(), withRoot: bool) [:0]const u8 {
|
||||||
|
|
@ -285,8 +288,8 @@ pub const Link = extern struct {
|
||||||
// Anything that's not an (indexed) directory or hardlink. Excluded directories are also "Files".
|
// Anything that's not an (indexed) directory or hardlink. Excluded directories are also "Files".
|
||||||
pub const File = extern struct {
|
pub const File = extern struct {
|
||||||
entry: Entry,
|
entry: Entry,
|
||||||
pack: Packed,
|
pack: Packed = .{},
|
||||||
name: [0]u8,
|
name: [0]u8 = undefined,
|
||||||
|
|
||||||
pub const Packed = packed struct(u8) {
|
pub const Packed = packed struct(u8) {
|
||||||
err: bool = false,
|
err: bool = false,
|
||||||
|
|
@ -296,10 +299,6 @@ pub const File = extern struct {
|
||||||
notreg: bool = false,
|
notreg: bool = false,
|
||||||
_pad: u3 = 0, // Make this struct "ABI sized" to allow inclusion in an extern struct
|
_pad: u3 = 0, // Make this struct "ABI sized" to allow inclusion in an extern struct
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn resetFlags(f: *@This()) void {
|
|
||||||
f.pack = .{};
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const Ext = extern struct {
|
pub const Ext = extern struct {
|
||||||
|
|
|
||||||
|
|
@ -163,7 +163,7 @@ const ScanDir = struct {
|
||||||
e.pack.blocks = 0;
|
e.pack.blocks = 0;
|
||||||
e.addStats(self.dir, 0);
|
e.addStats(self.dir, 0);
|
||||||
}
|
}
|
||||||
e.file().?.resetFlags();
|
e.file().?.pack = .{};
|
||||||
_ = self.entries.removeAdapted(@as(?*model.Entry,null), HashContext{ .cmp = name });
|
_ = self.entries.removeAdapted(@as(?*model.Entry,null), HashContext{ .cmp = name });
|
||||||
break :blk e;
|
break :blk e;
|
||||||
} else e.delStatsRec(self.dir);
|
} else e.delStatsRec(self.dir);
|
||||||
|
|
@ -218,10 +218,7 @@ const ScanDir = struct {
|
||||||
d.parent = self.dir;
|
d.parent = self.dir;
|
||||||
d.pack.dev = model.devices.getId(stat.dev);
|
d.pack.dev = model.devices.getId(stat.dev);
|
||||||
}
|
}
|
||||||
if (e.file()) |f| {
|
if (e.file()) |f| f.pack = .{ .notreg = !stat.dir and !stat.reg };
|
||||||
f.resetFlags();
|
|
||||||
f.pack.notreg = !stat.dir and !stat.reg;
|
|
||||||
}
|
|
||||||
if (e.link()) |l| l.ino = stat.ino;
|
if (e.link()) |l| l.ino = stat.ino;
|
||||||
if (e.ext()) |ext| {
|
if (e.ext()) |ext| {
|
||||||
if (ext.mtime > stat.ext.mtime)
|
if (ext.mtime > stat.ext.mtime)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue