ENH: improve robustness of scalarRanges from string (fixes #673)

- now avoid Istream and token mechanism in favour of a simpler string
  parser. This makes the code clearer, smaller, robuster.

- provide convenience ge/gt/le/lt static constructors for scalarRange
  for using bounds directly with specifying via a string parameter.

- scalarRange, scalarRanges now follow the unary predicate pattern
  (using an operator() for testing). This allows their reuse in
  other contexts. Eg, for filtering operations:

      myHash.filterValues(scalarRange::ge(100));

- remove unused scalarRanges methods that were specific to handling
  lists of time values. These were superseded by timeSelector methods
  several versions ago.
This commit is contained in:
Mark Olesen 2018-01-08 09:59:04 +01:00
parent 85eb441bea
commit f55a42a835
12 changed files with 540 additions and 482 deletions

View File

@ -0,0 +1,3 @@
Test-scalarRanges.C
EXE = $(FOAM_USER_APPBIN)/Test-scalarRanges

View File

@ -0,0 +1,112 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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/>.
Description
Test scalar ranges
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "scalarRanges.H"
using namespace Foam;
template<class HTable>
Ostream& printHash(const HTable& h)
{
const auto keys = h.sortedToc();
Info<<"keys: " << keys.size() << "(";
for (const auto& k : keys)
{
Info<<" " << k;
}
Info<< " )" << nl;
Info<<"vals: " << keys.size() << "(";
for (const auto& k : keys)
{
Info<<" " << h[k];
}
Info<< " )" << nl;
return Info;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noParallel();
argList::noFunctionObjects();
argList::addArgument("range,range range,range");
argList::addNote
(
"Test parsing of comma-separated ranges\n\n"
"Eg, ':10,20,40:70,1000:'"
);
argList args(argc, argv, false, true);
HashTable<scalar> testHash;
for (label i = 0; i < 26; ++i)
{
word key("X");
key[0] = 'a' + i;
testHash.insert(key, i);
key[0] = 'A' + i;
testHash.insert(key, 100 + i);
}
printHash(testHash)
<< nl;
for (int argi = 1; argi < argc; ++argi)
{
Info<<"tokenize " << args[argi] << nl;
scalarRanges ranges(args[argi]);
Info<<"=> " << ranges << endl;
HashTable<scalar> subHash(testHash);
subHash.filterValues(ranges);
Info<<"filtered:" << nl;
printHash(subHash)
<< nl;
subHash.filterValues(scalarRange::le(8));
Info<<"filtered <= 8:" << nl;
printHash(subHash)
<< nl;
}
return 0;
}
// ************************************************************************* //

View File

@ -813,7 +813,6 @@ DebugSwitches
saturateEvaporationModel 0;
scalarAverageField 0;
scalarField 0;
scalarRange 0;
scaleSimilarity 0;
scatterModel 0;
searchableBox 0;

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2017 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +27,6 @@ License
#include "ListOps.H"
#include "argList.H"
#include "Time.H"
#include "StringStream.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
@ -37,9 +36,9 @@ Foam::timeSelector::timeSelector()
{}
Foam::timeSelector::timeSelector(Istream& is)
Foam::timeSelector::timeSelector(const std::string& str)
:
scalarRanges(is)
scalarRanges(str)
{}
@ -47,7 +46,7 @@ Foam::timeSelector::timeSelector(Istream& is)
bool Foam::timeSelector::selected(const instant& value) const
{
return scalarRanges::selected(value.value());
return scalarRanges::operator()(value.value());
}
@ -67,7 +66,7 @@ Foam::List<bool> Foam::timeSelector::selected(const instantList& times) const
// Check specific values
for (const scalarRange& range : *this)
{
if (range.isExact())
if (range.single())
{
const scalar target = range.value();
@ -97,8 +96,7 @@ Foam::List<bool> Foam::timeSelector::selected(const instantList& times) const
}
Foam::instantList Foam::timeSelector::select(const instantList& times)
const
Foam::instantList Foam::timeSelector::select(const instantList& times) const
{
return subset(selected(times), times);
}
@ -211,10 +209,7 @@ Foam::instantList Foam::timeSelector::select
if (args.optionFound("time"))
{
// Can match 0/, but can never match constant/
selectTimes = timeSelector
(
args.optionLookup("time")()
).selected(times);
selectTimes = timeSelector(args["time"]).selected(times);
}
// Add in latestTime (if selected)
@ -301,7 +296,7 @@ Foam::instantList Foam::timeSelector::selectIfPresent
}
// No timeSelector option specified. Do not change runTime.
return instantList(1, instant(runTime.value(), runTime.timeName()));
return instantList{ instant(runTime.value(), runTime.timeName()) };
}

