Merge branch 'feature-delayed-compound-reading' into 'develop'

Extend ITstream handling and provision for delayed reading of compound tokens

See merge request Development/openfoam!621
This commit is contained in:
Mattijs Janssens 2023-08-17 08:16:56 +00:00
commit 11a1f78338
32 changed files with 1905 additions and 465 deletions

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,6 +27,7 @@ Description
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "ListStream.H"
#include "UListStream.H"
#include "wordList.H"
@ -155,35 +156,378 @@ void doTest
}
void printToken(const label index, const token& tok)
{
Info<< " " << index << " " << tok.name();
if (tok.good())
{
Info<< " : " << tok;
}
Info<< nl;
}
template<class BUF>
void testWalk1
(
const std::string& name,
const BUF& input,
const int verbose
)
{
Info<< "tokenized " << name.c_str() << ":" << nl
<< "====" << nl;
toString(Info, input)
<< nl
<< "====" << endl;
ITstream is(input);
Info<< is.size() << " tokens" << endl;
for (is.rewind(); !is.eof(); is.skip())
{
printToken(is.tokenIndex(), is.currentToken());
}
Info<< nl;
Info<< "every other token:" << nl;
for (is.seek(1); is.nRemainingTokens(); is.skip(2))
{
printToken(is.tokenIndex(), is.currentToken());
}
for (int i : { 3, 7, 11, 20 })
{
Info<< "peekToken: ";
printToken(i, is.peekToken(i));
}
labelRange range(is.size()-2, 2);
Info<< nl
<< "remove: " << range << " of 0/" << is.size() << " tokens" << endl;
is.remove(range);
Info<< "Now " << is.size() << " tokens" << endl;
for (is.rewind(); !is.eof(); is.skip())
{
printToken(is.tokenIndex(), is.currentToken());
}
range.reset(10, 3);
Info<< nl
<< "remove: " << range << " of 0/" << is.size() << " tokens" << endl;
is.remove(range);
Info<< "Now " << is.size() << " tokens" << endl;
for (is.rewind(); !is.eof(); is.skip())
{
printToken(is.tokenIndex(), is.currentToken());
}
Info<< nl;
}
void testRewrite(const std::string& input, const int verbose)
{
Info<< "tokens" << nl
<< "====" << nl;
toString(Info, input)
<< nl
<< "====" << endl;
ITstream is(input);
Info<< is.size() << " tokens" << endl;
if (verbose)
{
for (is.rewind(); !is.eof(); is.skip())
{
printToken(is.tokenIndex(), is.currentToken());
}
Info<< nl;
}
else
{
Info<< "==>";
for (const token& tok : is)
{
Info<< ' ' << tok;
}
Info<< nl;
}
Info<< nl
<< "removing sub-dictionary tokens" << nl;
for (is.rewind(); !is.eof(); is.skip())
{
if (is.currentToken().isPunctuation(token::BEGIN_BLOCK))
{
labelRange slice(is.tokenIndex(), 0);
#if 0
// This is a bad way to remove things since we lose the parse
// point!
for (/*nil*/; !is.eof(); is.skip())
{
if (is.currentToken().isPunctuation(token::END_BLOCK))
{
slice.size() = (is.tokenIndex() - slice.start()) + 1;
break;
}
}
#else
for (label toki = is.tokenIndex()+1; toki < is.size(); ++toki)
{
if (is.peekToken(toki).isPunctuation(token::END_BLOCK))
{
slice.size() = (toki - slice.start()) + 1;
break;
}
}
#endif
Info<< "remove range: " << slice
<< " currentIndex: " << is.tokenIndex() << '/' << is.size()
// NB peekToken handles out-of-range
<< " token: " << is.peekToken(is.tokenIndex()) << nl;
const label nRemoved = is.remove(slice);
Info<< "remove " << nRemoved
<< " new current: " << is.tokenIndex() << '/' << is.size()
// NB peekToken handles out-of-range
<< " token: " << is.peekToken(is.tokenIndex()) << nl;
Info<< "==>";
for (const token& tok : is)
{
Info<< ' ' << tok;
}
Info<< nl << nl;
}
}
Info<< nl;
}
void testRemoveDict(const std::string& input, const int verbose)
{
Info<< "tokens" << nl
<< "====" << nl;
toString(Info, input)
<< nl
<< "====" << endl;
ITstream is(input);
Info<< is.size() << " tokens" << endl;
if (verbose)
{
for (is.rewind(); !is.eof(); is.skip())
{
printToken(is.tokenIndex(), is.currentToken());
}
Info<< nl;
}
else
{
Info<< "==>";
for (const token& tok : is)
{
Info<< ' ' << tok;
}
Info<< nl;
}
for (label pos = 0; pos < is.size(); /*nil*/)
{
labelRange slice
(
is.find(token::BEGIN_BLOCK, token::END_BLOCK, pos)
);
if (slice.good())
{
pos = slice.end_value();
tokenList::subList substream(is.slice(slice));
Info<< " dict " << slice << " ==>";
for (const token& tok : substream)
{
Info<< ' ' << tok;
}
Info<< nl;
}
else
{
break;
}
}
Info<< nl
<< "removing sub-dictionary tokens" << nl;
for (is.rewind(); !is.eof(); is.skip())
{
if (is.currentToken().isPunctuation(token::BEGIN_BLOCK))
{
labelRange slice
(
is.find(token::BEGIN_BLOCK, token::END_BLOCK, is.tokenIndex())
);
if (slice.good())
{
ITstream substream(is.extract(slice));
Info<< "got " << slice << " ==>";
for (const token& tok : substream)
{
Info<< ' ' << tok;
}
Info<< nl;
dictionary dict(substream);
Info<< "tokenIndex: " << is.tokenIndex() << nl;
Info<< "sub-dict " << dict << nl;
Info<< "remove range: " << slice
<< " currentIndex: " << is.tokenIndex() << '/' << is.size()
<< " token: " << is.peekToken(is.tokenIndex()) << nl;
const label nRemoved = is.remove(slice);
Info<< "remove " << nRemoved
<< " new current: " << is.tokenIndex() << '/' << is.size()
<< " token: " << is.peekToken(is.tokenIndex()) << nl;
Info<< "==>";
for (const token& tok : is)
{
Info<< ' ' << tok;
}
Info<< nl << nl;
// Reposition the parse point
is.seek(slice.start());
is.skip(-1);
Info<< "continue after " << is.tokenIndex()
<< " : " << is.peekToken(is.tokenIndex()) << nl;
}
}
}
Info<< nl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
const char* charInput =
"( const char input \"string\" to tokenize )\n"
"List<label> 5(0 1 2 3 4);";
argList::noBanner();
argList::noParallel();
argList::addVerboseOption("additional verbosity");
argList::addBoolOption("basic", "basic tests");
argList::addBoolOption("rewrite", "test rewriting only");
argList::addBoolOption("remove-dict", "test rewriting only");
string stringInput("( string ; input \"string\" to tokenize )");
argList args(argc, argv);
List<char> listInput
if
(
ListOps::create<char>
!args.found("basic")
&& !args.found("rewrite")
&& !args.found("remove-dict")
)
{
Info<< "No test options specified!" << nl << nl;
}
if (args.found("basic"))
{
const char* charInput =
"( const char input \"string\" to tokenize )\n"
"List<label> 5(0 1 2 3 4);";
string stringInput("( string ; input \"string\" to tokenize )");
List<char> listInput
(
stringInput.cbegin(),
stringInput.cend(),
Foam::identityOp{}
)
);
ListOps::create<char>
(
stringInput.cbegin(),
stringInput.cend(),
Foam::identityOp{}
)
);
doTest("empty", "", true, true);
doTest("empty", "", true, true);
doTest("char*", charInput, true, true);
doTest("string", stringInput, true);
doTest("List<char>", listInput, true);
doTest("char*", charInput, true, true);
doTest("string", stringInput, true);
doTest("List<char>", listInput, true);
reverse(listInput);
doTest("List<char>", listInput, true);
reverse(listInput);
doTest("List<char>", listInput, true);
}
if (args.found("rewrite"))
{
testWalk1
(
"std::string",
"( string ; input \"string\" to tokenize )"
"{ other entry; value 100; value2 200; }"
, args.verbose()
);
testRewrite
(
"some entry ( string1 ; )"
"{ sub dict1; value 100; value2 200; }"
"other entry ( string2 ; )"
"{ sub dict2; value 100; value2 200; }"
"{ sub dict3; value 100; value2 200; }"
"trailing entry"
, args.verbose()
);
}
if (args.found("remove-dict"))
{
testRemoveDict
(
"some entry ( string1 ; )"
"{ sub dict1; value 100; value2 200; }"
"other entry ( string2 ; )"
"{ sub dict2; value 100; value2 200; }"
"{ sub dict3; value 100; value2 200; }"
"trailing entry"
, args.verbose()
);
testRemoveDict
(
"some entry no dictionary"
, args.verbose()
);
testRemoveDict
(
"{ leading dict; } last-stuff"
, args.verbose()
);
testRemoveDict
(
"first-stuff { trailing dict; }"
, args.verbose()
);
}
Info<< "\nEnd\n" << endl;

