List.C
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) 2017-2022 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 "List.H"
30 #include "ListLoopM.H"
31 #include "FixedList.H"
32 #include "PtrList.H"
33 #include "SLList.H"
34 #include "contiguous.H"
35 
36 // * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
37 
38 template<class T>
39 void Foam::List<T>::doResize(const label len)
40 {
41  if (len == this->size_)
42  {
43  return;
44  }
45 
46  if (len > 0)
47  {
48  // With sign-check to avoid spurious -Walloc-size-larger-than
49  const label overlap = min(this->size_, len);
50 
51  if (!overlap)
52  {
53  // Can discard old content before allocating new storage.
54  // - when used as storage for DynamicList, it is possible to have
55  // a zero-sized List with a non-null data pointer.
56 
57  if (this->v_) delete[] this->v_;
58  this->size_ = len;
59  this->v_ = new T[len];
60  }
61  else
62  {
63  // Recover old (overlapping) content when resizing
64 
65  T* nv = new T[len];
66 
67  // ie, std::copy(this->v_, this->v_ + overlap, nv);
68  #ifdef USEMEMCPY
69  if (is_contiguous<T>::value)
70  {
71  std::memcpy
72  (
73  static_cast<void*>(nv), this->v_, overlap*sizeof(T)
74  );
75  }
76  else
77  #endif
78  {
79  List_ACCESS(T, *this, vp);
80  for (label i = 0; i < overlap; ++i)
81  {
82  nv[i] = std::move(vp[i]);
83  }
84  }
85 
86  delete[] this->v_;
87  this->size_ = len;
88  this->v_ = nv;
89  }
90  }
91  else
92  {
93  // Or only #ifdef FULLDEBUG
94  if (len < 0)
95  {
97  << "bad size " << len
98  << abort(FatalError);
99  }
100  // #endif
101 
102  clear();
103  }
104 }
105 
106 
107 // * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * * //
108 
109 template<class T>
110 Foam::List<T>::List(const label len)
111 :
112  UList<T>(nullptr, len)
113 {
114  if (len < 0)
115  {
117  << "bad size " << len
118  << abort(FatalError);
119  }
120 
121  doAlloc();
122 }
123 
124 
125 template<class T>
126 Foam::List<T>::List(const label len, const T& val)
127 :
128  UList<T>(nullptr, len)
129 {
130  if (len < 0)
131  {
133  << "bad size " << len
134  << abort(FatalError);
135  }
136 
137  if (len)
138  {
139  doAlloc();
140 
141  List_ACCESS(T, (*this), vp);
142  for (label i=0; i < len; ++i)
143  {
144  vp[i] = val;
145  }
146  }
147 }
148 
149 
150 template<class T>
151 Foam::List<T>::List(const label len, const Foam::zero)
152 :
153  UList<T>(nullptr, len)
154 {
155  if (len < 0)
156  {
158  << "bad size " << len
159  << abort(FatalError);
160  }
161 
162  if (len)
163  {
164  doAlloc();
165 
166  List_ACCESS(T, (*this), vp);
167  for (label i=0; i < len; ++i)
168  {
169  vp[i] = Zero;
170  }
171  }
172 }
173 
174 
175 template<class T>
176 Foam::List<T>::List(const Foam::one, const T& val)
177 :
178  UList<T>(new T[1], 1)
179 {
180  this->v_[0] = val;
181 }
182 
183 
184 template<class T>
185 Foam::List<T>::List(const Foam::one, T&& val)
186 :
187  UList<T>(new T[1], 1)
188 {
189  this->v_[0] = std::move(val);
190 }
191 
192 
193 template<class T>
195 :
196  UList<T>(new T[1], 1)
197 {
198  this->v_[0] = Zero;
199 }
200 
201 
202 template<class T>
204 :
205  UList<T>(nullptr, a.size_)
206 {
207  const label len = this->size_;
208 
209  if (len)
210  {
211  doAlloc();
212 
213  #ifdef USEMEMCPY
215  {
216  std::memcpy
217  (
218  static_cast<void*>(this->v_), a.v_, this->size_bytes()
219  );
220  }
221  else
222  #endif
223  {
224  List_ACCESS(T, (*this), vp);
225  List_CONST_ACCESS(T, a, ap);
226  for (label i = 0; i < len; ++i)
227  {
228  vp[i] = ap[i];
229  }
230  }
231  }
232 }
233 
234 
235 template<class T>
236 Foam::List<T>::List(const List<T>& a)
237 :
238  UList<T>(nullptr, a.size_)
239 {
240  const label len = this->size_;
241 
242  if (len)
243  {
244  doAlloc();
245 
246  #ifdef USEMEMCPY
247  if (is_contiguous<T>::value)
248  {
249  std::memcpy
250  (
251  static_cast<void*>(this->v_), a.v_, this->size_bytes()
252  );
253  }
254  else
255  #endif
256  {
257  List_ACCESS(T, (*this), vp);
258  List_CONST_ACCESS(T, a, ap);
259  for (label i = 0; i < len; ++i)
260  {
261  vp[i] = ap[i];
262  }
263  }
264  }
265 }
266 
267 
268 template<class T>
269 Foam::List<T>::List(List<T>& a, bool reuse)
270 :
271  UList<T>(nullptr, a.size_)
272 {
273  if (reuse)
274  {
275  // Steal content
276  this->v_ = a.v_;
277  a.v_ = nullptr;
278  a.size_ = 0;
279  return;
280  }
281 
282  const label len = this->size_;
283 
284  if (len)
285  {
286  doAlloc();
287 
288  #ifdef USEMEMCPY
289  if (is_contiguous<T>::value)
290  {
291  std::memcpy
292  (
293  static_cast<void*>(this->v_), a.v_, this->size_bytes()
294  );
295  }
296  else
297  #endif
298  {
299  List_ACCESS(T, (*this), vp);
300  List_CONST_ACCESS(T, a, ap);
301  for (label i = 0; i < len; ++i)
302  {
303  vp[i] = ap[i];
304  }
305  }
306  }
307 }
308 
309 
310 template<class T>
311 Foam::List<T>::List(const UList<T>& list, const labelUList& indices)
312 :
313  UList<T>(nullptr, indices.size())
314 {
315  const label len = indices.size();
316 
317  if (len)
318  {
319  doAlloc();
320 
321  List_ACCESS(T, (*this), vp);
322 
323  for (label i=0; i < len; ++i)
324  {
325  vp[i] = list[indices[i]];
326  }
327  }
328 }
329 
330 
331 template<class T>
332 template<unsigned N>
334 (
335  const UList<T>& list,
336  const FixedList<label,N>& indices
337 )
338 :
339  UList<T>(nullptr, label(N))
340 {
341  const label len = label(N);
342 
343  doAlloc();
344 
345  List_ACCESS(T, (*this), vp);
346 
347  for (label i=0; i < len; ++i)
348  {
349  vp[i] = list[indices[i]];
350  }
351 }
352 
353 
354 template<class T>
355 template<unsigned N>
356 Foam::List<T>::List(const FixedList<T, N>& list)
357 :
358  UList<T>(nullptr, label(N))
359 {
360  doAlloc();
361  copyList(list);
362 }
363 
364 
365 template<class T>
366 Foam::List<T>::List(const PtrList<T>& list)
367 :
368  UList<T>(nullptr, list.size())
369 {
370  doAlloc();
371  copyList(list);
372 }
373 
374 
375 template<class T>
376 Foam::List<T>::List(const SLList<T>& list)
377 :
378  List<T>(list.begin(), list.end(), list.size())
379 {}
380 
381 
382 template<class T>
383 template<class Addr>
385 :
386  UList<T>(nullptr, list.size())
387 {
388  doAlloc();
389  copyList(list);
390 }
391 
392 
393 template<class T>
394 Foam::List<T>::List(std::initializer_list<T> list)
395 :
396  List<T>(list.begin(), list.end(), list.size())
397 {}
398 
399 
400 template<class T>
402 :
403  UList<T>()
404 {
405  // Can use transfer or swap to manage content
406  transfer(list);
407 }
408 
409 
410 template<class T>
411 template<int SizeMin>
413 :
414  UList<T>()
415 {
416  transfer(list);
417 }
418 
419 
420 template<class T>
422 :
423  UList<T>()
424 {
425  operator=(std::move(list));
426 }
427 
428 
429 // * * * * * * * * * * * * * * * Destructor * * * * * * * * * * * * * * * * //
430 
431 template<class T>
433 {
434  if (this->v_)
435  {
436  delete[] this->v_;
437  }
438 }
439 
440 
441 // * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
442 
443 template<class T>
444 void Foam::List<T>::resize(const label len, const T& val)
445 {
446  label idx = this->size_;
447  this->doResize(len);
448 
449  List_ACCESS(T, *this, vp);
450  while (idx < len)
451  {
452  vp[idx] = val;
453  ++idx;
454  }
455 }
456 
457 
458 template<class T>
459 void Foam::List<T>::transfer(List<T>& list)
460 {
461  if (this == &list)
462  {
463  return; // Self-assignment is a no-op
464  }
465 
466  // Clear and swap - could also check for self assignment
467  clear();
468  this->size_ = list.size_;
469  this->v_ = list.v_;
470 
471  list.size_ = 0;
472  list.v_ = nullptr;
473 }
474 
475 
476 template<class T>
477 template<int SizeMin>
479 {
480  // Shrink the allocated space to the number of elements used
481  list.shrink();
482  transfer(static_cast<List<T>&>(list));
483 
484  // Ensure DynamicList has proper capacity=0 too
485  list.clearStorage();
486 }
487 
488 
489 // * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
490 
491 template<class T>
492 void Foam::List<T>::operator=(const UList<T>& a)
493 {
494  if (this == &a)
495  {
496  return; // Self-assignment is a no-op
497  }
498 
499  reAlloc(a.size_);
500 
501  const label len = this->size_;
502 
503  if (len)
504  {
505  #ifdef USEMEMCPY
506  if (is_contiguous<T>::value)
507  {
508  std::memcpy
509  (
510  static_cast<void*>(this->v_), a.v_, this->size_bytes()
511  );
512  }
513  else
514  #endif
515  {
516  List_ACCESS(T, (*this), vp);
517  List_CONST_ACCESS(T, a, ap);
518  for (label i = 0; i < len; ++i)
519  {
520  vp[i] = ap[i];
521  }
522  }
523  }
524 }
525 
526 
527 template<class T>
528 void Foam::List<T>::operator=(const List<T>& list)
529 {
530  if (this == &list)
531  {
532  return; // Self-assignment is a no-op
533  }
534 
535  operator=(static_cast<const UList<T>&>(list));
536 }
537 
538 
539 template<class T>
540 void Foam::List<T>::operator=(const SLList<T>& list)
541 {
542  const label len = list.size();
543 
544  reAlloc(len);
545 
546  if (len)
547  {
548  T* iter = this->begin();
549 
550  for (const T& val : list)
551  {
552  *iter = val;
553  ++iter;
554  }
555  }
556 }
557 
558 
559 template<class T>
560 template<unsigned N>
561 void Foam::List<T>::operator=(const FixedList<T, N>& list)
562 {
563  reAlloc(static_cast<label>(N));
564 
565  T* iter = this->begin();
566 
567  for (const T& val : list)
568  {
569  *iter = val;
570  ++iter;
571  }
572 }
573 
574 
575 template<class T>
576 template<class Addr>
577 void Foam::List<T>::operator=(const IndirectListBase<T, Addr>& list)
578 {
579  const label len = list.size();
580 
581  reAlloc(len);
582 
583  if (len)
584  {
585  List_ACCESS(T, (*this), vp);
586 
587  for (label i=0; i < len; ++i)
588  {
589  vp[i] = list[i];
590  }
591  }
592 }
593 
594 
595 template<class T>
596 void Foam::List<T>::operator=(std::initializer_list<T> list)
597 {
598  const label len = list.size();
599 
600  reAlloc(len);
601 
602  if (len)
603  {
604  T* iter = this->begin();
605 
606  for (const T& val : list)
607  {
608  *iter = val;
609  ++iter;
610  }
611  }
612 }
613 
614 
615 template<class T>
616 void Foam::List<T>::operator=(List<T>&& list)
617 {
618  if (this == &list)
619  {
620  return; // Self-assignment is a no-op
621  }
623  transfer(list);
624 }
625 
626 
627 template<class T>
628 template<int SizeMin>
630 {
631  transfer(list);
632 }
633 
634 
635 template<class T>
637 {
638  label len = list.size();
639 
640  reAlloc(len);
641 
642  for (T* iter = this->begin(); len--; ++iter)
643  {
644  *iter = std::move(list.removeHead());
645  }
646 
647  list.clear();
648 }
649 
650 
651 // * * * * * * * * * * * * * * * Global Functions * * * * * * * * * * * * * //
652 
653 template<class T>
655 (
656  const UList<T>& list
657 )
658 {
659  labelList order;
660  Foam::sortedOrder(list, order, typename UList<T>::less(list));
661  return order;
662 }
663 
664 
665 template<class T>
667 (
668  const UList<T>& list,
669  labelList& order
670 )
671 {
672  Foam::sortedOrder(list, order, typename UList<T>::less(list));
673 }
674 
675 
676 template<class T, class ListComparePredicate>
678 (
679  const UList<T>& list,
680  labelList& order,
681  const ListComparePredicate& comp
682 )
683 {
684  // List lengths must be identical. Old content is overwritten
685  order.resize_nocopy(list.size());
686 
687  // Same as std::iota and ListOps::identity
688  label value = 0;
689  for (label& item : order)
690  {
691  item = value;
692  ++value;
693  }
694 
695  Foam::stableSort(order, comp);
696 }
697 
698 
699 // ************************************************************************* //
#define List_CONST_ACCESS(type, f, fp)
Definition: ListLoopM.H:37
void resize(const label len)
Adjust allocated size of list.
Definition: ListI.H:132
void transfer(List< T > &list)
Transfer the contents of the argument List into this list and annul the argument list.
Definition: List.C:452
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
labelList sortedOrder(const UList< T > &input)
Return the (stable) sort order for the list.
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
Template class for non-intrusive linked lists.
Definition: LList.H:46
~List()
Destructor.
Definition: List.C:425
void resize_nocopy(const label len)
Adjust allocated size of list without necessarily.
Definition: ListI.H:139
void stableSort(UList< T > &list)
Stable sort the list.
Definition: UList.C:362
void operator=(const UList< T > &a)
Assignment to UList operator. Takes linear time.
Definition: List.C:485
Base for lists with indirect addressing, templated on the list contents type and the addressing type...
UList< label > labelUList
A UList of labels.
Definition: UList.H:78
A 1D vector of objects of type <T> that resizes itself as necessary to accept the new objects...
Definition: DynamicList.H:51
const cellCellStencilObject & overlap
Definition: correctPhi.H:57
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
Macros for accessing List elements.
DynamicList< T, SizeMin > & shrink()
Shrink the allocated space to the number of elements used.
Definition: DynamicListI.H:432
constexpr auto end(C &c) -> decltype(c.end())
Return iterator to the end of the container c.
Definition: stdFoam.H:194
#define List_ACCESS(type, f, fp)
Definition: ListLoopM.H:33
const volScalarField & T
const Vector< label > N(dict.get< Vector< label >>("N"))
A list of pointers to objects of type <T>, with allocation/deallocation management of the pointers...
Definition: List.H:55
A template class to specify that a data type can be considered as being contiguous in memory...
Definition: contiguous.H:70
void clearStorage()
Clear the list and delete storage.
Definition: DynamicListI.H:396
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:57
List< label > labelList
A List of labels.
Definition: List.H:62
Non-intrusive singly-linked list.
constexpr auto begin(C &c) -> decltype(c.begin())
Return iterator to the beginning of the container c.
Definition: stdFoam.H:161
constexpr List() noexcept
Default construct.
Definition: ListI.H:88
A list compare binary predicate for normal sort.
Definition: UList.H:226
A class representing the concept of 1 (one) that can be used to avoid manipulating objects known to b...
Definition: one.H:56
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:133