// FileFinder.cxx #include "dataset_util/FileFinder.h" #include #include #include "dataset_util/getcwd.h" using std::ostream; using std::cout; using std::endl; typedef FileDirectory::Name Name; typedef FileDirectory::FileList FileList; typedef FileDirectory::DirectoryList DirectoryList; namespace { bool VERBOSE = false; } //********************************************************************** // Verbosity. void FileFinder::verbose(bool stat) { VERBOSE = stat; } //********************************************************************** // Constructor. FileFinder::FileFinder(Name dir, int height, int depth, int max_files) : m_dir(dir), m_height(height), m_depth(depth), m_max_files(max_files) { if ( height < 0 ) m_height = 1000000; if ( depth < 0 ) m_depth = 1000000; if ( max_files < 0 ) m_max_files = 1000000; } //********************************************************************** // Hide a subdirectory from file searches. void FileFinder::hide(Name name) { m_hidden_subdirs.push_back(name); } //********************************************************************** // Validity. bool FileFinder::is_valid() const { return m_dir.is_valid(); } //********************************************************************** // Find files and append to an existing list. // This is where the work is done. FileList& FileFinder::find_all(Name fname, FileList& files) const { if ( VERBOSE ) { cout << "Searching " << directory().name() << endl; } // Calculate the maximum size for the file list. unsigned int max_total_files = files.size() + max_files(); // For now name may not include any delimiters. // Exit if this is not the case. if ( fname.find(FileName::delimiter()) != Name::npos ) { return files; } // Check the current directory. if ( files.size() >= max_total_files ) return files; Name findfile = directory().find(fname); if ( findfile.size() ) { if ( VERBOSE ) { cout << " Found " << findfile << endl; } files.push_back(FileStatus(findfile)); } // Search subdirectories. if ( files.size() >= max_total_files ) return files; if ( depth() > 0 ) { const DirectoryList& subdirs = directory().subdirs(); for ( DirectoryList::const_iterator idir=subdirs.begin(); idir!=subdirs.end(); ++idir) { const FileDirectory& dir = *idir; // Skip directory if hidden. Name dirname = dir.name(); NameList::const_iterator iname = std::find(hidden_subdirs().begin(), hidden_subdirs().end(), dirname); if ( iname != hidden_subdirs().end() ) continue; // Calculate the max # files for subdirectory search. int maxf = max_total_files - files.size(); if ( maxf == 0 ) break; // Search subdirectory. FileFinder finder(dir.name(), 0, depth()-1, maxf); finder.find_all(fname, files); } } // Search parent directory. if ( files.size() >= max_total_files ) return files; if ( height() == 0 ) return files; Name pdirname = FileName(directory().name()).directory().name(); if ( pdirname.size() == 0 ) return files; int maxf = max_total_files - files.size(); if ( maxf <= 0 ) return files; FileFinder finder(pdirname, height()-1, depth()+1, maxf); finder.hide(directory().name()); finder.find_all(fname, files); // All done. return files; } //********************************************************************** // Find files in a new list. FileList FileFinder::find_all(Name name) const { FileList files; return find_all(name, files); } //********************************************************************** // Find the first file. Name FileFinder::find(Name name) const { if ( max_files() == 0 ) return ""; FileFinder finder(directory().name(), height(), depth(), 1); FileList files; finder.find_all(name, files); if ( files.size() == 0 ) return ""; return files.front().name(); } //********************************************************************** // Output stream. ostream& operator<<(ostream& lhs, const FileFinder& rhs) { if ( rhs.is_valid() ) { lhs << "File finder"; lhs << "\n Directory = " << rhs.directory().name(); lhs << "\n max height = " << rhs.height(); lhs << "\n max depth = " << rhs.depth(); lhs << "\n max files = " << rhs.max_files(); } else { lhs << "Invalid file finder"; lhs << "\n Directory = " << rhs.directory().name(); } lhs.flush(); return lhs; } //**********************************************************************