|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using MemoryPools.Collections.Specialized;
|
|
|
|
|
|
|
|
|
|
namespace MemoryPools.Collections.Linq
|
|
|
|
|
{
|
|
|
|
|
internal class IntersectExprEnumerable<T> : IPoolingEnumerable<T>
|
|
|
|
|
{
|
|
|
|
|
private int _count;
|
|
|
|
|
private IPoolingEnumerable<T> _src;
|
|
|
|
|
private IEqualityComparer<T> _comparer;
|
|
|
|
|
private PoolingDictionary<T, int> _second;
|
|
|
|
|
|
|
|
|
|
public IntersectExprEnumerable<T> Init(
|
|
|
|
|
IPoolingEnumerable<T> src,
|
|
|
|
|
PoolingDictionary<T, int> second,
|
|
|
|
|
IEqualityComparer<T> comparer = default)
|
|
|
|
|
{
|
|
|
|
|
_src = src;
|
|
|
|
|
_count = 0;
|
|
|
|
|
_second = second;
|
|
|
|
|
_comparer = comparer ?? EqualityComparer<T>.Default;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public IPoolingEnumerator<T> GetEnumerator()
|
|
|
|
|
{
|
|
|
|
|
_count++;
|
|
|
|
|
return Pool<IntersectExprEnumerator>.Get().Init(this, _src.GetEnumerator(), _comparer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void Dispose()
|
|
|
|
|
{
|
|
|
|
|
if(_count == 0) return;
|
|
|
|
|
_count--;
|
|
|
|
|
if (_count == 0)
|
|
|
|
|
{
|
|
|
|
|
_src = default;
|
|
|
|
|
_second?.Dispose();
|
|
|
|
|
Pool<PoolingDictionary<T, int>>.Return(_second);
|
|
|
|
|
|
|
|
|
|
_second = default;
|
|
|
|
|
Pool<IntersectExprEnumerable<T>>.Return(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
internal class IntersectExprEnumerator : IPoolingEnumerator<T>
|
|
|
|
|
{
|
|
|
|
|
private IntersectExprEnumerable<T> _parent;
|
|
|
|
|
private IPoolingEnumerator<T> _src;
|
|
|
|
|
private PoolingDictionary<T, int> _alreadyDoneItems;
|
|
|
|
|
|
|
|
|
|
public IntersectExprEnumerator Init(IntersectExprEnumerable<T> parent, IPoolingEnumerator<T> src, IEqualityComparer<T> comparer)
|
|
|
|
|
{
|
|
|
|
|
_src = src;
|
|
|
|
|
_parent = parent;
|
|
|
|
|
_alreadyDoneItems = Pool<PoolingDictionary<T, int>>.Get().Init(0, comparer);
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool MoveNext()
|
|
|
|
|
{
|
|
|
|
|
while (_src.MoveNext())
|
|
|
|
|
{
|
|
|
|
|
if (_parent._second.ContainsKey(_src.Current) &&
|
|
|
|
|
!_alreadyDoneItems.ContainsKey(_src.Current))
|
|
|
|
|
{
|
|
|
|
|
_alreadyDoneItems[_src.Current] = 1;
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Reset() => _src.Reset();
|
|
|
|
|
|
|
|
|
|
object IPoolingEnumerator.Current => Current;
|
|
|
|
|
|
|
|
|
|
public T Current => _src.Current;
|
|
|
|
|
|
|
|
|
|
public void Dispose()
|
|
|
|
|
{
|
|
|
|
|
_src?.Dispose();
|
|
|
|
|
_src = null;
|
|
|
|
|
|
|
|
|
|
_alreadyDoneItems?.Dispose();
|
|
|
|
|
Pool<PoolingDictionary<T, int>>.Return(_alreadyDoneItems);
|
|
|
|
|
_alreadyDoneItems = default;
|
|
|
|
|
|
|
|
|
|
_parent?.Dispose();
|
|
|
|
|
_parent = default;
|
|
|
|
|
|
|
|
|
|
Pool<IntersectExprEnumerator>.Return(this);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
IPoolingEnumerator IPoolingEnumerable.GetEnumerator() => GetEnumerator();
|
|
|
|
|
}
|
|
|
|
|
}
|