namespace Invercargill.DataStructures { public class RingBuffer : Enumerable, Lot, ReadOnlyAddressable, Addressable { private T[] array; private SafeReadFunc? safe_read; private SafeWriteFunc? safe_write; public override Tracker get_tracker () { int pos = 0; return new LambdaTracker (() => array.length > 0, () => safe_read(array, pos++ % array.length)); } public override uint? peek_count () { return null; // Technically infinate if iterated } public override EnumerableInfo get_info () { return new EnumerableInfo.infer_ultimate(this, EnumerableCategory.IN_MEMORY); } public override uint length { get { return array.length; }} public RingBuffer(uint size) { array = new T[size]; safe_read = get_safe_read_function_for(); if(safe_read == null) { safe_read = (a, i) => a[i]; } safe_write = get_safe_write_function_for(); if(safe_write == null) { safe_write = (a, i, v) => a[i] = v; } } public Enumerable once() { return take(array.length); } internal RingBuffer.take_array(owned T[] array) { this.array = (owned)array; safe_read = get_safe_read_function_for(); if(safe_read == null) { safe_read = (a, i) => a[i]; } safe_write = get_safe_write_function_for(); if(safe_write == null) { safe_write = (a, i, v) => a[i] = v; } } public new void set (uint index, T item) throws IndexError { var real_index = index % array.length; safe_write(array, real_index, item); } public new T get (uint index) { var real_index = index % array.length; return safe_read(array, real_index); } public bool try_get (uint index, out T value) { try { value = get(index); return true; } catch { value = null; return false; } } public uint? first_index_of (Invercargill.PredicateDelegate predicate) { var i = 0; foreach (var item in this) { if(predicate(item)) { return i; } i++; } return null; } public override uint count(PredicateDelegate? predicate = null) { if(predicate == null) { return array.length; } return base.take(array.length).count(predicate); } } }