| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313 | using System;using UnityEngine;namespace IngameDebugConsole{	public class CircularBuffer<T>	{		private readonly T[] array;		private int startIndex;		public int Count { get; private set; }		public T this[int index] { get { return array[( startIndex + index ) % array.Length]; } }		public CircularBuffer( int capacity )		{			array = new T[capacity];		}		// Old elements are overwritten when capacity is reached		public void Add( T value )		{			if( Count < array.Length )				array[Count++] = value;			else			{				array[startIndex] = value;				if( ++startIndex >= array.Length )					startIndex = 0;			}		}        public T[] ToArray()        {            T[] result = new T[Count];            for (int i = 0; i < Count; i++)                result[i] = this[i];            return result;        }	}	public class DynamicCircularBuffer<T>	{		private T[] array;		private int startIndex;		public int Count { get; private set; }		public int Capacity { get { return array.Length; } }		public T this[int index]		{			get { return array[( startIndex + index ) % array.Length]; }			set { array[( startIndex + index ) % array.Length] = value; }		}		public DynamicCircularBuffer( int initialCapacity = 2 )		{			array = new T[initialCapacity];		}		private void SetCapacity( int capacity )		{			T[] newArray = new T[capacity];			if( Count > 0 )			{				int elementsBeforeWrap = Mathf.Min( Count, array.Length - startIndex );				Array.Copy( array, startIndex, newArray, 0, elementsBeforeWrap );				if( elementsBeforeWrap < Count )					Array.Copy( array, 0, newArray, elementsBeforeWrap, Count - elementsBeforeWrap );			}			array = newArray;			startIndex = 0;		}		/// <summary>Inserts the value to the beginning of the collection.</summary>		public void AddFirst( T value )		{			if( array.Length == Count )				SetCapacity( Mathf.Max( array.Length * 2, 4 ) );			startIndex = ( startIndex > 0 ) ? ( startIndex - 1 ) : ( array.Length - 1 );			array[startIndex] = value;			Count++;		}		/// <summary>Adds the value to the end of the collection.</summary>		public void Add( T value )		{			if( array.Length == Count )				SetCapacity( Mathf.Max( array.Length * 2, 4 ) );			this[Count++] = value;		}		public void AddRange( DynamicCircularBuffer<T> other )		{			if( other.Count == 0 )				return;			if( array.Length < Count + other.Count )				SetCapacity( Mathf.Max( array.Length * 2, Count + other.Count ) );			int insertStartIndex = ( startIndex + Count ) % array.Length;			int elementsBeforeWrap = Mathf.Min( other.Count, array.Length - insertStartIndex );			int otherElementsBeforeWrap = Mathf.Min( other.Count, other.array.Length - other.startIndex );			Array.Copy( other.array, other.startIndex, array, insertStartIndex, Mathf.Min( elementsBeforeWrap, otherElementsBeforeWrap ) );			if( elementsBeforeWrap < otherElementsBeforeWrap ) // This array wrapped before the other array				Array.Copy( other.array, other.startIndex + elementsBeforeWrap, array, 0, otherElementsBeforeWrap - elementsBeforeWrap );			else if( elementsBeforeWrap > otherElementsBeforeWrap ) // The other array wrapped before this array				Array.Copy( other.array, 0, array, insertStartIndex + otherElementsBeforeWrap, elementsBeforeWrap - otherElementsBeforeWrap );			int copiedElements = Mathf.Max( elementsBeforeWrap, otherElementsBeforeWrap );			if( copiedElements < other.Count ) // Both arrays wrapped and there's still some elements left to copy				Array.Copy( other.array, copiedElements - otherElementsBeforeWrap, array, copiedElements - elementsBeforeWrap, other.Count - copiedElements );			Count += other.Count;		}		public T RemoveFirst()		{			T element = array[startIndex];			array[startIndex] = default( T );			if( ++startIndex == array.Length )				startIndex = 0;			Count--;			return element;		}		public T RemoveLast()		{			int index = ( startIndex + Count - 1 ) % array.Length;			T element = array[index];			array[index] = default( T );			Count--;			return element;		}		public int RemoveAll( Predicate<T> shouldRemoveElement )		{			return RemoveAll<T>( shouldRemoveElement, null, null );		}		public int RemoveAll<Y>( Predicate<T> shouldRemoveElement, Action<T, int> onElementIndexChanged, DynamicCircularBuffer<Y> synchronizedBuffer )		{			Y[] synchronizedArray = ( synchronizedBuffer != null ) ? synchronizedBuffer.array : null;			int elementsBeforeWrap = Mathf.Min( Count, array.Length - startIndex );			int removedElements = 0;			int i = startIndex, newIndex = startIndex, endIndex = startIndex + elementsBeforeWrap;			for( ; i < endIndex; i++ )			{				if( shouldRemoveElement( array[i] ) )					removedElements++;				else				{					if( removedElements > 0 )					{						T element = array[i];						array[newIndex] = element;						if( synchronizedArray != null )							synchronizedArray[newIndex] = synchronizedArray[i];						if( onElementIndexChanged != null )							onElementIndexChanged( element, newIndex - startIndex );					}					newIndex++;				}			}			i = 0;			endIndex = Count - elementsBeforeWrap;			if( newIndex < array.Length )			{				for( ; i < endIndex; i++ )				{					if( shouldRemoveElement( array[i] ) )						removedElements++;					else					{						T element = array[i];						array[newIndex] = element;						if( synchronizedArray != null )							synchronizedArray[newIndex] = synchronizedArray[i];						if( onElementIndexChanged != null )							onElementIndexChanged( element, newIndex - startIndex );						if( ++newIndex == array.Length )						{							i++;							break;						}					}				}			}			if( newIndex == array.Length )			{				newIndex = 0;				for( ; i < endIndex; i++ )				{					if( shouldRemoveElement( array[i] ) )						removedElements++;					else					{						if( removedElements > 0 )						{							T element = array[i];							array[newIndex] = element;							if( synchronizedArray != null )								synchronizedArray[newIndex] = synchronizedArray[i];							if( onElementIndexChanged != null )								onElementIndexChanged( element, newIndex + elementsBeforeWrap );						}						newIndex++;					}				}			}			TrimEnd( removedElements );			if( synchronizedBuffer != null )				synchronizedBuffer.TrimEnd( removedElements );			return removedElements;		}		public void TrimStart( int trimCount, Action<T> perElementCallback = null )		{			TrimInternal( trimCount, startIndex, perElementCallback );			startIndex = ( startIndex + trimCount ) % array.Length;		}		public void TrimEnd( int trimCount, Action<T> perElementCallback = null )		{			TrimInternal( trimCount, ( startIndex + Count - trimCount ) % array.Length, perElementCallback );		}		private void TrimInternal( int trimCount, int startIndex, Action<T> perElementCallback )		{			int elementsBeforeWrap = Mathf.Min( trimCount, array.Length - startIndex );			if( perElementCallback == null )			{				Array.Clear( array, startIndex, elementsBeforeWrap );				if( elementsBeforeWrap < trimCount )					Array.Clear( array, 0, trimCount - elementsBeforeWrap );			}			else			{				for( int i = startIndex, endIndex = startIndex + elementsBeforeWrap; i < endIndex; i++ )				{					perElementCallback( array[i] );					array[i] = default( T );				}				for( int i = 0, endIndex = trimCount - elementsBeforeWrap; i < endIndex; i++ )				{					perElementCallback( array[i] );					array[i] = default( T );				}			}			Count -= trimCount;		}		public void Clear()		{			int elementsBeforeWrap = Mathf.Min( Count, array.Length - startIndex );			Array.Clear( array, startIndex, elementsBeforeWrap );			if( elementsBeforeWrap < Count )				Array.Clear( array, 0, Count - elementsBeforeWrap );			startIndex = 0;			Count = 0;		}		public int IndexOf( T value )		{			int elementsBeforeWrap = Mathf.Min( Count, array.Length - startIndex );			int index = Array.IndexOf( array, value, startIndex, elementsBeforeWrap );			if( index >= 0 )				return index - startIndex;			if( elementsBeforeWrap < Count )			{				index = Array.IndexOf( array, value, 0, Count - elementsBeforeWrap );				if( index >= 0 )					return index + elementsBeforeWrap;			}			return -1;		}		public void ForEach( Action<T> action )		{			int elementsBeforeWrap = Mathf.Min( Count, array.Length - startIndex );			for( int i = startIndex, endIndex = startIndex + elementsBeforeWrap; i < endIndex; i++ )				action( array[i] );			for( int i = 0, endIndex = Count - elementsBeforeWrap; i < endIndex; i++ )				action( array[i] );		}	}}
 |