View File

@ -58,8 +58,8 @@ int main(int argc, char *argv[])
#include "setRootCase.H"
Info<< "Known compound tokens: "
<< token::compound::IstreamConstructorTablePtr_->sortedToc() << nl;
// Info<< "Known compound tokens: "
// << token::compound::emptyConstructorTablePtr_->sortedToc() << nl;
OStringStream ostr;

View File

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

View File

@ -0,0 +1 @@
/* EXE_INC = */

View File

@ -0,0 +1,297 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 token construct assign etc.
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "IOobject.H"
#include "IOstreams.H"
#include "IFstream.H"
#include "StringStream.H"
#include "cpuTime.H"
#include "labelList.H"
#include "DynamicList.H"
namespace Foam
{
template<class OS>
OS& printTypeCode(OS& os, char typeCode)
{
os << int(static_cast<unsigned char>(typeCode));
return os;
}
/*---------------------------------------------------------------------------*\
Class IFstream Declaration
\*---------------------------------------------------------------------------*/
bool test_pending = false;
class IFstreamDelayed
:
public IFstream
{
virtual bool readCompoundToken(token& tok, const word& type)
{
auto& is = *this;
bool delay = true;
// Low-level: get next valid character (after comments)
// and branch based on it being a '{' or not
char c = 0;
if (is.read(c))
{
// Delay further reading?
delay = (c == token::BEGIN_BLOCK);
is.putback(c);
if (c)
{
cerr<< "nextChar:" << c << " : delay read: " << delay << nl;
}
}
// Caller already checked token::compound::isCompound(...)
// but use readCompoundToken anyhow for convenience
if (tok.readCompoundToken(type, is, !delay))
{
cerr<< "readCompound(" << type << ")\n";
cerr<< "typeCode: ";
printTypeCode(cerr, tok.compoundToken().typeCode()) << nl;
if (test_pending && delay)
{
InfoErr<< "pending read "
<< tok.compoundToken().type() << endl;
tok.refCompoundToken().pending(true);
}
return true;
}
return false;
}
public:
// Constructors
using IFstream::IFstream;
//- Destructor
~IFstreamDelayed() = default;
};
} // End namespace Foam
using namespace Foam;
void populateCompound(token::compound& ct, const dictionary& dict)
{
Info<< "populateCompound: " << nl;
// This is where runTime dispatch, eg based on transport type
// could be used...
switch (ct.typeCode())
{
#undef fillComponents
#define fillComponents(Type, Variable, Value) \
{ \
ct.pending(false); \
ct.resize(10); \
UList<Type> Variable \
( \
reinterpret_cast<Type*>(ct.data_bytes()), \
label(ct.size_bytes() / sizeof(Type)) \
); \
Variable = Value; \
}
case token::tokenType::PUNCTUATION :
{
fillComponents(char, cmpts, '@');
}
break;
case token::tokenType::BOOL :
{
fillComponents(bool, cmpts, false);
}
break;
case token::tokenType::LABEL :
{
fillComponents(label, cmpts, 123);
}
break;
case token::tokenType::FLOAT :
{
fillComponents(float, cmpts, 2.7);
}
break;
case token::tokenType::DOUBLE :
{
fillComponents(double, cmpts, 3.1415);
}
break;
default:
break;
#undef fillComponents
}
if (!ct.pending())
{
Info<< "assigned values:" << endl;
}
}
void rewriteCompounds(ITstream& is)
{
Info<< "rewrite: " << flatOutput(is) << endl;
for (label toki = 0; toki < is.size(); ++toki)
{
if (is[toki].isCompound() && is[toki].compoundToken().pending())
{
Info<< "replace : " << is[toki].info() << endl;
if (is.peekToken(toki+1).isPunctuation(token::BEGIN_BLOCK))
{
labelRange slice
(
is.find(token::BEGIN_BLOCK, token::END_BLOCK, toki+1)
);
if (slice.good() && (slice.start() == toki+1))
{
Info<< "Compound at:" << toki
<< " dict:" << slice << endl;
ITstream substream(is.extract(slice));
dictionary dict(substream);
populateCompound(is[toki].refCompoundToken(), dict);
}
}
}
}
}
void rewriteDict(dictionary& dict)
{
for (entry& e : dict)
{
if (e.isDict())
{
rewriteDict(e.dict());
}
else if (e.isStream())
{
rewriteCompounds(e.stream());
}
}
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noParallel();
argList::addBoolOption("std", "standard reading (no delayed compounds)");
argList::addBoolOption("pending", "read with pending");
argList args(argc, argv, false, true);
Info<< "typeCodes:" << nl;
Info<< " bool=";
printTypeCode(Info, token::tokenType::BOOL) << nl;
Info<< " label=";
printTypeCode(Info, token::tokenType::LABEL) << nl;
Info<< " float=";
printTypeCode(Info, token::tokenType::FLOAT) << nl;
Info<< " double=";
printTypeCode(Info, token::tokenType::DOUBLE) << nl;
Info<< nl;
if (args.found("pending"))
{
test_pending = true;
}
if (args.found("std"))
{
for (label argi = 1; argi < args.size(); ++argi)
{
Info<< "Read: " << args[argi] << endl;
IFstream is(args[argi]);
dictionary dict(is);
Info<< "read: " << dict << nl;
}
}
else
{
for (label argi = 1; argi < args.size(); ++argi)
{
Info<< "Read delay: " << args[argi] << endl;
IFstreamDelayed is(args[argi]);
dictionary dict(is);
Info<< "read: " << dict << nl;
rewriteDict(dict);
Info<< "modified: " << dict << nl;
}
}
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,24 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2312 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
internalField uniform 1;
temperature List<scalar> 10(270 271 272 273 274 275 276 277 278 279);
pressure 1e5;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -0,0 +1,65 @@
/*--------------------------------*- C++ -*----------------------------------*\
| ========= | |
| \\ / F ield | OpenFOAM: The Open Source CFD Toolbox |
| \\ / O peration | Version: v2312 |
| \\ / A nd | Website: www.openfoam.com |
| \\/ M anipulation | |
\*---------------------------------------------------------------------------*/
FoamFile
{
version 2.0;
format ascii;
class dictionary;
object dictionary;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
internalField uniform 1;
// Regular syntax
valuesT List<scalar> (123 456 890);
// Test some non-standard syntax
temperature List<scalar>
{
transport adios;
length 10;
values (270 271 272 273 274 275 276 277 278 279);
};
// Test some non-standard syntax
velocity List<vector>
{
transport adios;
length 10;
values (270 271 272 273 274 275 276 277 278 279);
};
// Test some non-standard syntax
isGood List<bool>
{
transport adios;
length 10;
values (true false true);
};
// Test some non-standard syntax
master List<label>
{
transport adios;
length 10;
values (0 100 35 50);
};
// Test some non-standard syntax
edges List<edge>
{
transport adios;
length 10;
values ((0 1) (2 1));
};
pressure 1e5;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -34,6 +34,7 @@ Description
#include "StringStream.H"
#include "cpuTime.H"
#include "labelList.H"
#include "scalarList.H"
#include "DynamicList.H"
using namespace Foam;
@ -49,7 +50,7 @@ int main(int argc, char *argv[])
argList args(argc, argv, false, true);
token tok1;
Info<< "construct null: " << tok1.info() << endl;
Info<< "default construct: " << tok1.info() << endl;
tok1 = double(3.14159);
Info<< "assign double: " << tok1.info() << endl;
@ -81,7 +82,8 @@ int main(int argc, char *argv[])
token ctok1(new token::Compound<labelList>(identity(10)));
Info<< "compound token: " << ctok1.info() << nl << ctok1 << endl;
Info<< "compound from pointer: "
<< ctok1.info() << nl << ctok1 << endl;
}
{
@ -94,26 +96,155 @@ int main(int argc, char *argv[])
token ctok1(ptr.release()); // release() not get()!
Info<< "compound token: " << ctok1.info() << nl << ctok1 << endl;
Info<< "compound from autoPtr: "
<< ctok1.info() << nl << ctok1 << endl;
}
#if 0
{
// This version will segfault.
// The implicit pointer cast from autoPtr to pointer wracks havoc
autoPtr<token::Compound<labelList>> ptr
// Construct from pointer
autoPtr<token::compound> ptr
(
new token::Compound<labelList>(identity(10))
token::compound::New("List<label>")
);
token ctok1(ptr);
token ctok1(ptr.release()); // release() not get()!
Info<< "compound token: " << ctok1.info() << nl << ctok1 << endl;
Info<< "compound from New (via pointer): "
<< ctok1.info() << nl << ctok1 << endl;
}
{
// Construct from autoPtr
autoPtr<token::compound> ptr
(
token::Compound<scalarList>::New(10, 1.0)
);
token ctok1(std::move(ptr));
Info<< "compound from autoPtr: "
<< ctok1.info() << nl << ctok1 << endl;
// Shrink
ctok1.refCompoundToken().resize(5);
Info<< "resized: "
<< ctok1.info() << nl << ctok1 << endl;
const scalarList* listptr = ctok1.compoundToken().isA<scalarList>();
if (listptr)
{
for (scalar& val : const_cast<scalarList&>(*listptr))
{
val *= 5;
}
Info<< "multiplied List<scalar>: "
<< ctok1.info() << nl << ctok1 << endl;
}
listptr = ctok1.isCompound<scalarList>();
if (listptr)
{
for (scalar& val : const_cast<scalarList&>(*listptr))
{
val /= 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;
}
Info<< "divided List<label>: "
<< ctok1.info() << nl << ctok1 << endl;
}
else
{
Info<< "compound is not List<label>" << nl;
}
Info<< "Before fill_zero: " << ctok1 << endl;
ctok1.refCompoundToken().fill_zero();
Info<< "After fill_zero: " << ctok1 << endl;
if (ctok1.isCompound())
{
auto& ct = ctok1.refCompoundToken();
ct.resize(20);
bool handled = true;
switch (ct.typeCode())
{
case token::tokenType::BOOL :
{
UList<bool> cmpts
(
reinterpret_cast<bool*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(bool))
);
cmpts = false;
}
break;
case token::tokenType::LABEL :
{
UList<label> cmpts
(
reinterpret_cast<label*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(label))
);
cmpts = 123;
}
break;
case token::tokenType::FLOAT :
{
UList<float> cmpts
(
reinterpret_cast<float*>(ct.data_bytes()),
label(ct.size_bytes() / sizeof(float))
);
cmpts = 2.7;
}
break;
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;
}
if (handled)
{
Info<< "assigned: " << ctok1 << nl;
}
}
}
#endif
return 0;
}
// ************************************************************************* //

