Merge branch 'improve-IOobject_PtrList_CompactIOList_List' into 'develop'

general list cleanups

See merge request Development/openfoam!754
This commit is contained in:
Mattijs Janssens
2025-08-28 08:44:32 +00:00
114 changed files with 1757 additions and 943 deletions

View File

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

View File

@ -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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -86,20 +86,7 @@ Ostream& printAddr
const UPtrList<T>& list
)
{
const label len = list.size();
// Size and start delimiter
os << nl << indent << len << nl
<< indent << token::BEGIN_LIST << incrIndent << nl;
for (label i=0; i < len; ++i)
{
os << "addr=" << Foam::name(list.get(i)) << nl;
}
// End delimiter
os << decrIndent << indent << token::END_LIST << nl;
return os;
return list.printAddresses(os);
}
@ -176,11 +163,11 @@ Ostream& print
{
const label cap = list.capacity();
for (label i=len; i < cap; ++i)
for (label i = len; i < cap; ++i)
{
const T* ptr = list.get(i);
os << "unused " << name(ptr) << nl;
os << "unused " << Foam::name(ptr) << nl;
}
}
@ -518,6 +505,7 @@ int main(int argc, char *argv[])
print(Info, dynlist1d);
Info<< "addresses:" << nl;
dynlist1d.printAddresses(Info, true);
printAddr(Info, dynlist1d);
PtrList<Scalar> list1d;

View File

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

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2021 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -75,9 +75,9 @@ inline Ostream& info(const UList<bool>& bools)
Info<< "size=" << bools.size()
<< " count=" << BitOps::count(bools)
<< " !count=" << BitOps::count(bools, false)
<< " all:" << BitOps::all(bools)
<< " any:" << BitOps::any(bools)
<< " none:" << BitOps::none(bools) << nl;
<< " all:" << bools.all()
<< " any:" << bools.any()
<< " none:" << bools.none() << nl;
return Info;
}
@ -194,8 +194,10 @@ int main(int argc, char *argv[])
{
boolList bools = list1.values();
Info<<"===============" << nl;
Info<<"bools: " << flatOutput(bools) << nl;
Info<< "===============" << nl;
Info<< "bools: " << flatOutput(bools) << nl;
Info<< " ";
info(bools);
for (int i : { -10, 0, 8, 15, 32})
{
@ -238,17 +240,18 @@ int main(int argc, char *argv[])
}
#ifdef TEST_SFINAE
// This should fail to compile:
{
labelList labels = list1.toc();
if (labels.test(0))
{
Info<<"no" << endl;
Info<< "no" << endl;
}
List<double*> ptrs(10, nullptr);
if (ptrs.get(0))
{
Info<<"no" << endl;
Info<< "no" << endl;
}
}
#endif

View File

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

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2020-2022 OpenCFD Ltd.
Copyright (C) 2020-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -71,9 +71,9 @@ inline Ostream& info(const UList<bool>& bools)
Info<< "size=" << bools.size()
<< " count=" << BitOps::count(bools)
<< " !count=" << BitOps::count(bools, false)
<< " all:" << BitOps::all(bools)
<< " any:" << BitOps::any(bools)
<< " none:" << BitOps::none(bools) << nl;
<< " all:" << bools.all()
<< " any:" << bools.any()
<< " none:" << bools.none() << nl;
return Info;
}

View File

