ENH: add a test dictionary token streaming class

This commit is contained in:
Mark Olesen 2017-11-07 13:12:43 +01:00
parent ad116ef7f2
commit 2ae2783635
5 changed files with 698 additions and 0 deletions

View File

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

View File

@ -0,0 +1 @@
EXE_INC =

View File

@ -0,0 +1,95 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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/>.
Application
printDictionary
Description
Test dictionaryTokens
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "IOstreams.H"
#include "IOobject.H"
#include "IFstream.H"
#include "dictionaryTokens.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noParallel();
argList::noFunctionObjects();
argList::addBoolOption("info", "report token info");
argList::addBoolOption("value", "report token value");
argList::validArgs.insert("dict .. dictN");
argList args(argc, argv, false, true);
const bool optInfo = args.optionFound("info");
const bool optValue = args.optionFound("value");
for (label argi=1; argi < args.size(); ++argi)
{
IFstream is(args[argi]);
dictionary dict(is);
dictionaryTokens dictTokens(dict);
while (dictTokens.good())
{
if (optInfo)
{
// Token info
Info<< (*dictTokens).info() << nl;
}
else if (optValue)
{
// Token value
Info<< *dictTokens << nl;
}
else
{
// Token type
Info<< (*dictTokens).name() << nl;
}
++dictTokens;
}
Info<< nl;
}
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,309 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
\*---------------------------------------------------------------------------*/
#include "dictionaryTokens.H"
#include "IOstream.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
Foam::token Foam::dictionaryTokens::keywordToken(const entry& e)
{
const keyType& k = e.keyword();
if (k.empty())
{
return token::undefinedToken;
}
if (k.isPattern())
{
return token(static_cast<string>(k)); // quoted
}
else
{
return token(static_cast<word>(k)); // unquoted
}
}
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
bool Foam::dictionaryTokens::setIterator() const
{
primIter_.clear();
dictIter_.clear();
if (entryIter_ != dict_.cend())
{
const entry& base = *entryIter_;
if (isA<primitiveEntry>(base))
{
primIter_.reset
(
new dictionaryTokens::primitive_iterator
(
dynamicCast<const primitiveEntry&>(base)
)
);
return true;
}
else if (isA<dictionaryListEntry>(base))
{
// Must check for isA<dictionaryListEntry> before checking
// for isA<dictionaryEntry> !
dictIter_.reset
(
new dictionaryTokens::dictionary_iterator
(
dynamicCast<const dictionaryListEntry&>(base)
)
);
return true;
}
else if (isA<dictionaryEntry>(base))
{
dictIter_.reset
(
new dictionaryTokens::dictionary_iterator
(
dynamicCast<const dictionaryEntry&>(base)
)
);
return true;
}
}
return false;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::dictionaryTokens::dictionaryTokens(const dictionary& dict)
:
dict_(dict),
entryIter_(dict_.cbegin()),
primIter_(nullptr),
dictIter_(nullptr)
{
rewind();
}
Foam::dictionaryTokens::primitive_iterator::primitive_iterator
(
const primitiveEntry& e
)
:
tokensPtr_(&(static_cast<const tokenList&>(e))),
key_(dictionaryTokens::keywordToken(e)),
end_(token::punctuationToken::END_STATEMENT),
pos_((key_.good() ? -1 : 0))
{}
Foam::dictionaryTokens::dictionary_iterator::dictionary_iterator
(
const dictionaryEntry& e
)
:
key_(dictionaryTokens::keywordToken(e)),
lbrace_(token::punctuationToken::BEGIN_BLOCK),
rbrace_(token::punctuationToken::END_BLOCK),
state_(key_.good() ? states::KEY : states::OPEN),
dictTokens_(e.dict())
{}
Foam::dictionaryTokens::dictionary_iterator::dictionary_iterator
(
const dictionaryListEntry& e
)
:
key_(e.size()),
lbrace_(token::punctuationToken::BEGIN_LIST),
rbrace_(token::punctuationToken::END_LIST),
state_(states::KEY),
dictTokens_(e.dict())
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
bool Foam::dictionaryTokens::good() const
{
return
(
entryIter_ != dict_.cend()
&&
(
(primIter_.valid() && primIter_().good())
|| (dictIter_.valid() && dictIter_().good())
)
);
}
bool Foam::dictionaryTokens::primitive_iterator::good() const
{
return (tokensPtr_ && pos_ <= tokensPtr_->size());
}
bool Foam::dictionaryTokens::dictionary_iterator::good() const
{
return (state_ != states::END);
}
const Foam::token& Foam::dictionaryTokens::operator*() const
{
if (good())
{
if (primIter_.valid()) return *(primIter_());
if (dictIter_.valid()) return *(dictIter_());
}
return token::undefinedToken;
}
const Foam::token&
Foam::dictionaryTokens::primitive_iterator::operator*() const
{
if (good())
{
if (pos_ == -1)
{
return key_;
}
else if (pos_ >= tokensPtr_->size())
{
return end_; // The trailing ';'
}
return tokensPtr_->operator[](pos_);
}
return token::undefinedToken;
}
const Foam::token&
Foam::dictionaryTokens::dictionary_iterator::operator*() const
{
if (good())
{
if (state_ == states::KEY)
{
return key_; // keyword
}
if (state_ == states::OPEN)
{
return lbrace_; // Opening '{'
}
if (state_ == states::CONTENT)
{
return *(dictTokens_);
}
if (state_ == states::CLOSE)
{
return rbrace_; // Closing '}'
}
}
return token::undefinedToken;
}
bool Foam::dictionaryTokens::operator++()
{
bool ok = good();
if (ok)
{
if (primIter_.valid()) ok = ++(primIter_());
if (dictIter_.valid()) ok = ++(dictIter_());
if (!ok)
{
++entryIter_; // Next entry
setIterator();
}
}
return ok;
}
bool Foam::dictionaryTokens::primitive_iterator::operator++()
{
// Advance good iterators.
//
// Going beyond trailing ';' makes it into an end iterator
if (tokensPtr_ && (++pos_ > tokensPtr_->size()))
{
tokensPtr_ = nullptr;
return false;
}
return this->good();
}
bool Foam::dictionaryTokens::dictionary_iterator::operator++()
{
if
(
state_ == states::KEY
|| state_ == states::OPEN
|| state_ == states::CLOSE
)
{
++state_;
}
else if (state_ == states::CONTENT && !(++dictTokens_))
{
++state_;
}
return good();
}
void Foam::dictionaryTokens::rewind()
{
entryIter_ = dict_.cbegin();
setIterator();
}
// ************************************************************************* //

View File

@ -0,0 +1,289 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
OpenFOAM is free software: you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
You should have received a copy of the GNU General Public License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class
Foam::dictionaryTokens
Description
Provides a stream of tokens from a dictionary.
This can be used to return a stream of tokens from a dictionary
without overhead or needing to reparse information.
For example,
\code
OPstream os = ...;
dictionaryTokens toks(dict);
while (toks.good())
{
os.write(*toks);
++toks;
}
\endcode
Or alternatively,
\code
dictionaryTokens toks(dict);
while (toks.good())
{
os << *toks << nl;
++toks;
}
\endcode
SourceFiles
dictionaryTokens.C
\*---------------------------------------------------------------------------*/
#ifndef dictionaryTokens_H
#define dictionaryTokens_H
#include "dictionary.H"
#include "primitiveEntry.H"
#include "dictionaryEntry.H"
#include "dictionaryListEntry.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward declarations
class dictionaryTokens;
/*---------------------------------------------------------------------------*\
Class dictionaryTokens Declaration
\*---------------------------------------------------------------------------*/
class dictionaryTokens
{
public:
// Forward declarations
class primitive_iterator;
class dictionary_iterator;
private:
// Private Member Data
//- Reference to the dictionary being streamed.
const dictionary& dict_;
//- The current entry iterator
IDLList<entry>::const_iterator entryIter_;
//- The current entry iterator for primitiveEntry types
mutable autoPtr<primitive_iterator> primIter_;
//- The current entry iterator for dictionaryEntry and
//- dictionaryListEntry types
mutable autoPtr<dictionary_iterator> dictIter_;
//- Set/unset primitive and dictionary when changing to next entry
bool setIterator() const;
// Private Member Functions
//- Disallow bitwise copy/assignment
dictionaryTokens(const dictionaryTokens&) = delete;
void operator=(const dictionaryTokens&) = delete;
public:
// Static Member Functions
//- The entry keyword as word or string token
static token keywordToken(const entry& e);
// Constructors
//- Construct from reference to dictionary to be streamed
dictionaryTokens(const dictionary& dict);
// Member Functions
//- True if the token stream is in a valid state
bool good() const;
//- The current token, or undefined if the stream is in an invalid
//- invalid state.
const token& operator*() const;
//- Advance to the next token and return the updated stream stream.
bool operator++();
//- Reset to beginning
void rewind();
};
/*---------------------------------------------------------------------------*\
Class dictionaryTokens::primitive_iterator Declaration
\*---------------------------------------------------------------------------*/
//- An iterator for a primitiveEntry
//
// The token stream output has the form
//
// \verbatim
// keyword content tokens ';'
// \endverbatim
//
class dictionaryTokens::primitive_iterator
{
// Private Member Data
//- Reference to the tokenList being streamed.
const tokenList* tokensPtr_;
//- The keyword as a token (string, word or undefined)
const token key_;
//- The closing ';' as a token
const token end_;
//- The current position within the tokenList
label pos_;
// Private Member Functions
//- Disallow bitwise copy/assignment
primitive_iterator(const primitive_iterator&) = delete;
void operator=(const primitive_iterator&) = delete;
public:
// Constructors
//- Construct from reference to primitiveEntry
primitive_iterator(const primitiveEntry& e);
// Member Functions
//- True if the entry has keyword or tokens and has not indexed beyond
//- the final trailing ';'
bool good() const;
//- The current token, or undefined if the stream is invalid.
const token& operator*() const;
//- Advance to the next token and return the updated stream stream.
bool operator++();
};
/*---------------------------------------------------------------------------*\
Class dictionaryTokens::dictionary_iterator Declaration
\*---------------------------------------------------------------------------*/
//- An iterator for a dictionaryEntry and dictionaryListEntry
//
// The token stream output has the form
//
// \verbatim
// keyword '{' content '}'
// \endverbatim
//
// or for the dictionaryListEntry the form
//
// \verbatim
// size '(' content ')'
// \endverbatim
//
class dictionaryTokens::dictionary_iterator
{
// Private Member Data
//- The possible output states
enum states { KEY=0, OPEN, CONTENT, CLOSE, END };
//- The keyword or the size (dictionaryListEntry) as a token
const token key_;
//- The opening brace '{' or bracket '('
const token lbrace_;
//- The closing brace ')' or bracket ')'
const token rbrace_;
//- The current output state
int state_;
//- A streamer for the dictionary content
dictionaryTokens dictTokens_;
// Private Member Functions
//- Disallow bitwise copy/assignment
dictionary_iterator(const dictionary_iterator&) = delete;
void operator=(const dictionary_iterator&) = delete;
public:
// Constructors
//- Construct from reference to dictionaryEntry
dictionary_iterator(const dictionaryEntry& e);
//- Construct from reference to dictionaryListEntry
dictionary_iterator(const dictionaryListEntry& e);
// Member Functions
//- In a valid state
bool good() const;
//- The current token, or undefined if the stream is invalid.
const token& operator*() const;
//- Advance to the next token and return the updated stream stream.
bool operator++();
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
#endif
// ************************************************************************* //