diff --git a/ParadoxSaveParser.Lib/BufferedEnumerator.cs b/ParadoxSaveParser.Lib/BufferedEnumerator.cs index 2bca57b..fdabe3c 100644 --- a/ParadoxSaveParser.Lib/BufferedEnumerator.cs +++ b/ParadoxSaveParser.Lib/BufferedEnumerator.cs @@ -37,35 +37,73 @@ namespace ParadoxSaveParser.Lib; /// 2 3 | 4 | 5 /// 3 4 | 5 | /// -public class BufferedEnumerator : IEnumerator> +public class BufferedEnumerator : IEnumerator.Node> { - private readonly int _bufferSize; - private LinkedListNode? _currentNode; - private int _currentNodeIndex = -1; + public class Node + { +#nullable disable + public Node Previous; + public Node Next; + public T Value; +#nullable enable + } + private readonly IEnumerator _enumerator; - private readonly LinkedList _llist = new(); + private readonly Node[] _ringBuffer; + private Node? _currentNode; + private int _currentBufferIndex = -1; + private int _lastValueIndex = -1; public BufferedEnumerator(IEnumerator enumerator, int bufferSize) { _enumerator = enumerator; - _bufferSize = bufferSize; + _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 (_currentNodeIndex >= _bufferSize / 2) - _llist.RemoveFirst(); - - while (_llist.Count < _bufferSize && _enumerator.MoveNext()) + if (_currentBufferIndex == -1) { - _llist.AddLast(_enumerator.Current); + InitBuffer(); + + int beforeMidpoint = _ringBuffer.Length / 2 - 1; + for (int i = 0; i <= beforeMidpoint && _enumerator.MoveNext(); i++) + { + _ringBuffer[i].Value = _enumerator.Current; + } } - if (_llist.Count == 0) + + _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; - - _currentNodeIndex++; - _currentNode = _currentNode is null ? _llist.First : _currentNode.Next; - return _currentNode is not null; + + _currentNode = _ringBuffer[_currentBufferIndex]; + return true; } public void Reset() @@ -73,7 +111,7 @@ public class BufferedEnumerator : IEnumerator> throw new NotImplementedException(); } - public LinkedListNode Current => _currentNode!; + public Node Current => _currentNode!; object IEnumerator.Current => Current;