ENH: argList::optionReadList now uses ITstream directly

- stricter and robuster than previous solution using List::readList
  since the option input can be fully tokenized prior to list
  conversion.
This commit is contained in:
Mark Olesen
2017-11-24 10:39:20 +01:00
parent d3d82b909e
commit 9985b93cfc
3 changed files with 159 additions and 200 deletions

View File

@ -165,25 +165,25 @@ void Foam::argList::addArgument(const string& argumentName)
void Foam::argList::addBoolOption void Foam::argList::addBoolOption
( (
const word& opt, const word& optionName,
const string& usage const string& usage
) )
{ {
addOption(opt, "", usage); addOption(optionName, "", usage);
} }
void Foam::argList::addOption void Foam::argList::addOption
( (
const word& opt, const word& optionName,
const string& param, const string& param,
const string& usage const string& usage
) )
{ {
validOptions.set(opt, param); validOptions.set(optionName, param);
if (!usage.empty()) if (!usage.empty())
{ {
optionUsage.set(opt, usage); optionUsage.set(optionName, usage);
} }
} }
@ -204,17 +204,17 @@ void Foam::argList::addOptionCompat
void Foam::argList::addUsage void Foam::argList::addUsage
( (
const word& opt, const word& optionName,
const string& usage const string& usage
) )
{ {
if (usage.empty()) if (usage.empty())
{ {
optionUsage.erase(opt); optionUsage.erase(optionName);
} }
else else
{ {
optionUsage.set(opt, usage); optionUsage.set(optionName, usage);
} }
} }
@ -228,10 +228,10 @@ void Foam::argList::addNote(const string& note)
} }
void Foam::argList::removeOption(const word& opt) void Foam::argList::removeOption(const word& optionName)
{ {
validOptions.erase(opt); validOptions.erase(optionName);
optionUsage.erase(opt); optionUsage.erase(optionName);
} }
@ -1231,111 +1231,55 @@ Foam::argList::~argList()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::argList::setOption(const word& opt, const string& param) bool Foam::argList::setOption(const word& optionName, const string& param)
{ {
bool changed = false; // Some options are always protected
if
// Only allow valid options (
if (validOptions.found(opt)) optionName == "case"
|| optionName == "parallel"
|| optionName == "roots"
)
{ {
// Some options are to be protected FatalErrorInFunction
if <<"Option: '" << optionName << "' is protected" << nl
( << exit(FatalError);
opt == "case" return false;
|| opt == "parallel"
|| opt == "roots"
)
{
FatalError
<<"used argList::setOption on a protected option: '"
<< opt << "'" << endl;
FatalError.exit();
}
if (validOptions[opt].empty())
{
// Bool option
if (!param.empty())
{
// Disallow change of type
FatalError
<<"used argList::setOption to change bool to non-bool: '"
<< opt << "'" << endl;
FatalError.exit();
}
else
{
// Did not previously exist
changed = !options_.found(opt);
}
}
else
{
// Non-bool option
if (param.empty())
{
// Disallow change of type
FatalError
<<"used argList::setOption to change non-bool to bool: '"
<< opt << "'" << endl;
FatalError.exit();
}
else
{
// Existing value needs changing, or did not previously exist
changed = options_.found(opt) ? options_[opt] != param : true;
}
}
}
else
{
FatalError
<<"used argList::setOption on an invalid option: '"
<< opt << "'" << nl << "allowed are the following:"
<< validOptions << endl;
FatalError.exit();
} }
// Set/change the option as required if
if (changed) (
options_.found(optionName)
? (options_[optionName] != param)
: true
)
{ {
options_.set(opt, param); options_.set(optionName, param);
return true;
} }
return changed; return false;
} }
bool Foam::argList::unsetOption(const word& opt) bool Foam::argList::unsetOption(const word& optionName)
{ {
// Only allow valid options // Some options are always protected
if (validOptions.found(opt)) if
(
optionName == "case"
|| optionName == "parallel"
|| optionName == "roots"
)
{ {
// Some options are to be protected FatalErrorInFunction
if <<"Option: '" << optionName << "' is protected" << nl
( << exit(FatalError);
opt == "case" return false;
|| opt == "parallel"
|| opt == "roots"
)
{
FatalError
<<"used argList::unsetOption on a protected option: '"
<< opt << "'" << endl;
FatalError.exit();
}
// Remove the option, return true if state changed
return options_.erase(opt);
} }
FatalError // Remove the option, return true if state changed
<<"used argList::unsetOption on an invalid option: '" return options_.erase(optionName);
<< opt << "'" << nl << "allowed are the following:"
<< validOptions << endl;
FatalError.exit();
return false;
} }

