public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target)
            {
                bool flag;

                if (processor.Config.Flags.TryGetValue(Conditional.OperationName, out flag) && !flag)
                {
                    target.Write(Tokens[token].Value, Tokens[token].Start, Tokens[token].Length);
                    return(Tokens[token].Length);
                }

                List <byte> conditionBytes = new List <byte>();

                ScanToCloseCondition(processor, conditionBytes, ref bufferLength, ref currentBufferPosition);
                byte[]          condition      = conditionBytes.ToArray();
                EngineConfig    adjustedConfig = new EngineConfig(processor.Config.EnvironmentSettings, processor.Config.Whitespaces, processor.Config.LineEndings, processor.Config.Variables, _definition.VariableFormat);
                IProcessorState localState     = new ProcessorState(new MemoryStream(condition), new MemoryStream(), conditionBytes.Count, int.MaxValue, adjustedConfig, new IOperationProvider[0]);
                int             pos            = 0;
                int             len            = conditionBytes.Count;

                bool faulted;
                bool value = _definition.Evaluator(localState, ref len, ref pos, out faulted);

                if (faulted)
                {
                    target.Write(Tokens[0].Value, Tokens[0].Start, Tokens[0].Length);
                    MemoryStream fragment = new MemoryStream();
                    fragment.Write(condition, 0, condition.Length);
                    fragment.Write(_closeConditionTrie.Tokens[0].Value, _closeConditionTrie.Tokens[0].Start, _closeConditionTrie.Tokens[0].Length);
                    fragment.Write(processor.CurrentBuffer, currentBufferPosition, bufferLength - currentBufferPosition);
                    fragment.Position = 0;
                    processor.Inject(fragment);
                    currentBufferPosition = processor.CurrentBufferPosition;
                    int written = Tokens[0].Length;
                    return(written);
                }

                if (value)
                {
                    processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, trimBackward: true);
                    return(0);
                }

                processor.SeekBackUntil(_scanBackTrie, true);
                FindEnd(processor, ref bufferLength, ref currentBufferPosition);
                processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, _definition.WholeLine, _definition.TrimWhitespace);
                return(0);
            }
Example #2
0
            public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target)
            {
                bool flag;

                if (processor.Config.Flags.TryGetValue(Conditional.OperationName, out flag) && !flag)
                {
                    byte[] tokenValue = Tokens[token];
                    target.Write(tokenValue, 0, tokenValue.Length);
                    return(tokenValue.Length);
                }

                List <byte> conditionBytes = new List <byte>();

                ScanToCloseCondition(processor, conditionBytes, ref bufferLength, ref currentBufferPosition);
                byte[]          condition  = conditionBytes.ToArray();
                IProcessorState localState = new ProcessorState(new MemoryStream(condition), new MemoryStream(), conditionBytes.Count, int.MaxValue, processor.Config, new IOperationProvider[0]);
                int             pos        = 0;
                int             len        = conditionBytes.Count;

                bool faulted;
                bool value = _definition.Evaluator(localState, ref len, ref pos, out faulted);

                if (faulted)
                {
                    target.Write(Tokens[0], 0, Tokens[0].Length);
                    target.Write(condition, 0, condition.Length);
                    target.Write(_closeConditionTrie.Tokens[0], 0, _closeConditionTrie.Tokens[0].Length);
                    int written = Tokens[0].Length + condition.Length + _closeConditionTrie.Tokens[0].Length;
                    return(written);
                }

                if (value)
                {
                    processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, trimBackward: true);
                    return(0);
                }

                processor.SeekBackUntil(_scanBackTrie, true);
                FindEnd(processor, ref bufferLength, ref currentBufferPosition);
                processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, _definition.WholeLine, _definition.TrimWhitespace);
                return(0);
            }
Example #3
0
            public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target)
            {
                bool flag;

                if (processor.Config.Flags.TryGetValue(Region.OperationName, out flag) && !flag)
                {
                    target.Write(Tokens[token].Value, Tokens[token].Start, Tokens[token].Length);
                    return(Tokens[token].Length);
                }

                processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, wholeLine: _definition._wholeLine, trim: _definition._trimWhitespace);

                if (_startAndEndAreSame)
                {
                    token = _waitingForEnd ? 1 : 0;
                }

                //If we're resuming from a region that has been included (we've found the end now)
                //  just process the end
                if (_waitingForEnd && token == 1)
                {
                    _waitingForEnd = false;
                    return(0);
                }

                if (token != 0)
                {
                    return(0);
                }

                //If we're including the region, set that we're waiting for the end and return
                //  control to the processor
                if (_includeRegion)
                {
                    _waitingForEnd = true;
                    return(0);
                }

                //If we've made it here, we're skipping stuff, skip all the way to the end of the
                //  end token

                int i = currentBufferPosition;
                int j = 0;

                for (; j < _endToken.Length; ++j)
                {
                    if (i + j == bufferLength)
                    {
                        processor.AdvanceBuffer(i + j);
                        bufferLength = processor.CurrentBufferLength;
                        i            = -j;
                    }

                    //TODO: This should be using one of the tries rather than looking for the byte run directly
                    if (processor.CurrentBuffer[i + j] != _endToken.Value[j])
                    {
                        ++i;
                        j = -1;
                    }
                }

                i += j;

                processor.WhitespaceHandler(ref bufferLength, ref i, wholeLine: _definition._wholeLine, trim: _definition._trimWhitespace);

                currentBufferPosition = i;
                return(0);
            }