@ -64,7 +64,7 @@ Foam::label Foam::parLagrangianDistributor::readAllFields
); \
\
nTotal += parLagrangianDistributor::readFields \
<CompactIOField<Field<Type>, Type>> \
<CompactIOField<Field<Type>>> \
( \
cloud, \
haveCloud, \
@ -177,7 +177,7 @@ Foam::label Foam::parLagrangianDistributor::distributeAllStoredFields
); \
\
nTotal += this->distributeStoredFields \
<CompactIOField<Field<Type>, Type>> \
<CompactIOField<Field<Type>>> \
( \
lagrangianMap, \
cloud \

View File

@ -156,14 +156,15 @@ Foam::label Foam::parLagrangianDistributor::distributeFieldFields
const wordRes& selectedFields
) const
{
typedef CompactIOField<Field<Type>, Type> Container;
typedef CompactIOField<Field<Type>> Container;
typedef IOField<Field<Type>> fallbackType;
DynamicList<word> fieldNames;
// CompactIOField Field names
fieldNames.push_back
(
filterObjects<CompactIOField<Field<Type>, Type>>
filterObjects<Container>
(
objects,
selectedFields
@ -173,7 +174,7 @@ Foam::label Foam::parLagrangianDistributor::distributeFieldFields
// IOField Field names
fieldNames.push_back
(
filterObjects<IOField<Field<Type>>>
filterObjects<fallbackType>
(
objects,
selectedFields

View File

@ -129,7 +129,7 @@ void MapLagrangianFields
MapLagrangianFields
<
IOField<Field<Type>>,
CompactIOField<Field<Type>, Type>
CompactIOField<Field<Type>>
>
(
cloudName,
@ -141,8 +141,8 @@ void MapLagrangianFields
MapLagrangianFields
<
CompactIOField<Field<Type>, Type>,
CompactIOField<Field<Type>, Type>
CompactIOField<Field<Type>>,
CompactIOField<Field<Type>>
>
(
cloudName,

View File

@ -133,7 +133,7 @@ void MapLagrangianFields
MapLagrangianFields
<
IOField<Field<Type>>,
CompactIOField<Field<Type>, Type>
CompactIOField<Field<Type>>
>
(
cloudName,
@ -145,8 +145,8 @@ void MapLagrangianFields
MapLagrangianFields
<
CompactIOField<Field<Type>, Type>,
CompactIOField<Field<Type>, Type>
CompactIOField<Field<Type>>,
CompactIOField<Field<Type>>
>
(
cloudName,

View File

@ -42,7 +42,6 @@ chars = primitives/chars
$(chars)/char/char.C
$(chars)/wchar/wchar.C
$(chars)/lists/charList.C
$(chars)/lists/charUList.C
primitives/direction/directionIO.C

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -33,6 +33,12 @@ License
// * * * * * * * * * * * * * * * * * BitOps * * * * * * * * * * * * * * * * //
unsigned int Foam::BitOps::count(const bitSet& bitset, const bool on)
{
return bitset.count(on);
}
// See bitSet::setMany for original implementation
void Foam::BitOps::set(List<bool>& bools, const labelUList& locations)
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -77,26 +77,17 @@ inline unsigned int count(const UList<bool>& bools, const bool val=true)
return std::count(bools.begin(), bools.end(), val);
}
//- True if all entries are 'true' or if the set is empty.
//- True if all entries are 'true' or if the list is empty.
// For compatibility with bitSet::all()
inline bool all(const UList<bool>& bools)
{
return std::all_of(bools.begin(), bools.end(), identityOp());
}
inline bool all(const UList<bool>& bools) { return bools.all(); }
//- True if any entries are 'true'.
// For compatibility with bitSet::any()
inline bool any(const UList<bool>& bools)
{
return std::any_of(bools.begin(), bools.end(), identityOp());
}
inline bool any(const UList<bool>& bools) { return bools.any(); }
//- True if no entries are 'true'.
// For compatibility with bitSet::none()
inline bool none(const UList<bool>& bools)
{
return std::none_of(bools.begin(), bools.end(), identityOp());
}
inline bool none(const UList<bool>& bools) { return bools.none(); }
//- Set the listed locations (assign 'true').
@ -150,6 +141,10 @@ List<bool> select(const label n, const labelUList& locations);
// \return a List of bools
List<bool> select(const labelUList& locations);
//- Forward to bitSet::count()
unsigned int count(const bitSet& bitset, const bool on=true);
//- Return the (sorted) values corresponding to 'true' entries.
// Similar to bitSet::toc()
//
@ -292,13 +287,13 @@ struct bitInfo
constexpr bitInfo() noexcept : value(0) {}
//- Value construct
explicit bitInfo(UIntType val) : value(val) {}
explicit bitInfo(UIntType val) noexcept : value(val) {}
//- Conversion to base type
operator UIntType () const { return value; }
operator UIntType () const noexcept { return value; }
//- Conversion to base type
operator UIntType& () { return value; }
operator UIntType& () noexcept { return value; }
};
} // End namespace BitOps

View File

@ -149,6 +149,10 @@ public:
//- if the key does not exist in the table.
inline const T* get(const Key& key) const;
//- Return pointer associated with given entry or a nullptr
//- if the key does not exist in the table.
inline T* get(const Key& key);
// Edit
@ -234,7 +238,9 @@ public:
inline bool emplace(const Key& key, Args&&... args);
//- Emplace set an entry, overwriting any existing entries.
// \return Reference to the new element.
// \param key - the location to set
// \param args arguments to forward to the constructor of the element
// \return reference to the new element.
template<class... Args>
inline T& emplace_set(const Key& key, Args&&... args);

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -57,6 +57,19 @@ inline const T* Foam::HashPtrTable<T, Key, Hash>::get(const Key& key) const
}
template<class T, class Key, class Hash>
inline T* Foam::HashPtrTable<T, Key, Hash>::get(const Key& key)
{
// Like lookup() with a nullptr + const_cast
iterator iter(this->find(key));
if (iter.good())
{
return iter.val();
}
return nullptr;
}
template<class T, class Key, class Hash>
template<class... Args>
inline bool Foam::HashPtrTable<T, Key, Hash>::emplace

View File

@ -255,7 +255,7 @@ public:
// Edit
//- Swap with plain List content. Implies shrink_to_fit().
inline void swap(List<T>& list);
inline void swap(List<T>& other);
//- Swap content, independent of sizing parameter
template<int AnySizeMin>
@ -264,7 +264,7 @@ public:
//- Transfer contents of the argument List into this.
inline void transfer(List<T>& list);
//- Transfer contents of any sized DynamicList into this.
//- Transfer contents of any DynamicList into this.
template<int AnySizeMin>
inline void transfer(DynamicList<T, AnySizeMin>& list);

View File

@ -445,6 +445,8 @@ inline void Foam::DynamicList<T, SizeMin>::clear() noexcept
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::clearStorage()
{
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
List<T>::clear();
capacity_ = 0;
}
@ -465,12 +467,15 @@ inline void Foam::DynamicList<T, SizeMin>::shrink_to_fit()
template<class T, int SizeMin>
inline void
Foam::DynamicList<T, SizeMin>::swap(List<T>& list)
Foam::DynamicList<T, SizeMin>::swap(List<T>& other)
{
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
== static_cast<const List<T>*>(&other)
)
)
{
return; // Self-swap is a no-op
@ -480,7 +485,7 @@ Foam::DynamicList<T, SizeMin>::swap(List<T>& list)
this->shrink_to_fit();
// Swap storage and addressable size
UList<T>::swap(list);
UList<T>::swap(other);
// Update capacity
capacity_ = List<T>::size();
@ -495,10 +500,13 @@ inline void Foam::DynamicList<T, SizeMin>::swap
) noexcept
{
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&other)
)
)
{
return; // Self-swap is a no-op
}
@ -515,6 +523,10 @@ template<class T, int SizeMin>
inline void
Foam::DynamicList<T, SizeMin>::transfer(List<T>& list)
{
// No check for self-assignment (different types)
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
List<T>::transfer(list);
capacity_ = List<T>::size();
}
@ -529,19 +541,23 @@ Foam::DynamicList<T, SizeMin>::transfer
)
{
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
// Take over storage as-is (without shrink)
capacity_ = list.capacity();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
List<T>::transfer(static_cast<List<T>&>(list));
list.clearStorage(); // capacity=0 etc.
capacity_ = list.capacity();
list.setCapacity_unsafe(0); // All contents moved
}
@ -594,7 +610,14 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
const UList<T>& list
)
{
if (FOAM_UNLIKELY(this == &list))
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
)
{
FatalErrorInFunction
<< "Attempted push_back to self"
@ -665,7 +688,14 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
List<T>&& list
)
{
if (FOAM_UNLIKELY(this == &list))
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
)
{
FatalErrorInFunction
<< "Attempted push_back to self"
@ -675,6 +705,7 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
const label idx = List<T>::size();
resize(idx + list.size());
// Move the elements
std::move(list.begin(), list.end(), this->begin(idx));
list.clear();
@ -688,7 +719,26 @@ inline void Foam::DynamicList<T, SizeMin>::push_back
DynamicList<T, AnySizeMin>&& list
)
{
push_back(std::move(static_cast<List<T>&>(list)));
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
)
{
FatalErrorInFunction
<< "Attempted push_back to self"
<< abort(FatalError);
}
const label idx = List<T>::size();
resize(idx + list.size());
// Move the elements
std::move(list.begin(), list.end(), this->begin(idx));
list.clearStorage(); // Deletion, capacity=0 etc.
}
@ -866,15 +916,22 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::operator=
(
const DynamicList<T, SizeMin>& lst
const DynamicList<T, SizeMin>& list
)
{
if (this == &lst)
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
doAssignDynList(lst);
doAssignDynList(list);
}
@ -886,10 +943,13 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
)
{
if
(
FOAM_UNLIKELY
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
@ -912,44 +972,41 @@ template<class T, int SizeMin>
template<class Addr>
inline void Foam::DynamicList<T, SizeMin>::operator=
(
const IndirectListBase<T, Addr>& lst
const IndirectListBase<T, Addr>& list
)
{
// NOTE: Self-assignment needs special handling
/// if
/// (
/// static_cast<const UList<T>*>(this)
/// == static_cast<const UList<T>*>(&list.values())
/// )
// if
// (
// FOAM_UNLIKELY
// (
// static_cast<const UList<T>*>(this)
// == static_cast<const UList<T>*>(&list.values())
// )
// )
// { ... }
doAssignDynList(lst);
doAssignDynList(list);
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::operator=
(
List<T>&& lst
List<T>&& list
)
{
clear();
transfer(lst);
this->transfer(list);
}
template<class T, int SizeMin>
inline void Foam::DynamicList<T, SizeMin>::operator=
(
DynamicList<T, SizeMin>&& lst
DynamicList<T, SizeMin>&& list
)
{
if (this == &lst)
{
return; // Self-assignment is a no-op
}
clear();
transfer(lst);
this->transfer(list);
}
@ -960,17 +1017,7 @@ inline void Foam::DynamicList<T, SizeMin>::operator=
DynamicList<T, AnySizeMin>&& list
)
{
if
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
)
{
return; // Self-assignment is a no-op
}
clear();
transfer(list);
this->transfer(list);
}

View File

@ -169,8 +169,8 @@ template<class T, unsigned N>
bool Foam::FixedList<T, N>::operator==(const FixedList<T, N>& list) const
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
return
(
// List sizes are identical by definition (template parameter)
@ -185,8 +185,8 @@ bool Foam::FixedList<T, N>::operator<(const FixedList<T, N>& list) const
// List sizes are identical by definition (template parameter)
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
return std::lexicographical_compare
(
this->cbegin(), this->cend(),

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2017-2023 OpenCFD Ltd.
Copyright (C) 2017-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -356,12 +356,17 @@ inline void Foam::FixedList<T, N>::fill(const T& val)
template<class T, unsigned N>
inline void Foam::FixedList<T, N>::fill(Foam::zero)
{
if constexpr (std::is_arithmetic_v<T>)
{
// Usually small enough that parallel execution is pointless...
// Cannot use std::fill (ambiguous conversions for bool, char, etc)
std::fill_n(v_, N, T(0));
}
else
{
for (unsigned i = 0; i < N; ++i)
{
v_[i] = Zero;
v_[i] = Foam::zero{};
}
}
}

View File

@ -113,8 +113,8 @@ void Foam::UList<T>::deepCopy(const UList<T>& list)
else if (this->size_ > 0)
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
std::copy(list.cbegin(), list.cend(), this->v_);
}
}
@ -150,16 +150,6 @@ void Foam::UList<T>::deepCopy(const IndirectListBase<T, Addr>& list)
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// This is non-inlined to allow template specializations
template<class T>
void Foam::UList<T>::operator=(Foam::zero)
{
this->fill_uniform(Foam::zero{});
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
@ -244,8 +234,8 @@ template<class T>
bool Foam::UList<T>::operator==(const UList<T>& list) const
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
return
(
(this->size_ == list.size_)
@ -265,8 +255,8 @@ template<class T>
bool Foam::UList<T>::operator<(const UList<T>& list) const
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
return std::lexicographical_compare
(
this->cbegin(), this->cend(),

View File

@ -435,7 +435,7 @@ public:
inline void operator=(const T& val);
//- Assignment of all entries to zero
void operator=(Foam::zero);
inline void operator=(Foam::zero);
// Random access iterator (non-const)
@ -565,11 +565,38 @@ public:
// Special Methods
//- True if all entries are 'true' or if the list is empty.
// \note Method name compatibility with bitSet
template<class TypeT = T>
std::enable_if_t<std::is_same_v<bool, std::remove_cv_t<TypeT>>, bool>
inline all() const
{
return !contains(false);
}
//- True if any entries are 'true'.
// \note Method name compatibility with bitSet
template<class TypeT = T>
std::enable_if_t<std::is_same_v<bool, std::remove_cv_t<TypeT>>, bool>
inline any() const
{
return contains(true);
}
//- True if no entries are 'true'.
// \note Method name compatibility with bitSet
template<class TypeT = T>
std::enable_if_t<std::is_same_v<bool, std::remove_cv_t<TypeT>>, bool>
inline none() const
{
return !contains(true);
}
//- Test \c bool value at specified position,
//- always false for out-of-range access.
// \note Method name compatibility with bitSet, HashSet
template<class TypeT = T>
std::enable_if_t<std::is_same_v<bool, TypeT>, bool>
std::enable_if_t<std::is_same_v<bool, std::remove_cv_t<TypeT>>, bool>
inline test(const label i) const
{
return (i >= 0 && i < size_ && v_[i]);
@ -579,7 +606,7 @@ public:
//- always false for out-of-range access.
// \note Method name compatibility with bitSet
template<class TypeT = T>
std::enable_if_t<std::is_same_v<bool, TypeT>, bool>
std::enable_if_t<std::is_same_v<bool, std::remove_cv_t<TypeT>>, bool>
inline get(const label i) const
{
return (i >= 0 && i < size_ && v_[i]);
@ -664,17 +691,6 @@ public:
};
// * * * * * * * * * * * * Template Specializations * * * * * * * * * * * * //
//- Character list writeEntry
template<>
void UList<char>::writeEntry(Ostream& os) const;
//- Character list assign zero - avoids Foam::zero casting ambiguities
template<>
void UList<char>::operator=(Foam::zero);
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
//- Read List contents from Istream, list must have the proper size!

View File

@ -53,8 +53,8 @@ template<class T>
inline void Foam::UList<T>::fill_uniform(const T& val)
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
std::fill_n
(
this->v_, this->size_, val
@ -65,15 +65,21 @@ inline void Foam::UList<T>::fill_uniform(const T& val)
template<class T>
inline void Foam::UList<T>::fill_uniform(Foam::zero)
{
// Note: ambiguous conversions for char can still cause compilation
// issues.
// May also have special triggers when assigning non-contiguous from zero...
if constexpr (is_contiguous_v<T>)
if constexpr (std::is_arithmetic_v<T>)
{
// Can dispatch with
// - std::execution::parallel_unsequenced_policy
// - std::execution::unsequenced_policy
// - std::execution::par_unseq
// - std::execution::unseq
std::fill_n
(
this->v_, this->size_, T(0)
);
}
else if constexpr (is_contiguous_v<T>)
{
// Can dispatch with
// - std::execution::par_unseq
// - std::execution::unseq
std::fill_n
(
this->data_bytes(), this->size_bytes(), char(0)
@ -81,6 +87,9 @@ inline void Foam::UList<T>::fill_uniform(Foam::zero)
}
else
{
// May also have special triggers when assigning non-contiguous
// from zero...
const auto last = (this->v_ + this->size_);
for (auto first = this->v_; (first != last); (void)++first)
@ -348,29 +357,34 @@ inline void Foam::UList<T>::operator=(const T& val)
}
namespace Foam
{
// Template specialization for bool
template<>
inline const bool& Foam::UList<bool>::operator[](const label i) const
{
// Lazy evaluation - return false for out-of-range
if (i >= 0 && i < size_)
{
return v_[i];
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
return Foam::pTraits<bool>::zero;
}
} // End namespace Foam
template<class T>
inline void Foam::UList<T>::operator=(Foam::zero)
{
this->fill_uniform(Foam::zero{});
}
template<class T>
inline T& Foam::UList<T>::operator[](const label i)
{
if constexpr (std::is_same_v<bool, std::remove_cv_t<T>>)
{
// Lazy evaluation - return false for out-of-range
// Note: strictly speaking should not be modifiable but we cannot
// alway control which signature (const or non-const) is called
if (i < 0 || i >= size_)
{
return const_cast<bool&>(Foam::pTraits<bool>::null());
}
}
else
{
#ifdef FULLDEBUG
checkIndex(i);
#endif
}
return v_[i];
}
@ -378,9 +392,20 @@ inline T& Foam::UList<T>::operator[](const label i)
template<class T>
inline const T& Foam::UList<T>::operator[](const label i) const
{
if constexpr (std::is_same_v<bool, std::remove_cv_t<T>>)
{
// Lazy evaluation - return false for out-of-range
if (i < 0 || i >= size_)
{
return Foam::pTraits<bool>::null();
}
}
else
{
#ifdef FULLDEBUG
checkIndex(i);
#endif
}
return v_[i];
}

View File

@ -35,6 +35,25 @@ License
template<class T>
void Foam::UList<T>::writeEntry(Ostream& os) const
{
if constexpr (std::is_same_v<char, std::remove_cv_t<T>>)
{
// Char data has a compound type:
os << word("List<char>");
if (this->size())
{
// Non-zero size: write as binary, so has leading newline separator.
os << *this;
}
else
{
// Zero-sized binary - Write size only
// Note that char data is always binary I/O only
os << token::SPACE << label(0);
}
}
else
{
const word tag("List<" + word(pTraits<T>::typeName) + '>');
if (token::compound::isCompound(tag))
{
@ -45,14 +64,9 @@ void Foam::UList<T>::writeEntry(Ostream& os) const
{
os << *this;
}
else if
(
os.format() == IOstreamOption::BINARY
|| std::is_same_v<char, std::remove_cv_t<T>>
)
else if (os.format() == IOstreamOption::BINARY)
{
// Zero-sized binary - Write size only
// NB: special treatment for char data (binary I/O only)
os << label(0);
}
else
@ -60,6 +74,7 @@ void Foam::UList<T>::writeEntry(Ostream& os) const
// Zero-sized ASCII - Write size and delimiters
os << label(0) << token::BEGIN_LIST << token::END_LIST;
}
}
}

View File

@ -658,6 +658,18 @@ inline void identity(labelUList& map, label start = 0)
}
//- Count the occurrences of the given element.
// When start is specified, any occurrences before start are ignored.
// Like std::count but works with list indexing
template<class ListType>
label count
(
const ListType& input,
typename ListType::const_reference val,
const label start=0
);
//- Count the number of matching entries.
// When start is specified, any occurrences before start are ignored.
// Linear search.

View File

@ -1154,6 +1154,33 @@ bool Foam::ListOps::equal
}
template<class ListType>
Foam::label Foam::ListOps::count
(
const ListType& input,
typename ListType::const_reference val,
const label start
)
{
label num = 0;
const label len = input.size();
if (start >= 0)
{
for (label i = start; i < len; ++i)
{
if (val == input[i])
{
++num;
}
}
}
return num;
}
template<class ListType, class UnaryPredicate>
Foam::label Foam::ListOps::count_if
(

View File

@ -238,14 +238,18 @@ public:
//- Auto-sizes list as required.
inline autoPtr<T> set(const label i, const tmp<T>& ptr);
//- Reorder elements. Reordering must be unique (ie, shuffle).
inline void reorder(const labelUList& oldToNew);
// Writing
//- Print pointer addresses to Ostream (debugging only).
// Optionally print addresses within the upper (capacity) region
Ostream& printAddresses(Ostream& os, const bool full=false) const;
// Member Operators
//- Copy (clone) assignment
inline void operator=(const PtrList<T>& list);
inline void operator=(const UPtrList<T>& list);
//- Copy (clone) assignment
inline void operator=(const PtrDynList<T, SizeMin>& list);

View File

@ -226,6 +226,8 @@ inline void Foam::PtrDynList<T, SizeMin>::clear()
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::clearStorage()
{
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
PtrList<T>::clear();
capacity_ = 0;
}
@ -257,10 +259,13 @@ template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::swap(PtrList<T>& list)
{
if
(
FOAM_UNLIKELY
(
static_cast<const PtrList<T>*>(this)
== static_cast<const PtrList<T>*>(&list)
)
)
{
return; // Self-swap is a no-op
}
@ -284,10 +289,13 @@ inline void Foam::PtrDynList<T, SizeMin>::swap
) noexcept
{
if
(
FOAM_UNLIKELY
(
static_cast<const PtrList<T>*>(this)
== static_cast<const PtrList<T>*>(&other)
)
)
{
return; // Self-swap is a no-op
}
@ -303,15 +311,10 @@ inline void Foam::PtrDynList<T, SizeMin>::swap
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::transfer(PtrList<T>& list)
{
if
(
static_cast<const PtrList<T>*>(this)
== static_cast<const PtrList<T>*>(&list)
)
{
return; // Self assignment is a no-op
}
// No check for self-assignment (different types)
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
PtrList<T>::transfer(list);
capacity_ = PtrList<T>::size();
}
@ -325,19 +328,23 @@ inline void Foam::PtrDynList<T, SizeMin>::transfer
)
{
if
(
FOAM_UNLIKELY
(
static_cast<const PtrList<T>*>(this)
== static_cast<const PtrList<T>*>(&list)
)
)
{
return; // Self assignment is a no-op
}
// Take over storage as-is (without shrink)
capacity_ = list.capacity();
// Consistent allocated sizing
PtrList<T>::setAddressableSize(capacity_);
PtrList<T>::transfer(static_cast<PtrList<T>&>(list));
list.clearStorage(); // capacity=0 etc.
capacity_ = list.capacity();
list.setCapacity_unsafe(0); // All contents moved
}
@ -413,10 +420,13 @@ inline void Foam::PtrDynList<T, SizeMin>::push_back
)
{
if
(
FOAM_UNLIKELY
(
static_cast<const PtrList<T>*>(this)
== static_cast<const PtrList<T>*>(&other)
)
)
{
FatalErrorInFunction
<< "Attempted push_back to self"
@ -557,11 +567,20 @@ inline Foam::autoPtr<T> Foam::PtrDynList<T, SizeMin>::set
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::reorder(const labelUList& oldToNew)
Foam::Ostream& Foam::PtrDynList<T, SizeMin>::printAddresses
(
Ostream& os,
const bool full
) const
{
// Shrinking first is a bit annoying, but saves needing a special version.
this->shrink_to_fit();
PtrList<T>::reorder(oldToNew);
if (full)
{
return this->ptrs_.printAddresses(os, capacity_);
}
else
{
return UPtrList<T>::printAddresses(os);
}
}
@ -570,16 +589,23 @@ inline void Foam::PtrDynList<T, SizeMin>::reorder(const labelUList& oldToNew)
template<class T, int SizeMin>
inline void Foam::PtrDynList<T, SizeMin>::operator=
(
const PtrList<T>& list
const UPtrList<T>& list
)
{
if (this == &list)
if
(
FOAM_UNLIKELY
(
static_cast<const UPtrList<T>*>(this)
== static_cast<const UPtrList<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
this->resize(list.size());
PtrList<T>::operator=(list);
capacity_ = PtrList<T>::size();
}
@ -589,13 +615,20 @@ inline void Foam::PtrDynList<T, SizeMin>::operator=
const PtrDynList<T, SizeMin>& list
)
{
if (this == &list)
if
(
FOAM_UNLIKELY
(
static_cast<const UPtrList<T>*>(this)
== static_cast<const UPtrList<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
PtrList<T>::operator=(list);
capacity_ = PtrList<T>::size();
this->resize(list.size());
PtrList<T>::operator=(static_cast<UPtrList<T>&>(list));
}
@ -607,15 +640,19 @@ inline void Foam::PtrDynList<T, SizeMin>::operator=
)
{
if
(
FOAM_UNLIKELY
(
static_cast<const PtrList<T>*>(this)
== static_cast<const PtrList<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
PtrList<T>::operator=(list);
this->resize(list.size());
PtrList<T>::operator=(static_cast<UPtrList<T>&>(list));
capacity_ = PtrList<T>::size();
}

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2019 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -29,26 +29,55 @@ License
#include "PtrList.H"
#include "SLPtrList.H"
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
template<class T>
Foam::PtrList<T>::PtrList(PtrList<T>& list, bool reuse)
:
UPtrList<T>(list, reuse)
template<bool CheckSelf>
void Foam::PtrList<T>::copyPtrList(const UPtrList<T>& list)
{
if (!reuse)
// Check for self-assignment here instead of caller
if constexpr (CheckSelf)
{
// This works like an inplace clone method
const label len = this->size();
if (FOAM_UNLIKELY(this == &list))
{
return; // Self-assignment is a no-op
}
}
for (label i=0; i<len; ++i)
const label len = list.size();
// Truncate (frees old pointers) or extend the length
PtrList<T>::resize(len);
for (label i = 0; i < len; ++i)
{
this->ptrs_[i] = (list[i]).clone().ptr();
const T* src = list.get(i);
if (src)
{
if (this->ptrs_[i])
{
// Deep copy values into existing destination
*(this->ptrs_[i]) = *src;
}
else
{
// Clone pointers for new entries
this->ptrs_[i] = src->clone().ptr();
}
}
else
{
// No source pointer, so remove destination (if any) too
delete this->ptrs_[i];
this->ptrs_[i] = nullptr;
}
}
}
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
template<class T>
Foam::PtrList<T>::PtrList(const SLPtrList<T>& list)
:
@ -122,45 +151,4 @@ void Foam::PtrList<T>::resize(const label newLen)
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
void Foam::PtrList<T>::operator=(const PtrList<T>& list)
{
if (this == &list)
{
return; // Self-assignment is a no-op
}
const label oldLen = this->size();
const label newLen = list.size();
// Truncate (frees old pointers) or extend the length
resize(newLen);
if (newLen < oldLen)
{
// Copy values for existing entries
for (label i=0; i<newLen; ++i)
{
(*this)[i] = list[i];
}
}
else
{
// Copy values for existing entries
for (label i=0; i<oldLen; ++i)
{
(*this)[i] = list[i];
}
// Clone pointers for new entries
for (label i=oldLen; i<newLen; ++i)
{
this->ptrs_[i] = (list[i]).clone().ptr();
}
}
}
// ************************************************************************* //

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -70,6 +70,15 @@ class PtrList
:
public UPtrList<T>
{
// Private Member Functions
//- Copy assignment.
// For existing list entries, values are copied from the list.
// For new list entries, pointers are cloned from the list.
template<bool CheckSelf>
void copyPtrList(const UPtrList<T>& list);
protected:
// Protected Member Functions
@ -103,7 +112,7 @@ public:
inline PtrList(const PtrList<T>& list, const CloneArg& cloneArgs);
//- Construct as copy or re-use as specified
PtrList(PtrList<T>& list, bool reuse);
inline PtrList(PtrList<T>& list, bool reuse);
//- Copy construct using 'clone()' on each element of SLPtrList\<T\>
explicit PtrList(const SLPtrList<T>& list);
@ -221,6 +230,11 @@ public:
// Member Operators
//- Copy assignment.
// For existing list entries, values are copied from the list.
// For new list entries, pointers are cloned from the list.
void operator=(const UPtrList<T>& list);
//- Copy assignment.
// For existing list entries, values are copied from the list.
// For new list entries, pointers are cloned from the list.

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2018-2023 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -60,6 +60,23 @@ inline Foam::PtrList<T>::PtrList(PtrList<T>&& list) noexcept
{}
template<class T>
inline Foam::PtrList<T>::PtrList(PtrList<T>& list, bool reuse)
:
UPtrList<T>()
{
if (reuse)
{
transfer(list);
}
else
{
// No check for self-assignment
copyPtrList<false>(list);
}
}
template<class T>
inline Foam::PtrList<T>::PtrList(UList<T*>& list)
:
@ -278,7 +295,7 @@ inline Foam::autoPtr<T> Foam::PtrList<T>::release(const label i)
template<class T>
inline void Foam::PtrList<T>::transfer(PtrList<T>& list)
{
if (this == &list)
if (FOAM_UNLIKELY(this == &list))
{
return; // Self-assignment is a no-op
}
@ -290,6 +307,22 @@ inline void Foam::PtrList<T>::transfer(PtrList<T>& list)
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
template<class T>
inline void Foam::PtrList<T>::operator=(const UPtrList<T>& list)
{
// With check for self-assignment
this->copyPtrList<true>(list);
}
template<class T>
inline void Foam::PtrList<T>::operator=(const PtrList<T>& list)
{
// With check for self-assignment
this->copyPtrList<true>(list);
}
template<class T>
inline void Foam::PtrList<T>::operator=(PtrList<T>&& list)
{

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -99,11 +99,10 @@ Foam::label Foam::Detail::PtrListDetail<T>::find_next_not(label pos) const
template<class T>
void Foam::Detail::PtrListDetail<T>::free()
{
List<T*>& ptrs = *this;
const label len = ptrs.size();
// Presume they were allocated from front to back...
for (label i = len - 1; i >= 0; --i)
List<T*>& ptrs = *this;
for (auto i = this->size()-1; i >= 0; --i)
{
delete ptrs[i];
ptrs[i] = nullptr;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -147,6 +147,10 @@ public:
// Use with care
inline void setAddressableSize(const label n) noexcept;
//- Write pointer values to Ostream (debugging only).
// Optionally allow addressing beyond the regular range
Ostream& printAddresses(Ostream& os, label maxLen = -1) const;
//- Write output, optionally silently trimming nullptrs
Ostream& write(Ostream& os, const bool trimNull=false) const;

View File

@ -5,7 +5,7 @@
\\ / A nd | www.openfoam.com
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2018-2024 OpenCFD Ltd.
Copyright (C) 2018-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -31,6 +31,45 @@ License
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T>
Foam::Ostream& Foam::Detail::PtrListDetail<T>::printAddresses
(
Ostream& os,
label maxLen
) const
{
if (maxLen <= 0)
{
maxLen = this->size();
}
const label len = Foam::min(this->size(), maxLen);
// The (output) size and start delimiter
os << nl << indent << maxLen << nl
<< indent << token::BEGIN_LIST << nl;
// const T* const * iter = this->cdata();
const auto* iter = this->cdata();
// Contents
for (label i = 0; i < len; ++i)
{
os << indent << " " << Foam::name(iter[i]) << nl;
}
for (label i = len; i < maxLen; ++i)
{
os << indent << " [" << Foam::name(iter[i]) << ']' << nl;
}
// End delimiter
os << indent << token::END_LIST << nl;
os.check(FUNCTION_NAME);
return os;
}
template<class T>
Foam::Ostream& Foam::Detail::PtrListDetail<T>::write
(

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2011-2016 OpenFOAM Foundation
Copyright (C) 2015-2022 OpenCFD Ltd.
Copyright (C) 2015-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -65,23 +65,6 @@ Foam::label Foam::UPtrList<T>::squeezeNull()
}
template<class T>
void Foam::UPtrList<T>::trimTrailingNull()
{
label newLen = this->size();
for (label i = newLen-1; i >= 0 && !ptrs_[i]; --i)
{
--newLen;
}
// Or mutable?
// const_cast<Detail::PtrListDetail<T>&>(ptrs_).setAddressableSize(newLen);
ptrs_.setAddressableSize(newLen);
}
template<class T>
void Foam::UPtrList<T>::reorder(const labelUList& oldToNew, const bool check)
{
@ -98,7 +81,7 @@ void Foam::UPtrList<T>::reorder(const labelUList& oldToNew, const bool check)
Detail::PtrListDetail<T> newList(len);
for (label i=0; i<len; ++i)
for (label i = 0; i < len; ++i)
{
const label newIdx = oldToNew[i];
@ -127,7 +110,8 @@ void Foam::UPtrList<T>::reorder(const labelUList& oldToNew, const bool check)
newList.checkNonNull();
}
ptrs_.transfer(newList);
// Copy the pointers, do not swap or transfer lists!
ptrs_ = newList;
}
@ -148,7 +132,7 @@ void Foam::UPtrList<T>::sortOrder(const labelUList& order, const bool check)
Detail::PtrListDetail<T> newList(len);
Detail::PtrListDetail<T> guard(len);
for (label i=0; i<len; ++i)
for (label i = 0; i < len; ++i)
{
const label oldIdx = order[i];
@ -179,16 +163,35 @@ void Foam::UPtrList<T>::sortOrder(const labelUList& order, const bool check)
newList.checkNonNull();
}
ptrs_.transfer(newList);
// Copy the pointers, do not swap or transfer lists!
ptrs_ = newList;
}
// * * * * * * * * * * * * * * * Ostream Operators * * * * * * * * * * * * * //
template<class T>
Foam::Ostream& Foam::UPtrList<T>::printAddresses(Ostream& os) const
{
return ptrs_.printAddresses(os);
}
template<class T>
Foam::Ostream& Foam::UPtrList<T>::writeList
(
Ostream& os,
const bool trimNull
) const
{
return ptrs_.write(os, trimNull);
}
template<class T>
Foam::Ostream& Foam::operator<<(Ostream& os, const UPtrList<T>& list)
{
return list.ptrs_.write(os);
return list.writeList(os, false); // Do not ignore null
}

View File

@ -314,10 +314,6 @@ public:
// \return the number of non-null entries
label squeezeNull();
//- Reduce addressable list size to ignore any trailing null pointers.
// The reduces the effective list length without reallocation
void trimTrailingNull();
//- Append an element to the end of the list
inline void push_back(T* ptr);
@ -382,9 +378,18 @@ public:
inline void operator=(UPtrList<T>&& list);
// Writing
//- Print pointer addresses to Ostream (debugging only)
Ostream& printAddresses(Ostream& os) const;
//- Write UPtrList to Ostream, optionally ignoring null entries
Ostream& writeList(Ostream& os, const bool trimNull=false) const;
// IOstream Operators
//- Write UPtrList to Ostream
//- Write UPtrList to Ostream. Does not ignore null entries
friend Ostream& operator<< <T>(Ostream& os, const UPtrList<T>& list);

View File

@ -537,14 +537,15 @@ public:
//- True if headerClassName() is non-empty (after reading)
inline bool hasHeaderClass() const noexcept;
//- Check if headerClassName() equals the expected type.
//- Always true if the expected type is empty.
inline bool isHeaderClass(const word& expectedType) const;
//- Check if headerClassName() equals Type::typeName
//- Always true for a \c void type.
template<class Type>
inline bool isHeaderClass() const;
//- Same as isHeaderClass()
template<class Type>
bool isHeaderClassName() const { return isHeaderClass<Type>(); }
// Meta-data
@ -611,20 +612,18 @@ public:
fileName objectRelPath() const;
//- Redirect to fileHandler filePath, searching locally.
// When search is false, simply use the current instance,
// otherwise search previous instances.
fileName localFilePath
(
const word& typeName,
//! False: use current instance; True: search previous instances
const bool search=true
) const;
//- Redirect to fileHandler filePath, searching up if in parallel.
// When search is false, simply use the current instance,
// otherwise search previous instances.
fileName globalFilePath
(
const word& typeName,
//! False: use current instance; True: search previous instances
const bool search=true
) const;
@ -645,17 +644,29 @@ public:
bool readHeader(dictionary& headerDict, Istream& is);
//- Read header (respects is_globalIOobject trait) and check its info.
//- A \c void type suppresses trait and type-name checks.
template<class Type>
bool typeHeaderOk
(
//! Check headerClassName against the type-name
const bool checkType = true,
[[maybe_unused]] const bool checkType = true,
//! Also search previous instances if not found at current instance
const bool search = true,
//! Report any check-type failures
const bool verbose = true
);
//- Forwards to single-parameter version with the specified search type.
//- A \c void type suppresses trait and type-name checks.
template<class Type, bool Searching>
bool typeHeaderOk
(
//! Check headerClassName against the type-name
const bool checkType = true,
//! Report any check-type failures
const bool verbose = true
);
//- Call localFilePath or globalFilePath for given type
//- depending on its is_globalIOobject trait.
template<class Type>
@ -718,19 +729,16 @@ public:
//- Copy assignment, copies all values (except the registry)
void operator=(const IOobject& io);
// Housekeeping
//- Same as isHeaderClass()
template<class Type>
bool isHeaderClassName() const { return isHeaderClass<Type>(); }
};
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
//- Specialization for \c void always returns true (no headerClassName check).
template<>
inline bool IOobject::isHeaderClass<void>() const
{
return true;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
} // End namespace Foam

View File

@ -261,10 +261,23 @@ inline bool Foam::IOobject::hasHeaderClass() const noexcept
}
inline bool Foam::IOobject::isHeaderClass(const word& expectedType) const
{
return (expectedType.empty() || (expectedType == headerClassName_));
}
template<class Type>
inline bool Foam::IOobject::isHeaderClass() const
{
if constexpr (std::is_void_v<Type>)
{
return true;
}
else
{
return (Type::typeName == headerClassName_);
}
}

View File

@ -215,17 +215,13 @@ bool Foam::IOobject::readAndCheckHeader
ok = handler.readHeader(*this, fName, typeName);
UPstream::parRun(oldParRun);
if
(
ok && checkType
&& !typeName.empty() && headerClassName_ != typeName
)
if (ok && checkType && !isHeaderClass(typeName))
{
ok = false;
if (verbose)
{
WarningInFunction
<< "Unexpected class name \"" << headerClassName_
<< "Unexpected class name \"" << headerClassName()
<< "\" expected \"" << typeName
<< "\" when reading " << fName << endl;
}
@ -251,17 +247,13 @@ bool Foam::IOobject::readAndCheckHeader
);
ok = handler.readHeader(*this, fName, typeName);
if
(
ok && checkType
&& !typeName.empty() && headerClassName_ != typeName
)
if (ok && checkType && !isHeaderClass(typeName))
{
ok = false;
if (verbose)
{
WarningInFunction
<< "Unexpected class name \"" << headerClassName_
<< "Unexpected class name \"" << headerClassName()
<< "\" expected \"" << typeName
<< "\" when reading " << fName << endl;
}

View File

@ -42,6 +42,19 @@ bool Foam::IOobject::typeHeaderOk
const bool verbose
)
{
if constexpr (std::is_void_v<Type>)
{
return readAndCheckHeader
(
false, // isGlobal (false)
word::null, // typeName (n/a)
false, // checkType (false)
search,
verbose
);
}
else
{
return readAndCheckHeader
(
is_globalIOobject<Type>::value,
@ -50,6 +63,14 @@ bool Foam::IOobject::typeHeaderOk
search,
verbose
);
}
}
template<class Type, bool Searching>
bool Foam::IOobject::typeHeaderOk(const bool checkType, const bool verbose)
{
return typeHeaderOk<Type>(checkType, Searching, verbose);
}

View File

@ -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)
template<class T>
bool Foam::CompactIOField<T>::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();
// no-op
}
else if (headerClassName() == typeName)
else if (isHeaderClass(typeName))
{
is >> *this;
close();
// 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 " << IOField<T>::typeName << nl
<< " or " << plain_type::typeName << nl
<< " while reading object " << name()
<< exit(FatalIOError);
}
}
close();
return true;
}
@ -69,10 +71,100 @@ bool Foam::CompactIOField<T, BaseType>::readIOcontents(bool readOnProc)
}
template<class T>
Foam::label Foam::CompactIOField<T>::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>
bool Foam::CompactIOField<T>::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>
Foam::CompactIOField<T, BaseType>::CompactIOField(const IOobject& io)
template<class T>
Foam::CompactIOField<T>::CompactIOField(const IOobject& io)
:
regIOobject(io)
{
@ -80,8 +172,8 @@ Foam::CompactIOField<T, BaseType>::CompactIOField(const IOobject& io)
}
template<class T, class BaseType>
Foam::CompactIOField<T, BaseType>::CompactIOField
template<class T>
Foam::CompactIOField<T>::CompactIOField
(
const IOobject& io,
const bool readOnProc
@ -93,8 +185,8 @@ Foam::CompactIOField<T, BaseType>::CompactIOField
}
template<class T, class BaseType>
Foam::CompactIOField<T, BaseType>::CompactIOField
template<class T>
Foam::CompactIOField<T>::CompactIOField
(
const IOobject& io,
Foam::zero
@ -106,8 +198,8 @@ Foam::CompactIOField<T, BaseType>::CompactIOField
}
template<class T, class BaseType>
Foam::CompactIOField<T, BaseType>::CompactIOField
template<class T>
Foam::CompactIOField<T>::CompactIOField
(
const IOobject& io,
const label len
@ -122,8 +214,8 @@ Foam::CompactIOField<T, BaseType>::CompactIOField
}
template<class T, class BaseType>
Foam::CompactIOField<T, BaseType>::CompactIOField
template<class T>
Foam::CompactIOField<T>::CompactIOField
(
const IOobject& io,
const UList<T>& content
@ -138,8 +230,8 @@ Foam::CompactIOField<T, BaseType>::CompactIOField
}
template<class T, class BaseType>
Foam::CompactIOField<T, BaseType>::CompactIOField
template<class T>
Foam::CompactIOField<T>::CompactIOField
(
const IOobject& io,
Field<T>&& content
@ -153,16 +245,69 @@ Foam::CompactIOField<T, BaseType>::CompactIOField
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
Foam::label Foam::CompactIOField<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);
CompactIOField<T> reader(rio);
reader.readOpt(rOpt);
return reader.readIOsize();
}
template<class T>
Foam::Field<T> Foam::CompactIOField<T>::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> reader(rio);
return Field<T>(std::move(static_cast<Field<T>&>(reader)));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class BaseType>
bool Foam::CompactIOField<T, BaseType>::writeObject
template<class T>
bool Foam::CompactIOField<T>::writeObject
(
IOstreamOption streamOpt,
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);
@ -181,99 +326,136 @@ bool Foam::CompactIOField<T, BaseType>::writeObject
}
template<class T, class BaseType>
bool Foam::CompactIOField<T, BaseType>::writeData(Ostream& os) const
template<class T>
bool Foam::CompactIOField<T>::writeData(Ostream& os) const
{
return (os << *this).good();
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T, class BaseType>
void Foam::CompactIOField<T, BaseType>::operator=
(
const CompactIOField<T, BaseType>& rhs
)
template<class T>
Foam::Istream& Foam::CompactIOField<T>::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]);
Field<T>::operator=(rhs);
}
list.resize_nocopy(count);
std::move(iter, iter + count, list.begin());
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
template<class T, class BaseType>
Foam::Istream& Foam::operator>>
(
Foam::Istream& is,
Foam::CompactIOField<T, BaseType>& L
)
{
// 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++];
}
iter += count;
}
return is;
}
template<class T, class BaseType>
template<class T>
Foam::Ostream& Foam::CompactIOField<T>::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;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
template<class T>
Foam::Istream& Foam::operator>>
(
Foam::Istream& is,
Foam::CompactIOField<T>& lists
)
{
return lists.readCompact(is);
}
template<class T>
Foam::Ostream& Foam::operator<<
(
Foam::Ostream& os,
const Foam::CompactIOField<T, BaseType>& L
const Foam::CompactIOField<T>& 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;

View File

@ -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.
@ -50,25 +50,16 @@ namespace Foam
{
// Forward Declarations
template<class T, class BaseType> class CompactIOField;
template<class T> class CompactIOField;
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> Istream& operator>>(Istream&, CompactIOField<T>&);
template<class T> Ostream& operator<<(Ostream&, const CompactIOField<T>&);
/*---------------------------------------------------------------------------*\
Class CompactIOField Declaration
\*---------------------------------------------------------------------------*/
template<class T, class BaseType>
template<class T>
class CompactIOField
:
public regIOobject,
@ -81,8 +72,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 +93,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 +112,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>& rhs)
{
Field<T>::operator=(rhs);
}
//- Move assignment of entries
void operator=(CompactIOField<T>&& rhs)
{
Field<T>::operator=(std::move(static_cast<Field<T>&>(rhs)));
}
};

View File

@ -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()
template<class T>
bool Foam::CompactIOList<T>::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,29 +67,93 @@ bool Foam::CompactIOList<T, BaseType>::readIOcontents()
}
template<class T, class BaseType>
bool Foam::CompactIOList<T, BaseType>::overflows() const
template<class T>
Foam::label Foam::CompactIOList<T>::readIOsize()
{
const List<T>& lists = *this;
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>
bool Foam::CompactIOList<T>::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)
for (const auto& list : lists)
{
const label prev = total;
total += sublist.size();
total += list.size();
if (total < prev)
{
return true;
}
}
}
return false;
}
// * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
template<class T, class BaseType>
Foam::CompactIOList<T, BaseType>::CompactIOList(const IOobject& io)
template<class T>
Foam::CompactIOList<T>::CompactIOList(const IOobject& io)
:
regIOobject(io)
{
@ -99,8 +161,8 @@ Foam::CompactIOList<T, BaseType>::CompactIOList(const IOobject& io)
}
template<class T, class BaseType>
Foam::CompactIOList<T, BaseType>::CompactIOList
template<class T>
Foam::CompactIOList<T>::CompactIOList
(
const IOobject& io,
Foam::zero
@ -112,8 +174,8 @@ Foam::CompactIOList<T, BaseType>::CompactIOList
}
template<class T, class BaseType>
Foam::CompactIOList<T, BaseType>::CompactIOList
template<class T>
Foam::CompactIOList<T>::CompactIOList
(
const IOobject& io,
const label len
@ -128,8 +190,8 @@ Foam::CompactIOList<T, BaseType>::CompactIOList
}
template<class T, class BaseType>
Foam::CompactIOList<T, BaseType>::CompactIOList
template<class T>
Foam::CompactIOList<T>::CompactIOList
(
const IOobject& io,
const UList<T>& content
@ -144,8 +206,8 @@ Foam::CompactIOList<T, BaseType>::CompactIOList
}
template<class T, class BaseType>
Foam::CompactIOList<T, BaseType>::CompactIOList
template<class T>
Foam::CompactIOList<T>::CompactIOList
(
const IOobject& io,
List<T>&& content
@ -159,10 +221,48 @@ Foam::CompactIOList<T, BaseType>::CompactIOList
}
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
template<class T>
Foam::label Foam::CompactIOList<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);
CompactIOList<T> reader(rio);
reader.readOpt(rOpt);
return reader.readIOsize();
}
template<class T>
Foam::List<T> Foam::CompactIOList<T>::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> reader(rio);
return List<T>(std::move(static_cast<List<T>&>(reader)));
}
// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
template<class T, class BaseType>
bool Foam::CompactIOList<T, BaseType>::writeObject
template<class T>
bool Foam::CompactIOList<T>::writeObject
(
IOstreamOption streamOpt,
const bool writeOnProc
@ -177,12 +277,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);
@ -201,105 +302,136 @@ bool Foam::CompactIOList<T, BaseType>::writeObject
}
template<class T, class BaseType>
bool Foam::CompactIOList<T, BaseType>::writeData(Ostream& os) const
template<class T>
bool Foam::CompactIOList<T>::writeData(Ostream& os) const
{
return (os << *this).good();
}
// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
template<class T, class BaseType>
void Foam::CompactIOList<T, BaseType>::operator=
(
const CompactIOList<T, BaseType>& rhs
)
template<class T>
Foam::Istream& Foam::CompactIOList<T>::readCompact(Istream& is)
{
List<T>::operator=(rhs);
}
List<T>& lists = *this;
// The base type for packed values
typedef typename T::value_type base_type;
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
// Read compact: offsets + packed values
const labelList offsets(is);
List<base_type> values(is);
template<class T, class BaseType>
Foam::Istream& Foam::operator>>
(
Foam::Istream& is,
Foam::CompactIOList<T, BaseType>& L
)
{
// Read compact
const labelList start(is);
const List<BaseType> elems(is);
// Transcribe
const label len = Foam::max(0, (offsets.size()-1));
lists.resize_nocopy(len);
// Convert
L.setSize(start.size()-1);
auto iter = values.begin();
forAll(L, i)
for (label i = 0; i < len; ++i)
{
T& subList = L[i];
auto& list = lists[i];
const label count = (offsets[i+1] - offsets[i]);
label index = start[i];
subList.setSize(start[i+1] - index);
list.resize_nocopy(count);
forAll(subList, j)
{
subList[j] = elems[index++];
}
std::move(iter, iter + count, list.begin());
iter += count;
}
return is;
}
template<class T, class BaseType>
Foam::Ostream& Foam::operator<<
(
Foam::Ostream& os,
const Foam::CompactIOList<T, BaseType>& L
)
template<class T>
Foam::Ostream& Foam::CompactIOList<T>::writeCompact(Ostream& os) const
{
// Keep ASCII writing same
if (os.format() == IOstreamOption::ASCII)
{
os << static_cast<const List<T>&>(L);
}
else
{
const List<T>& lists = *this;
// The base type for packed values
typedef typename T::value_type base_type;
// Convert to compact format
labelList start(L.size()+1);
label total = 0;
const label len = lists.size();
start[0] = 0;
for (label i = 1; i < start.size(); i++)
// offsets
{
const label prev = start[i-1];
start[i] = prev+L[i-1].size();
labelList offsets(len+1);
if (start[i] < prev)
for (label i = 0; i < len; ++i)
{
offsets[i] = total;
total += lists[i].size();
if (total < offsets[i])
{
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"
<< "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);
}
}
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];
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 << start << elems;
os << values;
}
return os;
}
// * * * * * * * * * * * * * * * Friend Operators * * * * * * * * * * * * * //
template<class T>
Foam::Istream& Foam::operator>>
(
Foam::Istream& is,
Foam::CompactIOList<T>& lists
)
{
return lists.readCompact(is);
}
template<class T>
Foam::Ostream& Foam::operator<<
(
Foam::Ostream& os,
const Foam::CompactIOList<T>& lists
)
{
// Keep ASCII writing same
if (os.format() != IOstreamOption::BINARY)
{
os << static_cast<const List<T>&>(lists);
}
else
{
lists.writeCompact(os);
}
return os;

View File

@ -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.
@ -50,24 +50,16 @@ namespace Foam
{
// Forward Declarations
template<class T, class BaseType> class CompactIOList;
template<class T> 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> Istream& operator>>(Istream&, CompactIOList<T>&);
template<class T> Ostream& operator<<(Ostream&, const CompactIOList<T>&);
/*---------------------------------------------------------------------------*\
Class CompactIOList Declaration
\*---------------------------------------------------------------------------*/
template<class T, class BaseType>
template<class T>
class CompactIOList
:
public regIOobject,
@ -80,6 +72,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 +94,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 +110,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 +139,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>& rhs)
{
List<T>::operator=(rhs);
}
//- Move assignment of entries
void operator=(CompactIOList<T>&& 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.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);
}
// ************************************************************************* //

