diff --git a/applications/test/fileName/Test-fileName.C b/applications/test/fileName/Test-fileName.C index 8d97b9f1f5..0300c5f8a7 100644 --- a/applications/test/fileName/Test-fileName.C +++ b/applications/test/fileName/Test-fileName.C @@ -47,6 +47,38 @@ using namespace Foam; // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +unsigned testClean(std::initializer_list> tests) +{ + unsigned nFail = 0; + + for (const Pair& test : tests) + { + const std::string& input = test.first(); + const std::string& expected = test.second(); + + fileName cleaned(test.first()); + cleaned.clean(); + + if (cleaned == expected) + { + Info<< "(pass)" + << " clean " << input << " -> " << cleaned << nl; + } + else + { + Info<< "(fail)" + << " clean " << input << " -> " << cleaned + << " expected=" << expected + << nl; + + ++nFail; + } + } + + return nFail; +} + + unsigned testStrip ( const bool doClean, @@ -184,6 +216,16 @@ unsigned testRelative(std::initializer_list> tests) } +void testDirname(const fileName& input) +{ + Info<< "input:" << input + << " path:" << input.path() + << " name:\"" << input.name() << '"' + << " ext:\"" << input.ext() << '"' + << " components: " << flatOutput(input.components()) << nl; +} + + // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // Main program: @@ -196,6 +238,8 @@ int main(int argc, char *argv[]) argList::addBoolOption("relative", "test relative operations"); argList::addBoolOption("system", "test filesystem operations"); argList::addBoolOption("default", "reinstate default tests"); + argList::addBoolOption("clean", "clean()"); + argList::addBoolOption("dirname", "basename/dirname tables"); argList::addNote("runs default tests or specified ones only"); #include "setRootCase.H" @@ -254,6 +298,20 @@ int main(int argc, char *argv[]) Info<< "All ==> " << file4 << nl; } + if (args.found("dirname")) + { + testDirname(""); + testDirname("."); + testDirname("abc"); + testDirname("/"); + testDirname("/abc"); + testDirname("abc/def"); + testDirname("/abc/def"); + testDirname("/abc/def/"); + testDirname("/abc///def///"); + testDirname("/abc/../def"); + } + // Test various ext() methods if (args.found("ext")) @@ -381,6 +439,35 @@ int main(int argc, char *argv[]) } + if (args.found("clean")) + { + Info<< nl << "Test fileName::clean()" << nl << nl; + + unsigned nFail = testClean + ({ + { "/", "/" }, + { "/abc/", "/abc" }, + { "/abc////def", "/abc/def" }, + { "/abc/def/./ghi/.", "/abc/def/ghi" }, + { "abc/def/./", "abc/def" }, + { "./abc/", "./abc" }, + { "/abc/def/../ghi/jkl/nmo/..", "/abc/ghi/jkl" }, + { "abc/../def/ghi/../jkl", "abc/../def/jkl" }, + }); + + Info<< nl; + if (nFail) + { + Info<< "failed " << nFail; + } + else + { + Info<< "passed all"; + } + Info<< " fileName::clean tests" << nl; + } + + if (args.found("validate")) { unsigned nFail = 0; @@ -677,9 +764,27 @@ int main(int argc, char *argv[]) << " controlDict => " << findEtcFile("controlDict") << nl << " badName => " << findEtcFile("badName") << endl; - Info<< "This should emit a fatal error:" << endl; - Info<< " badName(die) => " << findEtcFile("badName", true) << nl - << endl; + { + + Info<< nl << "Expect a FatalError for findEtcFile() with a bad name:" + << nl; + + const bool throwingError = FatalError.throwExceptions(); + + try + { + Info<< " badName(die) => " << flush + << findEtcFile("", true) << nl + << endl; + } + catch (Foam::error& err) + { + Info<< nl << "findEtcFile() Caught FatalError " + << err << nl << endl; + } + FatalError.throwExceptions(throwingError); + } + Info<< "\nEnd\n" << endl; return 0; diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index aa7f6fe8ec..69fc40ccb4 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -735,10 +735,9 @@ void Foam::argList::setCasePaths() caseDir = cwd(); options_.erase("case"); } - else if (!caseDir.isAbsolute()) + else { - caseDir = cwd()/caseDir; - caseDir.clean(); + caseDir.toAbsolute(); } } else @@ -1126,7 +1125,7 @@ void Foam::argList::parse source = options_["decomposeParDict"]; if (isDir(source)) { - source = source/"decomposeParDict"; + source /= "decomposeParDict"; adjustOpt = true; } diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.C b/src/OpenFOAM/primitives/strings/fileName/fileName.C index 6fda7a5c8f..e1e6a5ba30 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileName.C +++ b/src/OpenFOAM/primitives/strings/fileName/fileName.C @@ -209,15 +209,14 @@ Foam::fileName::Type Foam::fileName::type(const bool followLink) const Foam::fileName& Foam::fileName::toAbsolute() { - fileName& f = *this; - - if (!f.isAbsolute()) + if (!isAbsolute(*this)) { + fileName& f = *this; f = cwd()/f; f.clean(); } - return f; + return *this; } @@ -482,9 +481,12 @@ Foam::fileName Foam::operator/(const string& a, const string& b) Foam::fileName Foam::search(const word& file, const fileName& directory) { - // Search the current directory for the file - fileNameList files(fileHandler().readDir(directory, fileName::FILE)); - for (const fileName& item : files) + // Search current directory for the file + for + ( + const fileName& item + : fileHandler().readDir(directory, fileName::FILE) + ) { if (item == file) { @@ -493,17 +495,20 @@ Foam::fileName Foam::search(const word& file, const fileName& directory) } // If not found search each of the sub-directories - fileNameList dirs(fileHandler().readDir(directory, fileName::DIRECTORY)); - for (const fileName& item : dirs) + for + ( + const fileName& item + : fileHandler().readDir(directory, fileName::DIRECTORY) + ) { fileName path = search(file, directory/item); - if (path != fileName::null) + if (!path.empty()) { return path; } } - return fileName::null; + return fileName(); } diff --git a/src/OpenFOAM/primitives/strings/fileName/fileName.H b/src/OpenFOAM/primitives/strings/fileName/fileName.H index 385c91c92e..78892c584b 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileName.H +++ b/src/OpenFOAM/primitives/strings/fileName/fileName.H @@ -157,7 +157,7 @@ public: ); //- This is a specialized (possibly slower) version of compare() - // that ignores duplicate or trailing slashes. + //- that ignores duplicate or trailing slashes. static bool equals(const std::string& s1, const std::string& s2); @@ -229,14 +229,16 @@ public: // // Behaviour compared to /usr/bin/basename: // \verbatim - // input name() basename - // ----- ------ -------- - // "foo" "foo" "foo" - // "/" "" "/" - // "/foo" "foo" "foo" - // "foo/bar" "bar" "bar" - // "/foo/bar" "bar" "bar" - // "/foo/bar/" "" "bar" + // input name() basename + // ----- ------ -------- + // "" "" "" + // "abc" "abc" "abc" + // "/" "" "/" + // "/abc" "abc" "abc" + // "abc/def" "def" "def" + // "/abc/def" "def" "def" + // "/abc/def/" "" "def" + // "/abc/../def" "def" "def" // \endverbatim inline static std::string name(const std::string& str); @@ -261,16 +263,18 @@ public: //- Return directory path name (part before last /) // The result normally coresponds to a Foam::fileName // - // Behaviour compared to /usr/bin/dirname: - // \verbatim + // Behaviour compared to /usr/bin/dirname: + // \verbatim // input path() dirname // ----- ------ ------- - // "foo" "." "." + // "" "." "." + // "abc" "." "." // "/" "/" "/" - // "/foo" "/" "foo" - // "foo/bar" "foo" "foo" - // "/foo/bar" "/foo" "/foo" - // "/foo/bar/" "/foo/bar/" "/foo" + // "/abc" "/" "/" + // "abc/def" "abc" "abc" + // "/abc/def" "/abc" "/abc" + // "/abc/def/" "/abc/def" "/abc" + // "/abc/../def" "/abc/.." "/abc/.." // \endverbatim inline static std::string path(const std::string& str); @@ -312,16 +316,18 @@ public: //- Return path components as wordList // - // Behaviour: - // \verbatim - // Input components() - // ----- ------ - // "foo" ("foo") - // "/foo" ("foo") - // "foo/bar" ("foo", "bar") - // "/foo/bar" ("foo", "bar") - // "/foo/bar/" ("foo", "bar") - // \endverbatim + // Behaviour: + // \verbatim + // input components() + // ----- ------------ + // "" () + // "." (".") + // "abc" ("abc") + // "/abc" ("abc") + // "abc/def" ("abc", "def") + // "/abc/def" ("abc", "def") + // "/abc/def/" ("abc", "def") + // \endverbatim wordList components(const char delimiter = '/') const; //- Return a single component of the path diff --git a/src/OpenFOAM/primitives/strings/fileName/fileNameI.H b/src/OpenFOAM/primitives/strings/fileName/fileNameI.H index b135a69ede..cf8a96dcdc 100644 --- a/src/OpenFOAM/primitives/strings/fileName/fileNameI.H +++ b/src/OpenFOAM/primitives/strings/fileName/fileNameI.H @@ -140,7 +140,7 @@ inline bool Foam::fileName::isAbsolute(const std::string& str) inline bool Foam::fileName::isAbsolute() const { - return !empty() && operator[](0) == '/'; + return isAbsolute(*this); } diff --git a/src/OpenFOAM/primitives/strings/string/string.C b/src/OpenFOAM/primitives/strings/string/string.C index b95a000862..29ab150c04 100644 --- a/src/OpenFOAM/primitives/strings/string/string.C +++ b/src/OpenFOAM/primitives/strings/string/string.C @@ -46,21 +46,30 @@ Foam::word Foam::string::ext() const return word::null; } - return substr(i+1, npos); + return substr(i+1); } -bool Foam::string::ext(const Foam::word& ending) +bool Foam::string::ext(const word& ending) { - if (!ending.empty() && !empty() && operator[](size()-1) != '/') + if (ending.empty() || empty() || back() == '/') + { + return false; + } + else if (ending[0] == '.') + { + if (ending.size() == 1) + { + return false; + } + } + else { append(1u, '.'); - append(ending); - - return true; } + append(ending); - return false; + return true; } @@ -90,7 +99,7 @@ bool Foam::string::hasExt(const wordRe& ending) const return false; } - const std::string end = substr(i+1, npos); // Compare *after* the dot + const std::string end = substr(i+1); // Compare *after* the dot return ending.match(end); }