ENH: refine SpanStream and CharStream methods

- support std::string_view (c++17) or span view (older c++) of stream
  buffer contents. This simplifies formatting + reparsing.

  Example,

      OCharStream os;
      os << ...;

      ISpanStream is(os.view());
      is >> ...;

- additional release() method for ICharStream, OCharStream
  that returns the contents as a DynamicList<char> and resets the stream.

- provide a str() method for API compatibility with older
  std::ostringstream etc.
This commit is contained in:
Mark Olesen 2023-10-04 18:27:25 +02:00 committed by Andrew Heather
parent 1ddcad820f
commit 3693d61e6c
8 changed files with 512 additions and 190 deletions

View File

@ -37,12 +37,28 @@ Description
using namespace Foam; using namespace Foam;
Ostream& writeList(Ostream& os, const UList<char>& list) Ostream& printString(Ostream& os, const char* first, const char* last)
{
os << '"';
for (; first != last; (void)++first)
{
os << *first;
}
os << '"';
return os;
}
Ostream& printView(Ostream& os, const char* first, const char* last)
{ {
char buf[4]; char buf[4];
os << list.size() << '('; os << label(last-first) << '(';
for (const char c : list)
for (; first != last; (void)++first)
{ {
const char c = *first;
if (isprint(c)) if (isprint(c))
{ {
os << c; os << c;
@ -67,16 +83,35 @@ Ostream& writeList(Ostream& os, const UList<char>& list)
} }
#if __cplusplus >= 201703L
Ostream& printView(Ostream& os, std::string_view s)
{
return printView(os, s.begin(), s.end());
}
#endif
Ostream& printView(Ostream& os, stdFoam::span<char> s)
{
return printView(os, s.begin(), s.end());
}
Ostream& printView(Ostream& os, const UList<char>& list)
{
return printView(os, list.begin(), list.end());
}
Ostream& writeList(Ostream& os, const UList<char>& list)
{
return printView(os, list.begin(), list.end());
}
Ostream& toString(Ostream& os, const UList<char>& list) Ostream& toString(Ostream& os, const UList<char>& list)
{ {
os << '"'; return printString(os, list.begin(), list.end());
for (const char c : list)
{
os << c;
}
os << '"';
return os;
} }
@ -85,6 +120,7 @@ void printInfo(const BufType& buf)
{ {
Info<< nl << "=========================" << endl; Info<< nl << "=========================" << endl;
buf.print(Info); buf.print(Info);
Info<< "addr: " << Foam::name(buf.list().cdata()) << nl;
toString(Info, buf.list()); toString(Info, buf.list());
Info<< nl << "=========================" << endl; Info<< nl << "=========================" << endl;
} }
@ -136,14 +172,16 @@ int main(int argc, char *argv[])
Info<< "transfer contents to a List" << endl; Info<< "transfer contents to a List" << endl;
ICharStream ibuf;
// Reclaim data storage from OCharStream -> ICharStream // Reclaim data storage from OCharStream -> ICharStream
{ ICharStream ibuf(std::move(obuf));
List<char> data;
obuf.swap(data); // OLD
ibuf.swap(data); // ICharStream ibuf;
} // {
// List<char> data;
// obuf.swap(data);
// ibuf.swap(data);
// }
Info<< nl; Info<< nl;
Info<< nl << "input string:"; Info<< nl << "input string:";

View File

@ -37,12 +37,28 @@ Description
using namespace Foam; using namespace Foam;
Ostream& writeList(Ostream& os, const UList<char>& list) Ostream& printString(Ostream& os, const char* first, const char* last)
{
os << '"';
for (; first != last; (void)++first)
{
os << *first;
}
os << '"';
return os;
}
Ostream& printView(Ostream& os, const char* first, const char* last)
{ {
char buf[4]; char buf[4];
os << list.size() << '('; os << label(last-first) << '(';
for (const char c : list)
for (; first != last; (void)++first)
{ {
const char c = *first;
if (isprint(c)) if (isprint(c))
{ {
os << c; os << c;
@ -67,16 +83,35 @@ Ostream& writeList(Ostream& os, const UList<char>& list)
} }
#if __cplusplus >= 201703L
Ostream& printView(Ostream& os, std::string_view s)
{
return printView(os, s.begin(), s.end());
}
#endif
Ostream& printView(Ostream& os, stdFoam::span<char> s)
{
return printView(os, s.begin(), s.end());
}
Ostream& printView(Ostream& os, const UList<char>& list)
{
return printView(os, list.begin(), list.end());
}
Ostream& writeList(Ostream& os, const UList<char>& list)
{
return printView(os, list);
}
Ostream& toString(Ostream& os, const UList<char>& list) Ostream& toString(Ostream& os, const UList<char>& list)
{ {
os << '"'; return printString(os, list.begin(), list.end());
for (const char c : list)
{
os << c;
}
os << '"';
return os;
} }
@ -85,6 +120,7 @@ void printInfo(const BufType& buf)
{ {
Info<< nl << "=========================" << endl; Info<< nl << "=========================" << endl;
buf.print(Info); buf.print(Info);
Info<< "addr: " << Foam::name(buf.list().cdata()) << nl;
toString(Info, buf.list()); toString(Info, buf.list());
Info<< nl << "=========================" << endl; Info<< nl << "=========================" << endl;
} }
@ -152,11 +188,6 @@ int main(int argc, char *argv[])
printInfo(obuf); printInfo(obuf);
obuf.shrink();
Info<< "after shrink" << nl;
printInfo(obuf);
// Add some more // Add some more
for (label i=10; i < 15; ++i) for (label i=10; i < 15; ++i)
{ {
@ -175,13 +206,16 @@ int main(int argc, char *argv[])
Info<< "transfer contents to a List or ICharStream" << nl; Info<< "transfer contents to a List or ICharStream" << nl;
ICharStream ibuf;
// Reclaim data storage from OCharStream -> ICharStream // Reclaim data storage from OCharStream -> ICharStream
{ ICharStream ibuf(std::move(obuf));
List<char> data;
obuf.swap(data); // OLD
ibuf.swap(data); // ICharStream ibuf;
} // {
// List<char> data;
// obuf.swap(data);
// ibuf.swap(data);
// }
Info<<"original:"; Info<<"original:";
printInfo(obuf); printInfo(obuf);
@ -253,6 +287,14 @@ int main(int argc, char *argv[])
Info<< "Compact" << nl; Info<< "Compact" << nl;
printInfo(os2); printInfo(os2);
Info<< "address: " << Foam::name(os2.list().cdata()) << nl;
List<char> chars(os2.release());
Info<< "chars: " << chars.size() << nl;
Info<< "address: " << Foam::name(chars.cdata()) << nl;
Info<< "release" << nl;
printInfo(os2);
} }

View File

@ -39,12 +39,28 @@ Description
using namespace Foam; using namespace Foam;
Ostream& writeList(Ostream& os, const UList<char>& list) Ostream& printString(Ostream& os, const char* first, const char* last)
{
os << '"';
for (; first != last; (void)++first)
{
os << *first;
}
os << '"';
return os;
}
Ostream& printView(Ostream& os, const char* first, const char* last)
{ {
char buf[4]; char buf[4];
os << list.size() << '('; os << label(last-first) << '(';
for (const char c : list)
for (; first != last; (void)++first)
{ {
const char c = *first;
if (isprint(c)) if (isprint(c))
{ {
os << c; os << c;
@ -69,29 +85,41 @@ Ostream& writeList(Ostream& os, const UList<char>& list)
} }
#if __cplusplus >= 201703L
Ostream& printView(Ostream& os, std::string_view s)
{
return printView(os, s.begin(), s.end());
}
#endif
Ostream& printView(Ostream& os, stdFoam::span<char> s)
{
return printView(os, s.begin(), s.end());
}
Ostream& printView(Ostream& os, const UList<char>& list)
{
return printView(os, list.begin(), list.end());
}
Ostream& writeList(Ostream& os, const UList<char>& list)
{
return printView(os, list.begin(), list.end());
}
Ostream& toString(Ostream& os, const UList<char>& list) Ostream& toString(Ostream& os, const UList<char>& list)
{ {
os << '"'; return printString(os, list.begin(), list.end());
for (const char c : list)
{
os << c;
}
os << '"';
return os;
} }
Ostream& toString(Ostream& os, const std::vector<char>& list) Ostream& toString(Ostream& os, const std::vector<char>& list)
{ {
os << '"'; return printString(os, list.data(), list.data() + list.size());
for (const char c : list)
{
os << c;
}
os << '"';
return os;
} }

View File

@ -53,6 +53,7 @@ namespace Foam
// Forward Declarations // Forward Declarations
class icharstream; class icharstream;
class ICharStream; class ICharStream;
class OCharStream;
// Older names (prior to 2023-08) // Older names (prior to 2023-08)
typedef ICharStream IListStream; typedef ICharStream IListStream;
@ -93,14 +94,6 @@ public:
reset(buffer, nbytes); reset(buffer, nbytes);
} }
// //- Construct (deep copy) from span character content
// explicit icharstream(stdFoam::span<char> s)
// :
// icharstream()
// {
// reset(buffer, nbytes);
// }
//- Move construct from List //- Move construct from List
icharstream(List<char>&& buffer) icharstream(List<char>&& buffer)
: :
@ -143,7 +136,28 @@ public:
//- Span of the input characters (is modifiable!) //- Span of the input characters (is modifiable!)
UList<char> list() const UList<char> list() const
{ {
return buffer_type::span_list(); return UList<char>
(
buffer_type::data_bytes(),
label(buffer_type::size_bytes())
);
}
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(buffer_type::view())
{
return buffer_type::view();
}
//- For istringstream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
std::string str() const
{
return std::string
(
buffer_type::data_bytes(),
buffer_type::size_bytes()
);
} }
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
@ -153,21 +167,21 @@ public:
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Reset content (copy) //- Reset stream content (copy), reset positions
void reset(const char* buffer, size_t nbytes) void reset(const char* buffer, size_t nbytes)
{ {
buffer_type::reset(buffer, nbytes); buffer_type::reset(buffer, nbytes);
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Transfer list contents to List buffer //- Exchange stream content and parameter contents, reset positions
void swap(List<char>& other) void swap(List<char>& other)
{ {
buffer_type::swap(other); buffer_type::swap(other);
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Transfer list contents to a DynamicList buffer //- Exchange stream content and parameter contents, reset positions
template<int SizeMin> template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other) void swap(DynamicList<char,SizeMin>& other)
{ {
@ -175,11 +189,18 @@ public:
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Reset stream and return contents as a List
DynamicList<char> release()
{
DynamicList<char> chars(buffer_type::release());
stream_type::clear(); // Clear old errors
return chars;
}
//- Some information about the input buffer position/capacity //- Some information about the input buffer position/capacity
void debug_info(Ostream& os) const void debug_info(Ostream& os) const
{ {
os << "get=" os << "get=" << input_pos() << '/' << capacity();
<< input_pos() << '/' << capacity();
} }
}; };
@ -252,7 +273,7 @@ public:
//- Move construct from List //- Move construct from List
explicit ICharStream explicit ICharStream
( (
::Foam::List<char>&& buffer, // Fully qualify (issue #1521) List<char>&& buffer,
IOstreamOption streamOpt = IOstreamOption() IOstreamOption streamOpt = IOstreamOption()
) )
: :
@ -296,6 +317,19 @@ public:
//- Span of the input characters (is modifiable!) //- Span of the input characters (is modifiable!)
UList<char> list() const { return stream_.list(); } UList<char> list() const { return stream_.list(); }
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(stream_.view())
{
return stream_.view();
}
//- For IStringStream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
auto str() const -> decltype(stream_.str())
{
return stream_.str();
}
//- Reset content (copy) //- Reset content (copy)
void reset(const char* buffer, size_t nbytes) void reset(const char* buffer, size_t nbytes)
{ {
@ -303,14 +337,14 @@ public:
syncState(); syncState();
} }
//- Transfer list contents to List buffer //- Exchange stream content and parameter contents, reset positions
void swap(List<char>& other) void swap(List<char>& other)
{ {
stream_.swap(other); stream_.swap(other);
syncState(); syncState();
} }
//- Transfer list contents to a DynamicList buffer //- Exchange stream content and parameter contents, reset positions
template<int SizeMin> template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other) void swap(DynamicList<char,SizeMin>& other)
{ {
@ -318,6 +352,14 @@ public:
syncState(); syncState();
} }
//- Reset stream and return contents as a List
DynamicList<char> release()
{
DynamicList<char> chars(stream_.release());
syncState();
return chars;
}
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
virtual void rewind() override virtual void rewind() override
{ {

View File

@ -64,9 +64,9 @@ See Also
#ifndef Foam_ISpanStream_H #ifndef Foam_ISpanStream_H
#define Foam_ISpanStream_H #define Foam_ISpanStream_H
#include "memoryStreamBuffer.H"
#include "UList.H" #include "UList.H"
#include "ISstream.H" #include "ISstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -117,12 +117,28 @@ public:
stream_type(static_cast<buffer_type*>(this)) stream_type(static_cast<buffer_type*>(this))
{} {}
// //- Construct (shallow copy) from span character content #if __cplusplus >= 201703L
// ispanstream(stdFoam::span<char> s) //- Construct (shallow copy) from std::string_view content
// : explicit ispanstream(std::string_view s)
// buffer_type(const_cast<char*>(s.data()), s.size()), {
// stream_type(static_cast<buffer_type*>(this)) buffer_type(const_cast<char*>(s.data()), s.size()),
// {} stream_type(static_cast<buffer_type*>(this))
}
#endif
//- Construct (shallow copy) from span character content
explicit ispanstream(stdFoam::span<char> s)
:
buffer_type(const_cast<char*>(s.data()), s.size()),
stream_type(static_cast<buffer_type*>(this))
{}
//- Construct (shallow copy) from span character content
explicit ispanstream(stdFoam::span<const char> s)
:
buffer_type(const_cast<char*>(s.data()), s.size()),
stream_type(static_cast<buffer_type*>(this))
{}
// Member Functions // Member Functions
@ -149,7 +165,28 @@ public:
//- Span of the input characters (is modifiable!) //- Span of the input characters (is modifiable!)
UList<char> list() const UList<char> list() const
{ {
return buffer_type::span_list(); return UList<char>
(
buffer_type::data_bytes(),
label(buffer_type::size_bytes())
);
}
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(buffer_type::view())
{
return buffer_type::view();
}
//- For istringstream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
std::string str() const
{
return std::string
(
buffer_type::data_bytes(),
buffer_type::size_bytes()
);
} }
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
@ -259,17 +296,6 @@ public:
reset(buffer); reset(buffer);
} }
//- Construct using data area from a List and number of bytes
ISpanStream
(
const ::Foam::UList<char>& buffer,
size_t nbytes,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(buffer.cdata(), nbytes, streamOpt)
{}
//- 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
explicit ISpanStream explicit ISpanStream
@ -281,6 +307,38 @@ public:
ISpanStream(buffer.cdata(), buffer.size(), streamOpt) ISpanStream(buffer.cdata(), buffer.size(), streamOpt)
{} {}
#if __cplusplus >= 201703L
//- Construct (shallow copy) from std::string_view content
explicit ISpanStream
(
std::string_view s,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(s.data(), s.size(), streamOpt)
{}
#endif
//- Construct (shallow copy) from span character content
explicit ISpanStream
(
stdFoam::span<const char> s,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(s.data(), s.size(), streamOpt)
{}
//- Construct (shallow copy) from span character content
explicit ISpanStream
(
stdFoam::span<char> s,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(s.data(), s.size(), streamOpt)
{}
// Member Functions // Member Functions
@ -300,10 +358,22 @@ public:
//- Same as (capacity() - input_pos()) //- Same as (capacity() - input_pos())
std::streamsize remaining() const { return stream_.remaining(); } std::streamsize remaining() const { return stream_.remaining(); }
//- Span of the current input characters (is modifiable!) //- Span of the current input characters (is modifiable!)
UList<char> list() const { return stream_.list(); } UList<char> list() const { return stream_.list(); }
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(stream_.view())
{
return stream_.view();
}
//- For IStringStream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
auto str() const -> decltype(stream_.str())
{
return stream_.str();
}
//- Reset input area, position to buffer start and clear errors //- Reset input area, position to buffer start and clear errors
void reset(const char* buffer, size_t nbytes) void reset(const char* buffer, size_t nbytes)
{ {
@ -318,6 +388,29 @@ public:
syncState(); syncState();
} }
#if __cplusplus >= 201703L
//- Reset input area to use data from a std::string_view
void reset(std::string_view s)
{
stream_.reset(s.data(), s.size());
syncState();
}
#endif
//- Reset input area to use data from span character content
void reset(stdFoam::span<char> s)
{
stream_.reset(s.data(), s.size());
syncState();
}
//- Reset input area to use data from span character content
void reset(stdFoam::span<const char> s)
{
stream_.reset(s.data(), s.size());
syncState();
}
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
virtual void rewind() override virtual void rewind() override
{ {

View File

@ -124,12 +124,6 @@ public:
buffer_type::reserve(n); buffer_type::reserve(n);
} }
//- Span of the current output characters (is modifiable!)
UList<char> list() const
{
return buffer_type::span_list();
}
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
void rewind() void rewind()
{ {
@ -137,14 +131,41 @@ public:
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Transfer list contents to List buffer //- Span of the current output characters (is modifiable!)
UList<char> list() const
{
return UList<char>
(
buffer_type::data_bytes(),
label(buffer_type::size_bytes())
);
}
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(buffer_type::view())
{
return buffer_type::view();
}
//- For ostringstream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
std::string str() const
{
return std::string
(
buffer_type::data_bytes(),
buffer_type::size_bytes()
);
}
//- Exchange stream content and parameter contents, reset positions
void swap(List<char>& other) void swap(List<char>& other)
{ {
buffer_type::swap(other); buffer_type::swap(other);
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Transfer list contents to a DynamicList buffer //- Exchange stream content and parameter contents, reset positions
template<int SizeMin> template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other) void swap(DynamicList<char,SizeMin>& other)
{ {
@ -152,11 +173,18 @@ public:
stream_type::clear(); // Clear old errors stream_type::clear(); // Clear old errors
} }
//- Reset buffer and return contents
DynamicList<char> release()
{
DynamicList<char> chars(buffer_type::release());
stream_type::clear(); // Clear old errors
return chars;
}
//- Some information about the output buffer position/capacity //- Some information about the output buffer position/capacity
void debug_info(Ostream& os) const void debug_info(Ostream& os) const
{ {
os << "put=" os << "put=" << output_pos() << '/' << capacity();
<< output_pos() << '/' << capacity();
} }
}; };
@ -214,19 +242,7 @@ public:
OSstream(stream_, "output", streamOpt.format(), streamOpt.version()) OSstream(stream_, "output", streamOpt.format(), streamOpt.version())
{} {}
//- Construct with initial reserved number of bytes //- Move construct from a List of initial storage
explicit OCharStream
(
size_t nbytes,
IOstreamOption streamOpt = IOstreamOption()
)
:
OCharStream(streamOpt)
{
stream_.reserve(nbytes);
}
//- Move construct from a List
explicit OCharStream explicit OCharStream
( (
::Foam::List<char>&& buffer, ::Foam::List<char>&& buffer,
@ -238,7 +254,8 @@ public:
stream_.swap(buffer); stream_.swap(buffer);
} }
//- Move construct from a DynamicList (uses entire capacity) //- Move construct from a DynamicList of initial storage
//- (uses entire capacity)
template<int SizeMin> template<int SizeMin>
explicit OCharStream explicit OCharStream
( (
@ -272,14 +289,27 @@ public:
//- Span of the current output characters (is modifiable!) //- Span of the current output characters (is modifiable!)
UList<char> list() const { return stream_.list(); } UList<char> list() const { return stream_.list(); }
//- Transfer list contents to List buffer //- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(stream_.view())
{
return stream_.view();
}
//- For OStringStream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
auto str() const -> decltype(stream_.str())
{
return stream_.str();
}
//- Exchange stream content and parameter contents, reset positions
void swap(List<char>& other) void swap(List<char>& other)
{ {
stream_.swap(other); stream_.swap(other);
syncState(); syncState();
} }
//- Transfer list contents to a DynamicList buffer //- Exchange stream content and parameter contents, reset positions
template<int SizeMin> template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other) void swap(DynamicList<char,SizeMin>& other)
{ {
@ -287,6 +317,14 @@ public:
syncState(); syncState();
} }
//- Reset buffer and return contents
DynamicList<char> release()
{
DynamicList<char> chars(stream_.release());
syncState();
return chars;
}
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
virtual void rewind() virtual void rewind()
{ {

View File

@ -132,13 +132,6 @@ public:
stream_type(static_cast<buffer_type*>(this)) stream_type(static_cast<buffer_type*>(this))
{} {}
// //- Construct (shallow copy) from span character content
// ospanstream(stdFoam::span<char> s)
// :
// buffer_type(const_cast<char*>(s.data()), s.size()),
// stream_type(static_cast<buffer_type*>(this))
// {}
// Member Functions // Member Functions
@ -157,7 +150,28 @@ public:
//- Span of the current output characters (is modifiable!) //- Span of the current output characters (is modifiable!)
UList<char> list() const UList<char> list() const
{ {
return buffer_type::span_list(); return UList<char>
(
buffer_type::data_bytes(),
label(buffer_type::size_bytes())
);
}
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(buffer_type::view())
{
return buffer_type::view();
}
//- For ostringstream compatibility, return the buffer as string copy.
// Use sparingly - it creates a full copy!!
std::string str() const
{
return std::string
(
buffer_type::data_bytes(),
buffer_type::size_bytes()
);
} }
//- Rewind the stream, clearing any old errors //- Rewind the stream, clearing any old errors
@ -222,7 +236,6 @@ protected:
Class OSpanStream Declaration Class OSpanStream Declaration
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
//- An OSstream attached to an unallocated external buffer
class OSpanStream class OSpanStream
: :
public Detail::OSpanStreamAllocator, public Detail::OSpanStreamAllocator,
@ -269,17 +282,6 @@ public:
stream_.reset(buffer, nbytes); stream_.reset(buffer, nbytes);
} }
//- Construct using data area from a List and number of bytes
OSpanStream
(
::Foam::UList<char>& buffer,
size_t nbytes,
IOstreamOption streamOpt = IOstreamOption()
)
:
OSpanStream(buffer.data(), nbytes, streamOpt)
{}
//- Construct using data area from a List and its inherent storage size //- Construct using data area from a List and its inherent storage size
explicit OSpanStream explicit OSpanStream
( (
@ -321,6 +323,19 @@ public:
//- Span of the current output characters (is modifiable!) //- Span of the current output characters (is modifiable!)
UList<char> list() const { return stream_.list(); } UList<char> list() const { return stream_.list(); }
//- A string_view (c++17) or span view (older c++) of buffer contents
auto view() const -> decltype(stream_.view())
{
return stream_.view();
}
//- For OStringStream compatibility, return buffer as string copy.
// Use sparingly - it creates a full copy!!
auto str() const -> decltype(stream_.str())
{
return stream_.str();
}
//- Reset the put area //- Reset the put area
void reset(char* buffer, size_t nbytes) void reset(char* buffer, size_t nbytes)
{ {

View File

@ -36,10 +36,9 @@ Description
#define Foam_memoryStreamBuffer_H #define Foam_memoryStreamBuffer_H
#include "stdFoam.H" // For span #include "stdFoam.H" // For span
#include "UList.H" #include "DynamicList.H"
#include <memory> #include <memory>
#include <sstream> // Possibly want stringstream too...
#include <type_traits> #include <type_traits>
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -208,17 +207,23 @@ public:
return (gptr() < egptr()) ? (egptr() - gptr()) : 0; return (gptr() < egptr()) ? (egptr() - gptr()) : 0;
} }
//- Span of the input characters (is modifiable!) //- The span data (start of input characters)
UList<char> span_list() const char* data_bytes() const { return eback(); }
{
return UList<char>(eback(), (egptr() - eback()));
}
// //- The span of input characters (is modifiable!) //- The span size (number of input characters)
// stdFoam::span<char> span() const std::streamsize size_bytes() const { return (egptr() - eback()); }
// {
// return stdFoam::span<char>(eback(), (egptr() - eback())); #if __cplusplus >= 201703L
// } std::string_view view() const
{
return std::string_view(data_bytes(), size_bytes());
}
#else
stdFoam::span<const char> view() const
{
return stdFoam::span<const char>(data_bytes(), size_bytes());
}
#endif
//- Some information about the input buffer position/capacity //- Some information about the input buffer position/capacity
void info(Ostream& os) const void info(Ostream& os) const
@ -273,7 +278,7 @@ public:
template<int SizeMin> template<int SizeMin>
in_dynamic(::Foam::DynamicList<char,SizeMin>&& buffer) in_dynamic(::Foam::DynamicList<char,SizeMin>&& buffer)
{ {
storage_.transfer(buffer); storage_.transfer(buffer); // Implies shrink_to_fit
sync_gbuffer(); sync_gbuffer();
} }
@ -302,24 +307,29 @@ public:
sync_gbuffer(); sync_gbuffer();
} }
//- Transfer list contents to List buffer //- Exchange buffer content and parameter contents, reset positions
void swap(::Foam::List<char>& other) void swap(List<char>& other)
{ {
storage_.swap(other); // Swap contents other.swap(storage_); // Swap contents
sync_gbuffer(); sync_gbuffer();
} }
//- Transfer list contents to a DynamicList buffer //- Exchange buffer content and parameter contents, reset positions
template<int SizeMin> template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other) void swap(DynamicList<char,SizeMin>& other)
{ {
List<char> tmp(std::move(storage_)); // NB: not storage_.swap(other)! - incorrect slicing
other.swap(storage_); // Swap contents: implies shrink_to_fit
other.shrink(); // Use addressed length only
storage_.transfer(other);
other.transfer(tmp);
sync_gbuffer(); sync_gbuffer();
} }
//- Reset buffer and return contents
DynamicList<char> release()
{
DynamicList<char> chars(std::move(storage_));
sync_gbuffer();
return chars;
}
}; };
@ -387,17 +397,23 @@ public:
//- The put buffer capacity //- The put buffer capacity
std::streamsize span_capacity() const { return (epptr() - pbase()); } std::streamsize span_capacity() const { return (epptr() - pbase()); }
//- Span of the output characters (is modifiable!) //- The span data (start of output characters)
UList<char> span_list() const char* data_bytes() const { return pbase(); }
{
return UList<char>(pbase(), (pptr() - pbase()));
}
//- The span of output characters (is modifiable!) //- The span size (size of output buffer)
// stdFoam::span<char> span() const std::streamsize size_bytes() const { return (pptr() - pbase()); }
// {
// return stdFoam::span<char>(pbase(), (pptr() - pbase())); #if __cplusplus >= 201703L
// } std::string_view view() const
{
return std::string_view(data_bytes(), size_bytes());
}
#else
stdFoam::span<const char> view() const
{
return stdFoam::span<const char>(data_bytes(), size_bytes());
}
#endif
//- Some information about the output buffer position/capacity //- Some information about the output buffer position/capacity
void info(Ostream& os) const void info(Ostream& os) const
@ -532,38 +548,48 @@ public:
} }
//- Shrink storage to addressed storage //- Shrink storage to addressed storage
inline void shrink() void shrink()
{ {
const auto cur = span_tellp(); // Addressed length const auto cur = span_tellp(); // Addressed length
storage_.resize(cur); storage_.resize(cur);
sync_pbuffer(); sync_pbuffer();
pbump(cur); pbump(cur);
} }
//- Transfer list contents to List buffer //- Exchange buffer content and parameter contents, reset positions
inline void swap(List<char>& other) void swap(List<char>& other)
{ {
const auto cur = span_tellp(); // Addressed length const auto cur = span_tellp(); // Output length
other.swap(storage_);
storage_.swap(other); // Swap contents other.resize(cur); // Truncate to output length
other.resize(cur); // Adjust to addressed length
sync_pbuffer(); sync_pbuffer();
} }
//- Transfer list contents to a DynamicList buffer //- Exchange buffer content and parameter contents, reset positions
template<int SizeMin> template<int SizeMin>
inline void swap(DynamicList<char,SizeMin>& other) void swap(DynamicList<char,SizeMin>& other)
{ {
const auto cur = span_tellp(); // Addressed length const auto cur = span_tellp(); // Output length
List<char> tmp(std::move(storage_));
other.resize(other.capacity()); // Use entire space other.resize(other.capacity()); // Use entire space
storage_.transfer(other); other.swap(storage_); // NB: not storage_.swap(other)
other.transfer(tmp); other.resize(cur); // Restrict to output length
other.resize(cur); // Adjust to addressed length
sync_pbuffer(); sync_pbuffer();
} }
//- Reset buffer and return contents as a DynamicList.
//- The list size corresponds to the region of output.
DynamicList<char> release()
{
const auto cur = span_tellp(); // Output length
DynamicList<char> chars(std::move(storage_));
chars.resize(cur); // Restrict to output length
if (chars.empty()) chars.clearStorage(); // Can destroy now
sync_pbuffer();
return chars;
}
}; };