ENH: adjust return type for token compound factory method

- return autoPtr<token::compound> instead of the derived type,
  otherwise cannot easily construct a token from it

ENH: additional typed version of refCompoundToken()

- symmetric with typed version of transferCompoundToken()
  and isCompound()

- add ITstream::findCompound<Type>() method.
  Useful for searching within token streams
This commit is contained in:
Mark Olesen 2024-04-23 12:11:24 +02:00
parent 880215e8e6
commit 411ac5fcfa
6 changed files with 222 additions and 86 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -35,6 +35,9 @@ Description
#include "labelList.H"
#include "scalarList.H"
#include "DynamicList.H"
#include "labelField.H"
#include "scalarField.H"
#include "SubField.H"
#include "SpanStream.H"
#include "formattingEntry.H"
@ -90,7 +93,7 @@ int main(int argc, char *argv[])
{
// This also works, but not actually using the autoPtr directly
autoPtr<token::Compound<labelList>> ptr
autoPtr<token::compound> ptr
(
new token::Compound<labelList>(identity(10, -9))
);
@ -131,44 +134,50 @@ int main(int argc, char *argv[])
Info<< "resized: "
<< ctok1.info() << nl << ctok1 << endl;
const scalarList* listptr = ctok1.compoundToken().isA<scalarList>();
if (listptr)
{
for (scalar& val : const_cast<scalarList&>(*listptr))
// Using isA<> on compoundToken()
const auto* listptr = ctok1.compoundToken().isA<scalarList>();
if (listptr)
{
val *= 5;
}
// sneaky, SubField bypasses const!
scalarField::subField fld(*listptr);
fld *= 5;
Info<< "multiplied List<scalar>: "
<< ctok1.info() << nl << ctok1 << endl;
Info<< "multiplied List<scalar>: "
<< ctok1.info() << nl << ctok1 << endl;
}
}
listptr = ctok1.isCompound<scalarList>();
if (listptr)
{
for (scalar& val : const_cast<scalarList&>(*listptr))
{
val /= 2;
}
// Using isCompound<...> - combined check
Info<< "divided List<scalar>: "
<< ctok1.info() << nl << ctok1 << endl;
const auto* listptr = ctok1.isCompound<scalarList>();
if (listptr)
{
scalarField::subField fld(*listptr);
fld /= 2;
Info<< "divided List<scalar>: "
<< ctok1.info() << nl << ctok1 << endl;
}
}
const labelList* listptr2 = ctok1.isCompound<labelList>();
if (listptr2)
{
for (label& val : const_cast<labelList&>(*listptr2))
{
val /= 2;
}
// Using isCompound<...> - combined check
Info<< "divided List<label>: "
<< ctok1.info() << nl << ctok1 << endl;
}
else
{
Info<< "compound is not List<label>" << nl;
const auto* listptr = ctok1.isCompound<labelList>();
if (listptr)
{
labelField::subField fld(*listptr);
fld /= 2;
Info<< "divided List<label>: "
<< ctok1.info() << nl << ctok1 << endl;
}
else
{
Info<< "compound is not List<label>" << nl;
}
}
Info<< "Before fill_zero: " << ctok1 << endl;
@ -183,57 +192,33 @@ int main(int argc, char *argv[])
auto& ct = ctok1.refCompoundToken();
ct.resize(20);
bool handled = true;
bool handled = false;
switch (ct.typeCode())
{
case token::tokenType::BOOL :
{
UList<bool> cmpts
(
reinterpret_cast<bool*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(bool))
);
cmpts = false;
#undef doLocalCode
#define doLocalCode(TokenType, cmptType, cmptValue) \
\
case TokenType : \
{ \
UList<cmptType> cmpts \
( \
reinterpret_cast<cmptType*>(ct.data_bytes()), \
label(ct.size_bytes() / sizeof(cmptType)) \
); \
cmpts = cmptValue; \
handled = true; \
break; \
}
break;
case token::tokenType::LABEL :
{
UList<label> cmpts
(
reinterpret_cast<label*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(label))
);
cmpts = 123;
}
break;
doLocalCode(token::tokenType::BOOL, bool, false);
doLocalCode(token::tokenType::LABEL, label, 123);
doLocalCode(token::tokenType::FLOAT, float, 2.7);
doLocalCode(token::tokenType::DOUBLE, double, 3.1415);
case token::tokenType::FLOAT :
{
UList<float> cmpts
(
reinterpret_cast<float*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(float))
);
cmpts = 2.7;
}
break;
#undef doLocalCode
case token::tokenType::DOUBLE :
{
UList<double> cmpts
(
reinterpret_cast<double*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(double))
);
cmpts = 3.1415;
}
break;
default:
handled = false;
break;
default : break;
}
@ -241,6 +226,10 @@ int main(int argc, char *argv[])
{
Info<< "assigned: " << ctok1 << nl;
}
else
{
Info<< "Warning: not handled!" << nl;
}
}
}
@ -327,6 +316,65 @@ int main(int argc, char *argv[])
Info<< "content" << nl << entry3 << nl;
}
{
primitiveEntry entry0("entry");
Info<< "empty: " << entry0 << nl;
// populate
{
tokenList& toks = entry0.stream();
toks.resize(2);
toks[0] = word("nonuniform");
toks[1] = token::Compound<scalarList>::New(10, scalar(1));
}
Info<< entry0 << nl;
// Modify contents
for (auto& tok : entry0.stream())
{
if (tok.isCompound<scalarList>())
{
tok.refCompoundToken<scalarList>() = 2;
}
}
Info<< entry0 << nl;
// Find and 'capture' contents
{
typedef List<scalar> ListType;
auto* inputDataPtr =
const_cast<ListType*>(entry0.stream().findCompound<ListType>());
if (inputDataPtr)
{
Info<< "found input data" << nl;
Info<< entry0 << nl;
ListType inputData(std::move(*inputDataPtr));
Info<< "input data, after move" << nl;
Info<< entry0 << nl;
ListType replaceData(5, scalar(3.145));
// some manipulation
replaceData.back() = scalar(1.414);
inputDataPtr->swap(replaceData);
Info<< "with replaced values" << nl;
}
}
Info<< entry0 << nl;
}
return 0;
}

