1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69
|
#include "main.ih"
inline bool accept(DirEntry const &entry)
{
return entry.d_name != "."s and entry.d_name != ".."s;
}
// yield all `DirEntry`s contained in the particular `path` (as long as it
// is a directory)
// if (not dirPtr)
// co_return;
// removed from 'dirEntries' after calling opendir: like Dir, let's assume
// that the demo allows us to assume that opendir succeeds.
//+dir
Generator<DirEntry> dirEntries(char const *path)
{
DIR *dirPtr = opendir(path);
while (auto entry = readdir(dirPtr))
{
if (accept(*entry))
co_yield *entry;
}
closedir(dirPtr);
}
//+dir
// keep track of the _full_ path rather than only the entry's own name
//+path
Generator<Pair> dirPathEntries(char const *path)
{
for (auto const &entry: dirEntries(path))
co_yield make_pair(entry,
(string{path} + '/' + entry.d_name).c_str());
}
//+path
// Recursively visit the directory tree:
// yield all entries in the current directory and if an entry is
// a directory, recursively handle that directory
//+allentries
RecursiveGenerator<Pair> visitAllEntries(char const *path)
{
for (auto &entry_pair: dirPathEntries(path))
{
co_yield entry_pair;
auto [entry, entry_path] = entry_pair;
if (entry.d_type == DT_DIR)
co_yield visitAllEntries(entry_path);
}
}
//+allentries
// Run this program with a directory path as single argument
// (it defaults to `.`, i.e., the current directory).
// It (recursively lists all files and directories in that directory
//main
int main(int argc, char **argv)
{
char const *path = argc == 1 ? "." : argv[1];
for (auto [entry, entryPath ]: visitAllEntries(path))
cout << entryPath << '\n';
}
//=
|