mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: wrap internal POSIX directory reading as an iterator class
This commit is contained in:
committed by
Andrew Heather
parent
af0dc60fa1
commit
ae94509f42
3
applications/test/readDir/Make/files
Normal file
3
applications/test/readDir/Make/files
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
Test-readDir.C
|
||||||
|
|
||||||
|
EXE = $(FOAM_USER_APPBIN)/Test-readDir
|
||||||
2
applications/test/readDir/Make/options
Normal file
2
applications/test/readDir/Make/options
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
/* EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude */
|
||||||
|
/* EXE_LIBS = -lfiniteVolume */
|
||||||
74
applications/test/readDir/Test-readDir.C
Normal file
74
applications/test/readDir/Test-readDir.C
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*---------------------------------------------------------------------------*\
|
||||||
|
========= |
|
||||||
|
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||||
|
\\ / O peration |
|
||||||
|
\\ / A nd | Copyright (C) 2019 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Description
|
||||||
|
Test functionality of Foam::readDir
|
||||||
|
|
||||||
|
\*---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "argList.H"
|
||||||
|
#include "OSspecific.H"
|
||||||
|
#include "fileNameList.H"
|
||||||
|
|
||||||
|
using namespace Foam;
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
// Main program:
|
||||||
|
|
||||||
|
int main(int argc, char *argv[])
|
||||||
|
{
|
||||||
|
argList::noBanner();
|
||||||
|
argList::noParallel();
|
||||||
|
argList::addBoolOption("dir", "list directories instead of files");
|
||||||
|
|
||||||
|
#include "setRootCase.H"
|
||||||
|
|
||||||
|
fileName::Type listType = fileName::FILE;
|
||||||
|
|
||||||
|
if (args.found("dir"))
|
||||||
|
{
|
||||||
|
Info<< "Listing directories" << nl;
|
||||||
|
listType = fileName::DIRECTORY;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Info<< "Listing files" << nl;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
{
|
||||||
|
Info<< nl;
|
||||||
|
for (const word& item : readDir(".", listType))
|
||||||
|
{
|
||||||
|
Info<< " " << item << nl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Info<< "\nEnd\n" << endl;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ************************************************************************* //
|
||||||
@ -104,6 +104,141 @@ static inline void redirects(const bool bg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// * * * * * * * * * * * * * * * * Local Classes * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
|
namespace Foam
|
||||||
|
{
|
||||||
|
namespace POSIX
|
||||||
|
{
|
||||||
|
|
||||||
|
//- A simple directory contents iterator
|
||||||
|
class directoryIterator
|
||||||
|
{
|
||||||
|
DIR* dirptr_;
|
||||||
|
|
||||||
|
bool exists_;
|
||||||
|
|
||||||
|
bool hidden_;
|
||||||
|
|
||||||
|
std::string item_;
|
||||||
|
|
||||||
|
//- Accept file/dir name
|
||||||
|
inline bool accept() const
|
||||||
|
{
|
||||||
|
return
|
||||||
|
(
|
||||||
|
item_.size() && item_ != "." && item_ != ".."
|
||||||
|
&& (hidden_ || item_[0] != '.')
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Constructors
|
||||||
|
|
||||||
|
//- Construct for dirName, optionally allowing hidden files/dirs
|
||||||
|
directoryIterator(const fileName& dirName, bool allowHidden = false)
|
||||||
|
:
|
||||||
|
dirptr_(nullptr),
|
||||||
|
exists_(false),
|
||||||
|
hidden_(allowHidden),
|
||||||
|
item_()
|
||||||
|
{
|
||||||
|
if (!dirName.empty())
|
||||||
|
{
|
||||||
|
dirptr_ = ::opendir(dirName.c_str());
|
||||||
|
exists_ = (dirptr_ != nullptr);
|
||||||
|
next(); // Move to first element
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//- Destructor
|
||||||
|
~directoryIterator()
|
||||||
|
{
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Member Functions
|
||||||
|
|
||||||
|
//- Directory open succeeded
|
||||||
|
bool exists() const
|
||||||
|
{
|
||||||
|
return exists_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Directory pointer is valid
|
||||||
|
bool good() const
|
||||||
|
{
|
||||||
|
return dirptr_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Close directory
|
||||||
|
void close()
|
||||||
|
{
|
||||||
|
if (dirptr_)
|
||||||
|
{
|
||||||
|
::closedir(dirptr_);
|
||||||
|
dirptr_ = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//- The current item
|
||||||
|
const std::string& val() const
|
||||||
|
{
|
||||||
|
return item_;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Read next item, always ignoring "." and ".." entries.
|
||||||
|
// Normally also ignore hidden files/dirs (beginning with '.')
|
||||||
|
// Automatically close when there are no more items
|
||||||
|
bool next()
|
||||||
|
{
|
||||||
|
struct dirent *list;
|
||||||
|
|
||||||
|
while (dirptr_ && (list = ::readdir(dirptr_)) != nullptr)
|
||||||
|
{
|
||||||
|
item_ = list->d_name;
|
||||||
|
|
||||||
|
if (accept())
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
close(); // No more items
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Member Operators
|
||||||
|
|
||||||
|
//- Same as good()
|
||||||
|
operator bool() const
|
||||||
|
{
|
||||||
|
return good();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Same as val()
|
||||||
|
const std::string& operator*() const
|
||||||
|
{
|
||||||
|
return val();
|
||||||
|
}
|
||||||
|
|
||||||
|
//- Same as next()
|
||||||
|
directoryIterator& operator++()
|
||||||
|
{
|
||||||
|
next();
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // End namespace POSIX
|
||||||
|
} // End namespace Foam
|
||||||
|
|
||||||
|
|
||||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||||
|
|
||||||
pid_t Foam::pid()
|
pid_t Foam::pid()
|
||||||
@ -743,7 +878,7 @@ Foam::fileNameList Foam::readDir
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Initial filename list size and the increment when resizing the list
|
// Initial filename list size and the increment when resizing the list
|
||||||
static const int maxNnames = 100;
|
constexpr int maxNnames = 100;
|
||||||
|
|
||||||
// Basic sanity: cannot strip '.gz' from directory names
|
// Basic sanity: cannot strip '.gz' from directory names
|
||||||
const bool stripgz = filtergz && (type != fileName::DIRECTORY);
|
const bool stripgz = filtergz && (type != fileName::DIRECTORY);
|
||||||
@ -751,14 +886,10 @@ Foam::fileNameList Foam::readDir
|
|||||||
|
|
||||||
fileNameList dirEntries;
|
fileNameList dirEntries;
|
||||||
|
|
||||||
// Open directory and set the structure pointer
|
// Iterate contents (ignores an empty directory name)
|
||||||
// Do not attempt to open an empty directory name
|
|
||||||
DIR *source;
|
POSIX::directoryIterator dirIter(directory);
|
||||||
if
|
if (!dirIter.exists())
|
||||||
(
|
|
||||||
directory.empty()
|
|
||||||
|| (source = ::opendir(directory.c_str())) == nullptr
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (POSIX::debug)
|
if (POSIX::debug)
|
||||||
{
|
{
|
||||||
@ -781,19 +912,12 @@ Foam::fileNameList Foam::readDir
|
|||||||
|
|
||||||
label nFailed = 0; // Entries with invalid characters
|
label nFailed = 0; // Entries with invalid characters
|
||||||
label nEntries = 0; // Number of selected entries
|
label nEntries = 0; // Number of selected entries
|
||||||
dirEntries.setSize(maxNnames);
|
dirEntries.resize(maxNnames);
|
||||||
|
|
||||||
// Read and parse all the entries in the directory
|
// Process the directory entries
|
||||||
for (struct dirent *list; (list = ::readdir(source)) != nullptr; /*nil*/)
|
for (/*nil*/; dirIter; ++dirIter)
|
||||||
{
|
{
|
||||||
const std::string item(list->d_name);
|
const std::string& item = *dirIter;
|
||||||
|
|
||||||
// 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.
|
// Validate filename without spaces, quotes, etc in the name.
|
||||||
// No duplicate slashes to strip - dirent will not have them anyhow.
|
// No duplicate slashes to strip - dirent will not have them anyhow.
|
||||||
@ -813,7 +937,7 @@ Foam::fileNameList Foam::readDir
|
|||||||
{
|
{
|
||||||
if (nEntries >= dirEntries.size())
|
if (nEntries >= dirEntries.size())
|
||||||
{
|
{
|
||||||
dirEntries.setSize(dirEntries.size() + maxNnames);
|
dirEntries.resize(dirEntries.size() + maxNnames);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (stripgz && name.hasExt(extgz))
|
if (stripgz && name.hasExt(extgz))
|
||||||
@ -827,10 +951,9 @@ Foam::fileNameList Foam::readDir
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
::closedir(source);
|
|
||||||
|
|
||||||
// Finalize the length of the entries list
|
// Finalize the length of the entries list
|
||||||
dirEntries.setSize(nEntries);
|
dirEntries.resize(nEntries);
|
||||||
|
|
||||||
if (nFailed && POSIX::debug)
|
if (nFailed && POSIX::debug)
|
||||||
{
|
{
|
||||||
@ -1171,14 +1294,11 @@ bool Foam::rm(const fileName& file)
|
|||||||
|
|
||||||
bool Foam::rmDir(const fileName& directory, const bool silent)
|
bool Foam::rmDir(const fileName& directory, const bool silent)
|
||||||
{
|
{
|
||||||
// Open directory and set the structure pointer
|
// Iterate contents (ignores an empty directory name)
|
||||||
// Do not attempt to open an empty directory name
|
// Also retain hidden files/dirs for removal
|
||||||
DIR *source;
|
|
||||||
if
|
POSIX::directoryIterator dirIter(directory, true);
|
||||||
(
|
if (!dirIter.exists())
|
||||||
directory.empty()
|
|
||||||
|| (source = ::opendir(directory.c_str())) == nullptr
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
if (!silent)
|
if (!silent)
|
||||||
{
|
{
|
||||||
@ -1201,18 +1321,13 @@ bool Foam::rmDir(const fileName& directory, const bool silent)
|
|||||||
|
|
||||||
// Process each directory entry, counting any errors encountered
|
// Process each directory entry, counting any errors encountered
|
||||||
label nErrors = 0;
|
label nErrors = 0;
|
||||||
for (struct dirent *list; (list = ::readdir(source)) != nullptr; /*nil*/)
|
|
||||||
{
|
|
||||||
const std::string item(list->d_name);
|
|
||||||
|
|
||||||
// Ignore "." and ".." directories
|
for (/*nil*/; dirIter; ++dirIter)
|
||||||
if (item.empty() || item == "." || item == "..")
|
{
|
||||||
{
|
const std::string& item = *dirIter;
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Allow invalid characters (spaces, quotes, etc),
|
// Allow invalid characters (spaces, quotes, etc),
|
||||||
// otherwise we cannot subdirs with these types of names.
|
// otherwise we cannot remove subdirs with these types of names.
|
||||||
// -> const fileName path = directory/name; <-
|
// -> const fileName path = directory/name; <-
|
||||||
|
|
||||||
const fileName path(fileName::concat(directory, item));
|
const fileName path(fileName::concat(directory, item));
|
||||||
@ -1256,7 +1371,6 @@ bool Foam::rmDir(const fileName& directory, const bool silent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// clean up
|
||||||
::closedir(source);
|
|
||||||
return !nErrors;
|
return !nErrors;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user