mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: add readContents to CompactIOList, CompactIOField
- align some of the internal handling with each other and with CompactListList ENH: add readContentsSize to IOList, IOField etc. - sometimes just need to know how many elements are stored on disk without actually caring about the content. In those cases, can frequently just get that information from the first label token without needing to read anything else.
This commit is contained in:
@ -1,3 +1,3 @@
|
||||
Test-CompactIOList.C
|
||||
Test-CompactIOList.cxx
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-CompactIOList
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2020-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2020-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,7 +25,7 @@ License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Application
|
||||
testCompactIOList
|
||||
Test-CompactIOList
|
||||
|
||||
Description
|
||||
Simple demonstration and test application for the CompactIOList container
|
||||
@ -46,13 +46,20 @@ using namespace Foam;
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::addBoolOption("ascii", "use ascii format");
|
||||
argList::addOption("count", "number of faces");
|
||||
|
||||
#include "setRootCase.H"
|
||||
#include "createTime.H"
|
||||
|
||||
IOstreamOption streamOpt(IOstreamOption::BINARY);
|
||||
// IOstreamOption streamOpt(IOstreamOption::ASCII);
|
||||
|
||||
const label size = 20000000;
|
||||
if (args.found("ascii"))
|
||||
{
|
||||
streamOpt.format(IOstreamOption::ASCII);
|
||||
}
|
||||
|
||||
const label size = args.getOrDefault<label>("count", 20000000);
|
||||
|
||||
// Old format
|
||||
// ~~~~~~~~~~
|
||||
@ -63,39 +70,50 @@ int main(int argc, char *argv[])
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faces2",
|
||||
"faces2-plain",
|
||||
runTime.constant(),
|
||||
polyMesh::meshSubDir,
|
||||
runTime,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
),
|
||||
size
|
||||
)
|
||||
);
|
||||
|
||||
const face f(identity(4));
|
||||
faces2.resize(size, face(identity(4)));
|
||||
|
||||
forAll(faces2, i)
|
||||
{
|
||||
faces2[i] = f;
|
||||
}
|
||||
|
||||
Info<< "Constructed faceList in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
|
||||
Info<< "Plain format faceList " << faces2.objectRelPath() << nl;
|
||||
Info<< " constructed in = " << runTime.cpuTimeIncrement()
|
||||
<< " s" << endl;
|
||||
|
||||
|
||||
faces2.writeObject(streamOpt, true);
|
||||
|
||||
Info<< "Written old format faceList in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
|
||||
Info<< " wrote in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||
|
||||
// Read
|
||||
faceIOList faces3
|
||||
// Read (size only)
|
||||
label count = faceIOList::readContentsSize
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faces2",
|
||||
"faces2-plain",
|
||||
runTime.constant(),
|
||||
polyMesh::meshSubDir,
|
||||
runTime,
|
||||
IOobject::MUST_READ
|
||||
)
|
||||
);
|
||||
|
||||
Info<< " counted " << count << " faces on disk in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||
|
||||
// Read
|
||||
faceIOList faces2b
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faces2-plain",
|
||||
runTime.constant(),
|
||||
polyMesh::meshSubDir,
|
||||
runTime,
|
||||
@ -105,7 +123,7 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
);
|
||||
|
||||
Info<< "Read old format " << faces3.size() << " faceList in = "
|
||||
Info<< " read " << faces2b.size() << " faces in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
|
||||
}
|
||||
|
||||
@ -114,44 +132,54 @@ int main(int argc, char *argv[])
|
||||
// ~~~~~~~~~~
|
||||
|
||||
{
|
||||
// Construct big faceList in new format
|
||||
// Construct big faceList in compact format
|
||||
faceCompactIOList faces2
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faces2",
|
||||
"faces2-compact",
|
||||
runTime.constant(),
|
||||
polyMesh::meshSubDir,
|
||||
runTime,
|
||||
IOobject::NO_READ,
|
||||
IOobject::NO_WRITE,
|
||||
IOobject::NO_REGISTER
|
||||
),
|
||||
size
|
||||
)
|
||||
);
|
||||
|
||||
const face f(identity(4));
|
||||
faces2.resize(size, face(identity(4)));
|
||||
|
||||
forAll(faces2, i)
|
||||
{
|
||||
faces2[i] = f;
|
||||
}
|
||||
|
||||
Info<< "Constructed new format faceList in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
|
||||
Info<< "Compact format faceList" << faces2.objectRelPath() << nl;
|
||||
Info<< " constructed in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||
|
||||
|
||||
faces2.writeObject(streamOpt, true);
|
||||
|
||||
Info<< "Written new format faceList in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
|
||||
Info<< " wrote in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||
|
||||
// Read
|
||||
faceCompactIOList faces3
|
||||
// Read (size only)
|
||||
label count = faceCompactIOList::readContentsSize
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faces2",
|
||||
"faces2-compact",
|
||||
runTime.constant(),
|
||||
polyMesh::meshSubDir,
|
||||
runTime,
|
||||
IOobject::MUST_READ
|
||||
)
|
||||
);
|
||||
Info<< " counted " << count << " faces on disk in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << endl;
|
||||
|
||||
// Read
|
||||
faceCompactIOList faces2b
|
||||
(
|
||||
IOobject
|
||||
(
|
||||
"faces2-compact",
|
||||
runTime.constant(),
|
||||
polyMesh::meshSubDir,
|
||||
runTime,
|
||||
@ -161,7 +189,7 @@ int main(int argc, char *argv[])
|
||||
)
|
||||
);
|
||||
|
||||
Info<< "Read new format " << faces3.size() << " faceList in = "
|
||||
Info<< " read " << faces2b.size() << " faces in = "
|
||||
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
|
||||
}
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,41 +27,43 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "CompactIOField.H"
|
||||
#include "labelList.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
bool Foam::CompactIOField<T, BaseType>::readIOcontents(bool readOnProc)
|
||||
{
|
||||
typedef IOField<T> plain_type;
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
// Do reading
|
||||
Istream& is = readStream(word::null, readOnProc);
|
||||
|
||||
if (readOnProc)
|
||||
if (!readOnProc)
|
||||
{
|
||||
if (headerClassName() == IOField<T>::typeName)
|
||||
{
|
||||
is >> static_cast<Field<T>&>(*this);
|
||||
close();
|
||||
}
|
||||
else if (headerClassName() == typeName)
|
||||
{
|
||||
is >> *this;
|
||||
close();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Unexpected class name " << headerClassName()
|
||||
<< " expected " << typeName
|
||||
<< " or " << IOField<T>::typeName << nl
|
||||
<< " while reading object " << name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
// no-op
|
||||
}
|
||||
else if (isHeaderClass(typeName))
|
||||
{
|
||||
// Compact form
|
||||
is >> *this; // or: this->readCompact(is);
|
||||
}
|
||||
else if (isHeaderClass<plain_type>())
|
||||
{
|
||||
// Non-compact form
|
||||
is >> static_cast<content_type&>(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Unexpected class name " << headerClassName()
|
||||
<< " expected " << typeName
|
||||
<< " or " << plain_type::typeName << nl
|
||||
<< " while reading object " << name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -69,6 +71,96 @@ bool Foam::CompactIOField<T, BaseType>::readIOcontents(bool readOnProc)
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::label Foam::CompactIOField<T, BaseType>::readIOsize(bool readOnProc)
|
||||
{
|
||||
typedef IOField<T> plain_type;
|
||||
|
||||
label count(-1);
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
Istream& is = readStream(word::null, readOnProc);
|
||||
|
||||
if (!readOnProc)
|
||||
{
|
||||
// no-op
|
||||
}
|
||||
else
|
||||
{
|
||||
token tok(is);
|
||||
|
||||
if (tok.isLabel())
|
||||
{
|
||||
// The majority of files will have lists with sizing prefix
|
||||
count = tok.labelToken();
|
||||
|
||||
if (isHeaderClass(typeName))
|
||||
{
|
||||
// Compact form: read offsets, not content
|
||||
if (--count < 0)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
is.putBack(tok);
|
||||
|
||||
if (isHeaderClass(typeName))
|
||||
{
|
||||
// Compact form: can just read the offsets
|
||||
labelList offsets(is);
|
||||
count = Foam::max(0, (offsets.size()-1));
|
||||
}
|
||||
else if (isHeaderClass<plain_type>())
|
||||
{
|
||||
// Non-compact form: need to read everything
|
||||
Field<T> list(is);
|
||||
count = list.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Unexpected class name " << headerClassName()
|
||||
<< " expected " << typeName
|
||||
<< " or " << plain_type::typeName << endl
|
||||
<< " while reading object " << name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
bool Foam::CompactIOField<T, BaseType>::overflows() const
|
||||
{
|
||||
// Can safely assume that int64 will not overflow
|
||||
if constexpr (sizeof(label) < sizeof(int64_t))
|
||||
{
|
||||
const UList<T>& lists = *this;
|
||||
|
||||
label total = 0;
|
||||
for (const auto& sublist : lists)
|
||||
{
|
||||
const label prev = total;
|
||||
total += sublist.size();
|
||||
if (total < prev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
@ -153,6 +245,46 @@ Foam::CompactIOField<T, BaseType>::CompactIOField
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::label
|
||||
Foam::CompactIOField<T, BaseType>::readContentsSize(const IOobject& io)
|
||||
{
|
||||
IOobject rio(io, IOobjectOption::NO_REGISTER);
|
||||
if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// Construct NO_READ, changing after construction
|
||||
const auto rOpt = rio.readOpt(IOobjectOption::NO_READ);
|
||||
|
||||
CompactIOField<T, BaseType> reader(rio);
|
||||
reader.readOpt(rOpt);
|
||||
|
||||
return reader.readIOsize();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::Field<T>
|
||||
Foam::CompactIOField<T, BaseType>::readContents(const IOobject& io)
|
||||
{
|
||||
IOobject rio(io, IOobjectOption::NO_REGISTER);
|
||||
if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
CompactIOField<T, BaseType> reader(rio);
|
||||
|
||||
return Field<T>(std::move(static_cast<Field<T>&>(reader)));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
@ -162,7 +294,22 @@ bool Foam::CompactIOField<T, BaseType>::writeObject
|
||||
const bool writeOnProc
|
||||
) const
|
||||
{
|
||||
if (streamOpt.format() == IOstreamOption::ASCII)
|
||||
if
|
||||
(
|
||||
streamOpt.format() == IOstreamOption::BINARY
|
||||
&& overflows()
|
||||
)
|
||||
{
|
||||
streamOpt.format(IOstreamOption::ASCII);
|
||||
|
||||
WarningInFunction
|
||||
<< "Overall number of elements of CompactIOField (size:"
|
||||
<< this->size() << ") overflows a label (int"
|
||||
<< (8*sizeof(label)) << ')' << nl
|
||||
<< " Switching to ascii writing" << endl;
|
||||
}
|
||||
|
||||
if (streamOpt.format() != IOstreamOption::BINARY)
|
||||
{
|
||||
// Change type to be non-compact format type
|
||||
const word oldTypeName(typeName);
|
||||
@ -188,20 +335,98 @@ bool Foam::CompactIOField<T, BaseType>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
void Foam::CompactIOField<T, BaseType>::operator=
|
||||
(
|
||||
const CompactIOField<T, BaseType>& rhs
|
||||
)
|
||||
Foam::Istream& Foam::CompactIOField<T,BaseType>::readCompact(Istream& is)
|
||||
{
|
||||
if (this == &rhs)
|
||||
Field<T>& lists = *this;
|
||||
|
||||
// The base type for packed values
|
||||
typedef typename T::value_type base_type;
|
||||
|
||||
// Read compact: offsets + packed values
|
||||
const labelList offsets(is);
|
||||
Field<base_type> values(is);
|
||||
|
||||
// Transcribe
|
||||
const label len = Foam::max(0, (offsets.size()-1));
|
||||
lists.resize_nocopy(len);
|
||||
|
||||
auto iter = values.begin();
|
||||
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
return; // Self-assigment is a no-op
|
||||
auto& list = lists[i];
|
||||
const label count = (offsets[i+1] - offsets[i]);
|
||||
|
||||
list.resize_nocopy(count);
|
||||
|
||||
std::move(iter, iter + count, list.begin());
|
||||
|
||||
iter += count;
|
||||
}
|
||||
|
||||
Field<T>::operator=(rhs);
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::Ostream& Foam::CompactIOField<T,BaseType>::writeCompact(Ostream& os) const
|
||||
{
|
||||
const Field<T>& lists = *this;
|
||||
|
||||
// The base type for packed values
|
||||
typedef typename T::value_type base_type;
|
||||
|
||||
// Convert to compact format
|
||||
label total = 0;
|
||||
const label len = lists.size();
|
||||
|
||||
// offsets
|
||||
{
|
||||
labelList offsets(len+1);
|
||||
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
offsets[i] = total;
|
||||
total += lists[i].size();
|
||||
|
||||
if (total < offsets[i])
|
||||
{
|
||||
FatalIOErrorInFunction(os)
|
||||
<< "Overall number of elements of CompactIOField (size:"
|
||||
<< len
|
||||
<< ") overflows the representation of a label" << nl
|
||||
<< "Please recompile with a larger representation"
|
||||
<< " for label" << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
offsets[len] = total;
|
||||
os << offsets;
|
||||
}
|
||||
|
||||
// packed values: make deepCopy for writing
|
||||
{
|
||||
Field<base_type> values(total);
|
||||
|
||||
auto iter = values.begin();
|
||||
|
||||
for (const auto& list : lists)
|
||||
{
|
||||
iter = std::copy_n(list.begin(), list.size(), iter);
|
||||
|
||||
// With IndirectList? [unlikely]
|
||||
// const label count = list.size();
|
||||
// for (label i = 0; i < count; (void)++i, (void)++iter)
|
||||
// {
|
||||
// *iter = list[i];
|
||||
// }
|
||||
}
|
||||
os << values;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
@ -211,30 +436,10 @@ template<class T, class BaseType>
|
||||
Foam::Istream& Foam::operator>>
|
||||
(
|
||||
Foam::Istream& is,
|
||||
Foam::CompactIOField<T, BaseType>& L
|
||||
Foam::CompactIOField<T, BaseType>& lists
|
||||
)
|
||||
{
|
||||
// Read compact
|
||||
const labelList start(is);
|
||||
const Field<BaseType> elems(is);
|
||||
|
||||
// Convert
|
||||
L.setSize(start.size()-1);
|
||||
|
||||
forAll(L, i)
|
||||
{
|
||||
T& subField = L[i];
|
||||
|
||||
label index = start[i];
|
||||
subField.setSize(start[i+1] - index);
|
||||
|
||||
forAll(subField, j)
|
||||
{
|
||||
subField[j] = elems[index++];
|
||||
}
|
||||
}
|
||||
|
||||
return is;
|
||||
return lists.readCompact(is);
|
||||
}
|
||||
|
||||
|
||||
@ -242,38 +447,17 @@ template<class T, class BaseType>
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Foam::Ostream& os,
|
||||
const Foam::CompactIOField<T, BaseType>& L
|
||||
const Foam::CompactIOField<T, BaseType>& lists
|
||||
)
|
||||
{
|
||||
// Keep ASCII writing same
|
||||
if (os.format() == IOstreamOption::ASCII)
|
||||
if (os.format() != IOstreamOption::BINARY)
|
||||
{
|
||||
os << static_cast<const Field<T>&>(L);
|
||||
os << static_cast<const Field<T>&>(lists);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert to compact format
|
||||
labelList start(L.size()+1);
|
||||
|
||||
start[0] = 0;
|
||||
for (label i = 1; i < start.size(); i++)
|
||||
{
|
||||
start[i] = start[i-1]+L[i-1].size();
|
||||
}
|
||||
|
||||
Field<BaseType> elems(start[start.size()-1]);
|
||||
|
||||
label elemI = 0;
|
||||
forAll(L, i)
|
||||
{
|
||||
const T& subField = L[i];
|
||||
|
||||
forAll(subField, j)
|
||||
{
|
||||
elems[elemI++] = subField[j];
|
||||
}
|
||||
}
|
||||
os << start << elems;
|
||||
lists.writeCompact(os);
|
||||
}
|
||||
|
||||
return os;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2020-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2020-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -52,17 +52,11 @@ namespace Foam
|
||||
// Forward Declarations
|
||||
template<class T, class BaseType> class CompactIOField;
|
||||
|
||||
template<class T, class BaseType> Istream& operator>>
|
||||
(
|
||||
Istream&,
|
||||
CompactIOField<T, BaseType>&
|
||||
);
|
||||
template<class T, class BaseType>
|
||||
Istream& operator>>(Istream&, CompactIOField<T, BaseType>&);
|
||||
|
||||
template<class T, class BaseType> Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const CompactIOField<T, BaseType>&
|
||||
);
|
||||
template<class T, class BaseType>
|
||||
Ostream& operator<<(Ostream&, const CompactIOField<T, BaseType>&);
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class CompactIOField Declaration
|
||||
@ -81,8 +75,18 @@ class CompactIOField
|
||||
// Return true if read (only accurate when readOnProc == true).
|
||||
bool readIOcontents(bool readOnProc = true);
|
||||
|
||||
//- Read the content size.
|
||||
// Return the size if read, -1 otherwise
|
||||
label readIOsize(bool readOnProc = true);
|
||||
|
||||
//- Has too many elements in it?
|
||||
bool overflows() const;
|
||||
|
||||
public:
|
||||
|
||||
//- The underlying content type
|
||||
typedef Field<T> content_type;
|
||||
|
||||
//- Runtime type information
|
||||
TypeName("FieldField");
|
||||
|
||||
@ -92,7 +96,7 @@ public:
|
||||
//- Default copy construct
|
||||
CompactIOField(const CompactIOField&) = default;
|
||||
|
||||
//- Construct from IOobject
|
||||
//- Construct from IOobject. Will be zero size if not read.
|
||||
explicit CompactIOField(const IOobject& io);
|
||||
|
||||
//- Construct from IOobject, with local processor conditional reading
|
||||
@ -111,29 +115,55 @@ public:
|
||||
CompactIOField(const IOobject& io, Field<T>&& content);
|
||||
|
||||
|
||||
// Factory Methods
|
||||
|
||||
//- Read and return content size, -1 if not read.
|
||||
// The IOobject is never registered
|
||||
static label readContentsSize(const IOobject& io);
|
||||
|
||||
//- Read and return contents. The IOobject is never registered
|
||||
static Field<T> readContents(const IOobject& io);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~CompactIOField() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Write using stream options
|
||||
//- Read as offsets/packed-values and transcribe into *this
|
||||
Istream& readCompact(Istream& is);
|
||||
|
||||
//- Write as offsets/packed-values
|
||||
Ostream& writeCompact(Ostream& os) const;
|
||||
|
||||
//- Write using stream options. Checks for overflow in binary
|
||||
virtual bool writeObject
|
||||
(
|
||||
IOstreamOption streamOpt,
|
||||
const bool writeOnProc
|
||||
) const;
|
||||
|
||||
//- Write as plain or compact content (depends on stream format)
|
||||
virtual bool writeData(Ostream& os) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const CompactIOField<T, BaseType>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using Field<T>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const CompactIOField<T, BaseType>& rhs)
|
||||
{
|
||||
Field<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(CompactIOField<T, BaseType>&& rhs)
|
||||
{
|
||||
Field<T>::operator=(std::move(static_cast<Field<T>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2015-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2015-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -27,41 +27,39 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "CompactIOList.H"
|
||||
#include "labelList.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
bool Foam::CompactIOList<T, BaseType>::readIOcontents()
|
||||
{
|
||||
if
|
||||
(
|
||||
readOpt() == IOobject::MUST_READ
|
||||
|| (isReadOptional() && headerOk())
|
||||
)
|
||||
typedef IOList<T> plain_type;
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
Istream& is = readStream(word::null);
|
||||
|
||||
if (headerClassName() == IOList<T>::typeName)
|
||||
if (isHeaderClass(typeName))
|
||||
{
|
||||
is >> static_cast<List<T>&>(*this);
|
||||
close();
|
||||
// Compact form
|
||||
is >> *this; // or: this->readCompact(is);
|
||||
}
|
||||
else if (headerClassName() == typeName)
|
||||
else if (isHeaderClass<plain_type>())
|
||||
{
|
||||
is >> *this;
|
||||
close();
|
||||
// Non-compact form
|
||||
is >> static_cast<content_type&>(*this);
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Unexpected class name " << headerClassName()
|
||||
<< " expected " << typeName
|
||||
<< " or " << IOList<T>::typeName << endl
|
||||
<< " or " << plain_type::typeName << endl
|
||||
<< " while reading object " << name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
close();
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -69,19 +67,83 @@ bool Foam::CompactIOList<T, BaseType>::readIOcontents()
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::label Foam::CompactIOList<T, BaseType>::readIOsize()
|
||||
{
|
||||
typedef IOList<T> plain_type;
|
||||
|
||||
label count(-1);
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
Istream& is = readStream(word::null);
|
||||
|
||||
token tok(is);
|
||||
|
||||
if (tok.isLabel())
|
||||
{
|
||||
// The majority of files will have lists with sizing prefix
|
||||
count = tok.labelToken();
|
||||
|
||||
if (isHeaderClass(typeName))
|
||||
{
|
||||
// Compact form: read offsets, not content
|
||||
if (--count < 0)
|
||||
{
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
is.putBack(tok);
|
||||
|
||||
if (isHeaderClass(typeName))
|
||||
{
|
||||
// Compact form: can just read the offsets
|
||||
labelList offsets(is);
|
||||
count = Foam::max(0, (offsets.size()-1));
|
||||
}
|
||||
else if (isHeaderClass<plain_type>())
|
||||
{
|
||||
// Non-compact form: need to read everything
|
||||
List<T> list(is);
|
||||
count = list.size();
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "Unexpected class name " << headerClassName()
|
||||
<< " expected " << typeName
|
||||
<< " or " << plain_type::typeName << endl
|
||||
<< " while reading object " << name()
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
close();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
bool Foam::CompactIOList<T, BaseType>::overflows() const
|
||||
{
|
||||
const List<T>& lists = *this;
|
||||
|
||||
label total = 0;
|
||||
for (const auto& sublist : lists)
|
||||
// Can safely assume that int64 will not overflow
|
||||
if constexpr (sizeof(label) < sizeof(int64_t))
|
||||
{
|
||||
const label prev = total;
|
||||
total += sublist.size();
|
||||
if (total < prev)
|
||||
const UList<T>& lists = *this;
|
||||
|
||||
label total = 0;
|
||||
for (const auto& list : lists)
|
||||
{
|
||||
return true;
|
||||
const label prev = total;
|
||||
total += list.size();
|
||||
if (total < prev)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@ -159,6 +221,46 @@ Foam::CompactIOList<T, BaseType>::CompactIOList
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::label
|
||||
Foam::CompactIOList<T, BaseType>::readContentsSize(const IOobject& io)
|
||||
{
|
||||
IOobject rio(io, IOobjectOption::NO_REGISTER);
|
||||
if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// Construct NO_READ, changing after construction
|
||||
const auto rOpt = rio.readOpt(IOobjectOption::NO_READ);
|
||||
|
||||
CompactIOList<T, BaseType> reader(rio);
|
||||
reader.readOpt(rOpt);
|
||||
|
||||
return reader.readIOsize();
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::List<T>
|
||||
Foam::CompactIOList<T, BaseType>::readContents(const IOobject& io)
|
||||
{
|
||||
IOobject rio(io, IOobjectOption::NO_REGISTER);
|
||||
if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
CompactIOList<T, BaseType> reader(rio);
|
||||
|
||||
return List<T>(std::move(static_cast<List<T>&>(reader)));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
@ -177,12 +279,13 @@ bool Foam::CompactIOList<T, BaseType>::writeObject
|
||||
streamOpt.format(IOstreamOption::ASCII);
|
||||
|
||||
WarningInFunction
|
||||
<< "Overall number of elements of CompactIOList of size "
|
||||
<< this->size() << " overflows the representation of a label"
|
||||
<< nl << " Switching to ascii writing" << endl;
|
||||
<< "Overall number of elements of CompactIOList (size:"
|
||||
<< this->size() << ") overflows a label (int"
|
||||
<< (8*sizeof(label)) << ')' << nl
|
||||
<< " Switching to ascii writing" << endl;
|
||||
}
|
||||
|
||||
if (streamOpt.format() == IOstreamOption::ASCII)
|
||||
if (streamOpt.format() != IOstreamOption::BINARY)
|
||||
{
|
||||
// Change type to be non-compact format type
|
||||
const word oldTypeName(typeName);
|
||||
@ -208,15 +311,98 @@ bool Foam::CompactIOList<T, BaseType>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, class BaseType>
|
||||
void Foam::CompactIOList<T, BaseType>::operator=
|
||||
(
|
||||
const CompactIOList<T, BaseType>& rhs
|
||||
)
|
||||
Foam::Istream& Foam::CompactIOList<T,BaseType>::readCompact(Istream& is)
|
||||
{
|
||||
List<T>::operator=(rhs);
|
||||
List<T>& lists = *this;
|
||||
|
||||
// The base type for packed values
|
||||
typedef typename T::value_type base_type;
|
||||
|
||||
// Read compact: offsets + packed values
|
||||
const labelList offsets(is);
|
||||
List<base_type> values(is);
|
||||
|
||||
// Transcribe
|
||||
const label len = Foam::max(0, (offsets.size()-1));
|
||||
lists.resize_nocopy(len);
|
||||
|
||||
auto iter = values.begin();
|
||||
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
auto& list = lists[i];
|
||||
const label count = (offsets[i+1] - offsets[i]);
|
||||
|
||||
list.resize_nocopy(count);
|
||||
|
||||
std::move(iter, iter + count, list.begin());
|
||||
|
||||
iter += count;
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
|
||||
template<class T, class BaseType>
|
||||
Foam::Ostream& Foam::CompactIOList<T,BaseType>::writeCompact(Ostream& os) const
|
||||
{
|
||||
const List<T>& lists = *this;
|
||||
|
||||
// The base type for packed values
|
||||
typedef typename T::value_type base_type;
|
||||
|
||||
// Convert to compact format
|
||||
label total = 0;
|
||||
const label len = lists.size();
|
||||
|
||||
// offsets
|
||||
{
|
||||
labelList offsets(len+1);
|
||||
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
offsets[i] = total;
|
||||
total += lists[i].size();
|
||||
|
||||
if (total < offsets[i])
|
||||
{
|
||||
FatalIOErrorInFunction(os)
|
||||
<< "Overall number of elements of CompactIOList (size:"
|
||||
<< len
|
||||
<< ") overflows the representation of a label" << nl
|
||||
<< "Please recompile with a larger representation"
|
||||
<< " for label" << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
offsets[len] = total;
|
||||
os << offsets;
|
||||
}
|
||||
|
||||
// packed values: make deepCopy for writing
|
||||
{
|
||||
List<base_type> values(total);
|
||||
|
||||
auto iter = values.begin();
|
||||
|
||||
for (const auto& list : lists)
|
||||
{
|
||||
iter = std::copy_n(list.begin(), list.size(), iter);
|
||||
|
||||
// With IndirectList? [unlikely]
|
||||
// const label count = list.size();
|
||||
// for (label i = 0; i < count; (void)++i, (void)++iter)
|
||||
// {
|
||||
// *iter = list[i];
|
||||
// }
|
||||
}
|
||||
os << values;
|
||||
}
|
||||
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
@ -226,30 +412,10 @@ template<class T, class BaseType>
|
||||
Foam::Istream& Foam::operator>>
|
||||
(
|
||||
Foam::Istream& is,
|
||||
Foam::CompactIOList<T, BaseType>& L
|
||||
Foam::CompactIOList<T, BaseType>& lists
|
||||
)
|
||||
{
|
||||
// Read compact
|
||||
const labelList start(is);
|
||||
const List<BaseType> elems(is);
|
||||
|
||||
// Convert
|
||||
L.setSize(start.size()-1);
|
||||
|
||||
forAll(L, i)
|
||||
{
|
||||
T& subList = L[i];
|
||||
|
||||
label index = start[i];
|
||||
subList.setSize(start[i+1] - index);
|
||||
|
||||
forAll(subList, j)
|
||||
{
|
||||
subList[j] = elems[index++];
|
||||
}
|
||||
}
|
||||
|
||||
return is;
|
||||
return lists.readCompact(is);
|
||||
}
|
||||
|
||||
|
||||
@ -257,49 +423,17 @@ template<class T, class BaseType>
|
||||
Foam::Ostream& Foam::operator<<
|
||||
(
|
||||
Foam::Ostream& os,
|
||||
const Foam::CompactIOList<T, BaseType>& L
|
||||
const Foam::CompactIOList<T, BaseType>& lists
|
||||
)
|
||||
{
|
||||
// Keep ASCII writing same
|
||||
if (os.format() == IOstreamOption::ASCII)
|
||||
if (os.format() != IOstreamOption::BINARY)
|
||||
{
|
||||
os << static_cast<const List<T>&>(L);
|
||||
os << static_cast<const List<T>&>(lists);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Convert to compact format
|
||||
labelList start(L.size()+1);
|
||||
|
||||
start[0] = 0;
|
||||
for (label i = 1; i < start.size(); i++)
|
||||
{
|
||||
const label prev = start[i-1];
|
||||
start[i] = prev+L[i-1].size();
|
||||
|
||||
if (start[i] < prev)
|
||||
{
|
||||
FatalIOErrorInFunction(os)
|
||||
<< "Overall number of elements " << start[i]
|
||||
<< " of CompactIOList of size "
|
||||
<< L.size() << " overflows the representation of a label"
|
||||
<< endl << "Please recompile with a larger representation"
|
||||
<< " for label" << exit(FatalIOError);
|
||||
}
|
||||
}
|
||||
|
||||
List<BaseType> elems(start[start.size()-1]);
|
||||
|
||||
label elemI = 0;
|
||||
forAll(L, i)
|
||||
{
|
||||
const T& subList = L[i];
|
||||
|
||||
forAll(subList, j)
|
||||
{
|
||||
elems[elemI++] = subList[j];
|
||||
}
|
||||
}
|
||||
os << start << elems;
|
||||
lists.writeCompact(os);
|
||||
}
|
||||
|
||||
return os;
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -52,16 +52,11 @@ namespace Foam
|
||||
// Forward Declarations
|
||||
template<class T, class BaseType> class CompactIOList;
|
||||
|
||||
template<class T, class BaseType> Istream& operator>>
|
||||
(
|
||||
Istream&,
|
||||
CompactIOList<T, BaseType>&
|
||||
);
|
||||
template<class T, class BaseType> Ostream& operator<<
|
||||
(
|
||||
Ostream&,
|
||||
const CompactIOList<T, BaseType>&
|
||||
);
|
||||
template<class T, class BaseType>
|
||||
Istream& operator>>(Istream&, CompactIOList<T, BaseType>&);
|
||||
|
||||
template<class T, class BaseType>
|
||||
Ostream& operator<<(Ostream&, const CompactIOList<T, BaseType>&);
|
||||
|
||||
/*---------------------------------------------------------------------------*\
|
||||
Class CompactIOList Declaration
|
||||
@ -80,6 +75,10 @@ class CompactIOList
|
||||
// Return true if read.
|
||||
bool readIOcontents();
|
||||
|
||||
//- Read the content size.
|
||||
// Return the size if read, -1 otherwise
|
||||
label readIOsize();
|
||||
|
||||
//- Has too many elements in it?
|
||||
bool overflows() const;
|
||||
|
||||
@ -98,7 +97,7 @@ public:
|
||||
//- Default copy construct
|
||||
CompactIOList(const CompactIOList&) = default;
|
||||
|
||||
//- Construct from IOobject
|
||||
//- Construct from IOobject. Will be zero size if not read.
|
||||
explicit CompactIOList(const IOobject& io);
|
||||
|
||||
//- Construct from IOobject and zero size (if not read)
|
||||
@ -114,12 +113,28 @@ public:
|
||||
CompactIOList(const IOobject& io, List<T>&& content);
|
||||
|
||||
|
||||
// Factory Methods
|
||||
|
||||
//- Read and return content size, -1 if not read.
|
||||
// The IOobject will not be registered
|
||||
static label readContentsSize(const IOobject& io);
|
||||
|
||||
//- Read and return contents. The IOobject will not be registered
|
||||
static List<T> readContents(const IOobject& io);
|
||||
|
||||
|
||||
//- Destructor
|
||||
virtual ~CompactIOList() = default;
|
||||
|
||||
|
||||
// Member Functions
|
||||
|
||||
//- Read as offsets/packed-values and transcribe into *this
|
||||
Istream& readCompact(Istream& is);
|
||||
|
||||
//- Write as offsets/packed-values
|
||||
Ostream& writeCompact(Ostream& os) const;
|
||||
|
||||
//- Write using stream options. Checks for overflow in binary
|
||||
virtual bool writeObject
|
||||
(
|
||||
@ -127,16 +142,26 @@ public:
|
||||
const bool writeOnProc
|
||||
) const;
|
||||
|
||||
//- Write as plain or compact content (depends on stream format)
|
||||
virtual bool writeData(Ostream& os) const;
|
||||
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const CompactIOList<T, BaseType>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using List<T>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const CompactIOList<T, BaseType>& rhs)
|
||||
{
|
||||
List<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(CompactIOList<T, BaseType>&& rhs)
|
||||
{
|
||||
List<T>::operator=(std::move(static_cast<List<T>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -132,6 +132,7 @@ Foam::Field<Type> Foam::GlobalIOField<Type>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// The object is global
|
||||
rio.globalObject(true);
|
||||
@ -160,13 +161,4 @@ bool Foam::GlobalIOField<Type>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::GlobalIOField<Type>::operator=(const GlobalIOField<Type>& rhs)
|
||||
{
|
||||
Field<Type>::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -69,7 +69,7 @@ public:
|
||||
//- Default copy construct
|
||||
GlobalIOField(const GlobalIOField&) = default;
|
||||
|
||||
//- Construct from IOobject
|
||||
//- Construct from IOobject. Will be zero size if not read.
|
||||
explicit GlobalIOField(const IOobject& io);
|
||||
|
||||
//- Construct from IOobject and field size (if not read)
|
||||
@ -119,11 +119,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const GlobalIOField<Type>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using Field<Type>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const GlobalIOField<Type>& rhs)
|
||||
{
|
||||
Field<Type>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(GlobalIOField<Type>&& rhs)
|
||||
{
|
||||
Field<Type>::operator=(std::move(static_cast<Field<Type>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -116,6 +116,7 @@ Foam::List<Type> Foam::GlobalIOList<Type>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// The object is global
|
||||
rio.globalObject(true);
|
||||
@ -144,13 +145,4 @@ bool Foam::GlobalIOList<Type>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::GlobalIOList<Type>::operator=(const GlobalIOList<Type>& rhs)
|
||||
{
|
||||
List<Type>::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -69,7 +69,7 @@ public:
|
||||
//- Default copy construct
|
||||
GlobalIOList(const GlobalIOList&) = default;
|
||||
|
||||
//- Construct from IOobject
|
||||
//- Construct from IOobject. Will be zero size if not read.
|
||||
explicit GlobalIOList(const IOobject& io);
|
||||
|
||||
//- Construct from IOobject and zero size (if not read)
|
||||
@ -119,11 +119,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const GlobalIOList<Type>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using List<Type>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const GlobalIOList<Type>& rhs)
|
||||
{
|
||||
List<Type>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(GlobalIOList<Type>&& rhs)
|
||||
{
|
||||
List<Type>::operator=(std::move(static_cast<List<Type>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2016-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2016-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -50,6 +50,38 @@ bool Foam::IOField<Type>::readIOcontents(bool readOnProc)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::label Foam::IOField<T>::readIOsize()
|
||||
{
|
||||
label count(-1);
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
Istream& is = readStream(typeName);
|
||||
|
||||
token tok(is);
|
||||
|
||||
const bool quick = tok.isLabel();
|
||||
|
||||
if (quick)
|
||||
{
|
||||
// The majority of files will have lists with sizing info
|
||||
count = tok.labelToken();
|
||||
}
|
||||
is.putBack(tok);
|
||||
|
||||
if (!quick)
|
||||
{
|
||||
List<T> list(is);
|
||||
close();
|
||||
count = list.size();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
@ -167,6 +199,26 @@ Foam::IOFieldRef<Type>::IOFieldRef
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
Foam::label Foam::IOField<Type>::readContentsSize(const IOobject& io)
|
||||
{
|
||||
IOobject rio(io, IOobjectOption::NO_REGISTER);
|
||||
if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// Construct NO_READ, changing after construction
|
||||
const auto rOpt = rio.readOpt(IOobjectOption::NO_READ);
|
||||
|
||||
IOField<Type> reader(rio);
|
||||
reader.readOpt(rOpt);
|
||||
|
||||
return reader.readIOsize();
|
||||
}
|
||||
|
||||
|
||||
template<class Type>
|
||||
Foam::Field<Type> Foam::IOField<Type>::readContents(const IOobject& io)
|
||||
{
|
||||
@ -175,6 +227,7 @@ Foam::Field<Type> Foam::IOField<Type>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
IOField<Type> reader(rio);
|
||||
|
||||
@ -200,13 +253,4 @@ bool Foam::IOFieldRef<Type>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class Type>
|
||||
void Foam::IOField<Type>::operator=(const IOField<Type>& rhs)
|
||||
{
|
||||
Field<Type>::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2017 OpenFOAM Foundation
|
||||
Copyright (C) 2018-2024 OpenCFD Ltd.
|
||||
Copyright (C) 2018-2025 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -62,6 +62,10 @@ class IOField
|
||||
// Return true if read (only accurate when readOnProc == true).
|
||||
bool readIOcontents(bool readOnProc = true);
|
||||
|
||||
//- Read the content size.
|
||||
// Return the size if read, -1 otherwise
|
||||
label readIOsize();
|
||||
|
||||
public:
|
||||
|
||||
//- The underlying content type
|
||||
@ -76,7 +80,7 @@ public:
|
||||
//- Default copy construct
|
||||
IOField(const IOField&) = default;
|
||||
|
||||
//- Construct from IOobject
|
||||
//- Construct from IOobject. Will be zero size if not read.
|
||||
explicit IOField(const IOobject& io);
|
||||
|
||||
//- Construct from IOobject, with local processor conditional reading
|
||||
@ -100,6 +104,10 @@ public:
|
||||
|
||||
// Factory Methods
|
||||
|
||||
//- Read and return content size, -1 if not read.
|
||||
// The IOobject will not be registered
|
||||
static label readContentsSize(const IOobject& io);
|
||||
|
||||
//- Read and return contents. The IOobject will not be registered
|
||||
static Field<Type> readContents(const IOobject& io);
|
||||
|
||||
@ -116,11 +124,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOField<Type>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using Field<Type>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOField<Type>& rhs)
|
||||
{
|
||||
Field<Type>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(IOField<Type>&& rhs)
|
||||
{
|
||||
Field<Type>::operator=(std::move(static_cast<Field<Type>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -44,6 +44,38 @@ bool Foam::IOList<T>::readIOcontents()
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::label Foam::IOList<T>::readIOsize()
|
||||
{
|
||||
label count(-1);
|
||||
|
||||
if (isReadRequired() || (isReadOptional() && headerOk()))
|
||||
{
|
||||
Istream& is = readStream(typeName);
|
||||
|
||||
token tok(is);
|
||||
|
||||
const bool quick = tok.isLabel();
|
||||
|
||||
if (quick)
|
||||
{
|
||||
// The majority of files will have lists with sizing info
|
||||
count = tok.labelToken();
|
||||
}
|
||||
is.putBack(tok);
|
||||
|
||||
if (!quick)
|
||||
{
|
||||
List<T> list(is);
|
||||
close();
|
||||
count = list.size();
|
||||
}
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
@ -128,6 +160,26 @@ Foam::IOListRef<T>::IOListRef
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
Foam::label Foam::IOList<T>::readContentsSize(const IOobject& io)
|
||||
{
|
||||
IOobject rio(io, IOobjectOption::NO_REGISTER);
|
||||
if (rio.readOpt() == IOobjectOption::READ_MODIFIED)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// Construct NO_READ, changing after construction
|
||||
const auto rOpt = rio.readOpt(IOobjectOption::NO_READ);
|
||||
|
||||
IOList<T> reader(rio);
|
||||
reader.readOpt(rOpt);
|
||||
|
||||
return reader.readIOsize();
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::List<T> Foam::IOList<T>::readContents(const IOobject& io)
|
||||
{
|
||||
@ -136,6 +188,7 @@ Foam::List<T> Foam::IOList<T>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
IOList<T> reader(rio);
|
||||
|
||||
@ -178,13 +231,4 @@ bool Foam::IOListRef<T>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
void Foam::IOList<T>::operator=(const IOList<T>& rhs)
|
||||
{
|
||||
List<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -61,6 +61,10 @@ class IOList
|
||||
//- Read if IOobject flags set. Return true if read.
|
||||
bool readIOcontents();
|
||||
|
||||
//- Read the content size.
|
||||
// Return the size if read, -1 otherwise
|
||||
label readIOsize();
|
||||
|
||||
public:
|
||||
|
||||
//- The underlying content type
|
||||
@ -75,7 +79,7 @@ public:
|
||||
//- Default copy construct
|
||||
IOList(const IOList&) = default;
|
||||
|
||||
//- Construct from IOobject
|
||||
//- Construct from IOobject. Will be zero size if not read.
|
||||
explicit IOList(const IOobject& io);
|
||||
|
||||
//- Construct from IOobject and zero size (if not read)
|
||||
@ -93,6 +97,10 @@ public:
|
||||
|
||||
// Factory Methods
|
||||
|
||||
//- Read and return content size, -1 if not read.
|
||||
// The IOobject is never registered
|
||||
static label readContentsSize(const IOobject& io);
|
||||
|
||||
//- Read and return contents. The IOobject is never registered
|
||||
static List<T> readContents(const IOobject& io);
|
||||
|
||||
@ -113,11 +121,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOList<T>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using List<T>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOList<T>& rhs)
|
||||
{
|
||||
List<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(IOList<T>&& rhs)
|
||||
{
|
||||
List<T>::operator=(std::move(static_cast<List<T>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -104,6 +104,7 @@ Foam::Map<T> Foam::IOMap<T>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
// The object is global
|
||||
rio.globalObject(true);
|
||||
@ -124,13 +125,4 @@ bool Foam::IOMap<T>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
void Foam::IOMap<T>::operator=(const IOMap<T>& rhs)
|
||||
{
|
||||
Map<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -120,11 +120,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOMap<T>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using Map<T>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOMap<T>& rhs)
|
||||
{
|
||||
Map<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(IOMap<T>&& rhs)
|
||||
{
|
||||
Map<T>::operator=(std::move(static_cast<Map<T>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -126,6 +126,7 @@ Foam::PtrList<T> Foam::IOPtrList<T>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
IOPtrList<T> reader(rio);
|
||||
|
||||
@ -142,13 +143,4 @@ bool Foam::IOPtrList<T>::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
void Foam::IOPtrList<T>::operator=(const IOPtrList<T>& rhs)
|
||||
{
|
||||
PtrList<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -101,11 +101,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOPtrList<T>& rhs);
|
||||
|
||||
//- Copy or move assignment of entries
|
||||
using PtrList<T>::operator=;
|
||||
|
||||
//- Copy assignment of entries
|
||||
void operator=(const IOPtrList<T>& rhs)
|
||||
{
|
||||
PtrList<T>::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of entries
|
||||
void operator=(IOPtrList<T>&& rhs)
|
||||
{
|
||||
PtrList<T>::operator=(std::move(static_cast<PtrList<T>&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -113,12 +113,4 @@ bool Foam::baseIOdictionary::writeData(Ostream& os) const
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
|
||||
|
||||
void Foam::baseIOdictionary::operator=(const baseIOdictionary& rhs)
|
||||
{
|
||||
dictionary::operator=(rhs);
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -123,11 +123,20 @@ public:
|
||||
|
||||
// Member Operators
|
||||
|
||||
//- Copy assignment of dictionary entries (leave regIOobject untouched)
|
||||
void operator=(const baseIOdictionary& rhs);
|
||||
|
||||
//- Copy assignment of dictionary entries
|
||||
using dictionary::operator=;
|
||||
|
||||
//- Copy assignment of dictionary entries
|
||||
void operator=(const baseIOdictionary& rhs)
|
||||
{
|
||||
dictionary::operator=(rhs);
|
||||
}
|
||||
|
||||
//- Move assignment of dictionary entries
|
||||
void operator=(baseIOdictionary&& rhs)
|
||||
{
|
||||
dictionary::operator=(std::move(static_cast<dictionary&>(rhs)));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -198,6 +198,7 @@ Foam::Field<Type> Foam::rawIOField<Type>::readContents(const IOobject& io)
|
||||
{
|
||||
rio.readOpt(IOobjectOption::MUST_READ);
|
||||
}
|
||||
rio.resetHeader();
|
||||
|
||||
rawIOField<Type> reader(rio);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user