View File

@ -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)));
}
};

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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)));
}
};

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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)));
}
};

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 * * * * * * * * * * * * * * * //
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);
}
// ************************************************************************* //

View File

@ -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)));
}
};

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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)));
}
};

View File

@ -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);
}
// ************************************************************************* //

View File

@ -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)));
}
};

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
//- 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)));
}
};

View File

@ -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);

View File

@ -6,7 +6,7 @@
\\/ M anipulation |
-------------------------------------------------------------------------------
Copyright (C) 2017 OpenFOAM Foundation
Copyright (C) 2019-2023 OpenCFD Ltd.
Copyright (C) 2019-2025 OpenCFD Ltd.
-------------------------------------------------------------------------------
License
This file is part of OpenFOAM.
@ -32,7 +32,7 @@ Description
taking an Istream or ISstream. Aborts at any attempt to read from it.
Note
The inheritance from an empty IStringStream is solely for convenience
The inheritance from an empty ICharStream is solely for convenience
of implementation and should not be relied upon.
SourceFiles
@ -43,7 +43,8 @@ SourceFiles
#ifndef Foam_dummyISstream_H
#define Foam_dummyISstream_H
#include "StringStream.H"
#include "autoPtr.H"
#include "SpanStream.H"
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
@ -56,7 +57,7 @@ namespace Foam
class dummyISstream
:
public IStringStream
public ICharStream
{
public:
@ -69,6 +70,15 @@ public:
virtual ~dummyISstream() = default;
// Factory Methods
//- Return a dummyISstream
static autoPtr<ISstream> New()
{
return autoPtr<ISstream>(new dummyISstream());
}
// Member Functions
// Stream-state

View File

@ -269,7 +269,7 @@ public:
// Edit
//- Swap with plain List content. Implies shrink_to_fit().
inline void swap(List<T>& list);
inline void swap(List<T>& other);
//- Swap content, independent of sizing parameter
template<int AnySizeMin>

View File

@ -567,12 +567,12 @@ inline void Foam::DynamicField<T, SizeMin>::shrink_to_fit()
template<class T, int SizeMin>
inline void
Foam::DynamicField<T, SizeMin>::swap(List<T>& list)
Foam::DynamicField<T, SizeMin>::swap(List<T>& other)
{
if
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
== static_cast<const List<T>*>(&other)
)
{
return; // Self-swap is a no-op
@ -582,7 +582,7 @@ Foam::DynamicField<T, SizeMin>::swap(List<T>& list)
this->shrink_to_fit();
// Swap storage and addressable size
UList<T>::swap(list);
UList<T>::swap(other);
// Update capacity
capacity_ = List<T>::size();
@ -658,17 +658,22 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
{
if
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
FOAM_UNLIKELY
(
static_cast<const UList<T>*>(this)
== static_cast<const UList<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
// Take over storage as-is (without shrink)
capacity_ = list.capacity();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
Field<T>::transfer(static_cast<List<T>&>(list));
list.clearStorage(); // capacity=0 etc.
capacity_ = list.capacity();
list.setCapacity_unsafe(0); // All contents moved
}
@ -681,17 +686,22 @@ inline void Foam::DynamicField<T, SizeMin>::transfer
{
if
(
static_cast<const List<T>*>(this)
== static_cast<const List<T>*>(&list)
FOAM_UNLIKELY
(
static_cast<const UList<T>*>(this)
== static_cast<const UList<T>*>(&list)
)
)
{
return; // Self-assignment is a no-op
}
// Take over storage as-is (without shrink)
capacity_ = list.capacity();
// Consistent allocated sizing
List<T>::setAddressableSize(capacity_);
Field<T>::transfer(static_cast<List<T>&>(list));
list.clearStorage(); // capacity=0 etc.
capacity_ = list.capacity();
list.setCapacity_unsafe(0); // All contents moved
}
@ -744,7 +754,14 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
const UList<T>& list
)
{
if (this == &list)
if
(
FOAM_UNLIKELY
(
static_cast<const UList<T>*>(this)
== static_cast<const UList<T>*>(&list)
)
)
{
FatalErrorInFunction
<< "Attempted push_back to self"
@ -764,7 +781,14 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
List<T>&& list
)
{
if (this == &list)
if
(
FOAM_UNLIKELY
(
static_cast<const UList<T>*>(this)
== static_cast<const UList<T>*>(&list)
)
)
{
FatalErrorInFunction
<< "Attempted push_back to self"
@ -774,6 +798,7 @@ inline void Foam::DynamicField<T, SizeMin>::push_back
const label idx = List<T>::size();
resize(idx + list.size());
// Move the elements
std::move(list.begin(), list.end(), this->begin(idx));
list.clear();
@ -880,7 +905,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
List<T>&& list
)
{
transfer(list);
this->transfer(list);
}
@ -890,7 +915,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
DynamicField<T, SizeMin>&& list
)
{
transfer(list);
this->transfer(list);
}
@ -901,7 +926,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
DynamicField<T, AnySizeMin>&& list
)
{
transfer(list);
this->transfer(list);
}
@ -912,7 +937,7 @@ inline void Foam::DynamicField<T, SizeMin>::operator=
DynamicList<T, AnySizeMin>&& list
)
{
transfer(list);
this->transfer(list);
}

View File

@ -39,8 +39,7 @@ namespace Foam
typedef IOField<diagTensorField> diagTensorFieldIOField;
//! Compact IO for a Field of diagTensorField
typedef CompactIOField<diagTensorField, diagTensor>
diagTensorFieldCompactIOField;
typedef CompactIOField<diagTensorField> diagTensorFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -40,7 +40,7 @@ namespace Foam
typedef IOField<labelField> labelFieldIOField;
//! Compact IO for a Field of labelField
typedef CompactIOField<labelField, label> labelFieldCompactIOField;
typedef CompactIOField<labelField> labelFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOField<scalarField> scalarFieldIOField;
//! Compact IO for a Field of scalarField
typedef CompactIOField<scalarField, scalar> scalarFieldCompactIOField;
typedef CompactIOField<scalarField> scalarFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOField<sphericalTensorField> sphericalTensorFieldIOField;
//! Compact IO for a Field of sphericalTensorField
typedef CompactIOField<sphericalTensorField, sphericalTensor>
typedef CompactIOField<sphericalTensorField>
sphericalTensorFieldCompactIOField;
}

