mirror of
https://github.com/ppy/osu.git
synced 2024-11-12 11:37:58 +08:00
ffe7edc16a
Co-authored-by: Dan Balasescu <smoogipoo@smgi.me>
111 lines
3.4 KiB
C#
111 lines
3.4 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace osu.Game.Rulesets.Difficulty.Utils
|
|
{
|
|
/// <summary>
|
|
/// An indexed queue where items are indexed beginning from the most recently enqueued item.
|
|
/// </summary>
|
|
public class ReverseQueue<T> : IEnumerable<T>
|
|
{
|
|
/// <summary>
|
|
/// The number of elements in the <see cref="ReverseQueue{T}"/>.
|
|
/// </summary>
|
|
public int Count { get; private set; }
|
|
|
|
private T[] items;
|
|
private int capacity;
|
|
private int start;
|
|
|
|
public ReverseQueue(int initialCapacity)
|
|
{
|
|
if (initialCapacity <= 0)
|
|
throw new ArgumentOutOfRangeException(nameof(initialCapacity));
|
|
|
|
items = new T[initialCapacity];
|
|
capacity = initialCapacity;
|
|
start = 0;
|
|
Count = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves the item at an index in the <see cref="ReverseQueue{T}"/>.
|
|
/// </summary>
|
|
/// <param name="index">The index of the item to retrieve. The most recently enqueued item is at index 0.</param>
|
|
public T this[int index]
|
|
{
|
|
get
|
|
{
|
|
if (index < 0 || index > Count - 1)
|
|
throw new ArgumentOutOfRangeException(nameof(index));
|
|
|
|
int reverseIndex = Count - 1 - index;
|
|
return items[(start + reverseIndex) % capacity];
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Enqueues an item to this <see cref="ReverseQueue{T}"/>.
|
|
/// </summary>
|
|
/// <param name="item">The item to enqueue.</param>
|
|
public void Enqueue(T item)
|
|
{
|
|
if (Count == capacity)
|
|
{
|
|
// Double the buffer size
|
|
var buffer = new T[capacity * 2];
|
|
|
|
// Copy items to new queue
|
|
for (int i = 0; i < Count; i++)
|
|
{
|
|
buffer[i] = items[(start + i) % capacity];
|
|
}
|
|
|
|
// Replace array with new buffer
|
|
items = buffer;
|
|
capacity *= 2;
|
|
start = 0;
|
|
}
|
|
|
|
items[(start + Count) % capacity] = item;
|
|
Count++;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Dequeues the least recently enqueued item from the <see cref="ReverseQueue{T}"/> and returns it.
|
|
/// </summary>
|
|
/// <returns>The item dequeued from the <see cref="ReverseQueue{T}"/>.</returns>
|
|
public T Dequeue()
|
|
{
|
|
var item = items[start];
|
|
start = (start + 1) % capacity;
|
|
Count--;
|
|
return item;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Clears the <see cref="ReverseQueue{T}"/> of all items.
|
|
/// </summary>
|
|
public void Clear()
|
|
{
|
|
start = 0;
|
|
Count = 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns an enumerator which enumerates items in the <see cref="ReverseQueue{T}"/> starting from the most recently enqueued item.
|
|
/// </summary>
|
|
public IEnumerator<T> GetEnumerator()
|
|
{
|
|
for (int i = Count - 1; i >= 0; i--)
|
|
yield return items[(start + i) % capacity];
|
|
}
|
|
|
|
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
|
|
}
|
|
}
|