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:
commit
11a1f78338
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
3
applications/test/compoundToken1/Make/files
Normal file
3
applications/test/compoundToken1/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-compoundToken1.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-compoundToken1
|
1
applications/test/compoundToken1/Make/options
Normal file
1
applications/test/compoundToken1/Make/options
Normal file
@ -0,0 +1 @@
|
||||
/* EXE_INC = */
|
297
applications/test/compoundToken1/Test-compoundToken1.C
Normal file
297
applications/test/compoundToken1/Test-compoundToken1.C
Normal 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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
24
applications/test/compoundToken1/testDict1
Normal file
24
applications/test/compoundToken1/testDict1
Normal 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;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
65
applications/test/compoundToken1/testDict2
Normal file
65
applications/test/compoundToken1/testDict2
Normal 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;
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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())
|
||||
|
@ -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();
|
||||
|
@ -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));
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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()
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
@ -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())
|
||||
|
@ -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();
|
||||
|
@ -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)) \
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user