ENH: cleanup and rationalize memory-backed streams

- more consistent naming:
  * Versions that hold and manage their own memory:
      IListStream, OListStream

  * Versions that reference a fixed size external memory:
      UIListStream, UOListStream

- use List storage instead of DynamicList within OListStream.
  Avoids duplicate bookkeeping, more direct handling of resizing.
This commit is contained in:
Mark Olesen
2017-10-26 12:09:47 +02:00
parent 5c1ec7ecb8
commit 2bd2f83f6e
26 changed files with 1735 additions and 639 deletions

View File

@ -0,0 +1,3 @@
Test-IListStream.C
EXE = $(FOAM_USER_APPBIN)/Test-IListStream

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,151 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "ListStream.H"
#include "UListStream.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;
}
template<class BufType>
void printInfo(const BufType& buf)
{
Info<< nl << "=========================" << endl;
buf.print(Info);
toString(Info, buf.list());
Info<< nl << "=========================" << endl;
}
void printTokens(Istream& is)
{
label count = 0;
token t;
while (is.good())
{
is >> t;
if (t.good())
{
++count;
Info<<"token: " << t << endl;
}
}
Info<< count << " tokens" << endl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
// Buffer storage
DynamicList<char> storage(16);
OListStream obuf(std::move(storage));
obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n";
// Move contents to output buffer
printInfo(obuf);
Info<<nl << "as string: ";
toString(Info, obuf.list()) << endl;
Info<< "transfer contents to a List" << endl;
IListStream ibuf(obuf.xfer());
Info<< nl;
Info<< nl << "input string:";
printInfo(ibuf);
Info<< nl << "orig output:";
printInfo(obuf);
printTokens(ibuf);
Info<<nl << "after:";
printInfo(ibuf);
// This should also work
ibuf.list() = 'X';
Info<<nl << "overwritten with const value:";
printInfo(ibuf);
// Can also change content like this:
{
const int n = min(26, ibuf.size());
for (int i=0; i<n; ++i)
{
ibuf.list()[i] = 'A' + i;
}
}
Info<<nl << "directly written:";
printInfo(ibuf);
// But cannot easily swap in/out an entirely new list storage:
//
// List<char> newvalues(52);
// {
// for (int i=0; i<26; ++i)
// {
// newvalues[2*i+0] = char('a' + i);
// newvalues[2*i+1] = char('A' + i);
// }
// }
// ibuf.swap(newvalues);
//
// Info<<nl << "after swap:";
// printInfo(ibuf);
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -0,0 +1,3 @@
Test-OCountStream.C
EXE = $(FOAM_USER_APPBIN)/Test-OCountStream

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,61 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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 "OCountStream.H"
#include "StringStream.H"
#include "IOstreams.H"
#include "argList.H"
using namespace Foam;
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
OCountStream cnt;
OStringStream str;
for (label i = 0; i < 50; ++i)
{
str << 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
cnt << 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
}
cnt.print(Info);
Info<< "via string-stream: " << str.str().size() << " chars" << endl;
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -1,2 +1,2 @@
/* EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude */ /* EXE_INC = */
/* EXE_LIBS = -lfiniteVolume */ /* EXE_LIBS = */

View File

@ -25,7 +25,7 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "OListStream.H" #include "ListStream.H"
#include "wordList.H" #include "wordList.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "argList.H" #include "argList.H"
@ -45,10 +45,31 @@ Ostream& toString(Ostream& os, const UList<char>& list)
} }
void printInfo(const OListStream& buf) template<class BufType>
void printInfo(const BufType& buf)
{ {
Info<< nl << buf.size() << " chars (" << buf.capacity() << " capacity) "; Info<< nl << "=========================" << endl;
toString(Info, buf.list()) << endl; buf.print(Info);
toString(Info, buf.list());
Info<< nl << "=========================" << endl;
}
void printTokens(Istream& is)
{
label count = 0;
token t;
while (is.good())
{
is >> t;
if (t.good())
{
++count;
Info<<"token: " << t << endl;
}
}
Info<< count << " tokens" << endl;
} }
@ -58,18 +79,126 @@ void printInfo(const OListStream& buf)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
// Buffer storage // Buffer storage
DynamicList<char> storage(8); DynamicList<char> storage(16);
OListStream obuf(std::move(storage)); OListStream obuf(std::move(storage));
obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n";
obuf.setBlockSize(100);
printInfo(obuf);
// Fill with some content
for (label i = 0; i < 50; ++i)
{
obuf<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
}
printInfo(obuf); printInfo(obuf);
obuf.rewind(); obuf.rewind();
obuf << 100; printInfo(obuf);
for (label i=0; i < 10; ++i)
{
obuf << "item" << i << "\n";
}
printInfo(obuf); printInfo(obuf);
obuf.shrink();
Info<< "after shrink" << nl;
printInfo(obuf);
// Add some more
for (label i=10; i < 15; ++i)
{
obuf << "more" << i << nl;
}
Info<< "appended more" << nl;
printInfo(obuf);
// Overwrite at some position
obuf.stdStream().rdbuf()->pubseekpos(0.60 * obuf.size());
obuf << "<" << nl << "OVERWRITE" << nl;
Info<<"after overwrite" << nl;
printInfo(obuf);
Info<< "transfer contents to a List or IListStream" << nl;
IListStream ibuf(obuf.xfer());
Info<<"original:";
printInfo(obuf);
Info<<"new input:" << nl;
printInfo(ibuf);
printTokens(ibuf);
// Create from other storage types
Info<< nl;
{
Info<<"create std::move(List)" << endl;
List<char> list(16, 'A');
Info<<"input:";
toString(Info, list) << endl;
OListStream buf1(std::move(list));
for (label i = 0; i < 26; ++i)
{
buf1 << char('A' +i);
}
for (label i = 0; i < 26; ++i)
{
buf1 << char('a' +i);
}
Info<<"orig:";
toString(Info, list) << endl;
printInfo(buf1);
}
Info<< nl;
List<char> written;
{
Info<<"create List.xfer()" << endl;
List<char> list(16, 'B');
Info<<"input:";
toString(Info, list) << endl;
OListStream buf1(list.xfer());
for (label i = 0; i < 26; ++i)
{
buf1 << char('A' + i);
}
for (label i = 0; i < 26; ++i)
{
buf1 << char('a' +i);
}
Info<<"orig:";
toString(Info, list) << endl;
printInfo(buf1);
// Move back to written
written = buf1.xfer();
printInfo(buf1);
}
Info<<"'captured' content ";
toString(Info, written);
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;
return 0; return 0;

