From c234027330fc6f4fc2317ac43e5b3e7278d2e462 Mon Sep 17 00:00:00 2001
From: Mark Olesen <Mark.Olesen@esi-group.com>
Date: Mon, 23 Oct 2017 12:06:59 +0200
Subject: [PATCH] ENH: include memory streams

- these provide a similar functionality to string-streams, but operate
  on a externally provided memory buffer which can be used to reduce
  the amount of copying.

- classes were previously staged as part of the ADIOS community
  repository.
---
 applications/test/UIBufStream/Make/files      |   3 +
 applications/test/UIBufStream/Make/options    |   2 +
 .../test/UIBufStream/Test-UIBufStream.C       |  88 ++++++
 .../db/IOstreams/memory/BufStreamAllocator.H  | 266 ++++++++++++++++++
 .../db/IOstreams/memory/OCountStream.H        | 230 +++++++++++++++
 .../db/IOstreams/memory/UIBufStream.H         | 168 +++++++++++
 .../db/IOstreams/memory/UOBufStream.H         | 190 +++++++++++++
 7 files changed, 947 insertions(+)
 create mode 100644 applications/test/UIBufStream/Make/files
 create mode 100644 applications/test/UIBufStream/Make/options
 create mode 100644 applications/test/UIBufStream/Test-UIBufStream.C
 create mode 100644 src/OpenFOAM/db/IOstreams/memory/BufStreamAllocator.H
 create mode 100644 src/OpenFOAM/db/IOstreams/memory/OCountStream.H
 create mode 100644 src/OpenFOAM/db/IOstreams/memory/UIBufStream.H
 create mode 100644 src/OpenFOAM/db/IOstreams/memory/UOBufStream.H

