ENH: add low-level polymorphic/boxed exprValue
- primarily for handling expression results, but can also be used as a universal value holder. Has some characteristics suitable for type-less IO: eg, is_integral(), nComponents() ENH: add is_pointer() check for expression scanToken
This commit is contained in:
parent
fc2760ab9c
commit
5635e14f81
@ -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, distributed under GPL-3.0-or-later.
|
||||
@ -17,8 +17,9 @@ Description
|
||||
|
||||
#include "IOstreams.H"
|
||||
#include "ITstream.H"
|
||||
#include "exprTraits.H"
|
||||
#include "uLabel.H"
|
||||
|
||||
#include "exprTraits.H"
|
||||
#include "error.H"
|
||||
#include "stringList.H"
|
||||
#include "exprScanToken.H"
|
||||
@ -27,16 +28,18 @@ using namespace Foam;
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
template<class Type>
|
||||
void printTraits()
|
||||
{
|
||||
const auto typeCode = exprTypeTraits<T>::value;
|
||||
const auto typeCode = exprTypeTraits<Type>::value;
|
||||
|
||||
Info<< "type " << pTraits<T>::typeName
|
||||
<< " code:" << int(typeCode)
|
||||
<< " name:" << exprTypeTraits<T>::name;
|
||||
Info<< "Type '" << pTraits<Type>::typeName
|
||||
<< "' = code:" << int(typeCode)
|
||||
<< " rank:" << exprTypeTraits<Type>::rank
|
||||
<< " cmpt:" << exprTypeTraits<Type>::nComponents
|
||||
<< " name:" << exprTypeTraits<Type>::name;
|
||||
|
||||
if (pTraits<T>::typeName != word(exprTypeTraits<T>::name))
|
||||
if (pTraits<Type>::typeName != word(exprTypeTraits<Type>::name))
|
||||
{
|
||||
Info<< " (UNSUPPORTED)";
|
||||
}
|
||||
@ -45,6 +48,17 @@ void printTraits()
|
||||
}
|
||||
|
||||
|
||||
void print(const expressions::scanToken& tok)
|
||||
{
|
||||
Info<< " type:" << int(tok.type_);
|
||||
if (tok.is_pointer())
|
||||
{
|
||||
Info<< " ptr:" << Foam::name(tok.name_);
|
||||
}
|
||||
Info<< nl;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main()
|
||||
@ -56,6 +70,7 @@ int main()
|
||||
printTraits<bool>();
|
||||
printTraits<label>();
|
||||
printTraits<scalar>();
|
||||
printTraits<complex>();
|
||||
printTraits<vector>();
|
||||
printTraits<tensor>();
|
||||
printTraits<symmTensor>();
|
||||
@ -71,33 +86,27 @@ int main()
|
||||
Info<< "Name of typeCode: "
|
||||
<< getName(expressions::valueTypeCode::type_bool) << nl;
|
||||
|
||||
|
||||
{
|
||||
expressions::scanToken tok;
|
||||
expressions::scanToken tok2;
|
||||
expressions::scanToken tok(expressions::scanToken::null());
|
||||
expressions::scanToken tok2(expressions::scanToken::null());
|
||||
|
||||
Info<< nl << "sizeof(scanToken): "
|
||||
<< sizeof(tok) << nl;
|
||||
|
||||
Info<< " type:" << int(tok.type_) << nl;
|
||||
Info<< " ptr:" << Foam::name(tok.name_) << nl;
|
||||
|
||||
Info<< " type:" << int(tok2.type_) << nl;
|
||||
Info<< " ptr:" << Foam::name(tok2.name_) << nl;
|
||||
print(tok);
|
||||
print(tok2);
|
||||
|
||||
tok.setWord("hello");
|
||||
|
||||
Info<< " type:" << int(tok.type_) << nl;
|
||||
Info<< " ptr:" << Foam::name(tok.name_) << nl;
|
||||
print(tok);
|
||||
|
||||
tok2 = tok;
|
||||
Info<< " type:" << int(tok2.type_) << nl;
|
||||
Info<< " ptr:" << Foam::name(tok2.name_) << nl;
|
||||
print(tok2);
|
||||
|
||||
tok2.destroy();
|
||||
|
||||
Info<< " type:" << int(tok2.type_) << nl;
|
||||
Info<< " ptr:" << Foam::name(tok2.name_) << nl;
|
||||
print(tok); // Not a leak, but old rubbish
|
||||
print(tok2);
|
||||
}
|
||||
|
||||
Info<< nl << "Done" << nl;
|
||||
|
3
applications/test/exprValue/Make/files
Normal file
3
applications/test/exprValue/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-exprValue.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-exprValue
|
2
applications/test/exprValue/Make/options
Normal file
2
applications/test/exprValue/Make/options
Normal file
@ -0,0 +1,2 @@
|
||||
/* EXE_INC = */
|
||||
/* EXE_LIBS = */
|
141
applications/test/exprValue/Test-exprValue.C
Normal file
141
applications/test/exprValue/Test-exprValue.C
Normal file
@ -0,0 +1,141 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM, distributed under GPL-3.0-or-later.
|
||||
|
||||
Application
|
||||
Test-exprValue
|
||||
|
||||
Description
|
||||
Test low-level polymorphic value container (exprValue)
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "argList.H"
|
||||
#include "IOstreams.H"
|
||||
#include "ITstream.H"
|
||||
#include "exprValue.H"
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
void printInfo(const expressions::exprValue& val)
|
||||
{
|
||||
Info<< "Boxed type:" << int(val.typeCode())
|
||||
<< " (" << val.valueTypeName() << ") good:"
|
||||
<< val.good() << " => " << val << nl;
|
||||
}
|
||||
|
||||
|
||||
expressions::exprValue tryParse(const std::string& str)
|
||||
{
|
||||
expressions::exprValue val, val2;
|
||||
|
||||
ITstream is(str);
|
||||
|
||||
const bool ok = val.read(is);
|
||||
|
||||
Info<< "read " << Foam::name(val.typeCode()) << " from " << str;
|
||||
|
||||
if (ok)
|
||||
{
|
||||
Info<< " trailing tokens:" << is.nRemainingTokens() << nl
|
||||
<< "value: " << val << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< " FAILED" << nl;
|
||||
}
|
||||
|
||||
if (ok)
|
||||
{
|
||||
Info<< "Direct from string: ";
|
||||
if (expressions::exprValue::read(str, val2))
|
||||
{
|
||||
Info<< "good" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
Info<< "bad" << nl;
|
||||
}
|
||||
}
|
||||
return val;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noBanner();
|
||||
argList::noParallel();
|
||||
|
||||
#include "setRootCase.H"
|
||||
|
||||
// Aborts
|
||||
// expressions::exprValue value(std::string(""));
|
||||
|
||||
{
|
||||
expressions::exprValue value;
|
||||
|
||||
// Nothing
|
||||
printInfo(value);
|
||||
|
||||
value.set(scalar(100));
|
||||
printInfo(value);
|
||||
|
||||
value.set(vector(1,2,3));
|
||||
printInfo(value);
|
||||
|
||||
value = vector(4,5,6);
|
||||
printInfo(value);
|
||||
|
||||
value = Zero;
|
||||
printInfo(value);
|
||||
|
||||
value.clear();
|
||||
printInfo(value);
|
||||
|
||||
value = 100 * vector(1,0,0);
|
||||
printInfo(value);
|
||||
}
|
||||
|
||||
|
||||
{
|
||||
Info<< nl << "Test parsing" << nl << nl;
|
||||
|
||||
for
|
||||
(
|
||||
const auto& input :
|
||||
stringList
|
||||
({
|
||||
"()", // bad
|
||||
"( 1 2 ", // also bad
|
||||
"( ", // really bad
|
||||
"(1 16 12)",
|
||||
"(1 bad)",
|
||||
"(5)",
|
||||
"1.2345",
|
||||
"5.678 trailing",
|
||||
"true",
|
||||
"false",
|
||||
" 1 ",
|
||||
" yes no "
|
||||
})
|
||||
)
|
||||
{
|
||||
(void) tryParse(input);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
@ -183,6 +183,7 @@ $(expr)/exprTools/exprTools.C
|
||||
$(expr)/scanToken/exprScanToken.C
|
||||
|
||||
$(expr)/traits/exprTraits.C
|
||||
$(expr)/value/exprValue.C
|
||||
|
||||
$(expr)/exprDriver/exprDriver.C
|
||||
$(expr)/exprDriver/exprDriverFields.C
|
||||
|
@ -24,7 +24,7 @@ License
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Namespace
|
||||
Class
|
||||
Foam::expressions::exprString
|
||||
|
||||
Description
|
||||
|
@ -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.
|
||||
@ -32,7 +32,7 @@ License
|
||||
Foam::expressions::scanToken Foam::expressions::scanToken::null()
|
||||
{
|
||||
scanToken tok;
|
||||
tok.type_ = LABEL;
|
||||
tok.type_ = tokenType::LABEL;
|
||||
tok.labelValue = 0;
|
||||
|
||||
return tok;
|
||||
@ -41,12 +41,12 @@ Foam::expressions::scanToken Foam::expressions::scanToken::null()
|
||||
|
||||
void Foam::expressions::scanToken::destroy()
|
||||
{
|
||||
if (type_ == VECTOR)
|
||||
if (type_ == tokenType::VECTOR)
|
||||
{
|
||||
delete vectorPtr;
|
||||
vectorPtr = nullptr;
|
||||
}
|
||||
else if (type_ == WORD)
|
||||
else if (type_ == tokenType::WORD)
|
||||
{
|
||||
delete wordPtr;
|
||||
wordPtr = nullptr;
|
||||
@ -56,35 +56,35 @@ void Foam::expressions::scanToken::destroy()
|
||||
|
||||
void Foam::expressions::scanToken::setLabel(label val)
|
||||
{
|
||||
type_ = LABEL;
|
||||
type_ = tokenType::LABEL;
|
||||
labelValue = val;
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::scanToken::setScalar(scalar val)
|
||||
{
|
||||
type_ = SCALAR;
|
||||
type_ = tokenType::SCALAR;
|
||||
scalarValue = val;
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::scanToken::setVector(scalar x, scalar y, scalar z)
|
||||
{
|
||||
type_ = VECTOR;
|
||||
type_ = tokenType::VECTOR;
|
||||
vectorPtr = new Foam::vector(x, y, z);
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::scanToken::setVector(const vector& val)
|
||||
{
|
||||
type_ = VECTOR;
|
||||
type_ = tokenType::VECTOR;
|
||||
vectorPtr = new Foam::vector(val);
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::scanToken::setWord(const word& val)
|
||||
{
|
||||
type_ = WORD;
|
||||
type_ = tokenType::WORD;
|
||||
wordPtr = new Foam::word(val);
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2019-2021 OpenCFD Ltd.
|
||||
Copyright (C) 2019-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -33,13 +33,15 @@ Description
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef expressions_scanToken_H
|
||||
#define expressions_scanToken_H
|
||||
#ifndef Foam_expressions_scanToken_H
|
||||
#define Foam_expressions_scanToken_H
|
||||
|
||||
#include "scalar.H"
|
||||
#include "vector.H"
|
||||
#include "word.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
namespace expressions
|
||||
@ -80,7 +82,7 @@ struct scanToken
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Return a null token - in lieu of a default constructor
|
||||
//- Return a null token (label = 0) - in lieu of a default constructor
|
||||
static scanToken null();
|
||||
|
||||
//- Assign type/value to be LABEL. Does not call destroy().
|
||||
@ -98,6 +100,12 @@ struct scanToken
|
||||
//- Assign type/value to be WORD (name). Does not call destroy().
|
||||
void setWord(const word& val);
|
||||
|
||||
//- True if a pointer type
|
||||
bool is_pointer() const noexcept
|
||||
{
|
||||
return (type_ == tokenType::VECTOR || type_ == tokenType::WORD);
|
||||
}
|
||||
|
||||
//- Manual deletion of pointer types
|
||||
void destroy();
|
||||
};
|
||||
|
@ -27,45 +27,82 @@ License
|
||||
|
||||
#include "exprTraits.H"
|
||||
|
||||
//TBD: handle complex?
|
||||
|
||||
#undef FOR_ALL_EXPR_TYPE_CODES
|
||||
#define FOR_ALL_EXPR_TYPE_CODES(Macro, ...) \
|
||||
Macro(bool, __VA_ARGS__) \
|
||||
Macro(label, __VA_ARGS__) \
|
||||
Macro(scalar, __VA_ARGS__) \
|
||||
Macro(vector, __VA_ARGS__) \
|
||||
Macro(sphericalTensor, __VA_ARGS__) \
|
||||
Macro(symmTensor, __VA_ARGS__) \
|
||||
Macro(tensor, __VA_ARGS__)
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
Foam::expressions::valueTypeCode
|
||||
Foam::expressions::valueTypeCodeOf(const word& dataTypeName)
|
||||
Foam::direction
|
||||
Foam::expressions::Detail::nComponents
|
||||
(
|
||||
const expressions::valueTypeCode typeCode
|
||||
) noexcept
|
||||
{
|
||||
#undef stringToTypeCode
|
||||
#define stringToTypeCode(Type) \
|
||||
\
|
||||
if (dataTypeName == exprTypeTraits<Type>::name) \
|
||||
{ \
|
||||
return expressions::valueTypeCode::type_##Type; \
|
||||
switch (typeCode)
|
||||
{
|
||||
case expressions::valueTypeCode::NONE :
|
||||
case expressions::valueTypeCode::INVALID :
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
return pTraits<Type>::nComponents; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
Foam::expressions::valueTypeCode
|
||||
Foam::expressions::valueTypeCodeOf
|
||||
(
|
||||
const word& dataTypeName,
|
||||
const expressions::valueTypeCode deflt
|
||||
)
|
||||
{
|
||||
if (!dataTypeName.empty())
|
||||
{
|
||||
stringToTypeCode(bool);
|
||||
stringToTypeCode(label);
|
||||
stringToTypeCode(scalar);
|
||||
stringToTypeCode(vector);
|
||||
stringToTypeCode(tensor);
|
||||
stringToTypeCode(sphericalTensor);
|
||||
stringToTypeCode(symmTensor);
|
||||
}
|
||||
#undef stringToTypeCode
|
||||
// Could compare with pTraits<Type>::typeName instead of
|
||||
// exprTypeTraits<Type>::name, but then we might miss
|
||||
// possible typos.
|
||||
|
||||
return expressions::valueTypeCode::INVALID;
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
\
|
||||
if (dataTypeName == exprTypeTraits<Type>::name) \
|
||||
{ \
|
||||
return expressions::valueTypeCode::type_##Type; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
}
|
||||
|
||||
return deflt;
|
||||
}
|
||||
|
||||
|
||||
Foam::word Foam::name(const expressions::valueTypeCode typeCode)
|
||||
{
|
||||
#undef case_typeCodeToString
|
||||
#define case_typeCodeToString(Type) \
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
return exprTypeTraits<Type>::name; \
|
||||
}
|
||||
|
||||
switch (typeCode)
|
||||
{
|
||||
case expressions::valueTypeCode::NONE :
|
||||
@ -75,22 +112,27 @@ Foam::word Foam::name(const expressions::valueTypeCode typeCode)
|
||||
|
||||
case expressions::valueTypeCode::INVALID :
|
||||
{
|
||||
// ie, ""
|
||||
// returns ""
|
||||
break;
|
||||
}
|
||||
|
||||
case_typeCodeToString(bool);
|
||||
case_typeCodeToString(label);
|
||||
case_typeCodeToString(scalar);
|
||||
case_typeCodeToString(vector);
|
||||
case_typeCodeToString(tensor);
|
||||
case_typeCodeToString(sphericalTensor);
|
||||
case_typeCodeToString(symmTensor);
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
return exprTypeTraits<Type>::name; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_TYPE_CODES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
}
|
||||
#undef case_typeCodeToString
|
||||
|
||||
return word();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#undef FOR_ALL_EXPR_TYPE_CODES
|
||||
|
||||
// ************************************************************************* //
|
||||
|
@ -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.
|
||||
@ -28,18 +28,33 @@ Class
|
||||
|
||||
Description
|
||||
Simple type identifiers for polymorphic expression values.
|
||||
|
||||
The definitions are similar to std::integral_constant in that they
|
||||
provide value, value_type (and name).
|
||||
|
||||
SourceFiles
|
||||
exprTraits.C
|
||||
|
||||
Namespace
|
||||
Foam::expressions
|
||||
|
||||
Description
|
||||
A namespace for expression-related classes/traits etc.
|
||||
|
||||
Namespace
|
||||
Foam::expressions::Detail
|
||||
|
||||
Description
|
||||
A namespace for implementation details related to expressions.
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef expressions_exprTraits_H
|
||||
#define expressions_exprTraits_H
|
||||
#ifndef Foam_expressions_exprTraits_H
|
||||
#define Foam_expressions_exprTraits_H
|
||||
|
||||
// Regular field types
|
||||
#include "label.H"
|
||||
#include "scalar.H"
|
||||
//TBD: #include "complex.H"
|
||||
#include "vector.H"
|
||||
#include "sphericalTensor.H"
|
||||
#include "symmTensor.H"
|
||||
@ -56,7 +71,7 @@ namespace expressions
|
||||
//- An enumeration of known and expected expression value types.
|
||||
// Do not rely on the enumeration values for any direct coding.
|
||||
//
|
||||
// \note NONE use used when initializing types, whereas INVALID is used
|
||||
// \note NONE used when initializing types, whereas INVALID is used
|
||||
// for unsupported types (never as a stored type).
|
||||
// This avoids false positives when testing.
|
||||
//
|
||||
@ -72,6 +87,7 @@ enum class valueTypeCode : unsigned char
|
||||
type_bool, //!< Type is 'bool'
|
||||
type_label, //!< Type is 'label'
|
||||
type_scalar, //!< Type is 'scalar'
|
||||
//TBD: type_complex, //!< Type is 'complex'
|
||||
|
||||
// Rank 1 types
|
||||
type_vector, //!< Type is 'vector'
|
||||
@ -86,7 +102,23 @@ enum class valueTypeCode : unsigned char
|
||||
// Global Functions
|
||||
|
||||
//- From string to valueTypeCode (if any)
|
||||
valueTypeCode valueTypeCodeOf(const word& dataTypeName);
|
||||
valueTypeCode valueTypeCodeOf
|
||||
(
|
||||
const word& dataTypeName,
|
||||
// Fallback for unknown
|
||||
const expressions::valueTypeCode deflt = expressions::valueTypeCode::INVALID
|
||||
);
|
||||
|
||||
|
||||
// Some implementation detail
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
//- The number of components associated with given valueTypeCode
|
||||
::Foam::direction nComponents(const expressions::valueTypeCode) noexcept;
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
@ -101,45 +133,58 @@ valueTypeCode valueTypeCodeOf(const word& dataTypeName);
|
||||
template<class Type>
|
||||
struct exprTypeTraits
|
||||
{
|
||||
// The value type
|
||||
typedef Type value_type;
|
||||
// The type name (similar to pTraits typeName)
|
||||
static constexpr const char* const name = "";
|
||||
// The enumeration number associated with the type
|
||||
static constexpr
|
||||
::Foam::expressions::valueTypeCode value =
|
||||
::Foam::expressions::valueTypeCode::INVALID;
|
||||
// The rank of the type
|
||||
static constexpr ::Foam::direction rank = 0;
|
||||
// The number of components
|
||||
static constexpr ::Foam::direction nComponents = 0;
|
||||
};
|
||||
|
||||
|
||||
#undef defineExprTypeTraits
|
||||
#define defineExprTypeTraits(Type, Name) \
|
||||
#define defineExprTypeTraits(Type, Name, Rank, NumCmpts) \
|
||||
/*! \brief \c Name expression traits */ \
|
||||
template<> \
|
||||
struct exprTypeTraits<Type> \
|
||||
{ \
|
||||
typedef Type value_type; \
|
||||
static constexpr const char* const name = #Name; \
|
||||
static constexpr const char* const name = #Name ; \
|
||||
static constexpr \
|
||||
::Foam::expressions::valueTypeCode value = \
|
||||
::Foam::expressions::valueTypeCode::type_##Name; \
|
||||
::Foam::expressions::valueTypeCode::type_##Name ; \
|
||||
static constexpr ::Foam::direction rank = Rank ; \
|
||||
static constexpr ::Foam::direction nComponents = NumCmpts ; \
|
||||
};
|
||||
|
||||
|
||||
// Define with "name" to match regular pTraits typeName
|
||||
defineExprTypeTraits(bool, bool);
|
||||
defineExprTypeTraits(::Foam::label, label);
|
||||
defineExprTypeTraits(::Foam::scalar, scalar);
|
||||
defineExprTypeTraits(::Foam::vector, vector);
|
||||
defineExprTypeTraits(::Foam::tensor, tensor);
|
||||
defineExprTypeTraits(::Foam::sphericalTensor, sphericalTensor);
|
||||
defineExprTypeTraits(::Foam::symmTensor, symmTensor);
|
||||
// Define with name to match pTraits::typeName, with rank/nComponents
|
||||
defineExprTypeTraits(bool, bool, 0, 1);
|
||||
defineExprTypeTraits(::Foam::label, label, 0, 1);
|
||||
defineExprTypeTraits(::Foam::scalar, scalar, 0, 1);
|
||||
//TBD: defineExprTypeTraits(::Foam::complex, complex, 0, 2);
|
||||
defineExprTypeTraits(::Foam::vector, vector, 1, 3);
|
||||
defineExprTypeTraits(::Foam::tensor, tensor, 2, 9);
|
||||
defineExprTypeTraits(::Foam::sphericalTensor, sphericalTensor, 2, 1);
|
||||
defineExprTypeTraits(::Foam::symmTensor, symmTensor, 2, 6);
|
||||
|
||||
#undef defineExprTypeTraits
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
//- A word representation of a valueTypeCode. Empty for INVALID
|
||||
//- A word representation of a valueTypeCode.
|
||||
//- Empty for expressions::valueTypeCode::INVALID
|
||||
word name(const expressions::valueTypeCode typeCode);
|
||||
|
||||
|
||||
//- A word representation of a valueTypeCode. Empty for INVALID
|
||||
//- A word representation of a valueTypeCode.
|
||||
//- Empty for expressions::valueTypeCode::INVALID
|
||||
template<>
|
||||
struct nameOp<expressions::valueTypeCode>
|
||||
{
|
||||
|
341
src/OpenFOAM/expressions/value/exprValue.C
Normal file
341
src/OpenFOAM/expressions/value/exprValue.C
Normal file
@ -0,0 +1,341 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-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 "exprValue.H"
|
||||
#include "ITstream.H"
|
||||
#include "Switch.H"
|
||||
#include <cstring> // For memcpy, memset
|
||||
|
||||
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
template<class Type>
|
||||
static void fillTokens(const Type& val, tokenList& toks)
|
||||
{
|
||||
const direction nCmpt = pTraits<Type>::nComponents;
|
||||
const direction nParen = 2*(pTraits<Type>::rank || (nCmpt > 1) ? 1 : 0);
|
||||
|
||||
toks.resize_nocopy(nCmpt + nParen);
|
||||
|
||||
auto iter = toks.begin();
|
||||
|
||||
if (nParen)
|
||||
{
|
||||
*iter = token::BEGIN_LIST;
|
||||
++iter;
|
||||
}
|
||||
|
||||
for (direction cmpt = 0; cmpt < nCmpt; ++cmpt)
|
||||
{
|
||||
*iter = component(val, cmpt);
|
||||
++iter;
|
||||
}
|
||||
|
||||
if (nParen)
|
||||
{
|
||||
*iter = token::END_LIST;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//- Specialized for bool
|
||||
template<>
|
||||
void fillTokens<bool>(const bool& val, tokenList& toks)
|
||||
{
|
||||
toks.resize_nocopy(1);
|
||||
toks.front() = token::boolean(val);
|
||||
}
|
||||
|
||||
|
||||
//- Specialized for label
|
||||
template<>
|
||||
void fillTokens<label>(const label& val, tokenList& toks)
|
||||
{
|
||||
toks.resize_nocopy(1);
|
||||
toks.front() = val;
|
||||
}
|
||||
|
||||
|
||||
//- Specialized for scalar
|
||||
template<>
|
||||
void fillTokens<scalar>(const scalar& val, tokenList& toks)
|
||||
{
|
||||
toks.resize_nocopy(1);
|
||||
toks.front() = val;
|
||||
}
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
Foam::expressions::valueTypeCode
|
||||
Foam::expressions::exprValue::peekType(const ITstream& is)
|
||||
{
|
||||
expressions::valueTypeCode whichCode(expressions::valueTypeCode::INVALID);
|
||||
|
||||
const token& tok0 = is.peek();
|
||||
|
||||
if (tok0.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
// Expecting "( content )" - eg, (x y z), (xx xy ...)
|
||||
|
||||
// First component starts after the opening '('.
|
||||
// Can use the current index if the '(' actually came from
|
||||
// the putBack.
|
||||
|
||||
const label firstCmpti = (is.tokenIndex() + (is.hasPutback() ? 0 : 1));
|
||||
|
||||
// Search for closing ')', require all components to be numbers
|
||||
for (label endCmpti = firstCmpti; endCmpti < is.size(); ++endCmpti)
|
||||
{
|
||||
const token& tok = is[endCmpti];
|
||||
|
||||
///InfoErr
|
||||
/// << "check token: " << (endCmpti-firstCmpti) << " : "
|
||||
/// << is[endCmpti].name() << nl;
|
||||
|
||||
if (tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
// Select based on the number of components
|
||||
// cf. pTraits<Type>::nComponents
|
||||
|
||||
switch (endCmpti - firstCmpti)
|
||||
{
|
||||
case 1: // pTraits<sphericalTensor>::nComponents
|
||||
whichCode = exprTypeTraits<sphericalTensor>::value;
|
||||
break;
|
||||
|
||||
// FUTURE?
|
||||
// case 2: // pTraits<complex>::nComponents
|
||||
// whichCode = exprTypeTraits<complex>::value;
|
||||
// break;
|
||||
|
||||
case 3: // pTraits<vector>::nComponents
|
||||
whichCode = exprTypeTraits<vector>::value;
|
||||
break;
|
||||
|
||||
case 6: // pTraits<symmTensor>::nComponents
|
||||
whichCode = exprTypeTraits<symmTensor>::value;
|
||||
break;
|
||||
|
||||
case 9: // pTraits<tensor>::nComponents
|
||||
whichCode = exprTypeTraits<tensor>::value;
|
||||
break;
|
||||
}
|
||||
|
||||
// Closing ')' terminates peeking
|
||||
break;
|
||||
}
|
||||
else if (!tok.isNumber())
|
||||
{
|
||||
// All components should be numeric
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (tok0.good())
|
||||
{
|
||||
/// InfoErr<< "check token: " << tok0.info() << nl;
|
||||
|
||||
if (tok0.isScalar())
|
||||
{
|
||||
whichCode = exprTypeTraits<scalar>::value;
|
||||
}
|
||||
else if (tok0.isLabel())
|
||||
{
|
||||
whichCode = exprTypeTraits<label>::value;
|
||||
}
|
||||
else if (Switch(tok0).good())
|
||||
{
|
||||
whichCode = exprTypeTraits<bool>::value;
|
||||
}
|
||||
}
|
||||
|
||||
return whichCode;
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValue::read
|
||||
(
|
||||
const std::string& str,
|
||||
exprValue& val
|
||||
)
|
||||
{
|
||||
ITstream is(str);
|
||||
|
||||
// No trailing non-whitespace!
|
||||
return (val.read(is) && !is.nRemainingTokens());
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::expressions::exprValue::clear()
|
||||
{
|
||||
std::memset(static_cast<void*>(this), '\0', sizeof(*this));
|
||||
// Redundant: typeCode_ = expressions::valueTypeCode::NONE;
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValue::deepCopy(const exprValue& rhs)
|
||||
{
|
||||
if (this != &rhs)
|
||||
{
|
||||
// Self-assignment is a no-op
|
||||
std::memcpy(static_cast<void*>(this), &rhs, sizeof(*this));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Foam::tokenList Foam::expressions::exprValue::tokens() const
|
||||
{
|
||||
tokenList toks;
|
||||
|
||||
switch (typeCode_)
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
const Type* dataPtr = data_.get<Type>(); \
|
||||
if (dataPtr) \
|
||||
{ \
|
||||
fillTokens<Type>(*dataPtr, toks); \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_VALUE_TYPES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
|
||||
// exprValue may only be a subset of valueTypeCode types
|
||||
default: break;
|
||||
}
|
||||
|
||||
return toks;
|
||||
}
|
||||
|
||||
|
||||
void Foam::expressions::exprValue::print(Ostream& os) const
|
||||
{
|
||||
switch (typeCode_)
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
const Type* dataPtr = data_.get<Type>(); \
|
||||
if (dataPtr) \
|
||||
{ \
|
||||
os << *dataPtr; \
|
||||
} \
|
||||
break; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_VALUE_TYPES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
|
||||
// exprValue may only be a subset of valueTypeCode types
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool Foam::expressions::exprValue::read(ITstream& is)
|
||||
{
|
||||
clear(); // type: none, value: zero
|
||||
|
||||
const valueTypeCode whichCode(exprValue::peekType(is));
|
||||
|
||||
switch (whichCode)
|
||||
{
|
||||
#undef doLocalCode
|
||||
#define doLocalCode(Type, UnusedParam) \
|
||||
\
|
||||
case expressions::valueTypeCode::type_##Type : \
|
||||
{ \
|
||||
data_.set<Type>(pTraits<Type>(is)); \
|
||||
typeCode_ = whichCode; \
|
||||
return true; \
|
||||
}
|
||||
|
||||
FOR_ALL_EXPR_VALUE_TYPES(doLocalCode);
|
||||
#undef doLocalCode
|
||||
|
||||
// exprValue may only be a subset of valueTypeCode types
|
||||
default: break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const expressions::exprValue& val
|
||||
)
|
||||
{
|
||||
val.print(os);
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
template<>
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Ostream& os,
|
||||
const InfoProxy<expressions::exprValue>& iproxy
|
||||
)
|
||||
{
|
||||
const auto& val = *iproxy;
|
||||
|
||||
if (val.good())
|
||||
{
|
||||
os << val.valueTypeName() << ": ";
|
||||
val.print(os);
|
||||
}
|
||||
else
|
||||
{
|
||||
// typeCode_ is *never* set to INVALID,
|
||||
// so NONE is the only remaining non-good type
|
||||
os << "none";
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
348
src/OpenFOAM/expressions/value/exprValue.H
Normal file
348
src/OpenFOAM/expressions/value/exprValue.H
Normal file
@ -0,0 +1,348 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-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::exprValue
|
||||
|
||||
Description
|
||||
A polymorphic typed union of simple primitive and VectorSpace types.
|
||||
It uses a 'fatter' representation that includes standard VectorSpace
|
||||
types, which avoids heap allocations at the expense of more storage.
|
||||
This is mostly not an issue since lists and fields would box/unbox
|
||||
an entire field, not individual values.
|
||||
|
||||
SourceFiles
|
||||
exprValue.C
|
||||
exprValueI.H
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef Foam_expressions_exprValue_H
|
||||
#define Foam_expressions_exprValue_H
|
||||
|
||||
#include "exprTraits.H"
|
||||
#include "error.H"
|
||||
#include "tokenList.H"
|
||||
#include "InfoProxy.H"
|
||||
#include <typeinfo>
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Execute macro for known exprValue types, with more probably ones first
|
||||
#undef FOR_ALL_EXPR_VALUE_TYPES
|
||||
#define FOR_ALL_EXPR_VALUE_TYPES(Macro, ...) \
|
||||
Macro(scalar, __VA_ARGS__) \
|
||||
Macro(vector, __VA_ARGS__) \
|
||||
Macro(tensor, __VA_ARGS__) \
|
||||
Macro(symmTensor, __VA_ARGS__) \
|
||||
Macro(sphericalTensor, __VA_ARGS__) \
|
||||
Macro(label, __VA_ARGS__) \
|
||||
Macro(bool, __VA_ARGS__)
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
namespace Foam
|
||||
{
|
||||
|
||||
// Forward Declarations
|
||||
class ITstream;
|
||||
|
||||
namespace expressions
|
||||
{
|
||||
namespace Detail
|
||||
{
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class exprValueUnion Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
//- The data content (as a union).
|
||||
// The stem of the member names correspond identically to the data types
|
||||
// to enable macro definitions (naming similar to Foam::token)
|
||||
union exprValueUnion
|
||||
{
|
||||
// Member Data
|
||||
|
||||
#undef declareUnionMember
|
||||
#define declareUnionMember(Type, UnusedParam) \
|
||||
\
|
||||
/*! Define Type data member */ \
|
||||
Type Type##Value;
|
||||
|
||||
FOR_ALL_EXPR_VALUE_TYPES(declareUnionMember);
|
||||
#undef declareUnionMember
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Runtime 'assert' for unimplemented generic methods
|
||||
// This seems to be the best way to catch programming errors
|
||||
// since static_assert does not help here.
|
||||
// The 'noexcept' is slightly misleading (needed for the caller)
|
||||
static void notSpecialized(const std::string& msg) noexcept
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "non-specialized: " << msg.c_str() << endl
|
||||
<< abort(FatalError);
|
||||
}
|
||||
|
||||
//- Return read pointer to typed union member,
|
||||
//- which is nullptr for unspecialized versions
|
||||
template<class Type>
|
||||
inline const Type* get() const noexcept { return nullptr; }
|
||||
|
||||
//- No generic set(), only specialized methods
|
||||
template<class Type>
|
||||
inline void set(const Type& val) noexcept
|
||||
{
|
||||
notSpecialized("set<" + std::string(typeid(Type).name()) + '>');
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
// Type-specific get/set (definitions)
|
||||
#undef defineMultiTypeValueUnionMethods
|
||||
#define defineMultiTypeValueUnionMethods(Type, UnusedParam) \
|
||||
\
|
||||
/*! Return read pointer to Type union member */ \
|
||||
template<> \
|
||||
inline const Type* exprValueUnion::get<Type>() const noexcept \
|
||||
{ \
|
||||
return &(Type##Value); \
|
||||
} \
|
||||
\
|
||||
/*! Set Type value */ \
|
||||
template<> \
|
||||
inline void exprValueUnion::set<Type>(const Type& val) noexcept \
|
||||
{ \
|
||||
Type##Value = val; \
|
||||
}
|
||||
|
||||
// Type-specific methods
|
||||
FOR_ALL_EXPR_VALUE_TYPES(defineMultiTypeValueUnionMethods);
|
||||
#undef defineMultiTypeValueUnionMethods
|
||||
|
||||
} // End namespace Detail
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class exprValue Declaration
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
class exprValue
|
||||
{
|
||||
// Private Data
|
||||
|
||||
//- The data content (as a union)
|
||||
Detail::exprValueUnion data_;
|
||||
|
||||
//- The data type (as a type-code)
|
||||
expressions::valueTypeCode typeCode_ = valueTypeCode::NONE;
|
||||
|
||||
|
||||
// Private Member Functions
|
||||
|
||||
//- Assign zero, preserving the data type
|
||||
inline void fill_zero();
|
||||
|
||||
//- Copy assignment
|
||||
void deepCopy(const exprValue& rhs);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
//- Runtime type information
|
||||
ClassName("exprValue");
|
||||
|
||||
|
||||
// Constructors
|
||||
|
||||
//- Default construct (zero-initialized) as 'none'
|
||||
inline exprValue();
|
||||
|
||||
//- Copy construct (deep copy)
|
||||
inline exprValue(const exprValue& rhs);
|
||||
|
||||
//- Construct from Type. Fatal for unsupported types
|
||||
template<class Type>
|
||||
inline explicit exprValue(const Type& val);
|
||||
|
||||
|
||||
// Static Methods (valueTypeCode)
|
||||
|
||||
//- True if valueTypeCode is not none/invalid
|
||||
inline static bool good
|
||||
(
|
||||
const expressions::valueTypeCode
|
||||
) noexcept;
|
||||
|
||||
//- True if valueTypeCode is bool/label
|
||||
inline static bool is_integral
|
||||
(
|
||||
const expressions::valueTypeCode
|
||||
) noexcept;
|
||||
|
||||
//- The number of components associated with the valueTypeCode
|
||||
inline static direction nComponents
|
||||
(
|
||||
const expressions::valueTypeCode
|
||||
) noexcept;
|
||||
|
||||
//- True if the specified type is supported
|
||||
template<class Type>
|
||||
inline static bool supportedType();
|
||||
|
||||
|
||||
// Static Methods
|
||||
|
||||
//- Detect the type from the available tokens.
|
||||
// Possible ambiguity between label and scalar.
|
||||
// \return INVALID for unsupported type
|
||||
static expressions::valueTypeCode peekType(const ITstream& is);
|
||||
|
||||
//- Read entire string as a exprValue,
|
||||
//- skipping leading/trailing whitespace.
|
||||
// \return True if successful.
|
||||
static bool read(const std::string& str, exprValue& val);
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- The value type code
|
||||
expressions::valueTypeCode typeCode() const noexcept
|
||||
{
|
||||
return typeCode_;
|
||||
}
|
||||
|
||||
//- True if the value type is not none/invalid
|
||||
inline bool good() const noexcept;
|
||||
|
||||
//- True if the value type is an integral (bool or label)
|
||||
inline bool is_integral() const noexcept;
|
||||
|
||||
//- The number of components associated with the value type
|
||||
inline direction nComponents() const noexcept;
|
||||
|
||||
//- The name for the value type. Similar to pTraits typeName
|
||||
inline word valueTypeName() const;
|
||||
|
||||
//- The name for the compound token (for a List of values).
|
||||
//- Eg, \c List\<scalar\>, \c List\<vector\> ...
|
||||
inline word listCompoundName() const;
|
||||
|
||||
//- Reset to 'none'
|
||||
void clear();
|
||||
|
||||
//- Guess type and read tokens (if possible)
|
||||
// \return True on success
|
||||
bool read(ITstream& is);
|
||||
|
||||
|
||||
// Typed Access
|
||||
|
||||
//- Return non-null pointer to the data element (if types match).
|
||||
//- Can also be tested as a bool.
|
||||
template<class Type>
|
||||
inline const Type* isA() const noexcept;
|
||||
|
||||
//- Assign from type.
|
||||
//- Returns false and sets to 'none' for unsupported types
|
||||
template<class Type>
|
||||
inline bool set(const Type& val);
|
||||
|
||||
//- Return the value. Return pTraits zero if the types mismatch
|
||||
template<class Type>
|
||||
inline const Type& get() const;
|
||||
|
||||
|
||||
// Type-specific methods, operators
|
||||
|
||||
#undef defineUnionMethods
|
||||
#define defineUnionMethods(Type, UnusedParam) \
|
||||
\
|
||||
/*! True if value is a Type */ \
|
||||
bool is_##Type() const noexcept \
|
||||
{ \
|
||||
return (typeCode_ == exprTypeTraits<Type>::value); \
|
||||
} \
|
||||
\
|
||||
/*! Assign from Type */ \
|
||||
void operator=(const Type& val) { this->set<Type>(val); }
|
||||
|
||||
FOR_ALL_EXPR_VALUE_TYPES(defineUnionMethods)
|
||||
#undef defineUnionMethods
|
||||
|
||||
|
||||
//- Copy assignment
|
||||
void operator=(const exprValue& rhs) { deepCopy(rhs); }
|
||||
|
||||
//- Assign from zero. Changes value but not type
|
||||
void operator=(const Foam::zero) { fill_zero(); }
|
||||
|
||||
|
||||
// Output
|
||||
|
||||
//- 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;
|
||||
|
||||
//- Print the (type-specific) content
|
||||
void print(Ostream& os) const;
|
||||
};
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace expressions
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
|
||||
//- Write value to output stream in ASCII format
|
||||
Ostream& operator<<(Ostream& os, const expressions::exprValue& val);
|
||||
|
||||
template<>
|
||||
Ostream& operator<<(Ostream& os, const InfoProxy<expressions::exprValue>&);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
} // End namespace Foam
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "exprValueI.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
#endif
|
||||
|
||||
// ************************************************************************* //
|
213
src/OpenFOAM/expressions/value/exprValueI.H
Normal file
213
src/OpenFOAM/expressions/value/exprValueI.H
Normal file
@ -0,0 +1,213 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021-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 "exprValue.H"
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::expressions::exprValue::good
|
||||
(
|
||||
const expressions::valueTypeCode valTypeCode
|
||||
) noexcept
|
||||
{
|
||||
return
|
||||
(
|
||||
valTypeCode != expressions::valueTypeCode::NONE
|
||||
&& valTypeCode != expressions::valueTypeCode::INVALID
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::expressions::exprValue::is_integral
|
||||
(
|
||||
const expressions::valueTypeCode valTypeCode
|
||||
) noexcept
|
||||
{
|
||||
return
|
||||
(
|
||||
valTypeCode == expressions::valueTypeCode::type_bool
|
||||
|| valTypeCode == expressions::valueTypeCode::type_label
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::direction Foam::expressions::exprValue::nComponents
|
||||
(
|
||||
const expressions::valueTypeCode valTypeCode
|
||||
) noexcept
|
||||
{
|
||||
return expressions::Detail::nComponents(valTypeCode);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline bool Foam::expressions::exprValue::supportedType()
|
||||
{
|
||||
return
|
||||
(
|
||||
expressions::valueTypeCode::INVALID != exprTypeTraits<Type>::value
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
inline void Foam::expressions::exprValue::fill_zero()
|
||||
{
|
||||
// Preserve the type
|
||||
const auto oldType(typeCode_);
|
||||
clear();
|
||||
typeCode_ = oldType;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
inline Foam::expressions::exprValue::exprValue()
|
||||
{
|
||||
clear(); // zero-initialized (type is NONE)
|
||||
}
|
||||
|
||||
|
||||
inline Foam::expressions::exprValue::exprValue(const exprValue& rhs)
|
||||
{
|
||||
deepCopy(rhs);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline Foam::expressions::exprValue::exprValue(const Type& val)
|
||||
{
|
||||
clear(); // type: none, value: zero
|
||||
|
||||
set<Type>(val);
|
||||
|
||||
if (!good())
|
||||
{
|
||||
FatalErrorInFunction
|
||||
<< "Cannot construct for unsupported type: "
|
||||
<< typeid(Type).name() << endl
|
||||
<< abort(FatalError);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
inline bool Foam::expressions::exprValue::good() const noexcept
|
||||
{
|
||||
return exprValue::good(typeCode_);
|
||||
}
|
||||
|
||||
|
||||
inline bool Foam::expressions::exprValue::is_integral() const noexcept
|
||||
{
|
||||
return exprValue::is_integral(typeCode_);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::direction
|
||||
Foam::expressions::exprValue::nComponents() const noexcept
|
||||
{
|
||||
return expressions::Detail::nComponents(typeCode_);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::word
|
||||
Foam::expressions::exprValue::valueTypeName() const
|
||||
{
|
||||
return Foam::name(typeCode_);
|
||||
}
|
||||
|
||||
|
||||
inline Foam::word Foam::expressions::exprValue::listCompoundName() const
|
||||
{
|
||||
return
|
||||
(
|
||||
good()
|
||||
// List<scalar>, List<vector> ...
|
||||
? word("List<" + Foam::name(typeCode_) + '>')
|
||||
: word()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline bool Foam::expressions::exprValue::set(const Type& val)
|
||||
{
|
||||
const auto whichCode(exprTypeTraits<Type>::value);
|
||||
|
||||
if
|
||||
(
|
||||
whichCode == expressions::valueTypeCode::NONE
|
||||
|| whichCode == expressions::valueTypeCode::INVALID
|
||||
)
|
||||
{
|
||||
clear();
|
||||
typeCode_ = expressions::valueTypeCode::NONE;
|
||||
return false;
|
||||
}
|
||||
|
||||
data_.set<Type>(val);
|
||||
typeCode_ = whichCode;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
inline const Type& Foam::expressions::exprValue::get() const
|
||||
{
|
||||
const Type* dataPtr = this->isA<Type>();
|
||||
|
||||
if (dataPtr)
|
||||
{
|
||||
return *dataPtr;
|
||||
}
|
||||
else
|
||||
{
|
||||
return pTraits<Type>::zero;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
inline const Type* Foam::expressions::exprValue::isA() const noexcept
|
||||
{
|
||||
// NOTE: typeCode_ is *never* set to INVALID,
|
||||
// so no false positives for unsupported types
|
||||
return
|
||||
(
|
||||
(typeCode_ == exprTypeTraits<Type>::value)
|
||||
? data_.get<Type>()
|
||||
: nullptr
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
Loading…
Reference in New Issue
Block a user