Commit 23c9dd71 authored by Mark Olesen's avatar Mark Olesen
Browse files

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
parent 0a5e4cf1
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
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)
{
label count = 0;
......@@ -126,21 +135,22 @@ int main(int argc, char *argv[])
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);
// 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<<nl << "swapped out:";
printInfo(newvalues);
Info<< "\nEnd\n" << endl;
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -40,17 +40,26 @@ int main(int argc, char *argv[])
OCountStream cnt;
OStringStream str;
ocountstream plain;
for (label i = 0; i < 50; ++i)
{
str << 1002 << " " << "abcd" << " "
str
<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
cnt
<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
cnt << 1002 << " " << "abcd" << " "
plain
<< 1002 << " " << "abcd" << " "
<< "def" << " " << 3.14159 << ";\n";
}
cnt.print(Info);
Info<< "via string-stream: " << str.str().size() << " chars" << endl;
Info<< "via ocountstream: " << plain.size() << " chars" << endl;
Info<< "\nEnd\n" << endl;
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -30,6 +30,9 @@ Description
#include "IOstreams.H"
#include "argList.H"
#include <sstream>
#include <vector>
using namespace Foam;
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>
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)
{
label count = 0;
......@@ -82,7 +107,7 @@ int main(int argc, char *argv[])
DynamicList<char> storage(1000);
UOListStream obuf(storage);
obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n";
obuf << 1002 << "\n" << "abcd" << "\n" << "def" << "\n" << 3.14159 << ";\n";
obuf.print(Info);
......@@ -92,15 +117,73 @@ int main(int argc, char *argv[])
Info<<"as string: " << string(storage.cdata(), storage.size()) << endl;
// Attach input buffer - could also do without previous resize
{
UIListStream ibuf(storage);
printTokens(ibuf);
Info<< nl << "Repeat..." << endl;
ibuf.rewind();
UIListStream ibuf(storage);
printTokens(ibuf);
}
printTokens(ibuf);
Info<< nl << "Repeat..." << endl;
ibuf.rewind();
// Attach input buffer - could also do without previous resize
{
Info<< "parse as std::istream\n";
printTokens(ibuf);
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;
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -51,7 +51,7 @@ namespace Foam
Class IListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer input allocator for with List storage
//- An stream/stream-buffer input allocator with List storage
class IListStreamAllocator
:
private List<char>,
......@@ -61,43 +61,46 @@ protected:
// Constructors
//- Construct with an empty list
//- Construct empty
IListStreamAllocator()
:
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)
:
List<char>(std::move(buffer)),
UIListStreamAllocator(list_storage())
UIListStreamAllocator(List<char>::data(), List<char>::size())
{}
//- Move construct from an existing DynamicList
//- Move construct from DynamicList
template<int SizeMin>
IListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
:
List<char>(std::move(buffer)),
UIListStreamAllocator(list_storage())
UIListStreamAllocator(List<char>::data(), List<char>::size())
{}
//- Transfer (move) construct
IListStreamAllocator(const Xfer<List<char>>& buffer)
:
List<char>(buffer),
UIListStreamAllocator(list_storage())
UIListStreamAllocator(List<char>::data(), List<char>::size())
{}
// Protected Member Functions
//- 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:
......@@ -107,21 +110,24 @@ public:
//- The current get position in the buffer
using UIListStreamAllocator::size;
inline void swap(List<char>& list)
{
List<char>::swap(list);
reset_gbuffer();
}
//- Clear storage
inline void clearStorage()
{
list_storage().clear();
sync_gbuffer_to_list();
List<char>::clear();
reset_gbuffer();
}
//- 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
Xfer<List<char>> moved = List<char>::xfer();
reset_gbuffer();
return moved;
}
};
......@@ -156,7 +162,7 @@ public:
{}
//- Move construct from an existing List
//- Move construct from List
IListStream
(
List<char>&& buffer,
......@@ -170,7 +176,7 @@ public:
{}
//- Move construct from an existing DynamicList
//- Move construct from DynamicList
template<int SizeMin>
IListStream
(
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2016-2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2016-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -49,14 +49,12 @@ class countstreambuf
:
public std::streambuf
{
// Private data
//- The number of bytes
std::streamsize size_;
//- The number of bytes counted
std::streamsize size_;
protected:
//- Simply handle output counting via overflow
//- Handle output counting via overflow
virtual int overflow(int c = EOF)
{
if (c != EOF)
......@@ -79,25 +77,25 @@ protected:
return 0;
}
public:
// Constructors
//- Construct null, or with precount size
countstreambuf(std::streamsize precount=0)
:
size_(precount)
{}
//- Construct null, or with precount size
countstreambuf(std::streamsize precount=0)
:
size_(precount)
{}
// Access
//- \return The number of bytes counted
std::streamsize size() const
{
return size_;
}
//- Number of bytes counted
std::streamsize size() const
{
return size_;
}
//- Some information about the number of bytes counted
inline void printBufInfo(Ostream& os) const
{
os << "count=" << size_;
}
};
......@@ -105,53 +103,30 @@ public:
Class ocountstream Declaration
\*---------------------------------------------------------------------------*/
//- Trivial output stream for calculating byte counts
// Since all output values are discarded, it can also be used as a /dev/null
// output buffer as well
//- Trivial output stream for calculating byte counts.
// Since all output values are discarded, it can be used as a /dev/null
// output buffer as well.
class ocountstream
:
virtual public std::ios,
protected countstreambuf,
public std::ostream
{
// Private data
countstreambuf buf_;
public:
// Constructors
//- Construct null
ocountstream()
:
std::ostream(&buf_)
{}
// Member Functions
// Access
//- Construct null
ocountstream()
:
countstreambuf(),
std::ostream(static_cast<countstreambuf*>(this))
{}
//- This hides both signatures of std::basic_ios::rdbuf()
countstreambuf* rdbuf()
{
return &buf_;
}
//- Get number of bytes counted
std::streamsize size() const
{
return buf_.size();
}
//- Rewind the stream, reset the count
void rewind()
{
buf_.pubseekpos(0);
clear(); // for safety, clear any old errors
}
//- Rewind the stream, reset the count
void rewind()
{
this->pubseekpos(0, std::ios_base::out);
clear(); // for safety, clear any old errors
}
};
......@@ -189,7 +164,7 @@ protected:
void printBufInfo(Ostream& os) const
{
os << "count=" << buf_.size();
buf_.printBufInfo(os);
}
public:
......
......@@ -2,7 +2,7 @@
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | Copyright (C) 2017 OpenCFD Ltd.
\\ / A nd | Copyright (C) 2017-2018 OpenCFD Ltd.
\\/ M anipulation |
-------------------------------------------------------------------------------
License
......@@ -29,9 +29,9 @@ Description
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.
The default list size is 512-bytes with a 256-byte block increment.
These values can be changed after construction using the reserve() and
the setBlockSize() methods.
See Also
Foam::IListStream
......@@ -45,6 +45,7 @@ See Also
#include "DynamicList.H"
#include "OSstream.H"
#include "stdFoam.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
......@@ -52,43 +53,39 @@ See Also
namespace Foam
{
// Forward declaration
class OListStreamAllocator;
/*---------------------------------------------------------------------------*\
Class OListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer output allocator for lists
//- An stream/stream-buffer output allocator with DynamicList-like storage
class OListStreamAllocator
{
//- A streambuf adapter to output to a List
class listbuf
//- A streambuf adapter with resizing similar to DynamicList
class dynbuf
:
public memorybuf::out
{
friend OListStreamAllocator;
friend class OListStreamAllocator;
//- Helper for setting the block size.
// Small list minimum of 64 bytes.
static int min_size(int n)
//- Helper for block size - small list minimum of 64 bytes.
constexpr static int min_size(int n)
{
return max(64, n);
return stdFoam::max(64, n);
}
//- Block size when resizing the list
int block_ = 256;
//- Underlying list storage.
// Internally manage like a DynamicList, but the addressable size
// is known through the stream pointers.
// Internally manage like a DynamicList, with its capacity known
// from the list size and the addressable size known through the
// stream pointers.
List<char> storage_;
protected:
//- Increment capacity directly and
// adjust buffer pointers to agree with list dimensions
//- Increment capacity directly and adjust buffer pointers to
//- correspond with the storage size.
inline void minCapacity
(
const std::streamsize n,
......@@ -115,8 +112,8 @@ class OListStreamAllocator
// << " pos:" << cur
// << " incr:" << incr << endl;
storage_.setSize(newCapacity);
sync_pbuffer_to_list();
storage_.resize(newCapacity);
sync_pbuffer();
pbump(cur);
}
}
......@@ -167,34 +164,34 @@ class OListStreamAllocator
//- Initialize put buffer
void init_pbuffer(const std::streamsize n)
{
set_pbuffer(storage_);
sync_pbuffer();
minCapacity(n);
}
public:
// Constructors
// Constructors
//- Construct with an empty list, or specified number of reserved bytes
listbuf(size_t nbytes = 512)