123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158 |
- using System;
- using System.Collections;
- using System.Collections.Generic;
- namespace NTERA.EmuEra.Game.EraEmu.GameProc.Function
- {
- public interface ICircularBuffer<T>
- {
- int Count { get; }
- int Capacity { get; set; }
- T Enqueue(T item);
- T Dequeue();
- void Clear();
- T this[int index] { get; set; }
- int IndexOf(T item);
- void Insert(int index, T item);
- void RemoveAt(int index);
- }
- public class CircularBuffer<T> : ICircularBuffer<T>, IEnumerable<T>
- {
- private T[] _buffer;
- private int _head;
- private int _tail;
- public CircularBuffer(int capacity)
- {
- if (capacity < 0)
- throw new ArgumentOutOfRangeException("capacity", "must be positive");
- _buffer = new T[capacity];
- _head = capacity - 1;
- }
- public int Count { get; private set; }
- public int Capacity
- {
- get => _buffer.Length;
- set
- {
- if (value < 0)
- throw new ArgumentOutOfRangeException("value", "must be positive");
- if (value == _buffer.Length)
- return;
- var buffer = new T[value];
- var newCount = 0;
- while (Count > 0 && newCount < value)
- buffer[newCount++] = Dequeue();
- _buffer = buffer;
- Count = newCount;
- _head = newCount - 1;
- _tail = 0;
- }
- }
- public T Enqueue(T item)
- {
- _head = (_head + 1) % Capacity;
- var overwritten = _buffer[_head];
- _buffer[_head] = item;
- if (Count == Capacity)
- _tail = (_tail + 1) % Capacity;
- else
- ++Count;
- return overwritten;
- }
- public T Dequeue()
- {
- if (Count == 0)
- throw new InvalidOperationException("queue exhausted");
- var dequeued = _buffer[_tail];
- _buffer[_tail] = default(T);
- _tail = (_tail + 1) % Capacity;
- --Count;
- return dequeued;
- }
- public void Clear()
- {
- _head = Capacity - 1;
- _tail = 0;
- Count = 0;
- }
- public T this[int index]
- {
- get
- {
- if (index < 0 || index >= Count)
- throw new ArgumentOutOfRangeException("index");
- return _buffer[(_tail + index) % Capacity];
- }
- set
- {
- if (index < 0 || index >= Count)
- throw new ArgumentOutOfRangeException("index");
- _buffer[(_tail + index) % Capacity] = value;
- }
- }
- public int IndexOf(T item)
- {
- for (var i = 0; i < Count; ++i)
- if (Equals(item, this[i]))
- return i;
- return -1;
- }
- public void Insert(int index, T item)
- {
- if (index < 0 || index > Count)
- throw new ArgumentOutOfRangeException("index");
- if (Count == index)
- Enqueue(item);
- else
- {
- var last = this[Count - 1];
- for (var i = index; i < Count - 2; ++i)
- this[i + 1] = this[i];
- this[index] = item;
- Enqueue(last);
- }
- }
- public void RemoveAt(int index)
- {
- if (index < 0 || index >= Count)
- throw new ArgumentOutOfRangeException("index");
- for (var i = index; i > 0; --i)
- this[i] = this[i - 1];
- Dequeue();
- }
- public IEnumerator<T> GetEnumerator()
- {
- if (Count == 0 || Capacity == 0)
- yield break;
- for (var i = 0; i < Count; ++i)
- yield return this[i];
- }
- IEnumerator IEnumerable.GetEnumerator()
- {
- return GetEnumerator();
- }
- }
- }
|