Example #4
0
            public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target)
            {
                bool flag;

                if (processor.Config.Flags.TryGetValue(OperationName, out flag) && !flag)
                {
                    target.Write(Tokens[token].Value, Tokens[token].Start, Tokens[token].Length);
                    return(Tokens[token].Length);
                }

                // conditional has not started, or this is the "if"
                if (_current != null || IsTokenIndexOfType(token, IfTokenBaseIndex) || IsTokenIndexOfType(token, IfTokenActionableBaseIndex))
                {
                    if (_definition._wholeLine)
                    {
                        processor.SeekBackUntil(processor.EncodingConfig.LineEndings);
                    }
                    else if (_definition._trimWhitespace)
                    {
                        processor.TrimWhitespace(false, true, ref bufferLength, ref currentBufferPosition);
                    }
                }

BEGIN:
                //Got the "if" token...
                if (IsTokenIndexOfType(token, IfTokenBaseIndex) || IsTokenIndexOfType(token, IfTokenActionableBaseIndex))
                {
                    if (_current == null)
                    {
                        _current = new EvaluationState(this);
                    }
                    else
                    {
                        _pendingCompletion.Push(_current);
                        _current = new EvaluationState(this);
                    }

                    //If the "if" branch is taken, all else and elseif blocks will be omitted, return
                    //  control to the processor so nested "if"s/mutations can be processed. Note that
                    //  this block will not be terminated until the corresponding endif is found
                    if (_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition))
                    {
                        if (_definition.WholeLine)
                        {
                            processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                        }

                        if (IsTokenIndexOfType(token, IfTokenActionableBaseIndex))
                        {
                            // "Actionable" if token, so enable the flag operation(s)
                            _current.ToggleActionableOperations(true, processor);
                        }

                        // if (true_condition) was found.
                        return(0);
                    }
                    else
                    {
                        // if (false_condition) was found. Skip to the next token of the if-elseif-elseif-...elseif-else-endif
                        SeekToNextTokenAtSameLevel(processor, ref bufferLength, ref currentBufferPosition, out token);
                        goto BEGIN;
                    }
                }

                // If we've got an unbalanced statement, emit the token
                if (_current == null)
                {
                    target.Write(Tokens[token].Value, Tokens[token].Start, Tokens[token].Length);
                    return(Tokens[token].Length);
                }

                //Got the endif token, exit to the parent "if" scope if it exists
                if (IsTokenIndexOfType(token, EndTokenBaseIndex))
                {
                    if (_pendingCompletion.Count > 0)
                    {
                        _current = _pendingCompletion.Pop();
                        _current.ToggleActionableOperations(_current.ActionableOperationsEnabled, processor);
                    }
                    else
                    {
                        // disable the special case operations (note: they may already be disabled, but cheaper to do than check)
                        _current.ToggleActionableOperations(false, processor);
                        _current = null;
                    }

                    if (_definition._wholeLine)
                    {
                        processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                    }
                    else if (_definition._trimWhitespace)
                    {
                        processor.TrimWhitespace(true, false, ref bufferLength, ref currentBufferPosition);
                    }

                    return(0);
                }

                if (_current.BranchTaken)
                {
                    processor.SeekBackUntil(processor.EncodingConfig.LineEndings, true);
                    //A previous branch was taken. Skip to the endif token.
                    // NOTE: this can probably use the new method SeekToNextTokenAtSameLevel() - they do almost the same thing.
                    SkipToMatchingEndif(processor, ref bufferLength, ref currentBufferPosition, ref token);

                    if (_pendingCompletion.Count > 0)
                    {
                        _current = _pendingCompletion.Pop();
                        _current.ToggleActionableOperations(_current.ActionableOperationsEnabled, processor);
                    }
                    else
                    {
                        // disable the special case operation (note: it may already be disabled, but cheaper to do than check)
                        _current.ToggleActionableOperations(false, processor);
                        _current = null;
                    }

                    if (_definition._wholeLine)
                    {
                        processor.SeekForwardUntil(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                    }
                    else if (_definition._trimWhitespace)
                    {
                        processor.TrimWhitespace(true, false, ref bufferLength, ref currentBufferPosition);
                    }

                    return(0);
                }

                //We have an "elseif" and haven't taken a previous branch
                if (IsTokenIndexOfType(token, ElseIfTokenBaseIndex) || IsTokenIndexOfType(token, ElseIfTokenActionableBaseIndex))
                {
                    // 8-19 attempt to make the same as if() handling
                    //
                    if (_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition))
                    {
                        if (_definition.WholeLine)
                        {
                            processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                        }

                        if (IsTokenIndexOfType(token, ElseIfTokenActionableBaseIndex))
                        {
                            // the elseif branch is taken.
                            _current.ToggleActionableOperations(true, processor);
                        }

                        return(0);
                    }
                    else
                    {
                        SeekToNextTokenAtSameLevel(processor, ref bufferLength, ref currentBufferPosition, out token);

                        // In the original version this was conditional on SeekToToken() succeeding.
                        // Not sure if it should be conditional. It should never fail, unless the template is malformed.
                        goto BEGIN;
                    }
                }

                //We have an "else" token and haven't taken any other branches, return control
                //  after setting that a branch has been taken
                if (IsTokenIndexOfType(token, ElseTokenBaseIndex) || IsTokenIndexOfType(token, ElseTokenActionableBaseIndex))
                {
                    if (IsTokenIndexOfType(token, ElseTokenActionableBaseIndex))
                    {
                        _current.ToggleActionableOperations(true, processor);
                    }

                    _current.BranchTaken = true;
                    processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, wholeLine: _definition._wholeLine, trim: _definition._trimWhitespace);
                    return(0);
                }
                else
                {
                    Debug.Assert(true, "Unknown token index: " + token);
                    return(0);   // TODO: revisit. Not sure what's best here.
                }
            }
            public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token, Stream target)
            {
                bool flag;

                if (processor.Config.Flags.TryGetValue("conditionals", out flag) && !flag)
                {
                    byte[] tokenValue = Tokens[token];
                    target.Write(tokenValue, 0, tokenValue.Length);
                    return(tokenValue.Length);
                }

                if (_current != null || token == 0)
                {
                    if (_definition._wholeLine)
                    {
                        processor.SeekBackUntil(processor.EncodingConfig.LineEndings);
                    }
                    else if (_definition._trimWhitespace)
                    {
                        processor.TrimWhitespace(false, true, ref bufferLength, ref currentBufferPosition);
                    }
                }

BEGIN:
                //Got the "if" token...
                if (token == 0)
                {
                    if (_current == null)
                    {
                        _current = new EvaluationState(this);
                    }
                    else
                    {
                        _pendingCompletion.Push(_current);
                        _current = new EvaluationState(this);
                    }

                    //If the "if" branch is taken, all else and elseif blocks will be omitted, return
                    //  control to the processor so nested "if"s/mutations can be processed. Note that
                    //  this block will not be terminated until the corresponding endif is found
                    if (_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition))
                    {
                        if (_definition.WholeLine)
                        {
                            processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                        }

                        return(0);
                    }

                    if (_definition.WholeLine)
                    {
                        processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                    }

                    SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token);

                    //Keep on scanning until we've hit a balancing token that belongs to us
                    while (token == 0)
                    {
                        int open = 1;
                        while (open != 0)
                        {
                            SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token);
                            if (token == 0)
                            {
                                ++open;
                            }
                            else if (token == 1)
                            {
                                --open;
                            }
                        }

                        SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token);
                    }

                    goto BEGIN;
                }

                //If we've got an unbalanced statement, emit the token
                if (_current == null)
                {
                    byte[] tokenValue = Tokens[token];
                    target.Write(tokenValue, 0, tokenValue.Length);
                    return(tokenValue.Length);
                }

                //Got the endif token, exit to the parent "if" scope if it exists
                if (token == 1)
                {
                    _current = null;

                    if (_pendingCompletion.Count > 0)
                    {
                        _current = _pendingCompletion.Pop();
                    }

                    if (_definition._wholeLine)
                    {
                        processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                    }
                    else if (_definition._trimWhitespace)
                    {
                        processor.TrimWhitespace(true, false, ref bufferLength, ref currentBufferPosition);
                    }

                    return(0);
                }

                if (_current.BranchTaken)
                {
                    processor.SeekBackUntil(processor.EncodingConfig.LineEndings, true);
                    //A previous branch was taken. Skip to the endif token.
                    SkipToMatchingEndif(processor, ref bufferLength, ref currentBufferPosition, ref token);
                    return(0);
                }

                //We have an "elseif" and haven't taken a previous branch
                if (token == _elseIfTokenIndex)
                {
                    //If the elseif branch is taken, return control for replacements to be done as usual
                    if (!_current.Evaluate(processor, ref bufferLength, ref currentBufferPosition))
                    {
                        if (_definition.WholeLine)
                        {
                            processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                        }

                        if (SeekToTerminator(processor, ref bufferLength, ref currentBufferPosition, out token))
                        {
                            goto BEGIN;
                        }
                    }

                    if (_definition.WholeLine)
                    {
                        processor.SeekForwardThrough(processor.EncodingConfig.LineEndings, ref bufferLength, ref currentBufferPosition);
                    }

                    //The "elseif" branch was not taken. Skip to the following else, elseif or endif token
                    return(0);
                }

                //We have an "else" token and haven't taken any other branches, return control
                //  after setting that a branch has been taken
                _current.BranchTaken = true;
                processor.WhitespaceHandler(ref bufferLength, ref currentBufferPosition, wholeLine: _definition._wholeLine, trim: _definition._trimWhitespace);
                return(0);
            }