View File

@ -277,47 +277,46 @@ public:
//- Return the path to the caseName //- Return the path to the caseName
inline fileName path() const; inline fileName path() const;
//- Return arguments //- The command arguments (non-options)
inline const stringList& args() const; inline const stringList& args() const;
//- Return non-const access to arguments //- Non-const access to the command arguments (non-options)
inline stringList& args(); inline stringList& args();
//- Return the argument corresponding to index. //- Return the number of arguments, which includes the name of
inline const string& arg(const label index) const; //- the executable
//- Return the number of arguments
inline label size() const; inline label size() const;
//- Read a value from the argument at index. //- Read a value from the argument at the given index.
// Index 0 corresponds to the name of the executable. // Index 0 corresponds to the name of the executable.
// Index 1 corresponds to the first argument. // Index 1 corresponds to the first argument.
template<class T> template<class T>
inline T argRead(const label index) const; inline T argRead(const label argIndex) const;
//- Return options //- Return the command options
inline const HashTable<string>& options() const; inline const HashTable<string>& options() const;
//- Return non-const access to options //- Return non-const access to the command options
inline HashTable<string>& options(); inline HashTable<string>& options();
//- Return the argument string associated with the named option
inline const string& option(const word& opt) const;
//- Return true if the named option is found //- Return true if the named option is found
inline bool optionFound(const word& opt) const; inline bool optionFound(const word& optionName) const;
//- Return an IStringStream from the named option //- Return an IStringStream from the named option
inline IStringStream optionLookup(const word& opt) const; inline IStringStream 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>
inline T optionRead(const word& opt) const; inline T optionRead(const word& optionName) const;
//- Read a value from the named option if present. //- Read a value from the named option if present.
// Return true if the named option was found. // Return true if the named option was found.
template<class T> template<class T>
inline bool optionReadIfPresent(const word& opt, T& val) const; inline bool optionReadIfPresent
(
const word& optionName,
T& val
) const;
//- Read a value from the named option if present. //- Read a value from the named option if present.
// Return true if the named option was found, otherwise // Return true if the named option was found, otherwise
@ -325,7 +324,7 @@ public:
template<class T> template<class T>
inline bool optionReadIfPresent inline bool optionReadIfPresent
( (
const word& opt, const word& optionName,
T& val, T& val,
const T& deflt const T& deflt
) const; ) const;
@ -335,25 +334,23 @@ public:
template<class T> template<class T>
inline T optionLookupOrDefault inline T optionLookupOrDefault
( (
const word& opt, const word& optionName,
const T& deflt const T& deflt
) const; ) const;
//- Read a List of values from the named option //- Read a List of values from the named option,
//- treating a single entry like a list of size 1.
template<class T> template<class T>
List<T> optionReadList(const word& opt) const inline List<T> optionReadList(const word& optionName) const;
{
return Foam::readList<T>(optionLookup(opt)());
}
//- Return the argument corresponding to index. //- Return the argument corresponding to index.
// Index 0 corresponds to the name of the executable. // Index 0 corresponds to the name of the executable.
// Index 1 corresponds to the first argument. // Index 1 corresponds to the first argument.
inline const string& operator[](const label index) const; inline const string& operator[](const label argIndex) const;
//- Return the argument string associated with the named option //- Return the string associated with the named option
inline const string& operator[](const word& opt) const; inline const string& operator[](const word& optionName) const;
// Edit // Edit
@ -364,7 +361,7 @@ public:
//- Add a bool option to validOptions with usage information //- Add a bool option to validOptions with usage information
static void addBoolOption static void addBoolOption
( (
const word& opt, const word& optionName,
const string& usage = "" const string& usage = ""
); );
@ -372,7 +369,7 @@ public:
// An option with an empty param is a bool option // An option with an empty param is a bool option
static void addOption static void addOption
( (
const word& opt, const word& optionName,
const string& param = "", const string& param = "",
const string& usage = "" const string& usage = ""
); );
@ -393,7 +390,7 @@ public:
//- Add option usage information to optionUsage //- Add option usage information to optionUsage
static void addUsage static void addUsage
( (
const word& opt, const word& optionName,
const string& usage const string& usage
); );
@ -402,7 +399,7 @@ public:
static void addNote(const string& note); static void addNote(const string& note);
//- Remove option from validOptions and from optionUsage //- Remove option from validOptions and from optionUsage
static void removeOption(const word& opt); static void removeOption(const word& optionName);
//- Flag command arguments as being non-mandatory //- Flag command arguments as being non-mandatory
static void nonMandatoryArgs(); static void nonMandatoryArgs();
@ -432,14 +429,14 @@ public:
//- Set option directly (use with caution) //- Set option directly (use with caution)
// An option with an empty param is a bool option. // An option with an empty param is a bool option.
// Not all valid options can also be set: eg, -case, -roots, ... // Not all valid options can also be set: eg, -case, -roots, ...
// Return true if the existing option value needed changing, // \return true if the existing option value was changed or
// or if the option did not previously exist. // did not previously exist.
bool setOption(const word& opt, const string& param = ""); bool setOption(const word& optionName, const string& param="");
//- Unset option directly (use with caution) //- Unset option directly (use with caution)
// Not all valid options can also be unset: eg, -case, -roots ... // Not all valid options can also be unset: eg, -case, -roots ...
// Return true if the option existed before being unset. // \return true if the option existed before being unset.
bool unsetOption(const word& opt); bool unsetOption(const word& optionName);
// Print // Print

