From 2ae278363534577035c88177494b359aab97a908 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Tue, 7 Nov 2017 13:12:43 +0100 Subject: [PATCH] ENH: add a test dictionary token streaming class --- applications/test/dictionaryTokens/Make/files | 4 + .../test/dictionaryTokens/Make/options | 1 + .../dictionaryTokens/Test-dictionaryTokens.C | 95 ++++++ .../test/dictionaryTokens/dictionaryTokens.C | 309 ++++++++++++++++++ .../test/dictionaryTokens/dictionaryTokens.H | 289 ++++++++++++++++ 5 files changed, 698 insertions(+) create mode 100644 applications/test/dictionaryTokens/Make/files create mode 100644 applications/test/dictionaryTokens/Make/options create mode 100644 applications/test/dictionaryTokens/Test-dictionaryTokens.C create mode 100644 applications/test/dictionaryTokens/dictionaryTokens.C create mode 100644 applications/test/dictionaryTokens/dictionaryTokens.H diff --git a/applications/test/dictionaryTokens/Make/files b/applications/test/dictionaryTokens/Make/files new file mode 100644 index 0000000000..413023a014 --- /dev/null +++ b/applications/test/dictionaryTokens/Make/files @@ -0,0 +1,4 @@ +Test-dictionaryTokens.C +dictionaryTokens.C + +EXE = $(FOAM_USER_APPBIN)/Test-dictionaryTokens diff --git a/applications/test/dictionaryTokens/Make/options b/applications/test/dictionaryTokens/Make/options new file mode 100644 index 0000000000..41306609f2 --- /dev/null +++ b/applications/test/dictionaryTokens/Make/options @@ -0,0 +1 @@ +EXE_INC = diff --git a/applications/test/dictionaryTokens/Test-dictionaryTokens.C b/applications/test/dictionaryTokens/Test-dictionaryTokens.C new file mode 100644 index 0000000000..6e77cddc5f --- /dev/null +++ b/applications/test/dictionaryTokens/Test-dictionaryTokens.C @@ -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 . + +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; +} + + +// ************************************************************************* // diff --git a/applications/test/dictionaryTokens/dictionaryTokens.C b/applications/test/dictionaryTokens/dictionaryTokens.C new file mode 100644 index 0000000000..28cb9f30cf --- /dev/null +++ b/applications/test/dictionaryTokens/dictionaryTokens.C @@ -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 . + +\*---------------------------------------------------------------------------*/ + +#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(k)); // quoted + } + else + { + return token(static_cast(k)); // unquoted + } +} + + +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +bool Foam::dictionaryTokens::setIterator() const +{ + primIter_.clear(); + dictIter_.clear(); + + if (entryIter_ != dict_.cend()) + { + const entry& base = *entryIter_; + + if (isA(base)) + { + primIter_.reset + ( + new dictionaryTokens::primitive_iterator + ( + dynamicCast(base) + ) + ); + + return true; + } + else if (isA(base)) + { + // Must check for isA before checking + // for isA ! + + dictIter_.reset + ( + new dictionaryTokens::dictionary_iterator + ( + dynamicCast(base) + ) + ); + + return true; + } + else if (isA(base)) + { + dictIter_.reset + ( + new dictionaryTokens::dictionary_iterator + ( + dynamicCast(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(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(); +} + + +// ************************************************************************* // diff --git a/applications/test/dictionaryTokens/dictionaryTokens.H b/applications/test/dictionaryTokens/dictionaryTokens.H new file mode 100644 index 0000000000..f686633567 --- /dev/null +++ b/applications/test/dictionaryTokens/dictionaryTokens.H @@ -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 . + +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::const_iterator entryIter_; + + //- The current entry iterator for primitiveEntry types + mutable autoPtr primIter_; + + //- The current entry iterator for dictionaryEntry and + //- dictionaryListEntry types + mutable autoPtr 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 + +// ************************************************************************* //