From 45c8503c1f9316b48e2ff8f6e8aed35448ee180a Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Fri, 5 Oct 2018 09:56:17 +0200 Subject: [PATCH] ENH: dictionary lookup with detection of zero tokens (#1033) - the opposite problem from issue #762. Now we also test if the input token stream had any tokens at all. - called by the dictionary get<> and readEntry() methods. --- .../test/dictionary2/Test-dictionary2.C | 82 ++++++++++++++++- src/OpenFOAM/db/dictionary/dictionary.C | 92 ++++++++++++------- src/OpenFOAM/db/dictionary/dictionary.H | 6 +- .../db/dictionary/dictionaryTemplates.C | 10 +- src/OpenFOAM/global/argList/argList.C | 32 +++++-- src/OpenFOAM/global/argList/argList.H | 14 ++- src/OpenFOAM/global/argList/argListI.H | 10 +- 7 files changed, 185 insertions(+), 61 deletions(-) diff --git a/applications/test/dictionary2/Test-dictionary2.C b/applications/test/dictionary2/Test-dictionary2.C index 36460568e6..fc883a9cf5 100644 --- a/applications/test/dictionary2/Test-dictionary2.C +++ b/applications/test/dictionary2/Test-dictionary2.C @@ -2,7 +2,7 @@ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | - \\ / A nd | Copyright (C) 2017 OpenCFD Ltd. + \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd. \\/ M anipulation | ------------------------------------------------------------------------------- License @@ -25,8 +25,7 @@ Application Test-dictionary2 Description - - Test dictionary insertion + Test dictionary insertion and some reading functionality. \*---------------------------------------------------------------------------*/ @@ -208,6 +207,83 @@ int main(int argc, char *argv[]) Info<< nl << "dictionary" << nl << nl; dict1.write(Info, false); + + { + Info<< nl << "Test reading good/bad/empty scalar entries" << nl; + dictionary dict2 + ( + IStringStream + ( + "good 3.14159;\n" + "empty;\n" + // "bad text;\n" // always fails + // "bad 3.14159 1234;\n" // fails for readScalar + )() + ); + dict2.write(Info); + + + // With readScalar + { + Info<< nl << "Test some bad input with readScalar()" << nl; + + const bool throwingIOError = FatalIOError.throwExceptions(); + const bool throwingError = FatalError.throwExceptions(); + + try + { + scalar val1 = readScalar(dict2.lookup("good")); + // scalar val2 = readScalar(dict2.lookup("bad")); + scalar val2 = -1; + scalar val3 = readScalar(dict2.lookup("empty")); + + Info<< "got good=" << val1 << " bad=" << val2 + << " empty=" << val3 << nl; + } + catch (Foam::IOerror& err) + { + Info<< "Caught FatalIOError " << err << nl << endl; + } + catch (Foam::error& err) + { + Info<< "Caught FatalError " << err << nl << endl; + } + FatalError.throwExceptions(throwingError); + FatalIOError.throwExceptions(throwingIOError); + } + + + // With get<scalar> + { + Info<< nl << "Test some bad input with get<scalar>()" << nl; + + const bool throwingIOError = FatalIOError.throwExceptions(); + const bool throwingError = FatalError.throwExceptions(); + + try + { + scalar val1 = dict2.get<scalar>("good"); + // scalar val2 = dict2.get<scalar>("bad"); + scalar val2 = -1; + scalar val3 = dict2.get<scalar>("empty"); + + Info<< "got good=" << val1 << " bad=" << val2 + << " empty=" << val3 << nl; + } + catch (Foam::IOerror& err) + { + Info<< "Caught FatalIOError " << err << nl << endl; + } + catch (Foam::error& err) + { + Info<< "Caught FatalError " << err << nl << endl; + } + FatalError.throwExceptions(throwingError); + FatalIOError.throwExceptions(throwingIOError); + } + } + + Info<< "\nDone\n" << endl; return 0; diff --git a/src/OpenFOAM/db/dictionary/dictionary.C b/src/OpenFOAM/db/dictionary/dictionary.C index 580744d06c..125c73e127 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.C +++ b/src/OpenFOAM/db/dictionary/dictionary.C @@ -48,24 +48,59 @@ bool Foam::dictionary::writeOptionalEntries // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -void Foam::dictionary::excessTokens +void Foam::dictionary::checkITstream ( const word& keyword, const ITstream& is ) const { - const label nExcess = is.nRemainingTokens(); - - if (!nExcess) + if (is.nRemainingTokens()) { - return; - } + const label remaining = is.nRemainingTokens(); + + // Similar to SafeFatalIOError + if (JobInfo::constructed) + { + OSstream& err = + FatalIOError + ( + "", // functionName + "", // sourceFileName + 0, // sourceFileLineNumber + this->name(), // ioFileName + is.lineNumber() // ioStartLineNumber + ); + + err << "'" << keyword << "' has " + << remaining << " excess tokens in stream" << nl << nl + << " "; + is.writeList(err, 0); + + err << exit(FatalIOError); + } + else + { + std::cerr + << nl + << "--> FOAM FATAL IO ERROR:" << nl; + + std::cerr + << "'" << keyword << "' has " + << remaining << " excess tokens in stream" << nl << nl; - // Similar to SafeFatalIOError + std::cerr + << "file: " << this->name() + << " at line " << is.lineNumber() << '.' << nl + << std::endl; - if (JobInfo::constructed) + ::exit(1); + } + } + else if (!is.size()) { - OSstream& err = + // Similar to SafeFatalIOError + if (JobInfo::constructed) + { FatalIOError ( "", // functionName @@ -73,31 +108,24 @@ void Foam::dictionary::excessTokens 0, // sourceFileLineNumber this->name(), // ioFileName is.lineNumber() // ioStartLineNumber - ); - - err << "'" << keyword << "' has " - << nExcess << " excess tokens in stream" << nl << nl - << " "; - is.writeList(err, 0); - - err << exit(FatalIOError); - } - else - { - std::cerr - << nl - << "--> FOAM FATAL IO ERROR:" << nl; - - std::cerr - << "'" << keyword << "' has " - << nExcess << " excess tokens in stream" << nl << nl; + ) + << "'" << keyword << "' had no tokens in stream" << nl << nl + << exit(FatalIOError); + } + else + { + std::cerr + << nl + << "--> FOAM FATAL IO ERROR:" << nl + << "'" << keyword << "' had no tokens in stream" << nl << nl; - std::cerr - << "file: " << this->name() - << " at line " << is.lineNumber() << '.' << nl - << std::endl; + std::cerr + << "file: " << this->name() + << " at line " << is.lineNumber() << '.' << nl + << std::endl; - ::exit(1); + ::exit(1); + } } } diff --git a/src/OpenFOAM/db/dictionary/dictionary.H b/src/OpenFOAM/db/dictionary/dictionary.H index 384efa081b..dafb0b5179 100644 --- a/src/OpenFOAM/db/dictionary/dictionary.H +++ b/src/OpenFOAM/db/dictionary/dictionary.H @@ -383,8 +383,10 @@ private: ) const; - //- Emit FatalIOError if excess tokens exist - void excessTokens(const word& keyword, const ITstream& is) const; + //- Check after reading if the input token stream has unconsumed + //- tokens remaining or if there were no tokens in the first place. + // Emits FatalIOError + void checkITstream(const word& keyword, const ITstream& is) const; public: diff --git a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C index 95cd8ab8a7..fab47e6488 100644 --- a/src/OpenFOAM/db/dictionary/dictionaryTemplates.C +++ b/src/OpenFOAM/db/dictionary/dictionaryTemplates.C @@ -97,7 +97,7 @@ bool Foam::dictionary::readCompat ITstream& is = finder.ptr()->stream(); is >> val; - excessTokens(keyword, is); + checkITstream(keyword, is); return true; } @@ -144,7 +144,7 @@ T Foam::dictionary::lookupOrDefault ITstream& is = finder.ptr()->stream(); is >> val; - excessTokens(keyword, is); + checkITstream(keyword, is); return val; } @@ -178,7 +178,7 @@ T Foam::dictionary::lookupOrAddDefault ITstream& is = finder.ptr()->stream(); is >> val; - excessTokens(keyword, is); + checkITstream(keyword, is); return val; } @@ -212,7 +212,7 @@ bool Foam::dictionary::readEntry ITstream& is = finder.ptr()->stream(); is >> val; - excessTokens(keyword, is); + checkITstream(keyword, is); return true; } @@ -262,7 +262,7 @@ T Foam::dictionary::lookupOrDefaultCompat ITstream& is = finder.ptr()->stream(); is >> val; - excessTokens(keyword, is); + checkITstream(keyword, is); return val; } diff --git a/src/OpenFOAM/global/argList/argList.C b/src/OpenFOAM/global/argList/argList.C index bb03845536..84a6736bd6 100644 --- a/src/OpenFOAM/global/argList/argList.C +++ b/src/OpenFOAM/global/argList/argList.C @@ -202,32 +202,46 @@ static void printBuildInfo(const bool full=true) // * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // -void Foam::argList::warnTrailing(const ITstream& is, const label index) +void Foam::argList::checkITstream(const ITstream& is, const label index) { - const label nExcess = is.nRemainingTokens(); + const label remaining = is.nRemainingTokens(); - if (nExcess) + if (remaining) { std::cerr << nl << "--> FOAM WARNING:" << nl << "argument " << index << " has " - << nExcess << " excess tokens" << nl << nl; + << remaining << " excess tokens" << nl << nl; + } + else if (!is.size()) + { + std::cerr + << nl + << "--> FOAM WARNING:" << nl + << "argument " << index << " had no tokens" << nl << nl; } } -void Foam::argList::warnTrailing(const ITstream& is, const word& optName) +void Foam::argList::checkITstream(const ITstream& is, const word& optName) { - const label nExcess = is.nRemainingTokens(); + const label remaining = is.nRemainingTokens(); - if (nExcess) + if (remaining) { std::cerr << nl << "--> FOAM WARNING:" << nl << "option -" << optName << " has " - << nExcess << " excess tokens" << nl << nl; + << remaining << " excess tokens" << nl << nl; + } + else if (!is.size()) + { + std::cerr + << nl + << "--> FOAM WARNING:" << nl + << "option -" << optName << " had no tokens" << nl << nl; } } @@ -1141,7 +1155,7 @@ void Foam::argList::parse source = "-hostRoots"; ITstream is = this->lookup("hostRoots"); List<Tuple2<wordRe, fileName>> hostRoots(is); - warnTrailing(is, "hostRoots"); + checkITstream(is, "hostRoots"); for (const auto& hostRoot : hostRoots) { diff --git a/src/OpenFOAM/global/argList/argList.H b/src/OpenFOAM/global/argList/argList.H index ba1baa8f3a..3bcc32ea1e 100644 --- a/src/OpenFOAM/global/argList/argList.H +++ b/src/OpenFOAM/global/argList/argList.H @@ -161,11 +161,15 @@ class argList const string& str ); - //- Warn if there are input tokens remaining on the stream - static void warnTrailing(const ITstream& is, const label index); - - //- Warn if there are input tokens remaining on the stream - static void warnTrailing(const ITstream& is, const word& optName); + //- Check after reading if the input token stream has unconsumed + //- tokens remaining or if there were no tokens in the first place. + // Emits Warning + static void checkITstream(const ITstream& is, const label index); + + //- Check after reading if the input token stream has unconsumed + //- tokens remaining or if there were no tokens in the first place. + // Emits Warning + static void checkITstream(const ITstream& is, const word& optName); //- Read a List of values from ITstream, //- treating a single entry like a list of size 1. diff --git a/src/OpenFOAM/global/argList/argListI.H b/src/OpenFOAM/global/argList/argListI.H index 8457a4cf82..c473becff1 100644 --- a/src/OpenFOAM/global/argList/argListI.H +++ b/src/OpenFOAM/global/argList/argListI.H @@ -230,7 +230,7 @@ inline T Foam::argList::get(const label index) const T val; is >> val; - warnTrailing(is, index); + checkITstream(is, index); return val; } @@ -244,7 +244,7 @@ inline T Foam::argList::opt(const word& optName) const T val; is >> val; - warnTrailing(is, optName); + checkITstream(is, optName); return val; } @@ -309,7 +309,7 @@ inline Foam::List<T> Foam::argList::getList(const label index) const List<T> list; readList(is, list); - warnTrailing(is, index); + checkITstream(is, index); return list; } @@ -323,7 +323,7 @@ inline Foam::List<T> Foam::argList::getList(const word& optName) const List<T> list; readList(is, list); - warnTrailing(is, optName); + checkITstream(is, optName); return list; } @@ -341,7 +341,7 @@ inline bool Foam::argList::readListIfPresent ITstream is(optName, options_[optName]); readList(is, list); - warnTrailing(is, optName); + checkITstream(is, optName); return true; } -- GitLab