commit: 4a0166e23b319388c7356c88a3ca2851b7438395
parent 074b50fa51aebb4378bc1e50fac94a4332bd6643
Author: Drew DeVault <sir@cmpwn.com>
Date: Fri, 18 Feb 2022 10:26:16 +0100
Use os::iter instead of os::readdir
This should be faster and more memory efficient, especially for large
directories, as it skips an allocation and allows the tool to work
incrementally. It also addresses a memory leak in the previous version;
the caller must free the return value of os::readdir.
Diffstat:
M | main.ha | 28 | +++++++++++++++++----------- |
1 file changed, 17 insertions(+), 11 deletions(-)
diff --git a/main.ha b/main.ha
@@ -90,19 +90,25 @@ fn is_excluded(filename: str) bool = {
};
fn check_dir(dirname: str, ignoring: bool) (ok | invalid) = {
- const dir_ls = match (os::readdir(dirname)) {
- case let d: []fs::dirent =>
- yield d;
- case let e: fs::error =>
- fmt::errorf("os::readdir({}): {}\n", dirname, fs::strerror(e))!;
+ const iter = match (os::iter(dirname)) {
+ case let iter: *fs::iterator =>
+ yield iter;
+ case let err: fs::error =>
+ fmt::errorf("os::iter({}): {}\n", dirname, fs::strerror(err))!;
return invalid;
};
- for (let i = 0z; i < len(dir_ls); i += 1) {
- const file = dir_ls[i];
- const filename = path::join(dirname, file.name);
+ for (true) {
+ const ent = match (fs::next(iter)) {
+ case let ent: fs::dirent =>
+ yield ent;
+ case void =>
+ break;
+ };
+
+ const filename = path::join(dirname, ent.name);
- if (file.name == "." || file.name == "..") {
+ if (ent.name == "." || ent.name == "..") {
continue;
};
@@ -110,9 +116,9 @@ fn check_dir(dirname: str, ignoring: bool) (ok | invalid) = {
ignoring = is_excluded(filename);
};
- if(fs::isdir(file.ftype)) {
+ if (fs::isdir(ent.ftype)) {
check_dir(filename, ignoring): void;
- } else if(fs::isfile(file.ftype)) {
+ } else if(fs::isfile(ent.ftype)) {
const is_blob = match (is_blob(filename)) {
case let b: bool =>
yield b;