diff --git a/applications/test/UIBufStream/Make/files b/applications/test/UIBufStream/Make/files
new file mode 100644
index 0000000000..611f5337be
--- /dev/null
+++ b/applications/test/UIBufStream/Make/files
@@ -0,0 +1,3 @@
+Test-UIBufStream.C
+
+EXE = $(FOAM_USER_APPBIN)/Test-UIBufStream
diff --git a/applications/test/UIBufStream/Make/options b/applications/test/UIBufStream/Make/options
new file mode 100644
index 0000000000..4e772fdf9d
--- /dev/null
+++ b/applications/test/UIBufStream/Make/options
@@ -0,0 +1,2 @@
+/* EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude */
+/* EXE_LIBS = -lfiniteVolume */
diff --git a/applications/test/UIBufStream/Test-UIBufStream.C b/applications/test/UIBufStream/Test-UIBufStream.C
new file mode 100644
index 0000000000..f183d623ab
--- /dev/null
+++ b/applications/test/UIBufStream/Test-UIBufStream.C
@@ -0,0 +1,88 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  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 "UIBufStream.H"
+#include "UOBufStream.H"
+#include "wordList.H"
+#include "IOstreams.H"
+#include "argList.H"
+
+using namespace Foam;
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+// Main program:
+
+int main(int argc, char *argv[])
+{
+    // Buffer storage
+    DynamicList<char> storage(1000);
+
+    UOBufStream obuf(storage);
+    obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n";
+
+    Info<<"formatted: " << obuf.size() << " chars" << endl;
+
+    // Match size
+    storage.resize(obuf.size());
+
+    Info<<"as string: " << string(storage.cdata(), storage.size()) << endl;
+
+    // Attach input buffer - could also do without previous resize
+
+    UIBufStream ibuf(storage, storage.size());
+
+    token t;
+
+    while (ibuf.good())
+    {
+        ibuf >> t;
+        if (t.good())
+        {
+            Info<<"token: " << t << endl;
+        }
+    }
+
+    Info<< nl << "Repeat..." << endl;
+    ibuf.rewind();
+
+    while (ibuf.good())
+    {
+        ibuf >> t;
+        if (t.good())
+        {
+            Info<<"token: " << t << endl;
+        }
+    }
+
+
+    Info<< "\nEnd\n" << endl;
+
+    return 0;
+}
+
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/memory/BufStreamAllocator.H b/src/OpenFOAM/db/IOstreams/memory/BufStreamAllocator.H
new file mode 100644
index 0000000000..0696e1a943
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/memory/BufStreamAllocator.H
@@ -0,0 +1,266 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016-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::BufStreamAllocator
+
+Description
+    Helper for memory buffer streams such as UIBufStream, UOBufStream
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef BufStreamAllocator_H
+#define BufStreamAllocator_H
+
+#include <type_traits>
+#include <sstream>
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                          Class memorybuf Declaration
+\*---------------------------------------------------------------------------*/
+
+//- A streambuf class for using externally allocated memory for its buffer
+class memorybuf
+:
+    public std::streambuf
+{
+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::in|std::ios_base::out
+        )
+        {
+            const bool testin  = which & std::ios_base::in;
+            const bool testout = which & std::ios_base::out;
+
+            if (way == std::ios_base::beg)
+            {
+                if (testin)
+                {
+                    setg(eback(), eback(), egptr());
+                    gbump(off);
+                }
+                if (testout)
+                {
+                    setp(pbase(), epptr());
+                    pbump(off);
+                }
+
+                return off;
+            }
+
+            if (way == std::ios_base::cur)
+            {
+                if (testin)
+                {
+                    gbump(off);
+                }
+                if (testout)
+                {
+                    pbump(off);
+                }
+            }
+            else if (way == std::ios_base::end)
+            {
+                if (testin)
+                {
+                    gbump(off);
+                }
+                if (testout)
+                {
+                    pbump(off);
+                }
+            }
+
+            if (testin)
+            {
+                return gptr() - eback();
+            }
+            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::in|std::ios_base::out
+        )
+        {
+            return seekoff(pos, std::ios_base::beg, which);
+        }
+
+
+        //- Get sequence of characters
+        virtual std::streamsize xsgetn(char* s, std::streamsize n)
+        {
+            std::streamsize count = 0;
+
+            // some optimization could be possible here
+            while (count < n && gptr() < egptr())
+            {
+                *(s + count++) = *(gptr());
+                gbump(1);
+            }
+
+            return count;
+        }
+
+
+        //- Put sequence of characters
+        virtual std::streamsize xsputn(const char* s, std::streamsize n)
+        {
+            std::streamsize count = 0;
+
+            // some optimization could be possible here
+            while (count < n && pptr() < epptr())
+            {
+                *(pptr()) = *(s + count++);
+                pbump(1);
+            }
+
+            return count;
+        }
+
+
+public:
+
+    // Constructors
+
+        //- Construct for specified buffer
+        memorybuf(char* buffer, std::streamsize num)
+        {
+            setg(buffer, buffer, buffer + num);
+            setp(buffer, buffer + num);
+        }
+
+};
+
+
+/*---------------------------------------------------------------------------*\
+                     Class BufStreamAllocator Declaration
+\*---------------------------------------------------------------------------*/
+
+//- An stream/stream-buffer allocator for external buffers
+template<class StreamType, bool Manage=false>
+class BufStreamAllocator
+{
+    // Private data
+
+        //- Storage
+        char *storage_;
+
+        //- The number of bytes in the storage
+        std::streamsize len_;
+
+        //- Reference to the underlying buffer
+        memorybuf buf_;
+
+protected:
+
+    // Protected data
+
+        typedef StreamType stream_type;
+
+        //- The stream pointer
+        stream_type stream_;
+
+
+    // Constructors
+
+        //- Construct with buffer and number of bytes
+        BufStreamAllocator(char *buffer, size_t nbytes)
+        :
+            storage_(buffer),
+            len_(nbytes),
+            buf_(storage_, len_),
+            stream_(&buf_)
+        {}
+
+
+    //- Destructor
+    ~BufStreamAllocator()
+    {
+        // Possible cleanup of storage
+        if (Manage && storage_)
+        {
+            delete storage_;
+            storage_ = nullptr;
+        }
+    }
+
+
+    // Protected Member Functions
+
+
+        //- Position of the get buffer
+        std::streampos tellg() const
+        {
+            return const_cast<stream_type&>(stream_).tellg();
+        }
+
+        //- Position of the put buffer
+        std::streampos tellp() const
+        {
+            return const_cast<stream_type&>(stream_).tellp();
+        }
+
+
+public:
+
+    // Public Member Functions
+
+        //- Move to buffer start, clear errors
+        void rewind()
+        {
+            stream_.rdbuf()->pubseekpos(0);
+            stream_.clear(); // for safety, clear any old errors
+        }
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/memory/OCountStream.H b/src/OpenFOAM/db/IOstreams/memory/OCountStream.H
new file mode 100644
index 0000000000..b3ce64b169
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/memory/OCountStream.H
@@ -0,0 +1,230 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016-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::OSCountStream
+
+Description
+    An output stream for calculating byte counts.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef OScountStream_H
+#define OScountStream_H
+
+#include "OSstream.H"
+#include <iostream>
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                       Class countstreambuf Declaration
+\*---------------------------------------------------------------------------*/
+
+//- A streambuf class for determining byte counts
+class countstreambuf
+:
+    public std::streambuf
+{
+    // Private data
+
+        //- The number of bytes
+        std::streamsize n_;
+
+protected:
+    // Protected members
+
+        //- Put sequence of characters
+        virtual std::streamsize xsputn(const char* s, std::streamsize num)
+        {
+            n_ += num;
+            return num;
+        }
+
+
+        //- Set position pointer to absolute position
+        //  For the counter, any positioning is ignored and it always acts like
+        //  seekpos(0), which resets the count.
+        virtual std::streampos seekpos
+        (
+            std::streampos sp,
+            std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
+        )
+        {
+            n_ = 0;
+            return 0;
+        }
+
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        countstreambuf()
+        :
+            n_(0)
+        {}
+
+
+    // Access
+
+        //- Get number of bytes counted
+        std::streamsize size() const
+        {
+            return n_;
+        }
+};
+
+
+/*---------------------------------------------------------------------------*\
+                        Class ocountstream Declaration
+\*---------------------------------------------------------------------------*/
+
+//- Trivial output stream for calculating byte counts
+//  Since all output values are discarded, it can also be used as a /dev/null
+//  output buffer as well
+class ocountstream
+:
+    virtual public std::ios,
+    public std::ostream
+{
+    // Private data
+
+    countstreambuf buf_;
+
+public:
+
+    // Constructors
+
+        //- Construct null
+        ocountstream()
+        :
+            std::ostream(&buf_)
+        {}
+
+
+    // Member Functions
+
+      // Access
+
+        //- This hides both signatures of std::basic_ios::rdbuf()
+        countstreambuf* rdbuf()
+        {
+            return &buf_;
+        }
+
+
+        //- Get number of bytes counted
+        std::streamsize size() const
+        {
+            return buf_.size();
+        }
+
+
+        //- Rewind the stream, reset the count
+        void rewind()
+        {
+            buf_.pubseekpos(0);
+            clear();    // for safety, clear any old errors
+        }
+};
+
+
+/*---------------------------------------------------------------------------*\
+                        Class OCountStream Declaration
+\*---------------------------------------------------------------------------*/
+
+//- An output stream for calculating byte counts
+class OCountStream
+:
+    private ocountstream,
+    public OSstream
+{
+
+    // Private Member Functions
+
+        //- Disallow default bitwise copy construct
+        OCountStream(const OCountStream&) = delete;
+
+        //- Disallow default bitwise assignment
+        void operator=(const OCountStream&) = delete;
+
+public:
+
+    // Constructors
+
+        //- Construct and set stream status
+        OCountStream
+        (
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion
+        )
+        :
+            ocountstream(),
+            OSstream
+            (
+                static_cast<ocountstream&>(*this),
+                "output",
+                format,
+                version
+        )
+        {}
+
+
+    //- Destructor
+    ~OCountStream()
+    {}
+
+
+    // Member functions
+
+      // Access
+
+        //- Return the number of bytes counted
+        using ocountstream::size;
+
+
+      // Edit
+
+        //- Rewind the stream, reset the count, clearing any old errors
+        void rewind()
+        {
+            ocountstream::rewind();
+            setGood();  // resynchronize with internal state
+        }
+
+};
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/memory/UIBufStream.H b/src/OpenFOAM/db/IOstreams/memory/UIBufStream.H
new file mode 100644
index 0000000000..e02929f181
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/memory/UIBufStream.H
@@ -0,0 +1,168 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016-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::UIBufStream
+
+Description
+    Similar to IStringStream but using an externally managed buffer for its
+    input. This allows the input buffer to be filled (and refilled) from
+    various sources.
+
+    Note that this stream will normally be used as a "one-shot" reader.
+    Caution must be exercised that the referenced buffer remains valid and
+    without any intermediate resizing for the duration of the stream's use.
+
+    An example of possible use:
+    \code
+        DynamicList<char> buffer(4096);   // allocate some large buffer
+
+        nread = something.read(buffer.data(),1024); // fill with content
+        buffer.setSize(nread);            // content size
+
+        // construct dictionary, or something else
+        UIBufStream is(buffer)
+        dictionary dict1(is);
+
+        // sometime later
+        nread = something.read(buffer.data(),2048); // fill with content
+        buffer.setSize(nread);              // content size
+
+        // without intermediate variable
+        dictionary dict2(UIBufStream(buffer)());
+    \endcode
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef UIBufStream_H
+#define UIBufStream_H
+
+#include "BufStreamAllocator.H"
+#include "ISstream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+/*---------------------------------------------------------------------------*\
+                         Class UIBufStream Declaration
+\*---------------------------------------------------------------------------*/
+
+class UIBufStream
+:
+    public BufStreamAllocator<std::istream,false>,
+    public ISstream
+{
+    typedef BufStreamAllocator<std::istream,false> allocator_type;
+
+public:
+
+    // Constructors
+
+        //- Construct using specified buffer and number of bytes
+        UIBufStream
+        (
+            const char* buffer,
+            size_t nbytes,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion,
+            const Foam::string& name="input"
+        )
+        :
+            allocator_type(const_cast<char*>(buffer), nbytes),
+            ISstream(stream_, name, format, version)
+        {}
+
+
+        //- Construct using data area from a List and number of bytes
+        UIBufStream
+        (
+            const UList<char>& buffer,
+            label size,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion,
+            const Foam::string& name="input"
+        )
+        :
+            UIBufStream(buffer.cdata(), size, format,version,name)
+        {}
+
+
+        //- Construct using data area from a List and its inherent storage size
+        //  Uses addressed size, thus no special treatment for a DynamicList
+        UIBufStream
+        (
+            const UList<char>& buffer,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion,
+            const Foam::string& name="input"
+        )
+        :
+            UIBufStream(buffer.cdata(), buffer.size(), format,version,name)
+        {}
+
+
+    //- Destructor
+    ~UIBufStream()
+    {}
+
+
+    // Member functions
+
+        //- Return the current get position in the buffer
+        std::streampos pos() const
+        {
+            return allocator_type::tellg();
+        }
+
+
+        //- Rewind the stream, clearing any old errors
+        virtual void rewind()
+        {
+            allocator_type::rewind();
+            setGood();  // resynchronize with internal state
+        }
+
+
+    // Member operators
+
+        //- A non-const reference to const Istream
+        //  Needed for read-constructors where the stream argument is temporary
+        Istream& operator()() const
+        {
+            return const_cast<Istream&>(static_cast<const Istream&>(*this));
+        }
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
diff --git a/src/OpenFOAM/db/IOstreams/memory/UOBufStream.H b/src/OpenFOAM/db/IOstreams/memory/UOBufStream.H
new file mode 100644
index 0000000000..6a8df54e7a
--- /dev/null
+++ b/src/OpenFOAM/db/IOstreams/memory/UOBufStream.H
@@ -0,0 +1,190 @@
+/*---------------------------------------------------------------------------*\
+  =========                 |
+  \\      /  F ield         | OpenFOAM: The Open Source CFD Toolbox
+   \\    /   O peration     |
+    \\  /    A nd           | Copyright (C) 2016-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::UOBufStream
+
+Description
+    Similar to OStringStream but using an externally managed buffer for
+    its output.
+
+    This allows the output buffer to be reused and can make it easier when
+    writing out data.  It is the user's responsibility to ensure proper
+    synchronization in the sizes. Provided that the external buffer is large
+    enough that overflow does not occur, the following usage pattern
+    works.
+
+    \code
+        DynamicList<char> buffer(4096);     // allocate some large buffer
+
+        {
+            UOBufStream os(buffer);
+            os << "content1" << " and more content";
+            buffer.setSize(os.size());      // synchronize sizes
+        }
+
+        something.write(buffer, buffer.size());
+    \endcode
+
+    Although the UOBufStream is quite lightweight, there may be cases
+    where it is preferable to reuse the stream as well.
+    \code
+        DynamicList<char> buffer(4096);     // allocate some large buffer
+
+        UOBufStream os(buffer);
+        os << "content1" << " and more content";
+        buffer.setSize(os.size());          // synchronize sizes
+
+        something.write(buffer, buffer.size());
+
+        os.rewind();
+        os << "content2";
+        buffer.setSize(os.size());      // synchronize sizes
+
+        something.write(buffer, buffer.size());
+
+        // or simply using the output size directly (without sync)
+        os.rewind();
+        os << "content3";
+
+        something.write(buffer, os.size());
+    \endcode
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef UOBufStream_H
+#define UOBufStream_H
+
+#include "BufStreamAllocator.H"
+#include "OSstream.H"
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+namespace Foam
+{
+
+// Forward declaration
+template<class T, int SizeMin> class DynamicList;
+
+
+/*---------------------------------------------------------------------------*\
+                         Class UOBufStream Declaration
+\*---------------------------------------------------------------------------*/
+
+//- An OSstream attached to an unallocated external buffer
+class UOBufStream
+:
+    public BufStreamAllocator<std::ostream,false>,
+    public OSstream
+{
+    typedef BufStreamAllocator<std::ostream,false> allocator_type;
+
+public:
+
+    // Constructors
+
+        //- Construct using specified buffer and number of bytes
+        UOBufStream
+        (
+            char* buffer,
+            size_t nbytes,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion
+        )
+        :
+            allocator_type(buffer, nbytes),
+            OSstream(stream_, "output", format,version)
+        {}
+
+
+        //- Construct using data area from a List and number of bytes
+        UOBufStream
+        (
+            UList<char>& buffer,
+            size_t size,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion
+        )
+        :
+            UOBufStream(buffer.data(), size, format,version)
+        {}
+
+
+        //- Construct using data area from a List and its inherent storage size
+        UOBufStream
+        (
+            UList<char>& buffer,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion
+        )
+        :
+            UOBufStream(buffer.data(), buffer.size(), format,version)
+        {}
+
+
+        //- Construct using data area from a DynamicList and its capacity
+        template<int SizeMin>
+        UOBufStream
+        (
+            DynamicList<char,SizeMin>& buffer,
+            streamFormat format=ASCII,
+            versionNumber version=currentVersion
+        )
+        :
+            UOBufStream(buffer.data(), buffer.capacity(), format,version)
+        {}
+
+
+    //- Destructor
+    ~UOBufStream()
+    {}
+
+
+    // Member functions
+
+        //- Return the current output position in the buffer
+        std::streampos size() const
+        {
+            return allocator_type::tellp();
+        }
+
+
+        //- Rewind the stream, clearing any old errors
+        void rewind()
+        {
+            allocator_type::rewind();
+            setGood();  // resynchronize with internal state
+        }
+
+};
+
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+} // End namespace Foam
+
+// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
+
+#endif
+
+// ************************************************************************* //
-- 
GitLab