mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: improve/simplify streaming of exprValue
- ensure that operator<< and operator>> behave symmetrically
This commit is contained in:
@ -1,3 +0,0 @@
|
||||
Test-exprValue.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-exprValue
|
||||
3
applications/test/exprValue1/Make/files
Normal file
3
applications/test/exprValue1/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-exprValue1.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-exprValue1
|
||||
@ -11,7 +11,7 @@ License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
|
||||
Application
|
||||
Test-exprValue
|
||||
Test-exprValue1
|
||||
|
||||
Description
|
||||
Test low-level polymorphic value container (exprValue)
|
||||
@ -59,11 +59,11 @@ expressions::exprValue tryParse(const std::string& str)
|
||||
Info<< "Direct from string: ";
|
||||
if (expressions::exprValue::read(str, val2))
|
||||
{
|
||||
Info<< "good" << nl;
|
||||
Info<< "OK" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "bad" << nl;
|
||||
Info<< "NOK" << nl;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
@ -128,21 +128,22 @@ int main(int argc, char *argv[])
|
||||
|
||||
expressions::exprValue oldValue(value);
|
||||
|
||||
// Since the IO serialization is not symmetric (in ASCII) there
|
||||
// is no 'operator>>' defined and thus the regular Pstream::broadcast
|
||||
// will not compile.
|
||||
// Even although the data are contiguous and that code branch is never
|
||||
// used.
|
||||
|
||||
// Fails to compile: Pstream::broadcast(value);
|
||||
|
||||
// Broadcast manually
|
||||
UPstream::broadcast
|
||||
(
|
||||
value.data_bytes(),
|
||||
value.size_bytes(),
|
||||
UPstream::worldComm
|
||||
);
|
||||
if (true)
|
||||
{
|
||||
// Broadcast with serialization
|
||||
Pstream::broadcast(value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Broadcast manually
|
||||
UPstream::broadcast
|
||||
(
|
||||
value.data_bytes(),
|
||||
value.size_bytes(),
|
||||
UPstream::worldComm
|
||||
);
|
||||
}
|
||||
|
||||
Pout<< "same values: " << (oldValue == value) << nl;
|
||||
|
||||
5
applications/test/exprValue2/Make/files
Normal file
5
applications/test/exprValue2/Make/files
Normal file
@ -0,0 +1,5 @@
|
||||
exprValueFieldTag.cxx
|
||||
|
||||
Test-exprValue2.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-exprValue2
|
||||
1
applications/test/exprValue2/Make/options
Normal file
1
applications/test/exprValue2/Make/options
Normal file
@ -0,0 +1 @@
|
||||
/* EXE_INC = */
|
||||
143
applications/test/exprValue2/Test-exprValue2.cxx
Normal file
143
applications/test/exprValue2/Test-exprValue2.cxx
Normal file
@ -0,0 +1,143 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 exprValue uniformity checks
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "IOobject.H"
|
||||
#include "IOstreams.H"
|
||||
#include "labelList.H"
|
||||
#include "scalarField.H"
|
||||
#include "vectorField.H"
|
||||
#include "DynamicList.H"
|
||||
#include "Random.H"
|
||||
#include "exprValue.H"
|
||||
#include "exprValueFieldTag.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
Ostream& printInfo(const expressions::exprValueFieldTag& tag)
|
||||
{
|
||||
tag.print(Pout);
|
||||
return Pout;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
using fieldTag = expressions::exprValueFieldTag;
|
||||
|
||||
Random rnd(123456);
|
||||
|
||||
argList::noCheckProcessorDirectories();
|
||||
|
||||
#include "setRootCase.H"
|
||||
|
||||
{
|
||||
scalarField fld1(20);
|
||||
scalarField fld2a(20, Zero);
|
||||
scalarField fld2b(10, 3.10);
|
||||
scalarField fld3;
|
||||
|
||||
forAll(fld1, i)
|
||||
{
|
||||
fld1[i] = rnd.position<scalar>(0, 20);
|
||||
}
|
||||
|
||||
fieldTag tag1(fld1.begin(), fld1.end());
|
||||
fieldTag tag2a(fld2a.begin(), fld2a.end());
|
||||
fieldTag tag2b(fld2b.begin(), fld2b.end());
|
||||
fieldTag tag3(fld3.begin(), fld3.end());
|
||||
|
||||
printInfo(tag1) << nl;
|
||||
printInfo(tag2a) << nl;
|
||||
printInfo(tag2b) << nl;
|
||||
printInfo(tag3) << nl;
|
||||
|
||||
fieldTag result;
|
||||
|
||||
result = fieldTag::combineOp{}(tag1, tag2a);
|
||||
printInfo(result) << nl;
|
||||
|
||||
Info<< "combine: ";
|
||||
printInfo(tag2a) << " and ";
|
||||
printInfo(tag2b) << nl;
|
||||
|
||||
result = fieldTag::combineOp{}(tag2a, tag2b);
|
||||
printInfo(result) << nl;
|
||||
}
|
||||
|
||||
{
|
||||
vectorField fld2a(20, Foam::zero{});
|
||||
vectorField fld2b(10, vector::uniform(3.10));
|
||||
|
||||
fieldTag tag2a(fld2a.begin(), fld2a.end());
|
||||
fieldTag tag2b(fld2b.begin(), fld2b.end());
|
||||
|
||||
printInfo(tag2a) << nl;
|
||||
printInfo(tag2b) << nl;
|
||||
|
||||
fieldTag result;
|
||||
|
||||
Info<< "combine: ";
|
||||
printInfo(tag2a) << " and ";
|
||||
printInfo(tag2b) << nl;
|
||||
|
||||
result = fieldTag::combineOp{}(tag2a, tag2b);
|
||||
printInfo(result) << nl;
|
||||
}
|
||||
|
||||
if (UPstream::parRun())
|
||||
{
|
||||
scalarField fld;
|
||||
|
||||
if (!UPstream::master())
|
||||
{
|
||||
fld.resize(UPstream::myProcNo(), UPstream::myProcNo());
|
||||
}
|
||||
|
||||
fieldTag oldTag(fld.begin(), fld.end());
|
||||
|
||||
printInfo(oldTag) << " input: " << fld << " <- before reduce" << nl;
|
||||
|
||||
fieldTag newTag = returnReduce(oldTag, fieldTag::combineOp());
|
||||
|
||||
printInfo(newTag) << " <- after reduce" << nl;
|
||||
}
|
||||
|
||||
|
||||
Info<< "\nEnd\n" << nl;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
170
applications/test/exprValue2/exprValueFieldTag.H
Normal file
170
applications/test/exprValue2/exprValueFieldTag.H
Normal file
@ -0,0 +1,170 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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/>.
|
||||
|
||||
Class
|
||||
Foam::expressions::exprValueFieldTag
|
||||
|
||||
Description
|
||||
A polymorphic single-value container for tracking Field content
|
||||
as uniform etc.
|
||||
|
||||
SourceFiles
|
||||
exprValueFieldTag.cxx
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_expressions_exprValueFieldTag_H
|
||||
#define Foam_expressions_exprValueFieldTag_H
|
||||
|
||||
#include "exprValue.H"
|
||||
#include "List.H" // For ListPolicy
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace expressions
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class exprValueFieldTag Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class exprValueFieldTag
|
||||
{
|
||||
// Private data
|
||||
|
||||
//- Uniformity of field
|
||||
int uniformity_{};
|
||||
|
||||
//- Representative (uniform) value for the field
|
||||
expressions::exprValue value_{};
|
||||
|
||||
public:
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct
|
||||
exprValueFieldTag() = default;
|
||||
|
||||
//- Construct from a range of values
|
||||
template<class Type>
|
||||
explicit exprValueFieldTag(const Type* first, const Type* last)
|
||||
{
|
||||
set(first, last);
|
||||
}
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- True if the uniformity is "empty"
|
||||
bool empty() const noexcept;
|
||||
|
||||
//- True if the uniformity is "uniform"
|
||||
bool is_uniform() const noexcept;
|
||||
|
||||
//- True if the uniformity is "non-uniform"
|
||||
bool is_nonuniform() const noexcept;
|
||||
|
||||
//- Test for equality of the values
|
||||
bool equal(const exprValueFieldTag& rhs) const;
|
||||
|
||||
//- Set value and uniformity from range of data
|
||||
template<class Type>
|
||||
void set(const Type* first, const Type* last)
|
||||
{
|
||||
uniformity_ =
|
||||
Foam::Detail::ListPolicy::check_uniformity(first, last);
|
||||
|
||||
if (first != last) // or uniformity_ != EMPTY
|
||||
{
|
||||
value_.set<Type>(*first);
|
||||
}
|
||||
else
|
||||
{
|
||||
value_.set<Type>(Foam::zero{});
|
||||
}
|
||||
}
|
||||
|
||||
//- Set uniform type and value
|
||||
template<class Type>
|
||||
void set_uniform(const Type& val)
|
||||
{
|
||||
uniformity_ = Foam::Detail::ListPolicy::uniformity::UNIFORM;
|
||||
value_.set<Type>(val);
|
||||
}
|
||||
|
||||
//- Set as non-uniform
|
||||
void set_nouniform() noexcept;
|
||||
|
||||
|
||||
// Reduction operations
|
||||
|
||||
//- Combine - eg, for global uniformity
|
||||
void combine(const exprValueFieldTag& b);
|
||||
|
||||
//- Binary operator to be used by reduce function for detecting
|
||||
//- global uniformity
|
||||
struct combineOp
|
||||
{
|
||||
exprValueFieldTag operator()
|
||||
(
|
||||
const exprValueFieldTag& a,
|
||||
const exprValueFieldTag& b
|
||||
) const
|
||||
{
|
||||
exprValueFieldTag result(a);
|
||||
result.combine(b);
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// IO Operations
|
||||
|
||||
void read(Istream& is);
|
||||
void write(Ostream& os) const;
|
||||
|
||||
//- Print description to Ostream
|
||||
void print(Ostream& os) const;
|
||||
};
|
||||
|
||||
} // End namespace expressions
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// IO
|
||||
Istream& operator>>(Istream&, expressions::exprValueFieldTag&);
|
||||
Ostream& operator<<(Ostream&, const expressions::exprValueFieldTag&);
|
||||
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
||||
160
applications/test/exprValue2/exprValueFieldTag.cxx
Normal file
160
applications/test/exprValue2/exprValueFieldTag.cxx
Normal file
@ -0,0 +1,160 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
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 "exprValueFieldTag.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
bool Foam::expressions::exprValueFieldTag::empty() const noexcept
|
||||
{
|
||||
return
|
||||
(
|
||||
uniformity_ == Foam::Detail::ListPolicy::uniformity::EMPTY
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValueFieldTag::is_uniform() const noexcept
|
||||
{
|
||||
return
|
||||
(
|
||||
uniformity_ == Foam::Detail::ListPolicy::uniformity::UNIFORM
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValueFieldTag::is_nonuniform() const noexcept
|
||||
{
|
||||
return
|
||||
(
|
||||
uniformity_ == Foam::Detail::ListPolicy::uniformity::NONUNIFORM
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValueFieldTag::equal
|
||||
(
|
||||
const exprValueFieldTag& rhs
|
||||
) const
|
||||
{
|
||||
return (value_ == rhs.value_);
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValueFieldTag::set_nouniform() noexcept
|
||||
{
|
||||
uniformity_ = Foam::Detail::ListPolicy::uniformity::NONUNIFORM;
|
||||
value_ = Foam::zero{};
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValueFieldTag::combine
|
||||
(
|
||||
const exprValueFieldTag& b
|
||||
)
|
||||
{
|
||||
if (b.empty())
|
||||
{
|
||||
// no-op
|
||||
return;
|
||||
}
|
||||
|
||||
exprValueFieldTag& a = *this;
|
||||
|
||||
if (a.empty())
|
||||
{
|
||||
a = b;
|
||||
}
|
||||
else if (a.is_nonuniform())
|
||||
{
|
||||
// Already non-uniform/mixed
|
||||
// a.uniformity_ |= b.uniformity_;
|
||||
|
||||
a.value_ = Foam::zero{};
|
||||
}
|
||||
else if (a.is_uniform() && b.is_uniform())
|
||||
{
|
||||
// Both are uniform, but are they the same value?
|
||||
if (!a.equal(b))
|
||||
{
|
||||
a.set_nouniform();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
void Foam::expressions::exprValueFieldTag::read(Istream& is)
|
||||
{
|
||||
label uniformTag;
|
||||
|
||||
is >> uniformTag;
|
||||
uniformity_ = int(uniformTag);
|
||||
value_.read(is);
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValueFieldTag::write(Ostream& os) const
|
||||
{
|
||||
os << label(uniformity_);
|
||||
value_.write(os, false); // No pruning
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValueFieldTag::print(Ostream& os) const
|
||||
{
|
||||
os << "{ uniform:"
|
||||
<< label(uniformity_)
|
||||
<< " type:" << label(value_.typeCode())
|
||||
<< " value: " << value_ << " }";
|
||||
}
|
||||
|
||||
|
||||
Foam::Istream& Foam::operator>>
|
||||
(
|
||||
Istream& is,
|
||||
expressions::exprValueFieldTag& tag
|
||||
)
|
||||
{
|
||||
tag.read(is);
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const expressions::exprValueFieldTag& tag
|
||||
)
|
||||
{
|
||||
tag.write(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -61,7 +61,37 @@ Foam::expressions::Detail::nComponents
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
return pTraits<Type>::nComponents; \
|
||||
return exprTypeTraits<Type>::nComponents; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Foam::direction
|
||||
Foam::expressions::Detail::rank
|
||||
(
|
||||
const expressions::valueTypeCode typeCode
|
||||
) noexcept
|
||||
{
|
||||
switch (typeCode)
|
||||
{
|
||||
case expressions::valueTypeCode::NONE :
|
||||
case expressions::valueTypeCode::INVALID :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
return exprTypeTraits<Type>::rank; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||
@ -112,7 +142,7 @@ Foam::word Foam::name(const expressions::valueTypeCode typeCode)
|
||||
|
||||
case expressions::valueTypeCode::INVALID :
|
||||
{
|
||||
// returns ""
|
||||
// returns "", could also return "bad"
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@ -117,6 +117,9 @@ namespace Detail
|
||||
//- The number of components associated with given valueTypeCode
|
||||
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept;
|
||||
|
||||
//- The vector-space rank associated with given valueTypeCode
|
||||
::Foam::direction rank(const expressions::valueTypeCode) noexcept;
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
|
||||
@ -129,6 +129,10 @@ Foam::expressions::exprValue::peekType(const ITstream& is)
|
||||
|
||||
switch (endCmpti - firstCmpti)
|
||||
{
|
||||
case 0: // Explicitly provided '()' - ie, none
|
||||
whichCode = expressions::valueTypeCode::NONE;
|
||||
break;
|
||||
|
||||
case 1: // pTraits<sphericalTensor>::nComponents
|
||||
whichCode = exprTypeTraits<sphericalTensor>::value;
|
||||
break;
|
||||
@ -177,6 +181,13 @@ Foam::expressions::exprValue::peekType(const ITstream& is)
|
||||
{
|
||||
whichCode = exprTypeTraits<bool>::value;
|
||||
}
|
||||
|
||||
// Treat anything else as 'invalid', which also implicitly
|
||||
// includes the token "bad"
|
||||
// else if (tok0.isWord("bad"))
|
||||
// {
|
||||
// whichCode = expressions::valueTypeCode::INVALID;
|
||||
// }
|
||||
}
|
||||
|
||||
return whichCode;
|
||||
@ -192,7 +203,7 @@ bool Foam::expressions::exprValue::read
|
||||
ITstream is(str);
|
||||
|
||||
// No trailing non-whitespace!
|
||||
return (val.read(is) && !is.nRemainingTokens());
|
||||
return (val.readTokens(is) && !is.nRemainingTokens());
|
||||
}
|
||||
|
||||
|
||||
@ -215,10 +226,33 @@ void Foam::expressions::exprValue::deepCopy(const exprValue& rhs)
|
||||
}
|
||||
|
||||
|
||||
Foam::tokenList Foam::expressions::exprValue::tokens() const
|
||||
Foam::tokenList Foam::expressions::exprValue::tokens(bool prune) const
|
||||
{
|
||||
// Handling for NONE, INVALID:
|
||||
// - NONE => pair of ( ) brackets
|
||||
// - INVALID => "bad" as a word
|
||||
//
|
||||
// With prune:
|
||||
// - no output for either
|
||||
|
||||
tokenList toks;
|
||||
|
||||
if (!prune)
|
||||
{
|
||||
if (typeCode_ == expressions::valueTypeCode::NONE)
|
||||
{
|
||||
toks.resize(2);
|
||||
toks.front() = token::BEGIN_LIST;
|
||||
toks.back() = token::END_LIST;
|
||||
return toks;
|
||||
}
|
||||
else if (typeCode_ == expressions::valueTypeCode::INVALID)
|
||||
{
|
||||
toks.emplace_back(word("bad"));
|
||||
return toks;
|
||||
}
|
||||
}
|
||||
|
||||
switch (typeCode_)
|
||||
{
|
||||
#undef doLocalCode
|
||||
@ -245,8 +279,29 @@ Foam::tokenList Foam::expressions::exprValue::tokens() const
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValue::print(Ostream& os) const
|
||||
void Foam::expressions::exprValue::write(Ostream& os, bool prune) const
|
||||
{
|
||||
// Handling for NONE, INVALID:
|
||||
// - NONE => pair of ( ) brackets
|
||||
// - INVALID => "bad" as a word
|
||||
//
|
||||
// With prune:
|
||||
// - no output for either
|
||||
|
||||
if (!prune)
|
||||
{
|
||||
if (typeCode_ == expressions::valueTypeCode::NONE)
|
||||
{
|
||||
os << token::BEGIN_LIST << token::END_LIST;
|
||||
return;
|
||||
}
|
||||
else if (typeCode_ == expressions::valueTypeCode::INVALID)
|
||||
{
|
||||
os << word("bad");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (typeCode_)
|
||||
{
|
||||
#undef doLocalCode
|
||||
@ -271,12 +326,87 @@ void Foam::expressions::exprValue::print(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValue::read(ITstream& is)
|
||||
bool Foam::expressions::exprValue::read(Istream& is)
|
||||
{
|
||||
ITstream* stream = dynamic_cast<ITstream*>(&is);
|
||||
|
||||
// Reading via tokens - simple for now
|
||||
// Expect either a single token (scalar, label, word etc)
|
||||
// or ( ... ) content
|
||||
|
||||
ITstream toks;
|
||||
|
||||
if (!stream)
|
||||
{
|
||||
token tok(is);
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
if (tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
// Expecting "( content )" - eg, (x y z), (xx xy ...)
|
||||
do
|
||||
{
|
||||
toks.add_tokens(tok);
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
}
|
||||
while (!tok.isPunctuation(token::END_LIST));
|
||||
|
||||
if (tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
toks.add_tokens(tok);
|
||||
}
|
||||
}
|
||||
else if (tok.good())
|
||||
{
|
||||
toks.add_tokens(tok);
|
||||
}
|
||||
|
||||
// Truncate to number tokens read
|
||||
toks.resize(toks.tokenIndex());
|
||||
toks.seek(0);
|
||||
|
||||
stream = &toks;
|
||||
}
|
||||
|
||||
return readTokens(*stream);
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValue::readTokens(ITstream& is)
|
||||
{
|
||||
clear(); // type: none, value: zero
|
||||
|
||||
const valueTypeCode whichCode(exprValue::peekType(is));
|
||||
|
||||
if (whichCode == expressions::valueTypeCode::NONE)
|
||||
{
|
||||
typeCode_ = whichCode;
|
||||
is.skip(2); // Skip tokens: '( )'
|
||||
return true;
|
||||
}
|
||||
|
||||
// This one should be rare or even impossible
|
||||
if (whichCode == expressions::valueTypeCode::INVALID)
|
||||
{
|
||||
typeCode_ = whichCode;
|
||||
|
||||
if (is.bad())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
const token& tok0 = is.peek();
|
||||
|
||||
if (tok0.isWord("bad"))
|
||||
{
|
||||
is.skip(1); // Skip token: "bad"
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
switch (whichCode)
|
||||
{
|
||||
#undef doLocalCode
|
||||
@ -347,13 +477,24 @@ bool Foam::expressions::exprValue::operator<(const exprValue& rhs) const
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
Foam::Istream& Foam::operator>>
|
||||
(
|
||||
Istream& is,
|
||||
expressions::exprValue& val
|
||||
)
|
||||
{
|
||||
val.read(is);
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const expressions::exprValue& val
|
||||
)
|
||||
{
|
||||
val.print(os);
|
||||
val.write(os, false); // no pruning
|
||||
return os;
|
||||
}
|
||||
|
||||
@ -367,16 +508,18 @@ Foam::Ostream& Foam::operator<<
|
||||
{
|
||||
const auto& val = *iproxy;
|
||||
|
||||
if (val.good())
|
||||
if (val.typeCode() == expressions::valueTypeCode::NONE)
|
||||
{
|
||||
os << val.valueTypeName() << ": ";
|
||||
val.print(os);
|
||||
os << "none";
|
||||
}
|
||||
else if (val.typeCode() == expressions::valueTypeCode::INVALID)
|
||||
{
|
||||
os << "bad";
|
||||
}
|
||||
else
|
||||
{
|
||||
// typeCode_ is *never* set to INVALID,
|
||||
// so NONE is the only remaining non-good type
|
||||
os << "none";
|
||||
os << val.valueTypeName() << ": ";
|
||||
val.write(os); // pruning is immaterial - !good() already handled
|
||||
}
|
||||
|
||||
return os;
|
||||
|
||||
@ -169,7 +169,7 @@ class exprValue
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Assign zero, preserving the data type
|
||||
//- Fill the data with zero, preserving the data type
|
||||
inline void fill_zero();
|
||||
|
||||
//- Copy assignment
|
||||
@ -215,6 +215,12 @@ public:
|
||||
const expressions::valueTypeCode
|
||||
) noexcept;
|
||||
|
||||
//- The vector-space rank associated with the valueTypeCode
|
||||
inline static direction rank
|
||||
(
|
||||
const expressions::valueTypeCode
|
||||
) noexcept;
|
||||
|
||||
//- True if the specified type is supported
|
||||
template<class Type>
|
||||
inline static bool supportedType();
|
||||
@ -250,6 +256,9 @@ public:
|
||||
//- The number of components associated with the value type
|
||||
inline direction nComponents() const noexcept;
|
||||
|
||||
//- The vector-space rank associated with the value type
|
||||
inline direction rank() const noexcept;
|
||||
|
||||
//- The name for the value type. Similar to pTraits typeName
|
||||
inline word valueTypeName() const;
|
||||
|
||||
@ -260,9 +269,13 @@ public:
|
||||
//- Reset to 'none'
|
||||
void clear();
|
||||
|
||||
//- Read read tokens (if possible)
|
||||
// \return True on success
|
||||
bool read(Istream& is);
|
||||
|
||||
//- Guess type and read tokens (if possible)
|
||||
// \return True on success
|
||||
bool read(ITstream& is);
|
||||
bool readTokens(ITstream& is);
|
||||
|
||||
|
||||
// Typed Access
|
||||
@ -346,11 +359,19 @@ public:
|
||||
//- Return info proxy for printing information to a stream
|
||||
InfoProxy<exprValue> info() const { return *this; }
|
||||
|
||||
//- The value as tokens. An empty list is returned for NONE.
|
||||
tokenList tokens() const;
|
||||
//- The exprValue as tokens.
|
||||
// For none : emits pair of brackets.
|
||||
// For invalid : emits "bad".
|
||||
//
|
||||
// \param prune suppress the output for none/invalid
|
||||
tokenList tokens(bool prune = false) const;
|
||||
|
||||
//- Print the (type-specific) content
|
||||
void print(Ostream& os) const;
|
||||
//- Write the (type-specific) content.
|
||||
// For none : emits pair of brackets.
|
||||
// For invalid : emits "bad".
|
||||
//
|
||||
// \param prune suppress the output for none/invalid
|
||||
void write(Ostream& os, bool prune = false) const;
|
||||
};
|
||||
|
||||
|
||||
@ -364,7 +385,11 @@ template<> struct is_contiguous<expressions::exprValue> : std::true_type {};
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
//- Write value to output stream in ASCII format. No output for !good().
|
||||
//- Read/parse value from input stream (uses ASCII format).
|
||||
Istream& operator>>(Istream& is, expressions::exprValue& val);
|
||||
|
||||
//- Write value to output stream (uses ASCII format).
|
||||
//- Writes 'none' or 'bad' for unknown/unsupported types.
|
||||
Ostream& operator<<(Ostream& os, const expressions::exprValue& val);
|
||||
|
||||
template<>
|
||||
|
||||
@ -64,6 +64,15 @@ inline Foam::direction Foam::expressions::exprValue::nComponents
|
||||
}
|
||||
|
||||
|
||||
inline Foam::direction Foam::expressions::exprValue::rank
|
||||
(
|
||||
const expressions::valueTypeCode valTypeCode
|
||||
) noexcept
|
||||
{
|
||||
return expressions::Detail::rank(valTypeCode);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline bool Foam::expressions::exprValue::supportedType()
|
||||
{
|
||||
@ -110,7 +119,7 @@ inline Foam::expressions::exprValue::exprValue(const Type& val)
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot construct for unsupported type: "
|
||||
<< typeid(Type).name() << endl
|
||||
<< typeid(Type).name() << nl
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
@ -137,6 +146,13 @@ Foam::expressions::exprValue::nComponents() const noexcept
|
||||
}
|
||||
|
||||
|
||||
inline Foam::direction
|
||||
Foam::expressions::exprValue::rank() const noexcept
|
||||
{
|
||||
return expressions::Detail::rank(typeCode_);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::word
|
||||
Foam::expressions::exprValue::valueTypeName() const
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user