View File

@ -3,7 +3,7 @@
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011-2015 OpenFOAM Foundation
\\/ M anipulation |
\\/ M anipulation | Copyright (C) 2018 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,17 +89,17 @@ class Time;
class timeSelector
:
public scalarRanges
private scalarRanges
{
public:
// Constructors
//- Construct Null
//- Construct null
timeSelector();
//- Construct from Istream
timeSelector(Istream& is);
//- Construct by parsing string for time ranges
timeSelector(const std::string& str);
// Member Functions

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -24,334 +24,106 @@ License
\*---------------------------------------------------------------------------*/
#include "scalarRange.H"
#include "token.H"
#include "string.H"
#include "error.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
namespace Foam
bool Foam::scalarRange::parse(const std::string& str, scalarRange& range)
{
int scalarRange::debug(debug::debugSwitch("scalarRange", 0));
}
range.clear();
const auto colon = str.find(':');
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::scalarRange::scalarRange()
:
type_(EMPTY),
value_(0),
value2_(0)
{}
Foam::scalarRange::scalarRange(const scalar lower, const scalar upper)
:
type_(RANGE),
value_(lower),
value2_(upper)
{
if (lower > upper)
if (colon == std::string::npos)
{
clear(); // Mark invalid range as empty
// "VALUE"
scalar val;
if (readScalar(str, val))
{
range = scalarRange(val);
}
}
}
Foam::scalarRange::scalarRange(Istream& is)
:
type_(EXACT),
value_(0),
value2_(0)
{
is >> *this;
if (scalarRange::debug)
else if (str.find(':', colon+1) != std::string::npos)
{
Info<<"constructed scalarRange: " << *this << endl;
// A second colon is a syntax error
return false;
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::scalarRange::clear()
{
type_ = scalarRange::EMPTY;
value_ = 0;
value2_ = 0;
}
bool Foam::scalarRange::empty() const
{
return type_ == EMPTY;
}
bool Foam::scalarRange::valid() const
{
return type_ != EMPTY;
}
bool Foam::scalarRange::isExact() const
{
return type_ == EXACT;
}
Foam::scalar Foam::scalarRange::value() const
{
return value_;
}
Foam::scalar Foam::scalarRange::lower() const
{
if (type_ == UPPER)
else if (colon == 0)
{
return -Foam::GREAT;
// ":MAX"
scalar val;
if (readScalar(str.substr(1), val))
{
range = scalarRange::le(val);
}
}
else if (colon == str.size()-1)
{
// "MIN:"
scalar val;
if (readScalar(str.substr(0, colon), val))
{
range = scalarRange::ge(val);
}
}
else
{
return value_;
// "MIN:MAX"
scalar minVal, maxVal;
if
(
readScalar(str.substr(0, colon), minVal)
&& readScalar(str.substr(colon+1), maxVal)
)
{
range = scalarRange(minVal, maxVal);
}
}
return range.valid();
}
Foam::scalar Foam::scalarRange::upper() const
Foam::scalarRange Foam::scalarRange::parse(const std::string& str)
{
switch (type_)
scalarRange range;
if (!parse(str, range))
{
case LOWER:
return Foam::GREAT;
break;
case RANGE:
return value2_;
break;
default:
return value_;
break;
Info<< "Bad scalar-range while parsing: " << str << endl;
}
}
bool Foam::scalarRange::selected(const scalar value) const
{
switch (type_)
{
case LOWER:
return value >= value_;
case UPPER:
return value <= value_;
case RANGE:
return value >= value_ && value <= value2_;
case EXACT:
return value == value_;
default:
return false;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
bool Foam::scalarRange::operator==(const scalarRange& range) const
{
return
(
type_ == range.type_
&& value_ == range.value_
&& value2_ == range.value2_
);
}
bool Foam::scalarRange::operator!=(const scalarRange& range) const
{
return !(operator==(range));
return range;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
Foam::Istream& Foam::operator>>(Istream& is, scalarRange& range)
{
range.type_ = scalarRange::EXACT;
range.value_ = 0;
range.value2_ = 0;
List<token> toks(4);
label nTok = 0;
// skip leading ','
do
{
is.read(toks[nTok]);
is.check("scalarRange token read");
}
while
(
toks[nTok].isPunctuation()
&& toks[nTok].pToken() == token::COMMA
);
++nTok;
// looks like ':VALUE'
if
(
toks[nTok-1].isPunctuation()
&& toks[nTok-1].pToken() == token::COLON
)
{
range.type_ = scalarRange::UPPER;
is.read(toks[nTok++]);
is.check("scalarRange token read");
}
// a number is now required
if (!toks[nTok-1].isNumber())
{
range.clear(); // Mark invalid range as empty
Info<< "rejected ill-formed or empty range:";
for (label i=0; i<nTok; ++i)
{
Info<< " " << toks[i];
}
Info<< endl;
is.setBad();
return is;
}
range.value_ = toks[nTok-1].number();
is.read(toks[nTok++]);
is.check("scalarRange token read");
if (scalarRange::debug)
{
Info<<"tokens:";
for (label i=0; i<nTok; ++i)
{
Info<< " " << toks[i];
}
Info<< endl;
}
// could be 'VALUE:' or 'VALUE:VALUE'
if
(
toks[nTok-1].isPunctuation()
&& toks[nTok-1].pToken() == token::COLON
)
{
if (range.type_ == scalarRange::UPPER)
{
range.clear(); // Mark invalid range as empty
Info<< "rejected ill-formed range:";
for (label i=0; i<nTok; ++i)
{
Info<< " " << toks[i];
}
Info<< endl;
is.setBad();
return is;
}
is.read(toks[nTok++]);
is.check("scalarRange token read");
if (scalarRange::debug)
{
Info<<"tokens:";
for (label i=0; i<nTok; ++i)
{
Info<< " " << toks[i];
}
Info<< endl;
}
// if there is a number, we have 'VALUE:VALUE' and not simply 'VALUE:'
if (toks[nTok-1].isNumber())
{
range.type_ = scalarRange::RANGE;
range.value2_ = toks[nTok-1].number();
is.read(toks[nTok++]);
is.check("scalarRange token read");
}
else
{
range.type_ = scalarRange::LOWER;
}
}
if (scalarRange::debug)
{
Info<<"tokens:";
for (label i=0; i<nTok; ++i)
{
Info<< " " << toks[i];
}
Info<< endl;
}
// some remaining tokens, but they are not the next comma
// - this is a problem!
if
(
toks[nTok-1].good()
&&
(
!toks[nTok-1].isPunctuation()
|| toks[nTok-1].pToken() != token::COMMA
)
)
{
range.clear(); // Mark invalid range as empty
Info<< "rejected ill-formed range:";
for (label i=0; i<nTok; ++i)
{
Info<< " " << toks[i];
}
Info<< endl;
is.setBad();
return is;
}
return is;
}
Foam::Ostream& Foam::operator<<(Ostream& os, const scalarRange& range)
{
switch (range.type_)
{
case scalarRange::LOWER:
os << range.value_ << " <=> Inf";
case scalarRange::EQ:
os << range.min_;
break;
case scalarRange::UPPER:
os << "-Inf <=> " << range.value_;
case scalarRange::GE:
case scalarRange::GT:
os << range.min_ << ":Inf";
break;
case scalarRange::RANGE:
os << range.value_ << " <=> " << range.value2_;
case scalarRange::LE:
case scalarRange::LT:
os << "-Inf:" << range.max_;
break;
case scalarRange::EXACT:
os << range.value_;
case scalarRange::GE_LE:
os << range.min_ << ":" << range.max_;
break;
default:
os << "empty";
os << "false";
break;
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -25,12 +25,10 @@ Class
Foam::scalarRange
Description
A scalar range specifier.
Scalar bounds to be used as a unary predicate.
The range selector can be specified as an "LOWER:UPPER" range, as a
"LOWER:" bound, as an ":UPPER" bound or simply as an "EXACT" value.
The read constructor uses a colon (:) as a range marker and a comma (,)
to delimit the next possible range selector.
The bound can be specified as an "MIN:MAX" range, as a "MIN:" or ":MAX"
bound or simply as a single "VALUE".
SourceFiles
scalarRange.C
@ -46,96 +44,125 @@ SourceFiles
namespace Foam
{
// Forward declaration of classes
class Istream;
class Ostream;
// Forward declaration of friend functions and operators
// Forward declarations
class scalarRange;
Istream& operator>>(Istream& is, scalarRange& range);
class Ostream;
Ostream& operator<<(Ostream& os, const scalarRange& range);
/*---------------------------------------------------------------------------*\
Class scalarRange Declaration
Class scalarRange Declaration
\*---------------------------------------------------------------------------*/
class scalarRange
{
//- Enumeration defining the types of token
enum rangeType
//- Enumeration defining type of range test to use
enum testType
{
EMPTY = 0,
EXACT,
LOWER,
UPPER,
RANGE
NONE = 0, //!< An empty, invalid (inverse) range. Never matches.
EQ, //!< A single value test.
GE, //!< Greater-than-equal.
GT, //!< Greater-than.
LE, //!< Less-than-equal.
LT, //!< Less-than.
GE_LE //!< An inclusive range.
};
// Private Member Data
enum rangeType type_;
scalar value_;
scalar value2_;
//- The type of range test
enum testType type_;
//- The min value of the range
scalar min_;
//- The max value of the range
scalar max_;
//- Construct from components without sanity checking
inline scalarRange(const testType type, scalar minVal, scalar maxVal);
public:
static int debug;
// Constructors
//- Construct an empty range
scalarRange();
//- Construct an empty (inverse) range
inline scalarRange();
//- Construct a range from lower to upper
scalarRange(const scalar lower, const scalar upper);
//- Construct an exact value matcher
explicit inline scalarRange(const scalar value);
//- Construct from Istream.
// Since commas can be used as list delimiters,
// leading and trailing commas are ignored.
scalarRange(Istream& is);
//- Construct a range from min-value to max-value
inline scalarRange(const scalar minVal, const scalar maxVal);
// Static Constructors
//- Construct by parsing string content.
// A colon (:) is used as a range marker or when specifying
// greater-than or less-than bounds.
// \return True if no parse problems were encountered.
static bool parse(const std::string& str, scalarRange& range);
//- Construct by parsing string content.
// Any parse problems are emitted as information and the returned
// range is of type empty().
// \return The parsed range, which is empty() on any problems
static scalarRange parse(const std::string& str);
//- Construct a greater-than-equals bound
inline static scalarRange ge(const scalar minVal);
//- Construct a greater-than bound
inline static scalarRange gt(const scalar minVal);
//- Construct a less-than-equals bound
inline static scalarRange le(const scalar maxVal);
//- Construct a less-than bound
inline static scalarRange lt(const scalar maxVal);
// Member Functions
//- Reset to an empty range.
void clear();
//- Reset to an empty (inverse) range.
inline void clear();
//- Is the range empty?
bool empty() const;
//- True if bounds are empty (eg, inverted)
inline bool empty() const;
//- Is the range non-empty?
bool valid() const;
//- True if bounds are non-empty.
inline bool valid() const;
//- Is the range 'EXACT'?
bool isExact() const;
//- True if the bounds represents a single value.
inline bool single() const;
//- The value constituting an 'EXACT' match
// or the values for 'UPPER' or 'LOWER' limits
scalar value() const;
//- The min value of the range.
inline scalar min() const;
//- The lower limit
scalar lower() const;
//- The max value of the range.
inline scalar max() const;
//- The upper limit
scalar upper() const;
//- Return true if the value is within the range
bool selected(const scalar value) const;
//- A representative (average) value for the range.
// For GE, LE bounds it is the min/max value, respectively.
inline scalar value() const;
// Member Operators
bool operator==(const scalarRange& range) const;
bool operator!=(const scalarRange& range) const;
//- Unary predicate to test if the value is within the bounds
inline bool operator()(const scalar& value) const;
inline bool operator==(const scalarRange& rhs) const;
inline bool operator!=(const scalarRange& rhs) const;
// IOstream Operators
friend Istream& operator>>(Istream& is, scalarRange& range);
//- Print information about the bounds.
friend Ostream& operator<<(Ostream& os, const scalarRange& range);
};
@ -146,6 +173,8 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "scalarRangeI.H"
#endif
// ************************************************************************* //

View File

@ -0,0 +1,184 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::scalarRange::scalarRange
(
const scalarRange::testType type,
const scalar minVal,
const scalar maxVal
)
:
type_(type),
min_(minVal),
max_(maxVal)
{}
inline Foam::scalarRange::scalarRange()
:
scalarRange(NONE, Foam::VGREAT, -Foam::VGREAT)
{}
inline Foam::scalarRange::scalarRange(const scalar value)
:
scalarRange(EQ, value, value)
{}
inline Foam::scalarRange::scalarRange(const scalar minVal, const scalar maxVal)
:
scalarRange(GE_LE, minVal, maxVal)
{
if (minVal > maxVal)
{
clear(); // Inverted - explicitly mark as such
}
else if (minVal == maxVal)
{
type_ = EQ;
}
}
inline Foam::scalarRange Foam::scalarRange::ge(const scalar minVal)
{
return scalarRange(GE, minVal, Foam::VGREAT);
}
inline Foam::scalarRange Foam::scalarRange::gt(const scalar minVal)
{
return scalarRange(GT, minVal, Foam::VGREAT);
}
inline Foam::scalarRange Foam::scalarRange::le(const scalar maxVal)
{
return scalarRange(LE, -Foam::VGREAT, maxVal);
}
inline Foam::scalarRange Foam::scalarRange::lt(const scalar maxVal)
{
return scalarRange(LT, -Foam::VGREAT, maxVal);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
inline void Foam::scalarRange::clear()
{
type_ = scalarRange::NONE;
min_ = Foam::VGREAT;
max_ = -Foam::VGREAT;
}
inline bool Foam::scalarRange::empty() const
{
return type_ == NONE;
}
inline bool Foam::scalarRange::valid() const
{
return type_;
}
inline bool Foam::scalarRange::single() const
{
return type_ == EQ;
}
inline Foam::scalar Foam::scalarRange::min() const
{
return min_;
}
inline Foam::scalar Foam::scalarRange::max() const
{
return max_;
}
inline Foam::scalar Foam::scalarRange::value() const
{
switch (type_)
{
case EQ:
return min_; // For equals, min and max are identical
case GE:
case GT:
return min_;
case LE:
case LT:
return max_;
case GE_LE:
return 0.5*(min_ + max_);
default:
return 0;
}
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::scalarRange::operator()(const scalar& value) const
{
switch (type_)
{
case EQ: return equal(value, min_);
case GE: return value >= min_;
case GT: return value > min_;
case LE: return value <= max_;
case LT: return value < max_;
case GE_LE: return value >= min_ && value <= max_;
default: return false;
}
}
inline bool Foam::scalarRange::operator==(const scalarRange& rhs) const
{
return (type_ == rhs.type_ && min_ == rhs.min_ && max_ == rhs.max_);
}
inline bool Foam::scalarRange::operator!=(const scalarRange& rhs) const
{
return !(operator==(rhs));
}
// ************************************************************************* //

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -24,114 +24,35 @@ License
\*---------------------------------------------------------------------------*/
#include "scalarRanges.H"
#include "DynamicList.H"
#include "ListOps.H"
#include "stringOps.H"
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::scalarRanges::scalarRanges()
Foam::scalarRanges::scalarRanges(const std::string& str)
:
List<scalarRange>(0)
{}
Foam::scalarRanges::scalarRanges(Istream& is)
:
List<scalarRange>(0)
List<scalarRange>()
{
DynamicList<scalarRange> lst;
const SubStrings<std::string> items = stringOps::splitAny(str, " ,;");
while (is.good())
setSize(items.size());
label nItems = 0;
for (const auto& item : items)
{
scalarRange sr(is);
if (sr.valid())
const std::string s = item.str();
if (scalarRange::parse(s, operator[](nItems)))
{
lst.append(sr);
++nItems;
}
else
{
Info<< "Bad scalar-range while parsing: " << s << endl;
}
}
transfer(lst);
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::scalarRanges::selected(const scalar value) const
{
forAll(*this, i)
{
if (operator[](i).selected(value))
{
return true;
}
}
return false;
}
Foam::List<bool> Foam::scalarRanges::selected
(
const UList<scalar>& values
) const
{
List<bool> lst(values.size(), false);
// check ranges
forAll(values, i)
{
if (selected(values[i]))
{
lst[i] = true;
}
}
// check specific values
forAll(*this, rangeI)
{
if (operator[](rangeI).isExact())
{
scalar target = operator[](rangeI).value();
int nearestIndex = -1;
scalar nearestDiff = Foam::GREAT;
forAll(values, timeIndex)
{
scalar diff = fabs(values[timeIndex] - target);
if (diff < nearestDiff)
{
nearestDiff = diff;
nearestIndex = timeIndex;
}
}
if (nearestIndex >= 0)
{
lst[nearestIndex] = true;
}
}
}
return lst;
}
Foam::List<Foam::scalar> Foam::scalarRanges::select
(
const List<scalar>& values
) const
{
return subset(selected(values), values);
}
void Foam::scalarRanges::inplaceSelect
(
List<scalar>& values
) const
{
inplaceSubset(selected(values), values);
setSize(nItems);
}

View File

@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2011 OpenFOAM Foundation
\\ / A nd | Copyright (C) 2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
@ -25,7 +25,7 @@ Class
Foam::scalarRanges
Description
A List of scalarRange.
A collection of scalar bounds to be used as a unary predicate.
SourceFiles
scalarRanges.C
@ -44,7 +44,7 @@ namespace Foam
{
/*---------------------------------------------------------------------------*\
Class scalarRanges Declaration
Class scalarRanges Declaration
\*---------------------------------------------------------------------------*/
class scalarRanges
@ -56,27 +56,18 @@ public:
// Constructors
//- Construct null
scalarRanges();
inline scalarRanges();
//- Construct from Istream.
// The list items are comma-delimited.
scalarRanges(Istream& is);
//- Construct by parsing a string for scalar ranges
// The individual items are space, comma or semicolon delimited.
scalarRanges(const std::string& str);
// Member Functions
// Member Operators
//- Return true if the given value is within the ranges
bool selected(const scalar value) const;
//- Unary predicate to test if the value is within any of the ranges
inline bool operator()(const scalar& value) const;
//- Return the set of selected entries in the given list
// that are within the ranges
List<bool> selected(const UList<scalar>& values) const;
//- Select a list of values that are within the ranges
List<scalar> select(const List<scalar>& values) const;
//- Select a list of values that are within the ranges
void inplaceSelect(List<scalar>& values) const;
};
@ -86,6 +77,8 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "scalarRangesI.H"
#endif
// ************************************************************************* //

View File

@ -0,0 +1,50 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2018 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/>.
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::scalarRanges::scalarRanges()
:
List<scalarRange>()
{}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
inline bool Foam::scalarRanges::operator()(const scalar& value) const
{
for (const scalarRange& range : *this)
{
if (range(value))
{
return true;
}
}
return false;
}
// ************************************************************************* //