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); }
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); }
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); }