STYLE: relegate special purpose readList<T> function to points of use

- the readList<T>(Istream&) function was introduced to handle command
  -options with either a single or a list value, but was also used for
  the #remove dictionary directive. However, the parsing was fragile
  if the list did not start with a '('.
  Now handle command-line arg/option list directly (via ITstream)
  and #remove with special-purpose reading of a string or word list.

  This removes ambiguity and reduces potential future problems.

STYLE: use ITstream instead of IStringStream for command-line lookups

- parses directly to a tokenList without a string copy.
This commit is contained in:
Mark Olesen
2017-11-26 12:45:49 +01:00
parent 5947f9a337
commit 2787a8664d
10 changed files with 115 additions and 71 deletions

View File

@ -308,17 +308,6 @@ public:
}; };
//- Read a bracket-delimited list, or handle a single value as list of size 1
// For example,
// \code
// wList = readList<word>(IStringStream("(patch1 patch2 patch3)")());
// wList = readList<word>(IStringStream("patch0")());
// \endcode
// Mostly useful for handling command-line arguments
template<class T>
List<T> readList(Istream& is);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam } // End namespace Foam

View File

@ -159,39 +159,4 @@ Foam::Istream& Foam::operator>>(Istream& is, List<T>& L)
} }
template<class T>
Foam::List<T> Foam::readList(Istream& is)
{
List<T> L;
token firstToken(is);
is.putBack(firstToken);
if (firstToken.isPunctuation())
{
if (firstToken.pToken() != token::BEGIN_LIST)
{
FatalIOErrorInFunction(is)
<< "incorrect first token, expected '(', found "
<< firstToken.info()
<< exit(FatalIOError);
}
// Read as singly-linked list
SLList<T> sll(is);
// Convert the singly-linked list to this list
L = sll;
}
else
{
// Create list with a single item
L.setSize(1);
is >> L[0];
}
return L;
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -7,7 +7,7 @@
#warn | dict | entry introducer #warn | dict | entry introducer
#error | dict | entry introducer #error | dict | entry introducer
| | | |
#remove | dict | readList<keyType> #remove | dict | keyType or List<keyType>
| | | |
#include | dict/primitive | string #include | dict/primitive | string
#includeEtc | dict/primitive | string #includeEtc | dict/primitive | string
@ -24,7 +24,7 @@ Pending future extensions
|-------------------|-------------------|-------------------|----------------- |-------------------|-------------------|-------------------|-----------------
#define | dict | entry introducer #define | dict | entry introducer
#local | dict | entry introducer #local | dict | entry introducer
#undef | dict | readList<word> #undef | dict | keyType or List<keyType>
2017-11-05 2017-11-26

View File

@ -27,7 +27,7 @@ License
#include "IOstreams.H" #include "IOstreams.H"
#include "ISstream.H" #include "ISstream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
@ -47,7 +47,7 @@ namespace Foam
} }
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
Foam::token Foam::functionEntry::readLine(const word& key, Istream& is) Foam::token Foam::functionEntry::readLine(const word& key, Istream& is)
{ {

View File

@ -67,9 +67,6 @@ class functionEntry
{ {
// Private Member Functions // Private Member Functions
//- Read line as string token
static token readLine(const word& key, Istream& is);
//- Disallow default bitwise copy construct //- Disallow default bitwise copy construct
functionEntry(const functionEntry&) = delete; functionEntry(const functionEntry&) = delete;
@ -77,6 +74,16 @@ class functionEntry
void operator=(const functionEntry&) = delete; void operator=(const functionEntry&) = delete;
protected:
//- Read line and return as a string token
static token readLine(const word& key, Istream& is);
//- Read a List of strings values, treating a single entry like a
//- list of size 1.
template<class StringType>
static List<StringType> readStringList(Istream& is);
public: public:
// Constructors // Constructors
@ -142,6 +149,12 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#ifdef NoRepository
#include "functionEntryTemplates.C"
#endif
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif #endif
// ************************************************************************* // // ************************************************************************* //

View File

@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 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/>.
\*---------------------------------------------------------------------------*/
#include "functionEntry.H"
#include "ISstream.H"
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
template<class StringType>
Foam::List<StringType>
Foam::functionEntry::readStringList(Istream& is)
{
ISstream& iss = dynamic_cast<ISstream&>(is);
token firstToken(iss);
List<StringType> list;
if (firstToken.isWord() || firstToken.isString())
{
// The first token appears viable as non-list
// - treated like list with one entry
iss.putBack(firstToken);
list.setSize(1);
iss >> list[0];
}
else
{
iss.putBack(firstToken);
iss >> list;
}
return list;
}
// ************************************************************************* //

View File

@ -54,7 +54,7 @@ bool Foam::functionEntries::removeEntry::execute
Istream& is Istream& is
) )
{ {
const List<keyType> patterns = readList<keyType>(is); const List<keyType> patterns = functionEntry::readStringList<keyType>(is);
for (const keyType& key : patterns) for (const keyType& key : patterns)
{ {

View File

@ -916,8 +916,19 @@ void Foam::argList::parse
{ {
distributed_ = true; distributed_ = true;
source = "-roots"; source = "-roots";
IStringStream is(options_["roots"]); ITstream is("roots", options_["roots"]);
roots = readList<fileName>(is);
if (is.size() == 1)
{
// Single token - treated like list with one entry
roots.setSize(1);
is >> roots[0];
}
else
{
is >> roots;
}
if (roots.size() != 1) if (roots.size() != 1)
{ {

View File

@ -101,8 +101,8 @@ SourceFiles
#include "word.H" #include "word.H"
#include "fileName.H" #include "fileName.H"
#include "parRun.H" #include "parRun.H"
#include "StringStream.H"
#include "OSspecific.H" #include "OSspecific.H"
#include "ITstream.H"
#include <utility> #include <utility>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -302,8 +302,8 @@ public:
//- Return true if the named option is found //- Return true if the named option is found
inline bool optionFound(const word& optionName) const; inline bool optionFound(const word& optionName) const;
//- Return an IStringStream from the named option //- Return an input token stream for the named option
inline IStringStream optionLookup(const word& optionName) const; inline ITstream optionLookup(const word& optionName) const;
//- Read a value from the named option //- Read a value from the named option
template<class T> template<class T>

View File

@ -24,7 +24,6 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "argList.H" #include "argList.H"
#include "ITstream.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -106,12 +105,12 @@ inline bool Foam::argList::optionFound(const word& optionName) const
} }
inline Foam::IStringStream Foam::argList::optionLookup inline Foam::ITstream Foam::argList::optionLookup
( (
const word& optionName const word& optionName
) const ) const
{ {
return IStringStream(options_[optionName]); return ITstream(optionName, options_[optionName]);
} }
@ -205,9 +204,12 @@ namespace Foam
template<class T> template<class T>
inline T Foam::argList::argRead(const label argIndex) const inline T Foam::argList::argRead(const label argIndex) const
{ {
T val; ITstream is(Foam::name(argIndex), args_[argIndex]);
IStringStream(args_[argIndex])() >> val; T val;
is >> val;
// Could also check is.nRemainingTokens() to detect trailing rubbish
return val; return val;
} }
@ -215,9 +217,12 @@ inline T Foam::argList::argRead(const label argIndex) const
template<class T> template<class T>
inline T Foam::argList::optionRead(const word& optionName) const inline T Foam::argList::optionRead(const word& optionName) const
{ {
T val; ITstream is(optionName, options_[optionName]);
IStringStream(options_[optionName])() >> val; T val;
is >> val;
// Could also check is.nRemainingTokens() to detect trailing rubbish
return val; return val;
} }
@ -281,18 +286,18 @@ inline Foam::List<T> Foam::argList::optionReadList
{ {
List<T> list; List<T> list;
ITstream its(optionName, options_[optionName]); ITstream is(optionName, options_[optionName]);
if (its.size() == 1) if (is.size() == 1)
{ {
// Single token - treated like list with one entry // Single token - treated like list with one entry
list.setSize(1); list.setSize(1);
its >> list[0]; is >> list[0];
} }
else else
{ {
its >> list; is >> list;
} }
return list; return list;