View File

@ -190,10 +190,7 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
list.clearStorage(); // Remove old contents
list.transfer
(
dynamicCast<token::Compound<List<T>>>
(
tok.transferCompoundToken(is)
)
tok.transferCompoundToken<List<T>>(is)
);
}
else if (tok.isLabel())

View File

@ -190,10 +190,7 @@ Foam::Istream& Foam::FixedList<T, N>::readList
{
// Compound: transfer contents
// - in practice probably never reach this branch
list = dynamicCast<token::Compound<List<T>>>
(
tok.transferCompoundToken(is)
);
list = tok.transferCompoundToken<List<T>>(is);
return is;
}
else if (tok.isLabel())

View File

@ -190,10 +190,7 @@ Foam::Istream& Foam::List<T>::readList(Istream& is)
list.clear(); // Clear old contents
list.transfer
(
dynamicCast<token::Compound<List<T>>>
(
tok.transferCompoundToken(is)
)
tok.transferCompoundToken<List<T>>(is)
);
}
else if (tok.isLabel())

View File

@ -173,10 +173,7 @@ Foam::Istream& Foam::UList<T>::readList(Istream& is)
List<T> elems;
elems.transfer
(
dynamicCast<token::Compound<List<T>>>
(
tok.transferCompoundToken(is)
)
tok.transferCompoundToken<List<T>>(is)
);
const label inputLen = elems.size();

View File