View File

@ -39,8 +39,7 @@ namespace Foam
typedef IOField<symmTensorField> symmTensorFieldIOField;
//! Compact IO for a Field of symmTensorField
typedef CompactIOField<symmTensorField, symmTensor>
symmTensorFieldCompactIOField;
typedef CompactIOField<symmTensorField> symmTensorFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOField<tensorField> tensorFieldIOField;
//! Compact IO for a Field of tensorField
typedef CompactIOField<tensorField, tensor> tensorFieldCompactIOField;
typedef CompactIOField<tensorField> tensorFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOField<vector2DField> vector2DFieldIOField;
//! Compact IO for a Field of vector2DField
typedef CompactIOField<vector2DField, vector2D> vector2DFieldCompactIOField;
typedef CompactIOField<vector2DField> vector2DFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOField<vectorField> vectorFieldIOField;
//! Compact IO for a Field of vectorField
typedef CompactIOField<vectorField, vector> vectorFieldCompactIOField;
typedef CompactIOField<vectorField> vectorFieldCompactIOField;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -147,7 +147,7 @@ public:
virtual fileName objectPath
(
const IOobject& io,
const word& typeName
const word& typeName //!< currently unused
) const;
//- Writes a regIOobject (so header, contents and divider).

View File

@ -327,7 +327,7 @@ Foam::fileOperations::dummyFileOperation::readStream
) const
{
NotImplemented;
return autoPtr<ISstream>(new dummyISstream());
return dummyISstream::New();
}
@ -351,7 +351,7 @@ Foam::fileOperations::dummyFileOperation::NewIFstream
) const
{
NotImplemented;
return autoPtr<ISstream>(new dummyISstream());
return dummyISstream::New();
}

