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 .
+
+Description
+
+\*---------------------------------------------------------------------------*/
+
+#include "OListStream.H"
+#include "wordList.H"
+#include "IOstreams.H"
+#include "argList.H"
+
+using namespace Foam;
+
+Ostream& toString(Ostream& os, const UList& 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 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 .
+
+Class
+ Foam::OListStream
+
+Description
+ An output stream that writes to a DynamicList.
+
+\*---------------------------------------------------------------------------*/
+
+#ifndef OListStream_H
+#define OListStream_H
+
+#include
+#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 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&& buffer)
+ :
+ storage_(std::move(buffer))
+ {
+ syncBufferPointers();
+ }
+
+
+ //- Move construct from an existing DynamicList
+ template
+ olistbuf(DynamicList&& 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&& buffer)
+ :
+ buf_(std::move(buffer)),
+ stream_(&buf_)
+ {}
+
+
+ //- Move construct from an existing DynamicList
+ template
+ OListStreamAllocator(DynamicList&& buffer)
+ :
+ buf_(std::move(buffer)),
+ stream_(&buf_)
+ {}
+
+
+ //- Destructor
+ ~OListStreamAllocator()
+ {}
+
+
+public:
+
+ // Member Functions
+
+ //- Content as a list of characters
+ UList list() const
+ {
+ return UList
+ (
+ const_cast(buf_.storage_.cdata()),
+ buf_.storage_.size()
+ );
+ }
+
+
+ //- Content as a list of characters
+ UList& list()
+ {
+ return static_cast&>(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_).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&& buffer,
+ streamFormat format=ASCII,
+ versionNumber version=currentVersion
+ )
+ :
+ allocator_type(std::move(buffer)),
+ OSstream(stream_, "output", format, version)
+ {}
+
+
+ //- Move construct from an existing DynamicList
+ template
+ OListStream
+ (
+ DynamicList&& 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
+
+// ************************************************************************* //