Compare commits

...

34 Commits

Author SHA1 Message Date
775d0b277b ENH: improve OpenFOAM I/O for std::vector container
- input: added support (similar to DynamicList)
- output: redirect through UList output, which enables binary etc

- these changes enable support for broadcast and other parallel IO
  for std::vector

ENH: support SubList of std::vector (entire length)

- allows a 'glue' layer for re-casting std::vector to UList etc
2023-09-27 20:52:49 +02:00
f7dfb02d12 DEFEATURE: remove unused (and partly-broken) SubDimensionedField 2023-09-27 19:37:18 +02:00
a252677618 BUG: Lambda2: reverse the sign of the governing equation (fixes #2731) 2023-09-27 17:09:13 +01:00
99f5d9a7db BUG: overset: correct sizing. Fixes #2985. 2023-09-18 18:12:37 +01:00
133149a1dd ENH: snappyHexMesh: mutliple inside points. Fixes #2981 2023-09-14 16:12:53 +01:00
6396256522 BUG: cyclicAMI: operate on copy. Fixes #2980
also
- steal nbr value
- do not copy nbr value if different internalfield
2023-09-14 15:10:15 +01:00
5d98eec6af ENH: re-toggle warnings in functionObjectList execution (#2973)
- when running with "errors warn;" it will reset the warnings counter
  (if any) when it returns to a good state.
  This re-enables un-suppressed warnings for the next cycle.
  Also reset the warnings counter on end().

ENH: add short-circuit in HashTable::erase(key)

- skip and return false if the table is empty or the key is not found.
  This makes for faster no-op behaviour.
2023-09-06 10:19:38 +02:00
2d76514b5b Merge branch 'issue-2966-errorhandling' into 'develop'
ENH: add error handling for empty surfaces in surfaceFieldValue (#2966)

See merge request Development/openfoam!627
2023-09-05 15:37:33 +00:00
2e3f0811a0 ENH: error handling for empty surfaces in surfaceFieldValue (#2966)
- for workflows with appearing/disappearing patches (for example)
  can specify that empty surfaces should be ignored or warned about
  instead of raising a FatalError.

  Note that this handling is additional to the regular top-level
  "errors" specification. So specifying 'strict' will only actually
  result in a FatalError if the "errors" does not trap errors.

- "ignore" : any empty surfaces are simply ignored and no
  file output (besides the header).

- "warn" : empty surfaces are warned about a few times (10)
  and the file output contains a NaN entry

- "strict" : corresponds to the default behaviour.
  Throws a FatalError if the surface is empty.
  This error may still be caught by the top-level "errors" handling.
2023-09-05 15:36:53 +00:00
ff2abdf1f0 ENH: relocate functionObjectList errorHandling types to error (#2966)
- was previously private within functionObjectList, now exposed from
  error as 'handlerTypes' and 'handlerNames' enumeration.
2023-09-05 15:36:53 +00:00
f49403969e Merge branch 'extend-list-functionality' into 'develop'
Add SubList re-slicing, find within a List sub-section, uniformity enumeration

See merge request Development/openfoam!626
2023-09-05 15:36:17 +00:00
2e8e259217 CONFIG: increment API level to 2307 2023-09-05 10:15:57 +02:00
0250a1b0bb ENH: support List sub-slice searching, use std::find()
- support UList shallowCopy with pointer/size
  (eg, for slicing into or from span)

ENH: add SubList::reset() functionality

- allows modification of a SubList after construction.
  Previously a SubList had an immutable location after construction
  and there was no way to shift or change its location.

BUG: missed special handling for DynamicList<char>::readList (fixes #2974)

- equivalent to List<char>::readList, in which the stream is
  temporarily toggled from ASCII to BINARY when reading in a List of
  char data.
  This specialization was missed when DynamicList<T>::readList() was
  fully implemented.
2023-09-05 10:15:17 +02:00
aa1b6d9cbd ENH: add ListPolicy uniformity enumeration and algorithm
- defines values for EMPTY, UNIFORM, NONUNIFORM and MIXED
  that allow bitwise OR reduction and provide an algorithm
  for calculating uniformity

ENH: consolidate more efficient uniformity checks in PackedList

ENH: improve linebreak handling when outputting small matrices
2023-09-04 14:40:33 +02:00
df6de6ed33 CONFIG: runParallel with --oversubscribe for openmpi
- not always required, but useful when running some tutorials locally
2023-09-04 14:24:13 +02:00
f800ccc3d9 Merge branch 'update-memory-streams' into 'develop'
update and enhancements for memory-based streams

See merge request Development/openfoam!624
2023-09-01 14:44:56 +00:00
459aaad0f9 ENH: improve robustness of raw reading, file size checks
- use ignore instead of seekg/tellg to swallow input (robuster)

- check for bad gcount() values

- wrap Foam::fileSize() compressed/uncompressed handling into IFstream.

- improve handling of compressed files in masterUncollatedFileOperation.
  Previously read into a string via stream iterators.
  Now read chunk-wise into a List of char for fewer reallocations.
2023-09-01 14:44:49 +00:00
a341d09afc ENH: update and enhancement of memory-streams
- soft renames (ie, old names still available via typedefs) for more
  reasonable names and more coverage with std stream variants.

  The old names could be a bit cryptic.
  For example, uiliststream (== an unallocated/external list storage),
  which is written as std::ispanstream for C++23.

  Could similarly argue that IListStream is better named as
  ICharStream, since it is an input stream of characters and the
  internal storage mechanism (List or something else) is mostly
  irrelevant.

  Extending the coverage to include all std stream variants, and
  simply rewrap them for OpenFOAM IOstream types. This simplifies the
  inheritance patterns and allows reuse of icharstream/ocharstream as
  a drop-in replace for istringstream/ostringstream in other wrappers.

  Classes:
    * icharstream / ICharStream   [old: none / IListStream]
    * ocharstream / OCharStream   [old: none / OListStream]
    * ispanstream / ISpanStream   [old: uiliststream / UIListStream]
    * ospanstream / OSpanStream   [old: none / UOListStream]

  Possible new uses : read file contents into a buffer, broadcast
  buffer contents to other ranks and then transfer into an icharstream
  to be read from. This avoid the multiple intermediate copies that
  would be associated when using an istringstream.

- Use size doubling instead of block-wise incremental for ocharstream
  (OCharStream). This corresponds to the sizing behaviour as per
  std::stringstream (according to gcc-11 includes)

STYLE: drop Foam_IOstream_extras constructors for memory streams

- transitional/legacy constructors but not used in any code
2023-09-01 14:44:49 +00:00
6d7e67408e BUG: snappyHexMesh: correct oppositeness checking. Fixes #2971 2023-08-31 14:06:02 +01:00
d8f5714d1b Merge branch 'feature-nonblocking-cyclicAMI' into 'develop'
Support non-blocking construction of cyclic AMI

See merge request Development/openfoam!623
2023-08-30 15:52:01 +00:00
69169c5abe ENH: add non-blocking handling for cyclicAMI (#2963)
Co-authored-by: Mark Olesen <>
2023-08-30 13:39:16 +00:00
539d538d5a ENH: mapDistribute consistency improvements
- nonBlocking: receive before send

- nonBlocking: wait for receive requests, process and then wait for
  other requests. Can be extended to use polling...

- the 'fake' send (to self) now send copies into recv buffers instead
  of send buffers.
  This provides a clear separation of send and receive fields

- avoid unnecessary reallocations with PtrList of send/recv buffers

- remove outer looping for accessAndFlip and pass target field
  as parameter for inner looping instead

ENH: refine mapDistribute send/recv requests handling

- separate send/recv requests for finer control
- receive does not need access to PtrList of sendBuffers, since the
  send-to-self now uses the recvBuffers
2023-08-30 13:39:16 +00:00
c09acbb781 ENH: avoid list resizing when reindexing AMIInterpolation::append (#2933)
- create reindexing values as interleaved identity maps directly into
  the remapping lookup.
2023-08-30 13:39:16 +00:00
b931772369 ENH: mapDistribute subMapTotalSize(), constructMapTotalSize()
- the sum of the respective list sizes

COMP: add noexcept to trivial mapDistribute constructors
2023-08-30 13:39:16 +00:00
750d9084d4 ENH: improve addressing into labelRanges (#2933)
- totalSize() returns retrieve the linear (total) size
  (naming as per globalIndex)
- operator[] retrieves the referenced value (linear indexing)
- labels() returns a flattened labelList (as per labelRange itself)
2023-08-30 13:39:16 +00:00
6defeddbff BUG: mapFields: incorrect patches. Fixes #2944. 2023-08-30 11:46:25 +01:00
9d291ab4cc ENH: add Pstream::broadcastList()
- broadcasts list contiguous content as a two-step process:
    1. broadcast the size, and resize for receiver list
    2. broadcast contiguous contents (if non-empty)

  This avoids serialization/de-serialization memory overhead but at
  the expense of an additional broadcast call.
  The trade-off of the extra broadcast of the size will be less
  important than avoiding a memory peak for large contiguous mesh data.

REVERT: unstable MPI_Mprobe/MPI_Mrecv on intelmpi + PMI-2 (#2796)

- partial revert of commit c6f528588b, for NBX implementation.
  Not yet flagged as causing errors here, but eliminated for
  consistency.
2023-08-29 11:24:16 +02:00
0e11f47f74 STYLE: prefer emplace_back() to append() + last() 2023-08-29 11:24:16 +02:00
698e05eeb3 STYLE: prefer push_uniq() to appendUniq
- more consistency with push_back etc.
2023-08-29 11:24:16 +02:00
2395e493d1 ENH: simplify add/remove patch/zone groups
STYLE: reuse polyBoundaryMesh patchSizes(), patchStarts()
2023-08-29 11:24:16 +02:00
12916cd7a3 ENH: additional fstream pointer constructors with IOstreamOption
- allow future tweaking based on the target stream format.

- add ifstreamPointer::open().
  Allows default construct followed by open()
2023-08-29 11:24:13 +02:00
b66369fb37 ENH: add sigFpe::fillNan(char* buf, size_t count)
- simplifies use with other allocators (eg, memory pools).
  Can also be used with other containers.

  vectorField fld = ...;
  sigFpe::fillNan(fld.data_bytes(), fld.size_bytes());

COMP: inline sigFpe::ignore helper class

- now unused (may be removed in the future), but can avoid compiling
  code for it

COMP: missing sigStopAtWriteNow() definition for MSwindows
2023-08-29 10:01:41 +02:00
b236e1493c SUBMODULE: compilation fix for visualization 2023-08-28 18:11:44 +02:00
a6744d0814 ENH: add is_range test to pTraits
- helps support algorithms with list-based forwarding
2023-08-28 15:50:32 +02:00
201 changed files with 7981 additions and 5012 deletions

View File

@ -1,2 +1,2 @@
api=2306
api=2307
patch=0

View File

@ -0,0 +1,3 @@
Test-ICharStream1.C
EXE = $(FOAM_USER_APPBIN)/Test-ICharStream1

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2018 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,14 +27,46 @@ Description
\*---------------------------------------------------------------------------*/
#include "ListStream.H"
#include "UListStream.H"
#include "SpanStream.H"
#include "wordList.H"
#include "IOstreams.H"
#include "argList.H"
#include <cctype>
#include <cstdio>
using namespace Foam;
Ostream& writeList(Ostream& os, const UList<char>& list)
{
char buf[4];
os << list.size() << '(';
for (const char c : list)
{
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& toString(Ostream& os, const UList<char>& list)
{
os << '"';
@ -93,7 +125,7 @@ int main(int argc, char *argv[])
// Buffer storage
DynamicList<char> storage(16);
OListStream obuf(std::move(storage));
OCharStream obuf(std::move(storage));
obuf << 1002 << " " << "abcd" << " " << "def" << " " << 3.14159 << ";\n";
// Move contents to output buffer
@ -104,9 +136,9 @@ int main(int argc, char *argv[])
Info<< "transfer contents to a List" << endl;
IListStream ibuf;
ICharStream ibuf;
// Reclaim data storage from OListStream -> IListStream
// Reclaim data storage from OCharStream -> ICharStream
{
List<char> data;
obuf.swap(data);
@ -161,6 +193,43 @@ int main(int argc, char *argv[])
Info<<nl << "swapped out:";
printInfo(newvalues);
{
iliststream is(std::move(newvalues));
char c = 0;
Info<< nl
<< "getting values from iliststream of "
<< is.list() << endl;
// Info<< " (" << is.tellg() << " " << is.remaining() << ")";
// Info<< "get:";
while (is.get(c))
{
Info<< ' ' << c;
// Info<< " (" << is.tellg() << " " << is.remaining() << ")";
}
Info<< " - end" << nl;
// Info<< "remaining: " << is.list() << endl;
// Info<< "remaining: " << is.remaining() << endl;
// Manipulate the list view
{
UList<char> chars(is.list());
Foam::reverse(chars);
}
is.rewind();
Info<< "get:";
while (is.get(c))
{
Info<< ' ' << c;
}
Info<< " - end" << nl;
}
Info<< "\nEnd\n" << endl;
return 0;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,6 +33,7 @@ Description
#include "argList.H"
#include "Fstream.H"
#include "OSspecific.H"
#include "etcFiles.H"
using namespace Foam;
@ -44,11 +45,14 @@ int main(int argc, char *argv[])
{
argList::noBanner();
argList::noParallel();
argList::noParallel();
argList::addOption("ignore", "file", "Test readRaw with ignore");
#include "setRootCase.H"
// Test with etc/controlDict (mandatory, from distribution)
if (!args.found("ignore"))
{
const fileName inputFile
(
@ -97,6 +101,43 @@ int main(int argc, char *argv[])
}
}
fileName testFile;
if (args.readIfPresent("ignore", testFile))
{
if (testFile.has_ext("gz"))
{
testFile.remove_ext();
Info<< "stripping extraneous .gz ending" << endl;
}
IFstream is(testFile);
auto& stdStream = is.stdStream();
List<char> buffer(1000);
Info<< "Test readRaw with: " << is.name()
<< " compressed:" << int(is.compression())
<< " file-size:" << is.fileSize() << nl;
for (int iter = 0; is.good() && iter < 1000; ++iter)
{
Info<< "iter:" << iter;
if (iter % 2)
{
Info<< " [read] ";
is.readRaw(buffer.data(), buffer.size());
}
else
{
Info<< " [ignore]";
is.readRaw(nullptr, buffer.size() / 2);
}
Info<< " : " << stdStream.gcount() << endl;
}
}
Info<< "\nEnd\n" << endl;
return 0;
}

View File

@ -1,3 +0,0 @@
Test-IListStream.C
EXE = $(FOAM_USER_APPBIN)/Test-IListStream

View File

@ -28,8 +28,6 @@ Description
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "ListStream.H"
#include "UListStream.H"
#include "wordList.H"
#include "IOstreams.H"
#include "argList.H"

View File

@ -183,9 +183,7 @@ int main(int argc, char *argv[])
Pout<<"recv: " << flatOutput(recv) << endl;
}
// MPI barrier
bool barrier = true;
Pstream::broadcast(barrier);
UPstream::barrier(UPstream::worldComm);
}

View File

@ -0,0 +1,3 @@
Test-OCharStream1.C
EXE = $(FOAM_USER_APPBIN)/Test-OCharStream1

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,13 +27,46 @@ Description
\*---------------------------------------------------------------------------*/
#include "ListStream.H"
#include "SpanStream.H"
#include "wordList.H"
#include "IOstreams.H"
#include "argList.H"
#include <cctype>
#include <cstdio>
using namespace Foam;
Ostream& writeList(Ostream& os, const UList<char>& list)
{
char buf[4];
os << list.size() << '(';
for (const char c : list)
{
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& toString(Ostream& os, const UList<char>& list)
{
os << '"';
@ -91,12 +124,12 @@ void outputDict(OS& os)
int main(int argc, char *argv[])
{
#include "setRootCase.H"
// Buffer storage
DynamicList<char> storage(16);
OListStream obuf(std::move(storage));
obuf.setBlockSize(100);
OCharStream obuf(std::move(storage));
printInfo(obuf);
@ -140,10 +173,10 @@ int main(int argc, char *argv[])
Info<<"after overwrite" << nl;
printInfo(obuf);
Info<< "transfer contents to a List or IListStream" << nl;
Info<< "transfer contents to a List or ICharStream" << nl;
IListStream ibuf;
// Reclaim data storage from OListStream -> IListStream
ICharStream ibuf;
// Reclaim data storage from OCharStream -> ICharStream
{
List<char> data;
obuf.swap(data);
@ -169,7 +202,7 @@ int main(int argc, char *argv[])
Info<<"input:";
toString(Info, list) << endl;
OListStream buf1(std::move(list));
OCharStream buf1(std::move(list));
Info<<"orig:";
toString(Info, list) << endl;
@ -204,7 +237,7 @@ int main(int argc, char *argv[])
Info<< nl << "Test dictionary" << nl;
{
OListStream os1;
OCharStream os1;
outputDict(os1);
@ -213,7 +246,7 @@ int main(int argc, char *argv[])
}
{
OListStream os2;
OCharStream os2;
os2.indentSize(0);
outputDict(os2);

View File

@ -74,7 +74,7 @@ int main(int argc, char *argv[])
Info<< "counter state: " << (cnt.stdStream().rdstate()) << nl
<< "via string-stream: " << str.str().size() << " chars" << nl
<< "via ocountstream: " << plain.size() << " chars" << endl;
<< "via ocountstream: " << plain.count() << " chars" << endl;
fileName outputName;
args.readIfPresent("write", outputName);

View File

@ -1,3 +0,0 @@
Test-OListStream.C
EXE = $(FOAM_USER_APPBIN)/Test-OListStream

View File

@ -0,0 +1,3 @@
Test-SpanStream1.C
EXE = $(FOAM_USER_APPBIN)/Test-SpanStream1

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2018 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,16 +27,48 @@ Description
\*---------------------------------------------------------------------------*/
#include "UListStream.H"
#include "SpanStream.H"
#include "wordList.H"
#include "IOstreams.H"
#include "argList.H"
#include <cctype>
#include <cstdio>
#include <sstream>
#include <vector>
using namespace Foam;
Ostream& writeList(Ostream& os, const UList<char>& list)
{
char buf[4];
os << list.size() << '(';
for (const char c : list)
{
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& toString(Ostream& os, const UList<char>& list)
{
os << '"';
@ -108,7 +140,7 @@ int main(int argc, char *argv[])
// Buffer storage
DynamicList<char> storage(1000);
UOListStream obuf(storage);
OSpanStream obuf(storage);
obuf << 1002 << "\n" << "abcd" << "\n" << "def" << "\n" << 3.14159 << ";\n";
obuf.print(Info);
@ -120,7 +152,7 @@ int main(int argc, char *argv[])
// Attach input buffer - could also do without previous resize
{
UIListStream ibuf(storage);
ISpanStream ibuf(storage);
printTokens(ibuf);
@ -135,13 +167,21 @@ int main(int argc, char *argv[])
{
Info<< "parse as std::istream\n";
uiliststream is(storage.cdata(), storage.size());
ispanstream is(storage.cdata(), storage.size());
Info<< "input: ";
writeList(Info, is.list()) << endl;
Info<< "where: " << is.tellg() << endl;
Info<< "capacity: " << is.capacity() << endl;
Info<< "total: " << is.capacity() << endl;
string tok;
while (std::getline(is, tok))
{
std::cerr << "tok: " << tok << nl;
Info<< "where: " << is.tellg() << endl;
}
Info<< nl << "Repeat..." << endl;
@ -170,7 +210,7 @@ int main(int argc, char *argv[])
toString(Info, chars);
Info<< "----" << nl;
uiliststream is(chars.data(), chars.size());
ispanstream is(chars.data(), chars.size());
string tok;
std::cerr<< nl << "Parsed..." << nl;
while (std::getline(is, tok))

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -37,6 +37,7 @@ Description
#include "scalarField.H"
#include "SubField.H"
#include "labelRange.H"
#include "ListOps.H"
#include <numeric>
using namespace Foam;
@ -57,26 +58,26 @@ int main(int argc, char *argv[])
argList::noFunctionObjects();
{
List<scalar> ident(25);
List<label> ident(25);
std::iota(ident.begin(), ident.end(), 0);
print(ident);
SubList<scalar>(ident, 10) = -10;
SubList<label>(ident, 10) = -10;
print(ident);
SubField<scalar>(ident, 10) = 10;
SubField<label>(ident, 10) = 10;
print(ident);
SubField<scalar>(ident, 10) += 10;
SubField<label>(ident, 10) += 10;
print(ident);
SubField<scalar>{ident, 10, 10} *= 5;
SubField<label>{ident, 10, 10} *= 5;
print(ident);
// NOTE: Need {} instead of ()
// SubList<scalar>(ident) = 100;
// SubList<label>(ident) = 100;
// GCC
// error: conflicting declaration 'Foam::SubList<double> ident'
@ -85,7 +86,30 @@ int main(int argc, char *argv[])
// warning: parentheses were disambiguated as redundant parentheses
// around declaration of variable named 'ident' [-Wvexing-parse]
SubList<scalar>{ident} = 100;
SubList<label>{ident} = 100;
print(ident);
SubList<label> sub(ident);
sub = 1;
print(sub);
sub.reset(ident, labelRange(4, 5)) = 5;
print(sub);
print(ident);
sub.reset(ident, labelRange(14, 5)) = 15;
print(sub);
print(ident);
// Cryptic, probably not a great idea to write this
sub.reset(ident, {20, 3}) = -1;
print(sub);
print(ident);
// This is also possible since we hold a concrete pointer/size
// and not an intermediate
ListOps::identity(sub.reset(ident, 8, 8));
print(sub);
print(ident);
}

View File

@ -1,3 +0,0 @@
Test-UIListStream.C
EXE = $(FOAM_USER_APPBIN)/Test-UIListStream

View File

@ -204,7 +204,7 @@ int main(int argc, char *argv[])
labelPair inOut;
pointField allCcs(globalNumbering.gather(mesh.cellCentres()));
inOut[0] = allCcs.size();
Pstream::broadcast(allCcs);
Pstream::broadcastList(allCcs);
inOut[1] = allCcs.size();
Pout<< " " << inOut << endl;

View File

@ -68,25 +68,51 @@ int main(int argc, char *argv[])
labelRange::debug = 1;
}
Info<< nl;
{
labelRange range(5, 10);
Info<< "identity: " << identity(range) << nl;
}
{
Info<<"test sorting" << endl;
DynamicList<labelRange> list1(10);
Info<< "test sorting" << endl;
labelRanges list1(10);
list1.emplace_back(25, 8);
list1.emplace_back(8);
list1.emplace_back(15, 5);
list1.emplace_back(50, -10, true);
sort(list1);
Info<<"sorted" << list1 << endl;
// Move construct
labelRanges ranges(std::move(list1));
if (!list1.empty())
{
Info<< "Move construct failed? "
<< flatOutput(list1.ranges()) << nl;
}
Info<< "unsorted: ";
ranges.writeList(Info) << nl;
ranges.sort();
Info<< "sorted: ";
ranges.writeList(Info) << nl;
Info<< nl
<< "list linear length = " << ranges.totalSize() << nl;
Info<< "list labels = ";
ranges.labels().writeList(Info) << nl;
Info<< nl;
for (int i : { -1, 0, 5, 8, 10, 20, 26 })
{
Info<< "value at [" << i << "] = " << ranges[i] << nl;
}
}
{
Info<<"test intersections" << endl;
Info<< "test intersections" << endl;
labelRange range1(-15, 25);
labelRange range2(7, 8);
labelRange range3(-20, 8);

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2022 OpenCFD Ltd.
Copyright (C) 2022-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -75,6 +75,16 @@ void testBroadcast(List<T>& values)
}
template<class T>
void testBroadcast(std::vector<T>& values)
{
Info<< nl << "is_contiguous:" << is_contiguous<T>::value << endl;
Pout<< "pre-broadcast: " << flatOutput(values) << endl;
Pstream::broadcast(values);
Pout<< "post-broadcast: " << flatOutput(values) << endl;
}
void testBroadcast(bitSet& values)
{
Pout<< "pre-broadcast: "
@ -135,6 +145,20 @@ int main(int argc, char *argv[])
testBroadcast(values);
}
{
std::vector<word> values;
if (Pstream::master())
{
values.resize(UPstream::nProcs());
for (decltype(values.size()) i=0; i < values.size(); ++i)
{
values[i] = "vector_" + Foam::name(i);
}
}
testBroadcast(values);
}
{
vector values(vector::uniform(-1));
if (Pstream::master())

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,7 +33,7 @@ Description
#include "scalar.H"
#include "FlatOutput.H"
#include "ListStream.H"
#include "SpanStream.H"
#include "StringStream.H"
#include "NASCore.H"
#include "parsing.H"
@ -443,22 +443,22 @@ int main(int argc, char *argv[])
<< " read " << sizeof(scalar) << nl;
List<otherType> srcList(15);
forAll(srcList, i)
{
srcList[i] = 1 + 10*i;
}
DynamicList<char> buf;
OListStream os(std::move(buf), IOstreamOption::BINARY);
OCharStream os(IOstreamOption::BINARY);
os << srcList;
os.swap(buf); // Recover buffer
DynamicList<char> buf;
os.swap(buf); // Recover written contents
// Read back
List<scalar> dstList;
UIListStream is(buf, IOstreamOption::BINARY);
ISpanStream is(buf, IOstreamOption::BINARY);
is.setScalarByteSize(sizeof(otherType));
Info<< "Stream scalar-size ("

View File

@ -0,0 +1,3 @@
Test-readBroadcast1.C
EXE = $(FOAM_USER_APPBIN)/Test-readBroadcast1

View File

@ -0,0 +1,2 @@
/* EXE_INC = */
/* EXE_LIBS = */

View File

@ -0,0 +1,297 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2023 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 <http://www.gnu.org/licenses/>.
Description
Test file reading with broadcast
\*---------------------------------------------------------------------------*/
#include "argList.H"
#include "OSspecific.H" // For fileSize()
#include "Fstream.H"
#include "Pstream.H"
#include "SpanStream.H"
#include <limits>
using namespace Foam;
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
bool optUseSeek = false;
bool optVerbose = false;
// Get file contents. Usually master-only and broadcast
static List<char> slurpFile
(
const fileName& pathname,
const bool parallel = UPstream::parRun(),
const bool masterOnly = true
)
{
Info<< "slurp master-only:" << masterOnly
<< " broadcast:" << (masterOnly && parallel)
<< " seek:" << optUseSeek
<< " file: " << pathname << nl;
if (optUseSeek)
{
Info<< "Rewinding gzstream does not work..." << nl;
}
// -------------------------
List<char> buffer;
ifstreamPointer ifp;
if (UPstream::master() || !masterOnly)
{
ifp.open(pathname);
}
if (ifp && ifp->good())
{
Info<< "compressed:"
<< (IOstreamOption::COMPRESSED == ifp.whichCompression()) << nl;
#if 0
uint64_t inputSize = Foam::fileSize(pathname);
if (IOstreamOption::COMPRESSED == ifp.whichCompression())
{
ifp->ignore(std::numeric_limits<std::streamsize>::max());
const std::streamsize nread = ifp->gcount();
if (nread == std::numeric_limits<std::streamsize>::max())
{
FatalErrorInFunction
<< "Failed call to ignore()" << nl
<< exit(FatalError);
}
inputSize = ifp->gcount();
if (optUseSeek)
{
// Rewinding gzstream does not really work...
ifp->rdbuf()->pubseekpos(0, std::ios_base::in);
}
else
{
// Open it again - gzstream rewinding is unreliable...
ifp.open(pathname);
}
}
buffer.resize(label(inputSize));
ifp->read(buffer.data(), buffer.size_bytes());
const std::streamsize nread = ifp->gcount();
if (nread == std::numeric_limits<std::streamsize>::max())
{
FatalErrorInFunction
<< "Failed call to read()" << nl
<< exit(FatalError);
}
buffer.resize(label(nread)); // Extra safety (paranoid)
#else
if (IOstreamOption::COMPRESSED == ifp.whichCompression())
{
// For compressed files we do not have any idea how large
// the result will be. So read chunk-wise.
// Using the compressed size for the chunk size:
// 50% compression = 2 iterations
// 66% compression = 3 iterations
// ...
const auto inputSize = Foam::fileSize(pathname + ".gz");
const uint64_t chunkSize =
(
(inputSize <= 1024)
? uint64_t(4096)
: uint64_t(2*inputSize)
);
uint64_t beg = 0;
bool normalExit = false;
for (int iter = 1; iter < 100000; ++iter)
{
if (optVerbose)
{
Info<< "iter " << iter << nl;
Info<< "chunk " << label(chunkSize) << nl;
Info<< "size " << label(iter * chunkSize) << nl;
}
buffer.resize(label(iter * chunkSize));
ifp->read(buffer.data() + beg, chunkSize);
const std::streamsize nread = ifp->gcount();
if (optVerbose)
{
Info<< "nread: " << nread << nl;
}
if
(
nread < 0
|| nread == std::numeric_limits<std::streamsize>::max()
)
{
if (iter == 0)
{
FatalErrorInFunction
<< "Failed call to read()" << nl
<< exit(FatalError);
}
break;
}
else
{
beg += uint64_t(nread);
if (nread >= 0 && uint64_t(nread) < chunkSize)
{
normalExit = true;
if (optVerbose)
{
Info<< "stopped after "
<< iter << " iterations" << nl;
}
buffer.resize(label(beg));
break;
}
}
}
if (!normalExit)
{
FatalErrorInFunction
<< "Abnormal exit" << nl
<< exit(FatalError);
}
}
else
{
const auto inputSize = Foam::fileSize(pathname);
if (inputSize >= 0)
{
buffer.resize(label(inputSize));
ifp->read(buffer.data(), buffer.size_bytes());
const std::streamsize nread = ifp->gcount();
if
(
nread < 0
|| nread == std::numeric_limits<std::streamsize>::max()
)
{
FatalErrorInFunction
<< "Failed call to read()" << nl
<< exit(FatalError);
}
buffer.resize(label(nread)); // Extra safety (paranoid)
}
}
#endif
}
// Done with input file
ifp.reset(nullptr);
if (parallel && masterOnly)
{
// On the assumption of larger files,
// prefer two broadcasts instead of serialization
Pstream::broadcastList(buffer);
}
return buffer;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
// Main program:
int main(int argc, char *argv[])
{
argList::noBanner();
argList::noFunctionObjects();
argList::noCheckProcessorDirectories();
argList::addBoolOption("seek", "seek with gzstream (fails!)");
argList::addVerboseOption("addition information");
argList::addBoolOption("seek", "seek with gzstream");
argList::addBoolOption("no-broadcast", "suppress broadcast contents");
argList::addNote("Test master-only reading (with broadcast)");
argList::addArgument("srcFile");
#include "setRootCase.H"
const bool syncPar = (UPstream::parRun() && !args.found("no-broadcast"));
optUseSeek = args.found("seek");
optVerbose = args.verbose();
auto srcName = args.get<fileName>(1);
if (srcName.has_ext("gz"))
{
srcName.remove_ext();
Info<< "stripping extraneous .gz ending" << endl;
}
ICharStream is;
{
List<char> buffer(slurpFile(srcName, syncPar));
is.swap(buffer);
}
Pout<< "input:" << is.capacity() << endl;
for (string line; is.getLine(line); /*nil*/)
{
Pout<< "L:" << is.lineNumber() << ": " << line.c_str() << nl;
}
Info<< "\nEnd\n" << endl;
return 0;
}
// ************************************************************************* //

View File

@ -51,13 +51,30 @@ int main(int argc, char *argv[])
hmm.source()[1] = vector(1.0, 4.0, 3.0);
hmm.source()[2] = vector(0.0, 5.0, 2.0);
Info<< hmm << endl;
Info<< hmm.solve() << endl;
Info<< hmm << endl;
Info<< hmm.LUsolve() << endl;
Info<< hmm << endl;
Info<< hmm << nl;
Info<< hmm.solve() << nl;
Info<< hmm << nl;
Info<< hmm.LUsolve() << nl;
Info<< hmm << nl;
Info<< "End\n" << endl;
{
scalarSquareMatrix mat0;
Info<< "empty: " << mat0 << endl;
mat0.resize_nocopy(1);
mat0 = Identity<scalar>();
Info<< "ident (1x1): " << mat0 << endl;
mat0.resize_nocopy(3);
mat0 = Identity<scalar>();
Info<< "ident (3x3): " << mat0 << endl;
mat0.resize_nocopy(5);
mat0 = Identity<scalar>();
Info<< "ident (5x5): " << mat0 << endl;
}
Info<< "\nEnd\n" << endl;
return 0;
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -47,7 +47,7 @@ Description
#include "Time.H"
#include "polyMesh.H"
#include "cellSet.H"
#include "SortableList.H"
#include "SortList.H"
#include "labelIOList.H"
#include "fvMesh.H"
#include "volFields.H"
@ -128,71 +128,54 @@ int main(int argc, char *argv[])
const scalarField& vols = mesh.cellVolumes();
SortableList<scalar> sortedVols(vols);
SortList<scalar> sortedVols(vols);
// All cell labels, sorted per bin.
DynamicList<DynamicList<label>> bins;
// Lower/upper limits
DynamicList<scalar> lowerLimits;
DynamicList<scalar> upperLimits;
DynamicList<scalarMinMax> limits;
// Create bin0. Have upperlimit as factor times lowerlimit.
bins.append(DynamicList<label>());
lowerLimits.append(sortedVols[0]);
upperLimits.append(1.1 * lowerLimits.last());
bins.emplace_back();
limits.emplace_back(sortedVols[0], 1.1*sortedVols[0]);
forAll(sortedVols, i)
{
if (sortedVols[i] > upperLimits.last())
if (sortedVols[i] > limits.back().max())
{
// New value outside of current bin
// Shrink old bin.
DynamicList<label>& bin = bins.last();
bin.shrink();
Info<< "Collected " << bin.size() << " elements in bin "
<< lowerLimits.last() << " .. "
<< upperLimits.last() << endl;
Info<< "Collected " << bins.back() << " elements in bin "
<< limits.back().min() << " .. "
<< limits.back().max() << endl;
// Create new bin.
bins.append(DynamicList<label>());
lowerLimits.append(sortedVols[i]);
upperLimits.append(1.1 * lowerLimits.last());
bins.emplace_back();
limits.emplace_back(sortedVols[i], 1.1 * sortedVols[i]);
Info<< "Creating new bin " << lowerLimits.last()
<< " .. " << upperLimits.last()
<< endl;
Info<< "Creating new bin "
<< limits.back().min() << " .. "
<< limits.back().max() << endl;
}
// Append to current bin.
DynamicList<label>& bin = bins.last();
bin.append(sortedVols.indices()[i]);
// Add to current bin.
bins.back().push_back(sortedVols.indices()[i]);
}
Info<< endl;
bins.last().shrink();
bins.shrink();
lowerLimits.shrink();
upperLimits.shrink();
//
// Write to cellSets.
//
Info<< "Volume bins:" << nl;
forAll(bins, binI)
forAll(bins, bini)
{
const DynamicList<label>& bin = bins[binI];
const auto& bin = bins[bini];
cellSet cells(mesh, "vol" + name(binI), bin.size());
cellSet cells(mesh, "vol" + Foam::name(bini), bin.size());
cells.insert(bin);
Info<< " " << lowerLimits[binI] << " .. " << upperLimits[binI]
Info<< " " << limits[bini].min() << " .. " << limits[bini].max()
<< " : writing " << bin.size() << " cells to cellSet "
<< cells.name() << endl;
@ -294,13 +277,13 @@ int main(int argc, char *argv[])
);
// Set cell values
forAll(bins, binI)
forAll(bins, bini)
{
const DynamicList<label>& bin = bins[binI];
const auto& bin = bins[bini];
forAll(bin, i)
{
refLevel[bin[i]] = bins.size() - binI - 1;
refLevel[bin[i]] = bins.size() - bini - 1;
postRefLevel[bin[i]] = refLevel[bin[i]];
}
}

View File

@ -468,8 +468,8 @@ inline Foam::List<Foam::label> Foam::conformalVoronoiMesh::processorsAttached
forAll(c1Procs, aPI)
{
procsAttached.appendUniq(c1Procs[aPI]);
procsAttached.appendUniq(c2Procs[aPI]);
procsAttached.push_uniq(c1Procs[aPI]);
procsAttached.push_uniq(c2Procs[aPI]);
}
return List<label>(procsAttached);

View File

@ -46,8 +46,8 @@ void Foam::shortEdgeFilter2D::assignBoundaryPointRegions
const edge& e = iter.key();
const label regi = iter.val();
boundaryPointRegions[e.start()].appendUniq(regi);
boundaryPointRegions[e.end()].appendUniq(regi);
boundaryPointRegions[e.first()].push_uniq(regi);
boundaryPointRegions[e.second()].push_uniq(regi);
}
}
@ -66,7 +66,7 @@ void Foam::shortEdgeFilter2D::updateEdgeRegionMap
const edgeList& edges = surfMesh.edges();
const labelList& meshPoints = surfMesh.meshPoints();
patchSizes.setSize(patchNames_.size(), 0);
patchSizes.resize_nocopy(patchNames_.size());
patchSizes = 0;
forAll(edges, edgeI)
@ -78,15 +78,13 @@ void Foam::shortEdgeFilter2D::updateEdgeRegionMap
const edge& e = edges[edgeI];
const label startI = meshPoints[e[0]];
const label endI = meshPoints[e[1]];
label region = -1;
const DynamicList<label> startPtRegions =
boundaryPtRegions[surfPtToBoundaryPt[startI]];
const DynamicList<label> endPtRegions =
boundaryPtRegions[surfPtToBoundaryPt[endI]];
const DynamicList<label>& startPtRegions =
boundaryPtRegions[surfPtToBoundaryPt[meshPoints[e.first()]]];
const DynamicList<label>& endPtRegions =
boundaryPtRegions[surfPtToBoundaryPt[meshPoints[e.second()]]];
if (startPtRegions.size() > 1 && endPtRegions.size() > 1)
{

View File

@ -87,11 +87,7 @@ label addPatch
)
);
auto& pp = *ppPtr;
if (!groupName.empty())
{
pp.inGroups().appendUniq(groupName);
}
pp.addGroup(groupName);
// Add patch, create calculated everywhere

View File

@ -148,21 +148,15 @@ void matchPatchFaces
// Mesh 0
//~~~~~~~
interfaceMesh0.append(labelList());
auto& intMesh0 = interfaceMesh0.last();
intMesh0.setSize(nSourcei, -1);
auto& intMesh0 = interfaceMesh0.emplace_back(nSourcei, -1);
intMesh0[sourcei] = meshi;
interfaceSource0.append(sourcei);
interfaceSource0.push_back(sourcei);
interfacePatch0.append(labelList());
auto& intPatch0 = interfacePatch0.last();
intPatch0.setSize(nSourcei, -1);
auto& intPatch0 = interfacePatch0.emplace_back(nSourcei, -1);
intPatch0[sourcei] = ppi.index();
interfaceNames0.append(wordList());
auto& intNames0 = interfaceNames0.last();
intNames0.setSize(nSourcei);
auto& intNames0 = interfaceNames0.emplace_back(nSourcei);
intNames0[sourcei] =
patchName(entryName, meshes[meshi], meshes[meshj]);
@ -170,33 +164,23 @@ void matchPatchFaces
// Mesh 1
//~~~~~~~
interfaceMesh1.append(labelList());
auto& intMesh1 = interfaceMesh1.last();
intMesh1.setSize(nSourcej, -1);
auto& intMesh1 = interfaceMesh1.emplace_back(nSourcej, -1);
intMesh1[sourcej] = meshj;
interfaceSource1.append(sourcej);
interfaceSource1.push_back(sourcej);
interfacePatch1.append(labelList());
auto& intPatch1 = interfacePatch1.last();
intPatch1.setSize(nSourcej, -1);
auto& intPatch1 = interfacePatch1.emplace_back(nSourcej, -1);
intPatch1[sourcej] = ppj.index();
interfaceNames1.append(wordList());
auto& intNames1 = interfaceNames1.last();
intNames1.setSize(nSourcej);
auto& intNames1 = interfaceNames1.emplace_back(nSourcej);
intNames1[sourcej] =
patchName(entryName, meshes[meshj], meshes[meshi]);
interfaceFaces0.append(List<DynamicList<label>>());
auto& intFaces0 = interfaceFaces0.last();
intFaces0.setSize(nSourcei);
auto& intFaces0 = interfaceFaces0.emplace_back(nSourcei);
DynamicList<label>& faces0 = intFaces0[sourcei];
faces0.setCapacity(ppi.size());
interfaceFaces1.append(List<DynamicList<label>>());
auto& intFaces1 = interfaceFaces1.last();
intFaces1.setSize(nSourcej);
auto& intFaces1 = interfaceFaces1.emplace_back(nSourcej);
DynamicList<label>& faces1 = intFaces1[sourcej];
faces1.setCapacity(ppj.size());
@ -249,7 +233,7 @@ void matchPatchFaces
{
if (weights[facei] > 0.5 || sourceMask[facei] > SMALL)
{
faces0.append(ppi.start()+facei);
faces0.push_back(ppi.start()+facei);
}
}
}
@ -259,7 +243,7 @@ void matchPatchFaces
{
if (weights[facei] > 0.5 || targetMask[facei] > SMALL)
{
faces1.append(ppj.start()+facei);
faces1.push_back(ppj.start()+facei);
}
}
}
@ -825,7 +809,7 @@ int main(int argc, char *argv[])
if (pDict.get<word>("constructFrom") == "autoPatch")
{
interRegionSources[meshi].append(sourcei);
interRegionSources[meshi].push_back(sourcei);
}
}
}

View File

@ -518,7 +518,7 @@ void Foam::meshDualiser::createFacesAroundEdge
if (startDual != -1)
{
verts.appendUniq(startDual);
verts.push_uniq(startDual);
}
}
break;

View File

@ -429,7 +429,7 @@ unset cmd
case "$WM_MPLIB" in
*OPENMPI*)
cmd="mpirun -app $PWD/mpirun.schema </dev/null"
cmd="mpirun --oversubscribe -app $PWD/mpirun.schema </dev/null"
;;
MPICH)
cmd="mpiexec"

View File

@ -304,16 +304,21 @@ runApplication()
#
runParallel()
{
local appName appRun optValue logFile logMode nProcs
local appName appRun optValue logFile logMode
local mpiopts nProcs
# Any additional parsed arguments (eg, decomposeParDict)
local appArgs="-parallel"
local mpirun="mpirun"
if [ "$FOAM_MPI" = msmpi ]
then
case "$FOAM_MPI" in
(msmpi*)
mpirun="mpiexec"
fi
;;
(*openmpi*)
mpiopts="--oversubscribe"
;;
esac
# Parse options until executable is encountered
while [ "$#" -gt 0 ] && [ -z "$appRun" ]
@ -378,11 +383,11 @@ runParallel()
if [ "$logMode" = append ]
then
(
$mpirun -n $nProcs $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
"$mpirun" $mpiopts -n "${nProcs:?}" $appRun $appArgs "$@" </dev/null >> $logFile 2>&1
)
else
(
$mpirun -n $nProcs $appRun $appArgs "$@" </dev/null > $logFile 2>&1
"$mpirun" $mpiopts -n "${nProcs:?}" $appRun $appArgs "$@" </dev/null > $logFile 2>&1
)
fi
fi

View File

@ -225,6 +225,8 @@ castellatedMeshControls
//cellZone sphere;
//cellZoneInside inside; // outside/insidePoint
//insidePoint (1 1 1); // if (cellZoneInside == insidePoint)
// or alternative multiple insidePoints:
//insidePoints ((1 1 1)); // if (cellZoneInside == insidePoint)
//- Optional specification of what to do with faceZone faces:
// internal : keep them as internal faces (default)

View File

@ -497,7 +497,7 @@ bool Foam::fileMonitor::removeWatch(const label watchFd)
<< watchFile_[watchFd] << endl;
}
freeWatchFds_.appendUniq(watchFd);
freeWatchFds_.push_uniq(watchFd);
return watcher_->removeWatch(watchFd);
}

View File

@ -7,7 +7,7 @@
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2011 Symscape
Copyright (C) 2016-2021 OpenCFD Ltd.
Copyright (C) 2016-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -36,6 +36,7 @@ License
#include "Switch.H"
#include <float.h> // For *fp functions
#include <algorithm>
#include <limits>
// File-local functions
@ -98,18 +99,7 @@ void Foam::sigFpe::sigHandler(int)
Foam::sigFpe::sigFpe()
{
set(false);
}
Foam::sigFpe::ignore::ignore()
:
wasActive_(sigFpe::active())
{
if (wasActive_)
{
sigFpe::unset();
}
set(false); // false = non-verbose
}
@ -117,28 +107,12 @@ Foam::sigFpe::ignore::ignore()
Foam::sigFpe::~sigFpe()
{
unset(false);
}
Foam::sigFpe::ignore::~ignore()
{
restore();
unset(false); // false = non-verbose
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::sigFpe::ignore::restore()
{
if (wasActive_)
{
sigFpe::set();
}
wasActive_ = false;
}
bool Foam::sigFpe::requested()
{
return isTrue("FOAM_SIGFPE", switchFpe_);
@ -153,8 +127,8 @@ void Foam::sigFpe::set(bool verbose)
if (verbose)
{
Info<< "trapFpe: Floating point exception trapping ";
Info<< "- disabled on this platform" << endl;
Info<< "trapFpe: Floating point exception trapping "
<< "- disabled on this platform" << endl;
}
#else
@ -194,7 +168,7 @@ void Foam::sigFpe::set(bool verbose)
{
if (verbose)
{
Info<< "setNaN : Initialise allocated memory to NaN "
Info<< "setNaN : Fill allocated memory with NaN "
<< "- not supported on this platform" << endl;
}
}
@ -222,9 +196,37 @@ void Foam::sigFpe::unset(bool verbose)
}
void Foam::sigFpe::fillNan(char* buf, size_t count)
{
if (!buf || !count) return;
// Fill with signaling_NaN
const scalar val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
reinterpret_cast<scalar*>(buf), (count/sizeof(scalar)), val
);
}
void Foam::sigFpe::fillNan(UList<scalar>& list)
{
list = std::numeric_limits<scalar>::signaling_NaN();
if (list.empty()) return;
// Fill with signaling_NaN
const scalar val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
list.data(), list.size(), val
);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -57,7 +57,7 @@ SourceFiles
#ifndef Foam_sigFpe_H
#define Foam_sigFpe_H
#include <cstddef> // for std::size_t
#include <cstddef> // For std::size_t
#include "scalarFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -87,7 +87,7 @@ class sigFpe
//- Floating point trapping currently active?
static bool sigActive_;
//- Flag to indicate mallocNan is currently active
//- Is NaN memory initialisation currently active?
static bool nanActive_;
@ -124,18 +124,21 @@ public:
//- True if NaN memory initialisation is currently active.
static bool nanActive() noexcept { return nanActive_; }
//- Activate SIGFPE signal handler when FOAM_SIGFPE is %set
// Fill memory with NaN when FOAM_SETNAN is %set
//- Activate SIGFPE handler when FOAM_SIGFPE is enabled.
//- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false);
//- Deactivate SIGFPE signal handler and NaN memory initialisation
//- Deactivate SIGFPE handler and NaN memory initialisation
static void unset(bool verbose=false);
//- Fill data block with NaN values
//- Fill data block with signaling_NaN values
static void fillNan(char* buf, size_t count);
//- Fill data block with signaling_NaN values
static void fillNan(UList<scalar>& list);
// Helper classes
// Helpers
//- Helper to locally ignore SIGFPE handling.
// Restores the original state of the SIGFPE handler on destruction.
@ -144,29 +147,46 @@ public:
//- The signal handler state when entering
bool wasActive_;
public:
//- No copy construct
ignore(const ignore&) = delete;
//- No copy assignment
void operator=(const ignore&) = delete;
//- No move construct
ignore(ignore&&) = delete;
//- No copy assignment
void operator=(const ignore&) = delete;
//- No move assignment
void operator=(ignore&&) = delete;
public:
//- Constructor deactivates any previously active SIGFPE handler
ignore();
ignore()
:
wasActive_(Foam::sigFpe::active())
{
if (wasActive_)
{
Foam::sigFpe::unset();
}
}
//- Destructor restores the original state of SIGFPE handler
~ignore();
~ignore() { reset(); }
//- Restore the original state of SIGFPE handler
void restore();
void reset()
{
if (wasActive_)
{
wasActive_ = false;
Foam::sigFpe::set();
}
}
//- Same as reset()
void restore() { reset(); }
};
};

View File

@ -77,7 +77,7 @@ public:
// Constructors
//- Default construct
sigStopAtWriteNow();
sigStopAtWriteNow() noexcept = default;
//- Construct with Time reference
explicit sigStopAtWriteNow(const Time& runTime, bool verbose=false);

View File

@ -493,7 +493,7 @@ bool Foam::fileMonitor::removeWatch(const label watchFd)
<< watchFile_[watchFd] << endl;
}
freeWatchFds_.appendUniq(watchFd);
freeWatchFds_.push_uniq(watchFd);
return watcher_->removeWatch(watchFd);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2015 OpenFOAM Foundation
Copyright (C) 2016-2021 OpenCFD Ltd.
Copyright (C) 2016-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,12 +33,12 @@ License
#include "IOstreams.H"
#include "UList.H"
#include "Switch.H"
#include <algorithm>
#include <limits>
// File-local functions
#include "signalMacros.C"
#include <limits>
#if defined(__linux__) && defined(__GNUC__)
#ifndef __USE_GNU
#define __USE_GNU // To use feenableexcept()
@ -85,32 +85,32 @@ extern "C"
{
extern void* __libc_malloc(size_t size);
// Override the GLIBC malloc to support mallocNan
// Override the GLIBC malloc to support filling with NaN
void* malloc(size_t size)
{
// Call the low-level GLIBC malloc function
void* ptr = __libc_malloc(size);
if (Foam::sigFpe::nanActive())
{
return Foam::sigFpe::mallocNan(size);
}
else
{
return __libc_malloc(size);
// Fill with signaling_NaN
const auto val = std::numeric_limits<Foam::scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
reinterpret_cast<Foam::scalar*>(ptr),
(size/sizeof(Foam::scalar)),
val
);
}
return ptr;
}
}
} // End extern C
void* Foam::sigFpe::mallocNan(size_t size)
{
// Call the low-level GLIBC malloc function
void* result = __libc_malloc(size);
// Initialize to signalling NaN
UList<scalar> list(reinterpret_cast<scalar*>(result), size/sizeof(scalar));
sigFpe::fillNan(list);
return result;
}
#endif // __linux__
@ -134,18 +134,7 @@ void Foam::sigFpe::sigHandler(int)
Foam::sigFpe::sigFpe()
{
set(false);
}
Foam::sigFpe::ignore::ignore()
:
wasActive_(sigFpe::active())
{
if (wasActive_)
{
sigFpe::unset();
}
set(false); // false = non-verbose
}
@ -153,28 +142,12 @@ Foam::sigFpe::ignore::ignore()
Foam::sigFpe::~sigFpe()
{
unset(false);
}
Foam::sigFpe::ignore::~ignore()
{
restore();
unset(false); // false = non-verbose
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::sigFpe::ignore::restore()
{
if (wasActive_)
{
sigFpe::set();
}
wasActive_ = false;
}
bool Foam::sigFpe::requested()
{
return isTrue("FOAM_SIGFPE", switchFpe_);
@ -224,7 +197,7 @@ void Foam::sigFpe::set(bool verbose)
if (verbose)
{
Info<< "setNaN : Initialise allocated memory to NaN ";
Info<< "setNaN : Fill allocated memory with NaN ";
if (nanActive_)
{
@ -275,9 +248,37 @@ void Foam::sigFpe::unset(bool verbose)
}
void Foam::sigFpe::fillNan(char* buf, size_t count)
{
if (!buf || !count) return;
// Fill with signaling_NaN
const auto val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
reinterpret_cast<scalar*>(buf), (count/sizeof(scalar)), val
);
}
void Foam::sigFpe::fillNan(UList<scalar>& list)
{
list = std::numeric_limits<scalar>::signaling_NaN();
if (list.empty()) return;
// Fill with signaling_NaN
const auto val = std::numeric_limits<scalar>::signaling_NaN();
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
std::fill_n
(
list.data(), list.size(), val
);
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -57,7 +57,7 @@ SourceFiles
#ifndef Foam_sigFpe_H
#define Foam_sigFpe_H
#include <cstddef> // for std::size_t
#include <cstddef> // For std::size_t
#include "scalarFwd.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -87,7 +87,7 @@ class sigFpe
//- Floating point trapping currently active?
static bool sigActive_;
//- Flag to indicate mallocNan is currently active
//- Is NaN memory initialisation currently active?
static bool nanActive_;
@ -124,23 +124,21 @@ public:
//- True if NaN memory initialisation is currently active.
static bool nanActive() noexcept { return nanActive_; }
//- Activate SIGFPE signal handler when FOAM_SIGFPE is %set
// Fill memory with NaN when FOAM_SETNAN is %set
//- Activate SIGFPE handler when FOAM_SIGFPE is enabled.
//- Activate fill memory with signaling_NaN when FOAM_SETNAN is enabled
static void set(bool verbose=false);
//- Deactivate SIGFPE signal handler and NaN memory initialisation
//- Deactivate SIGFPE handler and NaN memory initialisation
static void unset(bool verbose=false);
#ifdef __linux__
//- Malloc function which initializes to NaN
static void* mallocNan(size_t size);
#endif
//- Fill data block with signaling_NaN values
static void fillNan(char* buf, size_t count);
//- Fill data block with NaN values
//- Fill data block with signaling_NaN values
static void fillNan(UList<scalar>& list);
// Helper classes
// Helpers
//- Helper to locally ignore SIGFPE handling.
// Restores the original state of the SIGFPE handler on destruction.
@ -149,29 +147,46 @@ public:
//- The signal handler state when entering
bool wasActive_;
public:
//- No copy construct
ignore(const ignore&) = delete;
//- No copy assignment
void operator=(const ignore&) = delete;
//- No move construct
ignore(ignore&&) = delete;
//- No copy assignment
void operator=(const ignore&) = delete;
//- No move assignment
void operator=(ignore&&) = delete;
public:
//- Constructor deactivates any previously active SIGFPE handler
ignore();
ignore()
:
wasActive_(Foam::sigFpe::active())
{
if (wasActive_)
{
Foam::sigFpe::unset();
}
}
//- Destructor restores the original state of SIGFPE handler
~ignore();
~ignore() { reset(); }
//- Restore the original state of SIGFPE handler
void restore();
void reset()
{
if (wasActive_)
{
wasActive_ = false;
Foam::sigFpe::set();
}
}
//- Same as reset()
void restore() { reset(); }
};
};

View File

@ -271,7 +271,7 @@ gzstream = $(Streams)/gzstream
$(gzstream)/gzstream.C
memstream = $(Streams)/memory
$(memstream)/ListStream.C
$(memstream)/SpanStreams.C
Fstreams = $(Streams)/Fstreams
$(Fstreams)/IFstream.C

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -102,48 +102,51 @@ bool Foam::PackedList<Width>::uniform() const
return true;
}
// The value of the first element for testing
const unsigned int val = get(0);
const label nblocks = num_blocks(size());
bool identical = true;
if (!val)
{
// Zero value: can just check block content directly
// No bits set: just check there are no non-zero blocks
// - like bitSet::none()
identical = (-1 == first_block());
}
else if (val == PackedList<Width>::max_value)
{
// All bits set: just check there are no zero blocks
// - like bitSet::all()
identical = (-1 == first_not_block());
}
else
{
const label nblocks = num_blocks(size());
for (label blocki = 0; identical && blocki < nblocks; ++blocki)
if (nblocks > 1)
{
identical = !blocks_[blocki];
// Fill value for complete blocks
const unsigned int blockval = repeated_value(val);
// Check each complete block (nblocks-1)
for (label blocki = 0; identical && blocki < (nblocks-1); ++blocki)
{
identical = (blocks_[blocki] == blockval);
}
}
return identical;
}
else if (nblocks > 1)
{
// Fill value for complete blocks
const unsigned int blockval = repeated_value(val);
// Check each complete block (nblocks-1)
for (label blocki = 0; identical && blocki < (nblocks-1); ++blocki)
// Partial block: check manually
for
(
label elemi = elem_per_block*(nblocks-1);
identical && elemi < size();
++elemi
)
{
identical = (blocks_[blocki] == blockval);
identical = (val == get(elemi));
}
}
// Partial block: check manually
for
(
label elemi = elem_per_block*(nblocks-1);
identical && elemi < size();
++elemi
)
{
identical = (val == get(elemi));
}
return identical;
}
@ -194,16 +197,20 @@ Foam::PackedList<Width>::unpack() const
"Width of IntType is too small to hold result"
);
List<IntType> output(size());
if (empty())
{
return List<IntType>(0);
return output;
}
else if (uniform())
{
return List<IntType>(size(), static_cast<IntType>(get(0)));
output = static_cast<IntType>(get(0));
return output;
}
List<IntType> output(size());
// NON-UNIFORM and len > 0
label outi = 0;
// Process n-1 complete blocks
@ -215,7 +222,7 @@ Foam::PackedList<Width>::unpack() const
for (unsigned nget = elem_per_block; nget; --nget, ++outi)
{
output[outi] = IntType(blockval & max_value);
output[outi] = IntType(blockval & PackedList<Width>::max_value);
blockval >>= Width;
}
}

View File

@ -221,6 +221,14 @@ protected:
//- Copy assignment
inline void copyAssign(const PackedList<Width>& rhs);
//- Find the first block with a '1' bit
// \return block number or -1 for an list or if all bits are OFF.
inline label first_block() const;
//- Find the first block with a '0' bit
// \return block number or -1 for an list or if all bits are ON.
inline label first_not_block() const;
public:
@ -292,7 +300,7 @@ public:
//- Number of elements that can be stored without reallocating
inline label capacity() const noexcept;
//- True if all entries have identical values, and list is non-empty
//- True if all entries have identical values (and list is non-empty)
bool uniform() const;
//- Test for equality of sizes and the bits set

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -147,6 +147,73 @@ inline void Foam::PackedList<Width>::copyAssign(const PackedList<Width>& rhs)
}
template<unsigned Width>
inline Foam::label Foam::PackedList<Width>::first_block() const
{
if (size())
{
const label nblocks = num_blocks(size());
for (label blocki=0; blocki < nblocks; ++blocki)
{
if (blocks_[blocki])
{
return blocki;
}
}
}
return -1;
}
template<unsigned Width>
inline Foam::label Foam::PackedList<Width>::first_not_block() const
{
if (!size())
{
return -1;
}
// Check on complement (changes 0 <-> 1).
// If any 1's now appear, there was a 0 bit before
const label nblocks = num_blocks(size());
// Extra bits in the final block?
const unsigned int off = size() % elem_per_block;
if (!off)
{
for (label blocki=0; blocki < nblocks; ++blocki)
{
if (~(blocks_[blocki]))
{
return blocki;
}
}
}
else
{
for (label blocki=0; blocki < nblocks-1; ++blocki)
{
if (~(blocks_[blocki]))
{
return blocki;
}
}
// The final block needs masking
if (~(blocks_[nblocks-1]) & mask_lower(off))
{
return nblocks-1;
}
}
return -1;
}
// * * * * * * * * * * * * * * * Specializations * * * * * * * * * * * * * * //
namespace Foam

View File

@ -18,8 +18,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef PackedBoolList_H
#define PackedBoolList_H
#ifndef FoamCompat_PackedBoolList_H
#define FoamCompat_PackedBoolList_H
#include "bitSet.H"

View File

@ -65,13 +65,6 @@ class bitSet
:
public PackedList<1>
{
// Private Member Functions
//- Find the first block with a '0' bit
// \return block number or -1 if the set is empty or all bits are on.
inline label first_not_block() const;
protected:
// Logic/Set Operations
@ -138,7 +131,7 @@ public:
// Constructors
//- Default construct an empty, zero-sized bitSet
inline bitSet() noexcept;
inline constexpr bitSet() noexcept;
//- Construct from Istream
explicit bitSet(Istream& is);
@ -246,9 +239,6 @@ public:
// \note Method name compatibility with boost::dynamic_bitset
inline bool none() const;
//- True if all entries have identical values, and the set is non-empty
inline bool uniform() const;
//- Count number of bits set.
// \param on can be set to false to count the number of unset bits
// instead.

View File

@ -25,56 +25,9 @@ License
\*---------------------------------------------------------------------------*/
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
inline Foam::label Foam::bitSet::first_not_block() const
{
if (empty())
{
return -1;
}
// Use complement to change 0 <-> 1 and check if any 1's now appear
const label nblocks = num_blocks(size());
// Extra bits in the final block?
const unsigned int off = size() % elem_per_block;
if (!off)
{
for (label blocki=0; blocki < nblocks; ++blocki)
{
if (~(blocks_[blocki]))
{
return blocki;
}
}
}
else
{
for (label blocki=0; blocki < nblocks-1; ++blocki)
{
if (~(blocks_[blocki]))
{
return blocki;
}
}
// The final block needs masking
if (~(blocks_[nblocks-1]) & mask_lower(off))
{
return nblocks-1;
}
}
return -1;
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
inline Foam::bitSet::bitSet() noexcept
inline constexpr Foam::bitSet::bitSet() noexcept
:
PackedList<1>()
{}
@ -313,14 +266,14 @@ inline Foam::bitSet::const_iterator Foam::bitSet::cend() const noexcept
inline Foam::label Foam::bitSet::find_first() const
{
// Process block-wise, detecting any '1' bits
const label blocki = first_block();
const label nblocks = num_blocks(size());
for (label blocki = 0; blocki < nblocks; ++blocki)
if (blocki >= 0)
{
label pos = (blocki * elem_per_block);
// Detect first '1' bit within the block
for
(
unsigned int blockval = blocks_[blocki];
@ -348,7 +301,7 @@ inline Foam::label Foam::bitSet::find_first_not() const
{
label pos = (blocki * elem_per_block);
// Detect first '0' bit by checking the complement.
// Detect first '0' bit within the block (check the complement)
// No special masking for the final block, that was already checked
// in the first_not_block() call.
@ -461,39 +414,19 @@ inline const Foam::bitSet& Foam::bitSet::null()
inline bool Foam::bitSet::all() const
{
if (empty()) return true; // SIC. boost convention
return -1 == first_not_block();
return (-1 == first_not_block());
}
inline bool Foam::bitSet::any() const
{
if (size())
{
const label nblocks = num_blocks(size());
for (label blocki=0; blocki < nblocks; ++blocki)
{
if (blocks_[blocki])
{
return true;
}
}
}
return false;
return (-1 != first_block());
}
inline bool Foam::bitSet::none() const
{
return !any();
}
inline bool Foam::bitSet::uniform() const
{
return (size() == 1 || (size() > 1 && (test(0) ? all() : none())));
return (-1 == first_block());
}

View File

@ -108,6 +108,8 @@ const Foam::SubList<T> Foam::CircularBuffer<T>::array_two() const
template<class T>
Foam::label Foam::CircularBuffer<T>::find(const T& val, label pos) const
{
if (pos < 0) return -1; // no-op
label i = -1;
const auto list1 = this->array_one();

View File

@ -282,18 +282,21 @@ public:
// Search
//- True if the value is contained in the list.
inline bool contains(const T& val) const;
//- Is the value contained in the list?
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \return true if found.
inline bool contains(const T& val, label pos) const;
//- Find index of the first occurrence of the value.
// Any occurrences before the start pos are ignored.
// Linear search.
// \return position in list or -1 if not found.
label find(const T& val, label pos = 0) const;
//- Is the value contained in the list?
// Linear search from start pos until the end of the list.
// Any occurrences before the start pos are ignored.
// \return true if found.
inline bool contains(const T& val, label pos = 0) const;
// Stack-like Operations
@ -524,8 +527,8 @@ public:
//FOAM_DEPRECATED_FOR(2022-10, "push_back()")
void append(const UList<T>& list) { this->push_back(list); }
//- Append an element if not already in the buffer.
//FOAM_DEPRECATED_FOR(2022-10, "push_uniq()")
//- Same as push_uniq()
FOAM_DEPRECATED_STRICT(2022-10, "push_uniq()")
label appendUniq(const T& val) { return this->push_uniq(val); }
};

View File

@ -255,6 +255,13 @@ inline void Foam::CircularBuffer<T>::reserve_nocopy(const label len)
}
template<class T>
bool Foam::CircularBuffer<T>::contains(const T& val) const
{
return (this->array_one().contains(val) || this->array_two().contains(val));
}
template<class T>
inline bool Foam::CircularBuffer<T>::contains(const T& val, label pos) const
{

View File

@ -499,8 +499,12 @@ bool Foam::HashTable<T, Key, Hash>::erase(const iterator& iter)
template<class T, class Key, class Hash>
bool Foam::HashTable<T, Key, Hash>::erase(const Key& key)
{
iterator iter(find(key));
return iterator_erase(iter);
if (size_)
{
iterator iter(find(key));
if (iter.good()) return iterator_erase(iter);
}
return false;
}

View File

@ -31,13 +31,21 @@ template<class T, class Addr>
Foam::label Foam::IndirectListBase<T, Addr>::find
(
const T& val,
label pos
label pos,
label len
) const
{
const label len = addr_.size();
if (pos >= 0 && len)
if (pos >= 0 && pos < addr_.size())
{
// Change sub-length to (one-past) end position
// len == -1 (like std::string::npos) - search until end
if (len > 0) len += pos;
if (len < 0 || len > addr_.size())
{
len = addr_.size();
}
const T* const vals = values_.begin();
while (pos < len)
@ -62,7 +70,7 @@ Foam::label Foam::IndirectListBase<T, Addr>::rfind
label pos
) const
{
// pos == -1 has same meaning as std::string::npos - search from end
// pos == -1 (like std::string::npos) - search from end
if (pos < 0 || pos >= addr_.size())
{

View File

@ -179,11 +179,19 @@ public:
// Search
//- Is the value contained in the list?
// \param val The value to search for
// \param pos The first position to examine (default: 0, no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return true if found.
inline bool contains(const T& val, label pos = 0, label len = -1) const;
//- Find index of the first occurrence of the value.
// Any occurrences before the start pos are ignored.
// Linear search.
// \return -1 if not found.
label find(const T& val, label pos = 0) const;
// \param val The value to search for
// \param pos The first position to examine (default: 0, no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return position in list or -1 if not found.
label find(const T& val, label pos = 0, label len = -1) const;
//- Find index of the last occurrence of the value.
// Any occurrences after the end pos are ignored.
@ -191,12 +199,6 @@ public:
// \return -1 if not found.
label rfind(const T& val, label pos = -1) const;
//- Is the value contained in the list?
// Linear search from start pos until the end of the list.
// Any occurrences before the start pos are ignored.
// \return true if found.
inline bool contains(const T& val, label pos = 0) const;
// Member Operators

View File

@ -102,10 +102,11 @@ template<class T, class Addr>
inline bool Foam::IndirectListBase<T, Addr>::contains
(
const T& val,
label pos
label pos,
label len
) const
{
return (this->find(val, pos) >= 0);
return (this->find(val, pos, len) >= 0);
}

View File

@ -443,8 +443,8 @@ public:
this->push_back(std::move(list));
}
//- Append an element if not already in the list.
//FOAM_DEPRECATED_FOR(2022-10, "push_uniq()")
//- Same as push_uniq()
FOAM_DEPRECATED_STRICT(2022-10, "push_uniq()")
label appendUniq(const T& val) { return this->push_uniq(val); }
};

View File

@ -222,6 +222,27 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
);
}
}
else if (std::is_same<char, T>::value)
{
// Special treatment for char data (always binary and contiguous)
// (see List<char>::readList)
if (len)
{
const auto oldFmt = is.format(IOstreamOption::BINARY);
// read(...) includes surrounding start/end delimiters
is.read(list.data_bytes(), list.size_bytes());
is.format(oldFmt);
is.fatalCheck
(
"DynamicList<char>::readList(Istream&) : "
"reading binary block"
);
}
}
else
{
// Begin of contents marker

View File

@ -46,24 +46,42 @@ std::streamsize Foam::FixedList<T, N>::byteSize()
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, unsigned N>
Foam::label Foam::FixedList<T, N>::find(const T& val, label pos) const
Foam::label Foam::FixedList<T, N>::find(const T& val) const
{
if (pos >= 0)
const auto iter = std::find(this->cbegin(), this->cend(), val);
return (iter != this->cend() ? label(iter - this->cbegin()) : label(-1));
}
template<class T, unsigned N>
Foam::label Foam::FixedList<T, N>::find
(
const T& val,
label pos,
label len
) const
{
if (pos >= 0 && pos < label(N))
{
// auto iter = std::find(this->begin(pos), this->end(), val);
// if (iter != this->end())
// {
// return label(iter - this->begin());
// }
// Change sub-length to (one-past) end position
// len == -1 (like std::string::npos) - search until end
while (pos < label(N))
if (len > 0) len += pos;
if (len < 0 || len > label(N))
{
if (this->v_[pos] == val)
{
return pos;
}
len = label(N);
}
++pos;
const auto iter = std::find
(
(this->cbegin() + pos),
(this->cbegin() + len),
val
);
if (iter != (this->cbegin() + len))
{
return label(iter - this->cbegin());
}
}
@ -74,7 +92,8 @@ Foam::label Foam::FixedList<T, N>::find(const T& val, label pos) const
template<class T, unsigned N>
Foam::label Foam::FixedList<T, N>::rfind(const T& val, label pos) const
{
// pos == -1 has same meaning as std::string::npos - search from end
// pos == -1 (like std::string::npos) - search from end
if (pos < 0 || pos >= label(N))
{
pos = label(N)-1;

View File

@ -275,11 +275,27 @@ public:
// Search
//- True if the value is contained in the list.
inline bool contains(const T& val) const;
//- Is the value contained in the list?
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return true if found.
inline bool contains(const T& val, label pos, label len = -1) const;
//- Find index of the first occurrence of the value.
// Any occurrences before the start pos are ignored.
// Linear search.
// \return -1 if not found.
label find(const T& val, label pos = 0) const;
// \param val The value to search for
// \return position in list or -1 if not found.
label find(const T& val) const;
//- Find index of the first occurrence of the value.
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return position in list or -1 if not found.
label find(const T& val, label pos, label len = -1) const;
//- Find index of the last occurrence of the value.
// Any occurrences after the end pos are ignored.
@ -287,12 +303,6 @@ public:
// \return position in list or -1 if not found.
label rfind(const T& val, label pos = -1) const;
//- Is the value contained in the list?
// Linear search from start pos until the end of the list.
// Any occurrences before the start pos are ignored.
// \return true if found.
inline bool contains(const T& val, label pos = 0) const;
// Edit

View File

@ -307,9 +307,22 @@ inline bool Foam::FixedList<T, N>::uniform() const
template<class T, unsigned N>
inline bool Foam::FixedList<T, N>::contains(const T& val, label pos) const
inline bool Foam::FixedList<T, N>::contains(const T& val) const
{
return (this->find(val, pos) >= 0);
const auto iter = std::find(this->cbegin(), this->cend(), val);
return (iter != this->cend());
}
template<class T, unsigned N>
inline bool Foam::FixedList<T, N>::contains
(
const T& val,
label pos,
label len
) const
{
return (this->find(val, pos, len) >= 0);
}

View File

@ -395,8 +395,8 @@ public:
this->push_back(list);
}
//- Append an element if not already in the list.
//FOAM_DEPRECATED_FOR(2022-10, "push_uniq()")
//- Same as push_uniq()
FOAM_DEPRECATED_STRICT(2022-10, "push_uniq()")
label appendUniq(const T& val) { return this->push_uniq(val); }

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -89,7 +89,10 @@ public:
// Constructors
//- Construct from UList, the entire size
inline explicit SubList(const UList<T>& list);
inline explicit SubList(const UList<T>& list) noexcept;
//- Construct from std::vector, the entire size
inline explicit SubList(const std::vector<T>& list) noexcept;
//- Construct from FixedList, the entire size
template<unsigned N>
@ -128,6 +131,47 @@ public:
);
// Member Functions
//- Reset to zero-sized and nullptr
inline UList<T>& reset(std::nullptr_t) noexcept;
//- Reset to use entire UList
inline UList<T>& reset(const UList<T>& list) noexcept;
//- Reset to use UList with sub-list size, start at 0
inline UList<T>& reset
(
const UList<T>& list,
const label subSize
);
//- Reset to use UList with sub-list size and start index
inline UList<T>& reset
(
const UList<T>& list,
const label subSize,
const label startIndex
);
//- Reset to use UList with a (start,size) range.
// The range is subsetted with the list size itself to ensure that the
// result always addresses a valid section of the list.
inline UList<T>& reset
(
const UList<T>& list,
const labelRange& range
);
//- Reset to use UList with a (start,size) range, but bypassing
//- run-time range checking.
inline UList<T>& reset
(
const labelRange& range,
const UList<T>& list
);
// Member Operators
//- Allow cast to a const List\<T\>&

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -28,18 +28,37 @@ License
#include "FixedList.H"
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
inline const Foam::SubList<T>& Foam::SubList<T>::null()
{
return NullObjectRef<SubList<T>>();
}
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class T>
inline Foam::SubList<T>::SubList
(
const UList<T>& list
)
) noexcept
:
UList<T>(const_cast<T*>(list.cdata()), list.size())
{}
template<class T>
inline Foam::SubList<T>::SubList
(
const std::vector<T>& list
) noexcept
:
UList<T>(const_cast<T*>(list.data()), label(list.size()))
{}
template<class T>
template<unsigned N>
inline Foam::SubList<T>::SubList
@ -113,9 +132,102 @@ inline Foam::SubList<T>::SubList
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
inline const Foam::SubList<T>& Foam::SubList<T>::null()
inline Foam::UList<T>& Foam::SubList<T>::reset(std::nullptr_t) noexcept
{
return NullObjectRef<SubList<T>>();
UList<T>::shallowCopy(nullptr, 0);
return *this;
}
template<class T>
inline Foam::UList<T>& Foam::SubList<T>::reset
(
const UList<T>& list
) noexcept
{
UList<T>::shallowCopy(list);
return *this;
}
template<class T>
inline Foam::UList<T>& Foam::SubList<T>::reset
(
const UList<T>& list,
const label subSize
)
{
#ifdef FULLDEBUG
list.checkSize(subSize);
#endif
UList<T>::shallowCopy(const_cast<T*>(list.cdata()), subSize);
return *this;
}
template<class T>
inline Foam::UList<T>& Foam::SubList<T>::reset
(
const UList<T>& list,
const label subSize,
const label startIndex
)
{
#ifdef FULLDEBUG
list.checkRange(startIndex, subSize);
#endif
UList<T>::shallowCopy
(
const_cast<T*>(list.cdata() + startIndex),
subSize
);
return *this;
}
template<class T>
inline Foam::UList<T>& Foam::SubList<T>::reset
(
const UList<T>& list,
const labelRange& range
)
{
#ifdef FULLDEBUG
// subset0() always produces valid ranges but want to check
// that the input itself was valid
list.checkRange(range.start(), range.size());
#endif
labelRange clamped(range.subset0(list.size()));
UList<T>::shallowCopy
(
const_cast<T*>(list.cdata() + clamped.start()),
clamped.size()
);
return *this;
}
template<class T>
inline Foam::UList<T>& Foam::SubList<T>::reset
(
const labelRange& range,
const UList<T>& list
)
{
#ifdef FULLDEBUG
list.checkRange(range.start(), range.size());
#endif
UList<T>::shallowCopy
(
const_cast<T*>(list.cdata() + range.start()),
range.size()
);
return *this;
}

View File

@ -177,26 +177,37 @@ std::streamsize Foam::UList<T>::byteSize() const
template<class T>
Foam::label Foam::UList<T>::find(const T& val, label pos) const
Foam::label Foam::UList<T>::find(const T& val) const
{
const label len = this->size();
const auto iter = std::find(this->cbegin(), this->cend(), val);
return (iter != this->cend() ? label(iter - this->cbegin()) : label(-1));
}
if (pos >= 0)
template<class T>
Foam::label Foam::UList<T>::find(const T& val, label pos, label len) const
{
if (pos >= 0 && pos < this->size())
{
// auto iter = std::find(this->begin(pos), this->end(), val);
// if (iter != this->end())
// {
// return label(iter - this->begin());
// }
// Change sub-length to (one-past) end position
// len == -1 (like std::string::npos) - search until end
while (pos < len)
if (len > 0) len += pos;
if (len < 0 || len > this->size())
{
if (this->v_[pos] == val)
{
return pos;
}
len = this->size();
}
++pos;
const auto iter = std::find
(
(this->cbegin() + pos),
(this->cbegin() + len),
val
);
if (iter != (this->cbegin() + len))
{
return label(iter - this->cbegin());
}
}
@ -207,7 +218,8 @@ Foam::label Foam::UList<T>::find(const T& val, label pos) const
template<class T>
Foam::label Foam::UList<T>::rfind(const T& val, label pos) const
{
// pos == -1 has same meaning as std::string::npos - search from end
// pos == -1 (like std::string::npos) - search from end
if (pos < 0 || pos >= this->size())
{
pos = this->size()-1;

View File

@ -318,11 +318,27 @@ public:
// Search
//- True if the value is contained in the list.
inline bool contains(const T& val) const;
//- Is the value contained in the list?
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return true if found.
inline bool contains(const T& val, label pos, label len = -1) const;
//- Find index of the first occurrence of the value.
// Any occurrences before the start pos are ignored.
// Linear search.
// \param val The value to search for
// \return position in list or -1 if not found.
label find(const T& val, label pos = 0) const;
label find(const T& val) const;
//- Find index of the first occurrence of the value.
// \param val The value to search for
// \param pos The first position to examine (no-op if -ve)
// \param len The length of the search region (-ve until the end)
// \return position in list or -1 if not found.
label find(const T& val, label pos, label len = -1) const;
//- Find index of the last occurrence of the value.
// Any occurrences after the end pos are ignored.
@ -330,12 +346,6 @@ public:
// \return position in list or -1 if not found.
label rfind(const T& val, label pos = -1) const;
//- Is the value contained in the list?
// Linear search from start pos until the end of the list.
// Any occurrences before the start pos are ignored.
// \return true if found.
inline bool contains(const T& val, label pos = 0) const;
// Edit
@ -354,6 +364,9 @@ public:
// Copy
//- Copy the pointer and size
inline void shallowCopy(T* __restrict__ ptr, const label len) noexcept;
//- Copy the pointer and size held by the given UList
inline void shallowCopy(const UList<T>& list) noexcept;
@ -663,7 +676,11 @@ Ostream& operator<<(Ostream& os, const UList<T>& list)
return list.writeList(os, Detail::ListPolicy::short_length<T>::value);
}
//- Write std::vector to Ostream. ASCII only, no line-breaks
//- Read std::vector contents from Istream
template<class T>
Istream& operator>>(Istream& is, std::vector<T>& list);
//- Write std::vector to Ostream (via UList)
template<class T>
Ostream& operator<<(Ostream& os, const std::vector<T>& list);

View File

@ -304,9 +304,29 @@ inline std::streamsize Foam::UList<T>::size_bytes() const noexcept
template<class T>
inline bool Foam::UList<T>::contains(const T& val, label pos) const
inline bool Foam::UList<T>::contains(const T& val) const
{
return (this->find(val, pos) >= 0);
const auto iter = std::find(this->begin(), this->end(), val);
return (iter != this->end());
}
template<class T>
inline bool Foam::UList<T>::contains(const T& val, label pos, label len) const
{
return (this->find(val, pos, len) >= 0);
}
template<class T>
inline void Foam::UList<T>::shallowCopy
(
T* __restrict__ ptr,
const label len
) noexcept
{
size_ = len;
v_ = ptr;
}

View File

@ -187,10 +187,7 @@ Foam::Istream& Foam::UList<T>::readList(Istream& is)
<< exit(FatalIOError);
}
for (label i = 0; i < len; ++i)
{
list[i] = std::move(elems[i]);
}
std::move(elems.begin(), elems.end(), list.begin());
}
else if (tok.isLabel())
{

View File

@ -26,35 +26,183 @@ License
\*---------------------------------------------------------------------------*/
#include "UList.H"
#include "Istream.H"
#include "Ostream.H"
#include "contiguous.H"
#include "token.H"
#include <vector>
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
template<class T>
Foam::Ostream& Foam::operator<<(Ostream& os, const std::vector<T>& list)
Foam::Istream& Foam::operator>>(Istream& is, std::vector<T>& list)
{
auto iter = list.cbegin();
const auto last = list.cend();
is.fatalCheck(FUNCTION_NAME);
// Write ascii list contents, no line breaks
token tok(is);
os << label(list.size()) << token::BEGIN_LIST;
is.fatalCheck("Istream >> std::vector<T> : reading first token");
if (iter != last)
if (tok.isCompound())
{
os << *iter;
// No compound handling ...
while (++iter != last)
list.clear(); // Clear old contents
FatalIOErrorInFunction(is)
<< "Support for compoundToken - not implemented" << nl
<< exit(FatalIOError);
}
else if (tok.isLabel())
{
// Label: could be int(..), int{...} or just a plain '0'
const label len = tok.labelToken();
// Resize to length required
list.resize(len);
if (is.format() == IOstreamOption::BINARY && is_contiguous<T>::value)
{
os << token::SPACE << *iter;
// Binary and contiguous
if (len)
{
Detail::readContiguous<T>
(
is,
reinterpret_cast<char*>(list.data()), // data_bytes()
std::streamsize(list.size())*sizeof(T) // size_bytes()
);
is.fatalCheck
(
"Istream >> std::vector<T> : "
"reading binary block"
);
}
}
else if (std::is_same<char, T>::value)
{
// Special treatment for char data (binary I/O only)
const auto oldFmt = is.format(IOstreamOption::BINARY);
if (len)
{
// read(...) includes surrounding start/end delimiters
is.read
(
reinterpret_cast<char*>(list.data()), // data_bytes()
std::streamsize(list.size())*sizeof(T) // size_bytes()
);
is.fatalCheck
(
"Istream >> std::vector<char> : "
"reading binary block"
);
}
is.format(oldFmt);
}
else
{
// Begin of contents marker
const char delimiter = is.readBeginList("List");
if (len)
{
if (delimiter == token::BEGIN_LIST)
{
auto iter = list.begin();
const auto last = list.end();
// Contents
for (/*nil*/; (iter != last); (void)++iter)
{
is >> *iter;
is.fatalCheck
(
"Istream >> std::vector<char> : "
"reading entry"
);
}
}
else
{
// Uniform content (delimiter == token::BEGIN_BLOCK)
T elem;
is >> elem;
is.fatalCheck
(
"Istream >> std::vector<char> : "
"reading the single entry"
);
// Fill with the value
list.assign(list.size(), elem);
}
}
// End of contents marker
is.readEndList("List");
}
}
else if (tok.isPunctuation(token::BEGIN_LIST))
{
// "(...)" : read as bracketed list
os << token::END_LIST;
// Slightly sub-optimal since it has intermediate resizing,
// however don't expect this as input very often.
os.check(FUNCTION_NAME);
list.clear(); // Clear addressing, leave storage intact (probably)
is >> tok;
is.fatalCheck(FUNCTION_NAME);
while (!tok.isPunctuation(token::END_LIST))
{
is.putBack(tok);
// C++17
// is >> list.emplace_back();
// C++11
list.emplace_back();
is >> list.back();
is.fatalCheck
(
"Istream >> std::vector<char> : "
"reading entry"
);
is >> tok;
is.fatalCheck(FUNCTION_NAME);
}
}
else
{
list.clear(); // Clear old contents
FatalIOErrorInFunction(is)
<< "incorrect first token, expected <int> or '(', found "
<< tok.info() << nl
<< exit(FatalIOError);
}
return is;
}
template<class T>
Foam::Ostream& Foam::operator<<(Ostream& os, const std::vector<T>& list)
{
// Use UList for output
UList<T> proxy(const_cast<T*>(list.data()), label(list.size()));
os << proxy;
return os;
}

View File

@ -1065,14 +1065,9 @@ void Foam::ListOps::appendEqOp<T>::operator()
{
if (y.size())
{
label len = x.size();
if (len)
if (x.size())
{
x.resize(len + y.size());
for (const T& val : y)
{
x[len++] = val;
}
x.push_back(y);
}
else
{
@ -1095,11 +1090,7 @@ void Foam::ListOps::uniqueEqOp<T>::operator()
{
for (const T& val : y)
{
// --> x.push_uniq(val)
if (!x.contains(val))
{
x.push_back(val);
}
x.push_uniq(val);
}
}
else

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2019 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -88,6 +88,41 @@ template<> struct no_linebreak<word> : std::true_type {};
template<> struct no_linebreak<wordRe> : std::true_type {};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Classification of list/container uniformity.
//- The values can be used with bit-wise \c or reduction
enum uniformity : unsigned char
{
EMPTY = 0, //!< An empty container
UNIFORM = 0x1, //!< Container (non-empty) with identical values
NONUNIFORM = 0x2, //!< Container (non-empty) with different values
MIXED = 0x3 //!< Mixed uniform/non-uniform (eg, after reduction)
};
//- Algorithm to determine list/container uniformity
template<class InputIt>
enum uniformity check_uniformity(InputIt first, InputIt last)
{
if (first == last) return uniformity::EMPTY;
// Like std::all_of() with checking against element 0,
// but without using a lambda with auto type (pre C++14) etc.
const auto& elem0 = *first;
for ((void)++first; (first != last); (void)++first)
{
if (elem0 != *first)
{
return uniformity::NONUNIFORM;
}
}
return uniformity::UNIFORM;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace ListPolicy

View File

@ -37,7 +37,7 @@ License
#include "charList.H"
#include "labelPair.H"
#include "masterUncollatedFileOperation.H"
#include "ListStream.H"
#include "SpanStream.H"
#include "StringStream.H"
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -403,7 +403,7 @@ Foam::decomposedBlockData::readBlock
if (blocki == 0)
{
realIsPtr.reset(new IListStream(std::move(data)));
realIsPtr.reset(new ICharStream(std::move(data)));
realIsPtr->name() = is.name();
{
@ -422,7 +422,7 @@ Foam::decomposedBlockData::readBlock
{
{
// Read header from first block
UIListStream headerStream(data);
ISpanStream headerStream(data);
if (!headerIO.readHeader(headerStream))
{
FatalIOErrorInFunction(headerStream)
@ -440,7 +440,7 @@ Foam::decomposedBlockData::readBlock
// Read and discard data, only retain the last one
decomposedBlockData::readBlockEntry(is, data);
}
realIsPtr.reset(new IListStream(std::move(data)));
realIsPtr.reset(new ICharStream(std::move(data)));
realIsPtr->name() = is.name();
// Apply stream settings
@ -585,7 +585,7 @@ Foam::autoPtr<Foam::ISstream> Foam::decomposedBlockData::readBlocks
// Read master data
decomposedBlockData::readBlockEntry(is, data);
realIsPtr.reset(new IListStream(std::move(data)));
realIsPtr.reset(new ICharStream(std::move(data)));
realIsPtr->name() = fName;
{
@ -639,7 +639,7 @@ Foam::autoPtr<Foam::ISstream> Foam::decomposedBlockData::readBlocks
);
is >> data;
realIsPtr.reset(new IListStream(std::move(data)));
realIsPtr.reset(new ICharStream(std::move(data)));
realIsPtr->name() = fName;
}
}
@ -673,7 +673,7 @@ Foam::autoPtr<Foam::ISstream> Foam::decomposedBlockData::readBlocks
UIPstream is(UPstream::masterNo(), pBufs);
is >> data;
realIsPtr.reset(new IListStream(std::move(data)));
realIsPtr.reset(new ICharStream(std::move(data)));
realIsPtr->name() = fName;
}
}
@ -1090,7 +1090,7 @@ bool Foam::decomposedBlockData::writeData(Ostream& os) const
// Re-read my own data to find out the header information
if (Pstream::master(comm_))
{
UIListStream headerStream(contentData_);
ISpanStream headerStream(contentData_);
io.readHeader(headerStream);
verValue = headerStream.version().canonical();

View File

@ -29,7 +29,7 @@ License
#include "dictionary.H"
#include "foamVersion.H"
#include "objectRegistry.H"
#include "ListStream.H"
#include "SpanStream.H"
// * * * * * * * * * * * * * * * Local Functions * * * * * * * * * * * * * * //
@ -125,7 +125,7 @@ bool Foam::decomposedBlockData::readHeader(IOobject& io, Istream& is)
List<char> charData;
decomposedBlockData::readBlockEntry(is, charData);
UIListStream headerStream(charData);
ISpanStream headerStream(charData);
headerStream.name() = is.name();
ok = io.readHeader(headerStream);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2020 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -27,7 +27,7 @@ License
\*---------------------------------------------------------------------------*/
#include "IFstream.H"
#include "OSspecific.H"
#include "OSspecific.H" // For isFile(), fileSize()
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -45,7 +45,7 @@ Foam::IFstream::IFstream
IOstreamOption streamOpt
)
:
Foam::ifstreamPointer(pathname),
Foam::ifstreamPointer(pathname, streamOpt),
ISstream(*(ifstreamPointer::get()), pathname, streamOpt)
{
IOstreamOption::compression(ifstreamPointer::whichCompression());
@ -91,6 +91,45 @@ Foam::IFstream::IFstream
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
std::streamsize Foam::IFstream::fileSize() const
{
const std::istream* ptr = ifstreamPointer::get();
if (!ptr || this->name().empty())
{
return std::streamsize(-1);
}
off_t fileLen = -1;
if (IOstreamOption::COMPRESSED == ifstreamPointer::whichCompression())
{
fileLen = Foam::fileSize(this->name() + ".gz");
}
else
{
// TBD: special handing for wrapped icharstream
// if
// (
// const Foam::icharstream* charstr
// = dynamic_cast<const Foam::icharstream*>(ptr)>(ptr)
// )
// {
// return charstr->capacity();
// }
fileLen = Foam::fileSize(this->name());
}
if (fileLen >= 0)
{
return std::streamsize(fileLen);
}
return std::streamsize(-1);
}
std::istream& Foam::IFstream::stdStream()
{
std::istream* ptr = ifstreamPointer::get();

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2017-2021 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -94,6 +94,13 @@ public:
//- Read/write access to the name of the stream
using ISstream::name;
//- Return the size of the underlying file (-1 on error).
//- This corresponds to Foam::fileSize() but with extra handling of
//- compressed files.
// The return type is \c std::streamsize instead of \c off_t.
// \note Use sparingly since it involves a file stat()!
std::streamsize fileSize() const;
// STL stream

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2017-2022 OpenCFD Ltd.
Copyright (C) 2017-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -65,7 +65,7 @@ Foam::OFstream::OFstream
Foam::ofstreamPointer
(
pathname,
streamOpt.compression(),
streamOpt,
(IOstreamOption::appendType::APPEND == append),
(IOstreamOption::atomicType::ATOMIC == atomic)
),

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2022 OpenCFD Ltd.
Copyright (C) 2020-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -74,7 +74,7 @@ class ifstreamPointer
{
// Private Data
//- The stream pointer (ifstream or igzstream)
//- The stream pointer (ifstream | igzstream, ...)
std::unique_ptr<std::istream> ptr_;
@ -114,8 +114,20 @@ public:
//- Construct from pathname.
// Attempts to read the specified file.
// If that fails, try as a compressed file (.gz ending).
// \param pathname The file name to open for reading
explicit ifstreamPointer(const fileName& pathname);
//- Construct from pathname, option.
// Attempts to read the specified file.
// If that fails, try as a compressed file (.gz ending).
// \param pathname The file name to open for reading
// \param streamOpt Currently unused
ifstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt
);
// Member Functions
@ -125,6 +137,9 @@ public:
// Access
//- True if it holds a valid pointer
explicit operator bool() const noexcept { return bool(ptr_); }
//- The stream pointer (ifstream or igzstream)
std::istream* get() noexcept { return ptr_.get(); }
@ -135,6 +150,19 @@ public:
IOstreamOption::compressionType whichCompression() const;
// Wrapped Methods
//- Attempts to open the specified file for reading.
// If that fails, try as a compressed file (.gz ending).
// \param pathname The file name to open for reading
// \param streamOpt Currently unused
void open
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption()
);
// Edit
//- Return managed pointer and release ownership
@ -168,7 +196,7 @@ class ofstreamPointer
{
// Private Data
//- The stream pointer (ofstream | ogzstream | ocountstream)
//- The stream pointer (ofstream | ogzstream | ocountstream, ...)
std::unique_ptr<std::ostream> ptr_;
//- Atomic file creation
@ -211,9 +239,24 @@ public:
//- Default construct (empty)
ofstreamPointer() noexcept;
//- Construct as null output stream using Foam::ocountstream
//- Construct as null output stream (Foam::ocountstream)
explicit ofstreamPointer(std::nullptr_t);
//- Construct from pathname, option, append, file handling atomic
// \param pathname The file name to open for writing
// \param streamOpt Respects (UNCOMPRESSED | COMPRESSED)
// \param append Open in append mode
// \param atomic Write into temporary file (not target file).
// This option should only be used with a stream wrapper
// (eg, OFstream) that handles the final renaming.
explicit ofstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt = IOstreamOption(),
const bool append = false,
const bool atomic = false
);
//- Construct from pathname, compression, append, file handling atomic
// \param pathname The file name to open for writing
// \param comp UNCOMPRESSED | COMPRESSED
@ -221,10 +264,10 @@ public:
// \param atomic Write into temporary file (not target file).
// This option should only be used with a stream wrapper
// (eg, OFstream) that handles the final renaming.
explicit ofstreamPointer
ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp = IOstreamOption::UNCOMPRESSED,
IOstreamOption::compressionType comp,
const bool append = false,
const bool atomic = false
);
@ -238,6 +281,9 @@ public:
// Access
//- True if it holds a valid pointer
explicit operator bool() const noexcept { return bool(ptr_); }
//- The stream pointer (ofstream or ogzstream)
std::ostream* get() noexcept { return ptr_.get(); }

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2022 OpenCFD Ltd.
Copyright (C) 2018-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -60,8 +60,23 @@ bool Foam::ofstreamPointer::supports_gz()
}
// Future: List<char> slurpFile(....);
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
Foam::ifstreamPointer::ifstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt // Currently unused
)
:
ptr_(nullptr)
{
open(pathname, streamOpt);
}
Foam::ifstreamPointer::ifstreamPointer
(
const fileName& pathname
@ -69,6 +84,162 @@ Foam::ifstreamPointer::ifstreamPointer
:
ptr_(nullptr)
{
open(pathname);
}
Foam::ofstreamPointer::ofstreamPointer() noexcept
:
ptr_(),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer(std::nullptr_t)
:
ptr_(new Foam::ocountstream),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption streamOpt,
const bool append,
const bool atomic
)
:
ptr_(nullptr),
atomic_(atomic)
{
std::ios_base::openmode mode
(
std::ios_base::out | std::ios_base::binary
);
if (append)
{
mode |= std::ios_base::app;
// Cannot append to gzstream
streamOpt.compression(IOstreamOption::UNCOMPRESSED);
// Cannot use append + atomic operation, without lots of extra work
atomic_ = false;
}
// When opening new files, remove file variants out of the way.
// Eg, opening "file1"
// - remove old "file1.gz" (compressed)
// - also remove old "file1" if it is a symlink and we are not appending
//
// Not writing into symlinked files avoids problems with symlinked
// initial fields (eg, 0/U -> ../0.orig/U)
const fileName pathname_gz(pathname + ".gz");
const fileName pathname_tmp(pathname + "~tmp~");
fileName::Type fType = fileName::Type::UNDEFINED;
if (IOstreamOption::COMPRESSED == streamOpt.compression())
{
// Output compression requested.
#ifdef HAVE_LIBZ
// TBD:
// atomic_ = true; // Always treat COMPRESSED like an atomic
const fileName& target = (atomic_ ? pathname_tmp : pathname_gz);
// Remove old uncompressed version (if any)
fType = Foam::type(pathname, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new ogzstream(target, mode));
#else /* HAVE_LIBZ */
streamOpt.compression(IOstreamOption::UNCOMPRESSED);
Warning
<< nl
<< "No write support for gz compressed files (libz)"
<< " : downgraded to UNCOMPRESSED" << nl
<< "file: " << pathname_gz << endl;
#endif /* HAVE_LIBZ */
}
if (IOstreamOption::COMPRESSED != streamOpt.compression())
{
const fileName& target = (atomic_ ? pathname_tmp : pathname);
// Remove old compressed version (if any)
fType = Foam::type(pathname_gz, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname_gz);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new std::ofstream(target, mode));
}
}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append,
const bool atomic
)
:
ofstreamPointer
(
pathname,
IOstreamOption(IOstreamOption::ASCII, comp),
append,
atomic
)
{}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ifstreamPointer::open
(
const fileName& pathname,
IOstreamOption streamOpt // Currently unused
)
{
// Forcibly close old stream (if any)
ptr_.reset(nullptr);
const std::ios_base::openmode mode
(
std::ios_base::in | std::ios_base::binary
@ -110,131 +281,6 @@ Foam::ifstreamPointer::ifstreamPointer
}
Foam::ofstreamPointer::ofstreamPointer() noexcept
:
ptr_(),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer(std::nullptr_t)
:
ptr_(new Foam::ocountstream),
atomic_(false)
{}
Foam::ofstreamPointer::ofstreamPointer
(
const fileName& pathname,
IOstreamOption::compressionType comp,
const bool append,
const bool atomic
)
:
ptr_(nullptr),
atomic_(atomic)
{
std::ios_base::openmode mode
(
std::ios_base::out | std::ios_base::binary
);
if (append)
{
mode |= std::ios_base::app;
// Cannot append to gzstream
comp = IOstreamOption::UNCOMPRESSED;
// Cannot use append + atomic operation, without lots of extra work
atomic_ = false;
}
// When opening new files, remove file variants out of the way.
// Eg, opening "file1"
// - remove old "file1.gz" (compressed)
// - also remove old "file1" if it is a symlink and we are not appending
//
// Not writing into symlinked files avoids problems with symlinked
// initial fields (eg, 0/U -> ../0.orig/U)
const fileName pathname_gz(pathname + ".gz");
const fileName pathname_tmp(pathname + "~tmp~");
fileName::Type fType = fileName::Type::UNDEFINED;
if (IOstreamOption::COMPRESSED == comp)
{
// Output compression requested.
#ifdef HAVE_LIBZ
// TBD:
// atomic_ = true; // Always treat COMPRESSED like an atomic
const fileName& target = (atomic_ ? pathname_tmp : pathname_gz);
// Remove old uncompressed version (if any)
fType = Foam::type(pathname, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new ogzstream(target, mode));
#else /* HAVE_LIBZ */
comp = IOstreamOption::UNCOMPRESSED;
Warning
<< nl
<< "No write support for gz compressed files (libz)"
<< " : downgraded to UNCOMPRESSED" << nl
<< "file: " << pathname_gz << endl;
#endif /* HAVE_LIBZ */
}
if (IOstreamOption::COMPRESSED != comp)
{
const fileName& target = (atomic_ ? pathname_tmp : pathname);
// Remove old compressed version (if any)
fType = Foam::type(pathname_gz, false);
if (fType == fileName::SYMLINK || fType == fileName::FILE)
{
Foam::rm(pathname_gz);
}
// Avoid writing into symlinked files (non-append mode)
if (!append || atomic_)
{
fType = Foam::type(target, false);
if (fType == fileName::SYMLINK)
{
Foam::rm(target);
}
}
ptr_.reset(new std::ofstream(target, mode));
}
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
void Foam::ifstreamPointer::reopen_gz(const std::string& pathname)
{
#ifdef HAVE_LIBZ

View File

@ -102,9 +102,8 @@ public:
//- Broadcast buffer content to all processes in communicator.
using UPstream::broadcast;
//- Broadcast content (contiguous or non-contiguous)
//- to all processes in communicator.
// For \b non-parallel : do nothing.
//- Broadcast content (contiguous or non-contiguous) to all
//- communicator ranks. Does nothing in \b non-parallel.
template<class Type>
static void broadcast
(
@ -112,11 +111,22 @@ public:
const label comm = UPstream::worldComm
);
//- Broadcast multiple items to all processes in communicator.
// For \b non-parallel : do nothing.
//- Broadcast multiple items to all communicator ranks.
//- Does nothing in \b non-parallel.
template<class Type, class... Args>
static void broadcasts(const label comm, Type& arg1, Args&&... args);
//- Broadcast list content (contiguous or non-contiguous) to all
//- communicator ranks. Does nothing in \b non-parallel.
// For contiguous list data, this avoids serialization overhead,
// but at the expense of an additional broadcast call.
template<class ListType>
static void broadcastList
(
ListType& list,
const label comm = UPstream::worldComm
);
// Gather

View File

@ -80,4 +80,61 @@ void Foam::Pstream::broadcasts(const label comm, Type& arg1, Args&&... args)
}
template<class ListType>
void Foam::Pstream::broadcastList(ListType& list, const label comm)
{
if (is_contiguous<typename ListType::value_type>::value)
{
// List data are contiguous
// 1. broadcast the size
// 2. resize for receiver list
// 3. broadcast contiguous contents
if (UPstream::is_parallel(comm))
{
label len(list.size());
UPstream::broadcast
(
reinterpret_cast<char*>(&len),
sizeof(label),
comm,
UPstream::masterNo()
);
if (UPstream::is_subrank(comm))
{
list.resize_nocopy(len);
}
if (len)
{
UPstream::broadcast
(
list.data_bytes(),
list.size_bytes(),
comm,
UPstream::masterNo()
);
}
}
}
else if (UPstream::is_parallel(comm))
{
// List data are non-contiguous - serialize/de-serialize
if (UPstream::master(comm))
{
OPBstream os(UPstream::masterNo(), comm);
os << list;
}
else // UPstream::is_subrank(comm)
{
IPBstream is(UPstream::masterNo(), comm);
is >> list;
}
}
}
// ************************************************************************* //

View File

@ -1051,20 +1051,7 @@ Foam::Istream& Foam::ISstream::readRaw(char* data, std::streamsize count)
}
else
{
// Forward seek
// - use absolute positioning (see C++ notes about std::ifstream)
is_.seekg(is_.tellg() + std::istream::pos_type(count));
// Not sure if this is needed (as per rewind)
// some documentation indicates that ifstream needs
// seekg with values from a tellg
//
// stdStream().rdbuf()->pubseekpos
// (
// count,
// std::ios_base::seekdir::cur,
// std::ios_base::in
// );
is_.ignore(count);
}
}
syncState();
@ -1102,8 +1089,11 @@ void Foam::ISstream::rewind()
stdStream().clear(); // Clear the iostate error state flags
setGood(); // Sync local copy of iostate
// pubseekpos() rather than seekg() so that it works with gzstream
stdStream().rdbuf()->pubseekpos(0, std::ios_base::in);
// NOTE: this form of rewind does not work with igzstream.
// However, igzstream is usually wrapped as IFstream which has its
// own dedicated rewind treatment for igzstream.
}

View File

@ -76,9 +76,10 @@ inline int Foam::ISstream::peek()
inline Foam::ISstream& Foam::ISstream::getLine(std::string& str, char delim)
{
std::getline(is_, str, delim);
std::streamsize count = is_.gcount();
syncState();
if (delim == '\n')
if (delim == '\n' && count > 0)
{
++lineNumber_;
}
@ -90,11 +91,10 @@ inline Foam::ISstream& Foam::ISstream::getLine(std::string& str, char delim)
inline std::streamsize Foam::ISstream::getLine(std::nullptr_t, char delim)
{
is_.ignore(std::numeric_limits<std::streamsize>::max(), delim);
std::streamsize count = is_.gcount();
syncState();
std::streamsize count = is_.gcount();
if (delim == '\n' && count)
if (delim == '\n' && count > 0)
{
++lineNumber_;
}

View File

@ -259,7 +259,6 @@ public:
//- Rewind the output stream
virtual void rewind()
{
// pubseekpos() instead of seekp() for symmetry with other classes
stream_.rdbuf()->pubseekpos(0, std::ios_base::out);
}

View File

@ -28,8 +28,8 @@ License
#include "error.H"
#include "ITstream.H"
#include "SpanStream.H"
#include "StringStream.H"
#include "UIListStream.H"
#include <memory>
// * * * * * * * * * * * * * * Static Data Members * * * * * * * * * * * * * //
@ -94,7 +94,7 @@ Foam::tokenList Foam::ITstream::parse
IOstreamOption streamOpt
)
{
UIListStream is(input, streamOpt);
ISpanStream is(input, streamOpt);
tokenList tokens;
parseStream(is, tokens);
@ -108,7 +108,7 @@ Foam::tokenList Foam::ITstream::parse
IOstreamOption streamOpt
)
{
UIListStream is(input.data(), input.length(), streamOpt);
ISpanStream is(input, streamOpt);
tokenList tokens;
parseStream(is, tokens);
@ -122,7 +122,7 @@ Foam::tokenList Foam::ITstream::parse
IOstreamOption streamOpt
)
{
UIListStream is(input, strlen(input), streamOpt);
ISpanStream is(input, strlen(input), streamOpt);
tokenList tokens;
parseStream(is, tokens);
@ -261,7 +261,7 @@ Foam::ITstream::ITstream
:
ITstream(streamOpt, name)
{
UIListStream is(input, streamOpt);
ISpanStream is(input, streamOpt);
parseStream(is, static_cast<tokenList&>(*this));
ITstream::seek(0); // rewind(), but bypasss virtual
@ -277,7 +277,7 @@ Foam::ITstream::ITstream
:
ITstream(streamOpt, name)
{
UIListStream is(input.data(), input.length(), streamOpt);
ISpanStream is(input.data(), input.length(), streamOpt);
parseStream(is, static_cast<tokenList&>(*this));
ITstream::seek(0); // rewind(), but bypasss virtual
@ -293,7 +293,7 @@ Foam::ITstream::ITstream
:
ITstream(streamOpt, name)
{
UIListStream is(input, strlen(input), streamOpt);
ISpanStream is(input, strlen(input), streamOpt);
parseStream(is, static_cast<tokenList&>(*this));
ITstream::seek(0); // rewind(), but bypasss virtual

View File

@ -4,8 +4,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef IStringStream_H
#define IStringStream_H
#ifndef FoamCompat_IStringStream_H
#define FoamCompat_IStringStream_H
#include "StringStream.H"

View File

@ -0,0 +1,10 @@
// Compatibility include.
#ifndef FoamCompat_ListStream_H
#define FoamCompat_ListStream_H
#include "SpanStream.H"
#endif
// ************************************************************************* //

View File

@ -0,0 +1,10 @@
// Compatibility include.
#ifndef FoamCompat_OListStream_H
#define FoamCompat_UListStream_H
#include "SpanStream.H"
#endif
// ************************************************************************* //

View File

@ -4,8 +4,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef OStringStream_H
#define OStringStream_H
#ifndef FoamCompat_OStringStream_H
#define FoamCompat_OStringStream_H
#include "StringStream.H"

View File

@ -0,0 +1,10 @@
// Compatibility include.
#ifndef FoamCompat_UIListStream_H
#define FoamCompat_UIListStream_H
#include "SpanStream.H"
#endif
// ************************************************************************* //

View File

@ -0,0 +1,10 @@
// Compatibility include.
#ifndef FoamCompat_UListStream_H
#define FoamCompat_UListStream_H
#include "SpanStream.H"
#endif
// ************************************************************************* //

View File

@ -0,0 +1,10 @@
// Compatibility include.
#ifndef FoamCompat_UOListStream_H
#define FoamCompat_UOListStream_H
#include "SpanStream.H"
#endif
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2019-2022 OpenCFD Ltd.
Copyright (C) 2019-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -54,23 +54,21 @@ class osha1stream
public std::ostream
{
//- A streambuf class for calculating SHA1 digests
class sha1buf
:
public std::streambuf
class sha1buf : public std::streambuf
{
//- This does all the work and has its own buffering
SHA1 sha1_;
protected:
//- Handle overflow
virtual int overflow(int c = EOF)
//- Output overflow handling - append to SHA1
virtual int overflow(int_type c = traits_type::eof())
{
if (c != EOF) sha1_.append(c);
if (c != traits_type::eof()) sha1_.append(c);
return c;
}
//- Put sequence of characters
//- Put sequence of characters - append to SHA1
virtual std::streamsize xsputn(const char* s, std::streamsize n)
{
if (n) sha1_.append(s, n);
@ -83,10 +81,7 @@ class osha1stream
sha1buf() = default;
//- Full access to the sha1
SHA1& sha1() noexcept
{
return sha1_;
}
SHA1& sha1() noexcept { return sha1_; }
};
@ -100,25 +95,22 @@ public:
// Constructors
//- Default construct
osha1stream()
:
std::ostream(&buf_)
{}
osha1stream() : std::ostream(&buf_) {}
// Member Functions
//- This hides both signatures of std::basic_ios::rdbuf()
sha1buf* rdbuf()
{
return &buf_;
}
sha1buf* rdbuf() { return &buf_; }
//- Full access to the sha1
SHA1& sha1() noexcept
{
return buf_.sha1();
}
SHA1& sha1() noexcept { return buf_.sha1(); }
//- Return SHA1::Digest for the data processed until now
SHA1Digest digest() { return buf_.sha1().digest(); }
//- Clear the SHA1 calculation
void reset() { buf_.sha1().clear(); }
};
@ -129,48 +121,21 @@ namespace Detail
Class Detail::OSHA1streamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- Allocator for an osha1stream
//- An allocator for holding Foam::osha1stream
class OSHA1streamAllocator
{
protected:
// Protected Data
typedef osha1stream stream_type;
//- The output stream
stream_type stream_;
Foam::osha1stream stream_;
// Constructors
//- Default construct
OSHA1streamAllocator() = default;
public:
// Member Functions
//- Full access to the sha1
SHA1& sha1() noexcept
{
return stream_.sha1();
}
//- Return SHA1::Digest for the data processed until now
SHA1Digest digest()
{
return stream_.sha1().digest();
}
//- Clear the SHA1 calculation
void reset()
{
return stream_.sha1().clear();
}
};
} // End namespace Detail
@ -188,16 +153,15 @@ class OSHA1stream
{
typedef Detail::OSHA1streamAllocator allocator_type;
// Private Member Functions
//- No copy construct
OSHA1stream(const OSHA1stream&) = delete;
//- No copy assignment
void operator=(const OSHA1stream&) = delete;
public:
//- No copy construct
OSHA1stream(const OSHA1stream&) = delete;
//- No copy assignment
void operator=(const OSHA1stream&) = delete;
// Constructors
//- Construct with an empty digest
@ -211,6 +175,18 @@ public:
{}
// Member Functions
//- Full access to the sha1
SHA1& sha1() noexcept { return stream_.sha1(); }
//- Return SHA1::Digest for the data processed until now
SHA1Digest digest() { return stream_.digest(); }
//- Clear the SHA1 calculation
void reset() { stream_.reset(); }
// Write Functions
//- Add (unquoted) string contents.
@ -227,7 +203,7 @@ public:
// \deprecated(2017-07) - use reset() method
void rewind()
{
sha1().clear();
stream_.sha1().clear();
}

View File

@ -0,0 +1,352 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2023 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 <http://www.gnu.org/licenses/>.
Class
Foam::ICharStream
Description
An input stream that reads from a List and manages the List storage.
Similar to IStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying.
See Also
Foam::OCharStream
Foam::ISpanStream
Foam::OSpanStream
\*---------------------------------------------------------------------------*/
#ifndef Foam_ICharStream_H
#define Foam_ICharStream_H
#include "ISpanStream.H"
#include "List.H"
#include "DynamicList.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class icharstream;
class ICharStream;
// Older names (prior to 2023-08)
typedef ICharStream IListStream;
/*---------------------------------------------------------------------------*\
Class icharstream Declaration
\*---------------------------------------------------------------------------*/
//- Similar to std::istringstream, but with the ability to swap
//- character content.
//- Has some similarity to std::ispanstream (C++23)
class icharstream
:
virtual public std::ios,
protected Foam::memorybuf::in_dynamic,
public std::istream
{
typedef Foam::memorybuf::in_dynamic buffer_type;
typedef std::istream stream_type;
public:
// Constructors
//- Default construct - empty
icharstream()
:
buffer_type(),
stream_type(static_cast<buffer_type*>(this))
{}
//- Copy construct from content
icharstream(const char* buffer, size_t nbytes)
:
icharstream()
{
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)
:
icharstream()
{
swap(buffer);
}
//- Move construct from DynamicList
template<int SizeMin>
icharstream(DynamicList<char,SizeMin>&& buffer)
:
icharstream()
{
swap(buffer);
}
// Member Functions
//- The current get position within the buffer (tellg)
std::streampos input_pos() const
{
return buffer_type::span_tellg();
}
//- The get buffer capacity
std::streamsize capacity() const
{
return buffer_type::span_capacity();
}
//- The number of characters remaining in the get area.
//- Same as (capacity() - input_pos())
std::streamsize remaining() const
{
return buffer_type::span_remaining();
}
//- Span of the input characters (is modifiable!)
UList<char> list() const
{
return buffer_type::span_list();
}
//- Rewind the stream, clearing any old errors
void rewind()
{
buffer_type::pubseekpos(0, std::ios_base::in);
stream_type::clear(); // Clear old errors
}
//- Reset content (copy)
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
void swap(List<char>& other)
{
buffer_type::swap(other);
stream_type::clear(); // Clear old errors
}
//- Transfer list contents to a DynamicList buffer
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
buffer_type::swap(other);
stream_type::clear(); // Clear old errors
}
//- Some information about the input buffer position/capacity
void debug_info(Ostream& os) const
{
os << "get="
<< input_pos() << '/' << capacity();
}
};
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::ICharStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An allocator for holding Foam::icharstream
class ICharStreamAllocator
{
protected:
// Protected Data
//- The stream
Foam::icharstream stream_;
// Constructors
//- Default construct
ICharStreamAllocator() = default;
};
} // End namespace Detail
/*---------------------------------------------------------------------------*\
Class ICharStream Declaration
\*---------------------------------------------------------------------------*/
//- An ISstream with internal List storage. Always UNCOMPRESSED.
class ICharStream
:
public Detail::ICharStreamAllocator,
public Foam::ISstream
{
typedef Detail::ICharStreamAllocator allocator_type;
public:
// Constructors
//- Default construct (empty), optionally with specified stream option
explicit ICharStream
(
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(),
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
{}
//- Copy construct from string content
explicit ICharStream
(
const std::string& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
ICharStream(streamOpt)
{
stream_.reset(buffer.data(), buffer.size());
}
//- Move construct from List
explicit ICharStream
(
::Foam::List<char>&& buffer, // Fully qualify (issue #1521)
IOstreamOption streamOpt = IOstreamOption()
)
:
ICharStream(streamOpt)
{
stream_.swap(buffer);
}
//- Move construct from DynamicList (uses current size)
template<int SizeMin>
explicit ICharStream
(
DynamicList<char,SizeMin>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
ICharStream(streamOpt)
{
stream_.swap(buffer);
}
// Member Functions
//- Position of the get buffer
std::streampos tellg() const { return stream_.input_pos(); }
//- The current get position within the buffer (tellg)
std::streampos input_pos() const { return stream_.input_pos(); }
//- The input list size. Same as capacity()
label size() const { return label(stream_.capacity()); }
//- The get buffer capacity
std::streamsize capacity() const { return stream_.capacity(); }
//- The number of characters remaining in the get area.
//- Same as (capacity() - input_pos())
std::streamsize remaining() const { return stream_.remaining(); }
//- Span of the input characters (is modifiable!)
UList<char> list() const { return stream_.list(); }
//- Rewind the stream, clearing any old errors
virtual void rewind()
{
stream_.rewind();
syncState();
}
//- Reset content (copy)
void reset(const char* buffer, size_t nbytes)
{
stream_.reset(buffer, nbytes);
syncState();
}
//- Transfer list contents to List buffer
void swap(List<char>& other)
{
stream_.swap(other);
syncState();
}
//- Transfer list contents to a DynamicList buffer
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
stream_.swap(other);
syncState();
}
//- Print stream description to Ostream
virtual void print(Ostream& os) const;
// Member Operators
//- A non-const reference to const Istream
// Needed for read-constructors where the stream argument is temporary
Istream& operator()() const
{
// Could also rewind
return const_cast<ICharStream&>(*this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -1,261 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2022 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 <http://www.gnu.org/licenses/>.
Class
Foam::IListStream
Description
An input stream that reads from a List and manages the List storage.
Similar to IStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying.
See Also
Foam::OListStream
Foam::UIListStream
Foam::UOListStream
\*---------------------------------------------------------------------------*/
#ifndef Foam_IListStream_H
#define Foam_IListStream_H
#include "List.H"
#include "UIListStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::IListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer input allocator with List storage
class IListStreamAllocator
:
private List<char>,
public UIListStreamAllocator
{
protected:
// Constructors
//- Default construct
IListStreamAllocator()
:
List<char>(),
UIListStreamAllocator(List<char>::data(), List<char>::size())
{}
//- Move construct from List
IListStreamAllocator(List<char>&& buffer)
:
List<char>(std::move(buffer)),
UIListStreamAllocator(List<char>::data(), List<char>::size())
{}
//- Move construct from DynamicList
template<int SizeMin>
IListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
:
List<char>(std::move(buffer)),
UIListStreamAllocator(List<char>::data(), List<char>::size())
{}
// Protected Member Functions
//- Convenience method to address the underlying List storage
inline void reset_gbuffer()
{
UIListStreamAllocator::reset
(
List<char>::data(),
List<char>::size()
);
}
public:
// Member Functions
//- The current get position in the buffer
using UIListStreamAllocator::size;
//- Clear storage
inline void clearStorage()
{
List<char>::clear();
reset_gbuffer();
}
//- Transfer contents to other List
inline void swap(List<char>& list)
{
List<char>::swap(list);
reset_gbuffer();
}
};
} // End namespace Detail
/*---------------------------------------------------------------------------*\
Class IListStream Declaration
\*---------------------------------------------------------------------------*/
//- An ISstream with internal List storage. Always UNCOMPRESSED.
class IListStream
:
public Detail::IListStreamAllocator,
public ISstream
{
typedef Detail::IListStreamAllocator allocator_type;
public:
// Constructors
//- Default construct with an empty list
explicit IListStream
(
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(),
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
{}
//- Move construct from List
explicit IListStream
(
::Foam::List<char>&& buffer, // Fully qualify (issue #1521)
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(std::move(buffer)),
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
{}
//- Move construct from DynamicList
template<int SizeMin>
explicit IListStream
(
DynamicList<char,SizeMin>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(std::move(buffer)),
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
{}
// Member Functions
//- The current get position in the buffer
using allocator_type::size;
//- Return the current get position in the buffer
std::streampos pos() const
{
return allocator_type::tellg();
}
//- Rewind the stream, clearing any old errors
virtual void rewind()
{
allocator_type::rewind();
setGood(); // resynchronize with internal state
}
//- Print stream description to Ostream
virtual void print(Ostream& os) const;
// Member Operators
//- A non-const reference to const Istream
// Needed for read-constructors where the stream argument is temporary
Istream& operator()() const
{
// Could also rewind
return const_cast<IListStream&>(*this);
}
// Additional constructors and methods (as per v2012 and earlier)
#ifdef Foam_IOstream_extras
//- Construct with an empty list
explicit IListStream
(
IOstreamOption::streamFormat fmt
)
:
IListStream(IOstreamOption(fmt))
{}
//- Move construct from List
IListStream
(
::Foam::List<char>&& buffer, // Fully qualify (issue #1521)
IOstreamOption::streamFormat fmt
)
:
IListStream(std::move(buffer), IOstreamOption(fmt))
{}
//- Move construct from DynamicList
template<int SizeMin>
explicit IListStream
(
DynamicList<char,SizeMin>&& buffer,
IOstreamOption::streamFormat fmt
)
:
IListStream(std::move(buffer), IOstreamOption(fmt))
{}
#endif /* Foam_IOstream_extras */
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,352 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2023 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 <http://www.gnu.org/licenses/>.
Class
Foam::ISpanStream
Description
Similar to IStringStream but using an externally managed buffer for its
input. This allows the input buffer to be filled (and refilled) from
various sources.
Note that this stream will normally be used as a "one-shot" reader.
Caution must be exercised that the referenced buffer remains valid and
without any intermediate resizing for the duration of the stream's use.
An example of possible use:
\code
DynamicList<char> buffer(4096); // allocate some large buffer
nread = something.read(buffer.data(),1024); // fill with content
buffer.resize(nread); // content size
// Construct dictionary, or something else
ISpanStream is(buffer)
dictionary dict1(is);
// Sometime later
nread = something.read(buffer.data(),2048); // fill with content
buffer.resize(nread); // content size
// Without intermediate variable
dictionary dict2(ISpanStream(buffer)());
\endcode
See Also
Foam::ICharStream
Foam::OCharStream
Foam::OSpanStream
\*---------------------------------------------------------------------------*/
#ifndef Foam_ISpanStream_H
#define Foam_ISpanStream_H
#include "UList.H"
#include "ISstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class ispanstream;
class ISpanStream;
// Older names (prior to 2023-08)
typedef ispanstream uiliststream;
typedef ISpanStream UIListStream;
/*---------------------------------------------------------------------------*\
Class ispanstream Declaration
\*---------------------------------------------------------------------------*/
//- Similar to std::istringstream, but with an externally managed input buffer
//- which makes it most similar to std::ispanstream (C++23)
// This allows the input buffer to be filled or refilled from various sources
// without copying.
class ispanstream
:
virtual public std::ios,
protected Foam::memorybuf::in_base,
public std::istream
{
typedef Foam::memorybuf::in_base buffer_type;
typedef std::istream stream_type;
public:
// Constructors
//- Default construct - empty
ispanstream()
:
buffer_type(),
stream_type(static_cast<buffer_type*>(this))
{}
//- Construct (shallow copy) for character array and number of bytes
ispanstream(const char* buffer, size_t nbytes)
:
buffer_type(const_cast<char*>(buffer), nbytes),
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))
// {}
// Member Functions
//- The current get position within the buffer (tellg)
std::streampos input_pos() const
{
return buffer_type::span_tellg();
}
//- The get buffer capacity
std::streamsize capacity() const
{
return buffer_type::span_capacity();
}
//- The number of characters remaining in the get area.
//- Same as (capacity() - input_pos())
std::streamsize remaining() const
{
return buffer_type::span_remaining();
}
//- Span of the input characters (is modifiable!)
UList<char> list() const
{
return buffer_type::span_list();
}
//- Rewind the stream, clearing any old errors
void rewind()
{
buffer_type::pubseekpos(0, std::ios_base::in);
stream_type::clear(); // Clear old errors
}
//- Reset the get buffer area
void reset(const char* buffer, size_t nbytes)
{
buffer_type::resetg(const_cast<char*>(buffer), nbytes);
stream_type::clear(); // Clear old errors
}
//- Reset the get buffer area to use the data from a string
void reset(const std::string& s)
{
buffer_type::resetg(const_cast<char*>(&s[0]), s.size());
stream_type::clear(); // Clear old errors
}
//- Some information about the input buffer position/capacity
void debug_info(Ostream& os) const
{
os << "get="
<< input_pos() << '/' << capacity();
}
};
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::ISpanStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An allocator for holding Foam::ispanstream
class ISpanStreamAllocator
{
protected:
// Protected Data
//- The stream
Foam::ispanstream stream_;
// Constructors
//- Default construct (empty)
ISpanStreamAllocator() = default;
};
} // End namespace Detail
/*---------------------------------------------------------------------------*\
Class ISpanStream Declaration
\*---------------------------------------------------------------------------*/
class ISpanStream
:
public Detail::ISpanStreamAllocator,
public Foam::ISstream
{
typedef Detail::ISpanStreamAllocator allocator_type;
public:
// Constructors
//- Default construct (empty), optionally with specified stream option
explicit ISpanStream
(
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(),
ISstream(stream_, "input", streamOpt.format(), streamOpt.version())
{}
//- Construct using specified buffer and number of bytes
ISpanStream
(
const char* buffer,
size_t nbytes,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(streamOpt)
{
reset(buffer, nbytes);
}
//- Use data area from string content
explicit ISpanStream
(
const std::string& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(streamOpt)
{
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
(
const ::Foam::UList<char>& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
ISpanStream(buffer.cdata(), buffer.size(), streamOpt)
{}
// Member Functions
//- Position of the get buffer
std::streampos tellg() const { return stream_.input_pos(); }
//- The current get position within the buffer (tellg)
std::streampos input_pos() const { return stream_.input_pos(); }
//- The input list size. Same as capacity()
label size() const { return label(stream_.capacity()); }
//- The get buffer capacity
std::streamsize capacity() const { return stream_.capacity(); }
//- The number of characters remaining in the get area.
//- 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(); }
//- Reset input area, position to buffer start and clear errors
void reset(const char* buffer, size_t nbytes)
{
stream_.reset(buffer, nbytes);
syncState();
}
//- Reset input area to use data from a string
void reset(const std::string& s)
{
stream_.reset(s);
syncState();
}
//- Rewind the stream, clearing any old errors
virtual void rewind()
{
stream_.rewind();
syncState();
}
//- Print stream description to Ostream
virtual void print(Ostream& os) const;
// Member Operators
//- A non-const reference to const Istream
// Needed for read-constructors where the stream argument is temporary
Istream& operator()() const
{
// Could also rewind
return const_cast<ISpanStream&>(*this);
}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -0,0 +1,316 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2023 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 <http://www.gnu.org/licenses/>.
Class
Foam::OCharStream
Description
An output stream that writes to a List and manages the List storage.
Similar to OStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying.
The default initial size is 512-bytes and uses size doubling.
After construction can use the reserve() method to adjust this.
See Also
Foam::ICharStream
Foam::OSpanStream
Foam::ISpanStream
\*---------------------------------------------------------------------------*/
#ifndef Foam_OCharStream_H
#define Foam_OCharStream_H
#include "OSpanStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
// Forward Declarations
class ocharstream;
class OCharStream;
// Older names (prior to 2023-08)
typedef OCharStream OListStream;
/*---------------------------------------------------------------------------*\
Class ocharstream Declaration
\*---------------------------------------------------------------------------*/
//- Similar to std::ostringstream, but with the ability to swap
//- character content.
//- Has some similarity to std::ospanstream (C++23)
class ocharstream
:
virtual public std::ios,
protected Foam::memorybuf::out_dynamic,
public std::ostream
{
typedef Foam::memorybuf::out_dynamic buffer_type;
typedef std::ostream stream_type;
public:
// Constructors
//- Default construct - empty
ocharstream()
:
buffer_type(),
stream_type(static_cast<buffer_type*>(this))
{}
//- Move construct from List
ocharstream(List<char>&& buffer)
:
ocharstream()
{
swap(buffer);
}
//- Move construct from DynamicList
template<int SizeMin>
ocharstream(DynamicList<char,SizeMin>&& buffer)
:
ocharstream()
{
swap(buffer);
}
// Member Functions
//- The current output position within the buffer (tellp)
std::streampos output_pos() const
{
return (buffer_type::span_tellp());
}
//- The put buffer capacity
std::streamsize capacity() const
{
return buffer_type::span_capacity();
}
//- Reserve output space for at least this amount
void reserve(const std::streamsize 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
void rewind()
{
buffer_type::pubseekpos(0, std::ios_base::out);
stream_type::clear(); // Clear old errors
}
//- Transfer list contents to List buffer
void swap(List<char>& other)
{
buffer_type::swap(other);
stream_type::clear(); // Clear old errors
}
//- Transfer list contents to a DynamicList buffer
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
buffer_type::swap(other);
stream_type::clear(); // Clear old errors
}
//- Some information about the output buffer position/capacity
void debug_info(Ostream& os) const
{
os << "put="
<< output_pos() << '/' << capacity();
}
};
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::OCharStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An allocator for holding Foam::ocharstream
class OCharStreamAllocator
{
protected:
// Protected Data
//- The stream
Foam::ocharstream stream_;
// Constructors
//- Default construct - empty
OCharStreamAllocator() = default;
};
} // End namespace Detail
/*---------------------------------------------------------------------------*\
Class OCharStream Declaration
\*---------------------------------------------------------------------------*/
//- An OSstream with internal List storage
class OCharStream
:
public Detail::OCharStreamAllocator,
public Foam::OSstream
{
typedef Detail::OCharStreamAllocator allocator_type;
public:
// Constructors
//- Default construct (empty output)
explicit OCharStream
(
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(),
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
explicit OCharStream
(
::Foam::List<char>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
OCharStream(streamOpt)
{
stream_.swap(buffer);
}
//- Move construct from a DynamicList (uses entire capacity)
template<int SizeMin>
explicit OCharStream
(
::Foam::DynamicList<char,SizeMin>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
OCharStream(streamOpt)
{
stream_.swap(buffer);
}
// Member Functions
//- Position of the put buffer
std::streampos tellp() const { return stream_.output_pos(); }
//- The current output position within the buffer (tellp)
std::streampos output_pos() const { return stream_.output_pos(); }
//- The current output size. Same as tellp(), output_pos()
label size() const { return label(stream_.output_pos()); }
//- The put buffer capacity
std::streamsize capacity() const { return stream_.capacity(); }
//- Reserve output space for at least this amount
void reserve(const std::streamsize n) { stream_.reserve(n); }
//- Span of the current output characters (is modifiable!)
UList<char> list() const { return stream_.list(); }
//- Rewind the stream, clearing any old errors
virtual void rewind()
{
stream_.rewind();
syncState();
}
//- Transfer list contents to List buffer
void swap(List<char>& other)
{
stream_.swap(other);
syncState();
}
//- Transfer list contents to a DynamicList buffer
template<int SizeMin>
void swap(DynamicList<char,SizeMin>& other)
{
stream_.swap(other);
syncState();
}
//- Print stream description to Ostream
virtual void print(Ostream& os) const;
// Houskeeping
//- Block size was used in OpenFOAM-v2306 and earlier
void setBlockSize(int n) {}
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2016-2021 OpenCFD Ltd.
Copyright (C) 2016-2023 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -42,103 +42,6 @@ Description
namespace Foam
{
/*---------------------------------------------------------------------------*\
Class countstreambuf Declaration
\*---------------------------------------------------------------------------*/
//- A streambuf class for determining byte counts
class countstreambuf
:
public std::streambuf
{
//- The number of bytes counted
std::streamsize size_;
protected:
//- Set position pointer to relative position
virtual std::streampos seekoff
(
std::streamoff off,
std::ios_base::seekdir way,
std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
)
{
if (which & std::ios_base::out)
{
if (way == std::ios_base::beg)
{
size_ = off;
}
else if (way == std::ios_base::cur)
{
size_ += off;
}
else if (way == std::ios_base::end)
{
// not really possible
}
return size_; // tellp()
}
return -1;
}
//- Set position pointer to absolute position
// For the counter, adjust the count accordingly.
virtual std::streampos seekpos
(
std::streampos pos,
std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
)
{
return seekoff(pos, std::ios_base::beg, which);
}
//- Handle output counting via overflow
virtual int overflow(int c = EOF)
{
if (c != EOF)
{
++size_;
}
return c;
}
//- Put sequence of characters
virtual std::streamsize xsputn(const char* s, std::streamsize n)
{
size_ += n;
return n;
}
public:
//- Default construct, or with precount size
explicit countstreambuf(std::streamsize precount=0)
:
size_(precount)
{}
//- \return The buffer put position == number of bytes counted.
std::streamsize tellp() const
{
return size_;
}
//- Some information about the number of bytes counted
void printBufInfo(Ostream& os) const
{
os << "count=" << size_;
}
};
/*---------------------------------------------------------------------------*\
Class ocountstream Declaration
\*---------------------------------------------------------------------------*/
@ -149,34 +52,124 @@ public:
class ocountstream
:
virtual public std::ios,
protected countstreambuf,
public std::ostream
{
//- A streambuf class for determining byte counts
class countbuf : public std::streambuf
{
//- The number of bytes counted
std::streamsize size_;
protected:
//- Set position pointer to relative position
virtual std::streampos seekoff
(
std::streamoff off,
std::ios_base::seekdir way,
std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
)
{
if (which & std::ios_base::out)
{
if (way == std::ios_base::beg)
{
size_ = off;
}
else if (way == std::ios_base::cur)
{
size_ += off;
}
else if (way == std::ios_base::end)
{
// not really possible
}
return size_; // Like span_tellp()
}
return -1;
}
//- Set position pointer to absolute position
// For the counter, adjust the count accordingly.
virtual std::streampos seekpos
(
std::streampos pos,
std::ios_base::openmode which = std::ios_base::in|std::ios_base::out
)
{
return seekoff(pos, std::ios_base::beg, which);
}
//- Output overflow handling - increment counter
virtual int overflow(int_type c = traits_type::eof())
{
if (c != traits_type::eof()) ++size_;
return c;
}
//- Put sequence of characters - increment counter
virtual std::streamsize xsputn(const char* s, std::streamsize n)
{
size_ += n;
return n;
}
public:
// Constructors
//- Default construct, count = 0
countbuf() : size_(0) {}
// Member Functions
//- The number of bytes counted.
std::streamsize count() const noexcept { return size_; }
//- Reset the count
void reset(std::streamsize n = 0) noexcept { size_ = n; }
};
// Private Data
typedef countbuf buffer_type;
typedef std::ostream stream_type;
//- Reference to the underlying buffer
buffer_type buf_;
public:
//- Default construct
ocountstream()
:
countstreambuf(),
std::ostream(static_cast<countstreambuf*>(this))
{}
// Constructors
//- Default construct
ocountstream() : stream_type(&buf_) {}
//- \return The buffer put position == number of bytes counted.
using countstreambuf::tellp;
// Member Functions
//- \return The number of bytes counted
std::streamsize size() const
{
return countstreambuf::tellp();
}
//- This hides both signatures of std::basic_ios::rdbuf()
countbuf* rdbuf() { return &buf_; }
//- Rewind the stream, reset the count
void rewind()
{
this->pubseekpos(0, std::ios_base::out);
clear(); // for safety, clear any old errors
}
//- \return The number of bytes counted
std::streamsize count() const noexcept { return buf_.count(); }
//- Reset the count
void reset(std::streamsize n = 0) noexcept
{
buf_.reset(n);
stream_type::clear(); // Clear old errors
}
//- Some information about the output buffer position/capacity
void debug_info(Ostream& os) const
{
os << "count=" << buf_.count();
}
};
@ -187,55 +180,21 @@ namespace Detail
Class Detail::OCountStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer allocator for counting
//- An allocator for holding Foam::ocountstream
class OCountStreamAllocator
{
protected:
// Protected Data
typedef std::ostream stream_type;
//- The stream buffer
countstreambuf buf_;
//- The output stream
stream_type stream_;
Foam::ocountstream stream_;
// Constructors
//- Default construct, or with precount size
OCountStreamAllocator(std::streamsize precount=0)
:
buf_(precount),
stream_(&buf_)
{}
// Protected Member Functions
void printBufInfo(Ostream& os) const
{
buf_.printBufInfo(os);
}
public:
// Member Functions
//- The number of bytes counted
std::streamsize size() const
{
return buf_.tellp();
}
//- Rewind the stream, reset the count
void rewind()
{
buf_.pubseekpos(0);
stream_.clear(); // for safety, clear any old errors
}
//- Default construct
OCountStreamAllocator() = default;
};
} // End namespace Detail
@ -270,35 +229,33 @@ public:
//- Copy construct
OCountStream(const OCountStream& str)
:
allocator_type(str.size()),
allocator_type(),
OSstream(stream_, str.name(), static_cast<IOstreamOption>(str))
{}
{
stream_.reset(str.count());
}
// Member Functions
//- \return The number of bytes counted
std::streamsize count() const noexcept { return stream_.count(); }
//- \return The number of bytes counted
std::streamsize size() const noexcept { return stream_.count(); }
//- Reset the count
void reset(std::streamsize n = 0) noexcept { stream_.reset(n); }
//- Rewind the stream, reset the count, clearing any old errors
virtual void rewind()
{
allocator_type::rewind();
setGood(); // resynchronize with internal state
stream_.reset();
syncState();
}
//- Print stream description to Ostream
virtual void print(Ostream& os) const;
// Additional constructors and methods (as per v2012 and earlier)
#ifdef Foam_IOstream_extras
//- Construct empty with format
explicit OCountStream(IOstreamOption::streamFormat fmt)
:
OCountStream(IOstreamOption(fmt))
{}
#endif /* Foam_IOstream_extras */
};

View File

@ -1,522 +0,0 @@
/*---------------------------------------------------------------------------*\
========= |
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
\\ / O peration |
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017-2022 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 <http://www.gnu.org/licenses/>.
Class
Foam::OListStream
Description
An output stream that writes to a List and manages the List storage.
Similar to OStringStream but with a List for its storage instead of
as string to allow reuse of List contents without copying.
The default list size is 512-bytes with a 256-byte block increment.
These values can be changed after construction using the reserve() and
the setBlockSize() methods.
See Also
Foam::IListStream
Foam::UOListStream
Foam::UIListStream
\*---------------------------------------------------------------------------*/
#ifndef Foam_OListStream_H
#define Foam_OListStream_H
#include "DynamicList.H"
#include "OSstream.H"
#include "memoryStreamBuffer.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
namespace Foam
{
namespace Detail
{
/*---------------------------------------------------------------------------*\
Class Detail::OListStreamAllocator Declaration
\*---------------------------------------------------------------------------*/
//- An stream/stream-buffer output allocator with DynamicList-like storage
class OListStreamAllocator
{
//- A streambuf adapter with resizing similar to DynamicList
class dynbuf
:
public memorybuf::out
{
friend class OListStreamAllocator;
//- Helper for block size - small list minimum of 64 bytes.
constexpr static int min_size(int n)
{
return stdFoam::max(64, n);
}
//- Block size when resizing the list
int block_ = 256;
//- Underlying list storage.
// Internally manage like a DynamicList, with its capacity known
// from the list size and the addressable size known through the
// stream pointers.
List<char> storage_;
protected:
//- Increment capacity directly and adjust buffer pointers to
//- correspond with the storage size.
inline void minCapacity
(
const std::streamsize n,
const std::streamsize cur = 0
)
{
const auto newEnd = n + cur;
if (newEnd > storage_.size())
{
auto newCapacity =
(
(storage_.size() + block_)
- (storage_.size() % block_)
);
while (newCapacity < newEnd)
{
newCapacity += block_;
}
// Info<<"request:" << newEnd
// << " cur cap:" << storage_.size()
// << " new cap:" << newCapacity
// << " pos:" << cur
// << " incr:" << incr << endl;
storage_.resize(newCapacity);
sync_pbuffer();
pbump(cur);
}
}
//- Define new increment
inline void setBlockSize(const int i)
{
const auto prev = block_;
block_ = min_size(i);
if (block_ > prev)
{
minCapacity(0, tellp());
}
}
//- Handle overflow
virtual int overflow(int c = EOF)
{
if (c != EOF)
{
// Need another output block
minCapacity(block_, tellp());
*(pptr()) = c;
pbump(1);
}
return c;
}
//- Put sequence of characters
virtual std::streamsize xsputn(const char* s, std::streamsize n)
{
// Enough space so that appends work without problem
minCapacity(n, tellp());
std::streamsize count = 0;
while (count < n && pptr() < epptr())
{
*(pptr()) = *(s + count++);
pbump(1);
}
return count;
}
//- Initialize put buffer
void init_pbuffer(const std::streamsize n)
{
sync_pbuffer();
minCapacity(n);
}
public:
// Constructors
//- Default construct, with initial reserved number of bytes
dynbuf(size_t nbytes = 512)
:
storage_()
{
init_pbuffer(min_size(nbytes));
}
//- Move construct from List
dynbuf(List<char>&& buffer)
:
storage_(std::move(buffer))
{
init_pbuffer(block_);
}
//- Move construct from DynamicList.
template<int SizeMin>
dynbuf(DynamicList<char,SizeMin>&& buffer)
:
storage_(std::move(buffer))
{
init_pbuffer(block_);
}
// Member Functions
//- Return the current list output capacity
inline label capacity() const
{
return storage_.size();
}
//- Sync put buffer pointers to agree with list dimensions
// Sets put pointer to the begin (rewind).
inline void sync_pbuffer()
{
resetp(storage_.data(), storage_.size());
}
//- Clear storage
inline void clearStorage()
{
storage_.clear();
sync_pbuffer();
}
//- Shrink storage to addressed storage
inline void shrink()
{
const auto cur = tellp(); // Addressed area
storage_.resize(cur);
sync_pbuffer();
pbump(cur);
}
//- Transfer list contents to other List
inline void swap(List<char>& other)
{
const auto cur = tellp(); // Addressed area
storage_.swap(other);
storage_.resize(cur);
sync_pbuffer();
}
//- Transfer list contents to a DynamicList
template<int SizeMin>
inline void swap(DynamicList<char,SizeMin>& other)
{
const auto cur = tellp(); // Addressed area
storage_.swap(other); // Swap full list
other.setCapacity(other.size());
other.resize(cur);
sync_pbuffer();
}
};
protected:
// Protected Data
typedef std::ostream stream_type;
//- The stream buffer
dynbuf buf_;
//- The stream
stream_type stream_;
// Constructors
//- Default construct, with initial reserved number of bytes
OListStreamAllocator(size_t nbytes = 512)
:
buf_(nbytes),
stream_(&buf_)
{}
//- Move construct from List
OListStreamAllocator(List<char>&& buffer)
:
buf_(std::move(buffer)),
stream_(&buf_)
{}
//- Move construct from DynamicList
template<int SizeMin>
OListStreamAllocator(DynamicList<char,SizeMin>&& buffer)
:
buf_(std::move(buffer)),
stream_(&buf_)
{}
// Protected Member Functions
void printBufInfo(Ostream& os) const
{
os << "put=" << buf_.tellp()
<< "/" << buf_.capacity()
<< " block=" << buf_.block_;
}
public:
// Member Functions
//- Const UList access to the characters written (shallow copy).
inline const UList<char> list() const
{
return buf_.list();
}
//- Non-const UList access to the characters written (shallow copy).
inline UList<char> list()
{
return buf_.list();
}
//- The current list output capacity
inline label capacity() const
{
return buf_.capacity();
}
//- The current output position in the buffer,
//- which is also the addressed list size
inline label size() const
{
return buf_.tellp();
}
//- Reserve output space for at least this amount.
inline void reserve(const std::streamsize n)
{
// Also maintain current position when resizing
const auto cur = buf_.tellp();
if (n > cur)
{
buf_.minCapacity(n - cur, cur);
}
}
//- Adjust block size for output
inline void setBlockSize(int n)
{
return buf_.setBlockSize(n);
}
//- Transfer list contents to other List
inline void swap(List<char>& other)
{
buf_.swap(other);
}
//- Transfer list contents to a DynamicList
template<int SizeMin>
inline void swap(DynamicList<char,SizeMin>& other)
{
buf_.swap(other);
}
//- Shrink to addressed space, should not affect stream.
inline void shrink()
{
buf_.shrink();
}
//- Clear storage
void clearStorage()
{
buf_.clearStorage();
stream_.clear(); // for safety, clear any old errors
}
//- Move to buffer start, clear errors
void rewind()
{
buf_.pubseekpos(0, std::ios_base::out);
stream_.clear(); // for safety, clear any old errors
}
};
} // End namespace Detail
/*---------------------------------------------------------------------------*\
Class OListStream Declaration
\*---------------------------------------------------------------------------*/
//- An OSstream attached to a List
class OListStream
:
public Detail::OListStreamAllocator,
public OSstream
{
typedef Detail::OListStreamAllocator allocator_type;
public:
// Constructors
//- Default construct (empty output)
explicit OListStream
(
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(),
OSstream(stream_, "output", streamOpt.format(), streamOpt.version())
{}
//- Construct with initial reserved number of bytes
explicit OListStream
(
size_t nbytes,
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(nbytes),
OSstream(stream_, "output", streamOpt.format(), streamOpt.version())
{}
//- Move construct from an existing List
explicit OListStream
(
List<char>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(std::move(buffer)),
OSstream(stream_, "output", streamOpt.format(), streamOpt.version())
{}
//- Move construct from an existing DynamicList
template<int SizeMin>
explicit OListStream
(
DynamicList<char,SizeMin>&& buffer,
IOstreamOption streamOpt = IOstreamOption()
)
:
allocator_type(std::move(buffer)),
OSstream(stream_, "output", streamOpt.format(), streamOpt.version())
{}
// Member Functions
//- Rewind the stream, clearing any old errors
virtual void rewind()
{
allocator_type::rewind();
setGood(); // resynchronize with internal state
}
//- Print stream description to Ostream
virtual void print(Ostream& os) const;
// Additional constructors and methods (as per v2012 and earlier)
#ifdef Foam_IOstream_extras
//- Default construct (empty output)
explicit OListStream
(
IOstreamOption::streamFormat fmt
)
:
OListStream(IOstreamOption(fmt))
{}
//- Construct with initial reserved number of bytes
explicit OListStream
(
size_t nbytes,
IOstreamOption::streamFormat fmt
)
:
OListStream(nbytes, IOstreamOption(fmt))
{}
//- Move construct from an existing List
OListStream
(
List<char>&& buffer,
IOstreamOption::streamFormat fmt
)
:
OListStream(std::move(buffer), IOstreamOption(fmt))
{}
//- Move construct from an existing DynamicList
template<int SizeMin>
OListStream
(
DynamicList<char,SizeMin>&& buffer,
IOstreamOption::streamFormat fmt
)
:
OListStream(std::move(buffer), IOstreamOption(fmt))
{}
#endif /* Foam_IOstream_extras */
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
#endif
// ************************************************************************* //

Some files were not shown because too many files have changed in this diff Show More