View File

@ -24,6 +24,7 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "argList.H" #include "argList.H"
#include "ITstream.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
@ -81,12 +82,6 @@ inline Foam::stringList& Foam::argList::args()
} }
inline const Foam::string& Foam::argList::arg(const label index) const
{
return args_[index];
}
inline Foam::label Foam::argList::size() const inline Foam::label Foam::argList::size() const
{ {
return args_.size(); return args_.size();
@ -105,21 +100,18 @@ inline Foam::HashTable<Foam::string>& Foam::argList::options()
} }
inline const Foam::string& Foam::argList::option(const word& opt) const inline bool Foam::argList::optionFound(const word& optionName) const
{ {
return options_[opt]; return options_.found(optionName);
} }
inline bool Foam::argList::optionFound(const word& opt) const inline Foam::IStringStream Foam::argList::optionLookup
(
const word& optionName
) const
{ {
return options_.found(opt); return IStringStream(options_[optionName]);
}
inline Foam::IStringStream Foam::argList::optionLookup(const word& opt) const
{
return IStringStream(options_[opt]);
} }
@ -133,37 +125,37 @@ namespace Foam
template<> template<>
inline Foam::string inline Foam::string
argList::argRead<Foam::string>(const label index) const argList::argRead<Foam::string>(const label argIndex) const
{ {
return args_[index]; return args_[argIndex];
} }
template<> template<>
inline Foam::word inline Foam::word
argList::argRead<Foam::word>(const label index) const argList::argRead<Foam::word>(const label argIndex) const
{ {
return args_[index]; return args_[argIndex];
} }
template<> template<>
inline Foam::fileName inline Foam::fileName
argList::argRead<Foam::fileName>(const label index) const argList::argRead<Foam::fileName>(const label argIndex) const
{ {
return args_[index]; return args_[argIndex];
} }
template<> template<>
inline Foam::label inline Foam::label
argList::argRead<Foam::label>(const label index) const argList::argRead<Foam::label>(const label argIndex) const
{ {
return Foam::readLabel(args_[index]); return Foam::readLabel(args_[argIndex]);
} }
template<> template<>
inline Foam::scalar inline Foam::scalar
argList::argRead<Foam::scalar>(const label index) const argList::argRead<Foam::scalar>(const label argIndex) const
{ {
return Foam::readScalar(args_[index]); return Foam::readScalar(args_[argIndex]);
} }
// //
@ -172,37 +164,37 @@ namespace Foam
template<> template<>
inline Foam::string inline Foam::string
argList::optionRead<Foam::string>(const word& opt) const argList::optionRead<Foam::string>(const word& optionName) const
{ {
return options_[opt]; return options_[optionName];
} }
template<> template<>
inline Foam::word inline Foam::word
argList::optionRead<Foam::word>(const word& opt) const argList::optionRead<Foam::word>(const word& optionName) const
{ {
return options_[opt]; return options_[optionName];
} }
template<> template<>
inline Foam::fileName inline Foam::fileName
argList::optionRead<Foam::fileName>(const word& opt) const argList::optionRead<Foam::fileName>(const word& optionName) const
{ {
return options_[opt]; return options_[optionName];
} }
template<> template<>
inline Foam::label inline Foam::label
argList::optionRead<Foam::label>(const word& opt) const argList::optionRead<Foam::label>(const word& optionName) const
{ {
return Foam::readLabel(options_[opt]); return Foam::readLabel(options_[optionName]);
} }
template<> template<>
inline Foam::scalar inline Foam::scalar
argList::optionRead<Foam::scalar>(const word& opt) const argList::optionRead<Foam::scalar>(const word& optionName) const
{ {
return Foam::readScalar(options_[opt]); return Foam::readScalar(options_[optionName]);
} }
} }
@ -211,21 +203,21 @@ namespace Foam
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T> template<class T>
inline T Foam::argList::argRead(const label index) const inline T Foam::argList::argRead(const label argIndex) const
{ {
T val; T val;
IStringStream(args_[index])() >> val; IStringStream(args_[argIndex])() >> val;
return val; return val;
} }
template<class T> template<class T>
inline T Foam::argList::optionRead(const word& opt) const inline T Foam::argList::optionRead(const word& optionName) const
{ {
T val; T val;
optionLookup(opt)() >> val; IStringStream(options_[optionName])() >> val;
return val; return val;
} }
@ -233,71 +225,97 @@ inline T Foam::argList::optionRead(const word& opt) const
template<class T> template<class T>
inline bool Foam::argList::optionReadIfPresent inline bool Foam::argList::optionReadIfPresent
( (
const word& opt, const word& optionName,
T& val T& val
) const ) const
{ {
if (optionFound(opt)) if (optionFound(optionName))
{ {
val = optionRead<T>(opt); val = optionRead<T>(optionName);
return true; return true;
} }
else
{ return false;
return false;
}
} }
template<class T> template<class T>
inline bool Foam::argList::optionReadIfPresent inline bool Foam::argList::optionReadIfPresent
( (
const word& opt, const word& optionName,
T& val, T& val,
const T& deflt const T& deflt
) const ) const
{ {
if (optionReadIfPresent<T>(opt, val)) if (optionReadIfPresent<T>(optionName, val))
{ {
return true; return true;
} }
else
{ val = deflt;
val = deflt; return false;
return false;
}
} }
template<class T> template<class T>
inline T Foam::argList::optionLookupOrDefault inline T Foam::argList::optionLookupOrDefault
( (
const word& opt, const word& optionName,
const T& deflt const T& deflt
) const ) const
{ {
if (optionFound(opt)) if (optionFound(optionName))
{ {
return optionRead<T>(opt); return optionRead<T>(optionName);
}
return deflt;
}
template<class T>
inline Foam::List<T> Foam::argList::optionReadList
(
const word& optionName
) const
{
List<T> list;
ITstream its(optionName, options_[optionName]);
if (its.size() == 1)
{
// Single token - treated like list with one entry
list.setSize(1);
its >> list[0];
} }
else else
{ {
return deflt; its >> list;
} }
return list;
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline const Foam::string& Foam::argList::operator[](const label index) const inline const Foam::string& Foam::argList::operator[]
(
const label argIndex
) const
{ {
return args_[index]; return args_[argIndex];
} }
inline const Foam::string& Foam::argList::operator[](const word& opt) const inline const Foam::string& Foam::argList::operator[]
(
const word& optionName
) const
{ {
return options_[opt]; return options_[optionName];
} }