From 3693d61e6cac5963521459c06f91a52949b43bd7 Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 4 Oct 2023 18:27:25 +0200 Subject: [PATCH] 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 and resets the stream. - provide a str() method for API compatibility with older std::ostringstream etc. --- .../test/ICharStream1/Test-ICharStream1.C | 74 +++++++--- .../test/OCharStream1/Test-OCharStream1.C | 86 ++++++++--- .../test/SpanStream1/Test-SpanStream1.C | 66 ++++++--- .../db/IOstreams/memory/ICharStream.H | 76 +++++++--- .../db/IOstreams/memory/ISpanStream.H | 133 +++++++++++++++--- .../db/IOstreams/memory/OCharStream.H | 90 ++++++++---- .../db/IOstreams/memory/OSpanStream.H | 55 +++++--- .../db/IOstreams/memory/memoryStreamBuffer.H | 122 +++++++++------- 8 files changed, 512 insertions(+), 190 deletions(-) diff --git a/applications/test/ICharStream1/Test-ICharStream1.C b/applications/test/ICharStream1/Test-ICharStream1.C index ec2bc3da07..cf36c3cddd 100644 --- a/applications/test/ICharStream1/Test-ICharStream1.C +++ b/applications/test/ICharStream1/Test-ICharStream1.C @@ -37,12 +37,28 @@ Description using namespace Foam; -Ostream& writeList(Ostream& os, const UList& 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& 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 s) +{ + return printView(os, s.begin(), s.end()); +} + + +Ostream& printView(Ostream& os, const UList& list) +{ + return printView(os, list.begin(), list.end()); +} + + +Ostream& writeList(Ostream& os, const UList& list) +{ + return printView(os, list.begin(), list.end()); +} + + Ostream& toString(Ostream& os, const UList& 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 data; - obuf.swap(data); - ibuf.swap(data); - } + ICharStream ibuf(std::move(obuf)); + + // OLD + // ICharStream ibuf; + // { + // List data; + // obuf.swap(data); + // ibuf.swap(data); + // } Info<< nl; Info<< nl << "input string:"; diff --git a/applications/test/OCharStream1/Test-OCharStream1.C b/applications/test/OCharStream1/Test-OCharStream1.C index ccd663d30d..08e885161f 100644 --- a/applications/test/OCharStream1/Test-OCharStream1.C +++ b/applications/test/OCharStream1/Test-OCharStream1.C @@ -37,12 +37,28 @@ Description using namespace Foam; -Ostream& writeList(Ostream& os, const UList& 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& 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 s) +{ + return printView(os, s.begin(), s.end()); +} + + +Ostream& printView(Ostream& os, const UList& list) +{ + return printView(os, list.begin(), list.end()); +} + + +Ostream& writeList(Ostream& os, const UList& list) +{ + return printView(os, list); +} + + Ostream& toString(Ostream& os, const UList& 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 data; - obuf.swap(data); - ibuf.swap(data); - } + ICharStream ibuf(std::move(obuf)); + + // OLD + // ICharStream ibuf; + // { + // List 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 chars(os2.release()); + Info<< "chars: " << chars.size() << nl; + Info<< "address: " << Foam::name(chars.cdata()) << nl; + Info<< "release" << nl; + printInfo(os2); } diff --git a/applications/test/SpanStream1/Test-SpanStream1.C b/applications/test/SpanStream1/Test-SpanStream1.C index dede85f880..92fb58daa0 100644 --- a/applications/test/SpanStream1/Test-SpanStream1.C +++ b/applications/test/SpanStream1/Test-SpanStream1.C @@ -39,12 +39,28 @@ Description using namespace Foam; -Ostream& writeList(Ostream& os, const UList& 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& 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 s) +{ + return printView(os, s.begin(), s.end()); +} + + +Ostream& printView(Ostream& os, const UList& list) +{ + return printView(os, list.begin(), list.end()); +} + + +Ostream& writeList(Ostream& os, const UList& list) +{ + return printView(os, list.begin(), list.end()); +} + + Ostream& toString(Ostream& os, const UList& 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& list) { - os << '"'; - for (const char c : list) - { - os << c; - } - os << '"'; - - return os; + return printString(os, list.data(), list.data() + list.size()); } diff --git a/src/OpenFOAM/db/IOstreams/memory/ICharStream.H b/src/OpenFOAM/db/IOstreams/memory/ICharStream.H index 8751e6b9de..c242b9d08d 100644 --- a/src/OpenFOAM/db/IOstreams/memory/ICharStream.H +++ b/src/OpenFOAM/db/IOstreams/memory/ICharStream.H @@ -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 s) - // : - // icharstream() - // { - // reset(buffer, nbytes); - // } - //- Move construct from List icharstream(List&& buffer) : @@ -143,7 +136,28 @@ public: //- Span of the input characters (is modifiable!) UList list() const { - return buffer_type::span_list(); + return UList + ( + 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& 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 void swap(DynamicList& other) { @@ -175,11 +189,18 @@ public: stream_type::clear(); // Clear old errors } + //- Reset stream and return contents as a List + DynamicList release() + { + DynamicList 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&& buffer, // Fully qualify (issue #1521) + List&& buffer, IOstreamOption streamOpt = IOstreamOption() ) : @@ -296,6 +317,19 @@ public: //- Span of the input characters (is modifiable!) UList 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& other) { stream_.swap(other); syncState(); } - //- Transfer list contents to a DynamicList buffer + //- Exchange stream content and parameter contents, reset positions template void swap(DynamicList& other) { @@ -318,6 +352,14 @@ public: syncState(); } + //- Reset stream and return contents as a List + DynamicList release() + { + DynamicList chars(stream_.release()); + syncState(); + return chars; + } + //- Rewind the stream, clearing any old errors virtual void rewind() override { diff --git a/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H b/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H index 548eeee924..f2debfeb69 100644 --- a/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H +++ b/src/OpenFOAM/db/IOstreams/memory/ISpanStream.H @@ -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(this)) {} - // //- Construct (shallow copy) from span character content - // ispanstream(stdFoam::span s) - // : - // buffer_type(const_cast(s.data()), s.size()), - // stream_type(static_cast(this)) - // {} + #if __cplusplus >= 201703L + //- Construct (shallow copy) from std::string_view content + explicit ispanstream(std::string_view s) + { + buffer_type(const_cast(s.data()), s.size()), + stream_type(static_cast(this)) + } + #endif + + //- Construct (shallow copy) from span character content + explicit ispanstream(stdFoam::span s) + : + buffer_type(const_cast(s.data()), s.size()), + stream_type(static_cast(this)) + {} + + //- Construct (shallow copy) from span character content + explicit ispanstream(stdFoam::span s) + : + buffer_type(const_cast(s.data()), s.size()), + stream_type(static_cast(this)) + {} // Member Functions @@ -149,7 +165,28 @@ public: //- Span of the input characters (is modifiable!) UList list() const { - return buffer_type::span_list(); + return UList + ( + 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& 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 s, + IOstreamOption streamOpt = IOstreamOption() + ) + : + ISpanStream(s.data(), s.size(), streamOpt) + {} + + //- Construct (shallow copy) from span character content + explicit ISpanStream + ( + stdFoam::span 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 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 s) + { + stream_.reset(s.data(), s.size()); + syncState(); + } + + //- Reset input area to use data from span character content + void reset(stdFoam::span s) + { + stream_.reset(s.data(), s.size()); + syncState(); + } + //- Rewind the stream, clearing any old errors virtual void rewind() override { diff --git a/src/OpenFOAM/db/IOstreams/memory/OCharStream.H b/src/OpenFOAM/db/IOstreams/memory/OCharStream.H index 44ed6f294a..9b45472eae 100644 --- a/src/OpenFOAM/db/IOstreams/memory/OCharStream.H +++ b/src/OpenFOAM/db/IOstreams/memory/OCharStream.H @@ -124,12 +124,6 @@ public: buffer_type::reserve(n); } - //- Span of the current output characters (is modifiable!) - UList 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 list() const + { + return UList + ( + 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& 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 void swap(DynamicList& other) { @@ -152,11 +173,18 @@ public: stream_type::clear(); // Clear old errors } + //- Reset buffer and return contents + DynamicList release() + { + DynamicList 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&& 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 explicit OCharStream ( @@ -272,14 +289,27 @@ public: //- Span of the current output characters (is modifiable!) UList 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& other) { stream_.swap(other); syncState(); } - //- Transfer list contents to a DynamicList buffer + //- Exchange stream content and parameter contents, reset positions template void swap(DynamicList& other) { @@ -287,6 +317,14 @@ public: syncState(); } + //- Reset buffer and return contents + DynamicList release() + { + DynamicList chars(stream_.release()); + syncState(); + return chars; + } + //- Rewind the stream, clearing any old errors virtual void rewind() { diff --git a/src/OpenFOAM/db/IOstreams/memory/OSpanStream.H b/src/OpenFOAM/db/IOstreams/memory/OSpanStream.H index f59ee1c453..1903c5a6b6 100644 --- a/src/OpenFOAM/db/IOstreams/memory/OSpanStream.H +++ b/src/OpenFOAM/db/IOstreams/memory/OSpanStream.H @@ -132,13 +132,6 @@ public: stream_type(static_cast(this)) {} - // //- Construct (shallow copy) from span character content - // ospanstream(stdFoam::span s) - // : - // buffer_type(const_cast(s.data()), s.size()), - // stream_type(static_cast(this)) - // {} - // Member Functions @@ -157,7 +150,28 @@ public: //- Span of the current output characters (is modifiable!) UList list() const { - return buffer_type::span_list(); + return UList + ( + 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& 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 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) { diff --git a/src/OpenFOAM/db/IOstreams/memory/memoryStreamBuffer.H b/src/OpenFOAM/db/IOstreams/memory/memoryStreamBuffer.H index be8b31aef9..8de6992f87 100644 --- a/src/OpenFOAM/db/IOstreams/memory/memoryStreamBuffer.H +++ b/src/OpenFOAM/db/IOstreams/memory/memoryStreamBuffer.H @@ -36,10 +36,9 @@ Description #define Foam_memoryStreamBuffer_H #include "stdFoam.H" // For span -#include "UList.H" +#include "DynamicList.H" #include -#include // Possibly want stringstream too... #include // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -208,17 +207,23 @@ public: return (gptr() < egptr()) ? (egptr() - gptr()) : 0; } - //- Span of the input characters (is modifiable!) - UList span_list() const - { - return UList(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 span() const - // { - // return stdFoam::span(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 view() const + { + return stdFoam::span(data_bytes(), size_bytes()); + } + #endif //- Some information about the input buffer position/capacity void info(Ostream& os) const @@ -273,7 +278,7 @@ public: template in_dynamic(::Foam::DynamicList&& 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& other) + //- Exchange buffer content and parameter contents, reset positions + void swap(List& 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 void swap(DynamicList& other) { - List 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 release() + { + DynamicList 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 span_list() const - { - return UList(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 span() const - // { - // return stdFoam::span(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 view() const + { + return stdFoam::span(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& other) + //- Exchange buffer content and parameter contents, reset positions + void swap(List& 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 - inline void swap(DynamicList& other) + void swap(DynamicList& other) { - const auto cur = span_tellp(); // Addressed length - List 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 release() + { + const auto cur = span_tellp(); // Output length + DynamicList chars(std::move(storage_)); + chars.resize(cur); // Restrict to output length + + if (chars.empty()) chars.clearStorage(); // Can destroy now + sync_pbuffer(); + return chars; + } };