diff options
author | Alex Turbov <i.zaufi@gmail.com> | 2022-07-04 23:40:57 (GMT) |
---|---|---|
committer | Brad King <brad.king@kitware.com> | 2022-08-02 13:46:52 (GMT) |
commit | fdd14b1744c13f500000440de11cc27557432766 (patch) | |
tree | f8f584ecaada64934d9b66feb6cce0043c6481df | |
parent | 08e7fb3cfa80775ea8e50862180e4c3da6af9717 (diff) | |
download | CMake-fdd14b1744c13f500000440de11cc27557432766.zip CMake-fdd14b1744c13f500000440de11cc27557432766.tar.gz CMake-fdd14b1744c13f500000440de11cc27557432766.tar.bz2 |
cmFindPackageCommand: Deduplicate directory listing code
The `cmFileListGeneratorProject` and `cmFileListGeneratorMacProject`
was look very similar 'cept few lines.
Now they have a base class and the generator-specific logic has moved
to overrides.
-rw-r--r-- | Source/cmFindPackageCommand.cxx | 123 |
1 files changed, 58 insertions, 65 deletions
diff --git a/Source/cmFindPackageCommand.cxx b/Source/cmFindPackageCommand.cxx index edea44e..7f6510b 100644 --- a/Source/cmFindPackageCommand.cxx +++ b/Source/cmFindPackageCommand.cxx @@ -204,56 +204,63 @@ private: bool Loaded = false; }; -class cmFileListGeneratorProject +class cmDirectoryListGenerator { public: - cmFileListGeneratorProject(std::vector<std::string> const& names, - cmFindPackageCommand::SortOrderType so, - cmFindPackageCommand::SortDirectionType sd) + cmDirectoryListGenerator(std::vector<std::string> const& names) : Names{ names } , Matches{} , Current{ this->Matches.cbegin() } - , SortOrder{ so } - , SortDirection{ sd } { } + virtual ~cmDirectoryListGenerator() = default; std::string GetNextCandidate(const std::string& parent) { // Construct a list of matches if not yet if (this->Matches.empty()) { cmsys::Directory directoryLister; + // ALERT `Directory::Load()` keeps only names + // internally and LOST entry type from `dirent`. + // So, `Directory::FileIsDirectory` gonna use + // `SystemTools::FileIsDirectory()` and waste a syscall. + // TODO Need to enhance the `Directory` class. directoryLister.Load(parent); + + // ATTENTION Is it guaranteed that first two entries are + // `.` and `..`? + // TODO If so, just start with index 2 and drop the + // `isDirentryToIgnore(i)` condition to check. for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) { const char* const fname = directoryLister.GetFile(i); if (isDirentryToIgnore(fname)) { continue; } - for (const auto& name : this->Names.get()) { + + for (const auto& n : this->Names.get()) { + // NOTE Customization point for `cmFileListGeneratorMacProject` + const auto name = this->TransformNameBeforeCmp(n); // Skip entries that don't match and non-directories. // ATTENTION BTW, original code also didn't check if it's a symlink - // to a directory! ALERT `Directory::Load()` keep only names - // internally and LOST entry type So `Directory::FileIsDirectory` - // gonna use `SystemTools::FileIsDirectory()` (wasing a syscall) - // again! - if (cmsysString_strncasecmp(fname, name.c_str(), name.length()) == - 0 && - directoryLister.FileIsDirectory(i)) { + // to a directory! + const auto equal = + (cmsysString_strncasecmp(fname, name.c_str(), name.length()) == 0); + if (equal && directoryLister.FileIsDirectory(i)) { this->Matches.emplace_back(fname); } } } - // check if there is a specific sorting order to perform - if (this->SortOrder != cmFindPackageCommand::None) { - cmFindPackageCommand::Sort(this->Matches.begin(), this->Matches.end(), - this->SortOrder, this->SortDirection); - } + // NOTE Customization point for `cmFileListGeneratorProject` + this->OnMatchesLoaded(); + this->Current = this->Matches.cbegin(); } + if (this->Current != this->Matches.cend()) { auto candidate = cmStrCat(parent, '/', *this->Current++); return candidate; } + return {}; } @@ -263,73 +270,59 @@ public: this->Current = this->Matches.cbegin(); } -private: +protected: + virtual void OnMatchesLoaded() {} + virtual std::string TransformNameBeforeCmp(std::string same) { return same; } + std::reference_wrapper<const std::vector<std::string>> Names; std::vector<std::string> Matches; std::vector<std::string>::const_iterator Current; +}; + +class cmFileListGeneratorProject : public cmDirectoryListGenerator +{ +public: + cmFileListGeneratorProject(std::vector<std::string> const& names, + cmFindPackageCommand::SortOrderType so, + cmFindPackageCommand::SortDirectionType sd) + : cmDirectoryListGenerator{ names } + , SortOrder{ so } + , SortDirection{ sd } + { + } + + void OnMatchesLoaded() override + { + // check if there is a specific sorting order to perform + if (this->SortOrder != cmFindPackageCommand::None) { + cmFindPackageCommand::Sort(this->Matches.begin(), this->Matches.end(), + this->SortOrder, this->SortDirection); + } + } + +private: // sort parameters const cmFindPackageCommand::SortOrderType SortOrder; const cmFindPackageCommand::SortDirectionType SortDirection; }; -class cmFileListGeneratorMacProject +class cmFileListGeneratorMacProject : public cmDirectoryListGenerator { public: cmFileListGeneratorMacProject(const std::vector<std::string>& names, cm::string_view ext) - : Names{ names } + : cmDirectoryListGenerator{ names } , Extension{ ext } - , Matches{} - , Current{ this->Matches.cbegin() } { } - std::string GetNextCandidate(const std::string& parent) - { - // Construct a list of matches if not yet - if (this->Matches.empty()) { - cmsys::Directory directoryLister; - directoryLister.Load(parent); - for (auto i = 0ul; i < directoryLister.GetNumberOfFiles(); ++i) { - const char* const fname = directoryLister.GetFile(i); - if (isDirentryToIgnore(fname)) { - continue; - } - for (auto name : this->Names.get()) { - name += this->Extension; - // Skip entries that don't match and non-directories. - // ATTENTION BTW, original code also didn't check if it's a symlink - // to a directory! ALERT `Directory::Load()` keep only names - // internally and LOST entry type So `Directory::FileIsDirectory` - // gonna use `SystemTools::FileIsDirectory()` (wasing a syscall) - // again! - if (cmsysString_strncasecmp(fname, name.c_str(), name.length()) == - 0 && - directoryLister.FileIsDirectory(i)) { - this->Matches.emplace_back(fname); - } - } - } - this->Current = this->Matches.cbegin(); - } - if (this->Current != this->Matches.cend()) { - auto candidate = cmStrCat(parent, '/', *this->Current++); - return candidate; - } - return {}; - } - - void Reset() + std::string TransformNameBeforeCmp(std::string name) override { - this->Matches.clear(); - this->Current = this->Matches.cbegin(); + return cmStrCat(name, this->Extension); } private: - std::reference_wrapper<const std::vector<std::string>> Names; const cm::string_view Extension; - std::vector<std::string> Matches; - std::vector<std::string>::const_iterator Current; }; class cmFileListGeneratorGlob |