Commit 7d880758 authored by Mark Olesen's avatar Mark Olesen
Browse files

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.
parent 77753021
......@@ -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;
......
......@@ -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);
}
}
}
......
......@@ -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:
......
......@@ -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;
}
......
......@@ -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)
{
......
......@@ -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.
......
......@@ -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;
}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment