Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 19 additions & 12 deletions Sources/ContainerizationEXT4/EXT4+FileTree.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ extension EXT4 {
class FileTreeNode {
let inode: InodeNumber
let name: String
var children: [Ptr<FileTreeNode>] = []
private(set) var children: [Ptr<FileTreeNode>] = []
// Name index of `children` for O(1) lookup, maintained by addChild/removeChild.
private(set) var childIndex: [String: Ptr<FileTreeNode>] = [:]
var blocks: (start: UInt32, end: UInt32)?
var additionalBlocks: [(start: UInt32, end: UInt32)]?
var link: InodeNumber?
Expand All @@ -39,16 +41,19 @@ extension EXT4 {
) {
self.inode = inode
self.name = name
self.children = children
self.blocks = blocks
self.additionalBlocks = additionalBlocks
self.link = link
self.parent = parent
for child in children {
self.addChild(child)
}
}

deinit {
self.children.removeAll()
self.children = []
self.childIndex.removeAll()
self.blocks = nil
self.additionalBlocks = nil
self.link = nil
Expand All @@ -64,6 +69,16 @@ extension EXT4 {
let path = components.reversed().joined(separator: "/")
return FilePath(path).lexicallyNormalized()
}

func addChild(_ child: Ptr<FileTreeNode>) {
children.append(child)
childIndex[child.pointee.name] = child
}

func removeChild(named name: String) {
children.removeAll { $0.pointee.name == name }
childIndex[name] = nil
}
}

var root: Ptr<FileTreeNode>
Expand All @@ -82,18 +97,10 @@ extension EXT4 {
return node
}
for component in components {
var found = false
for childPtr in node.pointee.children {
let child = childPtr.pointee
if child.name == component {
node = childPtr
found = true
break
}
}
guard found else {
guard let childPtr = node.pointee.childIndex[component] else {
return nil
}
node = childPtr
}
return node
}
Expand Down
8 changes: 3 additions & 5 deletions Sources/ContainerizationEXT4/EXT4+Formatter.swift
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ extension EXT4 {
blocks: nil,
link: targetNode.inode
))
parentTreeNode.children.append(linkTreeNodePtr)
parentTreeNode.addChild(linkTreeNodePtr)
parentTreeNodePtr.pointee = parentTreeNode
}

Expand Down Expand Up @@ -254,9 +254,7 @@ extension EXT4 {
}
}
parentInodePtr.pointee = parentInode
parentNode.children.removeAll { childPtr in
childPtr.pointee.name == pathComponent
}
parentNode.removeChild(named: pathComponent)
parentNodePtr.pointee = parentNode

if let hardlink = pathNode.link {
Expand Down Expand Up @@ -412,7 +410,7 @@ extension EXT4 {
children: [],
blocks: (startBlock, endBlock)
))
parentTreeNode.children.append(childTreeNodePtr)
parentTreeNode.addChild(childTreeNodePtr)
parentTreeNodePtr.pointee = parentTreeNode
}
childInode.mode = mode
Expand Down
2 changes: 1 addition & 1 deletion Sources/ContainerizationEXT4/EXT4+Reader.swift
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ extension EXT4 {
itemTreeNode.blocks = blocks.first
}
let itemTreeNodePtr = Ptr(itemTreeNode)
root.children.append(itemTreeNodePtr)
root.addChild(itemTreeNodePtr)
itemPtr.pointee = root
let itemInode = try self.getInode(number: itemInodeNum)
if itemInode.mode.isDir() {
Expand Down
10 changes: 5 additions & 5 deletions Tests/ContainerizationEXT4Tests/TestEXT4Reader+IO.swift
Original file line number Diff line number Diff line change
Expand Up @@ -617,10 +617,10 @@ struct EXT4PathIOTests {
let tree = EXT4.FileTree(EXT4.RootInode, "/")

let dirPtr = EXT4.Ptr(EXT4.FileTree.FileTreeNode(inode: 3, name: "dir", parent: tree.root))
tree.root.pointee.children.append(dirPtr)
tree.root.pointee.addChild(dirPtr)

let filePtr = EXT4.Ptr(EXT4.FileTree.FileTreeNode(inode: 4, name: "file", parent: dirPtr))
dirPtr.pointee.children.append(filePtr)
dirPtr.pointee.addChild(filePtr)

#expect(dirPtr.pointee.path == FilePath("/dir"))
#expect(filePtr.pointee.path == FilePath("/dir/file"))
Expand All @@ -631,10 +631,10 @@ struct EXT4PathIOTests {
let tree = EXT4.FileTree(EXT4.RootInode, ".")

let dirPtr = EXT4.Ptr(EXT4.FileTree.FileTreeNode(inode: 3, name: "dir", parent: tree.root))
tree.root.pointee.children.append(dirPtr)
tree.root.pointee.addChild(dirPtr)

let filePtr = EXT4.Ptr(EXT4.FileTree.FileTreeNode(inode: 4, name: "file", parent: dirPtr))
dirPtr.pointee.children.append(filePtr)
dirPtr.pointee.addChild(filePtr)

#expect(dirPtr.pointee.path == FilePath("dir"))
#expect(filePtr.pointee.path == FilePath("dir/file"))
Expand All @@ -645,7 +645,7 @@ struct EXT4PathIOTests {
let tree = EXT4.FileTree(EXT4.RootInode, "dir")

let filePtr = EXT4.Ptr(EXT4.FileTree.FileTreeNode(inode: 3, name: "file", parent: tree.root))
tree.root.pointee.children.append(filePtr)
tree.root.pointee.addChild(filePtr)

#expect(filePtr.pointee.path == FilePath("dir/file"))
}
Expand Down