using System; using System.Collections; using System.Collections.Generic; namespace NitroxModel.DataStructures; /// /// Given a fixed size, fills to capacity and then overwrites earliest item. /// public class CircularBuffer : IList { private readonly List data; private readonly int maxSize; /// /// Returns the index last changed. If is empty, returns -1. /// public int LastChangedIndex { get; protected set; } = -1; /// /// Gets the item at the index, wrapping around the buffer if out-of-range. /// public T this[int index] { // Proper modulus operator which C# doesn't have. % = remainder operator and doesn't work in reverse for negative numbers. get => data[Math.Abs((index % data.Count + data.Count) % data.Count)]; set => throw new NotSupportedException(); } public int Count => data.Count; public bool IsReadOnly => false; public CircularBuffer(int maxSize, int initialCapacity = 0) { if (maxSize < 0) throw new ArgumentOutOfRangeException(nameof(maxSize), "Max size must be larger than -1"); this.maxSize = maxSize; data = new List(Math.Max(0, Math.Min(initialCapacity, maxSize))); } public int IndexOf(T item) { return data.IndexOf(item); } public void Insert(int index, T item) { throw new NotImplementedException(); } public void RemoveAt(int index) { data.RemoveAt(index); } public bool Remove(T item) { return data.Remove(item); } public void Add(T item) { if (maxSize == 0) return; if (data.Count < maxSize) { data.Add(item); LastChangedIndex++; return; } LastChangedIndex = (LastChangedIndex + 1) % maxSize; data[LastChangedIndex] = item; } public void AddRange(IEnumerable items) { foreach (T item in items) Add(item); } public void AddRange(params T[] items) { foreach (T item in items) Add(item); } public void Clear() { data.Clear(); LastChangedIndex = -1; } public bool Contains(T item) { return data.Contains(item); } public void CopyTo(T[] array, int arrayIndex) { data.CopyTo(array, arrayIndex); } public IEnumerator GetEnumerator() { return data.GetEnumerator(); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }