From 204ce3660ecd6f796de7fe5e4362e45855542658 Mon Sep 17 00:00:00 2001 From: Mark Olesen <Mark.Olesen@esi-group.com> Date: Tue, 24 Oct 2017 11:59:11 +0200 Subject: [PATCH] ENH: new stream output: OListStream - an output stream to a DynamicList --- applications/test/OListStream/Make/files | 3 + applications/test/OListStream/Make/options | 2 + .../test/OListStream/Test-OListStream.C | 79 ++++ .../db/IOstreams/memory/OListStream.H | 416 ++++++++++++++++++ 4 files changed, 500 insertions(+) create mode 100644 applications/test/OListStream/Make/files create mode 100644 applications/test/OListStream/Make/options create mode 100644 applications/test/OListStream/Test-OListStream.C create mode 100644 src/OpenFOAM/db/IOstreams/memory/OListStream.H diff --git a/applications/test/OListStream/Make/files b/applications/test/OListStream/Make/files new file mode 100644 index 0000000000..583b8e7f06 --- /dev/null +++ b/applications/test/OListStream/Make/files @@ -0,0 +1,3 @@ +Test-OListStream.C + +EXE = $(FOAM_USER_APPBIN)/Test-OListStream diff --git a/applications/test/OListStream/Make/options b/applications/test/OListStream/Make/options new file mode 100644 index 0000000000..4e772fdf9d --- /dev/null +++ b/applications/test/OListStream/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude */ +/* EXE_LIBS = -lfiniteVolume */ diff --git a/applications/test/OListStream/Test-OListStream.C b/applications/test/OListStream/Test-OListStream.C new file mode 100644 index 0000000000..adbbc722d5 --- /dev/null +++ b/applications/test/OListStream/Test-OListStream.C @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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/>. + +Description + +\*---------------------------------------------------------------------------*/ + +#include "OListStream.H" +#include "wordList.H" +#include "IOstreams.H" +#include "argList.H" + +using namespace Foam; + +Ostream& toString(Ostream& os, const UList<char>& list) +{ + os << '"'; + for (const char c : list) + { + os << c; + } + os << '"'; + + return os; +} + + +void printInfo(const OListStream& buf) +{ + Info<< nl << buf.size() << " chars (" << buf.capacity() << " capacity) "; + toString(Info, buf.list()) << endl; +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + // Buffer storage + DynamicList<char> storage(8); + + OListStream obuf(std::move(storage)); + obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n"; + + printInfo(obuf); + + obuf.rewind(); + obuf << 100; + + printInfo(obuf); + + Info<< "\nEnd\n" << endl; + + return 0; +} + + +// ************************************************************************* // diff --git a/src/OpenFOAM/db/IOstreams/memory/OListStream.H b/src/OpenFOAM/db/IOstreams/memory/OListStream.H new file mode 100644 index 0000000000..b76b7f6f7f --- /dev/null +++ b/src/OpenFOAM/db/IOstreams/memory/OListStream.H @@ -0,0 +1,416 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / 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::OListStream + +Description + An output stream that writes to a DynamicList. + +\*---------------------------------------------------------------------------*/ + +#ifndef OListStream_H +#define OListStream_H + +#include <sstream> +#include "DynamicList.H" +#include "OSstream.H" + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +namespace Foam +{ + +// Forward declaration +class OListStreamAllocator; + +/*---------------------------------------------------------------------------*\ + Class OListStreamAllocator Declaration +\*---------------------------------------------------------------------------*/ + +//- An stream/stream-buffer allocator for external buffers +class OListStreamAllocator +{ + //- A streambuf adapter to output to a DynamicList + class olistbuf + : + public std::streambuf + { + friend OListStreamAllocator; + + //- Underlying list storage + DynamicList<char,512> storage_; + + + //- Adjust buffer pointers to agree with list sizes + inline void syncBufferPointers() + { + setp(storage_.data(), storage_.data() + storage_.capacity()); + pbump(storage_.size()); + } + + //- Adjust addressed list size to agree with buffer pointers + inline void syncListSize() + { + storage_.setSize(pptr() - pbase()); + } + + + protected: + + // Protected members + + //- Set position pointer to relative position + virtual std::streampos seekoff + ( + std::streamoff off, + std::ios_base::seekdir way, + std::ios_base::openmode which = std::ios_base::out + ) + { + const bool testout = which & std::ios_base::out; + + if (way == std::ios_base::beg) + { + if (testout) + { + setp(pbase(), epptr()); + pbump(off); + } + + return off; + } + + if (way == std::ios_base::cur) + { + if (testout) + { + pbump(off); + } + } + else if (way == std::ios_base::end) + { + if (testout) + { + pbump(off); + } + } + + if (testout) + { + return pptr() - pbase(); + } + + return -1; + } + + + //- Set position pointer to absolute position + virtual std::streampos seekpos + ( + std::streampos pos, + std::ios_base::openmode which = std::ios_base::out + ) + { + if (which & std::ios_base::out) + { + setp(pbase(), epptr()); + pbump(pos); + + return pptr() - pbase(); + } + + return -1; + } + + + //- Put sequence of characters + virtual std::streamsize xsputn(const char* s, std::streamsize n) + { + const std::streamsize newlen = n + storage_.size(); + + if (newlen > storage_.capacity()) + { + // Either use reserve(), or setCapacity() directly + // with finer control over growth + storage_.reserve(newlen); + syncBufferPointers(); + } + + std::streamsize count = 0; + while (count < n && pptr() < epptr()) + { + *(pptr()) = *(s + count++); + pbump(1); + } + + // Synchronize list size with output + syncListSize(); + + return count; + } + + + public: + + // Constructors + + //- Construct with an empty list + olistbuf() + : + storage_(1024) + { + syncBufferPointers(); + } + + + //- Construct with a specified number of reserved bytes + olistbuf(size_t nbytes) + : + storage_() + { + storage_.reserve(std::max(label(nbytes),1024)); + syncBufferPointers(); + } + + + //- Move construct from an existing List + olistbuf(List<char>&& buffer) + : + storage_(std::move(buffer)) + { + syncBufferPointers(); + } + + + //- Move construct from an existing DynamicList + template<int AnySize> + olistbuf(DynamicList<char,AnySize>&& buffer) + : + storage_(std::move(buffer)) + { + syncBufferPointers(); + } + }; + + + // Private data + + //- Reference to the underlying buffer + olistbuf buf_; + + +protected: + + // Protected data + + typedef std::ostream stream_type; + + //- The output stream + stream_type stream_; + + + // Constructors + + //- Construct with an empty list + OListStreamAllocator() + : + buf_(), + stream_(&buf_) + {} + + + //- Construct with a specified number of reserved bytes + OListStreamAllocator(size_t nbytes) + : + buf_(nbytes), + stream_(&buf_) + {} + + + //- Move construct from an existing List + OListStreamAllocator(List<char>&& buffer) + : + buf_(std::move(buffer)), + stream_(&buf_) + {} + + + //- Move construct from an existing DynamicList + template<int SizeMin> + OListStreamAllocator(DynamicList<char,SizeMin>&& buffer) + : + buf_(std::move(buffer)), + stream_(&buf_) + {} + + + //- Destructor + ~OListStreamAllocator() + {} + + +public: + + // Member Functions + + //- Content as a list of characters + UList<char> list() const + { + return UList<char> + ( + const_cast<char*>(buf_.storage_.cdata()), + buf_.storage_.size() + ); + } + + + //- Content as a list of characters + UList<char>& list() + { + return static_cast<UList<char>&>(buf_.storage_); + } + + //- Return the current list capacity + inline label capacity() const + { + return buf_.storage_.capacity(); + } + + + //- Reserve allocation space for at least this size. + inline void reserve(const label nElem) + { + buf_.storage_.reserve(nElem); + buf_.syncBufferPointers(); + } + + + //- Return the current output position in the buffer + // The same as the DynamicList::size() + std::streampos size() const + { + return const_cast<stream_type&>(stream_).tellp(); + } + + + //- Move to buffer start, clear errors + void rewind() + { + buf_.storage_.clear(); + buf_.syncBufferPointers(); + stream_.clear(); // for safety, clear any old errors + } +}; + + +/*---------------------------------------------------------------------------*\ + Class OListStream Declaration +\*----------------------------------------------d-----------------------------*/ + +//- An OSstream attached a DynamicList +class OListStream +: + public OListStreamAllocator, + public OSstream +{ + typedef OListStreamAllocator allocator_type; + +public: + + // Constructors + + //- Construct with an empty list + OListStream + ( + streamFormat format=ASCII, + versionNumber version=currentVersion + ) + : + allocator_type(), + OSstream(stream_, "output", format,version) + {} + + + //- Construct with a specified number of reserved bytes + OListStream + ( + size_t nbytes, + streamFormat format=ASCII, + versionNumber version=currentVersion + ) + : + allocator_type(nbytes), + OSstream(stream_, "output", format, version) + {} + + + //- Move construct from an existing List + OListStream + ( + List<char>&& buffer, + streamFormat format=ASCII, + versionNumber version=currentVersion + ) + : + allocator_type(std::move(buffer)), + OSstream(stream_, "output", format, version) + {} + + + //- Move construct from an existing DynamicList + template<int SizeMin> + OListStream + ( + DynamicList<char,SizeMin>&& buffer, + streamFormat format=ASCII, + versionNumber version=currentVersion + ) + : + allocator_type(std::move(buffer)), + OSstream(stream_, "output", format, version) + {} + + + //- Destructor + ~OListStream() + {} + + + // Member functions + + //- Rewind the stream, clearing any old errors + using allocator_type::rewind; + +}; + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +} // End namespace Foam + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // + +#endif + +// ************************************************************************* // -- GitLab