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 len)
147 :
148  List<T>(),
149  capacity_(0)
150 {
151  reserve_nocopy(len);
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, 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 )
265 :
266  capacity_(0)
267 {
268  transfer(lst);
269 }
270 
271 
272 template<class T, int SizeMin>
273 template<int AnySizeMin>
275 (
277 )
278 :
279  capacity_(0)
280 {
281  transfer(lst);
282 }
283 
284 
285 template<class T, int SizeMin>
287 (
288  List<T>&& lst
289 )
290 :
291  List<T>(std::move(lst)),
292  capacity_(List<T>::size())
293 {}
294 
295 
296 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
297 
298 template<class T, int SizeMin>
299 inline std::streamsize
301 {
302  return std::streamsize(capacity_)*sizeof(T);
303 }
304 
305 
306 template<class T, int SizeMin>
308 (
309  const label len
310 )
311 {
312  this->doCapacity(false, len); // nocopy = false
313 }
314 
315 
316 template<class T, int SizeMin>
318 (
319  const label len
320 )
321 {
322  this->doCapacity(true, len); // nocopy = true
323 }
324 
325 
326 template<class T, int SizeMin>
328 (
329  const label len
330 ) noexcept
331 {
332  capacity_ = len;
333 }
334 
335 
336 template<class T, int SizeMin>
338 (
339  const label len
340 )
341 {
342  this->doReserve(false, len); // nocopy = false
343 }
344 
345 
346 template<class T, int SizeMin>
348 (
349  const label len
350 )
351 {
352  this->doReserve(true, len); // nocopy = true
353 }
354 
355 
356 template<class T, int SizeMin>
358 (
359  const label len
360 )
361 {
362  this->doResize(false, len); // nocopy = false
363 }
364 
365 
366 template<class T, int SizeMin>
368 (
369  const label len
370 )
371 {
372  this->doResize(true, len); // nocopy = true
373 }
374 
375 
376 template<class T, int SizeMin>
378 (
379  const label len,
380  const T& val
381 )
382 {
383  label idx = List<T>::size();
384  resize(len);
385 
386  // Fill newly exposed with constant value
387  while (idx < len)
388  {
389  this->operator[](idx) = val;
390  ++idx;
391  }
392 }
393 
394 
395 template<class T, int SizeMin>
397 {
399 }
400 
401 
402 template<class T, int SizeMin>
404 {
405  List<T>::clear();
406  capacity_ = 0;
407 }
408 
409 
410 template<class T, int SizeMin>
412 {
413  const label currLen = List<T>::size();
414 
415  // Address into the entire list
417 
418  return currLen;
419 }
420 
421 
422 template<class T, int SizeMin>
424 {
425  const label currLen = List<T>::size();
426  if (currLen < capacity_)
427  {
428  // Adjust addressable size to trigger proper resizing
429  List<T>::setAddressableSize(currLen+1);
430 
431  List<T>::resize(currLen);
432  capacity_ = List<T>::size();
433  }
434 }
435 
436 
437 template<class T, int SizeMin>
440 {
441  this->shrinkStorage();
442  return *this;
443 }
444 
445 
446 template<class T, int SizeMin>
447 template<int AnySizeMin>
449 (
451 )
452 {
453  if
454  (
455  static_cast<const List<T>*>(this)
456  == static_cast<const List<T>*>(&other)
457  )
458  {
459  return; // Self-swap is a no-op
460  }
461 
462  // Swap storage and addressable size
463  UList<T>::swap(other);
464 
465  // Swap capacity
466  std::swap(this->capacity_, other.capacity_);
467 }
468 
469 
470 template<class T, int SizeMin>
471 inline void
473 {
474  // Take over storage, clear addressing for list
475  capacity_ = list.size();
476  List<T>::transfer(list);
477 }
478 
479 
480 template<class T, int SizeMin>
481 template<int AnySizeMin>
482 inline void
484 (
486 )
487 {
488  if
489  (
490  static_cast<const List<T>*>(this)
491  == static_cast<const List<T>*>(&list)
492  )
493  {
494  return; // Self-assignment is a no-op
495  }
496 
497  // Take over storage as-is (without shrink, without using SizeMin)
498  // clear addressing and storage for old lst.
499  capacity_ = list.capacity();
500 
501  List<T>::transfer(static_cast<List<T>&>(list));
502  list.clearStorage(); // Ensure capacity=0
503 }
504 
505 
506 template<class T, int SizeMin>
507 template<class... Args>
509 {
510  // This could/should be better with inplace construction
511  // (as per std::vector), but currently lacking the methods for that
512  // so resize and move assign
513 
514  const label idx = List<T>::size();
515  resize(idx + 1);
516 
517  // move assign element
518  this->operator[](idx) = T(std::forward<Args>(args)...);
519  return this->back();
520 }
521 
522 
523 template<class T, int SizeMin>
525 (
526  const T& val
527 )
528 {
529  const label idx = List<T>::size();
530  resize(idx + 1);
532  this->operator[](idx) = val; // copy element
533 }
534 
535 
536 template<class T, int SizeMin>
538 (
539  T&& val
540 )
541 {
542  const label idx = List<T>::size();
543  resize(idx + 1);
545  this->operator[](idx) = std::move(val); // move assign element
546 }
547 
548 
549 template<class T, int SizeMin>
551 (
552  const UList<T>& lst
553 )
554 {
555  if (this == &lst)
556  {
558  << "Attempted push_back to self"
559  << abort(FatalError);
560  }
561 
562  label idx = List<T>::size();
563  resize(idx + lst.size());
564 
565  for (const T& val : lst)
566  {
567  this->operator[](idx++) = val; // copy element
568  }
569 }
570 
571 
572 template<class T, int SizeMin>
573 template<unsigned N>
575 (
576  const FixedList<T, N>& lst
577 )
578 {
579  label idx = List<T>::size();
580  resize(idx + lst.size());
581 
582  for (const T& val : lst)
583  {
584  this->operator[](idx++) = val; // copy element
585  }
586 }
587 
588 
589 template<class T, int SizeMin>
591 (
592  std::initializer_list<T> lst
593 )
594 {
595  label idx = List<T>::size();
596  resize(idx + lst.size());
597 
598  for (const T& val : lst)
599  {
600  this->operator[](idx++) = val; // copy element
601  }
602 }
603 
604 
605 template<class T, int SizeMin>
606 template<class Addr>
608 (
609  const IndirectListBase<T, Addr>& lst
610 )
611 {
612  label idx = List<T>::size();
613  const label n = lst.size();
614 
615  resize(idx + n);
616 
617  for (label i=0; i<n; ++i)
618  {
619  this->operator[](idx++) = lst[i]; // copy element
620  }
621 }
622 
623 
624 template<class T, int SizeMin>
626 (
627  List<T>&& list
628 )
629 {
630  if (this == &list)
631  {
633  << "Attempted push_back to self"
634  << abort(FatalError);
635  }
636 
637  label idx = List<T>::size();
638  resize(idx + list.size());
639 
640  for (T& val : list)
641  {
642  Foam::Swap(this->operator[](idx++), val); // moved content
643  }
644 
645  list.clear();
646 }
647 
648 
649 template<class T, int SizeMin>
650 template<int AnySizeMin>
652 (
654 )
655 {
656  push_back(std::move(static_cast<List<T>&>(list)));
657  list.clearStorage(); // Ensure capacity=0
658 }
659 
660 
661 template<class T, int SizeMin>
662 inline Foam::label Foam::DynamicList<T, SizeMin>::push_uniq(const T& val)
663 {
664  if (this->contains(val))
665  {
666  return 0;
667  }
668  else
669  {
670  this->push_back(val);
671  return 1; // Increased list length by one
672  }
673 }
674 
675 
676 template<class T, int SizeMin>
678 {
679  if (n >= this->size())
680  {
681  clear();
682  }
683  else if (n > 0)
684  {
685  resize(this->size() - n);
686  }
687 }
688 
689 
690 template<class T, int SizeMin>
692 {
693  // Location of last element and simultaneously the new size
694  const label idx = List<T>::size() - 1;
695 
696  if (idx < 0)
697  {
699  << "List is empty" << abort(FatalError);
700  }
701 
702  const T& val = List<T>::operator[](idx);
703 
704  List<T>::setAddressableSize(idx);
706  return val;
707 }
708 
709 
710 template<class T, int SizeMin>
712 (
713  const label idx,
714  const bool fast
715 )
716 {
717  if (fast)
718  {
719  // Simply swap idx <=> last
720  this->swapLast(idx);
721  }
722  else
723  {
724  // Move element to the end and move everything down
725  this->moveLast(idx);
726  }
727 
728  // Element to remove is now at the end
729  return this->remove();
730 }
731 
732 
733 template<class T, int SizeMin>
734 inline Foam::label Foam::DynamicList<T, SizeMin>::remove
735 (
736  const labelRange& range
737 )
738 {
739  return this->removeElements(this->validateRange(range));
740 }
741 
742 
743 template<class T, int SizeMin>
744 inline Foam::label Foam::DynamicList<T, SizeMin>::remove
745 (
746  std::initializer_list<label> start_size
747 )
748 {
749  return this->removeElements(this->validateRange(start_size));
750 }
751 
752 
753 template<class T, int SizeMin>
754 inline Foam::label Foam::DynamicList<T, SizeMin>::subset
755 (
756  const labelRange& range
757 )
758 {
759  return this->subsetElements(this->validateRange(range));
760 }
761 
762 
763 template<class T, int SizeMin>
764 inline Foam::label Foam::DynamicList<T, SizeMin>::subset
765 (
766  std::initializer_list<label> start_size
767 )
768 {
769  return this->subsetElements(this->validateRange(start_size));
770 }
771 
772 
773 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
774 
775 template<class T, int SizeMin>
777 (
778  const label i
779 )
780 {
781  if (i >= List<T>::size())
782  {
783  resize(i + 1);
784  }
786  return this->operator[](i);
787 }
788 
789 
790 template<class T, int SizeMin>
792 (
793  const T& val
794 )
795 {
796  UList<T>::operator=(val);
797 }
798 
799 
800 template<class T, int SizeMin>
802 (
803  const Foam::zero
804 )
805 {
807 }
808 
809 
810 template<class T, int SizeMin>
812 (
813  const UList<T>& lst
814 )
815 {
816  doAssignDynList(lst);
817 }
818 
819 
820 template<class T, int SizeMin>
821 template<unsigned N>
823 (
824  const FixedList<T, N>& lst
825 )
826 {
827  doAssignDynList(lst);
828 }
829 
830 
831 template<class T, int SizeMin>
833 (
834  const DynamicList<T, SizeMin>& lst
835 )
836 {
837  if (this == &lst)
838  {
839  return; // Self-assignment is a no-op
840  }
841 
842  doAssignDynList(lst);
843 }
844 
845 
846 template<class T, int SizeMin>
847 template<int AnySizeMin>
849 (
850  const DynamicList<T, AnySizeMin>& list
851 )
852 {
853  if
854  (
855  static_cast<const List<T>*>(this)
856  == static_cast<const List<T>*>(&list)
857  )
858  {
859  return; // Self-assignment is a no-op
860  }
862  doAssignDynList(list);
863 }
864 
865 
866 template<class T, int SizeMin>
868 (
869  std::initializer_list<T> lst
870 )
871 {
872  doAssignDynList(lst);
873 }
874 
875 
876 template<class T, int SizeMin>
877 template<class Addr>
879 (
880  const IndirectListBase<T, Addr>& lst
881 )
882 {
883  // NOTE: Self-assignment needs special handling
890  doAssignDynList(lst);
891 }
892 
893 
894 template<class T, int SizeMin>
896 (
897  List<T>&& lst
898 )
899 {
900  clear();
901  transfer(lst);
902 }
903 
904 
905 template<class T, int SizeMin>
907 (
909 )
910 {
911  if (this == &lst)
912  {
913  return; // Self-assignment is a no-op
914  }
915 
916  clear();
917  transfer(lst);
918 }
919 
920 
921 template<class T, int SizeMin>
922 template<int AnySizeMin>
924 (
926 )
927 {
928  if
929  (
930  static_cast<const List<T>*>(this)
931  == static_cast<const List<T>*>(&list)
932  )
933  {
934  return; // Self-assignment is a no-op
935  }
936 
937  clear();
938  transfer(list);
939 }
940 
941 
942 // ************************************************************************* //
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:101
label expandStorage() noexcept
Expand the addressable size to fit the allocated capacity.
Definition: DynamicListI.H:404
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:578
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:341
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:51
void resize(const label len)
Alter addressable list size, allocating new space if required while recovering old content...
Definition: DynamicListI.H:351
void setCapacity(const label len)
Alter the size of the underlying storage.
Definition: DynamicListI.H:301
void shrinkStorage()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:416
void pop_back(label n=1)
Reduce size by 1 or more elements. Can be called on an empty list.
Definition: DynamicListI.H:670
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
scalar range
void swap(DynamicList< T, AnySizeMin > &other)
Swap content, independent of sizing parameter.
Definition: DynamicListI.H:442
label capacity() const noexcept
Size of the underlying storage.
Definition: DynamicList.H:219
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:501
std::streamsize capacity_bytes() const noexcept
Number of contiguous bytes of the underlying storage.
Definition: DynamicListI.H:293
patchWriters clear()
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
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:99
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:331
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:321
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:432
void clear() noexcept
Clear the addressed list, i.e. set the size to zero.
Definition: DynamicListI.H:389
const volScalarField & T
void push_back(const T &val)
Copy append an element to the end of this list.
Definition: DynamicListI.H:518
label push_uniq(const T &val)
Append an element if not already in the list.
Definition: DynamicListI.H:655
T remove()
Remove and return the last element. Fatal on an empty list.
Definition: DynamicListI.H:684
void Swap(DynamicList< T, SizeMinA > &a, DynamicList< T, SizeMinB > &b)
Definition: DynamicList.H:659
void transfer(List< T > &list)
Transfer contents of the argument List into this.
Definition: DynamicListI.H:465
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:396
label subset(const labelRange &range)
Retain a (start,size) subset from the list.
Definition: DynamicListI.H:748
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:361
Foam::argList args(argc, argv)
void setCapacity_nocopy(const label len)
Alter the size of the underlying storage, without retaining old content.
Definition: DynamicListI.H:311
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133