/*---------------------------------------------------------------------------*\ ========= | \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | www.openfoam.com \\/ M anipulation | ------------------------------------------------------------------------------- Copyright (C) 2011-2016 OpenFOAM Foundation Copyright (C) 2017-2022 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. OpenFOAM is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. OpenFOAM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with OpenFOAM. If not, see . \*---------------------------------------------------------------------------*/ #include "List.H" #include "ListLoopM.H" #include "FixedList.H" #include "PtrList.H" #include "SLList.H" #include "contiguous.H" // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * // template void Foam::List::doResize(const label len) { if (len == this->size_) { return; } if (len > 0) { // With sign-check to avoid spurious -Walloc-size-larger-than T* nv = new T[len]; const label overlap = min(this->size_, len); if (overlap) { #ifdef USEMEMCPY if (is_contiguous::value) { std::memcpy ( static_cast(nv), this->v_, overlap*sizeof(T) ); } else #endif { List_ACCESS(T, *this, vp); for (label i = 0; i < overlap; ++i) { nv[i] = std::move(vp[i]); } } } clear(); this->size_ = len; this->v_ = nv; } else { // Or only #ifdef FULLDEBUG if (len < 0) { FatalErrorInFunction << "bad size " << len << abort(FatalError); } // #endif clear(); } } // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * // template Foam::List::List(const label len) : UList(nullptr, len) { if (len < 0) { FatalErrorInFunction << "bad size " << len << abort(FatalError); } doAlloc(); } template Foam::List::List(const label len, const T& val) : UList(nullptr, len) { if (len < 0) { FatalErrorInFunction << "bad size " << len << abort(FatalError); } if (len) { doAlloc(); List_ACCESS(T, (*this), vp); for (label i=0; i < len; ++i) { vp[i] = val; } } } template Foam::List::List(const label len, const Foam::zero) : UList(nullptr, len) { if (len < 0) { FatalErrorInFunction << "bad size " << len << abort(FatalError); } if (len) { doAlloc(); List_ACCESS(T, (*this), vp); for (label i=0; i < len; ++i) { vp[i] = Zero; } } } template Foam::List::List(const Foam::one, const T& val) : UList(new T[1], 1) { this->v_[0] = val; } template Foam::List::List(const Foam::one, T&& val) : UList(new T[1], 1) { this->v_[0] = std::move(val); } template Foam::List::List(const Foam::one, const Foam::zero) : UList(new T[1], 1) { this->v_[0] = Zero; } template Foam::List::List(const UList& a) : UList(nullptr, a.size_) { const label len = this->size_; if (len) { doAlloc(); #ifdef USEMEMCPY if (is_contiguous::value) { std::memcpy ( static_cast(this->v_), a.v_, this->size_bytes() ); } else #endif { List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); for (label i = 0; i < len; ++i) { vp[i] = ap[i]; } } } } template Foam::List::List(const List& a) : UList(nullptr, a.size_) { const label len = this->size_; if (len) { doAlloc(); #ifdef USEMEMCPY if (is_contiguous::value) { std::memcpy ( static_cast(this->v_), a.v_, this->size_bytes() ); } else #endif { List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); for (label i = 0; i < len; ++i) { vp[i] = ap[i]; } } } } template Foam::List::List(List& a, bool reuse) : UList(nullptr, a.size_) { if (reuse) { // Steal content this->v_ = a.v_; a.v_ = nullptr; a.size_ = 0; return; } const label len = this->size_; if (len) { doAlloc(); #ifdef USEMEMCPY if (is_contiguous::value) { std::memcpy ( static_cast(this->v_), a.v_, this->size_bytes() ); } else #endif { List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); for (label i = 0; i < len; ++i) { vp[i] = ap[i]; } } } } template Foam::List::List(const UList& list, const labelUList& indices) : UList(nullptr, indices.size()) { const label len = indices.size(); if (len) { doAlloc(); List_ACCESS(T, (*this), vp); for (label i=0; i < len; ++i) { vp[i] = list[indices[i]]; } } } template template Foam::List::List ( const UList& list, const FixedList& indices ) : UList(nullptr, label(N)) { const label len = label(N); doAlloc(); List_ACCESS(T, (*this), vp); for (label i=0; i < len; ++i) { vp[i] = list[indices[i]]; } } template template Foam::List::List(const FixedList& list) : UList(nullptr, label(N)) { doAlloc(); copyList(list); } template Foam::List::List(const PtrList& list) : UList(nullptr, list.size()) { doAlloc(); copyList(list); } template Foam::List::List(const SLList& list) : List(list.begin(), list.end(), list.size()) {} template template Foam::List::List(const IndirectListBase& list) : UList(nullptr, list.size()) { doAlloc(); copyList(list); } template Foam::List::List(std::initializer_list list) : List(list.begin(), list.end(), list.size()) {} template Foam::List::List(List&& list) : UList() { // Can use transfer or swap to manage content transfer(list); } template template Foam::List::List(DynamicList&& list) : UList() { transfer(list); } template Foam::List::List(SLList&& list) : UList() { operator=(std::move(list)); } // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * // template Foam::List::~List() { if (this->v_) { delete[] this->v_; } } // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template void Foam::List::resize(const label len, const T& val) { label idx = this->size_; this->doResize(len); List_ACCESS(T, *this, vp); while (idx < len) { vp[idx] = val; ++idx; } } template void Foam::List::transfer(List& list) { if (this == &list) { return; // Self-assignment is a no-op } // Clear and swap - could also check for self assignment clear(); this->size_ = list.size_; this->v_ = list.v_; list.size_ = 0; list.v_ = nullptr; } template template void Foam::List::transfer(DynamicList& list) { // Shrink the allocated space to the number of elements used list.shrink(); transfer(static_cast&>(list)); // Ensure DynamicList has proper capacity=0 too list.clearStorage(); } // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // template void Foam::List::operator=(const UList& a) { if (this == &a) { return; // Self-assignment is a no-op } reAlloc(a.size_); const label len = this->size_; if (len) { #ifdef USEMEMCPY if (is_contiguous::value) { std::memcpy ( static_cast(this->v_), a.v_, this->size_bytes() ); } else #endif { List_ACCESS(T, (*this), vp); List_CONST_ACCESS(T, a, ap); for (label i = 0; i < len; ++i) { vp[i] = ap[i]; } } } } template void Foam::List::operator=(const List& list) { if (this == &list) { return; // Self-assignment is a no-op } operator=(static_cast&>(list)); } template void Foam::List::operator=(const SLList& list) { const label len = list.size(); reAlloc(len); if (len) { T* iter = this->begin(); for (const T& val : list) { *iter = val; ++iter; } } } template template void Foam::List::operator=(const FixedList& list) { reAlloc(static_cast