View File

@ -203,18 +203,21 @@ public:
// (reg)IOobject functionality
//- Search for an object. checkGlobal
//- Search for an object
virtual fileName filePath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
//! The wanted object typeName [optional, likely unused]
const word& typeName,
const bool search
) const;
//- Search for a directory. checkGlobal
//- Search for a directory
virtual fileName dirPath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
const bool search
@ -234,7 +237,7 @@ public:
(
IOobject&,
const fileName&,
const word& typeName
const word& typeName //!< currently unused
) const;
//- Reads header for regIOobject and returns an ISstream
@ -243,7 +246,7 @@ public:
(
regIOobject&,
const fileName&,
const word& typeName,
const word& typeName, //!< currently unused
const bool readOnProc = true
) const;
@ -253,7 +256,7 @@ public:
regIOobject&,
const bool masterOnly,
const IOstreamOption::streamFormat format,
const word& typeName
const word& typeName //!< forwards to regIOobject
) const;
//- Generate an ISstream that reads a file

View File

@ -28,7 +28,6 @@ License
#include "fileOperation.H"
#include "objectRegistry.H"
#include "labelIOList.H"
#include "registerSwitch.H"
#include "stringOps.H"
#include "Time.H"
@ -728,7 +727,7 @@ bool Foam::fileOperation::exists(IOobject& io) const
(
isFile(objPath)
// object with local scope
&& io.typeHeaderOk<labelIOList>(false)
&& io.typeHeaderOk<regIOobject>(false)
);
}
@ -750,7 +749,7 @@ bool Foam::fileOperation::exists(IOobject& io) const
(
isFile(originalPath)
// object with local scope
&& io.typeHeaderOk<labelIOList>(false)
&& io.typeHeaderOk<regIOobject>(false)
);
}
}

View File

@ -684,27 +684,28 @@ public:
// (reg)IOobject functionality
//- Generate disk file name for object. Opposite of filePath.
// Optional wanted typeName.
virtual fileName objectPath
(
const IOobject& io,
//! The wanted object typeName [optional, likely unused]
const word& typeName
) const;
//- Search for an object. checkGlobal : also check undecomposed case
// Optional wanted typeName.
//- Search for an object
virtual fileName filePath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject&,
//! The wanted object typeName [optional, likely unused]
const word& typeName,
const bool search = true
) const = 0;
//- Search for a directory. checkGlobal : also check undecomposed
// case
//- Search for a directory
virtual fileName dirPath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
const bool search = true
@ -724,7 +725,7 @@ public:
(
IOobject&,
const fileName&,
const word& typeName
const word& typeName //!< frequently unused?
) const = 0;
//- Reads header for regIOobject and returns an ISstream
@ -733,7 +734,7 @@ public:
(
regIOobject&,
const fileName&,
const word& typeName,
const word& typeName, //!< frequently unused?
const bool readOnProc = true
) const = 0;
@ -742,7 +743,9 @@ public:
(
regIOobject&,
const bool masterOnly,
//! The format for parallel send/recv
const IOstreamOption::streamFormat format,
//! forwards to regIOobject
const word& typeName
) const = 0;

View File

@ -586,7 +586,7 @@ Foam::fileOperations::masterUncollatedFileOperation::read
}
else
{
isPtr.reset(new dummyISstream());
return dummyISstream::New();
}
}

View File

@ -411,20 +411,20 @@ protected:
//- Search (locally!) for object; return info on how it was found.
// Does not do any parallel communication.
// checkGlobal : also check undecomposed case
// isFile : true:check for file false:check for directory
// searchType : how was found
// processorsDir : name of processor directory
// instance : instance
virtual fileName filePathInfo
(
//! also check undecomposed case
const bool checkGlobal,
//! True (check for file), False (check for directory)
const bool isFile,
const IOobject& io,
const dirIndexList& pDirs,
const bool search,
//! [out] how was found
pathType& searchType,
//! [out] name of processor directory
word& processorsDir,
//! [out] instance
word& instance
) const;
@ -623,19 +623,20 @@ public:
// (reg)IOobject functinality
//- Search for an object. checkGlobal : also check undecomposed case
//- Search for an object
virtual fileName filePath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
const word& typeName,
const word& typeName, //!< currently unused
const bool search
) const;
//- Search for a directory. checkGlobal : also check undecomposed
// case
//- Search for a directory
virtual fileName dirPath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
const bool search
@ -655,7 +656,7 @@ public:
(
IOobject&,
const fileName&,
const word& typeName
const word& typeName //!< currently unused
) const;
//- Reads header for regIOobject and returns an ISstream
@ -664,7 +665,7 @@ public:
(
regIOobject&,
const fileName&,
const word& typeName,
const word& typeName, //!< currently unused
const bool readOnProc = true
) const;
@ -673,7 +674,9 @@ public:
(
regIOobject&,
const bool masterOnly,
//! The format for parallel send/recv
const IOstreamOption::streamFormat format,
//! forwards to regIOobject
const word& typeName
) const;

