Loading...
Searching...
No Matches
CircularBufferI.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) 2022-2025 OpenCFD Ltd.
9-------------------------------------------------------------------------------
10License
11 This file is part of OpenFOAM.
12
13 OpenFOAM is free software: you can redistribute it and/or modify it
14 under the terms of the GNU General Public License as published by
15 the Free Software Foundation, either version 3 of the License, or
16 (at your option) any later version.
17
18 OpenFOAM is distributed in the hope that it will be useful, but WITHOUT
19 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
20 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
21 for more details.
22
23 You should have received a copy of the GNU General Public License
24 along with OpenFOAM. If not, see <http://www.gnu.org/licenses/>.
25
26\*---------------------------------------------------------------------------*/
27
28// * * * * * * * * * * * * * Private Member Functions * * * * * * * * * * * //
29
30template<class T>
31inline Foam::label Foam::CircularBuffer<T>::toGlobal(label i) const
32{
33 const label len = this->size();
34
35 if (!len)
36 {
37 // Bounds error
38 return -1;
39 }
40 else if (i < 0)
41 {
42 // Wrap any number of times
43 while (i < 0) i += len;
44 }
45 else
46 {
47 // Wrap any number of times
48 while (i >= len) i -= len;
49 }
50
51 i += begin_;
52
53 if (i >= storage_.size())
54 {
55 i -= storage_.size();
56 }
57
58 return i;
59}
60
61
62template<class T>
63inline Foam::label Foam::CircularBuffer<T>::size_one() const noexcept
64{
65 return
66 (
67 (end_ >= begin_)
68 ? (end_ - begin_)
69 : (storage_.size() - begin_)
70 );
71}
72
73
74template<class T>
75inline Foam::label Foam::CircularBuffer<T>::size_two() const noexcept
76{
77 return
78 (
79 (end_ && end_ < begin_)
80 ? end_
81 : static_cast<label>(0)
82 );
83}
84
85
86template<class T>
87template<class OtherListType>
88inline void Foam::CircularBuffer<T>::copyList(const OtherListType& rhs)
89{
90 this->clear();
91
92 const label len = rhs.size();
93
94 if (len)
95 {
96 reserve(len + 1);
97
98 // Never overfilled, simply write at end_ (one-past position)
99
100 // - after clear(), begin_ and end_ are both 0
101
102 for (label i = 0; i < len; ++i)
103 {
104 storage_[end_] = rhs[i]; // copy element
105 ++end_;
106 }
108}
109
110
111// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
112
113template<class T>
114inline constexpr Foam::CircularBuffer<T>::CircularBuffer() noexcept
115:
116 storage_(),
117 begin_(0),
118 end_(0)
119{}
120
121
122template<class T>
123inline Foam::CircularBuffer<T>::CircularBuffer(const label len)
124:
125 storage_(Foam::max(min_size(), len+1)),
126 begin_(0),
127 end_(0)
128{}
129
130
131template<class T>
133(
134 const CircularBuffer<T>& list
135)
136:
137 storage_(list.storage_),
138 begin_(list.begin_),
139 end_(list.end_)
140{}
141
142
143template<class T>
145(
146 CircularBuffer<T>&& list
147)
148:
149 storage_(std::move(list.storage_)),
150 begin_(list.begin_),
151 end_(list.end_)
152{
153 list.begin_ = 0;
154 list.end_ = 0;
155}
156
157
158// * * * * * * * * * * * * * * * Member Functions * * * * * * * * * * * * * //
159
160template<class T>
161inline Foam::label Foam::CircularBuffer<T>::capacity() const noexcept
163 // or storage_.capacity();
164 return storage_.size();
165}
166
167
168template<class T>
170{
171 return storage_.empty() || (begin_ == end_);
172}
173
174
175template<class T>
176inline Foam::label Foam::CircularBuffer<T>::size() const noexcept
177{
178 const label diff(end_ - begin_);
179
180 if (diff < 0)
181 {
182 return (storage_.size() + diff);
184
185 return diff;
186}
187
188
189template<class T>
190inline Foam::label Foam::CircularBuffer<T>::space() const noexcept
191{
192 return (storage_.size() - size());
193}
194
195
196template<class T>
198{
199 return
200 (
201 (begin_ == end_)
203 : labelRange(begin_, this->size_one())
204 );
205}
206
207
208template<class T>
210{
211 return labelRange(0, this->size_two());
212}
213
214
215template<class T>
218 begin_ = end_ = 0;
219}
220
221
222template<class T>
225 storage_.clear();
226 begin_ = end_ = 0;
227}
228
229
230template<class T>
232{
233 if (this == &other)
234 {
235 return; // Self-swap is a no-op
236 }
237
238 // Swap storage and addressing
239 storage_.swap(other.storage_);
240 std::swap(begin_, other.begin_);
241 std::swap(end_, other.end_);
242}
243
244
245template<class T>
246inline void Foam::CircularBuffer<T>::reserve(const label len)
247{
248 this->doReserve(false, len);
249}
250
251
252template<class T>
253inline void Foam::CircularBuffer<T>::reserve_nocopy(const label len)
254{
255 this->doReserve(true, len);
256}
258
259template<class T>
261{
262 return (this->array_one().contains(val) || this->array_two().contains(val));
263}
264
265
266template<class T>
267inline bool Foam::CircularBuffer<T>::contains(const T& val, label pos) const
268{
269 return (this->find(val, pos) >= 0);
270}
272
273template<class T>
275{
276 if (empty())
277 {
278 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
280
281 return storage_[begin_];
282}
283
284
285template<class T>
286inline const T& Foam::CircularBuffer<T>::front() const
287{
288 if (empty())
289 {
290 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
292
293 return storage_[begin_];
294}
295
296
297template<class T>
299{
300 if (empty())
301 {
302 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
304
305 return storage_.rcValue(end_);
306}
307
308
309template<class T>
310inline const T& Foam::CircularBuffer<T>::back() const
311{
312 if (empty())
313 {
314 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
316
317 return storage_.rcValue(end_);
318}
319
320
321template<class T>
322inline void Foam::CircularBuffer<T>::push_front(const T& val)
323{
324 reserve(size() + 2);
325
326 // Never overfilled. Move begin and write
328 begin_ = storage_.rcIndex(begin_);
329 storage_[begin_] = val; // copy assign element
330}
331
332
333template<class T>
334inline void Foam::CircularBuffer<T>::push_front(T&& val)
336 reserve(size() + 2);
337
338 // Never overfilled. Move begin and write
339
340 begin_ = storage_.rcIndex(begin_);
341 storage_[begin_] = std::move(val); // move assign element
342}
344
345template<class T>
346template<class... Args>
349 reserve(size() + 2);
350
351 // Never overfilled. Move begin and write
352
353 begin_ = storage_.rcIndex(begin_);
354 storage_[begin_] = T(std::forward<Args>(args)...);
355
356 return storage_[begin_];
357}
359
360template<class T>
361inline void Foam::CircularBuffer<T>::push_back(const T& val)
362{
363 reserve(size() + 2);
364
365 // Never overfilled, simply write at end_ (one-past position)
367 storage_[end_] = val; // copy assign element
368 end_ = storage_.fcIndex(end_);
369}
370
371
372template<class T>
373inline void Foam::CircularBuffer<T>::push_back(T&& val)
374{
375 reserve(size() + 2);
376
377 // Never overfilled, simply write at end_ (one-past position)
378
379 storage_[end_] = std::move(val); // move assign element
380 end_ = storage_.fcIndex(end_);
381}
382
383
384template<class T>
385template<class... Args>
387{
388 reserve(size() + 2);
389
390 // Never overfilled, simply write at end_ (one-past position)
391
392 const label backIndex = end_;
393 storage_[end_] = T(std::forward<Args>(args)...);
394 end_ = storage_.fcIndex(end_);
395
396 return storage_[backIndex];
397}
398
399
400template<class T>
401inline void Foam::CircularBuffer<T>::pop_front(label n)
402{
403 if (n >= size())
405 begin_ = end_;
406 }
407 else
408 {
409 while (n-- > 0)
410 {
411 begin_ = storage_.fcIndex(begin_);
412 }
413 }
414}
415
416
417template<class T>
418inline void Foam::CircularBuffer<T>::pop_back(label n)
419{
420 if (n >= size())
422 end_ = begin_;
423 }
424 else
425 {
426 while (n-- > 0)
427 {
428 end_ = storage_.rcIndex(end_);
429 }
430 }
432
433
434template<class T>
435inline Foam::label Foam::CircularBuffer<T>::push_uniq(const T& val)
436{
437 if (this->contains(val))
438 {
439 return 0;
440 }
441 else
442 {
443 this->push_back(val);
444 return 1; // Increased list length by one
445 }
446}
447
448
449template<class T>
451{
452 const label len = rhs.size();
453
454 if (len)
455 {
456 reserve(size() + len + 1);
457
458 // Never overfilled, simply write at end_ (one-past position)
459
460 for (label i = 0; i < len; ++i)
461 {
462 storage_[end_] = rhs[i]; // copy element
463 end_ = storage_.fcIndex(end_);
465 }
466}
467
468
469template<class T>
470template<class Addr>
472(
474)
475{
476 const label len = rhs.size();
477
478 if (len)
479 {
480 reserve(size() + len + 1);
481
482 // Never overfilled, simply write at end_ (one-past position)
483
484 for (label i = 0; i < len; ++i)
486 storage_[end_] = rhs[i]; // copy element
487 end_ = storage_.fcIndex(end_);
488 }
490}
491
492
493// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
494
495template<class T>
498 const label idx = this->toGlobal(i);
499 return storage_[idx];
500}
501
502
503template<class T>
504inline const T& Foam::CircularBuffer<T>::operator[](label i) const
506 const label idx = this->toGlobal(i);
507 return storage_[idx];
508}
509
510
511template<class T>
513{
514 if (this == &rhs)
515 {
516 return; // Self-assignment is a no-op
517 }
518
519 this->clear();
520
521 const auto list1 = rhs.array_one();
522 const auto list2 = rhs.array_two();
523 const label len = (list1.size() + list2.size());
524
525 if (len)
526 {
527 reserve(len + 1);
528
529 // Never overfilled, simply write at end_ (one-past position)
530
531 // - after clear(), begin_ and end_ are both 0
532
533 for (const T& val : list1)
534 {
535 storage_[end_] = val;
536 ++end_;
537 }
538
539 for (const T& val : list2)
540 {
541 storage_[end_] = val;
542 ++end_;
543 }
544 }
545}
546
547
548template<class T>
550{
551 if (this == &rhs)
552 {
553 return; // Self-assignment is a no-op
554 }
556 this->clearStorage();
557 this->swap(rhs);
558}
559
560
561template<class T>
562inline void Foam::CircularBuffer<T>::operator=(const T& val)
564 this->array_one() = val;
565 this->array_two() = val;
566}
567
568
569template<class T>
572 this->array_one() = Foam::zero{};
573 this->array_two() = Foam::zero{};
574}
575
576
577template<class T>
580 this->copyList(rhs);
581}
582
583
584template<class T>
585template<class AnyAddr>
587(
589)
590{
591 this->copyList(rhs);
592}
593
594
595// ************************************************************************* //
label n
A simple list of objects of type <T> that is intended to be used as a circular buffer (eg,...
void pop_front(label n=1)
Shrink by moving the front of the buffer 1 or more times.
void clear() noexcept
Clear the addressed buffer, does not change allocation.
labelRange range_one() const noexcept
The addressing range covered by array_one().
T & emplace_front(Args &&... args)
Construct an element at the front of the buffer, return reference to the new element.
void pop_back(label n=1)
Shrink by moving the end of the buffer 1 or more times.
constexpr CircularBuffer() noexcept
Default construct, empty buffer without allocation.
T & emplace_back(Args &&... args)
Construct an element at the end of the buffer, return reference to the new element.
bool empty() const noexcept
Empty or exhausted buffer.
bool contains(const T &val) const
True if the value is contained in the list.
void reserve_nocopy(const label len)
Reserve allocation space for at least this size, allocating new space if required without retaining o...
T & back()
Access the last element (back). Requires !empty().
void clearStorage()
Clear the buffer and delete storage.
label push_uniq(const T &val)
Append an element if not already in the buffer.
label capacity() const noexcept
Size of the underlying storage.
label find(const writeData *&val, label pos=0) const
label size() const noexcept
The current number of buffer items.
void push_back(const T &val)
Copy append an element to the end of the buffer.
T & front()
Access the first element (front). Requires !empty().
static constexpr label min_size() noexcept
Lower capacity limit.
SubList< T > array_two()
The contents of the second internal array.
List< T > list() const
Return a copy of the buffer flattened into a single List. Use sparingly!
void reserve(const label len)
Reserve allocation space for at least this size, allocating new space if required and retaining old c...
labelRange range_two() const noexcept
The addressing range covered by array_two().
void swap(CircularBuffer< T > &other)
Swap content, independent of sizing parameter.
label space() const noexcept
The nominal space available to fill. Subtract 1 for the number to append before re-balancing is neede...
void push_front(const T &val)
Copy prepend an element to the front of the buffer.
void operator=(const CircularBuffer< T > &list)
Copy construct.
SubList< T > array_one()
The contents of the first internal array.
T & operator[](const label i)
Non-const access to an element in the list.
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
A 1D vector of objects of type <T>, where the size of the vector is known and can be used for subscri...
Definition UList.H:89
A range or interval of labels defined by a start and a size.
Definition labelRange.H:66
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition zero.H:58
const volScalarField & T
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition error.H:600
surface1 clear()
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
Namespace for OpenFOAM.
dimensionedScalar pos(const dimensionedScalar &ds)
label max(const labelHashSet &set, label maxValue=labelMin)
Find the max value in labelHashSet, optionally limited by second argument.
Definition hashSets.C:40
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition triad.C:373
errorManip< error > abort(error &err)
Definition errorManip.H:139
void rhs(fvMatrix< typename Expr::value_type > &m, const Expr &expression)
const direction noexcept
Definition scalarImpl.H:265
error FatalError
Error stream (stdout output on all processes), with additional 'FOAM FATAL ERROR' header text and sta...
void T(FieldField< Field, Type > &f1, const FieldField< Field, Type > &f2)
triangles reserve(surf.size())
Foam::argList args(argc, argv)