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 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 }
107 }
108}
109
110
111// * * * * * * * * * * * * * * * * Constructors * * * * * * * * * * * * * * //
112
113template<class T>
115:
116 storage_(),
117 begin_(0),
118 end_(0)
119{}
120
121
122template<class T>
124:
125 storage_(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>
162{
163 return storage_.size();
164}
165
166
167template<class T>
169{
170 return storage_.empty() || (begin_ == end_);
171}
172
173
174template<class T>
175inline Foam::label Foam::CircularBuffer<T>::size() const noexcept
176{
177 const label diff(end_ - begin_);
178
179 if (diff < 0)
180 {
181 return (storage_.size() + diff);
182 }
183
184 return diff;
185}
186
187
188template<class T>
189inline Foam::label Foam::CircularBuffer<T>::space() const noexcept
190{
191 return (storage_.size() - size());
192}
193
194
195template<class T>
197{
198 return
199 (
200 (begin_ == end_)
201 ? labelRange()
202 : labelRange(begin_, this->size_one())
203 );
204}
205
206
207template<class T>
209{
210 return labelRange(0, this->size_two());
211}
212
213
214template<class T>
216{
217 begin_ = end_ = 0;
218}
219
220
221template<class T>
223{
224 storage_.clear();
225 begin_ = end_ = 0;
226}
227
228
229template<class T>
231{
232 if (this == &other)
233 {
234 return; // Self-swap is a no-op
235 }
236
237 // Swap storage and addressing
238 storage_.swap(other.storage_);
239 std::swap(begin_, other.begin_);
240 std::swap(end_, other.end_);
241}
242
243
244template<class T>
245inline void Foam::CircularBuffer<T>::reserve(const label len)
246{
247 this->doReserve(false, len);
248}
249
250
251template<class T>
252inline void Foam::CircularBuffer<T>::reserve_nocopy(const label len)
253{
254 this->doReserve(true, len);
255}
256
257
258template<class T>
259inline bool Foam::CircularBuffer<T>::found(const T& val, label pos) const
260{
261 return (this->find(val, pos) >= 0);
262}
263
264
265template<class T>
267{
268 if (empty())
269 {
270 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
271 }
272
273 return storage_[begin_];
274}
275
276
277template<class T>
279{
280 if (empty())
281 {
282 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
283 }
284
285 return storage_[begin_];
286}
287
288
289template<class T>
291{
292 if (empty())
293 {
294 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
295 }
296
297 return storage_.rcValue(end_);
298}
299
300
301template<class T>
302inline const T& Foam::CircularBuffer<T>::last() const
303{
304 if (empty())
305 {
306 FatalErrorInFunction << "Buffer is empty" << abort(FatalError);
307 }
308
309 return storage_.rcValue(end_);
310}
311
312
313template<class T>
315{
316 reserve(size() + 2);
317
318 // Never overfilled. Move begin and write
319
320 begin_ = storage_.rcIndex(begin_);
321 storage_[begin_] = val; // copy assign element
322}
323
324
325template<class T>
327{
328 reserve(size() + 2);
329
330 // Never overfilled. Move begin and write
331
332 begin_ = storage_.rcIndex(begin_);
333 storage_[begin_] = std::move(val); // move assign element
334}
335
336
337template<class T>
339{
340 reserve(size() + 2);
341
342 // Never overfilled, simply write at end_ (one-past position)
343
344 storage_[end_] = val; // copy assign element
345 end_ = storage_.fcIndex(end_);
346}
347
348
349template<class T>
351{
352 reserve(size() + 2);
353
354 // Never overfilled, simply write at end_ (one-past position)
355
356 storage_[end_] = std::move(val); // move assign element
357 end_ = storage_.fcIndex(end_);
358}
359
360
361template<class T>
363{
364 if (n >= size())
365 {
366 begin_ = end_;
367 }
368 else
369 {
370 while (n-- > 0)
371 {
372 begin_ = storage_.fcIndex(begin_);
373 }
374 }
375}
376
377
378template<class T>
380{
381 if (n >= size())
382 {
383 end_ = begin_;
384 }
385 else
386 {
387 while (n-- > 0)
388 {
389 end_ = storage_.rcIndex(end_);
390 }
391 }
392}
393
394
395template<class T>
396inline Foam::label Foam::CircularBuffer<T>::appendUniq(const T& val)
397{
398 if (this->found(val))
399 {
400 return 0;
401 }
402 else
403 {
404 this->push_back(val);
405 return 1; // Increased list length by one
406 }
407}
408
409
410template<class T>
412{
413 const label len = rhs.size();
414
415 if (len)
416 {
417 reserve(size() + len + 1);
418
419 // Never overfilled, simply write at end_ (one-past position)
420
421 for (label i = 0; i < len; ++i)
422 {
423 storage_[end_] = rhs[i]; // copy element
424 end_ = storage_.fcIndex(end_);
425 }
426 }
427}
428
429
430template<class T>
431template<class Addr>
433(
435)
436{
437 const label len = rhs.size();
438
439 if (len)
440 {
441 reserve(size() + len + 1);
442
443 // Never overfilled, simply write at end_ (one-past position)
444
445 for (label i = 0; i < len; ++i)
446 {
447 storage_[end_] = rhs[i]; // copy element
448 end_ = storage_.fcIndex(end_);
449 }
450 }
451}
452
453
454// * * * * * * * * * * * * * * * Member Operators * * * * * * * * * * * * * //
455
456template<class T>
458{
459 const label idx = this->toGlobal(i);
460 return storage_[idx];
461}
462
463
464template<class T>
465inline const T& Foam::CircularBuffer<T>::operator[](label i) const
466{
467 const label idx = this->toGlobal(i);
468 return storage_[idx];
469}
470
471
472template<class T>
474{
475 if (this == &rhs)
476 {
477 return; // Self-assignment is a no-op
478 }
479
480 this->clear();
481
482 const auto list1 = rhs.array_one();
483 const auto list2 = rhs.array_two();
484 const label len = (list1.size() + list2.size());
485
486 if (len)
487 {
488 reserve(len + 1);
489
490 // Never overfilled, simply write at end_ (one-past position)
491
492 // - after clear(), begin_ and end_ are both 0
493
494 for (const T& val : list1)
495 {
496 storage_[end_] = val;
497 ++end_;
498 }
499
500 for (const T& val : list2)
501 {
502 storage_[end_] = val;
503 ++end_;
504 }
505 }
506}
507
508
509template<class T>
511{
512 if (this == &rhs)
513 {
514 return; // Self-assignment is a no-op
515 }
516
517 this->clearStorage();
518 this->swap(rhs);
519}
520
521
522template<class T>
524{
525 this->array_one() = val;
526 this->array_two() = val;
527}
528
529
530template<class T>
532{
533 this->array_one() = Zero;
534 this->array_two() = Zero;
535}
536
537
538template<class T>
540{
541 this->copyList(rhs);
542}
543
544
545template<class T>
546template<class AnyAddr>
548(
550)
551{
552 this->copyList(rhs);
553}
554
555
556// ************************************************************************* //
bool found
label n
Y[inertIndex] max(0.0)
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 & first()
Access the first element (front). Requires !empty().
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.
bool empty() const noexcept
Empty or exhausted buffer.
void reserve_nocopy(const label len)
void clearStorage()
Clear the buffer and delete storage.
label appendUniq(const T &val)
Append an element if not already in the buffer.
label capacity() const noexcept
Size of the underlying storage.
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.
SubList< T > array_two()
The contents of the first internal array.
void reserve(const label len)
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
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.
T & last()
Access the last element (back). Requires !empty().
Base for lists with indirect addressing, templated on the list contents type and the addressing type....
label fcIndex(const label i) const
label size() const noexcept
The number of elements in the list.
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:94
void size(const label n)
Older name for setAddressableSize.
Definition: UList.H:114
label fcIndex(const label i) const noexcept
Definition: UListI.H:60
A range or interval of labels defined by a start and a size.
Definition: labelRange.H:58
bool append() const noexcept
True if output format uses an append mode.
A class representing the concept of 0 (zero) that can be used to avoid manipulating objects known to ...
Definition: zero.H:63
const volScalarField & T
patchWriters clear()
#define FatalErrorInFunction
Report an error message using Foam::FatalError.
Definition: error.H:453
dimensionedScalar pos(const dimensionedScalar &ds)
scalar diff(const triad &A, const triad &B)
Return a quantity of the difference between two triads.
Definition: triad.C:378
errorManip< error > abort(error &err)
Definition: errorManip.H:144
static constexpr const zero Zero
Global zero (0)
Definition: zero.H:131
const direction noexcept
Definition: Scalar.H:223
error FatalError