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:
Mark Olesen
2025-08-25 15:09:31 +02:00
parent 697b8a1436
commit b2135600a8
21 changed files with 858 additions and 329 deletions

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2020-2022 OpenCFD Ltd. Copyright (C) 2020-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -25,7 +25,7 @@ License
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>. along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
Application Application
testCompactIOList Test-CompactIOList
Description Description
Simple demonstration and test application for the CompactIOList container Simple demonstration and test application for the CompactIOList container
@ -46,13 +46,20 @@ using namespace Foam;
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
argList::addBoolOption("ascii", "use ascii format");
argList::addOption("count", "number of faces");
#include "setRootCase.H" #include "setRootCase.H"
#include "createTime.H" #include "createTime.H"
IOstreamOption streamOpt(IOstreamOption::BINARY); 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 // Old format
// ~~~~~~~~~~ // ~~~~~~~~~~
@ -63,39 +70,50 @@ int main(int argc, char *argv[])
( (
IOobject IOobject
( (
"faces2", "faces2-plain",
runTime.constant(), runTime.constant(),
polyMesh::meshSubDir, polyMesh::meshSubDir,
runTime, runTime,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE, IOobject::NO_WRITE,
IOobject::NO_REGISTER IOobject::NO_REGISTER
), )
size
); );
const face f(identity(4)); faces2.resize(size, face(identity(4)));
forAll(faces2, i) Info<< "Plain format faceList " << faces2.objectRelPath() << nl;
{ Info<< " constructed in = " << runTime.cpuTimeIncrement()
faces2[i] = f; << " s" << endl;
}
Info<< "Constructed faceList in = "
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
faces2.writeObject(streamOpt, true); faces2.writeObject(streamOpt, true);
Info<< "Written old format faceList in = " Info<< " wrote in = "
<< runTime.cpuTimeIncrement() << " s" << nl << endl; << runTime.cpuTimeIncrement() << " s" << endl;
// Read // Read (size only)
faceIOList faces3 label count = faceIOList::readContentsSize
( (
IOobject 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(), runTime.constant(),
polyMesh::meshSubDir, polyMesh::meshSubDir,
runTime, 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; << 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 faceCompactIOList faces2
( (
IOobject IOobject
( (
"faces2", "faces2-compact",
runTime.constant(), runTime.constant(),
polyMesh::meshSubDir, polyMesh::meshSubDir,
runTime, runTime,
IOobject::NO_READ, IOobject::NO_READ,
IOobject::NO_WRITE, IOobject::NO_WRITE,
IOobject::NO_REGISTER IOobject::NO_REGISTER
), )
size
); );
const face f(identity(4)); faces2.resize(size, face(identity(4)));
forAll(faces2, i) Info<< "Compact format faceList" << faces2.objectRelPath() << nl;
{ Info<< " constructed in = "
faces2[i] = f; << runTime.cpuTimeIncrement() << " s" << endl;
}
Info<< "Constructed new format faceList in = "
<< runTime.cpuTimeIncrement() << " s" << nl << endl;
faces2.writeObject(streamOpt, true); faces2.writeObject(streamOpt, true);
Info<< "Written new format faceList in = " Info<< " wrote in = "
<< runTime.cpuTimeIncrement() << " s" << nl << endl; << runTime.cpuTimeIncrement() << " s" << endl;
// Read // Read (size only)
faceCompactIOList faces3 label count = faceCompactIOList::readContentsSize
( (
IOobject 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(), runTime.constant(),
polyMesh::meshSubDir, polyMesh::meshSubDir,
runTime, 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; << runTime.cpuTimeIncrement() << " s" << nl << endl;
} }

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd. Copyright (C) 2018-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,41 +27,43 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "CompactIOField.H" #include "CompactIOField.H"
#include "labelList.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T, class BaseType> template<class T, class BaseType>
bool Foam::CompactIOField<T, BaseType>::readIOcontents(bool readOnProc) bool Foam::CompactIOField<T, BaseType>::readIOcontents(bool readOnProc)
{ {
typedef IOField<T> plain_type;
if (isReadRequired() || (isReadOptional() && headerOk())) if (isReadRequired() || (isReadOptional() && headerOk()))
{ {
// Do reading
Istream& is = readStream(word::null, readOnProc); Istream& is = readStream(word::null, readOnProc);
if (readOnProc) if (!readOnProc)
{ {
if (headerClassName() == IOField<T>::typeName) // no-op
{ }
is >> static_cast<Field<T>&>(*this); else if (isHeaderClass(typeName))
close(); {
} // Compact form
else if (headerClassName() == typeName) is >> *this; // or: this->readCompact(is);
{ }
is >> *this; else if (isHeaderClass<plain_type>())
close(); {
} // Non-compact form
else is >> static_cast<content_type&>(*this);
{ }
FatalIOErrorInFunction(is) else
<< "Unexpected class name " << headerClassName() {
<< " expected " << typeName FatalIOErrorInFunction(is)
<< " or " << IOField<T>::typeName << nl << "Unexpected class name " << headerClassName()
<< " while reading object " << name() << " expected " << typeName
<< exit(FatalIOError); << " or " << plain_type::typeName << nl
} << " while reading object " << name()
<< exit(FatalIOError);
} }
close();
return true; 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 * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
template<class T, class BaseType> 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 * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class BaseType> template<class T, class BaseType>
@ -162,7 +294,22 @@ bool Foam::CompactIOField<T, BaseType>::writeObject
const bool writeOnProc const bool writeOnProc
) const ) 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 // Change type to be non-compact format type
const word oldTypeName(typeName); const word oldTypeName(typeName);
@ -188,20 +335,98 @@ bool Foam::CompactIOField<T, BaseType>::writeData(Ostream& os) const
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T, class BaseType> template<class T, class BaseType>
void Foam::CompactIOField<T, BaseType>::operator= Foam::Istream& Foam::CompactIOField<T,BaseType>::readCompact(Istream& is)
(
const CompactIOField<T, BaseType>& rhs
)
{ {
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& Foam::operator>>
( (
Foam::Istream& is, Foam::Istream& is,
Foam::CompactIOField<T, BaseType>& L Foam::CompactIOField<T, BaseType>& lists
) )
{ {
// Read compact return lists.readCompact(is);
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;
} }
@ -242,38 +447,17 @@ template<class T, class BaseType>
Foam::Ostream& Foam::operator<< Foam::Ostream& Foam::operator<<
( (
Foam::Ostream& os, Foam::Ostream& os,
const Foam::CompactIOField<T, BaseType>& L const Foam::CompactIOField<T, BaseType>& lists
) )
{ {
// Keep ASCII writing same // 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 else
{ {
// Convert to compact format lists.writeCompact(os);
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;
} }
return os; return os;

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2020-2024 OpenCFD Ltd. Copyright (C) 2020-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -52,17 +52,11 @@ namespace Foam
// Forward Declarations // Forward Declarations
template<class T, class BaseType> class CompactIOField; template<class T, class BaseType> class CompactIOField;
template<class T, class BaseType> Istream& operator>> template<class T, class BaseType>
( Istream& operator>>(Istream&, CompactIOField<T, BaseType>&);
Istream&,
CompactIOField<T, BaseType>&
);
template<class T, class BaseType> Ostream& operator<< template<class T, class BaseType>
( Ostream& operator<<(Ostream&, const CompactIOField<T, BaseType>&);
Ostream&,
const CompactIOField<T, BaseType>&
);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class CompactIOField Declaration Class CompactIOField Declaration
@ -81,8 +75,18 @@ class CompactIOField
// Return true if read (only accurate when readOnProc == true). // Return true if read (only accurate when readOnProc == true).
bool readIOcontents(bool 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: public:
//- The underlying content type
typedef Field<T> content_type;
//- Runtime type information //- Runtime type information
TypeName("FieldField"); TypeName("FieldField");
@ -92,7 +96,7 @@ public:
//- Default copy construct //- Default copy construct
CompactIOField(const CompactIOField&) = default; CompactIOField(const CompactIOField&) = default;
//- Construct from IOobject //- Construct from IOobject. Will be zero size if not read.
explicit CompactIOField(const IOobject& io); explicit CompactIOField(const IOobject& io);
//- Construct from IOobject, with local processor conditional reading //- Construct from IOobject, with local processor conditional reading
@ -111,29 +115,55 @@ public:
CompactIOField(const IOobject& io, Field<T>&& content); 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 //- Destructor
virtual ~CompactIOField() = default; virtual ~CompactIOField() = default;
// Member Functions // 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 virtual bool writeObject
( (
IOstreamOption streamOpt, IOstreamOption streamOpt,
const bool writeOnProc const bool writeOnProc
) const; ) const;
//- Write as plain or compact content (depends on stream format)
virtual bool writeData(Ostream& os) const; virtual bool writeData(Ostream& os) const;
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const CompactIOField<T, BaseType>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using Field<T>::operator=; 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)));
}
}; };

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2015-2024 OpenCFD Ltd. Copyright (C) 2015-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -27,41 +27,39 @@ License
\*---------------------------------------------------------------------------*/ \*---------------------------------------------------------------------------*/
#include "CompactIOList.H" #include "CompactIOList.H"
#include "labelList.H"
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T, class BaseType> template<class T, class BaseType>
bool Foam::CompactIOList<T, BaseType>::readIOcontents() bool Foam::CompactIOList<T, BaseType>::readIOcontents()
{ {
if typedef IOList<T> plain_type;
(
readOpt() == IOobject::MUST_READ if (isReadRequired() || (isReadOptional() && headerOk()))
|| (isReadOptional() && headerOk())
)
{ {
Istream& is = readStream(word::null); Istream& is = readStream(word::null);
if (headerClassName() == IOList<T>::typeName) if (isHeaderClass(typeName))
{ {
is >> static_cast<List<T>&>(*this); // Compact form
close(); is >> *this; // or: this->readCompact(is);
} }
else if (headerClassName() == typeName) else if (isHeaderClass<plain_type>())
{ {
is >> *this; // Non-compact form
close(); is >> static_cast<content_type&>(*this);
} }
else else
{ {
FatalIOErrorInFunction(is) FatalIOErrorInFunction(is)
<< "Unexpected class name " << headerClassName() << "Unexpected class name " << headerClassName()
<< " expected " << typeName << " expected " << typeName
<< " or " << IOList<T>::typeName << endl << " or " << plain_type::typeName << endl
<< " while reading object " << name() << " while reading object " << name()
<< exit(FatalIOError); << exit(FatalIOError);
} }
close();
return true; 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> template<class T, class BaseType>
bool Foam::CompactIOList<T, BaseType>::overflows() const bool Foam::CompactIOList<T, BaseType>::overflows() const
{ {
const List<T>& lists = *this; // Can safely assume that int64 will not overflow
if constexpr (sizeof(label) < sizeof(int64_t))
label total = 0;
for (const auto& sublist : lists)
{ {
const label prev = total; const UList<T>& lists = *this;
total += sublist.size();
if (total < prev) label total = 0;
for (const auto& list : lists)
{ {
return true; const label prev = total;
total += list.size();
if (total < prev)
{
return true;
}
} }
} }
return false; 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 * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class BaseType> template<class T, class BaseType>
@ -177,12 +279,13 @@ bool Foam::CompactIOList<T, BaseType>::writeObject
streamOpt.format(IOstreamOption::ASCII); streamOpt.format(IOstreamOption::ASCII);
WarningInFunction WarningInFunction
<< "Overall number of elements of CompactIOList of size " << "Overall number of elements of CompactIOList (size:"
<< this->size() << " overflows the representation of a label" << this->size() << ") overflows a label (int"
<< nl << " Switching to ascii writing" << endl; << (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 // Change type to be non-compact format type
const word oldTypeName(typeName); const word oldTypeName(typeName);
@ -208,15 +311,98 @@ bool Foam::CompactIOList<T, BaseType>::writeData(Ostream& os) const
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T, class BaseType> template<class T, class BaseType>
void Foam::CompactIOList<T, BaseType>::operator= Foam::Istream& Foam::CompactIOList<T,BaseType>::readCompact(Istream& is)
(
const CompactIOList<T, BaseType>& rhs
)
{ {
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& Foam::operator>>
( (
Foam::Istream& is, Foam::Istream& is,
Foam::CompactIOList<T, BaseType>& L Foam::CompactIOList<T, BaseType>& lists
) )
{ {
// Read compact return lists.readCompact(is);
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;
} }
@ -257,49 +423,17 @@ template<class T, class BaseType>
Foam::Ostream& Foam::operator<< Foam::Ostream& Foam::operator<<
( (
Foam::Ostream& os, Foam::Ostream& os,
const Foam::CompactIOList<T, BaseType>& L const Foam::CompactIOList<T, BaseType>& lists
) )
{ {
// Keep ASCII writing same // 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 else
{ {
// Convert to compact format lists.writeCompact(os);
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;
} }
return os; return os;

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd. Copyright (C) 2018-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -52,16 +52,11 @@ namespace Foam
// Forward Declarations // Forward Declarations
template<class T, class BaseType> class CompactIOList; template<class T, class BaseType> class CompactIOList;
template<class T, class BaseType> Istream& operator>> template<class T, class BaseType>
( Istream& operator>>(Istream&, CompactIOList<T, BaseType>&);
Istream&,
CompactIOList<T, BaseType>& template<class T, class BaseType>
); Ostream& operator<<(Ostream&, const CompactIOList<T, BaseType>&);
template<class T, class BaseType> Ostream& operator<<
(
Ostream&,
const CompactIOList<T, BaseType>&
);
/*---------------------------------------------------------------------------*\ /*---------------------------------------------------------------------------*\
Class CompactIOList Declaration Class CompactIOList Declaration
@ -80,6 +75,10 @@ class CompactIOList
// Return true if read. // Return true if read.
bool readIOcontents(); bool readIOcontents();
//- Read the content size.
// Return the size if read, -1 otherwise
label readIOsize();
//- Has too many elements in it? //- Has too many elements in it?
bool overflows() const; bool overflows() const;
@ -98,7 +97,7 @@ public:
//- Default copy construct //- Default copy construct
CompactIOList(const CompactIOList&) = default; CompactIOList(const CompactIOList&) = default;
//- Construct from IOobject //- Construct from IOobject. Will be zero size if not read.
explicit CompactIOList(const IOobject& io); explicit CompactIOList(const IOobject& io);
//- Construct from IOobject and zero size (if not read) //- Construct from IOobject and zero size (if not read)
@ -114,12 +113,28 @@ public:
CompactIOList(const IOobject& io, List<T>&& content); 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 //- Destructor
virtual ~CompactIOList() = default; virtual ~CompactIOList() = default;
// Member Functions // 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 //- Write using stream options. Checks for overflow in binary
virtual bool writeObject virtual bool writeObject
( (
@ -127,16 +142,26 @@ public:
const bool writeOnProc const bool writeOnProc
) const; ) const;
//- Write as plain or compact content (depends on stream format)
virtual bool writeData(Ostream& os) const; virtual bool writeData(Ostream& os) const;
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const CompactIOList<T, BaseType>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using List<T>::operator=; 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)));
}
}; };

View File

@ -132,6 +132,7 @@ Foam::Field<Type> Foam::GlobalIOField<Type>::readContents(const IOobject& io)
{ {
rio.readOpt(IOobjectOption::MUST_READ); rio.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
// The object is global // The object is global
rio.globalObject(true); 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);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -69,7 +69,7 @@ public:
//- Default copy construct //- Default copy construct
GlobalIOField(const GlobalIOField&) = default; GlobalIOField(const GlobalIOField&) = default;
//- Construct from IOobject //- Construct from IOobject. Will be zero size if not read.
explicit GlobalIOField(const IOobject& io); explicit GlobalIOField(const IOobject& io);
//- Construct from IOobject and field size (if not read) //- Construct from IOobject and field size (if not read)
@ -119,11 +119,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const GlobalIOField<Type>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using Field<Type>::operator=; 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)));
}
}; };

View File

@ -116,6 +116,7 @@ Foam::List<Type> Foam::GlobalIOList<Type>::readContents(const IOobject& io)
{ {
rio.readOpt(IOobjectOption::MUST_READ); rio.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
// The object is global // The object is global
rio.globalObject(true); 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);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -69,7 +69,7 @@ public:
//- Default copy construct //- Default copy construct
GlobalIOList(const GlobalIOList&) = default; GlobalIOList(const GlobalIOList&) = default;
//- Construct from IOobject //- Construct from IOobject. Will be zero size if not read.
explicit GlobalIOList(const IOobject& io); explicit GlobalIOList(const IOobject& io);
//- Construct from IOobject and zero size (if not read) //- Construct from IOobject and zero size (if not read)
@ -119,11 +119,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const GlobalIOList<Type>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using List<Type>::operator=; 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)));
}
}; };

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2016-2024 OpenCFD Ltd. Copyright (C) 2016-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. 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 * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
template<class Type> template<class Type>
@ -167,6 +199,26 @@ Foam::IOFieldRef<Type>::IOFieldRef
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * 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> template<class Type>
Foam::Field<Type> Foam::IOField<Type>::readContents(const IOobject& io) 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.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
IOField<Type> reader(rio); 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);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation | \\/ M anipulation |
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
Copyright (C) 2011-2017 OpenFOAM Foundation Copyright (C) 2011-2017 OpenFOAM Foundation
Copyright (C) 2018-2024 OpenCFD Ltd. Copyright (C) 2018-2025 OpenCFD Ltd.
------------------------------------------------------------------------------- -------------------------------------------------------------------------------
License License
This file is part of OpenFOAM. This file is part of OpenFOAM.
@ -62,6 +62,10 @@ class IOField
// Return true if read (only accurate when readOnProc == true). // Return true if read (only accurate when readOnProc == true).
bool readIOcontents(bool readOnProc = true); bool readIOcontents(bool readOnProc = true);
//- Read the content size.
// Return the size if read, -1 otherwise
label readIOsize();
public: public:
//- The underlying content type //- The underlying content type
@ -76,7 +80,7 @@ public:
//- Default copy construct //- Default copy construct
IOField(const IOField&) = default; IOField(const IOField&) = default;
//- Construct from IOobject //- Construct from IOobject. Will be zero size if not read.
explicit IOField(const IOobject& io); explicit IOField(const IOobject& io);
//- Construct from IOobject, with local processor conditional reading //- Construct from IOobject, with local processor conditional reading
@ -100,6 +104,10 @@ public:
// Factory Methods // 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 //- Read and return contents. The IOobject will not be registered
static Field<Type> readContents(const IOobject& io); static Field<Type> readContents(const IOobject& io);
@ -116,11 +124,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const IOField<Type>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using Field<Type>::operator=; 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)));
}
}; };

View File

@ -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 * * * * * * * * * * * * * * * // // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
template<class T> template<class T>
@ -128,6 +160,26 @@ Foam::IOListRef<T>::IOListRef
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * // // * * * * * * * * * * * * * 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> template<class T>
Foam::List<T> Foam::IOList<T>::readContents(const IOobject& io) 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.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
IOList<T> reader(rio); 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);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -61,6 +61,10 @@ class IOList
//- Read if IOobject flags set. Return true if read. //- Read if IOobject flags set. Return true if read.
bool readIOcontents(); bool readIOcontents();
//- Read the content size.
// Return the size if read, -1 otherwise
label readIOsize();
public: public:
//- The underlying content type //- The underlying content type
@ -75,7 +79,7 @@ public:
//- Default copy construct //- Default copy construct
IOList(const IOList&) = default; IOList(const IOList&) = default;
//- Construct from IOobject //- Construct from IOobject. Will be zero size if not read.
explicit IOList(const IOobject& io); explicit IOList(const IOobject& io);
//- Construct from IOobject and zero size (if not read) //- Construct from IOobject and zero size (if not read)
@ -93,6 +97,10 @@ public:
// Factory Methods // 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 //- Read and return contents. The IOobject is never registered
static List<T> readContents(const IOobject& io); static List<T> readContents(const IOobject& io);
@ -113,11 +121,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const IOList<T>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using List<T>::operator=; 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)));
}
}; };

View File

@ -104,6 +104,7 @@ Foam::Map<T> Foam::IOMap<T>::readContents(const IOobject& io)
{ {
rio.readOpt(IOobjectOption::MUST_READ); rio.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
// The object is global // The object is global
rio.globalObject(true); 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);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -120,11 +120,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const IOMap<T>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using Map<T>::operator=; 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)));
}
}; };

View File

@ -126,6 +126,7 @@ Foam::PtrList<T> Foam::IOPtrList<T>::readContents(const IOobject& io)
{ {
rio.readOpt(IOobjectOption::MUST_READ); rio.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
IOPtrList<T> reader(rio); 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);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -101,11 +101,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of entries
void operator=(const IOPtrList<T>& rhs);
//- Copy or move assignment of entries //- Copy or move assignment of entries
using PtrList<T>::operator=; 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)));
}
}; };

View File

@ -113,12 +113,4 @@ bool Foam::baseIOdictionary::writeData(Ostream& os) const
} }
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
void Foam::baseIOdictionary::operator=(const baseIOdictionary& rhs)
{
dictionary::operator=(rhs);
}
// ************************************************************************* // // ************************************************************************* //

View File

@ -123,11 +123,20 @@ public:
// Member Operators // Member Operators
//- Copy assignment of dictionary entries (leave regIOobject untouched)
void operator=(const baseIOdictionary& rhs);
//- Copy assignment of dictionary entries //- Copy assignment of dictionary entries
using dictionary::operator=; 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)));
}
}; };

View File

@ -198,6 +198,7 @@ Foam::Field<Type> Foam::rawIOField<Type>::readContents(const IOobject& io)
{ {
rio.readOpt(IOobjectOption::MUST_READ); rio.readOpt(IOobjectOption::MUST_READ);
} }
rio.resetHeader();
rawIOField<Type> reader(rio); rawIOField<Type> reader(rio);