using System.Collections; namespace ParadoxSaveParser.Lib; /// /// Enumerator wrapper that stores N/2 items before and N/2-1 after Current item. /// /// /// IEnumerator<int> Enumerator() /// { /// for(int i = 0; i < 6; i++) /// yield return i; /// } /// /// var en = Enumerator(); /// var bufen = new BufferedEnumerator<int>(en, 5); /// /// while(bufen.MoveNext()) /// { /// var cur = bufen.Current; /// for (var prev = cur.List?.First; prev != cur; prev = prev?.Next) /// Console.Write($"{prev?.Value} "); /// /// Console.Write($"| {cur.Value} |"); /// /// for (var next = cur.Next; next is not null; next = next.Next) /// Console.Write($" {next.Value}"); /// Console.WriteLine(); /// } /// /// Output: /// /// | 0 | 1 2 3 4 /// 0 | 1 | 2 3 4 /// 0 1 | 2 | 3 4 /// 1 2 | 3 | 4 5 /// 2 3 | 4 | 5 /// 3 4 | 5 | /// public class BufferedEnumerator : IEnumerator.Node> { public class Node { #nullable disable public Node Previous; public Node Next; public T Value; #nullable enable } private readonly IEnumerator _enumerator; private readonly Node[] _ringBuffer; private Node? _currentNode; private int _currentBufferIndex = -1; private int _lastValueIndex = -1; public BufferedEnumerator(IEnumerator enumerator, int bufferSize) { _enumerator = enumerator; _ringBuffer = new Node[bufferSize]; } private void InitBuffer() { _ringBuffer[0] = new Node { Value = default! }; for (int i = 1; i < _ringBuffer.Length; i++) { _ringBuffer[i] = new Node { Previous = _ringBuffer[i - 1], Value = default!, }; _ringBuffer[i - 1].Next = _ringBuffer[i]; } _ringBuffer[^1].Next = _ringBuffer[0]; _ringBuffer[0].Previous = _ringBuffer[^1]; } public bool MoveNext() { if (_currentBufferIndex == -1) { InitBuffer(); int beforeMidpoint = _ringBuffer.Length / 2 - 1; for (int i = 0; i <= beforeMidpoint && _enumerator.MoveNext(); i++) { _ringBuffer[i].Value = _enumerator.Current; } } _currentBufferIndex = (_currentBufferIndex + 1) % _ringBuffer.Length; if (_enumerator.MoveNext()) { int midpoint = (_currentBufferIndex + _ringBuffer.Length / 2) % _ringBuffer.Length; _ringBuffer[midpoint].Value = _enumerator.Current; _lastValueIndex = midpoint; } if(_currentBufferIndex == (_lastValueIndex + 1) % _ringBuffer.Length) return false; _currentNode = _ringBuffer[_currentBufferIndex]; return true; } public void Reset() { throw new NotImplementedException(); } public Node Current => _currentNode!; object IEnumerator.Current => Current; public void Dispose() { } }