This commit is contained in:
neuecc 2021-08-19 19:36:30 +09:00
parent 6fa62a2761
commit eec98af604
3 changed files with 108 additions and 43 deletions

View File

@ -3,54 +3,41 @@
public sealed partial class ObservableRingBuffer<T> public sealed partial class ObservableRingBuffer<T>
{ {
// TODO:not yet. readonly RingBuffer<T> buffer;
readonly T[] buffer;
int head; // TODO:SyncRoot
int count;
public ObservableRingBuffer(int capacity) public ObservableRingBuffer()
{ {
this.buffer = new T[capacity]; this.buffer = new RingBuffer<T>();
} }
public int Count => count; public ObservableRingBuffer(IEnumerable<T> collection)
{
this.buffer = new RingBuffer<T>(collection);
}
public int Count => buffer.Count;
public T this[int index] public T this[int index]
{ {
get get
{ {
var i = (head + index) % buffer.Length; return this.buffer[index];
return this.buffer[i];
} }
set set
{ {
this.buffer[index] = value;
} }
} }
public void AddLast() public void AddLast(T item)
{
// AddLast
// AddFirst
//new LinkedList<int>().remo
//new Stack<int>().Push
}
public void AddFirst()
{ {
} }
public void RemoveLast() public void AddLastRange(T[] items)
{ {
}
public void RemoveFirst()
{
} }
// GetReverseEnumerable
} }
} }

View File

@ -26,6 +26,27 @@ namespace ObservableCollections
this.mask = buffer.Length - 1; this.mask = buffer.Length - 1;
} }
public RingBuffer(IEnumerable<T> 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) static int CalculateCapacity(int size)
{ {
size--; size--;
@ -146,7 +167,12 @@ namespace ObservableCollections
} }
} }
public IEnumerator<T> GetEnumerator() public Enumerator GetEnumerator()
{
return new Enumerator(GetSpan());
}
IEnumerator<T> IEnumerable<T>.GetEnumerator()
{ {
if (count == 0) yield break; if (count == 0) yield break;
@ -220,17 +246,8 @@ namespace ObservableCollections
public int IndexOf(T item) public int IndexOf(T item)
{ {
var span = GetSpan();
var i = 0; var i = 0;
foreach (var v in span.First) foreach (var v in this)
{
if (EqualityComparer<T>.Default.Equals(item, v))
{
return i;
}
i++;
}
foreach (var v in span.Second)
{ {
if (EqualityComparer<T>.Default.Equals(item, v)) if (EqualityComparer<T>.Default.Equals(item, v))
{ {
@ -241,6 +258,17 @@ namespace ObservableCollections
return -1; 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<T>.Insert(int index, T item) void IList<T>.Insert(int index, T item)
{ {
throw new NotSupportedException(); throw new NotSupportedException();
@ -258,7 +286,7 @@ namespace ObservableCollections
IEnumerator IEnumerable.GetEnumerator() IEnumerator IEnumerable.GetEnumerator()
{ {
return GetEnumerator(); return ((IEnumerable<T>)this).GetEnumerator();
} }
[DoesNotReturn] [DoesNotReturn]
@ -266,15 +294,65 @@ namespace ObservableCollections
{ {
throw new InvalidOperationException("RingBuffer is empty."); throw new InvalidOperationException("RingBuffer is empty.");
} }
public ref struct Enumerator
{
ReadOnlySpan<T>.Enumerator firstEnumerator;
ReadOnlySpan<T>.Enumerator secondEnumerator;
bool useFirst;
public Enumerator(RingBufferSpan<T> 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<T> public ref struct RingBufferSpan<T>
{ {
public readonly Span<T> First; public readonly ReadOnlySpan<T> First;
public readonly Span<T> Second; public readonly ReadOnlySpan<T> Second;
public readonly int Count; public readonly int Count;
public RingBufferSpan(Span<T> first, Span<T> second, int count) internal RingBufferSpan(ReadOnlySpan<T> first, ReadOnlySpan<T> second, int count)
{ {
First = first; First = first;
Second = second; Second = second;

View File

@ -11,7 +11,7 @@ namespace ObservableCollections.Tests
public class RingBufferTest public class RingBufferTest
{ {
[Fact] [Fact]
public void Foo() public void All()
{ {
var list = new RingBuffer<int>(); var list = new RingBuffer<int>();