diff --git a/src/ObservableCollections/ObservableRingBuffer.cs b/src/ObservableCollections/ObservableRingBuffer.cs index 1ab0b5a..a5d6417 100644 --- a/src/ObservableCollections/ObservableRingBuffer.cs +++ b/src/ObservableCollections/ObservableRingBuffer.cs @@ -3,54 +3,41 @@ public sealed partial class ObservableRingBuffer { - // TODO:not yet. - readonly T[] buffer; + readonly RingBuffer buffer; - int head; - int count; + // TODO:SyncRoot - public ObservableRingBuffer(int capacity) + public ObservableRingBuffer() { - this.buffer = new T[capacity]; + this.buffer = new RingBuffer(); } - public int Count => count; + public ObservableRingBuffer(IEnumerable collection) + { + this.buffer = new RingBuffer(collection); + } + + public int Count => buffer.Count; public T this[int index] { get { - var i = (head + index) % buffer.Length; - return this.buffer[i]; + return this.buffer[index]; } set { - + this.buffer[index] = value; } } - public void AddLast() - { - - - // AddLast - // AddFirst - //new LinkedList().remo - //new Stack().Push - } - - public void AddFirst() + public void AddLast(T item) { } - public void RemoveLast() + public void AddLastRange(T[] items) { - } - public void RemoveFirst() - { } - - // GetReverseEnumerable } } diff --git a/src/ObservableCollections/RingBuffer.cs b/src/ObservableCollections/RingBuffer.cs index 4c4c4a3..77eaf2c 100644 --- a/src/ObservableCollections/RingBuffer.cs +++ b/src/ObservableCollections/RingBuffer.cs @@ -26,6 +26,27 @@ namespace ObservableCollections this.mask = buffer.Length - 1; } + public RingBuffer(IEnumerable collection) + { + var array = collection.TryGetNonEnumeratedCount(out var count) + ? new T[CalculateCapacity(count)] + : new T[8]; + var i = 0; + foreach (var item in collection) + { + if (i == array.Length) + { + Array.Resize(ref array, i * 2); + } + array[i++] = item; + } + + this.buffer = array; + this.head = 0; + this.count = i; + this.mask = buffer.Length - 1; + } + static int CalculateCapacity(int size) { size--; @@ -146,7 +167,12 @@ namespace ObservableCollections } } - public IEnumerator GetEnumerator() + public Enumerator GetEnumerator() + { + return new Enumerator(GetSpan()); + } + + IEnumerator IEnumerable.GetEnumerator() { if (count == 0) yield break; @@ -220,17 +246,8 @@ namespace ObservableCollections public int IndexOf(T item) { - var span = GetSpan(); var i = 0; - foreach (var v in span.First) - { - if (EqualityComparer.Default.Equals(item, v)) - { - return i; - } - i++; - } - foreach (var v in span.Second) + foreach (var v in this) { if (EqualityComparer.Default.Equals(item, v)) { @@ -241,6 +258,17 @@ namespace ObservableCollections return -1; } + public T[] ToArray() + { + var result = new T[count]; + var i = 0; + foreach (var item in this) + { + result[i++] = item; + } + return result; + } + void IList.Insert(int index, T item) { throw new NotSupportedException(); @@ -258,7 +286,7 @@ namespace ObservableCollections IEnumerator IEnumerable.GetEnumerator() { - return GetEnumerator(); + return ((IEnumerable)this).GetEnumerator(); } [DoesNotReturn] @@ -266,15 +294,65 @@ namespace ObservableCollections { throw new InvalidOperationException("RingBuffer is empty."); } + + public ref struct Enumerator + { + ReadOnlySpan.Enumerator firstEnumerator; + ReadOnlySpan.Enumerator secondEnumerator; + bool useFirst; + + public Enumerator(RingBufferSpan span) + { + this.firstEnumerator = span.First.GetEnumerator(); + this.secondEnumerator = span.Second.GetEnumerator(); + this.useFirst = true; + } + + public bool MoveNext() + { + if (useFirst) + { + if (firstEnumerator.MoveNext()) + { + return true; + } + else + { + useFirst = false; + } + } + + if (secondEnumerator.MoveNext()) + { + return true; + } + return false; + } + + public T Current + { + get + { + if (useFirst) + { + return firstEnumerator.Current; + } + else + { + return secondEnumerator.Current; + } + } + } + } } public ref struct RingBufferSpan { - public readonly Span First; - public readonly Span Second; + public readonly ReadOnlySpan First; + public readonly ReadOnlySpan Second; public readonly int Count; - public RingBufferSpan(Span first, Span second, int count) + internal RingBufferSpan(ReadOnlySpan first, ReadOnlySpan second, int count) { First = first; Second = second; diff --git a/tests/ObservableCollections.Tests/RingBufferTest.cs b/tests/ObservableCollections.Tests/RingBufferTest.cs index fd2c0f9..04e7b62 100644 --- a/tests/ObservableCollections.Tests/RingBufferTest.cs +++ b/tests/ObservableCollections.Tests/RingBufferTest.cs @@ -11,7 +11,7 @@ namespace ObservableCollections.Tests public class RingBufferTest { [Fact] - public void Foo() + public void All() { var list = new RingBuffer();