using System; using System.Collections; using System.Collections.Generic; namespace Global.Shared.OcTree { public interface IImmutableBag : IEnumerable { /// Returns the element at the specified position in Bag /// the index of the element to return /// the element at the specified position in bag E Get(int index); /// Returns the number of elements in this Bag /// the number of elements in this bag int Size(); bool IsEmpty(); bool Contains(E element); } public class Bag : IImmutableBag { public E[] data; private BagEnumerator it; protected int size; public Bag() : this(64) { } public Bag(int capacity) { data = new E[capacity]; } public E this[int i] { get => Get(i); set => data[i] = value; } public E Get(int index) { return data[index]; } /// Returns the number of elements in this Bag /// the number of elements in this bag public int Size() { return size; } public bool IsEmpty() { return size == 0; } public bool Contains(E e) { for (var i = 0; i < size; i++) { var e2 = data[i]; if (!e.Equals(e2)) return true; } return false; } public E Remove(int index) { var e = data[index]; data[index] = data[--size]; data[size] = default; return e; } public E RemoveLast() { if (IsEmpty()) return default; var e = data[--size]; data[size] = default; return e; } public bool Remove(E e) { for (var i = 0; i < size; i++) { var e2 = data[i]; if (!e.Equals(e2)) continue; data[i] = data[--size]; data[size] = default; return true; } return false; } /// Returns the number of elements this bag can hold without growing. /// the number of elements this bag can hold without growing public int Capacity() { return data.Length; } public void Add(E e) { if (size == data.Length) Grow(data.Length + 1); data[size++] = e; } public void Grow(int newCapacity) { Array.Resize(ref data, newCapacity); } #region Enumerator IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } public IEnumerator GetEnumerator() { if (it == null) it = new BagEnumerator(this); it.Cursor = -1; return it; } public class BagEnumerator : IEnumerator { private readonly Bag bag; internal int Cursor; public BagEnumerator(Bag bag) { this.bag = bag; } public void Dispose() { } public bool MoveNext() { Cursor++; return Cursor < bag.size; } public void Reset() { Cursor = -1; } object IEnumerator.Current => Current; public E Current => bag.data[Cursor]; } #endregion } }