| // Copyright (c) 2021, the Dart project authors. Please see the AUTHORS file | |
| // for details. All rights reserved. Use of this source code is governed by a | |
| // BSD-style license that can be found in the LICENSE file. | |
| import 'dart:math'; | |
| class RingBuffer<T> { | |
| RingBuffer(this._bufferSize) { | |
| _buffer = List<T?>.filled( | |
| _bufferSize, | |
| null, | |
| ); | |
| } | |
| Iterable<T> call() sync* { | |
| for (int i = _size - 1; i >= 0; --i) { | |
| yield _buffer[(_count - i - 1) % _bufferSize]!; | |
| } | |
| } | |
| /// Inserts a new element into the [RingBuffer]. | |
| /// | |
| /// Returns the element evicted as a result of adding the new element if the | |
| /// buffer is as max capacity, null otherwise. | |
| T? add(T element) { | |
| if (_buffer.isEmpty) { | |
| return null; | |
| } | |
| T? evicted; | |
| final index = _count % _bufferSize; | |
| if (index < _count) { | |
| evicted = _buffer[index]; | |
| } | |
| _buffer[index] = element; | |
| _count++; | |
| return evicted; | |
| } | |
| void resize(int size) { | |
| assert(size >= 0); | |
| if (size == _bufferSize) { | |
| return; | |
| } | |
| final resized = List<T?>.filled( | |
| size, | |
| null, | |
| ); | |
| int count = 0; | |
| if (size > 0) { | |
| for (final e in this()) { | |
| resized[count++ % size] = e; | |
| } | |
| } | |
| _count = count; | |
| _bufferSize = size; | |
| _buffer = resized; | |
| } | |
| bool get isTruncated => _count % bufferSize < _count; | |
| int get bufferSize => _bufferSize; | |
| int get _size => min(_count, _bufferSize); | |
| int _bufferSize; | |
| int _count = 0; | |
| late List<T?> _buffer; | |
| } |