diff --git a/applications/test/OTstream/Make/files b/applications/test/OTstream/Make/files new file mode 100644 index 0000000000..6d19c308c6 --- /dev/null +++ b/applications/test/OTstream/Make/files @@ -0,0 +1,3 @@ +Test-OTstream.C + +EXE = $(FOAM_USER_APPBIN)/Test-OTstream diff --git a/applications/test/OTstream/Make/options b/applications/test/OTstream/Make/options new file mode 100644 index 0000000000..18e6fe47af --- /dev/null +++ b/applications/test/OTstream/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = */ +/* EXE_LIBS = */ diff --git a/applications/test/OTstream/Test-OTstream.C b/applications/test/OTstream/Test-OTstream.C new file mode 100644 index 0000000000..6d1e7c8258 --- /dev/null +++ b/applications/test/OTstream/Test-OTstream.C @@ -0,0 +1,142 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Description + +\*---------------------------------------------------------------------------*/ + +#include "ITstream.H" +#include "OTstream.H" +#include "primitiveFields.H" +#include "argList.H" + +using namespace Foam; + +void printTokens(const UList& toks) +{ + label count = 0; + for (const token& t : toks) + { + Info<< "token: " << t.info() << nl; + ++count; + } + + Info<< count << " tokens" << nl << endl; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + // Test fields + + { + scalarField fld1({1, 2, 3, 4}); + + OTstream os; + + fld1.writeEntry("field", os); + + Info<< "Field: " << fld1 << nl + << "Tokens: " << flatOutput(os) << nl; + + printTokens(os); + } + + { + scalarField fld1(10, scalar(5)); + + OTstream os; + + fld1.writeEntry("field", os); + + Info<< "Field: " << fld1 << nl + << "Tokens: " << flatOutput(os) << nl; + + printTokens(os); + } + + { + vector val(1,2, 3); + + OTstream os; + + os << val; + + Info<< "Value: " << val << nl + << "Tokens: " << flatOutput(os) << nl; + + printTokens(os); + } + + { + bool val(true); + + OTstream os; + + os << val; + + Info<< "Value: " << val << nl + << "Tokens: " << flatOutput(os) << nl; + + printTokens(os); + } + + { + tensorField fld1(1, tensor::I); + + OTstream os; + + fld1.writeEntry("field", os); + + Info<< "Field: " << fld1 << nl + << "Tokens: " << flatOutput(os) << nl; + + printTokens(os); + } + + { + labelList fld1(identity(5)); + + OTstream os; + + fld1.writeEntry("field", os); + + Info<< "Field: " << fld1 << nl + << "Tokens: " << flatOutput(os) << nl; + + printTokens(os); + } + + + Info<< "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/Make/files b/src/OpenFOAM/Make/files index 4b71bd073e..18140ef5e1 100644 --- a/src/OpenFOAM/Make/files +++ b/src/OpenFOAM/Make/files @@ -230,6 +230,7 @@ $(Fstreams)/masterOFstream.C Tstreams = $(Streams)/Tstreams $(Tstreams)/ITstream.C +$(Tstreams)/OTstream.C StringStreams = $(Streams)/StringStreams $(StringStreams)/StringStream.C diff --git a/src/OpenFOAM/containers/Lists/List/ListI.H b/src/OpenFOAM/containers/Lists/List/ListI.H index c32eef5394..63a17ef8c1 100644 --- a/src/OpenFOAM/containers/Lists/List/ListI.H +++ b/src/OpenFOAM/containers/Lists/List/ListI.H @@ -159,11 +159,17 @@ inline void Foam::List::setSize(const label len, const T& val) template inline T& Foam::List::newElmt(const label i) { - const label n = this->size(); + label n = this->size(); if (i >= n) { - resize(2*n); + do + { + n *= 2; + } + while (i >= n); + + resize(n); } return UList::operator[](i); diff --git a/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C b/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C index 2080c45d72..a5698b110d 100644 --- a/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C +++ b/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.C @@ -100,6 +100,39 @@ Foam::tokenList Foam::ITstream::parse } +// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // + +void Foam::ITstream::reserveCapacity +( + const label nElem, + const bool lazy +) +{ + if (lazy) + { + // Reserve - leave excess capacity for further appends + + label n = tokenList::size(); + + if (nElem >= n) + { + do + { + n *= 2; + } + while (nElem >= n); + + tokenList::resize(n); + } + } + else + { + // Strict capacity + tokenList::resize(nElem); + } +} + + // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * // Foam::ITstream::ITstream @@ -317,16 +350,81 @@ Foam::Istream& Foam::ITstream::read(char*, std::streamsize) void Foam::ITstream::rewind() { - tokenIndex_ = 0; - lineNumber_ = 0; + seek(0); +} - if (size()) + +void Foam::ITstream::seek(label pos) +{ + lineNumber_ = 0; + tokenList& toks = *this; + + if (!pos) { - lineNumber_ = tokenList::first().lineNumber(); + // Seek begin (rewind) + tokenIndex_ = 0; + + if (!toks.empty()) + { + lineNumber_ = toks.first().lineNumber(); + } + + setOpened(); + setGood(); + } + else if (pos < 0 || pos >= toks.size()) + { + // Seek end or seek is out of range + tokenIndex_ = toks.size(); + + if (!toks.empty()) + { + lineNumber_ = toks.last().lineNumber(); + } + + setEof(); + } + else + { + // Seek middle (from the beginning) + tokenIndex_ = pos; + + if (!toks.empty()) + { + lineNumber_ = toks[tokenIndex_].lineNumber(); + } + + setOpened(); + setGood(); + } +} + + +void Foam::ITstream::append(const tokenList& newTokens, const bool lazy) +{ + reserveCapacity(tokenIndex_ + newTokens.size(), lazy); + tokenList& toks = *this; + + for (const token& t : newTokens) + { + toks[tokenIndex_] = t; // copy append + ++tokenIndex_; + } +} + + +void Foam::ITstream::append(tokenList&& newTokens, const bool lazy) +{ + reserveCapacity(tokenIndex_ + newTokens.size(), lazy); + tokenList& toks = *this; + + for (token& t : newTokens) + { + toks[tokenIndex_] = std::move(t); // move append + ++tokenIndex_; } - setOpened(); - setGood(); + newTokens.clear(); } diff --git a/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.H b/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.H index cb06a8a4e4..e7989497aa 100644 --- a/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.H +++ b/src/OpenFOAM/db/IOstreams/Tstreams/ITstream.H @@ -73,6 +73,15 @@ class ITstream // \return the number of tokens in the resulting list. static label parseStream(ISstream& input, tokenList& tokens); + //- An ad hoc combination of reserve and setCapacity somewhat + //- similar to DynamicList. + // + // In lazy mode, increase list size if needed, but leave any + // excess capacity - works like reserve. + // + // In non-lazy mode, set exact capacity + void reserveCapacity(const label nElem, const bool lazy); + public: @@ -149,7 +158,7 @@ public: ); - //- Construct as copy + //- Copy construct ITstream(const ITstream& is) : Istream(ASCII, currentVersion), @@ -209,13 +218,13 @@ public: return name_; } - //- Return the current token index + //- The current token index when reading, or the insertion point. label tokenIndex() const { return tokenIndex_; } - //- Return non-const access to the current token index + //- Non-const access to the current token index label& tokenIndex() { return tokenIndex_; @@ -280,9 +289,30 @@ public: //- Rewind the stream so that it may be read again virtual void rewind(); + //- Move the tokenIndex to the specified position. + // Using seek(0) is identical to rewind. + // Using seek(-1) moves to the end. + void seek(label pos); + // Edit + //- Copy append a tokenList at the current tokenIndex, + //- incrementing the index. + // + // \param newTokens the list of tokens to copy append + // \param lazy leaves any excess capacity for further appends. + // The caller will be responsible for resizing later. + void append(const tokenList& newTokens, const bool lazy); + + //- Move append a tokenList at the current tokenIndex, + //- incrementing the index. + // + // \param newTokens the list of tokens to move append + // \param lazy leaves any excess capacity for further appends. + // The caller will be responsible for resizing later. + void append(tokenList&& newTokens, const bool lazy); + //- Set flags of stream ios_base::fmtflags flags(const ios_base::fmtflags) { diff --git a/src/OpenFOAM/db/IOstreams/Tstreams/OTstream.C b/src/OpenFOAM/db/IOstreams/Tstreams/OTstream.C new file mode 100644 index 0000000000..436b4d852d --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/Tstreams/OTstream.C @@ -0,0 +1,208 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +\*---------------------------------------------------------------------------*/ + +#include "error.H" +#include "OTstream.H" +#include + +// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * // + +bool Foam::OTstream::write(const token& tok) +{ + if (tok.good()) + { + append(tok); + return true; + } + + return false; +} + + +bool Foam::OTstream::write(token&& tok) +{ + if (tok.good()) + { + append(std::move(tok)); + return true; + } + + return false; +} + + +Foam::Ostream& Foam::OTstream::write(const char c) +{ + if (!std::isspace(c) && std::isprint(c)) + { + // Should generally work, but need to verify corner cases + append(token(token::punctuationToken(c))); + } + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const char* str) +{ + const word nonWhiteChars(string::validate(str)); + + if (nonWhiteChars.size() == 1) + { + // Like punctuation + write(nonWhiteChars[0]); + } + else if (nonWhiteChars.size()) + { + // As a word + write(nonWhiteChars); + } + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const word& str) +{ + append(token(str)); // tokenType::WORD + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const string& str) +{ + append(token(str)); // tokenType::STRING + + return *this; +} + + +Foam::Ostream& Foam::OTstream::writeQuoted +( + const std::string& str, + const bool quoted +) +{ + if (quoted) + { + append(token(string(str))); // tokenType::STRING + } + else if (!str.empty()) + { + append(token(word(str, false))); // tokenType::WORD + } + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const int32_t val) +{ + append(token(label(val))); // tokenType::LABEL + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const int64_t val) +{ + append(token(label(val))); // tokenType::LABEL + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const floatScalar val) +{ + append(token(val)); // tokenType::FLOAT + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const doubleScalar val) +{ + append(token(val)); // tokenType::DOUBLE + + return *this; +} + + +Foam::Ostream& Foam::OTstream::write(const char* data, std::streamsize count) +{ + if (format() != BINARY) + { + FatalErrorInFunction + << "stream format not binary" + << Foam::abort(FatalError); + } + + NotImplemented; + + return *this; +} + + +Foam::Ostream& Foam::OTstream::writeRaw +( + const char* data, + std::streamsize count +) +{ + // No check for format() == BINARY since this is either done in the + // beginRawWrite() method, or the caller knows what they are doing. + + NotImplemented; + + return *this; +} + + +bool Foam::OTstream::beginRawWrite(std::streamsize count) +{ + if (format() != BINARY) + { + FatalErrorInFunction + << "stream format not binary" + << Foam::abort(FatalError); + } + + NotImplemented; + + return true; +} + + +void Foam::OTstream::print(Ostream& os) const +{ + os << "OTstream : " << name().c_str() << ", " << size() << " tokens, "; + IOstream::print(os); +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Tstreams/OTstream.H b/src/OpenFOAM/db/IOstreams/Tstreams/OTstream.H new file mode 100644 index 0000000000..3d6e6e0369 --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/Tstreams/OTstream.H @@ -0,0 +1,283 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2019 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 . + +Class + Foam::OTstream + +Description + A simple output token stream + +SourceFiles + OTstream.C + +\*---------------------------------------------------------------------------*/ + +#ifndef OTstream_H +#define OTstream_H + +#include "token.H" +#include "Ostream.H" +#include "DynamicList.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Typedefs + +typedef DynamicList tokenDynList; + + +/*---------------------------------------------------------------------------*\ + Class OTstream Declaration +\*---------------------------------------------------------------------------*/ + +//- Output to string buffer, using a OSstream +class OTstream +: + public Ostream, + public DynamicList +{ +public: + + // Constructors + + //- Construct and set stream status + OTstream + ( + streamFormat format=ASCII, + versionNumber version=currentVersion + ) + : + Ostream(format, version), + DynamicList() + { + setOpened(); + setGood(); + } + + //- Copy construct + OTstream(const OTstream& os) + : + Ostream(os.format(), os.version()), + DynamicList(os.tokens()) + { + setOpened(); + setGood(); + } + + //- Move construct + OTstream(OTstream&& os) + : + Ostream(os.format(), os.version()), + DynamicList(std::move(os.tokens())) + { + setOpened(); + setGood(); + } + + + //- Destructor + ~OTstream() = default; + + + // Member Functions + + //- The tokens + const DynamicList& tokens() const + { + return *this; + } + + //- The tokens + DynamicList& tokens() + { + return *this; + } + + + // Write + + //- Write token to stream or otherwise handle it. + // \return false if the token type was not handled by this method + virtual bool write(const token& tok); + + //- Write token to stream or otherwise handle it. + // \return false if the token type was not handled by this method + virtual bool write(token&& tok); + + //- Write single character. Whitespace is suppressed. + virtual Ostream& write(const char c); + + //- Write the word-characters of a character string. + // Sends as a single char, or as word. + virtual Ostream& write(const char* str); + + //- Write word + virtual Ostream& write(const word& str); + + //- Write string + virtual Ostream& write(const string& str); + + //- Write std::string surrounded by quotes. + // Optional write without quotes. + virtual Ostream& writeQuoted + ( + const std::string& str, + const bool quoted=true + ); + + //- Write int32_t as a label + virtual Ostream& write(const int32_t val); + + //- Write int64_t as a label + virtual Ostream& write(const int64_t val); + + //- Write floatScalar + virtual Ostream& write(const floatScalar val); + + //- Write doubleScalar + virtual Ostream& write(const doubleScalar val); + + //- Write binary block with 8-byte alignment. + virtual Ostream& write(const char* data, std::streamsize count); + + //- Low-level raw binary output. + virtual Ostream& writeRaw(const char* data, std::streamsize count); + + //- Begin marker for low-level raw binary output. + // The count indicates the number of bytes for subsequent + // writeRaw calls. + virtual bool beginRawWrite(std::streamsize count); + + //- End marker for low-level raw binary output. + virtual bool endRawWrite() + { + return true; + } + + //- Add indentation characters + virtual void indent() + {} + + + // Stream state functions + + //- Flush stream + virtual void flush() + {} + + //- Add newline and flush stream + virtual void endl() + {} + + //- Get the current padding character + // \return previous padding character + virtual char fill() const + { + return 0; + } + + //- Set padding character for formatted field up to field width + virtual char fill(const char) + { + return 0; + } + + //- Get width of output field + virtual int width() const + { + return 0; + } + + //- Set width of output field + // \return previous width + virtual int width(const int) + { + return 0; + } + + //- Get precision of output field + virtual int precision() const + { + return 0; + } + + //- Set precision of output field + // \return old precision + virtual int precision(const int) + { + return 0; + } + + + + // Inquiry + + //- Return flags of output stream + virtual ios_base::fmtflags flags() const + { + return ios_base::fmtflags(0); + } + + + // Edit + + //- Set flags of stream + ios_base::fmtflags flags(const ios_base::fmtflags) + { + return ios_base::fmtflags(0); + } + + + // Other + + //- Reset the output buffer and rewind the stream + void reset() + { + this->rewind(); + } + + //- Rewind the output stream + virtual void rewind() + { + DynamicList::clear(); + } + + //- Print description of IOstream to Ostream + void print(Ostream& os) const; +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/Tstreams/Tstream.H b/src/OpenFOAM/db/IOstreams/Tstreams/Tstream.H new file mode 100644 index 0000000000..9c265a8dc6 --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/Tstreams/Tstream.H @@ -0,0 +1,15 @@ +/*---------------------------------------------------------------------------*\ +Description + Compatibility include + +\*---------------------------------------------------------------------------*/ + +#ifndef Tstream_H +#define Tstream_H + +#include "ITstream.H" +#include "OTstream.H" + +#endif + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C index d40a444b09..c7402d1322 100644 --- a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C +++ b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.C @@ -33,26 +33,6 @@ License // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // -void Foam::primitiveEntry::appendTokenList(const UList& toks) -{ - for (const token& tok : toks) - { - newElmt(tokenIndex()++) = tok; // copy append - } -} - - -void Foam::primitiveEntry::appendTokenList(List&& toks) -{ - for (token& tok : toks) - { - newElmt(tokenIndex()++) = std::move(tok); // move append - } - - toks.clear(); -} - - bool Foam::primitiveEntry::expandVariable ( const string& varName, @@ -103,7 +83,7 @@ bool Foam::primitiveEntry::expandVariable tokenList toks(ITstream::parse(str, IOstream::ASCII)); - appendTokenList(std::move(toks)); + ITstream::append(std::move(toks), true); // Lazy resizing } else if (eptr->isDict()) { @@ -111,12 +91,12 @@ bool Foam::primitiveEntry::expandVariable tokenList toks(eptr->dict().tokens()); - appendTokenList(std::move(toks)); + ITstream::append(std::move(toks), true); // Lazy resizing } else { - // Found primitive entry - appendTokenList(eptr->stream()); + // Found primitive entry - copy tokens + ITstream::append(eptr->stream(), true); // Lazy resizing } return true; diff --git a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.H b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.H index 84a18f862e..605c196a8d 100644 --- a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.H +++ b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntry.H @@ -76,15 +76,6 @@ class primitiveEntry Istream& is ); - //- Copy append the given tokens at the current tokenIndex - // No filtering on the tokens. - void appendTokenList(const UList& toks); - - //- Move append the given tokens at the current tokenIndex - // No filtering on the tokens. - void appendTokenList(List&& toks); - - //- Expand the given variable. // The keyword starts with '$', but has been removed by the caller // and thus passed as a varName. diff --git a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntryIO.C b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntryIO.C index 5d737a292f..da1555cbcd 100644 --- a/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntryIO.C +++ b/src/OpenFOAM/db/dictionary/primitiveEntry/primitiveEntryIO.C @@ -304,7 +304,7 @@ void Foam::primitiveEntry::write(Ostream& os) const } -// * * * * * * * * * * * * * Ostream operator * * * * * * * * * * * * * * * // +// * * * * * * * * * * * * * Ostream Operator * * * * * * * * * * * * * * * // template<> Foam::Ostream& Foam::operator<<