@ -69,6 +69,19 @@ inline static label byteAlign(const label pos, const size_t align)
);
}
// Read into compound token (assumed to be a known type)
inline static bool readCompoundToken
(
token& tok,
const word& compoundType,
Istream& is
)
{
// The isCompound() check is not needed (already checked by caller)
return tok.readCompoundToken(compoundType, is);
}
} // End namespace Foam
@ -339,11 +352,11 @@ Foam::Istream& Foam::UIPstreamBase::read(token& t)
word val;
if (readString(val))
{
if (token::compound::isCompound(val))
{
t = token::compound::New(val, *this).ptr();
}
else
if
(
!token::compound::isCompound(val)
|| !readCompoundToken(t, val, *this)
)
{
t = std::move(val);
t.setType(token::tokenType(c));

View File

@ -74,6 +74,18 @@ inline void inplaceTrimRight(std::string& s)
} // End anonymous namespace
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::ISstream::readCompoundToken
(
token& tok,
const word& compoundType
)
{
return tok.readCompoundToken(compoundType, *this);
}
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
bool Foam::ISstream::seekCommentEnd_Cstyle()
@ -792,13 +804,13 @@ Foam::Istream& Foam::ISstream::read(token& t)
{
t.setBad();
}
else if (token::compound::isCompound(val))
else if
(
!token::compound::isCompound(val)
|| !readCompoundToken(t, val)
)
{
t = token::compound::New(val, *this).ptr();
}
else
{
t = std::move(val); // Move contents to token
t = std::move(val); // Move contents to token
}
return *this;

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2012 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -70,6 +70,9 @@ class ISstream
//- after skipping any C/C++ comments.
char nextValid();
//- Read into compound token (assumed to be a known type)
virtual bool readCompoundToken(token& tok, const word& compoundType);
//- No copy assignment
void operator=(const ISstream&) = delete;

View File

@ -46,20 +46,25 @@ namespace Foam
// Return the number of tokens in the resulting list.
static label parseStream(ISstream& is, tokenList& tokens)
{
label nTok = 0;
tokens.clear();
tokens.resize(64, token());
label count = 0;
token tok;
while (!is.read(tok).bad() && tok.good())
{
tokens.newElmt(nTok++) = std::move(tok);
if (count >= tokens.size())
{
// Increase capacity (doubling) with min-size [64]
tokens.resize(max(label(64), 2*tokens.size()));
}
tokens[count] = std::move(tok);
++count;
}
tokens.resize(nTok);
tokens.resize(count);
return nTok;
return count;
}
} // End namespace Foam
@ -355,7 +360,21 @@ const Foam::token& Foam::ITstream::peek() const
return Istream::peekBack();
}
return peekAt(tokenIndex_);
return peekNoFail(tokenIndex_);
}
Foam::token& Foam::ITstream::currentToken()
{
if (tokenIndex_ < 0 || tokenIndex_ >= tokenList::size())
{
FatalIOErrorInFunction(*this)
<< "Token index " << tokenIndex_ << " out of range [0,"
<< tokenList::size() << "]\n"
<< abort(FatalIOError);
}
return tokenList::operator[](tokenIndex_);
}
@ -406,45 +425,50 @@ void Foam::ITstream::seek(label pos)
}
void Foam::ITstream::skip(label n)
bool Foam::ITstream::skip(label n)
{
const tokenList& toks = *this;
const label nToks = toks.size();
if (n < 0)
if (!n)
{
// Move backwards
while (n++ && tokenIndex_)
{
--tokenIndex_;
}
// No movement - just check the current range
return (tokenIndex_ >= 0 && tokenIndex_ < tokenList::size());
}
if (tokenIndex_ < nToks)
tokenIndex_ += n; // Move forward (+ve) or backwards (-ve)
bool noError = true;
if (tokenIndex_ < 0)
{
// Underflow range
noError = false;
tokenIndex_ = 0;
}
else if (tokenIndex_ >= tokenList::size())
{
// Overflow range
noError = false;
tokenIndex_ = tokenList::size();
if (!tokenList::empty())
{
lineNumber_ = toks[tokenIndex_].lineNumber();
setOpened();
setGood();
// The closest reference lineNumber
lineNumber_ = tokenList::back().lineNumber();
}
}
else if (n > 0)
{
// Move forward
while (n-- && tokenIndex_ < nToks)
{
++tokenIndex_;
}
if (tokenIndex_ < nToks)
{
lineNumber_ = toks[tokenIndex_].lineNumber();
setOpened();
setGood();
}
else
{
setEof();
}
// Update stream information
if (tokenIndex_ < tokenList::size())
{
lineNumber_ = tokenList::operator[](tokenIndex_).lineNumber();
setOpened();
setGood();
}
else
{
setEof();
}
return noError;
}
@ -500,6 +524,153 @@ Foam::Istream& Foam::ITstream::read(token& tok)
}
Foam::labelRange Foam::ITstream::find
(
const token::punctuationToken delimOpen,
const token::punctuationToken delimClose,
label pos
) const
{
if (pos < 0)
{
pos = tokenIndex_;
}
labelRange slice;
for (label depth = 0; pos < tokenList::size(); ++pos)
{
const token& tok = tokenList::operator[](pos);
if (tok.isPunctuation())
{
if (tok.isPunctuation(delimOpen))
{
if (!depth)
{
// Initial open delimiter
slice.start() = pos;
}
++depth;
}
else if (tok.isPunctuation(delimClose))
{
--depth;
if (depth < 0)
{
// A closing delimiter without an open!
// Raise error?
break;
}
if (!depth)
{
// The end - include delimiter into the count
slice.size() = (pos - slice.start()) + 1;
break;
}
}
}
}
return slice;
}
Foam::ITstream Foam::ITstream::extract(const labelRange& range)
{
ITstream result
(
static_cast<IOstreamOption>(*this),
this->name()
);
result.setLabelByteSize(this->labelByteSize());
result.setScalarByteSize(this->scalarByteSize());
// Validate the slice range of list
const labelRange slice(range.subset0(tokenList::size()));
if (!slice.good())
{
// No-op
return result;
}
auto first = tokenList::begin(slice.begin_value());
auto last = tokenList::begin(slice.end_value());
result.resize(label(last - first));
// Move tokens into result list
std::move(first, last, result.begin());
result.seek(0); // rewind
(void) remove(slice); // Adjust the original list
return result;
}
Foam::label Foam::ITstream::remove(const labelRange& range)
{
// Validate the slice range of list
const labelRange slice(range.subset0(tokenList::size()));
if (!slice.good())
{
// No-op
return 0;
}
if (slice.end_value() >= tokenList::size())
{
// Remove entire tail
tokenList::resize(slice.begin_value());
}
else
{
// Attempt to adjust the current token index to something sensible...
if (slice.contains(tokenIndex_))
{
// Within the removed slice - reposition tokenIndex before it
seek(slice.begin_value());
skip(-1);
}
else if (tokenIndex_ >= slice.end_value())
{
// After the removed slice - reposition tokenIndex relatively
skip(-slice.size());
}
// Move tokens down in the list
std::move
(
tokenList::begin(slice.end_value()),
tokenList::end(),
tokenList::begin(slice.begin_value())
);
// Truncate
tokenList::resize(tokenList::size() - slice.size());
}
if (tokenIndex_ >= tokenList::size())
{
tokenIndex_ = tokenList::size();
setEof();
}
else if (tokenIndex_ >= 0 && tokenIndex_ < tokenList::size())
{
lineNumber_ = tokenList::operator[](tokenIndex_).lineNumber();
}
return slice.size();
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::Istream& Foam::ITstream::read(char&)
{
NotImplemented;

View File

@ -75,14 +75,13 @@ class ITstream
// In non-lazy mode, set exact capacity
void reserveCapacity(const label nElem, const bool lazy);
//- Failsafe read-access to token at specified location
//- or undefinedToken
inline const token& peekAt(const label i) const
inline const token& peekNoFail(const label i) const
{
return
(
i >= 0 && i < tokenList::size()
(i >= 0 && i < tokenList::size())
? tokenList::operator[](i)
: token::undefinedToken
);
@ -229,35 +228,56 @@ public:
//- The name of the input token stream, for modification.
virtual fileName& name() { return name_; }
//- The line number of the first token in stream
label startLineNumber() const
{
return (tokenList::empty() ? -1 : tokenList::front().lineNumber());
}
//- The line number of the last token in stream
label endLineNumber() const
{
return (tokenList::empty() ? -1 : tokenList::back().lineNumber());
}
// Token Access
//- True if putback token is in use
bool hasPutback() const noexcept
{
return Istream::hasPutback();
}
bool hasPutback() const noexcept { return Istream::hasPutback(); }
//- Failsafe peek at the \b first token in the list.
//- Failsafe peek at the token at the \b front of the tokenList
// \return \c undefinedToken if the list is empty.
const token& front() const { return peekAt(0); }
const token& front() const { return peekNoFail(0); }
//- Failsafe peek at the \b last token in the list.
//- Failsafe peek at the token at the \b back of the tokenList
// \return \c undefinedToken if the list is empty.
const token& back() const { return peekAt(tokenList::size()-1); }
const token& back() const { return peekNoFail(tokenList::size()-1); }
//- Failsafe peek at what the next read would return,
//- including handling of any putback
// \return \c undefinedToken if list is exhausted
const token& peek() const;
//- Read access to the token at the current tokenIndex.
//- \returns \c undefinedToken if list is exhausted
const token& currentToken() const { return peekNoFail(tokenIndex_); }
//- Write access to the token at the current tokenIndex.
//- Fatal if not in range
token& currentToken();
//- Failsafe read access to token at given position in the tokenList
// \return \c undefinedToken for out-of-range
const token& peekToken(const label i) const { return peekNoFail(i); };
//- The current token index when reading, or the insertion point.
label tokenIndex() const noexcept { return tokenIndex_; }
//- Non-const access to the current token index
label& tokenIndex() noexcept { return tokenIndex_; }
//- Set the token index. \return the previous value
//- Set the token index (no checks). \return the previous value
label tokenIndex(const label num) noexcept
{
label old(tokenIndex_);
@ -277,15 +297,52 @@ public:
void seek(label pos);
//- Move tokenIndex relative to the current position.
// Will not overrun the beginning or end positions.
// Will not overrun the beginning (0) or one-past end positions.
//
// Use skip(2) to move forward two tokens.
// Use skip(-2) to move backward two tokens.
void skip(label n = 1);
// \return True if the indexing completed without underflow/overflow
bool skip(label n = 1);
// Searching
//- Regular searching
using tokenList::find;
//- Find range containing matching delimiter pair, starting at the
//- the specified position. The position -1 indicates to continue
//- from the present tokenIndex() position.
labelRange find
(
const token::punctuationToken delimOpen,
const token::punctuationToken delimClose,
label pos = 0
) const;
// Token list modification
//- Remove a (start,size) subset from the list and move remaining
//- elements down.
// If the tokenIndex() is within or to the right of the removed
// region, it will be adjusted to remain valid. However, this may
// not correspond to the expected parsing point so external bookkeeping
// is likely necessary.
// \note The range is subsetted with the list size itself to ensure
// the result always addresses a valid section of the list.
ITstream extract(const labelRange& range);
//- Remove a (start,size) subset from the list and move remaining
//- elements down.
// If the tokenIndex() is within or to the right of the removed
// region, it will be adjusted to remain valid. However, this may
// not correspond to the expected parsing point so external bookkeeping
// is likely necessary.
// \note The range is subsetted with the list size itself to ensure
// the result always addresses a valid section of the list.
label remove(const labelRange& range);
//- Copy append a token at the current tokenIndex,
//- incrementing the index.
void push_back(const token& t, const bool lazy);
@ -326,51 +383,44 @@ public:
}
// Read Functions
// Read Functions
//- Return next token from stream
virtual Istream& read(token& tok);
//- Return next token from stream
virtual Istream& read(token& tok);
//- Read a character
virtual Istream& read(char&);
//- Read a character : triggers not implemented error
virtual Istream& read(char&);
//- Read a word
virtual Istream& read(word&);
//- Read a word : triggers not implemented error
virtual Istream& read(word&);
// Read a string (including enclosing double-quotes)
virtual Istream& read(string&);
//- Read a string (including enclosing double-quotes) :
//- triggers not implemented error
virtual Istream& read(string&);
//- Read a label
virtual Istream& read(label&);
//- Read a label : triggers not implemented error
virtual Istream& read(label&);
//- Read a float
virtual Istream& read(float&);
//- Read a float : triggers not implemented error
virtual Istream& read(float&);
//- Read a double
virtual Istream& read(double&);
//- Read a double : triggers not implemented error
virtual Istream& read(double&);
//- Read binary block
// \note Not implemented
virtual Istream& read(char* data, std::streamsize);
//- Read binary block : triggers not implemented error
virtual Istream& read(char* data, std::streamsize);
//- Low-level raw binary read
// \note Not implemented
virtual Istream& readRaw(char* data, std::streamsize count);
//- Low-level raw binary read : triggers not implemented error
virtual Istream& readRaw(char* data, std::streamsize count);
//- Start of low-level raw binary read
virtual bool beginRawRead()
{
return false;
}
//- Start of low-level raw binary read : no-op
virtual bool beginRawRead() { return false; }
//- End of low-level raw binary read
virtual bool endRawRead()
{
return false;
}
//- End of low-level raw binary read : no-op
virtual bool endRawRead() { return false; }
//- Rewind the stream so that it may be read again
virtual void rewind();
//- Rewind the stream so that it may be read again. Same as seek(0)
virtual void rewind();
// Output
@ -385,7 +435,7 @@ public:
// Member Operators
//- Use operator() from Istream
//- Return a non-const reference to const Istream
using Istream::operator();
//- Copy assignment, with rewind()

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,8 +36,8 @@ Note
namespace Foam
{
typedef token::compound tokenCompound;
defineTypeNameAndDebug(tokenCompound, 0);
defineRunTimeSelectionTable(tokenCompound, Istream);
defineTypeName(tokenCompound);
defineRunTimeSelectionTable(tokenCompound, empty);
}
const Foam::token Foam::token::undefinedToken;
@ -57,11 +57,33 @@ void Foam::token::parseError(const char* expected) const
Foam::autoPtr<Foam::token::compound> Foam::token::compound::New
(
const word& compoundType,
Istream& is
const word& compoundType
)
{
auto* ctorPtr = IstreamConstructorTable(compoundType);
auto* ctorPtr = emptyConstructorTable(compoundType);
if (!ctorPtr)
{
FatalErrorInLookup
(
"compound",
compoundType,
*emptyConstructorTablePtr_
) << abort(FatalError);
}
return autoPtr<token::compound>(ctorPtr());
}
Foam::autoPtr<Foam::token::compound> Foam::token::compound::New
(
const word& compoundType,
Istream& is,
const bool readContent
)
{
auto* ctorPtr = emptyConstructorTable(compoundType);
if (!ctorPtr)
{
@ -70,49 +92,76 @@ Foam::autoPtr<Foam::token::compound> Foam::token::compound::New
is,
"compound",
compoundType,
*IstreamConstructorTablePtr_
*emptyConstructorTablePtr_
) << abort(FatalIOError);
}
return autoPtr<Foam::token::compound>(ctorPtr(is));
autoPtr<token::compound> aptr(ctorPtr());
if (readContent)
{
aptr->read(is);
}
return aptr;
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::token::compound::isCompound(const word& name)
bool Foam::token::compound::isCompound(const word& compoundType)
{
// Could also return the constructor pointer directly
// and test as bool or use for construction
//
// token::compound::emptyConstructorPtr ctorPtr = nullptr;
// if (emptyConstructorTablePtr_)
// {
// ctorPtr = emptyConstructorTablePtr_->cfind(compoundType);
// if (iter.good()) ctorPtr = iter.val();
// }
// return ctorPtr;
return
(
IstreamConstructorTablePtr_
&& IstreamConstructorTablePtr_->found(name)
emptyConstructorTablePtr_
&& emptyConstructorTablePtr_->contains(compoundType)
);
}
Foam::token::compound& Foam::token::transferCompoundToken()
bool Foam::token::readCompoundToken
(
const word& compoundType,
Istream& is,
const bool readContent
)
{
if (type_ != tokenType::COMPOUND)
// Like compound::New() but more failure tolerant.
// - a no-op if the compoundType is unknown
auto* ctorPtr = token::compound::emptyConstructorTable(compoundType);
if (!ctorPtr)
{
parseError("compound");
return false;
}
if (data_.compoundPtr->moved())
{
FatalErrorInFunction
<< "compound has already been transferred from token\n "
<< info() << abort(FatalError);
}
else
{
data_.compoundPtr->moved(true);
}
autoPtr<token::compound> aptr(ctorPtr());
return *data_.compoundPtr;
if (readContent)
{
aptr->read(is);
}
// Could also set pending(false) for !readContent,
// but prefer to leave that to the caller.
(*this) = std::move(aptr);
return true;
}
Foam::token::compound& Foam::token::transferCompoundToken(const Istream& is)
Foam::token::compound& Foam::token::transferCompoundToken(const Istream* is)
{
if (type_ != tokenType::COMPOUND)
{
@ -121,12 +170,38 @@ Foam::token::compound& Foam::token::transferCompoundToken(const Istream& is)
if (data_.compoundPtr->moved())
{
FatalIOErrorInFunction(is)
<< "compound has already been transferred from token\n "
<< info() << abort(FatalIOError);
if (is)
{
FatalIOErrorInFunction(*is)
<< "compound has already been transferred from token\n "
<< info() << abort(FatalIOError);
}
else
{
FatalErrorInFunction
<< "compound has already been transferred from token\n "
<< info() << abort(FatalError);
}
}
// // TDB
// else if (data_.compoundPtr->pending())
// {
// if (is)
// {
// FatalIOErrorInFunction(*is)
// << "compound is pending (not yet read?)\n "
// << info() << abort(FatalIOError);
// }
// else
// {
// FatalErrorInFunction
// << "compound is pending (not yet read?)\n "
// << info() << abort(FatalError);
// }
// }
else
{
// TBD: reset pending?
data_.compoundPtr->moved(true);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -44,8 +44,9 @@ SourceFiles
#include "uLabel.H"
#include "scalar.H"
#include "word.H"
#include "InfoProxy.H"
#include "contiguous.H"
#include "refCount.H"
#include "InfoProxy.H"
#include "typeInfo.H"
#define NoHashTableC
@ -170,28 +171,25 @@ public:
:
public refCount
{
//- Has compound token already been transferred
bool moved_;
protected:
//- No copy construct
compound(const compound&) = delete;
//- No copy assignment
compound& operator=(const compound&) = delete;
//- The compound token state, internally used values only
// (0: initial, 1: moved, 2: pending read...)
unsigned char state_;
public:
//- Declare type-name, virtual type (with debug switch)
TypeName("compound");
//- Declare type-name, virtual type (without debug switch)
TypeNameNoDebug("compound");
//- Declare run-time constructor selection table
declareRunTimeSelectionTable
(
autoPtr,
compound,
Istream,
(Istream& is),
(is)
empty,
(),
()
);
@ -200,41 +198,95 @@ public:
//- Default construct
constexpr compound() noexcept
:
moved_(false)
state_(0)
{}
//- Construct compound from Istream
static autoPtr<compound> New(const word& type, Istream& is);
//- Destructor
virtual ~compound() noexcept = default;
// Selectors
//- Default construct specified compound type
static autoPtr<compound> New(const word& compoundType);
//- Default construct specified compound type
//- and read from stream
static autoPtr<compound> New
(
const word& compoundType,
Istream& is,
const bool readContent = true
);
//- Check if dynamic_cast to \c Type is possible.
template<class Type>
const Type* isA() const
{
return dynamic_cast<const Type*>(this);
}
// Member Functions
//- Test if name is a known (registered) compound type
static bool isCompound(const word& name);
//- True if a known (registered) compound type
static bool isCompound(const word& compoundType);
//- Get compound transferred status
bool moved() const noexcept
{
return moved_;
}
bool moved() const noexcept { return (state_ & 1); }
//- Set compound transferred status
void moved(bool b) noexcept
{
moved_ = b;
if (b) { state_ |= 1; } else { state_ &= ~1; }
}
//- Get compound pending-read status
bool pending() const noexcept { return (state_ & 2); }
//- Set compound pending-read status
void pending(bool b) noexcept
{
if (b) { state_ |= 2; } else { state_ &= ~2; }
}
//- The size of the underlying content
virtual label size() const = 0;
//- Redirect write to underlying content
//- Change the size of the underlying container content
virtual void resize(const label n) = 0;
//- Fill with zero values, or with default constructed
virtual void fill_zero() = 0;
//- Read from stream into the underlying content
virtual void read(Istream& is) = 0;
//- Write the underlying content
virtual void write(Ostream& os) const = 0;
// Attributes and access methods
//- The token type (if any) corresponding to the contained
//- component type (LABEL, FLOAT, DOUBLE, etc).
virtual tokenType typeCode() const = 0;
//- The number of vector-space or other components
//- of the underlying data content
virtual direction nComponents() const = 0;
//- Pointer to the underlying data as byte data
virtual const char* cdata_bytes() const = 0;
//- Pointer to the underlying data as byte data
virtual char* data_bytes() = 0;
//- Size of the (contiguous) byte data
virtual std::streamsize size_bytes() const = 0;
// Operators
//- Output operator
@ -242,30 +294,63 @@ public:
};
//- A templated class for holding compound tokens
//- A templated class for holding compound tokens.
//- The underlying container is normally a List of values,
//- it must have a \c value_type typedef as well as
//- size(), resize(), cdata_bytes(), data_bytes(), size_bytes() methods
template<class T>
class Compound
:
public token::compound,
public T
{
// Private Member Functions
//- Fill with zero (contiguous types)
template<class ValT = typename T::value_type>
typename std::enable_if<pTraits_has_zero<ValT>::value, void>::type
_m_fill_zero()
{
T::operator=(pTraits<ValT>::zero);
}
//- Fill with default value initialized (non-contiguous types)
template<class ValT = typename T::value_type>
typename std::enable_if<!pTraits_has_zero<ValT>::value, void>::type
_m_fill_zero()
{
T::operator=(ValT());
}
public:
//- Declare type-name, virtual type (with debug switch)
TypeName("Compound<T>");
//- The type of values held by the compound
typedef typename T::value_type value_type;
//- Declare type-name, virtual type (without debug switch)
TypeNameNoDebug("Compound<T>");
//- No copy construct
Compound<T>(const Compound<T>&) = delete;
//- No copy assignment
Compound<T>& operator=(const Compound<T>&) = delete;
// Constructors
//- Copy construct
explicit Compound(const T& val)
//- Default construct
Compound() = default;
//- Copy construct from base content
explicit Compound(const T& content)
:
T(val)
T(content)
{}
//- Move construct
explicit Compound(T&& val)
//- Move construct from base content
explicit Compound(T&& content)
:
T(std::move(val))
T(std::move(content))
{}
//- Read construct from Istream
@ -275,6 +360,19 @@ public:
{}
// Selectors
//- Construct autoPtr compound type with forwarding arguments
template<class... Args>
static autoPtr<Compound<T>> New(Args&&... args)
{
return autoPtr<Compound<T>>
(
new Compound<T>(T(std::forward<Args>(args)...))
);
}
// Member Functions
//- The size of the underlying content
@ -283,11 +381,59 @@ public:
return T::size();
}
//- Change the size of the underlying container content
virtual void resize(const label n)
{
T::resize(n);
}
//- Fill with zero value or with default value initialized
virtual void fill_zero() { _m_fill_zero(); }
//- Redirect read to underlying content
virtual void read(Istream& is)
{
token::compound::state_ = 0; // Clean state
operator>>(is, static_cast<T&>(*this));
}
//- Redirect write to underlying content
virtual void write(Ostream& os) const
{
operator<<(os, static_cast<const T&>(*this));
}
// Attributes and access methods
//- The token type (if any) corresponding to the contained
//- component type (LABEL, FLOAT, DOUBLE, etc).
virtual tokenType typeCode() const;
//- The number of vector-space or other components
//- of the underlying data content
virtual direction nComponents() const
{
return pTraits_nComponents<value_type>();
}
//- Pointer to the underlying data as byte data
virtual const char* cdata_bytes() const
{
return T::cdata_bytes();
}
//- Pointer to the underlying data as byte data
virtual char* data_bytes()
{
return T::data_bytes();
}
//- Size of the (contiguous) byte data
virtual std::streamsize size_bytes() const
{
return T::size_bytes();
}
};
@ -385,6 +531,9 @@ public:
//- Construct from a compound pointer, taking ownership
inline explicit token(token::compound* ptr, label lineNum=0);
//- Move construct from a compound pointer, taking ownership
inline explicit token(autoPtr<token::compound>&& ptr, label lineNum=0);
//- Construct from Istream
explicit token(Istream& is);
@ -416,8 +565,11 @@ public:
// Status
//- Return the name of the token type
word name() const;
//- Return the name for the token type
static word name(const token::tokenType tokType);
//- Return the name of the current token type
inline word name() const;
//- Return the token type
inline tokenType type() const noexcept;
@ -510,6 +662,15 @@ public:
//- Token is COMPOUND
inline bool isCompound() const noexcept;
//- True if token is COMPOUND and its type() is equal to parameter
inline bool isCompound(const word& compoundType) const;
//- If token is COMPOUND and can be dynamic_cast to the \c Type
//- return a const pointer to the content.
// Return nullptr on any failure.
template<class Type>
inline const Type* isCompound() const;
//- True if token is not UNDEFINED or ERROR. Same as good().
explicit operator bool() const noexcept { return good(); }
@ -561,15 +722,35 @@ public:
// or an upcast WORD or DIRECTIVE
inline const string& stringToken() const;
//- Read access for compound token
//- Const reference to compound token. Fatal if the wrong type.
inline const compound& compoundToken() const;
//- Return reference to compound token. Fatal if the wrong type.
inline compound& 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.
bool readCompoundToken
(
const word& compoundType,
Istream& is,
const bool readContent = true
);
//- Return reference to compound and mark internally as \em released.
compound& transferCompoundToken();
// Optional Istream parameter only as reference for errors messages.
compound& transferCompoundToken(const Istream* is = nullptr);
//- Return reference to compound and mark internally as \em released.
// The Istream is used for reference error messages only.
compound& transferCompoundToken(const Istream& is);
inline compound& transferCompoundToken(const Istream& is);
//- Mark the compound as \em released and return a reference
//- to the underlying encapsulated container - eg, \c List<label>
// The Istream is used for reference error messages only.
template<class Type>
inline Type& transferCompoundToken(const Istream& is);
// Edit
@ -581,7 +762,7 @@ public:
inline void setBad();
//- Swap token contents: type, data, line-number
inline void swap(token& tok);
inline void swap(token& tok) noexcept;
// Info
@ -713,21 +894,21 @@ Ostream& operator<<(Ostream& os, const InfoProxy<token>& ip);
//- Define compound using \a Type for its name
#define defineCompoundTypeName(Type, UnusedTag) \
defineTemplateTypeNameAndDebugWithName(token::Compound<Type>, #Type, 0);
defineTemplateTypeNameWithName(token::Compound<Type>, #Type);
//- Define compound using \a Name for its name
#define defineNamedCompoundTypeName(Type, Name) \
defineTemplateTypeNameAndDebugWithName(token::Compound<Type>, #Name, 0);
defineTemplateTypeNameWithName(token::Compound<Type>, #Name);
//- Add compound to selection table, lookup using typeName
//- Add compound to selection tables, lookup using typeName
#define addCompoundToRunTimeSelectionTable(Type, Tag) \
token::compound::addIstreamConstructorToTable<token::Compound<Type>> \
add##Tag##IstreamConstructorToTable_;
token::compound::addemptyConstructorToTable<token::Compound<Type>> \
add##Tag##emptyConstructorToTable_;
//- Add compound to selection table, lookup as \a Name
//- Add compound to selection tables, lookup as \a Name
#define addNamedCompoundToRunTimeSelectionTable(Type, Tag, Name) \
token::compound::addIstreamConstructorToTable<token::Compound<Type>> \
add##Tag##IstreamConstructorToTable_(#Name);
token::compound::addemptyConstructorToTable<token::Compound<Type>> \
add##Tag##emptyConstructorToTable_(#Name);
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -241,9 +241,20 @@ inline Foam::token::token(token::compound* ptr, label lineNum)
line_(lineNum)
{
data_.compoundPtr = ptr;
if (!data_.compoundPtr)
{
// Could handle nullptr as Fatal, but this is simpler
setUndefined();
}
}
inline Foam::token::token(autoPtr<token::compound>&& ptr, label lineNum)
:
token(ptr.release(), lineNum)
{}
// * * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * //
inline Foam::token::~token()
@ -295,7 +306,14 @@ inline void Foam::token::reset()
}
inline void Foam::token::swap(token& tok)
inline void Foam::token::setBad()
{
reset();
type_ = tokenType::ERROR;
}
inline void Foam::token::swap(token& tok) noexcept
{
if (this == &tok)
{
@ -308,6 +326,12 @@ inline void Foam::token::swap(token& tok)
}
inline Foam::word Foam::token::name() const
{
return token::name(type_);
}
inline Foam::token::tokenType Foam::token::type() const noexcept
{
return type_;
@ -452,7 +476,7 @@ inline int Foam::token::flagToken() const
}
parseError("flag bitmask");
return NO_FLAG;
return flagType::NO_FLAG;
}
@ -719,22 +743,109 @@ inline bool Foam::token::isCompound() const noexcept
}
inline const Foam::token::compound& Foam::token::compoundToken() const
inline bool Foam::token::isCompound(const word& compoundType) const
{
if (type_ == tokenType::COMPOUND)
{
return *data_.compoundPtr;
}
parseError("compound");
return *data_.compoundPtr; // This is questionable.
return
(
type_ == tokenType::COMPOUND
&& data_.compoundPtr->type() == compoundType
);
}
inline void Foam::token::setBad()
template<class Type>
inline const Type* Foam::token::isCompound() const
{
reset();
type_ = tokenType::ERROR;
return
(
type_ == tokenType::COMPOUND
? dynamic_cast<const Type*>(data_.compoundPtr)
: nullptr
);
}
inline const Foam::token::compound& Foam::token::compoundToken() const
{
if (type_ != tokenType::COMPOUND)
{
parseError("compound");
}
return *data_.compoundPtr;
}
inline Foam::token::compound& Foam::token::refCompoundToken()
{
if (type_ != tokenType::COMPOUND)
{
parseError("compound");
}
return *data_.compoundPtr;
}
inline Foam::token::compound&
Foam::token::transferCompoundToken(const Istream& is)
{
return transferCompoundToken(&is);
}
template<class Type>
inline Type& Foam::token::transferCompoundToken(const Istream& is)
{
return static_cast<Type&>
(
dynamicCast<token::Compound<Type>>
(
transferCompoundToken(&is)
)
);
}
template<class T>
Foam::token::tokenType Foam::token::Compound<T>::typeCode() const
{
// Does not cover all possibilities perfectly, but should handle
// most of the common ones (bool, label, scalar, vector lists).
// Something like List<edge> will not be quite correct if we rely
// on nComponents
typedef typename T::value_type valueType;
if (std::is_same<valueType, bool>::value)
{
// List<bool>
return token::tokenType::BOOL;
}
else if (is_contiguous_label<valueType>::value)
{
// List<label>, List<labelVector> etc
return token::tokenType::LABEL;
}
else if (is_contiguous_scalar<valueType>::value)
{
// List<scalar>, List<vector>, List<tensor> etc
return
(
sizeof(float) == sizeof(Foam::scalar)
? token::tokenType::FLOAT
: token::tokenType::DOUBLE
);
}
else if (std::is_same<valueType, char>::value)
{
// List<char>
return token::tokenType::PUNCTUATION;
}
else
{
// Do not handle List<word> or List<string> at the moment
// since filling non-contiguous data is probably not desirable
return token::tokenType::UNDEFINED;
}
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,7 +28,6 @@ License
#include "error.H"
#include "token.H"
#include "scalar.H"
#include "IOstreams.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -96,6 +95,10 @@ static OS& printTokenInfo(OS& os, const token& tok)
case token::tokenType::COMPOUND:
{
if (tok.compoundToken().pending())
{
os << "pending ";
}
if (tok.compoundToken().moved())
{
os << "moved ";
@ -129,11 +132,11 @@ Foam::token::token(Istream& is)
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::word Foam::token::name() const
Foam::word Foam::token::name(const token::tokenType tokType)
{
switch (type_)
switch (tokType)
{
case token::tokenType::UNDEFINED: return "undefined";
case token::tokenType::BOOL: return "bool";
@ -155,7 +158,7 @@ Foam::word Foam::token::name() const
break;
}
return "unknown(" + std::to_string(int(type_)) + ")";
return "unknown(" + std::to_string(int(tokType)) + ")";
}
@ -251,8 +254,13 @@ Foam::Ostream& Foam::operator<<(Ostream& os, const token::punctuationToken& pt)
Foam::Ostream& Foam::operator<<(Ostream& os, const token::compound& ct)
{
os << ct.type() << token::SPACE;
ct.write(os);
os << ct.type();
if (!ct.pending())
{
// Do not write compound content if tagged as 'pending-read'
os << token::SPACE;
ct.write(os);
}
return os;
}

View File

@ -260,54 +260,17 @@ void Foam::dictionary::checkITstream
const word& keyword
) const
{
if (is.nRemainingTokens())
const label remaining = (is.size() ? is.nRemainingTokens() : -100);
if (!remaining)
{
const label remaining = is.nRemainingTokens();
// Similar to SafeFatalIOError
if (JobInfo::constructed)
{
OSstream& err =
FatalIOError
(
"", // functionName
"", // sourceFileName
0, // sourceFileLineNumber
relativeName(), // ioFileName == dictionary name
is.lineNumber() // ioStartLineNumber
);
err << "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl
<< " ";
is.writeList(err, 0);
err << exit(FatalIOError);
}
else
{
std::cerr
<< nl
<< "--> FOAM FATAL IO ERROR:" << nl;
std::cerr
<< "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl;
std::cerr
// ioFileName == dictionary name
<< "file: " << relativeName()
<< " at line " << is.lineNumber() << '.' << nl
<< std::endl;
std::exit(1);
}
return;
}
else if (!is.size())
// Similar to SafeFatalIOError
if (JobInfo::constructed)
{
// Similar to SafeFatalIOError
if (JobInfo::constructed)
{
OSstream& err =
FatalIOError
(
"", // functionName
@ -315,27 +278,52 @@ void Foam::dictionary::checkITstream
0, // sourceFileLineNumber
relativeName(), // ioFileName == dictionary name
is.lineNumber() // ioStartLineNumber
)
<< "Entry '" << keyword
<< "' had no tokens in stream" << nl << nl
<< exit(FatalIOError);
);
if (remaining > 0)
{
err
<< "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl
<< " ";
is.writeList(err, 0); // <- flatOutput
}
else
{
err << "Entry '" << keyword
<< "' had no tokens in stream" << nl << nl;
}
err << exit(FatalIOError);
}
else
{
// Not yet constructed
std::cerr
<< nl
<< "--> FOAM FATAL IO ERROR:" << nl;
if (remaining > 0)
{
std::cerr
<< "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl;
}
else
{
std::cerr
<< nl
<< "--> FOAM FATAL IO ERROR:" << nl
<< "Entry '" << keyword
<< "' had no tokens in stream" << nl << nl;
std::cerr
// ioFileName == dictionary name
<< "file: " << relativeName()
<< " at line " << is.lineNumber() << '.' << nl
<< std::endl;
std::exit(1);
}
std::cerr
// ioFileName == dictionary name
<< "file: " << relativeName()
<< " at line " << is.lineNumber() << '.' << nl
<< std::endl;
std::exit(1);
}
}

View File

@ -414,8 +414,9 @@ public:
bool keepHeader = false
);
//- Construct top-level dictionary from Istream,
//- reading entries until EOF. Discards the header.
//- Construct top-level dictionary from Istream (discards the header).
//- Reads entries until EOF or when the first token is a
//- '{' character, it will stop reading at the matching '}' character.
// \note this constructor should be explicit
dictionary(Istream& is);
@ -970,10 +971,14 @@ public:
// Emits FatalIOError
void checkITstream(const ITstream& is, const word& keyword) const;
//- Read dictionary from Istream. Discards the header.
//- Read dictionary from Istream (discards the header).
//- Reads entries until EOF or when the first token is a
//- '{' character, it will stop reading at the matching '}' character.
bool read(Istream& is);
//- Read dictionary from Istream, optionally keeping the header
//- Read dictionary from Istream (optionally keeping the header)
//- Reads entries until EOF or when the first token is a
//- '{' character, it will stop reading at the matching '}' character.
bool read(Istream& is, bool keepHeader);

View File

@ -109,55 +109,19 @@ void Foam::entry::raiseBadInput(const ITstream& is) const
void Foam::entry::checkITstream(const ITstream& is) const
{
const label remaining = (is.size() ? is.nRemainingTokens() : -100);
if (!remaining)
{
return;
}
const word& keyword = keyword_;
if (is.nRemainingTokens())
// Similar to SafeFatalIOError
if (JobInfo::constructed)
{
const label remaining = is.nRemainingTokens();
// Similar to SafeFatalIOError
if (JobInfo::constructed)
{
OSstream& err =
FatalIOError
(
"", // functionName
"", // sourceFileName
0, // sourceFileLineNumber
this->relativeName(), // ioFileName
is.lineNumber() // ioStartLineNumber
);
err << "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl
<< " ";
is.writeList(err, 0);
err << exit(FatalIOError);
}
else
{
std::cerr
<< nl
<< "--> FOAM FATAL IO ERROR:" << nl;
std::cerr
<< "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl;
std::cerr
<< "file: " << this->relativeName()
<< " at line " << is.lineNumber() << '.' << nl
<< std::endl;
std::exit(1);
}
}
else if (!is.size())
{
// Similar to SafeFatalIOError
if (JobInfo::constructed)
{
OSstream& err =
FatalIOError
(
"", // functionName
@ -165,26 +129,54 @@ void Foam::entry::checkITstream(const ITstream& is) const
0, // sourceFileLineNumber
this->relativeName(), // ioFileName
is.lineNumber() // ioStartLineNumber
)
);
if (remaining > 0)
{
err
<< "Entry '" << keyword
<< "' had no tokens in stream" << nl << nl
<< exit(FatalIOError);
<< "' has " << remaining << " excess tokens in stream"
<< nl << nl
<< " ";
is.writeList(err, 0); // <- flatOutput
}
else
{
err
<< "Entry '" << keyword
<< "' had no tokens in stream"
<< nl << nl;
}
err << exit(FatalIOError);
}
else
{
// Not yet constructed
std::cerr
<< nl
<< "--> FOAM FATAL IO ERROR:" << nl;
if (remaining > 0)
{
std::cerr
<< "Entry '" << keyword << "' has "
<< remaining << " excess tokens in stream" << nl << nl;
}
else
{
std::cerr
<< nl
<< "--> FOAM FATAL IO ERROR:" << nl
<< "Entry '" << keyword
<< "' had no tokens in stream" << nl << nl;
std::cerr
<< "file: " << this->relativeName()
<< " at line " << is.lineNumber() << '.' << nl
<< std::endl;
std::exit(1);
}
std::cerr
<< "file: " << this->relativeName()
<< " at line " << is.lineNumber() << '.' << nl
<< std::endl;
std::exit(1);
}
}

View File

@ -218,14 +218,21 @@ bool Foam::primitiveEntry::expandVariable
Foam::primitiveEntry::primitiveEntry(const keyType& key)
:
entry(key),
ITstream(zero{}, key)
ITstream(Foam::zero{}, key)
{}
Foam::primitiveEntry::primitiveEntry(const keyType& key, const token& tok)
:
entry(key),
ITstream(key, tokenList(one{}, tok))
ITstream(key, tokenList(Foam::one{}, tok))
{}
Foam::primitiveEntry::primitiveEntry(const keyType& key, token&& tok)
:
entry(key),
ITstream(key, tokenList(Foam::one{}, std::move(tok)))
{}
@ -251,7 +258,11 @@ Foam::primitiveEntry::primitiveEntry
{}
Foam::primitiveEntry::primitiveEntry(const keyType& key, const ITstream& is)
Foam::primitiveEntry::primitiveEntry
(
const keyType& key,
const ITstream& is
)
:
entry(key),
ITstream(is)
@ -262,20 +273,6 @@ Foam::primitiveEntry::primitiveEntry(const keyType& key, const ITstream& is)
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
Foam::label Foam::primitiveEntry::startLineNumber() const
{
const tokenList& tokens = *this;
return (tokens.empty() ? -1 : tokens.front().lineNumber());
}
Foam::label Foam::primitiveEntry::endLineNumber() const
{
const tokenList& tokens = *this;
return (tokens.empty() ? -1 : tokens.back().lineNumber());
}
Foam::ITstream& Foam::primitiveEntry::stream() const
{
ITstream& is = const_cast<primitiveEntry&>(*this);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -114,9 +114,12 @@ public:
// Contents to be filled with a later assignment
explicit primitiveEntry(const keyType& key);
//- Construct from keyword and a single token
//- Construct from keyword and a single token (copy)
primitiveEntry(const keyType& key, const token& tok);
//- Construct from keyword and a single token (move)
primitiveEntry(const keyType& key, token&& tok);
//- Construct from keyword and a list of tokens
primitiveEntry(const keyType& key, const UList<token>& tokens);
@ -166,11 +169,17 @@ public:
return ITstream::relativeName();
}
//- Return line number of first token in dictionary
virtual label startLineNumber() const;
//- The line number of the first token in the entry
virtual label startLineNumber() const
{
return ITstream::startLineNumber();
}
//- Return line number of last token in dictionary
virtual label endLineNumber() const;
//- The line number of the last token in the entry
virtual label endLineNumber() const
{
return ITstream::endLineNumber();
}
//- Return true - this entry is a stream
virtual bool isStream() const noexcept
@ -182,11 +191,11 @@ public:
virtual ITstream& stream() const;
//- This entry is not a dictionary,
// calling this function generates a FatalError
//- calling this function generates a FatalError
virtual const dictionary& dict() const;
//- This entry is not a dictionary,
// calling this function generates a FatalError
//- calling this function generates a FatalError
virtual dictionary& dict();
//- Read tokens from the given stream

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -220,12 +220,17 @@ bool Foam::primitiveEntry::read(const dictionary& dict, Istream& is)
void Foam::primitiveEntry::readEntry(const dictionary& dict, Istream& is)
{
const label keywordLineNumber = is.lineNumber();
tokenIndex() = 0;
if (read(dict, is))
if (ITstream::empty())
{
setSize(tokenIndex());
tokenIndex() = 0;
ITstream::resize(16);
}
ITstream::seek(0);
if (read(dict, is)) // Read with 'lazy' appending
{
ITstream::resize(tokenIndex()); // Truncate to number tokens read
ITstream::seek(0);
}
else
{
@ -256,9 +261,8 @@ Foam::primitiveEntry::primitiveEntry
entry(key),
ITstream
(
is.name() + '.' + key,
tokenList(10),
static_cast<IOstreamOption>(is)
static_cast<IOstreamOption>(is),
is.name() + '.' + key
)
{
readEntry(dict, is);

View File

@ -35,11 +35,12 @@ template<class T>
Foam::primitiveEntry::primitiveEntry(const keyType& key, const T& val)
:
entry(key),
ITstream(key, tokenList(10))
ITstream(IOstreamOption(), key)
{
OStringStream os;
os << val << token::END_STATEMENT;
readEntry(dictionary::null, IStringStream(os.str())());
IStringStream is(os.str());
readEntry(dictionary::null, is);
}

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2022 OpenCFD Ltd.
Copyright (C) 2021-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -63,10 +63,7 @@ Istream& List<char>::readList(Istream& is)
list.clear(); // Clear old contents
list.transfer
(
dynamicCast<token::Compound<List<char>>>
(
tok.transferCompoundToken(is)
)
tok.transferCompoundToken<List<char>>(is)
);
}
else if (tok.isLabel())

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2021-2022 OpenCFD Ltd.
Copyright (C) 2021-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -125,10 +125,7 @@ Istream& UList<char>::readList(Istream& is)
List<char> elems;
elems.transfer
(
dynamicCast<token::Compound<List<char>>>
(
tok.transferCompoundToken(is)
)
tok.transferCompoundToken<List<char>>(is)
);
const label inputLen = elems.size();

View File

@ -190,20 +190,13 @@ bool Foam::genericPatchFieldBase::processEntry
#undef doLocalCode
#define doLocalCode(ValueType, Member) \
if \
( \
tok.compoundToken().type() \
== token::Compound<List<ValueType>>::typeName \
) \
if (tok.isCompound<List<ValueType>>()) \
{ \
auto fPtr = autoPtr<Field<ValueType>>::New(); \
\
fPtr->transfer \
( \
dynamicCast<token::Compound<List<ValueType>>> \
( \
tok.transferCompoundToken(is) \
) \
tok.transferCompoundToken<List<ValueType>>(is) \
); \
\
if (!checkFieldSize(fPtr->size(), patchSize, patchName, key, io)) \

View File

@ -256,17 +256,10 @@ bool Foam::mappedPatchBase::writeIOField
{
const auto& fld = *fldPtr;
token tok;
tok = new token::Compound<List<Type>>(fld);
primitiveEntry* pePtr = new primitiveEntry
(
fld.name(),
tokenList
(
one(),
std::move(tok)
)
token(new token::Compound<List<Type>>(fld))
);
dict.set(pePtr);
@ -288,22 +281,12 @@ bool Foam::mappedPatchBase::constructIOField
objectRegistry& obr
)
{
const word tag = "List<" + word(pTraits<Type>::typeName) + '>';
const word tag("List<" + word(pTraits<Type>::typeName) + '>');
if (tok.isCompound() && tok.compoundToken().type() == tag)
if (tok.isCompound(tag))
{
IOField<Type>* fldPtr = obr.getObjectPtr<IOField<Type>>(name);
if (fldPtr)
{
fldPtr->transfer
(
dynamicCast<token::Compound<List<Type>>>
(
tok.transferCompoundToken(is)
)
);
}
else
auto* fldPtr = obr.getObjectPtr<IOField<Type>>(name);
if (!fldPtr)
{
fldPtr = new IOField<Type>
(
@ -311,21 +294,20 @@ bool Foam::mappedPatchBase::constructIOField
(
name,
obr,
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::REGISTER
IOobjectOption::NO_READ,
IOobjectOption::NO_WRITE,
IOobjectOption::REGISTER
),
label(0)
);
fldPtr->transfer
(
dynamicCast<token::Compound<List<Type>>>
(
tok.transferCompoundToken(is)
)
Foam::zero{}
);
objectRegistry::store(fldPtr);
}
fldPtr->transfer
(
tok.transferCompoundToken<List<Type>>(is)
);
return true;
}
else
@ -343,12 +325,8 @@ void Foam::mappedPatchBase::storeField
const Field<Type>& values
)
{
IOField<Type>* fldPtr = obr.getObjectPtr<IOField<Type>>(fieldName);
if (fldPtr)
{
*fldPtr = values;
}
else
auto* fldPtr = obr.getObjectPtr<IOField<Type>>(fieldName);
if (!fldPtr)
{
fldPtr = new IOField<Type>
(
@ -356,14 +334,16 @@ void Foam::mappedPatchBase::storeField
(
fieldName,
obr,
IOobject::NO_READ,
IOobject::NO_WRITE,
IOobject::REGISTER
IOobjectOption::NO_READ,
IOobjectOption::NO_WRITE,
IOobjectOption::REGISTER
),
values
Foam::zero{}
);
objectRegistry::store(fldPtr);
}
*fldPtr = values;
}