From 2feb11dbeb2a01bac48cf65dd8eb37a1cab4322e Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 10 Jan 2018 15:01:12 +0100 Subject: [PATCH] ENH: add testing for directory lister class --- applications/test/DirLister/DirLister.C | 144 +++++++++ applications/test/DirLister/DirLister.H | 306 ++++++++++++++++++ applications/test/DirLister/DirListerI.H | 203 ++++++++++++ .../test/DirLister/DirListerTemplates.C | 91 ++++++ applications/test/DirLister/Make/files | 4 + applications/test/DirLister/Make/options | 2 + applications/test/DirLister/Test-DirLister.C | 198 ++++++++++++ 7 files changed, 948 insertions(+) create mode 100644 applications/test/DirLister/DirLister.C create mode 100644 applications/test/DirLister/DirLister.H create mode 100644 applications/test/DirLister/DirListerI.H create mode 100644 applications/test/DirLister/DirListerTemplates.C create mode 100644 applications/test/DirLister/Make/files create mode 100644 applications/test/DirLister/Make/options create mode 100644 applications/test/DirLister/Test-DirLister.C diff --git a/applications/test/DirLister/DirLister.C b/applications/test/DirLister/DirLister.C new file mode 100644 index 0000000000..45460ddd34 --- /dev/null +++ b/applications/test/DirLister/DirLister.C @@ -0,0 +1,144 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "DirLister.H" +#include + +// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * // + +static const Foam::word extgz("gz"); + + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +bool Foam::DirLister::const_iterator::open(const fileName& dir) +{ + if (!dir.empty()) + { + dirptr_ = ::opendir(dir.c_str()); + } + + return dirptr_; +} + + +void Foam::DirLister::const_iterator::close() +{ + if (dirptr_) + { + ::closedir(dirptr_); + dirptr_ = nullptr; + } +} + + +Foam::word Foam::DirLister::next(DIR* dirPtr) const +{ + // Read next entry in the directory + + struct dirent *list; + while (dirPtr && (list = ::readdir(dirPtr)) != nullptr) + { + const std::string item(list->d_name); + + // Ignore files/directories beginning with "." + // These are the ".", ".." directories and any hidden files/dirs + if (item.empty() || item[0] == '.') + { + continue; + } + + // Validate filename without spaces, quotes, etc in the name. + // No duplicate slashes to strip - dirent will not have them anyhow. + + word name(fileName::validate(item)); + if (name != item) + { + // ++nFailed_; + continue; + } + + bool ok = false; + fileName::Type fType = fileName::UNDEFINED; + + if + ( + (requestedType_ == fileName::DIRECTORY) + || (requestedType_ == fileName::FILE && !fileName::isBackup(name)) + ) + { + fType = (dirName_/name).type(followLink_); + + // A DIRECTORY or FILE was request, so only accept the same type + ok = (requestedType_ == fType); + } + else if (requestedType_ == fileName::UNDEFINED) + { + fType = (dirName_/name).type(followLink_); + + // An UNDEFINED type was requested, so accept DIRECTORY or FILE + ok = + ( + (fType == fileName::DIRECTORY) + || (fType == fileName::FILE && !fileName::isBackup(name)) + ); + } + + if (ok) + { + if (fType == fileName::FILE && stripgz_ && name.hasExt(extgz)) + { + name = name.lessExt(); + } + + if (!name.empty() && accept(name)) + { + return name; + } + } + } + + return word(); +} + + +// * * * * * * * * * * * * * * * Const Iterator * * * * * * * * * * * * * * // + +bool Foam::DirLister::const_iterator::next() +{ + if (lister_ && dirptr_) + { + name_ = lister_->next(dirptr_); + if (name_.empty()) + { + close(); + } + } + + return dirptr_; +} + + +// ************************************************************************* // diff --git a/applications/test/DirLister/DirLister.H b/applications/test/DirLister/DirLister.H new file mode 100644 index 0000000000..e1108e7122 --- /dev/null +++ b/applications/test/DirLister/DirLister.H @@ -0,0 +1,306 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Class + Foam::DirLister + +Description + A class for listing directory contents, or obtaining a list of + directory contents. + + For many situations, the iterator-based access is the most convenient + since it allows use of a range-for without any intermediate variables + or allocations. + + List all directories or files: + \code + for (const word& item : DirLister(".")) + { + Info<< "dir or file: " << item << nl; + } + \endcode + + List files or directories only: + \code + for (const word& item : DirLister(".").files()) + { + Info<< "file: " << item << nl; + } + for (const word& item : DirLister(".").dirs()) + { + Info<< "dir: " << item << nl; + } + \endcode + These can be combined with a unary predicate to select only specific + items: + \code + { + wordReList matchProcs + { + wordRe("processors"), + wordRe("processor\\d+", wordRe::REGEX) + }; + + for + ( + const word& item + : DirLister::dirs(".").where(wordRes(matchProcs)) + ) + { + Info<< "processor dir: " << item << nl; + } + } + \endcode + The unary predicate can similarly be used with the list or sorted + methods: + \code + { + wordReList matchProcs + { + wordRe("processor[0-9][0-9]*", wordRe::REGEX), + wordRe("processors") + }; + + fileNameList procDirs + ( + DirLister::dirs(".").sorted(wordRes(matchProcs)) + ); + } + \endcode + +See Also + Foam::readDir + +SourceFiles + DirListerI.H + DirLister.C + DirListerTemplates.C + +\*---------------------------------------------------------------------------*/ + +#ifndef DirLister_H +#define DirLister_H + +#include "fileNameList.H" +#include "wordList.H" +#include + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +/*---------------------------------------------------------------------------*\ + Class DirLister Declaration +\*---------------------------------------------------------------------------*/ + +class DirLister +{ + // Private data + + fileName dirName_; + + fileName::Type requestedType_; + + bool followLink_; + + bool stripgz_; + + +protected: + + // Protected Member Functions + + //- Placeholder for additional selection filters + virtual inline bool accept(const word& name) const; + + //- Traverse to next entry + word next(DIR* dirPtr) const; + + +public: + + //- Specialization for filtering with a predicate + template class Filtered; + + + // Constructors + + //- Construct from components - list files and directories + inline DirLister + ( + const fileName& directory, + const fileName::Type = fileName::UNDEFINED, + const bool filtergz = true, + const bool followLink = true + ); + + + //- Convenience constructor for listing directories + inline static DirLister dirs + ( + const fileName& directory, + const bool followLink = true + ); + + //- Convenience constructor for listing files + inline static DirLister files + ( + const fileName& directory, + const bool filtergz = true, + const bool followLink = true + ); + + //- Convenience for constructing a filtered iterator + template + inline Filtered where + ( + const UnaryPredicate& pred, + const bool prune = false + ) const; + + + //- Destructor + virtual ~DirLister() = default; + + + // Member Functions + + //- Return the directory name + inline const fileName& dirName() const; + + + //- Return a complete list of names + template + List list() const; + + //- Return complete list of names + template + List list + ( + const UnaryPredicate& pred, + const bool prune = false + ) const; + + //- Return a complete list of names, sorted in natural order + template + List sorted() const; + + //- Return complete list of names, sorted in natural order + template + List sorted + ( + const UnaryPredicate& pred, + const bool prune = false + ) const; + + + // Iterators + + //- Const iterator for traversing directory contents + class const_iterator + { + const DirLister* lister_; + DIR* dirptr_; + word name_; + + //- Open directory and set dirptr_ (nullptr on failure) + bool open(const fileName& dir); + + //- Close dirptr_ + void close(); + + bool next(); + + public: + + //- Construct end iterator + inline const_iterator(); + + //- Construct begin iterator + inline const_iterator(const DirLister* lister); + + //- Destructor + inline ~const_iterator(); + + inline const_iterator& operator++(); + inline const word& operator*() const; + + inline bool operator==(const const_iterator& iter) const; + inline bool operator!=(const const_iterator& iter) const; + }; + + + inline const_iterator cbegin() const; + inline const_iterator cend() const; + + inline const_iterator begin() const; + inline const_iterator end() const; + +}; + + +//- A DirLister specialization for filtering with a predicate +template +class DirLister::Filtered +: + public DirLister +{ + const UnaryPredicate& pred_; + bool prune_; + +protected: + + friend class DirLister; + + virtual inline bool accept(const word& name) const; + + //- Constructor + inline Filtered + ( + const DirLister& lister, + const UnaryPredicate& pred, + const bool prune = false + ); + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#include "DirListerI.H" + +#ifdef NoRepository + #include "DirListerTemplates.C" +#endif + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/applications/test/DirLister/DirListerI.H b/applications/test/DirLister/DirListerI.H new file mode 100644 index 0000000000..1c714acec1 --- /dev/null +++ b/applications/test/DirLister/DirListerI.H @@ -0,0 +1,203 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +inline bool Foam::DirLister::accept(const word& name) const +{ + return true; +} + + +template +inline bool Foam::DirLister::Filtered::accept +( + const word& name +) const +{ + return (pred_(name) ? !prune_ : prune_); +} + + +// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // + +inline Foam::DirLister::DirLister +( + const fileName& directory, + const fileName::Type requestedType, + const bool filtergz, + const bool followLink +) +: + dirName_(directory), + requestedType_(requestedType), + followLink_(followLink), + stripgz_(filtergz) +{} + + +inline Foam::DirLister Foam::DirLister::dirs +( + const fileName& directory, + const bool followLink +) +{ + return DirLister(directory, fileName::DIRECTORY, false, followLink); +} + + +inline Foam::DirLister Foam::DirLister::files +( + const fileName& directory, + const bool filtergz, + const bool followLink +) +{ + return DirLister(directory, fileName::FILE, filtergz, followLink); +} + + +template +inline Foam::DirLister::Filtered::Filtered +( + const Foam::DirLister& lister, + const UnaryPredicate& pred, + const bool prune +) +: + DirLister(lister), + pred_(pred), + prune_(prune) +{} + + +template +inline Foam::DirLister::Filtered +Foam::DirLister::where(const UnaryPredicate& pred, const bool prune) const +{ + return DirLister::Filtered(*this, pred, prune); +} + + +// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // + +inline const Foam::fileName& Foam::DirLister::dirName() const +{ + return dirName_; +} + + +// * * * * * * * * * * * * * * * Const Iterator * * * * * * * * * * * * * * // + +inline Foam::DirLister::const_iterator::const_iterator() +: + lister_(nullptr), + dirptr_(nullptr), + name_() +{} + + +inline Foam::DirLister::const_iterator::const_iterator +( + const Foam::DirLister* lister +) +: + lister_(lister), + dirptr_(nullptr), + name_() +{ + if (lister_ && open(lister_->dirName())) + { + next(); // increment to first entry + } +} + + +inline Foam::DirLister::const_iterator::~const_iterator() +{ + close(); +} + + +inline const Foam::word& Foam::DirLister::const_iterator::operator*() const +{ + return name_; +} + + +Foam::DirLister::const_iterator& +Foam::DirLister::const_iterator::operator++() +{ + next(); + return *this; +} + + +inline bool Foam::DirLister::const_iterator::operator== +( + const const_iterator& iter +) +const +{ + // Directory entries are unique, so just compare the names + return (name_ == iter.name_); +} + + +inline bool Foam::DirLister::const_iterator::operator!= +( + const const_iterator& iter +) +const +{ + return name_ != iter.name_; +} + + +inline Foam::DirLister::const_iterator Foam::DirLister::cbegin() const +{ + return const_iterator(this); +} + + +inline Foam::DirLister::const_iterator Foam::DirLister::cend() const +{ + return const_iterator(); +} + + +inline Foam::DirLister::const_iterator Foam::DirLister::begin() const +{ + return cbegin(); +} + + +inline Foam::DirLister::const_iterator Foam::DirLister::end() const +{ + return cend(); +} + + +// ************************************************************************* // diff --git a/applications/test/DirLister/DirListerTemplates.C b/applications/test/DirLister/DirListerTemplates.C new file mode 100644 index 0000000000..52c0bfe842 --- /dev/null +++ b/applications/test/DirLister/DirListerTemplates.C @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +\*---------------------------------------------------------------------------*/ + +#include "predicates.H" +#include "stringOps.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +template +Foam::List Foam::DirLister::list +( + const UnaryPredicate& pred, + const bool prune +) const +{ + // Initial list size and resizing increment + static const int incr = 100; + + List lst(incr); + + label nItems = 0; + for (const auto& item: *this) + { + if (pred(item) ? !prune : prune) + { + if (nItems >= lst.size()) + { + lst.setSize(lst.size() + incr); + } + + lst[nItems++] = item; + } + } + + lst.setSize(nItems); + + return lst; +} + + +template +Foam::List Foam::DirLister::list() const +{ + return list(predicates::always()); +} + + +template +Foam::List Foam::DirLister::sorted +( + const UnaryPredicate& pred, + const bool prune +) const +{ + List lst(list(pred, prune)); + sort(lst, stringOps::natural_sort()); + + return lst; +} + + +template +Foam::List Foam::DirLister::sorted() const +{ + return sorted(predicates::always()); +} + + +// ************************************************************************* // diff --git a/applications/test/DirLister/Make/files b/applications/test/DirLister/Make/files new file mode 100644 index 0000000000..d42f88a4a5 --- /dev/null +++ b/applications/test/DirLister/Make/files @@ -0,0 +1,4 @@ +Test-DirLister.C +DirLister.C + +EXE = $(FOAM_USER_APPBIN)/Test-DirLister diff --git a/applications/test/DirLister/Make/options b/applications/test/DirLister/Make/options new file mode 100644 index 0000000000..6a9e9810b3 --- /dev/null +++ b/applications/test/DirLister/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = -I$(LIB_SRC)/cfdTools/include */ +/* EXE_LIBS = -lfiniteVolume */ diff --git a/applications/test/DirLister/Test-DirLister.C b/applications/test/DirLister/Test-DirLister.C new file mode 100644 index 0000000000..b528a1558a --- /dev/null +++ b/applications/test/DirLister/Test-DirLister.C @@ -0,0 +1,198 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | Copyright (C) 2018 OpenCFD Ltd. + \\/ M anipulation | +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Description + Test functionality of DirLister + +\*---------------------------------------------------------------------------*/ + +#include "DirLister.H" +#include "fileNameList.H" +#include "wordRes.H" +#include "predicates.H" +#include "FlatOutput.H" +#include "error.H" +#include "stringOps.H" +#include "scalar.H" + +using namespace Foam; + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + { + Info<< nl + << "List items" << nl + << "~~~~~~~~~~" << nl; + for (const word& item : DirLister(".")) + { + Info<< " " << item << nl; + } + } + + { + Info<< nl + << "List files" << nl + << "~~~~~~~~~~" << nl; + for (const word& item : DirLister::files(".")) + { + Info<< " " << item << nl; + } + } + + { + Info<< nl + << "List dirs" << nl + << "~~~~~~~~~~" << nl; + for (const word& item : DirLister::dirs(".")) + { + Info<< " " << item << nl; + } + } + + { + Info<< nl + << "List files - filtered" << nl + << "~~~~~~~~~~" << nl; + for + ( + const word& item + : DirLister::files(".").where + ( + [](const word& val){ return val.startsWith("T"); } + ) + ) + { + Info<< " " << item << nl; + } + } + + { + Info<< nl + << "List dirs - filtered" << nl + << "~~~~~~~~~~" << nl; + + for + ( + const word& item + : DirLister::dirs(".").where(regExp("Ma.*")) + ) + { + Info<< " " << item << nl; + } + } + + { + Info<< nl + << "List dirs - filtered" << nl + << "~~~~~~~~~~" << nl; + + for + ( + const word& item + : DirLister::dirs(".").where(predicates::always()) + ) + { + Info<< " " << item << nl; + } + } + + + { + Info<< nl + << "List items" << nl + << "~~~~~~~~~~" << nl + << DirLister(".").list() << nl; + } + + { + Info<< nl + << "List files - filtered" << nl + << "~~~~~~~~~~" << nl + << DirLister(".").list + ( + [](const word& val){ return val.startsWith("D"); }, + false + ) + << nl; + } + + { + Info<< nl + << "List files - filtered" << nl + << "~~~~~~~~~~" << nl; + + wordReList relist + { + wordRe("processors"), + wordRe("processor[0-9][0-9]*", wordRe::REGEX) + }; + wordRes matcher(relist); + + Info<<"matcher: " << flatOutput(matcher) << endl; + + for (const word& item : DirLister::dirs(".").where(wordRes(relist))) + { + Info<< "=> " << item << nl; + } + + Info<< "dirList: " + << flatOutput + ( + DirLister::dirs(".").sorted(wordRes(relist)) + ) << nl; + } + + + { + Info<< nl + << "List time dirs" << nl + << "~~~~~~~~~~" << nl; + + for + ( + const word& item + : DirLister::dirs(".").where + ( + [](const word& val) + { + scalar s; + return readScalar(val, s) || val == "constant"; + } + ) + ) + { + Info<< "=> " << item << nl; + } + } + + + Info<< "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* //