View File

@ -433,7 +433,7 @@ public:
using tokenList::find;
//- Find range containing matching delimiter pair, starting at the
//- the specified position. The position -1 indicates to continue
//- specified position. The position -1 indicates to continue
//- from the present tokenIndex() position.
labelRange find
(
@ -442,6 +442,13 @@ public:
label pos = 0
) const;
//- Find compoundToken of specified Type, starting at the
//- specified position. The position -1 indicates to continue
//- from the present tokenIndex() position.
// \return nullptr if not found
template<class Type>
const Type* findCompound(label pos = 0) const;
// Token list modification
@ -636,6 +643,10 @@ public:
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#include "ITstreamI.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,52 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2024 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/>.
\*---------------------------------------------------------------------------*/
template<class Type>
const Type* Foam::ITstream::findCompound(label pos) const
{
if (pos < 0)
{
pos = tokenIndex_;
}
const Type* ptr = nullptr;
for (; pos < tokenList::size(); ++pos)
{
ptr = tokenList::operator[](pos).isCompound<Type>();
if (ptr)
{
break;
}
}
return ptr;
}
// ************************************************************************* //

View File

@ -105,9 +105,9 @@ public:
CHAR_DATA, //!< String-variant: plain character content
// Aliases
FLOAT_SCALAR = FLOAT,
DOUBLE_SCALAR = DOUBLE,
VERBATIMSTRING = VERBATIM
FLOAT_SCALAR = FLOAT, //!< compatibility name for FLOAT
DOUBLE_SCALAR = DOUBLE, //!< compatibility name for DOUBLE
VERBATIMSTRING = VERBATIM //!< compatibility name for VERBATIM
};
@ -222,7 +222,8 @@ public:
const bool readContent = true
);
//- Check if dynamic_cast to \c Type is possible.
//- Attempt dynamic_cast to \c Type
//- returns nullptr if cast is not possible
template<class Type>
const Type* isA() const
{
@ -367,11 +368,13 @@ public:
// Selectors
//- Construct autoPtr compound type with forwarding arguments
//- Construct autoPtr compound with forwarding arguments.
// The return type is compound, not Compound since that
// is what the token interface requires.
template<class... Args>
static autoPtr<Compound<T>> New(Args&&... args)
static autoPtr<compound> New(Args&&... args)
{
return autoPtr<Compound<T>>
return autoPtr<compound>
(
new Compound<T>(T(std::forward<Args>(args)...))
);
@ -386,7 +389,7 @@ public:
return T::size();
}
//- Change the size of the underlying container content
//- Change the size of the underlying content
virtual void resize(const label n)
{
T::resize(n);
@ -759,8 +762,15 @@ public:
inline const compound& compoundToken() const;
//- Return reference to compound token. Fatal if the wrong type.
//- No checks for \em released or \em pending states
inline compound& refCompoundToken();
//- Return reference to the underlying encapsulated container
//- (eg, \c List<label> etc) of a compound token.
//- No checks for \em released or \em pending states
template<class Type>
inline Type& refCompoundToken();
//- Default construct the specified compound type and read from stream.
// A no-op and returns false if compound type is unknown.
// Modify the token and return true on success.

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2024 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -873,6 +873,23 @@ inline Foam::token::compound& Foam::token::refCompoundToken()
}
template<class Type>
inline Type& Foam::token::refCompoundToken()
{
if (type_ != tokenType::COMPOUND)
{
parseError("compound");
}
return static_cast<Type&>
(
dynamicCast<token::Compound<Type>>
(
*data_.compoundPtr
)
);
}
inline Foam::token::compound&
Foam::token::transferCompoundToken(const Istream& is)
{

View File

@ -281,9 +281,7 @@ bool Foam::mappedPatchBase::constructIOField
objectRegistry& obr
)
{
const word tag("List<" + word(pTraits<Type>::typeName) + '>');
if (tok.isCompound(tag))
if (tok.isCompound<List<Type>>())
{
auto* fldPtr = obr.getObjectPtr<IOField<Type>>(name);
if (!fldPtr)