using System; using System.Collections.Generic; namespace MemoryPools.Collections.Linq { public static partial class PoolingEnumerable { public static IPoolingEnumerable Empty() => Range(0, 0).Select(x => (T)(object)x); public static IPoolingEnumerable Range(int startIndex, int count) { return Pool.Get().Init(startIndex, count); } public static IPoolingEnumerable Range(int count) { return Pool.Get().Init(0, count); } public static IPoolingEnumerable Repeat(T element, int count) => Range(0, count).Select(element, (item, x) => item); public static bool Contains(this IPoolingEnumerable self, T element) { foreach (var item in self) { if (item?.Equals(element) ?? false) return true; } return false; } public static int Count(this IPoolingEnumerable self) { var count = 0; foreach (var _ in self) { count++; } return count; } public static long LongCount(this IPoolingEnumerable self) { long count = 0; foreach (var _ in self) { count++; } return count; } public static T ElementAt(this IPoolingEnumerable self, int position) { var i = 0; foreach (var item in self) { if (i == position) return item; i++; } throw new InvalidOperationException("Sequence is too small. Index not found"); } public static bool SequenceEqual(this IPoolingEnumerable self, IPoolingEnumerable other) { var comparer = EqualityComparer.Default; using (var left = self.GetEnumerator()) using (var right = other.GetEnumerator()) { bool equals, leftHas, rightHas; do { leftHas = left.MoveNext(); rightHas = right.MoveNext(); equals = comparer.Equals(left.Current, right.Current); if (leftHas != rightHas || !equals) return false; } while (leftHas && rightHas); return !leftHas && !rightHas; } } } internal class RangeExprEnumerable : IPoolingEnumerable { private int _start; private int _workCount; private int _count; public RangeExprEnumerable Init(int start, int count) { _start = start; _workCount = count; _count = 0; return this; } public IPoolingEnumerator GetEnumerator() { _count++; return Pool.Get().Init(this, _start, _workCount); } private void Dispose() { if (_count == 0) return; _count--; if (_count == 0) { _start = _workCount = 0; _count = 0; Pool.Return(this); } } internal class RangeExprEnumerator : IPoolingEnumerator { private int _start; private int _current; private int _workCount; private RangeExprEnumerable _parent; public RangeExprEnumerator Init(RangeExprEnumerable parent, int start, int workCount) { _current = -1; _start = start; _workCount = workCount; _parent = parent; return this; } public bool MoveNext() { if (_current == 0) return false; if (_current == -1) { _current = _workCount; return _workCount != 0; } _current--; return _current != 0; } public void Reset() => _current = _start; object IPoolingEnumerator.Current => _current; public int Current => _start + (_workCount - _current); public void Dispose() { _current = -1; _parent?.Dispose(); _parent = default!; Pool.Return(this); } } IPoolingEnumerator IPoolingEnumerable.GetEnumerator() { return GetEnumerator(); } } }