diff --git a/applications/test/exprValue/Make/files b/applications/test/exprValue/Make/files deleted file mode 100644 index e205df0b3c..0000000000 --- a/applications/test/exprValue/Make/files +++ /dev/null @@ -1,3 +0,0 @@ -Test-exprValue.cxx - -EXE = $(FOAM_USER_APPBIN)/Test-exprValue diff --git a/applications/test/exprValue1/Make/files b/applications/test/exprValue1/Make/files new file mode 100644 index 0000000000..70f3fad0c7 --- /dev/null +++ b/applications/test/exprValue1/Make/files @@ -0,0 +1,3 @@ +Test-exprValue1.cxx + +EXE = $(FOAM_USER_APPBIN)/Test-exprValue1 diff --git a/applications/test/exprValue/Make/options b/applications/test/exprValue1/Make/options similarity index 100% rename from applications/test/exprValue/Make/options rename to applications/test/exprValue1/Make/options diff --git a/applications/test/exprValue/Test-exprValue.cxx b/applications/test/exprValue1/Test-exprValue1.cxx similarity index 87% rename from applications/test/exprValue/Test-exprValue.cxx rename to applications/test/exprValue1/Test-exprValue1.cxx index a4753b365f..df77fd9956 100644 --- a/applications/test/exprValue/Test-exprValue.cxx +++ b/applications/test/exprValue1/Test-exprValue1.cxx @@ -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; diff --git a/applications/test/exprValue2/Make/files b/applications/test/exprValue2/Make/files new file mode 100644 index 0000000000..c49a9ce705 --- /dev/null +++ b/applications/test/exprValue2/Make/files @@ -0,0 +1,5 @@ +exprValueFieldTag.cxx + +Test-exprValue2.cxx + +EXE = $(FOAM_USER_APPBIN)/Test-exprValue2 diff --git a/applications/test/exprValue2/Make/options b/applications/test/exprValue2/Make/options new file mode 100644 index 0000000000..1f502ad153 --- /dev/null +++ b/applications/test/exprValue2/Make/options @@ -0,0 +1 @@ +/* EXE_INC = */ diff --git a/applications/test/exprValue2/Test-exprValue2.cxx b/applications/test/exprValue2/Test-exprValue2.cxx new file mode 100644 index 0000000000..93897ae321 --- /dev/null +++ b/applications/test/exprValue2/Test-exprValue2.cxx @@ -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 . + +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(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; +} + + +// ************************************************************************* // diff --git a/applications/test/exprValue2/exprValueFieldTag.H b/applications/test/exprValue2/exprValueFieldTag.H new file mode 100644 index 0000000000..cd92e3597c --- /dev/null +++ b/applications/test/exprValue2/exprValueFieldTag.H @@ -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 . + +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 + 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 + void set(const Type* first, const Type* last) + { + uniformity_ = + Foam::Detail::ListPolicy::check_uniformity(first, last); + + if (first != last) // or uniformity_ != EMPTY + { + value_.set(*first); + } + else + { + value_.set(Foam::zero{}); + } + } + + //- Set uniform type and value + template + void set_uniform(const Type& val) + { + uniformity_ = Foam::Detail::ListPolicy::uniformity::UNIFORM; + value_.set(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 + +// ************************************************************************* // diff --git a/applications/test/exprValue2/exprValueFieldTag.cxx b/applications/test/exprValue2/exprValueFieldTag.cxx new file mode 100644 index 0000000000..e30226107b --- /dev/null +++ b/applications/test/exprValue2/exprValueFieldTag.cxx @@ -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 . + +\*---------------------------------------------------------------------------*/ + +#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; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/expressions/traits/exprTraits.C b/src/OpenFOAM/expressions/traits/exprTraits.C index 3e6a389536..55a8c68705 100644 --- a/src/OpenFOAM/expressions/traits/exprTraits.C +++ b/src/OpenFOAM/expressions/traits/exprTraits.C @@ -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::nComponents; \ + return exprTypeTraits::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::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; } diff --git a/src/OpenFOAM/expressions/traits/exprTraits.H b/src/OpenFOAM/expressions/traits/exprTraits.H index c3452da052..a74f0844ce 100644 --- a/src/OpenFOAM/expressions/traits/exprTraits.H +++ b/src/OpenFOAM/expressions/traits/exprTraits.H @@ -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 diff --git a/src/OpenFOAM/expressions/value/exprValue.C b/src/OpenFOAM/expressions/value/exprValue.C index 3e7a44b6d3..bfddba1137 100644 --- a/src/OpenFOAM/expressions/value/exprValue.C +++ b/src/OpenFOAM/expressions/value/exprValue.C @@ -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::nComponents whichCode = exprTypeTraits::value; break; @@ -177,6 +181,13 @@ Foam::expressions::exprValue::peekType(const ITstream& is) { whichCode = exprTypeTraits::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(&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; diff --git a/src/OpenFOAM/expressions/value/exprValue.H b/src/OpenFOAM/expressions/value/exprValue.H index 014e36f205..16cf5753c2 100644 --- a/src/OpenFOAM/expressions/value/exprValue.H +++ b/src/OpenFOAM/expressions/value/exprValue.H @@ -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 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 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 : 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<> diff --git a/src/OpenFOAM/expressions/value/exprValueI.H b/src/OpenFOAM/expressions/value/exprValueI.H index 9072c9225f..87a65b1584 100644 --- a/src/OpenFOAM/expressions/value/exprValueI.H +++ b/src/OpenFOAM/expressions/value/exprValueI.H @@ -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 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 {