ENH: coding cleanup for memory streams

- simplify structure.
- protect against nullptr when resetting memory streams
- make UIListStream swappable
- add uiliststream as an example of using a plain std::istream
This commit is contained in:
Mark Olesen
2018-01-22 09:42:06 +01:00
parent 0a5e4cf1b0
commit 23c9dd716d
9 changed files with 450 additions and 348 deletions

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -56,6 +56,15 @@ void printInfo(const BufType& buf)
} }
template<>
void printInfo(const List<char>& buf)
{
Info<< nl << "=========================" << endl;
toString(Info, buf);
Info<< nl << "=========================" << endl;
}
void printTokens(Istream& is) void printTokens(Istream& is)
{ {
label count = 0; label count = 0;
@ -126,21 +135,22 @@ int main(int argc, char *argv[])
Info<<nl << "directly written:"; Info<<nl << "directly written:";
printInfo(ibuf); printInfo(ibuf);
// But cannot easily swap in/out an entirely new list storage: // Swap in/out an entirely new list storage:
// List<char> newvalues(52);
// List<char> newvalues(52); {
// { for (int i=0; i<26; ++i)
// for (int i=0; i<26; ++i) {
// { newvalues[2*i+0] = char('a' + i);
// newvalues[2*i+0] = char('a' + i); newvalues[2*i+1] = char('A' + i);
// newvalues[2*i+1] = char('A' + i); }
// } }
// } ibuf.swap(newvalues);
// ibuf.swap(newvalues);
//
// Info<<nl << "after swap:";
// printInfo(ibuf);
Info<<nl << "after swap:";
printInfo(ibuf);
Info<<nl << "swapped out:";
printInfo(newvalues);
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -40,17 +40,26 @@ int main(int argc, char *argv[])
OCountStream cnt; OCountStream cnt;
OStringStream str; OStringStream str;
ocountstream plain;
for (label i = 0; i < 50; ++i) for (label i = 0; i < 50; ++i)
{ {
str << 1002 << " " << "abcd" << " " str
<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n"; << "def" << " " << 3.14159 << ";\n";
cnt << 1002 << " " << "abcd" << " " cnt
<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
plain
<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n"; << "def" << " " << 3.14159 << ";\n";
} }
cnt.print(Info); cnt.print(Info);
Info<< "via string-stream: " << str.str().size() << " chars" << endl; Info<< "via string-stream: " << str.str().size() << " chars" << endl;
Info<< "via ocountstream: " << plain.size() << " chars" << endl;
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -30,6 +30,9 @@ Description
#include "IOstreams.H" #include "IOstreams.H"
#include "argList.H" #include "argList.H"
#include <sstream>
#include <vector>
using namespace Foam; using namespace Foam;
Ostream& toString(Ostream& os, const UList<char>& list) Ostream& toString(Ostream& os, const UList<char>& list)
@ -45,6 +48,19 @@ Ostream& toString(Ostream& os, const UList<char>& list)
} }
Ostream& toString(Ostream& os, const std::vector<char>& list)
{
os << '"';
for (const char c : list)
{
os << c;
}
os << '"';
return os;
}
template<class BufType> template<class BufType>
void printInfo(const BufType& buf) void printInfo(const BufType& buf)
{ {
@ -55,6 +71,15 @@ void printInfo(const BufType& buf)
} }
template<>
void printInfo(const UList<char>& buf)
{
Info<< nl << "=========================" << endl;
toString(Info, buf);
Info<< nl << "=========================" << endl;
}
void printTokens(Istream& is) void printTokens(Istream& is)
{ {
label count = 0; label count = 0;
@ -82,7 +107,7 @@ int main(int argc, char *argv[])
DynamicList<char> storage(1000); DynamicList<char> storage(1000);
UOListStream obuf(storage); UOListStream obuf(storage);
obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n"; obuf << 1002 << "\n" << "abcd" << "\n" << "def" << "\n" << 3.14159 << ";\n";
obuf.print(Info); obuf.print(Info);
@ -92,7 +117,7 @@ int main(int argc, char *argv[])
Info<<"as string: " << string(storage.cdata(), storage.size()) << endl; Info<<"as string: " << string(storage.cdata(), storage.size()) << endl;
// Attach input buffer - could also do without previous resize // Attach input buffer - could also do without previous resize
{
UIListStream ibuf(storage); UIListStream ibuf(storage);
printTokens(ibuf); printTokens(ibuf);
@ -101,6 +126,64 @@ int main(int argc, char *argv[])
ibuf.rewind(); ibuf.rewind();
printTokens(ibuf); printTokens(ibuf);
}
// Attach input buffer - could also do without previous resize
{
Info<< "parse as std::istream\n";
uiliststream is(storage.cdata(), storage.size());
string tok;
while (std::getline(is, tok))
{
std::cerr << "tok: " << tok << nl;
}
Info<< nl << "Repeat..." << endl;
is.rewind();
while (std::getline(is, tok))
{
std::cerr << "tok: " << tok << nl;
}
}
// Simple test using stl items only
{
std::vector<char> chars;
chars.reserve(1024);
for (int i=0; i < 10; ++i)
{
chars.push_back('A' + i);
chars.push_back('0' + i);
chars.push_back('\n');
}
Info<< "parse std::vector of char: ";
toString(Info, chars);
Info<< "----" << nl;
uiliststream is(chars.data(), chars.size());
string tok;
std::cerr<< nl << "Parsed..." << nl;
while (std::getline(is, tok))
{
std::cerr << "tok: " << tok << nl;
}
Info<< nl << "Repeat..." << endl;
is.rewind();
while (std::getline(is, tok))
{
std::cerr << "tok: " << tok << nl;
}
}
Info<< "\nEnd\n" << endl; Info<< "\nEnd\n" << endl;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -51,7 +51,7 @@ namespace Foam
Class IListStreamAllocator Declaration Class IListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An stream/stream-buffer input allocator for with List storage //- An stream/stream-buffer input allocator with List storage
class IListStreamAllocator class IListStreamAllocator
: :
private List<char>, private List<char>,
@ -61,43 +61,46 @@ protected:
// Constructors // Constructors
//- Construct with an empty list //- Construct empty
IListStreamAllocator() IListStreamAllocator()
: :
List<char>(), List<char>(),
UIListStreamAllocator(list_storage()) UIListStreamAllocator(List<char>::data(), List<char>::size())
{} {}
//- Move construct from an existing List //- Move construct from List
IListStreamAllocator(List<char>&& buffer) IListStreamAllocator(List<char>&& buffer)
: :
List<char>(std::move(buffer)), List<char>(std::move(buffer)),
UIListStreamAllocator(list_storage()) UIListStreamAllocator(List<char>::data(), List<char>::size())
{} {}
//- Move construct from DynamicList
//- Move construct from an existing DynamicList
template<int SizeMin> template<int SizeMin>
IListStreamAllocator(DynamicList<char,SizeMin>&& buffer) IListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
: :
List<char>(std::move(buffer)), List<char>(std::move(buffer)),
UIListStreamAllocator(list_storage()) UIListStreamAllocator(List<char>::data(), List<char>::size())
{} {}
//- Transfer (move) construct //- Transfer (move) construct
IListStreamAllocator(const Xfer<List<char>>& buffer) IListStreamAllocator(const Xfer<List<char>>& buffer)
: :
List<char>(buffer), List<char>(buffer),
UIListStreamAllocator(list_storage()) UIListStreamAllocator(List<char>::data(), List<char>::size())
{} {}
// Protected Member Functions // Protected Member Functions
//- Convenience method to address the underlying List storage //- Convenience method to address the underlying List storage
inline List<char>& list_storage() inline void reset_gbuffer()
{ {
return static_cast<List<char>&>(*this); UIListStreamAllocator::reset
(
List<char>::data(),
List<char>::size()
);
} }
public: public:
@ -107,21 +110,24 @@ public:
//- The current get position in the buffer //- The current get position in the buffer
using UIListStreamAllocator::size; using UIListStreamAllocator::size;
inline void swap(List<char>& list)
{
List<char>::swap(list);
reset_gbuffer();
}
//- Clear storage //- Clear storage
inline void clearStorage() inline void clearStorage()
{ {
list_storage().clear(); List<char>::clear();
sync_gbuffer_to_list(); reset_gbuffer();
} }
//- Transfer contents to the Xfer container as a plain List //- Transfer contents to the Xfer container as a plain List
inline Xfer<List<char>> xfer() inline Xfer<List<char>> xfer()
{ {
Xfer<List<char>> moved = list_storage().xfer(); Xfer<List<char>> moved = List<char>::xfer();
reset_gbuffer();
// Update buffer pointers for remaining (zero) size list
sync_gbuffer_to_list(); // or rewind
return moved; return moved;
} }
}; };
@ -156,7 +162,7 @@ public:
{} {}
//- Move construct from an existing List //- Move construct from List
IListStream IListStream
( (
List<char>&& buffer, List<char>&& buffer,
@ -170,7 +176,7 @@ public:
{} {}
//- Move construct from an existing DynamicList //- Move construct from DynamicList
template<int SizeMin> template<int SizeMin>
IListStream IListStream
( (

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -49,14 +49,12 @@ class countstreambuf
: :
public std::streambuf public std::streambuf
{ {
// Private data //- The number of bytes counted
//- The number of bytes
std::streamsize size_; std::streamsize size_;
protected: protected:
//- Simply handle output counting via overflow //- Handle output counting via overflow
virtual int overflow(int c = EOF) virtual int overflow(int c = EOF)
{ {
if (c != EOF) if (c != EOF)
@ -79,25 +77,25 @@ protected:
return 0; return 0;
} }
public: public:
// Constructors
//- Construct null, or with precount size //- Construct null, or with precount size
countstreambuf(std::streamsize precount=0) countstreambuf(std::streamsize precount=0)
: :
size_(precount) size_(precount)
{} {}
//- \return The number of bytes counted
// Access
//- Number of bytes counted
std::streamsize size() const std::streamsize size() const
{ {
return size_; return size_;
} }
//- Some information about the number of bytes counted
inline void printBufInfo(Ostream& os) const
{
os << "count=" << size_;
}
}; };
@ -105,51 +103,28 @@ public:
Class ocountstream Declaration Class ocountstream Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- Trivial output stream for calculating byte counts //- Trivial output stream for calculating byte counts.
// Since all output values are discarded, it can also be used as a /dev/null // Since all output values are discarded, it can be used as a /dev/null
// output buffer as well // output buffer as well.
class ocountstream class ocountstream
: :
virtual public std::ios, virtual public std::ios,
protected countstreambuf,
public std::ostream public std::ostream
{ {
// Private data
countstreambuf buf_;
public: public:
// Constructors
//- Construct null //- Construct null
ocountstream() ocountstream()
: :
std::ostream(&buf_) countstreambuf(),
std::ostream(static_cast<countstreambuf*>(this))
{} {}
// 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 //- Rewind the stream, reset the count
void rewind() void rewind()
{ {
buf_.pubseekpos(0); this->pubseekpos(0, std::ios_base::out);
clear(); // for safety, clear any old errors clear(); // for safety, clear any old errors
} }
}; };
@ -189,7 +164,7 @@ protected:
void printBufInfo(Ostream& os) const void printBufInfo(Ostream& os) const
{ {
os << "count=" << buf_.size(); buf_.printBufInfo(os);
} }
public: public:

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -29,9 +29,9 @@ Description
Similar to OStringStream but with a List for its storage instead of Similar to OStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying. as string to allow reuse of List contents without copying.
The default list size is 512 with a 256 byte block increment. The default list size is 512-bytes with a 256-byte block increment.
These values can be changed on construction of via the These values can be changed after construction using the reserve() and
reserve() and setBlockSize() methods. the setBlockSize() methods.
See Also See Also
Foam::IListStream Foam::IListStream
@ -45,6 +45,7 @@ See Also
#include "DynamicList.H" #include "DynamicList.H"
#include "OSstream.H" #include "OSstream.H"
#include "stdFoam.H"
#include "memoryStreamBuffer.H" #include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -52,43 +53,39 @@ See Also
namespace Foam namespace Foam
{ {
// Forward declaration
class OListStreamAllocator;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class OListStreamAllocator Declaration Class OListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An stream/stream-buffer output allocator for lists //- An stream/stream-buffer output allocator with DynamicList-like storage
class OListStreamAllocator class OListStreamAllocator
{ {
//- A streambuf adapter to output to a List //- A streambuf adapter with resizing similar to DynamicList
class listbuf class dynbuf
: :
public memorybuf::out public memorybuf::out
{ {
friend OListStreamAllocator; friend class OListStreamAllocator;
//- Helper for setting the block size. //- Helper for block size - small list minimum of 64 bytes.
// Small list minimum of 64 bytes. constexpr static int min_size(int n)
static int min_size(int n)
{ {
return max(64, n); return stdFoam::max(64, n);
} }
//- Block size when resizing the list //- Block size when resizing the list
int block_ = 256; int block_ = 256;
//- Underlying list storage. //- Underlying list storage.
// Internally manage like a DynamicList, but the addressable size // Internally manage like a DynamicList, with its capacity known
// is known through the stream pointers. // from the list size and the addressable size known through the
// stream pointers.
List<char> storage_; List<char> storage_;
protected: protected:
//- Increment capacity directly and //- Increment capacity directly and adjust buffer pointers to
// adjust buffer pointers to agree with list dimensions //- correspond with the storage size.
inline void minCapacity inline void minCapacity
( (
const std::streamsize n, const std::streamsize n,
@ -115,8 +112,8 @@ class OListStreamAllocator
// << " pos:" << cur // << " pos:" << cur
// << " incr:" << incr << endl; // << " incr:" << incr << endl;
storage_.setSize(newCapacity); storage_.resize(newCapacity);
sync_pbuffer_to_list(); sync_pbuffer();
pbump(cur); pbump(cur);
} }
} }
@ -167,7 +164,7 @@ class OListStreamAllocator
//- Initialize put buffer //- Initialize put buffer
void init_pbuffer(const std::streamsize n) void init_pbuffer(const std::streamsize n)
{ {
set_pbuffer(storage_); sync_pbuffer();
minCapacity(n); minCapacity(n);
} }
@ -177,24 +174,24 @@ class OListStreamAllocator
// Constructors // Constructors
//- Construct with an empty list, or specified number of reserved bytes //- Construct with an empty list, or specified number of reserved bytes
listbuf(size_t nbytes = 512) dynbuf(size_t nbytes = 512)
: :
storage_() storage_()
{ {
init_pbuffer(min_size(nbytes)); init_pbuffer(min_size(nbytes));
} }
//- Move construct content from an existing List //- Move construct from List
listbuf(List<char>&& buffer) dynbuf(List<char>&& buffer)
: :
storage_(std::move(buffer)) storage_(std::move(buffer))
{ {
init_pbuffer(block_); init_pbuffer(block_);
} }
//- Move construct content from an existing DynamicList //- Move construct from DynamicList
template<int AnySize> template<int AnySize>
listbuf(DynamicList<char,AnySize>&& buffer) dynbuf(DynamicList<char,AnySize>&& buffer)
: :
storage_(std::move(buffer)) storage_(std::move(buffer))
{ {
@ -202,7 +199,7 @@ class OListStreamAllocator
} }
//- Transfer (move) construct //- Transfer (move) construct
listbuf(const Xfer<List<char>>& buffer) dynbuf(const Xfer<List<char>>& buffer)
: :
storage_(buffer) storage_(buffer)
{ {
@ -219,26 +216,36 @@ class OListStreamAllocator
} }
//- Sync put buffer pointers to agree with list dimensions //- Sync put buffer pointers to agree with list dimensions
inline void sync_pbuffer_to_list() inline void sync_pbuffer()
{ {
set_pbuffer(storage_); resetp(storage_.data(), storage_.size());
} }
//- Clear storage //- Clear storage
inline void clearStorage() inline void clearStorage()
{ {
storage_.clear(); storage_.clear();
sync_pbuffer_to_list(); sync_pbuffer();
} }
//- Shrink to addressed storage //- Shrink to addressed storage
inline void shrink() inline void shrink()
{ {
const auto cur = tellp(); const auto cur = tellp();
storage_.setSize(cur); storage_.resize(cur);
sync_pbuffer_to_list(); sync_pbuffer();
pbump(cur); pbump(cur);
} }
//- Transfer contents to the Xfer container as a plain List
inline Xfer<List<char>> xfer()
{
const auto cur = tellp(); // Addressed area
storage_.resize(cur);
auto lst = storage_.xfer();
sync_pbuffer();
return lst;
}
}; };
protected: protected:
@ -248,7 +255,7 @@ protected:
typedef std::ostream stream_type; typedef std::ostream stream_type;
//- The stream buffer //- The stream buffer
listbuf buf_; dynbuf buf_;
//- The stream //- The stream
stream_type stream_; stream_type stream_;
@ -263,14 +270,14 @@ protected:
stream_(&buf_) stream_(&buf_)
{} {}
//- Move construct from an existing List //- Move construct from List
OListStreamAllocator(List<char>&& buffer) OListStreamAllocator(List<char>&& buffer)
: :
buf_(std::move(buffer)), buf_(std::move(buffer)),
stream_(&buf_) stream_(&buf_)
{} {}
//- Move construct from an existing DynamicList //- Move construct from DynamicList
template<int SizeMin> template<int SizeMin>
OListStreamAllocator(DynamicList<char,SizeMin>&& buffer) OListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
: :
@ -290,8 +297,8 @@ protected:
void printBufInfo(Ostream& os) const void printBufInfo(Ostream& os) const
{ {
os << "pos=" << buf_.tellp() os << "put=" << buf_.tellp()
<< " capacity=" << buf_.capacity() << "/" << buf_.capacity()
<< " block=" << buf_.block_; << " block=" << buf_.block_;
} }
@ -299,12 +306,30 @@ public:
// Member Functions // Member Functions
//- Const UList access to the characters written (shallow copy).
inline const UList<char> list() const
{
return buf_.list();
}
//- Non-const UList access to the characters written (shallow copy).
inline UList<char> list()
{
return buf_.list();
}
//- The current list output capacity //- The current list output capacity
inline label capacity() const inline label capacity() const
{ {
return buf_.capacity(); return buf_.capacity();
} }
//- The current output position in the buffer,
//- which is also the addressed list size
inline label size() const
{
return buf_.tellp();
}
//- Reserve output space for at least this amount. //- Reserve output space for at least this amount.
inline void reserve(const std::streamsize n) inline void reserve(const std::streamsize n)
@ -317,55 +342,16 @@ public:
} }
} }
//- Adjust block size for output //- Adjust block size for output
inline void setBlockSize(int n) inline void setBlockSize(int n)
{ {
return buf_.setBlockSize(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>
(
const_cast<char*>(buf_.storage_.cdata()),
buf_.tellp()
);
}
//- Non-const access to written contents as a list of characters
inline UList<char> list()
{
return UList<char>(buf_.storage_.data(), buf_.tellp());
}
//- Transfer contents to the Xfer container as a plain List //- Transfer contents to the Xfer container as a plain List
inline Xfer<List<char>> xfer() inline Xfer<List<char>> xfer()
{ {
buf_.shrink(); // Shrink to addressed area return buf_.xfer();
auto lst = buf_.storage_.xfer();
buf_.sync_pbuffer_to_list();
return lst;
}
//- Move to buffer start, clear errors
void rewind()
{
buf_.pubseekpos(0, std::ios_base::out);
stream_.clear(); // for safety, clear any old errors
} }
//- Shrink to addressed space, should not affect stream. //- Shrink to addressed space, should not affect stream.
@ -381,6 +367,12 @@ public:
stream_.clear(); // for safety, clear any old errors stream_.clear(); // for safety, clear any old errors
} }
//- Move to buffer start, clear errors
void rewind()
{
buf_.pubseekpos(0, std::ios_base::out);
stream_.clear(); // for safety, clear any old errors
}
}; };
@ -464,7 +456,7 @@ public:
{} {}
// Member functions // Member Functions
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
virtual void rewind() virtual void rewind()

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -38,7 +38,7 @@ Description
DynamicList<char> buffer(4096); // allocate some large buffer DynamicList<char> buffer(4096); // allocate some large buffer
nread = something.read(buffer.data(),1024); // fill with content nread = something.read(buffer.data(),1024); // fill with content
buffer.setSize(nread); // content size buffer.resize(nread); // content size
// construct dictionary, or something else // construct dictionary, or something else
UIListStream is(buffer) UIListStream is(buffer)
@ -46,7 +46,7 @@ Description
// sometime later // sometime later
nread = something.read(buffer.data(),2048); // fill with content nread = something.read(buffer.data(),2048); // fill with content
buffer.setSize(nread); // content size buffer.resize(nread); // content size
// without intermediate variable // without intermediate variable
dictionary dict2(UIListStream(buffer)()); dictionary dict2(UIListStream(buffer)());
@ -73,47 +73,49 @@ namespace Foam
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class UIListAllocator Declaration Class uiliststream Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An stream/stream-buffer input allocator for a externally allocated lists //- Similar to std::istringstream, but with an externally managed input buffer.
class UIListStreamAllocator // This allows the input buffer to be filled or refilled from various sources
{ // without copying.
//- A streambuf class for input from UList or equivalent class uiliststream
class ulistbuf
: :
public memorybuf::in virtual public std::ios,
protected memorybuf::in,
public std::istream
{ {
friend UIListStreamAllocator;
//- Underlying list storage
UList<char> list_;
public: public:
//- Construct for specified buffer //- Construct for character array and number of bytes
ulistbuf(UList<char>& buffer) uiliststream(const char* buffer, size_t nbytes)
: :
list_(buffer) memorybuf::in(const_cast<char*>(buffer), nbytes),
std::istream(static_cast<memorybuf::in*>(this))
{}
//- Reset buffer pointers
inline void reset(char *buffer, size_t nbytes)
{ {
set_gbuffer(list_); resetg(buffer, nbytes);
} }
//- Construct for specified buffer //- Rewind the stream, clearing any old errors
ulistbuf(char* buffer, std::streamsize num) void rewind()
:
list_(buffer, num)
{ {
set_gbuffer(list_); this->pubseekpos(0, std::ios_base::in);
} clear(); // for safety, clear any old errors
//- Sync get buffer pointers to agree with list dimensions
inline void sync_gbuffer_to_list()
{
set_gbuffer(list_);
} }
}; };
/*---------------------------------------------------------------------------*\
Class UIListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer input allocator for a externally allocated list
class UIListStreamAllocator
{
protected: protected:
// Protected data // Protected data
@ -121,7 +123,7 @@ protected:
typedef std::istream stream_type; typedef std::istream stream_type;
//- The stream buffer //- The stream buffer
ulistbuf buf_; memorybuf::in buf_;
//- The stream //- The stream
stream_type stream_; stream_type stream_;
@ -129,14 +131,7 @@ protected:
// Constructors // Constructors
//- Construct with list buffer //- Construct for character array and number of bytes
UIListStreamAllocator(UList<char>& list)
:
buf_(list),
stream_(&buf_)
{}
//- Construct with buffer and number of bytes
UIListStreamAllocator(char *buffer, size_t nbytes) UIListStreamAllocator(char *buffer, size_t nbytes)
: :
buf_(buffer, nbytes), buf_(buffer, nbytes),
@ -146,50 +141,45 @@ protected:
// Protected Member Functions // Protected Member Functions
//- Sync get buffer pointers to agree with list dimensions //- Reset buffer pointers
inline void sync_gbuffer_to_list() inline void reset(char *buffer, size_t nbytes)
{ {
buf_.sync_gbuffer_to_list(); buf_.resetg(buffer, nbytes);
} }
void printBufInfo(Ostream& os) const void printBufInfo(Ostream& os) const
{ {
os << "pos=" << buf_.tellg() buf_.printBufInfo(os);
<< " size=" << buf_.list_.size();
} }
public: public:
// Public Member Functions // Public Member Functions
//- Const access to available contents as a list of characters //- Const UList access to the input characters (shallow copy).
inline const UList<char>& list() const inline const UList<char> list() const
{ {
return buf_.list_; return buf_.list();
} }
//- Non-const UList access to the input characters (shallow copy).
//- Non-const access to available contents as a list of characters
inline UList<char> list() inline UList<char> list()
{ {
return buf_.list_; return buf_.list();
} }
//- The list size //- The list size
inline label size() const inline label size() const
{ {
return buf_.list_.size(); return buf_.capacity();
} }
//- Position of the get buffer //- Position of the get buffer
std::streampos tellg() const std::streampos tellg() const
{ {
return buf_.tellg(); return buf_.tellg();
} }
//- Move to buffer start, clear errors //- Move to buffer start, clear errors
void rewind() void rewind()
{ {
@ -278,7 +268,6 @@ public:
return allocator_type::tellg(); return allocator_type::tellg();
} }
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
virtual void rewind() virtual void rewind()
{ {
@ -286,7 +275,6 @@ public:
setGood(); // resynchronize with internal state setGood(); // resynchronize with internal state
} }
//- Print description to Ostream //- Print description to Ostream
virtual void print(Ostream& os) const; virtual void print(Ostream& os) const;

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -40,7 +40,7 @@ Description
{ {
UOListStream os(buffer); UOListStream os(buffer);
os << "content1" << " and more content"; os << "content1" << " and more content";
buffer.setSize(os.size()); // synchronize sizes buffer.resize(os.size()); // synchronize sizes
} }
something.write(buffer, buffer.size()); something.write(buffer, buffer.size());
@ -53,13 +53,13 @@ Description
UOListStream os(buffer); UOListStream os(buffer);
os << "content1" << " and more content"; os << "content1" << " and more content";
buffer.setSize(os.size()); // synchronize sizes buffer.resize(os.size()); // synchronize sizes
something.write(buffer, buffer.size()); something.write(buffer, buffer.size());
os.rewind(); os.rewind();
os << "content2"; os << "content2";
buffer.setSize(os.size()); // synchronize sizes buffer.resize(os.size()); // synchronize sizes
something.write(buffer, buffer.size()); something.write(buffer, buffer.size());
@ -91,51 +91,12 @@ namespace Foam
{ {
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class UOListAllocator Declaration Class UOListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An stream/stream-buffer allocator for external buffers //- An stream/stream-buffer allocator for external buffers
class UOListAllocator class UOListStreamAllocator
{ {
//- A streambuf adapter for output to UList or equivalent
class ulistbuf
:
public memorybuf::out
{
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:
// Protected data // Protected data
@ -143,7 +104,7 @@ protected:
typedef std::ostream stream_type; typedef std::ostream stream_type;
//- The stream buffer //- The stream buffer
ulistbuf buf_; memorybuf::out buf_;
//- The stream //- The stream
stream_type stream_; stream_type stream_;
@ -151,63 +112,47 @@ protected:
// Constructors // Constructors
//- Construct with buffer and number of bytes //- Construct for character array and number of bytes
UOListAllocator(char *buffer, size_t nbytes) UOListStreamAllocator(char *buffer, size_t nbytes)
: :
buf_(buffer, nbytes), buf_(buffer, nbytes),
stream_(&buf_) stream_(&buf_)
{} {}
// Protected Member Functions
void printBufInfo(Ostream& os) const void printBufInfo(Ostream& os) const
{ {
os << "pos=" << buf_.tellp() buf_.printBufInfo(os);
<< " capacity=" << buf_.capacity();
} }
public: public:
// Public Member Functions // Public Member Functions
//- Const UList access to the characters written (shallow copy).
inline const UList<char> list() const
{
return buf_.list();
}
//- Non-const UList access to the characters written (shallow copy).
inline UList<char> list()
{
return buf_.list();
}
//- The current list output capacity //- The current list output capacity
inline label capacity() const inline label capacity() const
{ {
return buf_.capacity(); return buf_.capacity();
} }
//- The current output position in the buffer, //- The current output position in the buffer,
// which is also the addressed list size //- which is also the addressed list size
inline label size() const inline label size() const
{ {
return buf_.tellp(); 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 //- Move to buffer start, clear errors
void rewind() void rewind()
{ {
@ -224,10 +169,10 @@ public:
//- An OSstream attached to an unallocated external buffer //- An OSstream attached to an unallocated external buffer
class UOListStream class UOListStream
: :
public UOListAllocator, public UOListStreamAllocator,
public OSstream public OSstream
{ {
typedef UOListAllocator allocator_type; typedef UOListStreamAllocator allocator_type;
public: public:

View File

@ -2,7 +2,7 @@
========= | ========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration | \\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd. \\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
@ -42,6 +42,9 @@ Description
namespace Foam namespace Foam
{ {
// Forward declarations
class Ostream;
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class memorybuf Declaration Class memorybuf Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
@ -126,6 +129,19 @@ protected:
} }
//- \return the current buffer get position
inline std::streamsize tellg() const
{
return (gptr() - eback());
}
//- \return the current buffer put position
inline std::streamsize tellp() const
{
return (pptr() - pbase());
}
public: public:
// Forward declarations // Forward declarations
@ -145,6 +161,9 @@ class memorybuf::in
{ {
protected: protected:
//- Default construct null
in() = default;
//- Get sequence of characters //- Get sequence of characters
virtual std::streamsize xsgetn(char* s, std::streamsize n) virtual std::streamsize xsgetn(char* s, std::streamsize n)
{ {
@ -159,17 +178,53 @@ protected:
return count; return count;
} }
public:
//- The buffer get position //- Construct for character array and number of bytes
inline std::streamsize tellg() const in(char* s, std::streamsize n)
{ {
return (gptr() - eback()); resetg(s, n);
} }
//- Sync get buffer pointers to agree with list dimensions //- Reset for character array and number of bytes
inline void set_gbuffer(UList<char>& list) inline void resetg(char* s, std::streamsize n)
{ {
setg(list.begin(), list.begin(), list.end()); if (s)
{
setg(s, s, s + n);
}
else
{
setg(nullptr, nullptr, nullptr);
}
}
//- The buffer get position
using memorybuf::tellg;
//- The buffer capacity
inline std::streamsize capacity() const
{
return (egptr() - eback());
}
//- Const UList access to the input characters (shallow copy).
inline const UList<char> list() const
{
return UList<char>(eback(), (egptr() - eback()));
}
//- Non-const UList access to the input characters (shallow copy).
inline UList<char> list()
{
return UList<char>(eback(), (egptr() - eback()));
}
//- Some information about the input buffer position/capacity
inline void printBufInfo(Ostream& os) const
{
os << "get=" << (gptr() - eback()) // tellp()
<< "/" << (egptr() - eback()); // capacity
} }
}; };
@ -185,6 +240,9 @@ class memorybuf::out
{ {
protected: protected:
//- Default construct null
out() = default;
//- 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)
{ {
@ -198,18 +256,54 @@ protected:
return count; return count;
} }
public:
//- Construct for character array and number of bytes
out(char* s, std::streamsize n)
{
resetp(s, n);
}
//- Reset for character array and number of bytes
inline void resetp(char* s, std::streamsize n)
{
if (s)
{
setp(s, s + n);
}
else
{
setp(nullptr, nullptr);
}
}
//- The buffer put position //- The buffer put position
inline std::streamsize tellp() const using memorybuf::tellp;
//- The buffer capacity
inline std::streamsize capacity() const
{ {
return (pptr() - pbase()); return (epptr() - pbase());
} }
//- Sync put buffer pointers to agree with list dimensions //- Const UList access to the characters written (shallow copy).
inline void set_pbuffer(UList<char>& list) inline const UList<char> list() const
{ {
setp(list.begin(), list.end()); return UList<char>(pbase(), (pptr() - pbase()));
} }
//- Non-const UList access to the characters written (shallow copy).
inline UList<char> list()
{
return UList<char>(pbase(), (pptr() - pbase()));
}
//- Some information about the output buffer position/capacity
inline void printBufInfo(Ostream& os) const
{
os << "put=" << (pptr() - pbase()) // tellp()
<< "/" << (epptr() - pbase()); // capacity
}
}; };