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;
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];
os << list.size() << '(';
for (const char c : list)
os << label(last-first) << '(';
for (; first != last; (void)++first)
{
const char c = *first;
if (isprint(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)
{
os << '"';
for (const char c : list)
{
os << c;
}
os << '"';
return os;
return printString(os, list.begin(), list.end());
}
@ -85,6 +120,7 @@ void printInfo(const BufType& buf)
{
Info<< nl << "=========================" << endl;
buf.print(Info);
Info<< "addr: " << Foam::name(buf.list().cdata()) << nl;
toString(Info, buf.list());
Info<< nl << "=========================" << endl;
}
@ -136,14 +172,16 @@ int main(int argc, char *argv[])
Info<< "transfer contents to a List" << endl;
ICharStream ibuf;
// Reclaim data storage from OCharStream -> ICharStream
{
List<char> data;
obuf.swap(data);
ibuf.swap(data);
}
ICharStream ibuf(std::move(obuf));
// OLD
// ICharStream ibuf;
// {
// List<char> data;
// obuf.swap(data);
// ibuf.swap(data);
// }
Info<< nl;
Info<< nl << "input string:";

View File

@ -37,12 +37,28 @@ Description
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];
os << list.size() << '(';
for (const char c : list)
os << label(last-first) << '(';
for (; first != last; (void)++first)
{
const char c = *first;
if (isprint(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)
{
os << '"';
for (const char c : list)
{
os << c;
}
os << '"';
return os;
return printString(os, list.begin(), list.end());
}
@ -85,6 +120,7 @@ void printInfo(const BufType& buf)
{
Info<< nl << "=========================" << endl;
buf.print(Info);
Info<< "addr: " << Foam::name(buf.list().cdata()) << nl;
toString(Info, buf.list());
Info<< nl << "=========================" << endl;
}
@ -152,11 +188,6 @@ int main(int argc, char *argv[])
printInfo(obuf);
obuf.shrink();
Info<< "after shrink" << nl;
printInfo(obuf);
// Add some more
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;
ICharStream ibuf;
// Reclaim data storage from OCharStream -> ICharStream
{
List<char> data;
obuf.swap(data);
ibuf.swap(data);
}
ICharStream ibuf(std::move(obuf));
// OLD
// ICharStream ibuf;
// {
// List<char> data;
// obuf.swap(data);
// ibuf.swap(data);
// }
Info<<"original:";
printInfo(obuf);
@ -253,6 +287,14 @@ int main(int argc, char *argv[])
Info<< "Compact" << nl;
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;
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];
os << list.size() << '(';
for (const char c : list)
os << label(last-first) << '(';
for (; first != last; (void)++first)
{
const char c = *first;
if (isprint(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)
{
os << '"';
for (const char c : list)
{
os << c;
}
os << '"';
return os;
return printString(os, list.begin(), list.end());
}
Ostream& toString(Ostream& os, const std::vector<char>& list)
{
os << '"';
for (const char c : list)
{
os << c;
}
os << '"';
return os;
return printString(os, list.data(), list.data() + list.size());
}

View File

@ -53,6 +53,7 @@ namespace Foam
// Forward Declarations
class icharstream;
class ICharStream;
class OCharStream;
// Older names (prior to 2023-08)
typedef ICharStream IListStream;
@ -93,14 +94,6 @@ public:
reset(buffer, nbytes);
}
// //- Construct (deep copy) from span character content
// explicit icharstream(stdFoam::span<char> s)
// :
// icharstream()
// {
// reset(buffer, nbytes);
// }
//- Move construct from List
icharstream(List<char>&& buffer)
:
@ -143,7 +136,28 @@ public:
//- Span of the input characters (is modifiable!)
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
@ -153,21 +167,21 @@ public:
stream_type::clear(); // Clear old errors
}
//- Reset content (copy)
//- Reset stream content (copy), reset positions
void reset(const char* buffer, size_t nbytes)
{
buffer_type::reset(buffer, nbytes);
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)
{
buffer_type::swap(other);
stream_type::clear(); // Clear old errors
}
//- Transfer list contents to a DynamicList buffer
//- Exchange stream content and parameter contents, reset positions
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
@ -175,11 +189,18 @@ public:
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
void debug_info(Ostream& os) const
{
os << "get="
<< input_pos() << '/' << capacity();
os << "get=" << input_pos() << '/' << capacity();
}
};
@ -252,7 +273,7 @@ public:
//- Move construct from List
explicit ICharStream
(
::Foam::List<char>&& buffer, // Fully qualify (issue #1521)
List<char>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
@ -296,6 +317,19 @@ public:
//- Span of the input characters (is modifiable!)
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)
void reset(const char* buffer, size_t nbytes)
{
@ -303,14 +337,14 @@ public:
syncState();
}
//- Transfer list contents to List buffer
//- Exchange stream content and parameter contents, reset positions
void swap(List<char>& other)
{
stream_.swap(other);
syncState();
}
//- Transfer list contents to a DynamicList buffer
//- Exchange stream content and parameter contents, reset positions
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
@ -318,6 +352,14 @@ public:
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
virtual void rewind() override
{

View File

@ -64,9 +64,9 @@ See Also
#ifndef Foam_ISpanStream_H
#define Foam_ISpanStream_H
#include "memoryStreamBuffer.H"
#include "UList.H"
#include "ISstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -117,12 +117,28 @@ public:
stream_type(static_cast<buffer_type*>(this))
{}
// //- Construct (shallow copy) from span character content
// ispanstream(stdFoam::span<char> s)
// :
// buffer_type(const_cast<char*>(s.data()), s.size()),
// stream_type(static_cast<buffer_type*>(this))
// {}
#if __cplusplus >= 201703L
//- 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))
}
#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
@ -149,7 +165,28 @@ public:
//- Span of the input characters (is modifiable!)
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
@ -259,17 +296,6 @@ public:
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
// Uses addressed size, thus no special treatment for a DynamicList
explicit ISpanStream
@ -281,6 +307,38 @@ public:
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
@ -300,10 +358,22 @@ public:
//- Same as (capacity() - input_pos())
std::streamsize remaining() const { return stream_.remaining(); }
//- Span of the current input characters (is modifiable!)
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
void reset(const char* buffer, size_t nbytes)
{
@ -318,6 +388,29 @@ public:
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
virtual void rewind() override
{

View File

@ -124,12 +124,6 @@ public:
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
void rewind()
{
@ -137,14 +131,41 @@ public:
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)
{
buffer_type::swap(other);
stream_type::clear(); // Clear old errors
}
//- Transfer list contents to a DynamicList buffer
//- Exchange stream content and parameter contents, reset positions
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
@ -152,11 +173,18 @@ public:
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
void debug_info(Ostream& os) const
{
os << "put="
<< output_pos() << '/' << capacity();
os << "put=" << output_pos() << '/' << capacity();
}
};
@ -214,19 +242,7 @@ public:
OSstream(stream_, "output", streamOpt.format(), streamOpt.version())
{}
//- Construct with initial reserved number of bytes
explicit OCharStream
(
size_t nbytes,
IOstreamOption streamOpt = IOstreamOption()
)
:
OCharStream(streamOpt)
{
stream_.reserve(nbytes);
}
//- Move construct from a List
//- Move construct from a List of initial storage
explicit OCharStream
(
::Foam::List<char>&& buffer,
@ -238,7 +254,8 @@ public:
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>
explicit OCharStream
(
@ -272,14 +289,27 @@ public:
//- Span of the current output characters (is modifiable!)
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)
{
stream_.swap(other);
syncState();
}
//- Transfer list contents to a DynamicList buffer
//- Exchange stream content and parameter contents, reset positions
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
@ -287,6 +317,14 @@ public:
syncState();
}
//- Reset buffer and return contents
DynamicList<char> release()
{
DynamicList<char> chars(stream_.release());
syncState();
return chars;
}
//- Rewind the stream, clearing any old errors
virtual void rewind()
{

View File

@ -132,13 +132,6 @@ public:
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
@ -157,7 +150,28 @@ public:
//- Span of the current output characters (is modifiable!)
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
@ -222,7 +236,6 @@ protected:
Class OSpanStream Declaration
\*---------------------------------------------------------------------------*/
//- An OSstream attached to an unallocated external buffer
class OSpanStream
:
public Detail::OSpanStreamAllocator,
@ -269,17 +282,6 @@ public:
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
explicit OSpanStream
(
@ -321,6 +323,19 @@ public:
//- Span of the current output characters (is modifiable!)
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
void reset(char* buffer, size_t nbytes)
{

View File

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