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);
            }
Example #3
0
        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);
        }
Example #4
0
        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);
        }