void Path::visit(VisitCallback callback, void *userData) const { if (!callback || !isDir()) return; Set<Path> seenDirs; visitorWrapper(*this, callback, seenDirs, userData); }
void Path::visit(const std::function<VisitResult(const Path &path)> &callback) const { if (!callback || !isDir()) return; Set<Path> seenDirs; visitorWrapper(*this, callback, seenDirs); }
static void visitorWrapper(Path path, Path::VisitCallback callback, Set<Path> &seen, void *userData) { if (!seen.insert(path.resolved())) { return; } DIR *d = opendir(path.constData()); if (!d) return; char buf[PATH_MAX + sizeof(dirent) + 1]; dirent *dbuf = reinterpret_cast<dirent*>(buf); dirent *p; if (!path.endsWith('/')) path.append('/'); const int s = path.size(); path.reserve(s + 128); List<String> recurseDirs; while (!readdir_r(d, dbuf, &p) && p) { if (!strcmp(p->d_name, ".") || !strcmp(p->d_name, "..")) continue; path.truncate(s); path.append(p->d_name); #if defined(_DIRENT_HAVE_D_TYPE) && defined(_BSD_SOURCE) if (p->d_type == DT_DIR) path.append('/'); #else if (path.isDir()) path.append('/'); #endif switch (callback(path, userData)) { case Path::Abort: p = 0; break; case Path::Recurse: if (path.isDir()) recurseDirs.append(p->d_name); break; case Path::Continue: break; } } closedir(d); const int count = recurseDirs.size(); for (int i=0; i<count; ++i) { path.truncate(s); path.append(recurseDirs.at(i)); visitorWrapper(path, callback, seen, userData); } }