diff --git a/applications/test/List/Test-List.C b/applications/test/List/Test-List.C index bbba8219b320a16c88967188cc2f41715e343b4b..9ab2732c2e68ff4e9bb496aa64d27a11720b421f 100644 --- a/applications/test/List/Test-List.C +++ b/applications/test/List/Test-List.C @@ -76,7 +76,6 @@ int main(int argc, char *argv[]) Info<<"is >>: " << intlist << endl; } - List<vector> list1(IStringStream("1 ((0 1 2))")()); Info<< "list1: " << list1 << endl; @@ -150,7 +149,6 @@ int main(int argc, char *argv[]) Info<< "normal: " << longLabelList << nl; Info<< "flatOutput: " << flatOutput(longLabelList) << nl; // Info<< "flatOutput(14): " << flatOutput(longLabelList, 14) << nl; - // Info<< "flatOutput(15): " << flatOutput(longLabelList, 15) << nl; stringList longStringList(12); forAll(longStringList, i) @@ -165,6 +163,66 @@ int main(int argc, char *argv[]) // contiguous longStringList[i].resize(3, 'a' + i); } + // test SubList and labelRange + { + Info<< nl; + labelList longLabelList = identity(25); + reverse(longLabelList); + + FixedList<label, 6> fixedLabelList{0,1,2,3,4,5}; + const labelList constLabelList = identity(25); + + Info<< "full-list: " << flatOutput(longLabelList) << nl; + + labelRange range1(-15, 25); + Info<<"sub range:" << range1 << "="; + Info<< SubList<label>(longLabelList, range1) << nl; + + labelRange range2(7, 8); + Info<<"sub range:" << range2 << "="; + Info<< SubList<label>(longLabelList, range2) << nl; + + // labelRange range2(7, 8); + Info<<"use range " << range2 << " to set value"; + SubList<label>(longLabelList, range2) = -15; + Info<< "=> " << flatOutput(longLabelList) << nl; + + // This syntax looks even nicer: + + // GOOD: does not compile + // > constLabelList[labelRange(23,5)] = 5; + + // Check correct overlaps + longLabelList[labelRange(-10, 12)] = 200; + longLabelList[{18,3}] = 100; + longLabelList[{23,3}] = 400; + // and complete misses + longLabelList[{500,50}] = 100; + + // labelRange automatically suppresses -ve size -> nop + longLabelList[{5,-5}] = 42; + longLabelList[{21,100}] = 42; + + //Good: does not compile + //> longLabelList[labelRange(20,50)] = constLabelList; + + //Good: does not compile + // longLabelList[labelRange(20,50)] = fixedLabelList; + + Info<< "updated: " << constLabelList[labelRange(23,5)] << nl; + Info<< "updated: " << flatOutput(longLabelList) << nl; + + //Nope: sort(longLabelList[labelRange(18,5)]); + { + // Instead + UList<label> sub = longLabelList[labelRange(0, 8)]; + sort(sub); + } + Info<< "sub-sorted: " << flatOutput(longLabelList) << nl; + + // Info<<"Slice=" << longLabelList[labelRange(23,5)] << nl; + } + wordReList reLst; wordList wLst; stringList sLst; diff --git a/src/OpenFOAM/containers/Lists/SubList/SubList.H b/src/OpenFOAM/containers/Lists/SubList/SubList.H index b55fced6bb53d9272febef281fa1eacc5e82c901..1a02f11d79dd1c6907cd561cb92c281f9551bc54 100644 --- a/src/OpenFOAM/containers/Lists/SubList/SubList.H +++ b/src/OpenFOAM/containers/Lists/SubList/SubList.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -40,6 +40,7 @@ SourceFiles #define SubList_H #include "List.H" +#include "labelRange.H" // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // @@ -55,7 +56,6 @@ class SubList : public UList<T> { - public: // Static Member Functions @@ -81,6 +81,23 @@ public: const label startIndex ); + //- Construct from UList and a (start,size) range. + // The range is subsetted with the list size itself to ensure that the + // result always addresses a valid section of the list. + inline SubList + ( + const UList<T>& list, + const labelRange& range + ); + + //- Construct from UList and a (start,size) range, but bypassing + // run-time range checking. + inline SubList + ( + const labelRange& range, + const UList<T>& list + ); + // Member operators @@ -88,13 +105,13 @@ public: inline operator const Foam::List<T>&() const; //- Assignment of all entries to the given sub-list - inline void operator=(const SubList<T>&); + inline void operator=(const SubList<T>& list); //- Assignment of all entries to the given list - inline void operator=(const UList<T>&); + inline void operator=(const UList<T>& list); //- Assignment of all entries to the given value - inline void operator=(const T&); + inline void operator=(const T& t); }; diff --git a/src/OpenFOAM/containers/Lists/SubList/SubListI.H b/src/OpenFOAM/containers/Lists/SubList/SubListI.H index 733b813b51c39a39723e3f2d6f66ac429a5c9d57..42accb1871ca9d7c1f9b336398ec163a698f2a20 100644 --- a/src/OpenFOAM/containers/Lists/SubList/SubListI.H +++ b/src/OpenFOAM/containers/Lists/SubList/SubListI.H @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -51,7 +51,6 @@ inline Foam::SubList<T>::SubList UList<T>(&(list.v_[startIndex]), subSize) { #ifdef FULLDEBUG - // Artificially allow the start of a zero-sized subList to be // one past the end of the original list. if (subSize) @@ -69,6 +68,28 @@ inline Foam::SubList<T>::SubList } +template<class T> +inline Foam::SubList<T>::SubList +( + const UList<T>& list, + const labelRange& range +) +: + SubList<T>(list.validateRange(range), list) +{} + + +template<class T> +inline Foam::SubList<T>::SubList +( + const labelRange& range, + const UList<T>& list +) +: + SubList<T>(list, range.size(), range.start()) +{} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template<class T> @@ -88,16 +109,16 @@ inline Foam::SubList<T>::operator const Foam::List<T>&() const template<class T> -inline void Foam::SubList<T>::operator=(const SubList<T>& sl) +inline void Foam::SubList<T>::operator=(const SubList<T>& list) { - UList<T>::deepCopy(sl); + UList<T>::deepCopy(list); } template<class T> -inline void Foam::SubList<T>::operator=(const UList<T>& l) +inline void Foam::SubList<T>::operator=(const UList<T>& list) { - UList<T>::deepCopy(l); + UList<T>::deepCopy(list); } diff --git a/src/OpenFOAM/containers/Lists/UList/UList.C b/src/OpenFOAM/containers/Lists/UList/UList.C index 7bc6b9d20c52ab2a0e7651cccd8b6d4081a7a467..9517aa8234ce20afa4dafd704f535cdb85ebf061 100644 --- a/src/OpenFOAM/containers/Lists/UList/UList.C +++ b/src/OpenFOAM/containers/Lists/UList/UList.C @@ -3,7 +3,7 @@ \\ / F ield | OpenFOAM: The Open Source CFD Toolbox \\ / O peration | \\ / A nd | Copyright (C) 2011-2016 OpenFOAM Foundation - \\/ M anipulation | + \\/ M anipulation | Copyright (C) 2017 OpenCFD Ltd. ------------------------------------------------------------------------------- License This file is part of OpenFOAM. @@ -26,9 +26,49 @@ License #include "UList.H" #include "ListLoopM.H" #include "contiguous.H" +#include "labelRange.H" #include <algorithm> +// * * * * * * * * * * * * Protected Member Functions * * * * * * * * * * * // + +template<class T> +Foam::labelRange Foam::UList<T>::validateRange(const labelRange& range) const +{ + const labelRange slice = range.subset(0, this->size()); + + #ifdef FULLDEBUG + this->checkStart(slice.start()); + this->checkSize(slice.start() + slice.size()); + #endif + + return slice; +} + + +template<class T> +Foam::labelRange Foam::UList<T>::validateRange +( + std::initializer_list<label> start_size_pair +) const +{ + if (start_size_pair.size() != 2) + { + FatalErrorInFunction + << "range specified with " << start_size_pair.size() + << " elements instead of 2" + << abort(FatalError); + } + + auto iter = start_size_pair.begin(); + + const label beg = *(iter++); + const label sz = *iter; + + return this->validateRange(labelRange(beg, sz)); +} + + // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * // template<class T> @@ -64,6 +104,47 @@ void Foam::UList<T>::deepCopy(const UList<T>& a) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // +template<class T> +Foam::UList<T> Foam::UList<T>::operator[](const labelRange& range) +{ + const labelRange slice = validateRange(range); + + return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList +} + +template<class T> +const Foam::UList<T> Foam::UList<T>::operator[](const labelRange& range) const +{ + const labelRange slice = validateRange(range); + + return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList +} + + +template<class T> +Foam::UList<T> Foam::UList<T>::operator[] +( + std::initializer_list<label> start_size_pair +) +{ + const labelRange slice = validateRange(start_size_pair); + + return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList +} + +template<class T> +const Foam::UList<T> Foam::UList<T>::operator[] +( + std::initializer_list<label> start_size_range +) const +{ + // Restricted range + const labelRange slice = validateRange(start_size_range); + + return UList<T>(&(this->v_[slice.start()]), slice.size()); // SubList +} + + template<class T> void Foam::UList<T>::operator=(const T& t) { diff --git a/src/OpenFOAM/containers/Lists/UList/UList.H b/src/OpenFOAM/containers/Lists/UList/UList.H index 4b819515625c70001d6b01ad7d54b014df3ab77e..2ee8bc73795552482e7f6d188d3ac4d6d8058760 100644 --- a/src/OpenFOAM/containers/Lists/UList/UList.H +++ b/src/OpenFOAM/containers/Lists/UList/UList.H @@ -48,13 +48,15 @@ SourceFiles #include "nullObject.H" #include "zero.H" #include "stdFoam.H" +#include <initializer_list> // * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * // namespace Foam { -// Forward declaration of friend classes +// Forward declarations +class labelRange; template<class T> class List; template<class T> class SubList; @@ -101,6 +103,16 @@ protected: //- Write the UList with its compound type void writeEntry(Ostream& os) const; + //- Return a validated (start,size) subset range, which means that it + // always addresses a valid section of the list. + labelRange validateRange(const labelRange& range) const; + + //- Return a validated (start,size) subset range, which means that it + // always addresses a valid section of the list. + labelRange validateRange + ( + std::initializer_list<label> start_size_pair + ) const; public: @@ -239,6 +251,29 @@ public: // an out-of-range element returns false without any ill-effects inline const T& operator[](const label i) const; + //- Return (start,size) subset from UList with non-const access. + // The range is subsetted with the list size itself to ensure that the + // result always addresses a valid section of the list. + UList<T> operator[](const labelRange& range); + + //- Return (start,size) subset from UList with const access. + // The range is subsetted with the list size itself to ensure that the + // result always addresses a valid section of the list. + const UList<T> operator[](const labelRange& range) const; + + //- Return (start,size) subset from UList with non-const access. + // The range is subsetted with the list size itself to ensure that the + // result always addresses a valid section of the list. + UList<T> operator[](std::initializer_list<label> start_size_range); + + //- Return (start,size) subset from UList with const access. + // The range is subsetted with the list size itself to ensure that the + // result always addresses a valid section of the list. + const UList<T> operator[] + ( + std::initializer_list<label> start_size_range + ) const; + //- Allow cast to a const List<T>& inline operator const Foam::List<T>&() const; diff --git a/src/OpenFOAM/containers/Lists/UList/UListI.H b/src/OpenFOAM/containers/Lists/UList/UListI.H index bd9fe339ebd7697b2924fbeee98390439615958b..971fa7faa0530ceadb3964ada7746733a85efa37 100644 --- a/src/OpenFOAM/containers/Lists/UList/UListI.H +++ b/src/OpenFOAM/containers/Lists/UList/UListI.H @@ -71,7 +71,7 @@ inline Foam::label Foam::UList<T>::rcIndex(const label i) const template<class T> inline void Foam::UList<T>::checkStart(const label start) const { - if (start<0 || (start && start>=size_)) + if (start < 0 || (start && start >= size_)) { FatalErrorInFunction << "start " << start << " out of range 0 ... " << max(size_-1, 0) @@ -83,7 +83,7 @@ inline void Foam::UList<T>::checkStart(const label start) const template<class T> inline void Foam::UList<T>::checkSize(const label size) const { - if (size<0 || size>size_) + if (size < 0 || size > size_) { FatalErrorInFunction << "size " << size << " out of range 0 ... " << size_ @@ -162,7 +162,6 @@ inline void Foam::UList<T>::shallowCopy(const UList<T>& a) // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * // - template<class T> inline T& Foam::UList<T>::operator[](const label i) { @@ -172,7 +171,6 @@ inline T& Foam::UList<T>::operator[](const label i) return v_[i]; } - namespace Foam { // Template specialization for bool @@ -191,7 +189,6 @@ namespace Foam } } - template<class T> inline const T& Foam::UList<T>::operator[](const label i) const {