View File

@ -1,3 +0,0 @@
Test-UIBufStream.C
EXE = $(FOAM_USER_APPBIN)/Test-UIBufStream

View File

@ -1,2 +0,0 @@
/* EXE_INC = -I$(LIB_SRC)/finiteVolume/lnInclude */
/* EXE_LIBS = -lfiniteVolume */

View File

@ -0,0 +1,3 @@
Test-UIListStream.C
EXE = $(FOAM_USER_APPBIN)/Test-UIListStream

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -25,14 +25,54 @@ Description
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "UIBufStream.H" #include "UListStream.H"
#include "UOBufStream.H"
#include "wordList.H" #include "wordList.H"
#include "IOstreams.H" #include "IOstreams.H"
#include "argList.H" #include "argList.H"
using namespace Foam; using namespace Foam;
Ostream& toString(Ostream& os, const UList<char>& list)
{
os << '"';
for (const char c : list)
{
os << c;
}
os << '"';
return os;
}
template<class BufType>
void printInfo(const BufType& buf)
{
Info<< nl << "=========================" << endl;
buf.print(Info);
toString(Info, buf.list());
Info<< nl << "=========================" << endl;
}
void printTokens(Istream& is)
{
label count = 0;
token t;
while (is.good())
{
is >> t;
if (t.good())
{
++count;
Info<<"token: " << t << endl;
}
}
Info<< count << " tokens" << endl;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program: // Main program:
@ -41,10 +81,10 @@ int main(int argc, char *argv[])
// Buffer storage // Buffer storage
DynamicList<char> storage(1000); DynamicList<char> storage(1000);
UOBufStream obuf(storage); UOListStream obuf(storage);
obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n"; obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n";
Info<<"formatted: " << obuf.size() << " chars" << endl; obuf.print(Info);
// Match size // Match size
storage.resize(obuf.size()); storage.resize(obuf.size());
@ -53,31 +93,14 @@ int main(int argc, char *argv[])
// Attach input buffer - could also do without previous resize // Attach input buffer - could also do without previous resize
UIBufStream ibuf(storage, storage.size()); UIListStream ibuf(storage);
token t; printTokens(ibuf);
while (ibuf.good())
{
ibuf >> t;
if (t.good())
{
Info<<"token: " << t << endl;
}
}
Info<< nl << "Repeat..." << endl; Info<< nl << "Repeat..." << endl;
ibuf.rewind(); ibuf.rewind();
while (ibuf.good()) printTokens(ibuf);
{
ibuf >> t;
if (t.good())
{
Info<<"token: " << t << endl;
}
}
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;

View File

@ -175,6 +175,9 @@ $(hashes)/base64Layer.C
gzstream = $(Streams)/gzstream gzstream = $(Streams)/gzstream
$(gzstream)/gzstream.C $(gzstream)/gzstream.C
memstream = $(Streams)/memory
$(memstream)/ListStream.C
Fstreams = $(Streams)/Fstreams Fstreams = $(Streams)/Fstreams
$(Fstreams)/IFstream.C $(Fstreams)/IFstream.C
$(Fstreams)/OFstream.C $(Fstreams)/OFstream.C

View File

@ -79,11 +79,6 @@ protected:
{} {}
//- Destructor
~StringStreamAllocator()
{}
public: public:
// Public Member Functions // Public Member Functions
@ -112,6 +107,8 @@ class IStringStream
public StringStreamAllocator<std::istringstream>, public StringStreamAllocator<std::istringstream>,
public ISstream public ISstream
{ {
typedef StringStreamAllocator<std::istringstream> allocator_type;
public: public:
// Constructors // Constructors
@ -125,7 +122,7 @@ public:
const Foam::string& name="input" const Foam::string& name="input"
) )
: :
StringStreamAllocator<std::istringstream>(buffer), allocator_type(buffer),
ISstream(stream_, name, format, version) ISstream(stream_, name, format, version)
{} {}
@ -139,7 +136,7 @@ public:
const Foam::string& name="input" const Foam::string& name="input"
) )
: :
StringStreamAllocator<std::istringstream>(buffer), allocator_type(buffer),
ISstream(stream_, name, format, version) ISstream(stream_, name, format, version)
{} {}
@ -147,28 +144,23 @@ public:
//- Construct as copy of content //- Construct as copy of content
IStringStream(const IStringStream& str) IStringStream(const IStringStream& str)
: :
StringStreamAllocator<std::istringstream>(str.str()), allocator_type(str.str()),
ISstream(stream_, str.name(), str.format(), str.version()) ISstream(stream_, str.name(), str.format(), str.version())
{} {}
//- Destructor
~IStringStream()
{}
// Member Functions // Member Functions
//- Print description to Ostream
void print(Ostream& os) const;
//- Reset the input buffer and rewind the stream //- Reset the input buffer and rewind the stream
void reset(const std::string& s) virtual void reset(const std::string& s)
{ {
this->str(s); this->str(s);
this->rewind(); this->rewind();
} }
//- Print description to Ostream
virtual void print(Ostream& os) const;
// Member operators // Member operators
@ -192,6 +184,8 @@ class OStringStream
public StringStreamAllocator<std::ostringstream>, public StringStreamAllocator<std::ostringstream>,
public OSstream public OSstream
{ {
typedef StringStreamAllocator<std::ostringstream> allocator_type;
public: public:
// Constructors // Constructors
@ -203,7 +197,7 @@ public:
versionNumber version=currentVersion versionNumber version=currentVersion
) )
: :
StringStreamAllocator<std::ostringstream>(), allocator_type(),
OSstream(stream_, "output", format, version) OSstream(stream_, "output", format, version)
{} {}
@ -211,16 +205,11 @@ public:
//- Construct as copy of content //- Construct as copy of content
OStringStream(const OStringStream& str) OStringStream(const OStringStream& str)
: :
StringStreamAllocator<std::ostringstream>(str.str()), allocator_type(str.str()),
OSstream(stream_, str.name(), str.format(), str.version()) OSstream(stream_, str.name(), str.format(), str.version())
{} {}
//- Destructor
~OStringStream()
{}
// Member Functions // Member Functions
//- Reset the output buffer and rewind the stream //- Reset the output buffer and rewind the stream
@ -231,14 +220,14 @@ public:
} }
//- Rewind the output stream //- Rewind the output stream
void rewind() virtual void rewind()
{ {
// pubseekpos() instead of seekp() for symmetry with other classes // pubseekpos() instead of seekp() for symmetry with other classes
stream_.rdbuf()->pubseekpos(0, std::ios_base::out); stream_.rdbuf()->pubseekpos(0, std::ios_base::out);
} }
//- Print description to Ostream //- Print description to Ostream
void print(Ostream& os) const; virtual void print(Ostream& os) const;
}; };

