using System.Collections;
using System.Collections.Generic;
using LanLib.UpdateManager.Extensions;
namespace LanLib.UpdateManager.Internal
{
/// Generic list with O(1) insertion and removal.
///
///
/// - Adding duplicate values and removing items that are not present are both no-op.
/// -
/// Items may be added and removed while the collection is being enumerated without raising exceptions.
/// This collection guarantees that all items are enumerated, even if insertions or removals happen during enumeration.
///
/// -
/// All enumerators reference the same list index, so avoid having more than one enumerator at the same time.
/// Creating a new enumerator resets this shared index.
///
///
///
public class FastRemoveList : IReadOnlyList
{
private readonly List _list = new List();
private readonly Dictionary _indexMap = new Dictionary();
private int _loopIndex;
/// Get the number of items contained in the .
public int Count => _list.Count;
/// Item registered at if index is valid, otherwise.
public T this[int index] => index >= 0 && index < Count ? _list[index] : default;
/// Add to the end of the list.
/// if value was not already present in the list and was successfully added, otherwise.
///
/// Adding a value while the collection is being enumerated is permitted and won't raise exceptions.
/// This operation is O(1).
///
public bool Add(T value)
{
if (_indexMap.ContainsKey(value))
{
return false;
}
_list.Add(value);
_indexMap.Add(value, _list.Count - 1);
return true;
}
/// Remove from the list, if found.
/// if value was present in the list and was successfully removed, otherwise.
///
/// Removing a value while the collection is being enumerated is permitted and won't raise exceptions.
/// This operation is O(1).
///
public bool Remove(T value)
{
if (!_indexMap.TryGetValue(value, out int indexToRemove))
{
return false;
}
_indexMap.Remove(value);
// If removing the object that was just enumerated, make sure the
// new object swapped back to this index gets enumerated as well
if (indexToRemove == _loopIndex)
{
_loopIndex--;
}
// If removing an object that was already enumerated while the loop is
// still running, swap it with current loop index to make sure we
// still enumerate the last element that will be swapped back later
else if (indexToRemove < _loopIndex)
{
_list.Swap(_loopIndex, indexToRemove, out T swappedValue);
_indexMap[swappedValue] = indexToRemove;
indexToRemove = _loopIndex;
_loopIndex--;
}
_list.RemoveAtSwapBack(indexToRemove, out T swappedBack);
if (swappedBack != null)
{
_indexMap[swappedBack] = indexToRemove;
}
return true;
}
/// Removes all values from the .
public void Clear()
{
_list.Clear();
_indexMap.Clear();
}
/// Returns an enumerator that iterates through the .
public Enumerator GetEnumerator()
{
return new Enumerator(this);
}
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
public struct Enumerator : IEnumerator
{
private FastRemoveList _list;
public Enumerator(FastRemoveList list)
{
_list = list;
Reset();
}
public T Current => _list[_list._loopIndex];
object IEnumerator.Current => Current;
public void Dispose()
{
}
public bool MoveNext()
{
if (_list._loopIndex < _list.Count - 1)
{
_list._loopIndex++;
return true;
}
else
{
return false;
}
}
public void Reset()
{
_list._loopIndex = -1;
}
}
}
}