From dd136d61acd061bad25c5edc93b7182f446cdeef Mon Sep 17 00:00:00 2001 From: Mark Olesen Date: Wed, 24 Sep 2025 10:36:22 +0200 Subject: [PATCH] ENH: add in-place modification for OCharStream - enables partial overwriting of content - make default construct zero-sized, add reserve_exact() method STYLE: minor adjustments for Enum, IOstreamOption --- applications/test/IStringStream/Make/files | 2 +- ...IStringStream.C => Test-IStringStream.cxx} | 0 .../test/OCharStream1/Test-OCharStream1.cxx | 22 +- applications/test/OCharStream2/Make/files | 3 + applications/test/OCharStream2/Make/options | 2 + .../test/OCharStream2/Test-OCharStream2.cxx | 404 ++++++++++++++++++ applications/test/OStringStream/Make/files | 2 +- ...OStringStream.C => Test-OStringStream.cxx} | 0 applications/test/sha1/Make/files | 2 +- .../test/sha1/{Test-SHA1.C => Test-SHA1.cxx} | 4 + src/OpenFOAM/db/IOstreams/IOstreams/Ostream.H | 2 +- .../db/IOstreams/hashes/OSHA1stream.H | 9 +- .../db/IOstreams/memory/ICharStream.H | 19 +- .../db/IOstreams/memory/ISpanStream.H | 19 +- .../db/IOstreams/memory/OCharStream.H | 146 ++++++- .../db/IOstreams/memory/OSpanStream.H | 141 ++++-- .../db/IOstreams/memory/memoryStreamBuffer.H | 215 ++++++++-- src/OpenFOAM/db/options/IOstreamOption.C | 82 ++-- src/OpenFOAM/db/options/IOstreamOption.H | 8 +- src/OpenFOAM/primitives/enums/Enum.H | 20 +- src/OpenFOAM/primitives/enums/EnumI.H | 30 +- 21 files changed, 938 insertions(+), 194 deletions(-) rename applications/test/IStringStream/{Test-IStringStream.C => Test-IStringStream.cxx} (100%) create mode 100644 applications/test/OCharStream2/Make/files create mode 100644 applications/test/OCharStream2/Make/options create mode 100644 applications/test/OCharStream2/Test-OCharStream2.cxx rename applications/test/OStringStream/{Test-OStringStream.C => Test-OStringStream.cxx} (100%) rename applications/test/sha1/{Test-SHA1.C => Test-SHA1.cxx} (96%) diff --git a/applications/test/IStringStream/Make/files b/applications/test/IStringStream/Make/files index 2f212b0042..7050fdd534 100644 --- a/applications/test/IStringStream/Make/files +++ b/applications/test/IStringStream/Make/files @@ -1,3 +1,3 @@ -Test-IStringStream.C +Test-IStringStream.cxx EXE = $(FOAM_USER_APPBIN)/Test-IStringStream diff --git a/applications/test/IStringStream/Test-IStringStream.C b/applications/test/IStringStream/Test-IStringStream.cxx similarity index 100% rename from applications/test/IStringStream/Test-IStringStream.C rename to applications/test/IStringStream/Test-IStringStream.cxx diff --git a/applications/test/OCharStream1/Test-OCharStream1.cxx b/applications/test/OCharStream1/Test-OCharStream1.cxx index b5def1b8fa..a4f96d2507 100644 --- a/applications/test/OCharStream1/Test-OCharStream1.cxx +++ b/applications/test/OCharStream1/Test-OCharStream1.cxx @@ -111,7 +111,10 @@ template void printInfo(const BufType& buf) { Info<< nl << "=========================" << endl; - buf.print(Info); + if constexpr (std::is_same_v) + { + buf.print(Info); + } Info<< "addr: " << Foam::name(buf.list().cdata()) << nl; toString(Info, buf.list()); Info<< nl << "=========================" << endl; @@ -183,12 +186,25 @@ int main(int argc, char *argv[]) printInfo(obuf); // Overwrite at some position - obuf.stdStream().rdbuf()->pubseekpos(0.60 * obuf.size()); - obuf << "<" << nl << "OVERWRITE" << nl; + if (auto i = obuf.view().find("item5"); i != std::string::npos) + { + // obuf.seek(0.60 * obuf.size()); + obuf.seek(i); + obuf << "" << nl; + } Info<<"after overwrite" << nl; printInfo(obuf); + // Truncate + { + constexpr float fraction = 0.90; + Info<<"truncated at " << (100*fraction) << "% [" + << int(fraction*obuf.size()) << " chars]" << nl; + obuf.seek(fraction*obuf.size()); + printInfo(obuf); + } + Info<< "transfer contents to a List or ICharStream" << nl; // Reclaim data storage from OCharStream -> ICharStream diff --git a/applications/test/OCharStream2/Make/files b/applications/test/OCharStream2/Make/files new file mode 100644 index 0000000000..e2ffcd6203 --- /dev/null +++ b/applications/test/OCharStream2/Make/files @@ -0,0 +1,3 @@ +Test-OCharStream2.cxx + +EXE = $(FOAM_USER_APPBIN)/Test-OCharStream2 diff --git a/applications/test/OCharStream2/Make/options b/applications/test/OCharStream2/Make/options new file mode 100644 index 0000000000..18e6fe47af --- /dev/null +++ b/applications/test/OCharStream2/Make/options @@ -0,0 +1,2 @@ +/* EXE_INC = */ +/* EXE_LIBS = */ diff --git a/applications/test/OCharStream2/Test-OCharStream2.cxx b/applications/test/OCharStream2/Test-OCharStream2.cxx new file mode 100644 index 0000000000..fb785f8d3f --- /dev/null +++ b/applications/test/OCharStream2/Test-OCharStream2.cxx @@ -0,0 +1,404 @@ +/*---------------------------------------------------------------------------*\ + ========= | + \\ / F ield | OpenFOAM: The Open Source CFD Toolbox + \\ / O peration | + \\ / A nd | www.openfoam.com + \\/ M anipulation | +------------------------------------------------------------------------------- + Copyright (C) 2025 OpenCFD Ltd. +------------------------------------------------------------------------------- +License + This file is part of OpenFOAM. + + OpenFOAM is free software: you can redistribute it and/or modify it + under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + OpenFOAM is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + for more details. + + You should have received a copy of the GNU General Public License + along with OpenFOAM. If not, see . + +Description + +\*---------------------------------------------------------------------------*/ + +#include "SpanStream.H" +#include "wordList.H" +#include "IOstreams.H" +#include "argList.H" + +#include +#include +#include +#include + +using namespace Foam; + +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 << label(last-first) << '('; + + for (; first != last; (void)++first) + { + const char c = *first; + + if (isprint(c)) + { + os << c; + } + else if (c == '\t') + { + os << "\\t"; + } + else if (c == '\n') + { + os << "\\n"; + } + else + { + ::snprintf(buf, 4, "%02X", c); + os << "\\x" << buf; + } + } + os << ')'; + + return os; +} + + +Ostream& printView(Ostream& os, std::string_view 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) +{ + return printString(os, list.begin(), list.end()); +} + + +Ostream& toString(Ostream& os, std::string_view s) +{ + return printString(os, s.begin(), s.end()); +} + + +template +void printInfo(const BufType& buf) +{ + Info<< nl << "=========================" << endl; + if constexpr (std::is_same_v) + { + buf.print(Info); + } + Info<< "addr: " << Foam::name(buf.view().data()) << nl; + toString(Info, buf.view()); + Info<< nl << "=========================" << endl; +} + + +template +void leftpad(std::ostream& os, IntType val, char fillch = ' ') +{ + // set fill char and width + os.setf(std::ios_base::left, std::ios_base::adjustfield); + fillch = os.fill(fillch); + os.width(std::numeric_limits::digits10+1); + os << val; + // restore fill char + os.fill(fillch); +} + + +template +void rightpad(std::ostream& os, IntType val, char fillch = ' ') +{ + // set fill char and width + os.setf(std::ios_base::right, std::ios_base::adjustfield); + fillch = os.fill(fillch); + os.width(std::numeric_limits::digits10+1); + os << val; + // restore fill char + os.fill(fillch); +} + + +// Left-padded value with trailing comment slashes +template +void leftpad(ocharstream& os, IntType val) +{ + const auto beg = os.tellp(); + os << val; + int count = (std::numeric_limits::digits10+1) - (os.tellp() - beg); + + // With two spaces before comments + if (count > 0) { os << ' '; --count; } + if (count > 0) { os << ' '; --count; } + for (const char c = (count >= 2 ? '/' : ' '); count > 0; --count) + { + os << c; + } +} + + +// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // +// Main program: + +int main(int argc, char *argv[]) +{ + argList::noParallel(); + argList::addBoolOption("fake-zerosize", "Fake overwriting with zero data"); + argList::addBoolOption("dict-format", "Format as dictionary entry"); + + #include "setRootCase.H" + + const bool optFakeZerosize = args.found("fake-zerosize"); + const bool isDictFormat = args.found("dict-format"); + + // const constexpr int width = (std::numeric_limits