View File

@ -112,8 +112,6 @@ public:
// Member Functions // Member Functions
// Access
//- This hides both signatures of std::basic_ios::rdbuf() //- This hides both signatures of std::basic_ios::rdbuf()
sha1buf* rdbuf() sha1buf* rdbuf()
{ {
@ -155,11 +153,6 @@ protected:
{} {}
//- Destructor
~OSHA1streamAllocator()
{}
public: public:
// Member Functions // Member Functions
@ -223,11 +216,6 @@ public:
{} {}
//- Destructor
~OSHA1stream()
{}
// Member functions // Member functions
//- Clear the SHA1 calculation //- Clear the SHA1 calculation

View File

@ -1,266 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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
// ************************************************************************* //

View File

@ -0,0 +1,245 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::IListStream
Description
An input stream that reads from a List and manages the List storage.
Similar to IStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying.
See Also
Foam::OListStream
Foam::UIListStream
Foam::UOListStream
\*---------------------------------------------------------------------------*/
#ifndef IListStream_H
#define IListStream_H
#include "List.H"
#include "UIListStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class IListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer input allocator for with List storage
class IListStreamAllocator
:
private List<char>,
public UIListStreamAllocator
{
protected:
// Constructors
//- Construct with an empty list
IListStreamAllocator()
:
List<char>(),
UIListStreamAllocator(list_storage())
{}
//- Move construct from an existing List
IListStreamAllocator(List<char>&& buffer)
:
List<char>(std::move(buffer)),
UIListStreamAllocator(list_storage())
{}
//- Move construct from an existing DynamicList
template<int SizeMin>
IListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
:
List<char>(std::move(buffer)),
UIListStreamAllocator(list_storage())
{}
//- Transfer (move) construct
IListStreamAllocator(const Xfer<List<char>>& buffer)
:
List<char>(buffer),
UIListStreamAllocator(list_storage())
{}
// Protected Member Functions
//- Convenience method to address the underlying List storage
inline List<char>& list_storage()
{
return static_cast<List<char>&>(*this);
}
public:
// Member Functions
//- The current get position in the buffer
using UIListStreamAllocator::size;
//- Clear storage
inline void clearStorage()
{
list_storage().clear();
sync_gbuffer_to_list();
}
//- Transfer contents to the Xfer container as a plain List
inline Xfer<List<char>> xfer()
{
Xfer<List<char>> moved = list_storage().xfer();
// Update buffer pointers for remaining (zero) size list
sync_gbuffer_to_list(); // or rewind
return moved;
}
};
/*---------------------------------------------------------------------------*\
Class IListStream Declaration
\*----------------------------------------------d-----------------------------*/
//- An ISstream with internal List storage
class IListStream
:
public IListStreamAllocator,
public ISstream
{
typedef IListStreamAllocator allocator_type;
public:
// Constructors
//- Construct with an empty list
IListStream
(
streamFormat format=ASCII,
versionNumber version=currentVersion,
const Foam::string& name="input"
)
:
allocator_type(),
ISstream(stream_, name, format, version)
{}
//- Move construct from an existing List
IListStream
(
List<char>&& buffer,
streamFormat format=ASCII,
versionNumber version=currentVersion,
const Foam::string& name="input"
)
:
allocator_type(std::move(buffer)),
ISstream(stream_, name, format, version)
{}
//- Move construct from an existing DynamicList
template<int SizeMin>
IListStream
(
DynamicList<char,SizeMin>&& buffer,
streamFormat format=ASCII,
versionNumber version=currentVersion,
const Foam::string& name="input"
)
:
allocator_type(std::move(buffer)),
ISstream(stream_, name, format, version)
{}
//- Transfer (move) construct
IListStream
(
const Xfer<List<char>>& buffer,
streamFormat format=ASCII,
versionNumber version=currentVersion,
const Foam::string& name="input"
)
:
allocator_type(buffer),
ISstream(stream_, name, format, version)
{}
// Member functions
//- The current get position in the buffer
using allocator_type::size;
//- 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
}
//- Print description to Ostream
virtual void print(Ostream& os) const;
// 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
// ************************************************************************* //

View File

@ -0,0 +1,72 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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/>.
\*---------------------------------------------------------------------------*/
#include "UListStream.H"
#include "ListStream.H"
#include "OCountStream.H"
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::IListStream::print(Ostream& os) const
{
os << "IListStream: ";
printBufInfo(os);
os << Foam::endl;
}
void Foam::UIListStream::print(Ostream& os) const
{
os << "UIListStream: ";
printBufInfo(os);
os << Foam::endl;
}
void Foam::OListStream::print(Ostream& os) const
{
os << "OListStream: ";
printBufInfo(os);
os << Foam::endl;
}
void Foam::UOListStream::print(Ostream& os) const
{
os << "UOListStream: ";
printBufInfo(os);
os << Foam::endl;
}
void Foam::OCountStream::print(Ostream& os) const
{
os << "OCountStream: ";
printBufInfo(os);
os << Foam::endl;
}
// ************************************************************************* //

View File

@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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
Input/output streams with managed List storage.
\*---------------------------------------------------------------------------*/
#ifndef ListStream_H
#define ListStream_H
#include "IListStream.H"
#include "OListStream.H"
#endif
// ************************************************************************* //

View File

@ -52,29 +52,30 @@ class countstreambuf
// Private data // Private data
//- The number of bytes //- The number of bytes
std::streamsize n_; std::streamsize size_;
protected: protected:
// Protected members
//- Put sequence of characters //- Simply handle output counting via overflow
virtual std::streamsize xsputn(const char* s, std::streamsize num) virtual int overflow(int c = EOF)
{ {
n_ += num; if (c != EOF)
return num; {
++size_;
}
return c;
} }
//- Set position pointer to absolute position //- Set position pointer to absolute position
// For the counter, any positioning is ignored and it always acts like // For the counter, any positioning is ignored and it always acts like
// seekpos(0), which resets the count. // seekpos(0), which resets the count.
virtual std::streampos seekpos virtual std::streampos seekpos
( (
std::streampos sp, std::streampos,
std::ios_base::openmode which = std::ios_base::in|std::ios_base::out std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
) )
{ {
n_ = 0; size_ = 0;
return 0; return 0;
} }
@ -83,19 +84,19 @@ public:
// Constructors // Constructors
//- Construct null //- Construct null, or with precount size
countstreambuf() countstreambuf(std::streamsize precount=0)
: :
n_(0) size_(precount)
{} {}
// Access // Access
//- Get number of bytes counted //- Number of bytes counted
std::streamsize size() const std::streamsize size() const
{ {
return n_; return size_;
} }
}; };
@ -154,6 +155,62 @@ public:
}; };
/*---------------------------------------------------------------------------*\
Class OCountStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer allocator for counting
class OCountStreamAllocator
{
protected:
// Protected data
typedef std::ostream stream_type;
//- The stream buffer
countstreambuf buf_;
//- The output stream
stream_type stream_;
// Constructors
//- Construct null, or with precount size
OCountStreamAllocator(std::streamsize precount=0)
:
buf_(precount),
stream_(&buf_)
{}
// Protected Member Functions
void printBufInfo(Ostream& os) const
{
os << "count=" << buf_.size();
}
public:
// Member Functions
//- The number of bytes counted
std::streamsize size() const
{
return buf_.size();
}
//- Rewind the stream, reset the count
void rewind()
{
buf_.pubseekpos(0);
stream_.clear(); // for safety, clear any old errors
}
};
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class OCountStream Declaration Class OCountStream Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -161,17 +218,10 @@ public:
//- An output stream for calculating byte counts //- An output stream for calculating byte counts
class OCountStream class OCountStream
: :
private ocountstream, public OCountStreamAllocator,
public OSstream public OSstream
{ {
typedef OCountStreamAllocator allocator_type;
// Private Member Functions
//- Disallow default bitwise copy construct
OCountStream(const OCountStream&) = delete;
//- Disallow default bitwise assignment
void operator=(const OCountStream&) = delete;
public: public:
@ -184,39 +234,30 @@ public:
versionNumber version=currentVersion versionNumber version=currentVersion
) )
: :
ocountstream(), allocator_type(),
OSstream OSstream(stream_, "output", format, version)
(
static_cast<ocountstream&>(*this),
"output",
format,
version
)
{} {}
//- Copy construct
//- Destructor OCountStream(const OCountStream& os)
~OCountStream() :
allocator_type(os.size()),
OSstream(stream_, os.name(), os.format(), os.version())
{} {}
// Member functions // Member functions
// Access
//- Return the number of bytes counted
using ocountstream::size;
// Edit
//- Rewind the stream, reset the count, clearing any old errors //- Rewind the stream, reset the count, clearing any old errors
void rewind() virtual void rewind()
{ {
ocountstream::rewind(); allocator_type::rewind();
setGood(); // resynchronize with internal state setGood(); // resynchronize with internal state
} }
//- Print description to Ostream
virtual void print(Ostream& os) const;
}; };
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -25,16 +25,27 @@ Class
Foam::OListStream Foam::OListStream
Description Description
An output stream that writes to a DynamicList. An output stream that writes to a List and manages the List storage.
Similar to OStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying.
The default list size is 512 with a 256 byte block increment.
These values can be changed on construction of via the
reserve() and setBlockSize() methods.
See Also
Foam::IListStream
Foam::UOListStream
Foam::UIListStream
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef OListStream_H #ifndef OListStream_H
#define OListStream_H #define OListStream_H
#include <sstream>
#include "DynamicList.H" #include "DynamicList.H"
#include "OSstream.H" #include "OSstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -48,114 +59,100 @@ class OListStreamAllocator;
Class OListStreamAllocator Declaration Class OListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An stream/stream-buffer allocator for external buffers //- An stream/stream-buffer output allocator for lists
class OListStreamAllocator class OListStreamAllocator
{ {
//- A streambuf adapter to output to a DynamicList //- A streambuf adapter to output to a List
class olistbuf class listbuf
: :
public std::streambuf public memorybuf::output
{ {
friend OListStreamAllocator; friend OListStreamAllocator;
//- Underlying list storage //- Helper for setting the block size.
DynamicList<char,512> storage_; // Small list minimum of 64 bytes.
static int min_size(int n)
//- Adjust buffer pointers to agree with list sizes
inline void syncBufferPointers()
{ {
setp(storage_.data(), storage_.data() + storage_.capacity()); return max(64, n);
pbump(storage_.size());
} }
//- Adjust addressed list size to agree with buffer pointers //- Block size when resizing the list
inline void syncListSize() int block_ = 256;
{
storage_.setSize(pptr() - pbase()); //- Underlying list storage.
} // Internally manage like a DynamicList, but the addressable size
// is known through the stream pointers.
List<char> storage_;
protected: protected:
// Protected members //- Increment capacity directly and
// adjust buffer pointers to agree with list dimensions
//- Set position pointer to relative position inline void minCapacity
virtual std::streampos seekoff
( (
std::streamoff off, const std::streamsize n,
std::ios_base::seekdir way, const std::streamsize cur = 0
std::ios_base::openmode which = std::ios_base::out
) )
{ {
const bool testout = which & std::ios_base::out; const auto newEnd = n + cur;
if (newEnd > storage_.size())
if (way == std::ios_base::beg)
{ {
if (testout) auto newCapacity =
{
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, (storage_.size() + block_)
std::ios_base::openmode which = std::ios_base::out - (storage_.size() % block_)
) );
{
if (which & std::ios_base::out)
{
setp(pbase(), epptr());
pbump(pos);
return pptr() - pbase(); while (newCapacity < newEnd)
{
newCapacity += block_;
} }
return -1; // Info<<"request:" << newEnd
// << " cur cap:" << storage_.size()
// << " new cap:" << newCapacity
// << " pos:" << cur
// << " incr:" << incr << endl;
storage_.setSize(newCapacity);
sync_pbuffer_to_list();
pbump(cur);
}
}
//- Define new increment
inline void setBlockSize(const int i)
{
const auto prev = block_;
block_ = min_size(i);
if (block_ > prev)
{
minCapacity(0, tellp());
}
}
//- Handle overflow
virtual int overflow(int c = EOF)
{
if (c != EOF)
{
// Need another output block
minCapacity(block_, tellp());
*(pptr()) = c;
pbump(1);
}
return c;
} }
//- Put sequence of characters //- Put sequence of characters
virtual std::streamsize xsputn(const char* s, std::streamsize n) virtual std::streamsize xsputn(const char* s, std::streamsize n)
{ {
const std::streamsize newlen = n + storage_.size(); // Enough space so that appends work without problem
minCapacity(n, tellp());
if (newlen > storage_.capacity())
{
// Either use reserve(), or setCapacity() directly
// with finer control over growth
storage_.reserve(newlen);
syncBufferPointers();
}
std::streamsize count = 0; std::streamsize count = 0;
while (count < n && pptr() < epptr()) while (count < n && pptr() < epptr())
@ -164,90 +161,108 @@ class OListStreamAllocator
pbump(1); pbump(1);
} }
// Synchronize list size with output
syncListSize();
return count; return count;
} }
//- Initialize put buffer
void init_pbuffer(const std::streamsize n)
{
set_pbuffer(storage_);
minCapacity(n);
}
public: public:
// Constructors // Constructors
//- Construct with an empty list //- Construct with an empty list, or specified number of reserved bytes
olistbuf() listbuf(size_t nbytes = 512)
:
storage_(1024)
{
syncBufferPointers();
}
//- Construct with a specified number of reserved bytes
olistbuf(size_t nbytes)
: :
storage_() storage_()
{ {
storage_.reserve(std::max(label(nbytes),1024)); init_pbuffer(min_size(nbytes));
syncBufferPointers();
} }
//- Move construct content from an existing List
//- Move construct from an existing List listbuf(List<char>&& buffer)
olistbuf(List<char>&& buffer)
: :
storage_(std::move(buffer)) storage_(std::move(buffer))
{ {
syncBufferPointers(); init_pbuffer(block_);
} }
//- Move construct content from an existing DynamicList
//- Move construct from an existing DynamicList
template<int AnySize> template<int AnySize>
olistbuf(DynamicList<char,AnySize>&& buffer) listbuf(DynamicList<char,AnySize>&& buffer)
: :
storage_(std::move(buffer)) storage_(std::move(buffer))
{ {
syncBufferPointers(); init_pbuffer(block_);
}
//- Transfer (move) construct
listbuf(const Xfer<List<char>>& buffer)
:
storage_(buffer)
{
init_pbuffer(block_);
}
// Member Functions
//- Return the current list output capacity
inline label capacity() const
{
return storage_.size();
}
//- Sync put buffer pointers to agree with list dimensions
inline void sync_pbuffer_to_list()
{
set_pbuffer(storage_);
}
//- Clear storage
inline void clearStorage()
{
storage_.clear();
sync_pbuffer_to_list();
}
//- Shrink to addressed storage
inline void shrink()
{
const auto cur = tellp();
storage_.setSize(cur);
sync_pbuffer_to_list();
pbump(cur);
} }
}; };
// Private data
//- Reference to the underlying buffer
olistbuf buf_;
protected: protected:
// Protected data // Protected data
typedef std::ostream stream_type; typedef std::ostream stream_type;
//- The output stream //- The stream buffer
listbuf buf_;
//- The stream
stream_type stream_; stream_type stream_;
// Constructors // Constructors
//- Construct with an empty list //- Construct with an empty list or specified number of reserved bytes
OListStreamAllocator() OListStreamAllocator(size_t nbytes = 512)
:
buf_(),
stream_(&buf_)
{}
//- Construct with a specified number of reserved bytes
OListStreamAllocator(size_t nbytes)
: :
buf_(nbytes), buf_(nbytes),
stream_(&buf_) stream_(&buf_)
{} {}
//- Move construct from an existing List //- Move construct from an existing List
OListStreamAllocator(List<char>&& buffer) OListStreamAllocator(List<char>&& buffer)
: :
@ -255,7 +270,6 @@ protected:
stream_(&buf_) stream_(&buf_)
{} {}
//- Move construct from an existing DynamicList //- Move construct from an existing DynamicList
template<int SizeMin> template<int SizeMin>
OListStreamAllocator(DynamicList<char,SizeMin>&& buffer) OListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
@ -264,71 +278,117 @@ protected:
stream_(&buf_) stream_(&buf_)
{} {}
//- Transfer (move) construct
//- Destructor OListStreamAllocator(const Xfer<List<char>>& buffer)
~OListStreamAllocator() :
buf_(buffer),
stream_(&buf_)
{} {}
// Protected Member Functions
void printBufInfo(Ostream& os) const
{
os << "pos=" << buf_.tellp()
<< " capacity=" << buf_.capacity()
<< " block=" << buf_.block_;
}
public: public:
// Member Functions // Member Functions
//- Content as a list of characters //- The current list output capacity
UList<char> list() const inline label capacity() const
{
return buf_.capacity();
}
//- Reserve output space for at least this amount.
inline void reserve(const std::streamsize n)
{
// Also maintain current position when resizing
const auto cur = buf_.tellp();
if (n > cur)
{
buf_.minCapacity(n - cur, cur);
}
}
//- Adjust block size for output
inline void setBlockSize(int n)
{
return buf_.setBlockSize(n);
}
//- The current output position in the buffer,
// which is also the addressed list size
inline label size() const
{
return buf_.tellp();
}
//- Const access to written contents as a list of characters
inline const UList<char> list() const
{ {
return UList<char> return UList<char>
( (
const_cast<char*>(buf_.storage_.cdata()), const_cast<char*>(buf_.storage_.cdata()),
buf_.storage_.size() buf_.tellp()
); );
} }
//- Content as a list of characters //- Non-const access to written contents as a list of characters
UList<char>& list() inline UList<char> list()
{ {
return static_cast<UList<char>&>(buf_.storage_); return UList<char>(buf_.storage_.data(), buf_.tellp());
}
//- Return the current list capacity
inline label capacity() const
{
return buf_.storage_.capacity();
} }
//- Reserve allocation space for at least this size. //- Transfer contents to the Xfer container as a plain List
inline void reserve(const label nElem) inline Xfer<List<char>> xfer()
{ {
buf_.storage_.reserve(nElem); buf_.shrink(); // Shrink to addressed area
buf_.syncBufferPointers(); auto lst = buf_.storage_.xfer();
} buf_.sync_pbuffer_to_list();
return lst;
//- 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 //- Move to buffer start, clear errors
void rewind() void rewind()
{ {
buf_.storage_.clear(); buf_.pubseekpos(0, std::ios_base::out);
buf_.syncBufferPointers();
stream_.clear(); // for safety, clear any old errors stream_.clear(); // for safety, clear any old errors
} }
//- Shrink to addressed space, should not affect stream.
inline void shrink()
{
buf_.shrink();
}
//- Clear storage
void clearStorage()
{
buf_.clearStorage();
stream_.clear(); // for safety, clear any old errors
}
}; };
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class OListStream Declaration Class OListStream Declaration
\*----------------------------------------------d-----------------------------*/ \*---------------------------------------------------------------------------*/
//- An OSstream attached a DynamicList //- An OSstream attached to a List
class OListStream class OListStream
: :
public OListStreamAllocator, public OListStreamAllocator,
@ -348,7 +408,7 @@ public:
) )
: :
allocator_type(), allocator_type(),
OSstream(stream_, "output", format,version) OSstream(stream_, "output", format, version)
{} {}
@ -391,16 +451,30 @@ public:
OSstream(stream_, "output", format, version) OSstream(stream_, "output", format, version)
{} {}
//- Transfer (move) construct
//- Destructor OListStream
~OListStream() (
const Xfer<List<char>>& buffer,
streamFormat format=ASCII,
versionNumber version=currentVersion
)
:
allocator_type(buffer),
OSstream(stream_, "output", format, version)
{} {}
// Member functions // Member functions
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
using allocator_type::rewind; virtual void rewind()
{
allocator_type::rewind();
setGood(); // resynchronize with internal state
}
//- Print description to Ostream
virtual void print(Ostream& os) const;
}; };

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class Class
Foam::UIBufStream Foam::UIListStream
Description Description
Similar to IStringStream but using an externally managed buffer for its Similar to IStringStream but using an externally managed buffer for its
@ -41,7 +41,7 @@ Description
buffer.setSize(nread); // content size buffer.setSize(nread); // content size
// construct dictionary, or something else // construct dictionary, or something else
UIBufStream is(buffer) UIListStream is(buffer)
dictionary dict1(is); dictionary dict1(is);
// sometime later // sometime later
@ -49,16 +49,23 @@ Description
buffer.setSize(nread); // content size buffer.setSize(nread); // content size
// without intermediate variable // without intermediate variable
dictionary dict2(UIBufStream(buffer)()); dictionary dict2(UIListStream(buffer)());
\endcode \endcode
See Also
Foam::IListStream
Foam::OListStream
Foam::UOListStream
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef UIBufStream_H #ifndef UIListStream_H
#define UIBufStream_H #define UIListStream_H
#include "BufStreamAllocator.H" #include "FixedList.H"
#include "UList.H"
#include "ISstream.H" #include "ISstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -66,22 +73,149 @@ namespace Foam
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class UIBufStream Declaration Class UIListAllocator Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
class UIBufStream //- An stream/stream-buffer input allocator for a externally allocated lists
class UIListStreamAllocator
{
//- A streambuf class for input from UList or equivalent
class ulistbuf
:
public memorybuf::input
{
friend UIListStreamAllocator;
//- Underlying list storage
UList<char> list_;
public:
//- Construct for specified buffer
ulistbuf(UList<char>& buffer)
:
list_(buffer)
{
set_gbuffer(list_);
}
//- Construct for specified buffer
ulistbuf(char* buffer, std::streamsize num)
:
list_(buffer, num)
{
set_gbuffer(list_);
}
//- Sync get buffer pointers to agree with list dimensions
inline void sync_gbuffer_to_list()
{
set_gbuffer(list_);
}
};
protected:
// Protected data
typedef std::istream stream_type;
//- The stream buffer
ulistbuf buf_;
//- The stream
stream_type stream_;
// Constructors
//- Construct with list buffer
UIListStreamAllocator(UList<char>& list)
:
buf_(list),
stream_(&buf_)
{}
//- Construct with buffer and number of bytes
UIListStreamAllocator(char *buffer, size_t nbytes)
:
buf_(buffer, nbytes),
stream_(&buf_)
{}
// Protected Member Functions
//- Sync get buffer pointers to agree with list dimensions
inline void sync_gbuffer_to_list()
{
buf_.sync_gbuffer_to_list();
}
void printBufInfo(Ostream& os) const
{
os << "pos=" << buf_.tellg()
<< " size=" << buf_.list_.size();
}
public:
// Public Member Functions
//- Const access to available contents as a list of characters
inline const UList<char>& list() const
{
return buf_.list_;
}
//- Non-const access to available contents as a list of characters
inline UList<char> list()
{
return buf_.list_;
}
//- The list size
inline label size() const
{
return buf_.list_.size();
}
//- Position of the get buffer
std::streampos tellg() const
{
return buf_.tellg();
}
//- Move to buffer start, clear errors
void rewind()
{
buf_.pubseekpos(0, std::ios_base::in);
stream_.clear(); // for safety, clear any old errors
}
};
/*---------------------------------------------------------------------------*\
Class UIListStream Declaration
\*---------------------------------------------------------------------------*/
class UIListStream
: :
public BufStreamAllocator<std::istream,false>, public UIListStreamAllocator,
public ISstream public ISstream
{ {
typedef BufStreamAllocator<std::istream,false> allocator_type; typedef UIListStreamAllocator allocator_type;
public: public:
// Constructors // Constructors
//- Construct using specified buffer and number of bytes //- Construct using specified buffer and number of bytes
UIBufStream UIListStream
( (
const char* buffer, const char* buffer,
size_t nbytes, size_t nbytes,
@ -95,8 +229,21 @@ public:
{} {}
//- Construct using data area from a FixedList
template<unsigned FixedSize>
UIListStream
(
const FixedList<char,FixedSize>& buffer,
streamFormat format=ASCII,
versionNumber version=currentVersion,
const Foam::string& name="input"
)
:
UIListStream(buffer.cdata(), FixedSize, format, version, name)
{}
//- Construct using data area from a List and number of bytes //- Construct using data area from a List and number of bytes
UIBufStream UIListStream
( (
const UList<char>& buffer, const UList<char>& buffer,
label size, label size,
@ -105,13 +252,13 @@ public:
const Foam::string& name="input" const Foam::string& name="input"
) )
: :
UIBufStream(buffer.cdata(), size, format,version,name) UIListStream(buffer.cdata(), size, format, version, name)
{} {}
//- Construct using data area from a List and its inherent storage size //- Construct using data area from a List and its inherent storage size
// Uses addressed size, thus no special treatment for a DynamicList // Uses addressed size, thus no special treatment for a DynamicList
UIBufStream UIListStream
( (
const UList<char>& buffer, const UList<char>& buffer,
streamFormat format=ASCII, streamFormat format=ASCII,
@ -119,12 +266,7 @@ public:
const Foam::string& name="input" const Foam::string& name="input"
) )
: :
UIBufStream(buffer.cdata(), buffer.size(), format,version,name) UIListStream(buffer.cdata(), buffer.size(), format, version, name)
{}
//- Destructor
~UIBufStream()
{} {}
@ -145,6 +287,10 @@ public:
} }
//- Print description to Ostream
virtual void print(Ostream& os) const;
// Member operators // Member operators
//- A non-const reference to const Istream //- A non-const reference to const Istream

View File

@ -0,0 +1,37 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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
Input/output streams with externally managed storage.
\*---------------------------------------------------------------------------*/
#ifndef UListStream_H
#define UListStream_H
#include "UIListStream.H"
#include "UOListStream.H"
#endif
// ************************************************************************* //

View File

@ -22,7 +22,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Class Class
Foam::UOBufStream Foam::UOListStream
Description Description
Similar to OStringStream but using an externally managed buffer for Similar to OStringStream but using an externally managed buffer for
@ -38,7 +38,7 @@ Description
DynamicList<char> buffer(4096); // allocate some large buffer DynamicList<char> buffer(4096); // allocate some large buffer
{ {
UOBufStream os(buffer); UOListStream os(buffer);
os << "content1" << " and more content"; os << "content1" << " and more content";
buffer.setSize(os.size()); // synchronize sizes buffer.setSize(os.size()); // synchronize sizes
} }
@ -46,12 +46,12 @@ Description
something.write(buffer, buffer.size()); something.write(buffer, buffer.size());
\endcode \endcode
Although the UOBufStream is quite lightweight, there may be cases Although the UOListStream is quite lightweight, there may be cases
where it is preferable to reuse the stream as well. where it is preferable to reuse the stream as well.
\code \code
DynamicList<char> buffer(4096); // allocate some large buffer DynamicList<char> buffer(4096); // allocate some large buffer
UOBufStream os(buffer); UOListStream os(buffer);
os << "content1" << " and more content"; os << "content1" << " and more content";
buffer.setSize(os.size()); // synchronize sizes buffer.setSize(os.size()); // synchronize sizes
@ -70,41 +70,171 @@ Description
something.write(buffer, os.size()); something.write(buffer, os.size());
\endcode \endcode
See Also
Foam::IListStream
Foam::OListStream
Foam::UIListStream
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#ifndef UOBufStream_H #ifndef UOListStream_H
#define UOBufStream_H #define UOListStream_H
#include "BufStreamAllocator.H" #include "DynamicList.H"
#include "FixedList.H"
#include "OSstream.H" #include "OSstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam namespace Foam
{ {
// Forward declaration /*---------------------------------------------------------------------------*\
template<class T, int SizeMin> class DynamicList; Class UOListAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer allocator for external buffers
class UOListAllocator
{
//- A streambuf adapter for output to UList or equivalent
class ulistbuf
:
public memorybuf::output
{
friend UOListAllocator;
//- Underlying list storage
UList<char> list_;
public:
// Constructors
//- Construct for specified buffer
ulistbuf(char* buffer, std::streamsize num)
:
list_(buffer, num)
{
set_pbuffer(list_);
}
// Member Functions
//- Return the current list output capacity
inline label capacity() const
{
return list_.size();
}
//- Sync put buffer pointers to agree with list dimensions
inline void sync_pbuffer_to_list()
{
set_pbuffer(list_);
}
};
protected:
// Protected data
typedef std::ostream stream_type;
//- The stream buffer
ulistbuf buf_;
//- The stream
stream_type stream_;
// Constructors
//- Construct with buffer and number of bytes
UOListAllocator(char *buffer, size_t nbytes)
:
buf_(buffer, nbytes),
stream_(&buf_)
{}
// Protected Member Functions
void printBufInfo(Ostream& os) const
{
os << "pos=" << buf_.tellp()
<< " capacity=" << buf_.capacity();
}
public:
// Public Member Functions
//- The current list output capacity
inline label capacity() const
{
return buf_.capacity();
}
//- The current output position in the buffer,
// which is also the addressed list size
inline label size() const
{
return buf_.tellp();
}
//- Const access to written contents as a list of characters
inline const UList<char> list() const
{
return UList<char>
(
const_cast<char*>(buf_.list_.cdata()),
buf_.tellp()
);
}
//- Non-const access to written contents as a list of characters
inline UList<char> list()
{
return UList<char>
(
const_cast<char*>(buf_.list_.cdata()),
buf_.tellp()
);
}
//- Move to buffer start, clear errors
void rewind()
{
buf_.pubseekpos(0, std::ios_base::out);
stream_.clear(); // for safety, clear any old errors
}
};
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class UOBufStream Declaration Class UOListStream Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An OSstream attached to an unallocated external buffer //- An OSstream attached to an unallocated external buffer
class UOBufStream class UOListStream
: :
public BufStreamAllocator<std::ostream,false>, public UOListAllocator,
public OSstream public OSstream
{ {
typedef BufStreamAllocator<std::ostream,false> allocator_type; typedef UOListAllocator allocator_type;
public: public:
// Constructors // Constructors
//- Construct using specified buffer and number of bytes //- Construct using specified buffer and number of bytes
UOBufStream UOListStream
( (
char* buffer, char* buffer,
size_t nbytes, size_t nbytes,
@ -113,12 +243,12 @@ public:
) )
: :
allocator_type(buffer, nbytes), allocator_type(buffer, nbytes),
OSstream(stream_, "output", format,version) OSstream(stream_, "output", format, version)
{} {}
//- Construct using data area from a List and number of bytes //- Construct using data area from a List and number of bytes
UOBufStream UOListStream
( (
UList<char>& buffer, UList<char>& buffer,
size_t size, size_t size,
@ -126,56 +256,58 @@ public:
versionNumber version=currentVersion versionNumber version=currentVersion
) )
: :
UOBufStream(buffer.data(), size, format,version) UOListStream(buffer.data(), size, format, version)
{} {}
//- Construct using data area from a FixedList
template<unsigned FixedSize>
UOListStream
(
FixedList<char,FixedSize>& buffer,
streamFormat format=ASCII,
versionNumber version=currentVersion
)
:
UOListStream(buffer.data(), FixedSize, format, version)
{}
//- Construct using data area from a List and its inherent storage size //- Construct using data area from a List and its inherent storage size
UOBufStream UOListStream
( (
UList<char>& buffer, UList<char>& buffer,
streamFormat format=ASCII, streamFormat format=ASCII,
versionNumber version=currentVersion versionNumber version=currentVersion
) )
: :
UOBufStream(buffer.data(), buffer.size(), format,version) UOListStream(buffer.data(), buffer.size(), format, version)
{} {}
//- Construct using data area from a DynamicList and its capacity //- Construct using data area from a DynamicList and its capacity
template<int SizeMin> template<int SizeMin>
UOBufStream UOListStream
( (
DynamicList<char,SizeMin>& buffer, DynamicList<char,SizeMin>& buffer,
streamFormat format=ASCII, streamFormat format=ASCII,
versionNumber version=currentVersion versionNumber version=currentVersion
) )
: :
UOBufStream(buffer.data(), buffer.capacity(), format,version) UOListStream(buffer.data(), buffer.capacity(), format, version)
{}
//- Destructor
~UOBufStream()
{} {}
// Member functions // 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 //- Rewind the stream, clearing any old errors
void rewind() virtual void rewind()
{ {
allocator_type::rewind(); allocator_type::rewind();
setGood(); // resynchronize with internal state setGood(); // resynchronize with internal state
} }
//- Print description to Ostream
virtual void print(Ostream& os) const;
}; };

View File

@ -0,0 +1,224 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / 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::memorybuf
Description
A std::streambuf used for memory buffer streams such as
UIListStream, UOListStream, etc.
\*---------------------------------------------------------------------------*/
#ifndef memoryStreamBuffer_H
#define memoryStreamBuffer_H
#include "UList.H"
#include <type_traits>
#include <sstream>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class memorybuf Declaration
\*---------------------------------------------------------------------------*/
//- A streambuf for memory
class memorybuf
:
public std::streambuf
{
protected:
//- 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);
}
}
else if (way == std::ios_base::cur)
{
if (testin)
{
gbump(off);
}
if (testout)
{
pbump(off);
}
}
else if (way == std::ios_base::end)
{
if (testin)
{
setg(eback(), eback(), egptr());
gbump(egptr() - eback() - off);
}
if (testout)
{
setp(pbase(), epptr());
pbump(epptr() - pbase() - off);
}
}
if (testin)
{
return (gptr() - eback()); // tellg()
}
if (testout)
{
return (pptr() - pbase()); // tellp()
}
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);
}
public:
// Forward declarations
class input;
class output;
};
/*---------------------------------------------------------------------------*\
Class memorybuf::input Declaration
\*---------------------------------------------------------------------------*/
//- An output streambuf for memory access
class memorybuf::input
:
public memorybuf
{
protected:
//- Get sequence of characters
virtual std::streamsize xsgetn(char* s, std::streamsize n)
{
std::streamsize count = 0;
while (count < n && gptr() < egptr())
{
*(s + count++) = *(gptr());
gbump(1);
}
return count;
}
//- The buffer get position
inline std::streamsize tellg() const
{
return (gptr() - eback());
}
//- Sync get buffer pointers to agree with list dimensions
inline void set_gbuffer(UList<char>& list)
{
setg(list.begin(), list.begin(), list.end());
}
};
/*---------------------------------------------------------------------------*\
Class memorybuf::output Declaration
\*---------------------------------------------------------------------------*/
//- An output streambuf for memory access
class memorybuf::output
:
public memorybuf
{
protected:
//- Put sequence of characters
virtual std::streamsize xsputn(const char* s, std::streamsize n)
{
std::streamsize count = 0;
while (count < n && pptr() < epptr())
{
*(pptr()) = *(s + count++);
pbump(1);
}
return count;
}
//- The buffer put position
inline std::streamsize tellp() const
{
return (pptr() - pbase());
}
//- Sync put buffer pointers to agree with list dimensions
inline void set_pbuffer(UList<char>& list)
{
setp(list.begin(), list.end());
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //