mirror of
https://develop.openfoam.com/Development/openfoam.git
synced 2025-11-28 03:28:01 +00:00
ENH: eliminate reliance on SLList during reading
- fully implement DynamicList::readList() instead of simply redirecting to List::readList(). This also benefits DynamicField. Leverage DynamicList reading to simplify and improve CircularBuffer reading. - bracket lists are now read chunk-wise instead of using a singly-linked list. For integral and vector-space types (eg, scalar, vector, etc) this avoids intermediate allocations for each element. ENH: add CircularBuffer emplace_front/emplace_back STYLE: isolate to-be-deprecated construct/assign forms - still have construct/assign FixedList from a C-array. This is not really needed, can use std::initializer_list - still have construct/assign List from SLList. Prefer to avoid these in the future. DEFEATURE: remove construct/assign FixedList from SLList - never used DEFEATURE: remove move construct/assign List from SLList - now unused. Retain copy construct/assign from SLList for transition purposes.
This commit is contained in:
@ -92,7 +92,10 @@ int main(int argc, char *argv[])
|
||||
}
|
||||
report(buf1);
|
||||
|
||||
buf1.push_back(identity(5)); report(buf1);
|
||||
buf1.push_back(identity(5));
|
||||
buf1.emplace_front(-1000);
|
||||
buf1.emplace_back(1000);
|
||||
report(buf1);
|
||||
|
||||
buf1.info(Info);
|
||||
Info<< buf1 << nl;
|
||||
|
||||
@ -202,14 +202,31 @@ int main(int argc, char *argv[])
|
||||
Info<< "get<3>: " << list1.get<3>() << nl;
|
||||
// Will not compile: Info<< "get<4>: " << list1.get<4>() << nl;
|
||||
|
||||
label a[4] = {0, 1, 2, 3};
|
||||
FixedList<label, 4> list2(a);
|
||||
// Test deprecated form
|
||||
label array2[4] = {0, 1, 2, 3};
|
||||
FixedList<label, 4> list2(array2);
|
||||
|
||||
Info<< "list2:" << list2
|
||||
<< " hash:" << FixedList<label, 4>::hasher()(list2) << nl
|
||||
<< " hash:" << Hash<FixedList<label, 4>>()(list2) << nl;
|
||||
|
||||
|
||||
// Test deprecated form
|
||||
SLList<label> sllist3;
|
||||
{
|
||||
sllist3.push_back(0);
|
||||
sllist3.push_back(1);
|
||||
sllist3.push_back(2);
|
||||
sllist3.push_back(3);
|
||||
}
|
||||
FixedList<label, 4> list3(sllist3);
|
||||
|
||||
Info<< "list3:" << list3 << nl;
|
||||
// Test deprecated forms
|
||||
list3 = array2;
|
||||
list2 = sllist3;
|
||||
|
||||
|
||||
// Using FixedList for content too
|
||||
{
|
||||
List<FixedList<label, 4>> twolists{list1, list2};
|
||||
|
||||
3
applications/test/ListRead1/Make/files
Normal file
3
applications/test/ListRead1/Make/files
Normal file
@ -0,0 +1,3 @@
|
||||
Test-ListRead1.C
|
||||
|
||||
EXE = $(FOAM_USER_APPBIN)/Test-ListRead1
|
||||
2
applications/test/ListRead1/Make/options
Normal file
2
applications/test/ListRead1/Make/options
Normal file
@ -0,0 +1,2 @@
|
||||
/* EXE_INC = */
|
||||
/* EXE_LIBS = */
|
||||
234
applications/test/ListRead1/Test-ListRead1.C
Normal file
234
applications/test/ListRead1/Test-ListRead1.C
Normal file
@ -0,0 +1,234 @@
|
||||
/*---------------------------------------------------------------------------*\
|
||||
========= |
|
||||
\\ / F ield | OpenFOAM: The Open Source CFD Toolbox
|
||||
\\ / O peration |
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
|
||||
OpenFOAM is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
|
||||
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
Application
|
||||
Test-ListRead1
|
||||
|
||||
Description
|
||||
List reading
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "OSspecific.H"
|
||||
#include "argList.H"
|
||||
#include "wordRes.H"
|
||||
|
||||
#include "IOstreams.H"
|
||||
#include "Fstream.H"
|
||||
#include "StringStream.H"
|
||||
#include "scalar.H"
|
||||
#include "vector.H"
|
||||
|
||||
#include "labelRange.H"
|
||||
#include "scalarList.H"
|
||||
#include "HashOps.H"
|
||||
#include "ListOps.H"
|
||||
#include "IndirectList.H"
|
||||
#include "SubList.H"
|
||||
#include "SliceList.H"
|
||||
#include "ListPolicy.H"
|
||||
|
||||
#include <list>
|
||||
#include <numeric>
|
||||
#include <functional>
|
||||
|
||||
using namespace Foam;
|
||||
|
||||
label chunkSize = 128;
|
||||
|
||||
template<class T>
|
||||
bool readBracketList(List<T>& list, Istream& is)
|
||||
{
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
token tok(is);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"List<T>::readBracketList(Istream&) : reading first token"
|
||||
);
|
||||
|
||||
if (!tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// "(...)" : read element-wise.
|
||||
// Uses chunk-wise reading to avoid too many re-allocations
|
||||
// and avoids relocation of contiguous memory until all of the reading
|
||||
// is completed. Chunks are wrapped as unique_ptr to ensure proper
|
||||
// cleanup on failure.
|
||||
|
||||
// The choice of chunk-size is somewhat arbitrary...
|
||||
// constexpr label chunkSize = 128;
|
||||
typedef std::unique_ptr<List<T>> chunkType;
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
if (tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
// Trivial case, an empty list
|
||||
list.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use all storage
|
||||
//private:// list.resize(list.capacity());
|
||||
|
||||
// Start with a few slots, recover current memory where possible
|
||||
List<chunkType> chunks(16);
|
||||
if (list.empty())
|
||||
{
|
||||
chunks[0] = chunkType(new List<T>(chunkSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
chunks[0] = chunkType(new List<T>(std::move(list)));
|
||||
}
|
||||
|
||||
label nChunks = 1; // Active number of chunks
|
||||
label totalCount = 0; // Total number of elements
|
||||
label localIndex = 0; // Chunk-local index
|
||||
|
||||
InfoErr
|
||||
<< nl << "initial chunk: " << chunks[0]->size() << endl;
|
||||
|
||||
while (!tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
|
||||
if (chunks[nChunks-1]->size() <= localIndex)
|
||||
{
|
||||
// Increase number of slots (doubling)
|
||||
if (nChunks >= chunks.size())
|
||||
{
|
||||
chunks.resize(2*chunks.size());
|
||||
}
|
||||
|
||||
InfoErr<< "new chunk" << endl;
|
||||
chunks[nChunks] = chunkType(new List<T>(chunkSize));
|
||||
++nChunks;
|
||||
localIndex = 0;
|
||||
}
|
||||
|
||||
is >> chunks[nChunks-1]->operator[](localIndex);
|
||||
++localIndex;
|
||||
++totalCount;
|
||||
|
||||
InfoErr
|
||||
<< " chunk=" << nChunks
|
||||
<< " index=" << localIndex
|
||||
<< " total=" << totalCount << nl;
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"List<T>::readBracketList(Istream&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
// Simple case
|
||||
if (nChunks == 1)
|
||||
{
|
||||
list = std::move(*(chunks[0]));
|
||||
list.resize(totalCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Destination
|
||||
//private:// list.setCapacity_nocopy(totalCount);
|
||||
list.resize_nocopy(totalCount);
|
||||
auto dest = list.begin();
|
||||
|
||||
for (label chunki = 0; chunki < nChunks; ++chunki)
|
||||
{
|
||||
List<T> currChunk(std::move(*(chunks[chunki])));
|
||||
chunks[chunki].reset(nullptr);
|
||||
|
||||
const label localLen = min(currChunk.size(), totalCount);
|
||||
|
||||
dest = std::move
|
||||
(
|
||||
currChunk.begin(),
|
||||
currChunk.begin(localLen),
|
||||
dest
|
||||
);
|
||||
|
||||
totalCount -= localLen;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
// Main program:
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
argList::noBanner();
|
||||
argList::noParallel();
|
||||
argList::noFunctionObjects();
|
||||
argList::addOption("chunk-size", "value", "change read chunk size");
|
||||
argList::addArgument("file1 .. fileN");
|
||||
|
||||
argList args(argc, argv, false, true);
|
||||
|
||||
args.readIfPresent("chunk-size", chunkSize);
|
||||
|
||||
Info<< "chunk-size: " << chunkSize << nl;
|
||||
|
||||
if (args.size() <= 1)
|
||||
{
|
||||
InfoErr<< "Provide a file or files to test" << nl;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (label argi=1; argi < args.size(); ++argi)
|
||||
{
|
||||
const auto input = args.get<fileName>(argi);
|
||||
IFstream is(input);
|
||||
|
||||
while (!is.eof())
|
||||
{
|
||||
labelList list;
|
||||
|
||||
readBracketList(list, is);
|
||||
Info<< "read: " << flatOutput(list) << endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// ************************************************************************* //
|
||||
17
applications/test/ListRead1/testLists1
Normal file
17
applications/test/ListRead1/testLists1
Normal file
@ -0,0 +1,17 @@
|
||||
(
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
10 11 12 13 14 15 16 17 18 19
|
||||
20 21 22 23 24 25 26 27 28 29
|
||||
30 31 32 33 34 35 36 37 38 39
|
||||
40 41 42 43 44 45 46 47 48 49
|
||||
)
|
||||
|
||||
(
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
10 11 12 13 14 15 16 17 18 19
|
||||
20 21 22 23 24 25 26 27 28 29
|
||||
30 31 32 33 34 35 36 37 38 39
|
||||
40 41 42 43 44 45 46 47 48 49
|
||||
)
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
@ -303,12 +303,22 @@ public:
|
||||
//- Move prepend an element to the front of the buffer
|
||||
inline void push_front(T&& val);
|
||||
|
||||
//- Construct an element at the front of the buffer,
|
||||
//- return reference to the new element
|
||||
template<class... Args>
|
||||
inline T& emplace_front(Args&&... args);
|
||||
|
||||
//- Copy append an element to the end of the buffer
|
||||
inline void push_back(const T& val);
|
||||
|
||||
//- Move Append an element to the end of the buffer
|
||||
//- Move append an element to the end of the buffer
|
||||
inline void push_back(T&& val);
|
||||
|
||||
//- Construct an element at the end of the buffer,
|
||||
//- return reference to the new element
|
||||
template<class... Args>
|
||||
inline T& emplace_back(Args&&... args);
|
||||
|
||||
//- Shrink by moving the front of the buffer 1 or more times
|
||||
inline void pop_front(label n = 1);
|
||||
|
||||
|
||||
@ -334,6 +334,21 @@ inline void Foam::CircularBuffer<T>::push_front(T&& val)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
template<class... Args>
|
||||
inline T& Foam::CircularBuffer<T>::emplace_front(Args&&... args)
|
||||
{
|
||||
reserve(size() + 2);
|
||||
|
||||
// Never overfilled. Move begin and write
|
||||
|
||||
begin_ = storage_.rcIndex(begin_);
|
||||
storage_[begin_] = T(std::forward<Args>(args)...);
|
||||
|
||||
return storage_[begin_];
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::CircularBuffer<T>::push_back(const T& val)
|
||||
{
|
||||
@ -358,6 +373,22 @@ inline void Foam::CircularBuffer<T>::push_back(T&& val)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
template<class... Args>
|
||||
inline T& Foam::CircularBuffer<T>::emplace_back(Args&&... args)
|
||||
{
|
||||
reserve(size() + 2);
|
||||
|
||||
// Never overfilled, simply write at end_ (one-past position)
|
||||
|
||||
const label backIndex = end_;
|
||||
storage_[end_] = T(std::forward<Args>(args)...);
|
||||
end_ = storage_.fcIndex(end_);
|
||||
|
||||
return storage_[backIndex];
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
inline void Foam::CircularBuffer<T>::pop_front(label n)
|
||||
{
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2022 OpenCFD Ltd.
|
||||
Copyright (C) 2022-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -25,7 +25,7 @@ License
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "List.H"
|
||||
#include "DynamicList.H"
|
||||
#include "Istream.H"
|
||||
#include "contiguous.H"
|
||||
|
||||
@ -46,8 +46,8 @@ Foam::Ostream& Foam::CircularBuffer<T>::info(Ostream& os) const
|
||||
os << "size=" << size() << '/' << capacity()
|
||||
<< " begin=" << begin_
|
||||
<< " end=" << end_
|
||||
/// << " one=" << this->range_one() << this->array_one()
|
||||
/// << " two=" << this->range_two() << this->array_two()
|
||||
// << " one=" << this->range_one() << this->array_one()
|
||||
// << " two=" << this->range_two() << this->array_two()
|
||||
<< nl;
|
||||
|
||||
return os;
|
||||
@ -57,91 +57,27 @@ Foam::Ostream& Foam::CircularBuffer<T>::info(Ostream& os) const
|
||||
template<class T>
|
||||
Foam::Istream& Foam::CircularBuffer<T>::readList(Istream& is)
|
||||
{
|
||||
// Clear list
|
||||
storage_.clear();
|
||||
// Delegate to DynamicList for reading
|
||||
DynamicList<T> elements(std::move(storage_));
|
||||
elements.readList(is);
|
||||
|
||||
// Reset the list addressing range
|
||||
begin_ = 0;
|
||||
end_ = 0;
|
||||
end_ = elements.size();
|
||||
|
||||
// More work than it should be. We avoid completely filled buffers!
|
||||
const label minLen = (end_ + min_size());
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
token tok(is);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"CircularBuffer<T>::readList(Istream&) : "
|
||||
"reading first token"
|
||||
);
|
||||
|
||||
if (tok.isCompound())
|
||||
if (!elements.empty() && (elements.capacity() < minLen))
|
||||
{
|
||||
// Compound: simply transfer contents
|
||||
|
||||
storage_.transfer
|
||||
(
|
||||
dynamicCast<token::Compound<List<T>>>
|
||||
(
|
||||
tok.transferCompoundToken(is)
|
||||
)
|
||||
);
|
||||
|
||||
end_ = storage_.size();
|
||||
if (end_)
|
||||
{
|
||||
// Resize larger to avoid full buffer
|
||||
storage_.resize(end_ + min_size());
|
||||
}
|
||||
// Avoid full buffer (beg/end ambiguity)
|
||||
// Use setCapacity instead of resize to avoid additional doubling...
|
||||
elements.setCapacity(minLen);
|
||||
}
|
||||
else if (tok.isLabel())
|
||||
{
|
||||
// Label: could be int(..), int{...} or just a plain '0'
|
||||
|
||||
const label len = tok.labelToken();
|
||||
// Use the entire storage
|
||||
elements.resize(elements.capacity());
|
||||
|
||||
end_ = len;
|
||||
if (end_)
|
||||
{
|
||||
// Resize larger to avoid full buffer
|
||||
storage_.resize(end_ + min_size());
|
||||
}
|
||||
|
||||
// Dispatch to UList reading...
|
||||
|
||||
UList<T> list(storage_.data(), end_);
|
||||
|
||||
is.putBack(tok);
|
||||
list.readList(is);
|
||||
}
|
||||
else if (tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
// "(...)" : read as SLList and transfer contents
|
||||
|
||||
is.putBack(tok); // Putback the opening bracket
|
||||
SLList<T> sll(is); // Read as singly-linked list
|
||||
|
||||
const label len = sll.size();
|
||||
|
||||
end_ = len;
|
||||
if (end_)
|
||||
{
|
||||
// Resize larger to avoid full buffer
|
||||
storage_.resize(end_ + min_size());
|
||||
|
||||
// Move assign each list element
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
storage_[i] = std::move(sll.removeHead());
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "incorrect first token, expected <int> or '(', found "
|
||||
<< tok.info() << nl
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
storage_ = std::move(elements);
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
@ -105,6 +105,10 @@ class DynamicList
|
||||
// The 'nocopy' option will not attempt to recover old content
|
||||
inline void doResize(const bool nocopy, const label len);
|
||||
|
||||
//- Read List from Istream between '(' and ')' delimiters.
|
||||
//- The size is not known a priori.
|
||||
bool readBracketList(Istream& is);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
@ -5,7 +5,7 @@
|
||||
\\ / A nd | www.openfoam.com
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -28,8 +28,8 @@ License
|
||||
#include "List.H"
|
||||
#include "Istream.H"
|
||||
#include "token.H"
|
||||
#include "SLList.H"
|
||||
#include "contiguous.H"
|
||||
#include <memory>
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
@ -43,6 +43,133 @@ Foam::DynamicList<T, SizeMin>::DynamicList(Istream& is)
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class T, int SizeMin>
|
||||
bool Foam::DynamicList<T, SizeMin>::readBracketList(Istream& is)
|
||||
{
|
||||
DynamicList<T, SizeMin>& list = *this;
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
token tok(is);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"DynamicList<T>::readBracketList(Istream&) : reading first token"
|
||||
);
|
||||
|
||||
if (!tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// "(...)" : read element-wise.
|
||||
// Uses chunk-wise reading to avoid too many re-allocations
|
||||
// and avoids relocation of contiguous memory until all of the reading
|
||||
// is completed. Chunks are wrapped as unique_ptr to ensure proper
|
||||
// cleanup on failure.
|
||||
|
||||
// The choice of chunk-size is somewhat arbitrary...
|
||||
constexpr label chunkSize = 128;
|
||||
typedef std::unique_ptr<List<T>> chunkType;
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
if (tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
// Trivial case, an empty list
|
||||
list.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use all storage
|
||||
list.resize(list.capacity());
|
||||
|
||||
// Start with a few slots, recover current memory where possible
|
||||
List<chunkType> chunks(16);
|
||||
if (list.empty())
|
||||
{
|
||||
chunks[0] = chunkType(new List<T>(chunkSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
chunks[0] = chunkType(new List<T>(std::move(list)));
|
||||
}
|
||||
|
||||
label nChunks = 1; // Active number of chunks
|
||||
label totalCount = 0; // Total number of elements
|
||||
label localIndex = 0; // Chunk-local index
|
||||
|
||||
while (!tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
|
||||
if (chunks[nChunks-1]->size() <= localIndex)
|
||||
{
|
||||
// Increase number of slots (doubling)
|
||||
if (nChunks >= chunks.size())
|
||||
{
|
||||
chunks.resize(2*chunks.size());
|
||||
}
|
||||
|
||||
chunks[nChunks] = chunkType(new List<T>(chunkSize));
|
||||
++nChunks;
|
||||
localIndex = 0;
|
||||
}
|
||||
|
||||
is >> chunks[nChunks-1]->operator[](localIndex);
|
||||
++localIndex;
|
||||
++totalCount;
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"DynamicList<T>::readBracketList(Istream&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
// Simple case
|
||||
if (nChunks == 1)
|
||||
{
|
||||
list = std::move(*(chunks[0]));
|
||||
list.resize(totalCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Destination
|
||||
list.setCapacity_nocopy(totalCount);
|
||||
list.resize_nocopy(totalCount);
|
||||
auto dest = list.begin();
|
||||
|
||||
for (label chunki = 0; chunki < nChunks; ++chunki)
|
||||
{
|
||||
List<T> currChunk(std::move(*(chunks[chunki])));
|
||||
chunks[chunki].reset(nullptr);
|
||||
|
||||
const label localLen = min(currChunk.size(), totalCount);
|
||||
|
||||
dest = std::move
|
||||
(
|
||||
currChunk.begin(),
|
||||
currChunk.begin(localLen),
|
||||
dest
|
||||
);
|
||||
|
||||
totalCount -= localLen;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T, int SizeMin>
|
||||
@ -50,12 +177,136 @@ Foam::Istream& Foam::DynamicList<T, SizeMin>::readList(Istream& is)
|
||||
{
|
||||
DynamicList<T, SizeMin>& list = *this;
|
||||
|
||||
// Needs rewrite (2021-10)
|
||||
// Use entire storage - ie, resize(capacity())
|
||||
(void) list.expandStorage();
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
static_cast<List<T>&>(list).readList(is);
|
||||
list.capacity_ = list.size();
|
||||
token tok(is);
|
||||
|
||||
is.fatalCheck("DynamicList<T>::readList(Istream&) : reading first token");
|
||||
|
||||
if (tok.isCompound())
|
||||
{
|
||||
// Compound: simply transfer contents
|
||||
|
||||
list.clearStorage(); // Remove old contents
|
||||
list.transfer
|
||||
(
|
||||
dynamicCast<token::Compound<List<T>>>
|
||||
(
|
||||
tok.transferCompoundToken(is)
|
||||
)
|
||||
);
|
||||
}
|
||||
else if (tok.isLabel())
|
||||
{
|
||||
// Label: could be int(..), int{...} or just a plain '0'
|
||||
|
||||
const label len = tok.labelToken();
|
||||
|
||||
// Resize to length required
|
||||
list.resize_nocopy(len);
|
||||
|
||||
if (is.format() == IOstreamOption::BINARY && is_contiguous<T>::value)
|
||||
{
|
||||
// Binary and contiguous
|
||||
|
||||
if (len)
|
||||
{
|
||||
Detail::readContiguous<T>
|
||||
(
|
||||
is,
|
||||
list.data_bytes(),
|
||||
list.size_bytes()
|
||||
);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"DynamicList<T>::readList(Istream&) : "
|
||||
"reading binary block"
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Begin of contents marker
|
||||
const char delimiter = is.readBeginList("List");
|
||||
|
||||
if (len)
|
||||
{
|
||||
if (delimiter == token::BEGIN_LIST)
|
||||
{
|
||||
for (label i=0; i<len; ++i)
|
||||
{
|
||||
is >> list[i];
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"DynamicList<T>::readList(Istream&) : "
|
||||
"reading entry"
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Uniform content (delimiter == token::BEGIN_BLOCK)
|
||||
|
||||
T elem;
|
||||
is >> elem;
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"DynamicList<T>::readList(Istream&) : "
|
||||
"reading the single entry"
|
||||
);
|
||||
|
||||
// Fill with the value
|
||||
this->fill_uniform(elem);
|
||||
}
|
||||
}
|
||||
|
||||
// End of contents marker
|
||||
is.readEndList("List");
|
||||
}
|
||||
}
|
||||
else if (tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
// "(...)" : read read as bracketed list
|
||||
|
||||
is.putBack(tok);
|
||||
this->readBracketList(is);
|
||||
|
||||
// Could also simply be done with emplace_back for each element
|
||||
// but prefer the same mechanism as List::readList to avoid
|
||||
// intermediate resizing
|
||||
|
||||
// // list.clear(); // Clear addressing, leave storage intact
|
||||
// //
|
||||
// // is >> tok;
|
||||
// // is.fatalCheck(FUNCTION_NAME);
|
||||
// //
|
||||
// // while (!tok.isPunctuation(token::END_LIST))
|
||||
// // {
|
||||
// // is.putBack(tok);
|
||||
// // is >> list.emplace_back();
|
||||
// //
|
||||
// // is.fatalCheck
|
||||
// // (
|
||||
// // "DynamicList<T>::readList(Istream&) : "
|
||||
// // "reading entry"
|
||||
// // );
|
||||
// //
|
||||
// // is >> tok;
|
||||
// // is.fatalCheck(FUNCTION_NAME);
|
||||
// // }
|
||||
}
|
||||
else
|
||||
{
|
||||
list.clear(); // Clear old contents
|
||||
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "incorrect first token, expected <int> or '(', found "
|
||||
<< tok.info() << nl
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
return is;
|
||||
}
|
||||
|
||||
@ -48,9 +48,9 @@ SourceFiles
|
||||
#include "stdFoam.H"
|
||||
#include "autoPtr.H"
|
||||
#include "Hash.H"
|
||||
#include "SLListFwd.H"
|
||||
#include "ListPolicy.H"
|
||||
|
||||
// <algorithm> already included by stdFoam.H
|
||||
#include <iterator>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
@ -154,9 +154,6 @@ public:
|
||||
//- Construct and initialize all entries to zero
|
||||
inline explicit FixedList(const Foam::zero);
|
||||
|
||||
//- Copy construct from C-array (deprecated)
|
||||
inline explicit FixedList(const T list[N]);
|
||||
|
||||
//- Copy construct
|
||||
inline FixedList(const FixedList<T, N>& list);
|
||||
|
||||
@ -185,9 +182,6 @@ public:
|
||||
const FixedList<label, N>& indices
|
||||
);
|
||||
|
||||
//- Construct from SLList. Runtime size check
|
||||
inline explicit FixedList(const SLList<T>& list);
|
||||
|
||||
//- Construct from Istream
|
||||
explicit FixedList(Istream& is);
|
||||
|
||||
@ -342,15 +336,9 @@ public:
|
||||
//- Return element of constant FixedList
|
||||
inline const T& operator[](const label i) const;
|
||||
|
||||
//- Assignment to array operator. Takes linear time
|
||||
inline void operator=(const T list[N]);
|
||||
|
||||
//- Assignment to UList operator. Takes linear time
|
||||
inline void operator=(const UList<T>& list);
|
||||
|
||||
//- Assignment to SLList operator. Takes linear time
|
||||
inline void operator=(const SLList<T>& list);
|
||||
|
||||
//- Assignment to an initializer list. Takes linear time
|
||||
inline void operator=(std::initializer_list<T> list);
|
||||
|
||||
@ -529,6 +517,14 @@ public:
|
||||
{
|
||||
return this->contains(val, pos);
|
||||
}
|
||||
|
||||
|
||||
//- Deprecated: copy construct from C-array
|
||||
explicit FixedList(const T list[N]) { std::copy_n(list, N, v_); }
|
||||
|
||||
//- Deprecated: assignment from C-array
|
||||
// \deprecated(2023-08) - use other assignment operators
|
||||
void operator=(const T list[N]) { std::copy_n(list, N, v_); }
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -27,8 +27,6 @@ License
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#include "UList.H"
|
||||
#include "SLList.H"
|
||||
// <algorithm> already included by stdFoam.H
|
||||
|
||||
// * * * * * * * * * * * * * Static Member Functions * * * * * * * * * * * * //
|
||||
|
||||
@ -55,16 +53,6 @@ inline Foam::FixedList<T, N>::FixedList(const Foam::zero)
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline Foam::FixedList<T, N>::FixedList(const T list[N])
|
||||
{
|
||||
for (unsigned i=0; i<N; ++i)
|
||||
{
|
||||
v_[i] = list[i];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline Foam::FixedList<T, N>::FixedList(const FixedList<T, N>& list)
|
||||
{
|
||||
@ -140,20 +128,6 @@ inline Foam::FixedList<T, N>::FixedList
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline Foam::FixedList<T, N>::FixedList(const SLList<T>& list)
|
||||
{
|
||||
checkSize(list.size());
|
||||
|
||||
auto iter = list.begin();
|
||||
for (unsigned i=0; i<N; ++i)
|
||||
{
|
||||
v_[i] = *iter;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline Foam::autoPtr<Foam::FixedList<T, N>>
|
||||
Foam::FixedList<T, N>::clone() const
|
||||
@ -444,15 +418,6 @@ inline const T& Foam::FixedList<T, N>::operator[](const label i) const
|
||||
}
|
||||
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline void Foam::FixedList<T, N>::operator=(const T list[N])
|
||||
{
|
||||
for (unsigned i=0; i<N; ++i)
|
||||
{
|
||||
v_[i] = list[i];
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline void Foam::FixedList<T, N>::operator=(const UList<T>& list)
|
||||
{
|
||||
@ -464,18 +429,6 @@ inline void Foam::FixedList<T, N>::operator=(const UList<T>& list)
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline void Foam::FixedList<T, N>::operator=(const SLList<T>& list)
|
||||
{
|
||||
checkSize(list.size());
|
||||
|
||||
auto iter = list.begin();
|
||||
for (unsigned i=0; i<N; ++i)
|
||||
{
|
||||
v_[i] = *iter;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
template<class T, unsigned N>
|
||||
inline void Foam::FixedList<T, N>::operator=(std::initializer_list<T> list)
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2011-2016 OpenFOAM Foundation
|
||||
Copyright (C) 2017-2022 OpenCFD Ltd.
|
||||
Copyright (C) 2017-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -30,7 +30,6 @@ License
|
||||
#include "ListLoopM.H"
|
||||
#include "FixedList.H"
|
||||
#include "PtrList.H"
|
||||
#include "SLList.H"
|
||||
#include "contiguous.H"
|
||||
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
@ -314,13 +313,6 @@ Foam::List<T>::List(const PtrList<T>& list)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::List<T>::List(const SLList<T>& list)
|
||||
:
|
||||
List<T>(list.begin(), list.end(), list.size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T>
|
||||
template<class Addr>
|
||||
Foam::List<T>::List(const IndirectListBase<T, Addr>& list)
|
||||
@ -359,15 +351,6 @@ Foam::List<T>::List(DynamicList<T, SizeMin>&& list)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
Foam::List<T>::List(SLList<T>&& list)
|
||||
:
|
||||
UList<T>()
|
||||
{
|
||||
operator=(std::move(list));
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
@ -463,28 +446,6 @@ void Foam::List<T>::operator=(const List<T>& list)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::List<T>::operator=(const SLList<T>& list)
|
||||
{
|
||||
const label len = list.size();
|
||||
|
||||
reAlloc(len);
|
||||
|
||||
if (len)
|
||||
{
|
||||
// std::copy(list.begin(), list.end(), this->v_);
|
||||
|
||||
T* iter = this->begin();
|
||||
|
||||
for (const T& val : list)
|
||||
{
|
||||
*iter = val;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
template<unsigned N>
|
||||
void Foam::List<T>::operator=(const FixedList<T, N>& list)
|
||||
@ -562,22 +523,6 @@ void Foam::List<T>::operator=(DynamicList<T, SizeMin>&& list)
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::List<T>::operator=(SLList<T>&& list)
|
||||
{
|
||||
label len = list.size();
|
||||
|
||||
reAlloc(len);
|
||||
|
||||
for (T* iter = this->begin(); len--; ++iter)
|
||||
{
|
||||
*iter = std::move(list.removeHead());
|
||||
}
|
||||
|
||||
list.clear();
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
@ -626,4 +571,36 @@ void Foam::sortedOrder
|
||||
}
|
||||
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * Housekeeping * * * * * * * * * * * * * * * //
|
||||
|
||||
#include "SLList.H"
|
||||
|
||||
template<class T>
|
||||
Foam::List<T>::List(const SLList<T>& list)
|
||||
:
|
||||
List<T>(list.begin(), list.end(), list.size())
|
||||
{}
|
||||
|
||||
|
||||
template<class T>
|
||||
void Foam::List<T>::operator=(const SLList<T>& list)
|
||||
{
|
||||
const label len = list.size();
|
||||
|
||||
reAlloc(len);
|
||||
|
||||
// Cannot use std::copy algorithm
|
||||
// - SLList doesn't define iterator category
|
||||
|
||||
T* iter = this->begin();
|
||||
|
||||
for (const T& val : list)
|
||||
{
|
||||
*iter = val;
|
||||
++iter;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ************************************************************************* //
|
||||
|
||||
@ -103,6 +103,19 @@ class List
|
||||
const label len
|
||||
);
|
||||
|
||||
//- Read List from Istream between '(' and ')' delimiters.
|
||||
//- The size is not known a priori.
|
||||
bool readBracketList(Istream& is);
|
||||
|
||||
|
||||
// Methods as per DynamicList to simplify code maintenance
|
||||
|
||||
//- Stub method for internal naming as per DynamicList
|
||||
label capacity() const noexcept { return UList<T>::size(); }
|
||||
|
||||
//- Stub method for internal naming as per DynamicList
|
||||
void setCapacity_nocopy(const label len) { resize_nocopy(len); }
|
||||
|
||||
|
||||
public:
|
||||
|
||||
@ -164,9 +177,6 @@ public:
|
||||
//- Construct as copy of PtrList<T>
|
||||
explicit List(const PtrList<T>& list);
|
||||
|
||||
//- Construct as copy of SLList<T>
|
||||
explicit List(const SLList<T>& list);
|
||||
|
||||
//- Construct as copy of IndirectList contents
|
||||
template<class Addr>
|
||||
explicit List(const IndirectListBase<T, Addr>& list);
|
||||
@ -181,9 +191,6 @@ public:
|
||||
template<int SizeMin>
|
||||
List(DynamicList<T, SizeMin>&& list);
|
||||
|
||||
//- Move construct from SLList
|
||||
List(SLList<T>&& list);
|
||||
|
||||
//- Construct from Istream
|
||||
List(Istream& is);
|
||||
|
||||
@ -279,9 +286,6 @@ public:
|
||||
//- Assignment operator. Takes linear time
|
||||
void operator=(const List<T>& list);
|
||||
|
||||
//- Assignment to SLList operator. Takes linear time
|
||||
void operator=(const SLList<T>& list);
|
||||
|
||||
//- Assignment from IndirectList. Takes linear time
|
||||
template<class Addr>
|
||||
void operator=(const IndirectListBase<T, Addr>& list);
|
||||
@ -306,9 +310,6 @@ public:
|
||||
template<int SizeMin>
|
||||
void operator=(DynamicList<T, SizeMin>&& list);
|
||||
|
||||
//- Move assignment. Takes constant time
|
||||
void operator=(SLList<T>&& list);
|
||||
|
||||
|
||||
// Reading/writing
|
||||
|
||||
@ -389,6 +390,13 @@ public:
|
||||
//- Append an element if not already in the list.
|
||||
//FOAM_DEPRECATED_FOR(2022-10, "push_uniq()")
|
||||
label appendUniq(const T& val) { return this->push_uniq(val); }
|
||||
|
||||
|
||||
//- Copy construct from SLList
|
||||
explicit List(const SLList<T>& list);
|
||||
|
||||
//- Copy assign from SLList in linear time
|
||||
void operator=(const SLList<T>& list);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -29,21 +29,148 @@ License
|
||||
#include "List.H"
|
||||
#include "Istream.H"
|
||||
#include "token.H"
|
||||
#include "SLList.H"
|
||||
#include "contiguous.H"
|
||||
#include <memory>
|
||||
|
||||
// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
Foam::List<T>::List(Istream& is)
|
||||
:
|
||||
UList<T>(nullptr, 0)
|
||||
UList<T>()
|
||||
{
|
||||
this->readList(is);
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * * IOstream Operators * * * * * * * * * * * * //
|
||||
// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
bool Foam::List<T>::readBracketList(Istream& is)
|
||||
{
|
||||
List<T>& list = *this;
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
token tok(is);
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"List<T>::readBracketList(Istream&) : reading first token"
|
||||
);
|
||||
|
||||
if (!tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
return false;
|
||||
}
|
||||
|
||||
{
|
||||
// "(...)" : read element-wise.
|
||||
// Uses chunk-wise reading to avoid too many re-allocations
|
||||
// and avoids relocation of contiguous memory until all of the reading
|
||||
// is completed. Chunks are wrapped as unique_ptr to ensure proper
|
||||
// cleanup on failure.
|
||||
|
||||
// The choice of chunk-size is somewhat arbitrary...
|
||||
constexpr label chunkSize = 128;
|
||||
typedef std::unique_ptr<List<T>> chunkType;
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
if (tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
// Trivial case, an empty list
|
||||
list.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
// Use all storage
|
||||
list.resize(list.capacity());
|
||||
|
||||
// Start with a few slots, recover current memory where possible
|
||||
List<chunkType> chunks(16);
|
||||
if (list.empty())
|
||||
{
|
||||
chunks[0] = chunkType(new List<T>(chunkSize));
|
||||
}
|
||||
else
|
||||
{
|
||||
chunks[0] = chunkType(new List<T>(std::move(list)));
|
||||
}
|
||||
|
||||
label nChunks = 1; // Active number of chunks
|
||||
label totalCount = 0; // Total number of elements
|
||||
label localIndex = 0; // Chunk-local index
|
||||
|
||||
while (!tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
|
||||
if (chunks[nChunks-1]->size() <= localIndex)
|
||||
{
|
||||
// Increase number of slots (doubling)
|
||||
if (nChunks >= chunks.size())
|
||||
{
|
||||
chunks.resize(2*chunks.size());
|
||||
}
|
||||
|
||||
chunks[nChunks] = chunkType(new List<T>(chunkSize));
|
||||
++nChunks;
|
||||
localIndex = 0;
|
||||
}
|
||||
|
||||
is >> chunks[nChunks-1]->operator[](localIndex);
|
||||
++localIndex;
|
||||
++totalCount;
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"List<T>::readBracketList(Istream&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
// Simple case
|
||||
if (nChunks == 1)
|
||||
{
|
||||
list = std::move(*(chunks[0]));
|
||||
list.resize(totalCount);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Destination
|
||||
list.setCapacity_nocopy(totalCount);
|
||||
list.resize_nocopy(totalCount);
|
||||
auto dest = list.begin();
|
||||
|
||||
for (label chunki = 0; chunki < nChunks; ++chunki)
|
||||
{
|
||||
List<T> currChunk(std::move(*(chunks[chunki])));
|
||||
chunks[chunki].reset(nullptr);
|
||||
|
||||
const label localLen = min(currChunk.size(), totalCount);
|
||||
|
||||
dest = std::move
|
||||
(
|
||||
currChunk.begin(),
|
||||
currChunk.begin(localLen),
|
||||
dest
|
||||
);
|
||||
|
||||
totalCount -= localLen;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * * //
|
||||
|
||||
template<class T>
|
||||
Foam::Istream& Foam::List<T>::readList(Istream& is)
|
||||
@ -142,15 +269,9 @@ Foam::Istream& Foam::List<T>::readList(Istream& is)
|
||||
}
|
||||
else if (tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
// "(...)" : read as SLList and transfer contents
|
||||
|
||||
list.clear(); // Clear old contents
|
||||
|
||||
is.putBack(tok); // Putback the opening bracket
|
||||
SLList<T> sll(is); // Read as singly-linked list
|
||||
|
||||
// Reallocate and move assign list elements
|
||||
list = std::move(sll);
|
||||
// "(...)" : read as bracketed list
|
||||
is.putBack(tok);
|
||||
this->readBracketList(is);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -29,7 +29,6 @@ License
|
||||
#include "UList.H"
|
||||
#include "Ostream.H"
|
||||
#include "token.H"
|
||||
#include "SLList.H"
|
||||
#include "contiguous.H"
|
||||
|
||||
// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * //
|
||||
@ -275,25 +274,46 @@ Foam::Istream& Foam::UList<T>::readList(Istream& is)
|
||||
}
|
||||
else if (tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
// "(...)" : read as SLList and transfer contents
|
||||
// "(...)" : read into list, handling size-mismatch after
|
||||
|
||||
is.putBack(tok); // Putback the opening bracket
|
||||
SLList<T> sll(is); // Read as singly-linked list
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
label inputLen = 0;
|
||||
|
||||
while (!tok.isPunctuation(token::END_LIST))
|
||||
{
|
||||
is.putBack(tok);
|
||||
if (inputLen < len)
|
||||
{
|
||||
is >> list[inputLen];
|
||||
}
|
||||
else
|
||||
{
|
||||
// Read and discard
|
||||
T dummy;
|
||||
is >> dummy;
|
||||
}
|
||||
++inputLen;
|
||||
|
||||
is.fatalCheck
|
||||
(
|
||||
"UList<T>::readList(Istream&) : "
|
||||
"reading entry"
|
||||
);
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
// List lengths must match
|
||||
if (sll.size() != len)
|
||||
if (inputLen != len)
|
||||
{
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "incorrect length for UList. Read "
|
||||
<< sll.size() << " expected " << len
|
||||
<< inputLen << " expected " << len
|
||||
<< exit(FatalIOError);
|
||||
}
|
||||
|
||||
// Move assign each list element
|
||||
for (label i = 0; i < len; ++i)
|
||||
{
|
||||
list[i] = std::move(sll.removeHead());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@ -50,9 +50,6 @@ Istream& List<char>::readList(Istream& is)
|
||||
{
|
||||
List<char>& list = *this;
|
||||
|
||||
// Anull list
|
||||
list.clear();
|
||||
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
|
||||
token tok(is);
|
||||
@ -63,6 +60,7 @@ Istream& List<char>::readList(Istream& is)
|
||||
{
|
||||
// Compound: simply transfer contents
|
||||
|
||||
list.clear(); // Clear old contents
|
||||
list.transfer
|
||||
(
|
||||
dynamicCast<token::Compound<List<char>>>
|
||||
@ -77,8 +75,8 @@ Istream& List<char>::readList(Istream& is)
|
||||
|
||||
const label len = tok.labelToken();
|
||||
|
||||
// Resize to actual length read
|
||||
list.resize(len);
|
||||
// Resize to length required
|
||||
list.resize_nocopy(len);
|
||||
|
||||
// Binary, always contiguous
|
||||
|
||||
@ -100,6 +98,8 @@ Istream& List<char>::readList(Istream& is)
|
||||
}
|
||||
else
|
||||
{
|
||||
list.clear(); // Clear old contents
|
||||
|
||||
FatalIOErrorInFunction(is)
|
||||
<< "incorrect first token, expected <int>, found "
|
||||
<< tok.info() << nl
|
||||
|
||||
@ -35,10 +35,11 @@ SourceFiles
|
||||
|
||||
\*---------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef blockMeshTools_H
|
||||
#define blockMeshTools_H
|
||||
#ifndef Foam_blockMeshTools_H
|
||||
#define Foam_blockMeshTools_H
|
||||
|
||||
#include "dictionary.H"
|
||||
#include "DynamicList.H"
|
||||
|
||||
// * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * //
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@
|
||||
\\/ M anipulation |
|
||||
-------------------------------------------------------------------------------
|
||||
Copyright (C) 2016 OpenFOAM Foundation
|
||||
Copyright (C) 2021 OpenCFD Ltd.
|
||||
Copyright (C) 2021-2023 OpenCFD Ltd.
|
||||
-------------------------------------------------------------------------------
|
||||
License
|
||||
This file is part of OpenFOAM.
|
||||
@ -40,12 +40,14 @@ void Foam::blockMeshTools::read
|
||||
|
||||
if (tok.isLabel())
|
||||
{
|
||||
// Label: should be int(..)
|
||||
|
||||
const label len = tok.labelToken();
|
||||
|
||||
// Set list length to that read
|
||||
list.resize(len);
|
||||
// Resize to length required
|
||||
list.resize_nocopy(len);
|
||||
|
||||
// Read beginning of contents
|
||||
// Begin of contents marker
|
||||
const char delimiter = is.readBeginList("List");
|
||||
|
||||
if (len)
|
||||
@ -59,12 +61,15 @@ void Foam::blockMeshTools::read
|
||||
}
|
||||
}
|
||||
|
||||
// Read end of contents
|
||||
// End of contents marker
|
||||
is.readEndList("List");
|
||||
}
|
||||
else if (tok.isPunctuation(token::BEGIN_LIST))
|
||||
{
|
||||
SLList<T> sll;
|
||||
// "(...)" : read with DynamicList and transfer contents
|
||||
|
||||
DynamicList<T> elements(std::move(list));
|
||||
elements.clear(); // Reset addressing only
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
@ -73,16 +78,14 @@ void Foam::blockMeshTools::read
|
||||
{
|
||||
is.putBack(tok);
|
||||
|
||||
T elem;
|
||||
read(is, elem, dict);
|
||||
sll.append(elem);
|
||||
read(is, elements.emplace_back(), dict);
|
||||
|
||||
is >> tok;
|
||||
is.fatalCheck(FUNCTION_NAME);
|
||||
}
|
||||
|
||||
// Convert the singly-linked list to this list
|
||||
list = std::move(sll);
|
||||
// Transfer back to regular list
|
||||
list = std::move(elements);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user