DynamicListI.H
Go to the documentation of this file.
1 /*---------------------------------------------------------------------------*\
2  ========= |
3  \\ / F ield | OpenFOAM: The Open Source CFD Toolbox
4  \\ / O peration |
5  \\ / A nd | www.openfoam.com
6  \\/ M anipulation |
7 -------------------------------------------------------------------------------
8  Copyright (C) 2011-2016 OpenFOAM Foundation
9  Copyright (C) 2016-2023 OpenCFD Ltd.
10 -------------------------------------------------------------------------------
11 License
12  This file is part of OpenFOAM.
13 
14  OpenFOAM is free software: you can redistribute it and/or modify it
15  under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
20  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
21  FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
22  for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
26 
27 \*---------------------------------------------------------------------------*/
28 
29 #include "FixedList.H"
30 
31 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
32 
33 template<class T, int SizeMin>
34 template<class ListType>
36 (
37  const ListType& list
38 )
39 {
40  const label len = list.size();
41 
42  if (capacity_ < len)
43  {
44  // Needs more space for the copy operation
45  List<T>::setAddressableSize(capacity_); // Use entire space
46  List<T>::resize_nocopy(len);
47  capacity_ = List<T>::size();
48  }
49 
50  // Perform copy into addressable portion
51  List<T>::setAddressableSize(len);
52  List<T>::operator=(list);
53 }
54 
55 
56 template<class T, int SizeMin>
58 (
59  const bool nocopy,
60  const label newCapacity
61 )
62 {
63  if (newCapacity == capacity_)
64  {
65  return;
66  }
67 
68  // Addressable length, possibly truncated by new capacity
69  const label currLen = min(List<T>::size(), newCapacity);
70 
71  // Corner case...
72  if (List<T>::size() == newCapacity)
73  {
74  // Adjust addressable size to trigger proper resizing.
75  // Using (old size+1) is safe since it does not affect the 'overlap'
76  // of old and new addressable regions, but incurs fewew copy
77  // operations than extending to use the current capacity would.
78  List<T>::setAddressableSize(currLen+1);
79  }
80 
81  if (nocopy)
82  {
83  List<T>::resize_nocopy(newCapacity);
84  }
85  else
86  {
87  List<T>::resize(newCapacity);
88  }
89 
90  capacity_ = List<T>::size();
91  List<T>::setAddressableSize(currLen);
92 }
93 
94 
95 template<class T, int SizeMin>
97 (
98  const bool nocopy,
99  const label len
100 )
101 {
102  if (capacity_ < len)
103  {
104  // Preserve addressed size
105  const label currLen = List<T>::size();
106 
107  // Increase capacity (doubling)
108  capacity_ = max(SizeMin, max(len, label(2*capacity_)));
109 
110  if (nocopy)
111  {
112  List<T>::resize_nocopy(capacity_);
113  }
114  else
115  {
116  List<T>::resize(capacity_);
117  }
118  List<T>::setAddressableSize(currLen);
119  }
120 }
121 
122 
123 template<class T, int SizeMin>
125 (
126  const bool nocopy,
127  const label len
128 )
129 {
130  this->doReserve(nocopy, len);
132 }
133 
134 
135 // * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
136 
137 template<class T, int SizeMin>
139 :
140  List<T>(),
141  capacity_(0)
142 {}
143 
144 
145 template<class T, int SizeMin>
146 inline Foam::DynamicList<T, SizeMin>::DynamicList(const label initialCapacity)
147 :
148  List<T>(),
149  capacity_(0)
150 {
151  reserve_nocopy(initialCapacity);
152 }
153 
154 
155 template<class T, int SizeMin>
157 (
158  const label len,
159  const T& val
160 )
161 :
162  List<T>(len, val),
163  capacity_(List<T>::size())
164 {}
165 
166 
167 template<class T, int SizeMin>
169 (
170  const label len,
171  const Foam::zero
172 )
173 :
174  List<T>(len, Foam::zero{}),
175  capacity_(List<T>::size())
176 {}
177 
178 
179 template<class T, int SizeMin>
181 (
182  const DynamicList<T, SizeMin>& list
183 )
184 :
185  List<T>(list),
186  capacity_(List<T>::size())
187 {}
188 
189 
190 template<class T, int SizeMin>
191 template<int AnySizeMin>
193 (
194  const DynamicList<T, AnySizeMin>& list
195 )
196 :
197  List<T>(list),
198  capacity_(List<T>::size())
199 {}
200 
201 
202 template<class T, int SizeMin>
204 (
205  const UList<T>& list
206 )
207 :
208  List<T>(list),
209  capacity_(List<T>::size())
210 {}
211 
212 
213 template<class T, int SizeMin>
215 (
216  const UList<T>& list,
217  const labelUList& indices
218 )
219 :
220  List<T>(list, indices),
221  capacity_(List<T>::size())
222 {}
223 
224 
225 template<class T, int SizeMin>
226 template<unsigned N>
228 (
229  const FixedList<T, N>& list
230 )
231 :
232  List<T>(list),
233  capacity_(List<T>::size())
234 {}
235 
236 
237 template<class T, int SizeMin>
239 (
240  std::initializer_list<T> lst
241 )
242 :
243  List<T>(lst),
244  capacity_(List<T>::size())
245 {}
246 
247 
248 template<class T, int SizeMin>
249 template<class Addr>
251 (
252  const IndirectListBase<T, Addr>& lst
253 )
254 :
255  List<T>(lst),
256  capacity_(List<T>::size())
257 {}
258 
259 
260 template<class T, int SizeMin>
262 (
264 ) noexcept
265 :
266  List<T>(std::move(static_cast<List<T>&>(list))),
267  capacity_(list.capacity())
268 {
269  list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
270 }
271 
272 
273 template<class T, int SizeMin>
274 template<int AnySizeMin>
276 (
278 ) noexcept
279 :
280  List<T>(std::move(static_cast<List<T>&>(list))),
281  capacity_(list.capacity())
282 {
283  list.setCapacity_unsafe(0); // Same as shrink_unsafe() but noexcept
284 }
285 
286 
287 template<class T, int SizeMin>
289 (
290  List<T>&& list
291 ) noexcept
292 :
293  List<T>(std::move(list)),
294  capacity_(List<T>::size())
295 {}
296 
297 
298 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
299 
300 template<class T, int SizeMin>
301 inline std::streamsize
303 {
304  return std::streamsize(capacity_)*sizeof(T);
305 }
306 
307 
308 template<class T, int SizeMin>
310 (
311  const label len
312 )
313 {
314  this->doCapacity(false, len); // nocopy = false
315 }
316 
317 
318 template<class T, int SizeMin>
320 (
321  const label len
322 )
323 {
324  this->doCapacity(true, len); // nocopy = true
325 }
326 
327 
328 template<class T, int SizeMin>
330 (
331  const label len
332 ) noexcept
333 {
334  capacity_ = len;
335 }
336 
337 
338 template<class T, int SizeMin>
340 (
341  const label len
342 )
343 {
344  this->doReserve(false, len); // nocopy = false
345 }
346 
347 
348 template<class T, int SizeMin>
350 (
351  const label len
352 )
353 {
354  this->doReserve(true, len); // nocopy = true
355 }
356 
357 
358 template<class T, int SizeMin>
360 (
361  const label len
362 )
363 {
364  this->doResize(false, len); // nocopy = false
365 }
366 
367 
368 template<class T, int SizeMin>
370 (
371  const label len,
372  const T& val
373 )
374 {
375  this->doResize(true, len); // nocopy = true
376  UList<T>::operator=(val);
377 }
378 
379 
380 template<class T, int SizeMin>
382 (
383  const label len
384 )
385 {
386  this->doResize(true, len); // nocopy = true
387 }
388 
389 
390 template<class T, int SizeMin>
392 (
393  const label len,
394  const T& val
395 )
396 {
397  const label oldLen = List<T>::size();
398  resize(len);
399 
400  // Fill newly exposed with constant value
401  if (oldLen < List<T>::size())
402  {
403  std::fill
404  (
405  this->begin(oldLen), this->end(), val
406  );
407  }
408 }
409 
410 
411 template<class T, int SizeMin>
413 {
415 }
416 
417 
418 template<class T, int SizeMin>
420 {
421  List<T>::clear();
422  capacity_ = 0;
423 }
424 
425 
426 template<class T, int SizeMin>
428 {
429  const label currLen = List<T>::size();
430  if (currLen < capacity_)
431  {
432  // Adjust addressable size to trigger proper resizing
433  List<T>::setAddressableSize(currLen+1);
434  List<T>::resize(currLen);
435  capacity_ = List<T>::size();
436  }
437 }
438 
439 
440 template<class T, int SizeMin>
442 {
443  if (List<T>::empty())
444  {
445  // Delete storage if empty
446  List<T>::clear();
447  }
448  capacity_ = List<T>::size();
449 }
450 
451 
452 template<class T, int SizeMin>
455 {
456  this->shrink_to_fit();
457  return *this;
458 }
459 
460 
461 template<class T, int SizeMin>
462 inline void
464 {
465  if
466  (
467  static_cast<const List<T>*>(this)
468  == static_cast<const List<T>*>(&list)
469  )
470  {
471  return; // Self-swap is a no-op
472  }
473 
474  // Remove unused storage
475  this->shrink_to_fit();
476 
477  // Swap storage and addressable size
478  UList<T>::swap(list);
479 
480  // Update capacity
481  capacity_ = List<T>::size();
482 }
483 
484 
485 template<class T, int SizeMin>
486 template<int AnySizeMin>
488 (
490 ) noexcept
491 {
492  if
493  (
494  static_cast<const List<T>*>(this)
495  == static_cast<const List<T>*>(&other)
496  )
497  {
498  return; // Self-swap is a no-op
499  }
500 
501  // Swap storage and addressable size
502  UList<T>::swap(other);
503 
504  // Swap capacity
505  std::swap(this->capacity_, other.capacity_);
506 }
507 
508 
509 template<class T, int SizeMin>
510 inline void
512 {
513  List<T>::transfer(list);
514  capacity_ = List<T>::size();
515 }
516 
517 
518 template<class T, int SizeMin>
519 template<int AnySizeMin>
520 inline void
522 (
524 )
525 {
526  if
527  (
528  static_cast<const List<T>*>(this)
529  == static_cast<const List<T>*>(&list)
530  )
531  {
532  return; // Self-assignment is a no-op
533  }
534 
535  // Take over storage as-is (without shrink)
536  capacity_ = list.capacity();
537 
538  List<T>::transfer(static_cast<List<T>&>(list));
539  list.clearStorage(); // capacity=0 etc.
540 }
541 
542 
543 template<class T, int SizeMin>
544 template<class... Args>
546 {
547  // This could/should be better with inplace construction
548  // (as per std::vector), but currently lacking the methods for that
549  // so resize and move assign
550 
551  const label idx = List<T>::size();
552  resize(idx + 1);
553 
554  // move assign element
555  UList<T>::operator[](idx) = T(std::forward<Args>(args)...);
556  return UList<T>::operator[](idx);
557 }
558 
559 
560 template<class T, int SizeMin>
562 (
563  const T& val
564 )
565 {
566  const label idx = List<T>::size();
567  resize(idx + 1);
569  UList<T>::operator[](idx) = val; // copy element
570 }
571 
572 
573 template<class T, int SizeMin>
575 (
576  T&& val
577 )
578 {
579  const label idx = List<T>::size();
580  resize(idx + 1);
582  UList<T>::operator[](idx) = std::move(val); // move assign element
583 }
584 
585 
586 template<class T, int SizeMin>
588 (
589  const UList<T>& list
590 )
591 {
592  if (this == &list)
593  {
595  << "Attempted push_back to self"
596  << abort(FatalError);
597  }
598 
599  const label idx = List<T>::size();
600  resize(idx + list.size());
601 
602  std::copy(list.begin(), list.end(), this->begin(idx));
603 }
604 
605 
606 template<class T, int SizeMin>
607 template<unsigned N>
609 (
610  const FixedList<T, N>& list
611 )
612 {
613  const label idx = List<T>::size();
614  resize(idx + list.size());
616  std::copy(list.begin(), list.end(), this->begin(idx));
617 }
618 
619 
620 template<class T, int SizeMin>
622 (
623  std::initializer_list<T> list
624 )
625 {
626  const label idx = List<T>::size();
627  resize(idx + list.size());
628 
629  std::copy(list.begin(), list.end(), this->begin(idx));
630 }
631 
632 
633 template<class T, int SizeMin>
634 template<class Addr>
636 (
637  const IndirectListBase<T, Addr>& list
638 )
639 {
640  // Note: push_back will still work even if the indirect list
641  // actually references *this, since its source elements will not
642  // overlap the new destinations.
643 
644  const label idx = this->size();
645  const label n = list.size();
646 
647  resize(list + n);
648 
649  auto iter = this->begin(idx);
650 
651  for (label i = 0; i < n; (void)++i, (void)++iter)
652  {
653  *iter = list[i]; // copy element
654  }
655 }
656 
657 
658 template<class T, int SizeMin>
660 (
661  List<T>&& list
662 )
663 {
664  if (this == &list)
665  {
667  << "Attempted push_back to self"
668  << abort(FatalError);
669  }
670 
671  const label idx = List<T>::size();
672  resize(idx + list.size());
673 
674  std::move(list.begin(), list.end(), this->begin(idx));
675 
676  list.clear();
677 }
678 
679 
680 template<class T, int SizeMin>
681 template<int AnySizeMin>
683 (
685 )
686 {
687  push_back(std::move(static_cast<List<T>&>(list)));
688  list.clearStorage(); // Deletion, capacity=0 etc.
689 }
690 
691 
692 template<class T, int SizeMin>
693 inline Foam::label Foam::DynamicList<T, SizeMin>::push_uniq(const T& val)
694 {
695  if (this->contains(val))
696  {
697  return 0;
698  }
699  else
700  {
701  this->push_back(val);
702  return 1; // Increased list length by one
703  }
704 }
705 
706 
707 template<class T, int SizeMin>
709 {
710  if (n >= this->size())
711  {
712  clear();
713  }
714  else if (n > 0)
715  {
716  resize(this->size() - n);
717  }
718 }
719 
720 
721 template<class T, int SizeMin>
723 {
724  // Location of last element and simultaneously the new size
725  const label idx = List<T>::size() - 1;
726 
727  if (idx < 0)
728  {
730  << "List is empty" << abort(FatalError);
731  }
732 
733  const T& val = List<T>::operator[](idx);
734 
735  List<T>::setAddressableSize(idx);
737  return val;
738 }
739 
740 
741 template<class T, int SizeMin>
743 (
744  const label idx,
745  const bool fast
746 )
747 {
748  if (fast)
749  {
750  // Simply swap idx <=> last
751  this->swapLast(idx);
752  }
753  else
754  {
755  // Move element to the end and move everything down
756  this->moveLast(idx);
757  }
758 
759  // Element to remove is now at the end
760  return this->remove();
761 }
762 
763 
764 template<class T, int SizeMin>
765 inline Foam::label Foam::DynamicList<T, SizeMin>::remove
766 (
767  const labelRange& range
768 )
769 {
770  return this->removeElements(this->validateRange(range));
771 }
772 
773 
774 template<class T, int SizeMin>
775 inline Foam::label Foam::DynamicList<T, SizeMin>::remove
776 (
777  std::initializer_list<label> start_size
778 )
779 {
780  return this->removeElements(this->validateRange(start_size));
781 }
782 
783 
784 template<class T, int SizeMin>
785 inline Foam::label Foam::DynamicList<T, SizeMin>::subset
786 (
787  const labelRange& range
788 )
789 {
790  return this->subsetElements(this->validateRange(range));
791 }
792 
793 
794 template<class T, int SizeMin>
795 inline Foam::label Foam::DynamicList<T, SizeMin>::subset
796 (
797  std::initializer_list<label> start_size
798 )
799 {
800  return this->subsetElements(this->validateRange(start_size));
801 }
802 
803 
804 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
805 
806 template<class T, int SizeMin>
808 (
809  const label i
810 )
811 {
812  if (i >= List<T>::size())
813  {
814  resize(i + 1);
815  }
817  return UList<T>::operator[](i);
818 }
819 
820 
821 template<class T, int SizeMin>
823 (
824  const T& val
825 )
826 {
827  UList<T>::operator=(val);
828 }
829 
830 
831 template<class T, int SizeMin>
833 (
834  const Foam::zero
835 )
836 {
838 }
839 
840 
841 template<class T, int SizeMin>
843 (
844  const UList<T>& lst
845 )
846 {
847  doAssignDynList(lst);
848 }
849 
850 
851 template<class T, int SizeMin>
852 template<unsigned N>
854 (
855  const FixedList<T, N>& lst
856 )
857 {
858  doAssignDynList(lst);
859 }
860 
861 
862 template<class T, int SizeMin>
864 (
865  const DynamicList<T, SizeMin>& lst
866 )
867 {
868  if (this == &lst)
869  {
870  return; // Self-assignment is a no-op
871  }
872 
873  doAssignDynList(lst);
874 }
875 
876 
877 template<class T, int SizeMin>
878 template<int AnySizeMin>
880 (
881  const DynamicList<T, AnySizeMin>& list
882 )
883 {
884  if
885  (
886  static_cast<const List<T>*>(this)
887  == static_cast<const List<T>*>(&list)
888  )
889  {
890  return; // Self-assignment is a no-op
891  }
893  doAssignDynList(list);
894 }
895 
896 
897 template<class T, int SizeMin>
899 (
900  std::initializer_list<T> lst
901 )
902 {
903  doAssignDynList(lst);
904 }
905 
906 
907 template<class T, int SizeMin>
908 template<class Addr>
910 (
911  const IndirectListBase<T, Addr>& lst
912 )
913 {
914  // NOTE: Self-assignment needs special handling
921  doAssignDynList(lst);
922 }
923 
924 
925 template<class T, int SizeMin>
927 (
928  List<T>&& lst
929 )
930 {
931  clear();
932  transfer(lst);
933 }
934 
935 
936 template<class T, int SizeMin>
938 (
940 )
941 {
942  if (this == &lst)
943  {
944  return; // Self-assignment is a no-op
945  }
946 
947  clear();
948  transfer(lst);
949 }
950 
951 
952 template<class T, int SizeMin>
953 template<int AnySizeMin>
955 (
957 )
958 {
959  if
960  (
961  static_cast<const List<T>*>(this)
962  == static_cast<const List<T>*>(&list)
963  )
964  {
965  return; // Self-assignment is a no-op
966  }
967 
968  clear();
969  transfer(list);
970 }
971 
972 
973 // ************************************************************************* //
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:116
friend Ostream & operator(Ostream &os, const DynamicList< T, SizeMin > &list)
Write to Ostream.
patchWriters resize(patchIds.size())
A 1D vector of objects of type <T> with a fixed length <N>.
Definition: HashTable.H:107
iterator begin() noexcept
Return an iterator to begin traversing the FixedList.
Definition: FixedListI.H:482
error FatalError
Error stream (stdout output on all processes), with additional &#39;FOAM FATAL ERROR&#39; header text and sta...
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:598
A 1D array of objects of type <T>, where the size of the vector is known and used for subscript bound...
Definition: BitOps.H:56
void reserve_nocopy(const label len)
Reserve allocation space for at least this size, allocating new space if required without retaining o...
Definition: DynamicListI.H:343
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:40
constexpr DynamicList() noexcept
Default construct, an empty list without allocation.
Definition: DynamicListI.H:131
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:52
void shrink_unsafe()
Shrink the internal bookkeeping of the allocated space to the number of addressed elements without af...
Definition: DynamicListI.H:434
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:353
iterator end() noexcept
Return an iterator to end traversing the FixedList.
Definition: FixedListI.H:506
void setCapacity(const label len)
Alter the size of the underlying storage.
Definition: DynamicListI.H:303
void resize_fill(const label len, const T &val)
Alter addressable size and set val for all addressed entries.
Definition: DynamicListI.H:363
void pop_back(label n=1)
Reduce size by 1 or more elements. Can be called on an empty list.
Definition: DynamicListI.H:701
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
scalar range
void shrink_to_fit()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:420
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicList.H:225
static constexpr label size() noexcept
Return the number of elements in the FixedList.
Definition: FixedList.H:600
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
T & emplace_back(Args &&... args)
Construct an element at the end of the list, return reference to the new list element.
Definition: DynamicListI.H:538
std::streamsize capacity_bytes() const noexcept
Number of contiguous bytes of the underlying storage.
Definition: DynamicListI.H:295
patchWriters clear()
label size() const noexcept
The number of elements in the list.
label min(const labelHashSet &set, label minValue=labelMax)
Find the min value in labelHashSet, optionally limited by second argument.
Definition: hashSets.C:26
errorManip< error > abort(error &err)
Definition: errorManip.H:139
iterator begin() noexcept
Return an iterator to begin traversing the UList.
Definition: UListI.H:391
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition: HashTable.H:105
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
Definition: DynamicListI.H:333
const direction noexcept
Definition: Scalar.H:258
void setCapacity_unsafe(const label len) noexcept
Change the value for the list capacity directly (ADVANCED, UNSAFE) Does not perform any memory manage...
Definition: DynamicListI.H:323
DynamicList< T, SizeMin > & shrink()
Calls shrink_to_fit() and returns a reference to the DynamicList.
Definition: DynamicListI.H:447
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:201
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:405
const volScalarField & T
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:555
void swap(List< T > &list)
Swap with plain List content. Implies shrink_to_fit().
Definition: DynamicListI.H:456
label push_uniq(const T &val)
Append an element if not already in the list.
Definition: DynamicListI.H:686
T remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:715
void transfer(List< T > &list)
Transfer contents of the argument List into this.
Definition: DynamicListI.H:504
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:412
label subset(const labelRange &range)
Retain a (start,size) subset from the list.
Definition: DynamicListI.H:779
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
label n
void resize_nocopy(const label len)
Alter addressable list size, allocating new space if required without necessarily recovering old cont...
Definition: DynamicListI.H:375
iterator end() noexcept
Return an iterator to end traversing the UList.
Definition: UListI.H:435
Foam::argList args(argc, argv)
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:168
void setCapacity_nocopy(const label len)
Alter the size of the underlying storage, without retaining old content.
Definition: DynamicListI.H:313
Namespace for OpenFOAM.