public TerminalLocation <T> Evaluate(byte[] buffer, int bufferLength, bool isFinalBuffer, int lastNetBufferEffect, ref int bufferPosition) { TerminalLocation <T> terminal; _sequenceNumber += lastNetBufferEffect; int sequenceNumberToBufferPositionRelationship = _sequenceNumber - bufferPosition; int originalSequenceNumber = _sequenceNumber; if (lastNetBufferEffect != 0 || !_evaluator.TryGetNext(isFinalBuffer && bufferPosition >= bufferLength, ref _sequenceNumber, out terminal)) { while (!_evaluator.Accept(buffer[bufferPosition], ref _sequenceNumber, out terminal)) { ++_sequenceNumber; ++bufferPosition; if (bufferPosition >= bufferLength) { if (!isFinalBuffer) { break; } else { _evaluator.FinalizeMatchesInProgress(ref _sequenceNumber, out terminal); break; } } originalSequenceNumber = _sequenceNumber; } } if (terminal != null) { terminal.Location -= sequenceNumberToBufferPositionRelationship; if (originalSequenceNumber > _sequenceNumber + 1) { int expectedShift = terminal.Terminal.Length - terminal.Terminal.End - 1; if (expectedShift == 0) { int actualShift = originalSequenceNumber - _sequenceNumber - 1; int compensation = actualShift - expectedShift; bufferPosition -= compensation; } } } return(terminal); }
public IOperation GetOperation(byte[] buffer, int bufferLength, ref int bufferPosition, out int token) { int originalPosition = bufferPosition; TrieEvaluator <OperationTerminal> evaluator = new TrieEvaluator <OperationTerminal>(this); int sn = originalPosition; for (; bufferPosition < bufferLength; ++bufferPosition) { if (evaluator.Accept(buffer[bufferPosition], ref sn, out TerminalLocation <OperationTerminal> terminal)) { if (terminal.Location == originalPosition) { bufferPosition -= sn - terminal.Location - terminal.Terminal.End; token = terminal.Terminal.Token; return(terminal.Terminal.Operation); } else { token = -1; bufferPosition = originalPosition; return(null); } } ++sn; } if (bufferPosition == bufferLength) { evaluator.FinalizeMatchesInProgress(ref sn, out TerminalLocation <OperationTerminal> terminal); if (terminal != null) { bufferPosition -= sn - terminal.Location - terminal.Terminal.End; token = terminal.Terminal.Token; return(terminal.Terminal.Operation); } } bufferPosition = originalPosition; token = -1; return(null); }
public TerminalLocation <T> Evaluate(byte[] buffer, int bufferLength, bool isFinalBuffer, int lastNetBufferEffect, ref int bufferPosition) { TerminalLocation <T> terminal; _sequenceNumber += lastNetBufferEffect; int sequenceNumberToBufferPositionRelationship = _sequenceNumber - bufferPosition; if (lastNetBufferEffect != 0 || !_evaluator.TryGetNext(isFinalBuffer && bufferPosition >= bufferLength, ref _sequenceNumber, out terminal)) { while (!_evaluator.Accept(buffer[bufferPosition], ref _sequenceNumber, out terminal)) { ++_sequenceNumber; ++bufferPosition; if (bufferPosition >= bufferLength) { if (!isFinalBuffer) { break; } else { _evaluator.FinalizeMatchesInProgress(ref _sequenceNumber, out terminal); break; } } } } if (terminal != null) { terminal.Location -= sequenceNumberToBufferPositionRelationship; } return(terminal); }
public bool Run() { int nextSequenceNumberThatCouldBeWritten = CurrentSequenceNumber; int bytesWrittenSinceLastFlush = 0; bool anyOperationsExecuted = false; while (true) { //Loop until we run out of data in the buffer while (CurrentBufferPosition < CurrentBufferLength) { int posedPosition = CurrentSequenceNumber; bool skipAdvanceBuffer = false; if (_trie.Accept(CurrentBuffer[CurrentBufferPosition], ref posedPosition, out TerminalLocation <OperationTerminal> terminal)) { IOperation operation = terminal.Terminal.Operation; int matchLength = terminal.Terminal.End - terminal.Terminal.Start + 1; int handoffBufferPosition = CurrentBufferPosition + matchLength - (CurrentSequenceNumber - terminal.Location); if (terminal.Location > nextSequenceNumberThatCouldBeWritten) { int toWrite = terminal.Location - nextSequenceNumberThatCouldBeWritten; //Console.WriteLine("UnmatchedBlock"); //string text = System.Text.Encoding.UTF8.GetString(CurrentBuffer, handoffBufferPosition - toWrite - matchLength, toWrite).Replace("\0", "\\0"); //Console.WriteLine(text); _target.Write(CurrentBuffer, handoffBufferPosition - toWrite - matchLength, toWrite); bytesWrittenSinceLastFlush += toWrite; nextSequenceNumberThatCouldBeWritten = posedPosition - matchLength + 1; } if (operation.Id == null || (Config.Flags.TryGetValue(operation.Id, out bool opEnabledFlag) && opEnabledFlag)) { CurrentSequenceNumber += handoffBufferPosition - CurrentBufferPosition; CurrentBufferPosition = handoffBufferPosition; posedPosition = handoffBufferPosition; int bytesWritten = operation.HandleMatch(this, CurrentBufferLength, ref posedPosition, terminal.Terminal.Token, _target); bytesWrittenSinceLastFlush += bytesWritten; CurrentSequenceNumber += posedPosition - CurrentBufferPosition; CurrentBufferPosition = posedPosition; nextSequenceNumberThatCouldBeWritten = CurrentSequenceNumber; skipAdvanceBuffer = true; anyOperationsExecuted = true; } else { int oldSequenceNumber = CurrentSequenceNumber; CurrentSequenceNumber = terminal.Location + terminal.Terminal.End + 1; CurrentBufferPosition += CurrentSequenceNumber - oldSequenceNumber; } if (bytesWrittenSinceLastFlush >= _flushThreshold) { _target.Flush(); bytesWrittenSinceLastFlush = 0; } } if (!skipAdvanceBuffer) { ++CurrentSequenceNumber; ++CurrentBufferPosition; } } //Calculate the sequence number at the head of the buffer int headSequenceNumber = CurrentSequenceNumber - CurrentBufferPosition; // Calculate the buffer position to advance to. It can not be negative. // Taking a maximum is a workaround for out-of-sync _trie.OldestRequiredSequenceNumber which may appear near EOF. int bufferPositionToAdvanceTo = Math.Max(_trie.OldestRequiredSequenceNumber - headSequenceNumber, 0); int numberOfUncommittedBytesBeforeThePositionToAdvanceTo = _trie.OldestRequiredSequenceNumber - nextSequenceNumberThatCouldBeWritten; //If we'd advance data out of the buffer that hasn't been // handled already, write it out if (numberOfUncommittedBytesBeforeThePositionToAdvanceTo > 0) { int toWrite = numberOfUncommittedBytesBeforeThePositionToAdvanceTo; // Console.WriteLine("AdvancePreserve"); // Console.WriteLine($"nextSequenceNumberThatCouldBeWritten {nextSequenceNumberThatCouldBeWritten}"); // Console.WriteLine($"headSequenceNumber {headSequenceNumber}"); // Console.WriteLine($"bufferPositionToAdvanceTo {bufferPositionToAdvanceTo}"); // Console.WriteLine($"numberOfUncommittedBytesBeforeThePositionToAdvanceTo {numberOfUncommittedBytesBeforeThePositionToAdvanceTo}"); // Console.WriteLine($"CurrentBufferPosition {CurrentBufferPosition}"); // Console.WriteLine($"CurrentBufferLength {CurrentBufferLength}"); // Console.WriteLine($"CurrentBuffer.Length {CurrentBuffer.Length}"); // string text = System.Text.Encoding.UTF8.GetString(CurrentBuffer, bufferPositionToAdvanceTo - toWrite, toWrite).Replace("\0", "\\0"); // Console.WriteLine(text); _target.Write(CurrentBuffer, bufferPositionToAdvanceTo - toWrite, toWrite); bytesWrittenSinceLastFlush += toWrite; nextSequenceNumberThatCouldBeWritten = _trie.OldestRequiredSequenceNumber; } //We ran out of data in the buffer, so attempt to advance // if we fail, if (!AdvanceBuffer(bufferPositionToAdvanceTo)) { int posedPosition = CurrentSequenceNumber; _trie.FinalizeMatchesInProgress(ref posedPosition, out TerminalLocation <OperationTerminal> terminal); while (terminal != null) { IOperation operation = terminal.Terminal.Operation; int matchLength = terminal.Terminal.End - terminal.Terminal.Start + 1; int handoffBufferPosition = CurrentBufferPosition + matchLength - (CurrentSequenceNumber - terminal.Location); if (terminal.Location > nextSequenceNumberThatCouldBeWritten) { int toWrite = terminal.Location - nextSequenceNumberThatCouldBeWritten; // Console.WriteLine("TailUnmatchedBlock"); // string text = System.Text.Encoding.UTF8.GetString(CurrentBuffer, handoffBufferPosition - toWrite - matchLength, toWrite).Replace("\0", "\\0"); // Console.WriteLine(text); _target.Write(CurrentBuffer, handoffBufferPosition - toWrite - matchLength, toWrite); bytesWrittenSinceLastFlush += toWrite; nextSequenceNumberThatCouldBeWritten = terminal.Location; } if (operation.Id == null || (Config.Flags.TryGetValue(operation.Id, out bool opEnabledFlag) && opEnabledFlag)) { CurrentSequenceNumber += handoffBufferPosition - CurrentBufferPosition; CurrentBufferPosition = handoffBufferPosition; posedPosition = handoffBufferPosition; int bytesWritten = operation.HandleMatch(this, CurrentBufferLength, ref posedPosition, terminal.Terminal.Token, _target); bytesWrittenSinceLastFlush += bytesWritten; CurrentSequenceNumber += posedPosition - CurrentBufferPosition; CurrentBufferPosition = posedPosition; nextSequenceNumberThatCouldBeWritten = CurrentSequenceNumber; anyOperationsExecuted = true; } else { int oldSequenceNumber = CurrentSequenceNumber; CurrentSequenceNumber = terminal.Location + terminal.Terminal.End + 1; CurrentBufferPosition += CurrentSequenceNumber - oldSequenceNumber; } _trie.FinalizeMatchesInProgress(ref posedPosition, out terminal); } break; } } int endSequenceNumber = CurrentSequenceNumber - CurrentBufferPosition + CurrentBufferLength; if (endSequenceNumber > nextSequenceNumberThatCouldBeWritten) { int toWrite = endSequenceNumber - nextSequenceNumberThatCouldBeWritten; // Console.WriteLine("LastBlock"); // string text = System.Text.Encoding.UTF8.GetString(CurrentBuffer, CurrentBufferLength - toWrite, toWrite).Replace("\0", "\\0"); // Console.WriteLine(text); _target.Write(CurrentBuffer, CurrentBufferLength - toWrite, toWrite); } _target.Flush(); return(anyOperationsExecuted); }
public bool Run() { int nextSequenceNumberThatCouldBeWritten = 0; int bytesWrittenSinceLastFlush = 0; bool anyOperationsExecuted = false; while (true) { //Loop until we run out of data in the buffer while (CurrentBufferPosition < CurrentBufferLength) { int posedPosition = CurrentSequenceNumber; bool skipAdvanceBuffer = false; if (_trie.Accept(CurrentBuffer[CurrentBufferPosition], ref posedPosition, out TerminalLocation <OperationTerminal> terminal)) { IOperation operation = terminal.Terminal.Operation; int matchLength = terminal.Terminal.End - terminal.Terminal.Start; int handoffBufferPosition = CurrentBufferPosition + matchLength - (CurrentSequenceNumber - terminal.Location); if (terminal.Location > nextSequenceNumberThatCouldBeWritten) { int toWrite = terminal.Location - nextSequenceNumberThatCouldBeWritten; _target.Write(CurrentBuffer, handoffBufferPosition - toWrite - matchLength, toWrite); bytesWrittenSinceLastFlush += toWrite; nextSequenceNumberThatCouldBeWritten = posedPosition - matchLength; } if (operation.Id == null || (Config.Flags.TryGetValue(operation.Id, out bool opEnabledFlag) && opEnabledFlag)) { CurrentSequenceNumber += handoffBufferPosition - CurrentBufferPosition; CurrentBufferPosition = handoffBufferPosition; posedPosition = handoffBufferPosition; int bytesWritten = operation.HandleMatch(this, CurrentBufferLength, ref posedPosition, terminal.Terminal.Token, _target); bytesWrittenSinceLastFlush += bytesWritten; CurrentSequenceNumber += posedPosition - CurrentBufferPosition; CurrentBufferPosition = posedPosition; nextSequenceNumberThatCouldBeWritten = CurrentSequenceNumber; skipAdvanceBuffer = true; anyOperationsExecuted = true; } else { int oldSequenceNumber = CurrentSequenceNumber; CurrentSequenceNumber = terminal.Location + terminal.Terminal.End; CurrentBufferPosition += CurrentSequenceNumber - oldSequenceNumber; } if (bytesWrittenSinceLastFlush >= _flushThreshold) { _target.Flush(); } } if (!skipAdvanceBuffer) { ++CurrentSequenceNumber; ++CurrentBufferPosition; } } //Calculate the sequence number at the head of the buffer int headSequenceNumber = CurrentSequenceNumber - CurrentBufferPosition; int bufferPositionToAdvanceTo = _trie.OldestRequiredSequenceNumber - headSequenceNumber; int numberOfUncommittedBytesBeforeThePositionToAdvanceTo = _trie.OldestRequiredSequenceNumber - nextSequenceNumberThatCouldBeWritten; //If we'd advance data out of the buffer that hasn't been // handled already, write it out if (numberOfUncommittedBytesBeforeThePositionToAdvanceTo > 0) { int toWrite = numberOfUncommittedBytesBeforeThePositionToAdvanceTo; _target.Write(CurrentBuffer, bufferPositionToAdvanceTo - toWrite, toWrite); bytesWrittenSinceLastFlush += toWrite; nextSequenceNumberThatCouldBeWritten = _trie.OldestRequiredSequenceNumber; } //We ran out of data in the buffer, so attempt to advance // if we fail, if (!AdvanceBuffer(bufferPositionToAdvanceTo)) { int posedPosition = CurrentSequenceNumber; _trie.FinalizeMatchesInProgress(ref posedPosition, out TerminalLocation <OperationTerminal> terminal); while (terminal != null) { IOperation operation = terminal.Terminal.Operation; int matchLength = terminal.Terminal.End - terminal.Terminal.Start; int handoffBufferPosition = CurrentBufferPosition + matchLength - (CurrentSequenceNumber - terminal.Location); if (terminal.Location > nextSequenceNumberThatCouldBeWritten) { int toWrite = terminal.Location - nextSequenceNumberThatCouldBeWritten; _target.Write(CurrentBuffer, handoffBufferPosition - toWrite - matchLength, toWrite); bytesWrittenSinceLastFlush += toWrite; nextSequenceNumberThatCouldBeWritten = terminal.Location; } if (operation.Id == null || (Config.Flags.TryGetValue(operation.Id, out bool opEnabledFlag) && opEnabledFlag)) { CurrentSequenceNumber += handoffBufferPosition - CurrentBufferPosition; CurrentBufferPosition = handoffBufferPosition; posedPosition = handoffBufferPosition; int bytesWritten = operation.HandleMatch(this, CurrentBufferLength, ref posedPosition, terminal.Terminal.Token, _target); bytesWrittenSinceLastFlush += bytesWritten; CurrentSequenceNumber += posedPosition - CurrentBufferPosition; CurrentBufferPosition = posedPosition; nextSequenceNumberThatCouldBeWritten = CurrentSequenceNumber; anyOperationsExecuted = true; } else { int oldSequenceNumber = CurrentSequenceNumber; CurrentSequenceNumber = terminal.Location + terminal.Terminal.End; CurrentBufferPosition += CurrentSequenceNumber - oldSequenceNumber; } _trie.FinalizeMatchesInProgress(ref posedPosition, out terminal); } break; } } int endSequenceNumber = CurrentSequenceNumber - CurrentBufferPosition + CurrentBufferLength; if (endSequenceNumber > nextSequenceNumberThatCouldBeWritten) { int toWrite = endSequenceNumber - nextSequenceNumberThatCouldBeWritten; _target.Write(CurrentBuffer, CurrentBufferLength - toWrite, toWrite); } _target.Flush(); return(anyOperationsExecuted); }