View File

@ -621,7 +621,7 @@ Foam::fileOperations::uncollatedFileOperation::readStream
{
if (!readOnProc)
{
return autoPtr<ISstream>(new dummyISstream());
return dummyISstream::New();
}
if (fName.empty())

View File

@ -243,19 +243,20 @@ public:
// (reg)IOobject functionality
//- Search for an object. checkGlobal : also check undecomposed case
//- Search for an object
virtual fileName filePath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
const word& typeName,
const word& typeName, //!< currently unused
const bool search
) const;
//- Search for a directory. checkGlobal : also check undecomposed
// case
//- Search for a directory
virtual fileName dirPath
(
//! also check undecomposed case
const bool checkGlobal,
const IOobject& io,
const bool search
@ -275,16 +276,16 @@ public:
(
IOobject&,
const fileName&,
const word& typeName
const word& typeName //!< currently only for debug info
) const;
//- Reads header for regIOobject and returns an ISstream
// to read the contents.
//- to read the contents.
virtual autoPtr<ISstream> readStream
(
regIOobject&,
const fileName&,
const word& typeName,
const word& typeName, //!< currently unused
const bool readOnProc = true
) const;
@ -293,7 +294,9 @@ public:
(
regIOobject&,
const bool masterOnly,
//! The format for parallel send/recv
const IOstreamOption::streamFormat format,
//! forwards to regIOobject
const word& typeName
) const;

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOList<cell> cellIOList;
//! Compact IO for a List of cell
typedef CompactIOList<cell, label> cellCompactIOList;
typedef CompactIOList<cell> cellCompactIOList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOList<edge> edgeIOList;
//! Compact IO for a List of edge
typedef CompactIOList<edge, label> edgeCompactIOList;
typedef CompactIOList<edge> edgeCompactIOList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOList<face> faceIOList;
//! Compact IO for a List of face
typedef CompactIOList<face, label> faceCompactIOList;
typedef CompactIOList<face> faceCompactIOList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -28,8 +28,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef cellZoneMesh_H
#define cellZoneMesh_H
#ifndef Foam_cellZoneMesh_H
#define Foam_cellZoneMesh_H
#include "ZoneMesh.H"
#include "cellZone.H"

View File

@ -27,12 +27,12 @@ Typedef
Foam::cellZoneMesh
Description
A ZoneMesh with the type cellZone
A ZoneMesh with cellZone content on a polyMesh
\*---------------------------------------------------------------------------*/
#ifndef cellZoneMeshFwd_H
#define cellZoneMeshFwd_H
#ifndef Foam_cellZoneMeshFwd_H
#define Foam_cellZoneMeshFwd_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -28,8 +28,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef faceZoneMesh_H
#define faceZoneMesh_H
#ifndef Foam_faceZoneMesh_H
#define Foam_faceZoneMesh_H
#include "ZoneMesh.H"
#include "faceZone.H"

View File

@ -27,12 +27,12 @@ Typedef
Foam::faceZoneMesh
Description
A ZoneMesh with the type faceZone
A ZoneMesh with faceZone content on a polyMesh
\*---------------------------------------------------------------------------*/
#ifndef faceZoneMeshFwd_H
#define faceZoneMeshFwd_H
#ifndef Foam_faceZoneMeshFwd_H
#define Foam_faceZoneMeshFwd_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -28,8 +28,8 @@ Description
\*---------------------------------------------------------------------------*/
#ifndef pointZoneMesh_H
#define pointZoneMesh_H
#ifndef Foam_pointZoneMesh_H
#define Foam_pointZoneMesh_H
#include "ZoneMesh.H"
#include "pointZone.H"

View File

@ -27,12 +27,12 @@ Typedef
Foam::pointZoneMesh
Description
A ZoneMesh with the type pointZone
A ZoneMesh with pointZone content on a polyMesh
\*---------------------------------------------------------------------------*/
#ifndef pointZoneMeshFwd_H
#define pointZoneMeshFwd_H
#ifndef Foam_pointZoneMeshFwd_H
#define Foam_pointZoneMeshFwd_H
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOList<scalarList> scalarListIOList;
//! Compact IO for a List of scalarList
typedef CompactIOList<scalarList, scalar> scalarListCompactIOList;
typedef CompactIOList<scalarList> scalarListCompactIOList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

View File

@ -39,7 +39,7 @@ namespace Foam
typedef IOList<vectorList> vectorListIOList;
//! Compact IO for a List of vectorList
typedef CompactIOList<vectorList, vector> vectorListCompactIOList;
typedef CompactIOList<vectorList> vectorListCompactIOList;
}
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //

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