| File: Operations\Region.cs | Web Access |
| Project: src\sdk\src\TemplateEngine\Microsoft.TemplateEngine.Core\Microsoft.TemplateEngine.Core.csproj (Microsoft.TemplateEngine.Core) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Text; using Microsoft.TemplateEngine.Core.Contracts; namespace Microsoft.TemplateEngine.Core.Operations { public class Region : IOperationProvider { public static readonly string OperationName = "region"; private readonly ITokenConfig _end; private readonly bool _include; private readonly ITokenConfig _start; private readonly bool _toggle; private readonly bool _wholeLine; private readonly bool _trimWhitespace; private readonly bool _initialState; public Region(ITokenConfig start, ITokenConfig end, bool include, bool wholeLine, bool trimWhitespace, string? id, bool initialState) { _wholeLine = wholeLine; _trimWhitespace = trimWhitespace; _start = start; _end = end; _include = include; _toggle = _start.Equals(_end); Id = id; _initialState = initialState; } public string? Id { get; } public IOperation GetOperation(Encoding encoding, IProcessorState processorState) { IToken startToken = _start.ToToken(encoding); IToken endToken = _end.ToToken(encoding); return new Implementation(this, startToken, endToken, _include, _toggle, Id, _initialState); } private class Implementation : IOperation { private readonly IToken _endToken; private readonly bool _includeRegion; private readonly bool _startAndEndAreSame; private readonly Region _definition; private bool _waitingForEnd; public Implementation(Region owner, IToken startToken, IToken endToken, bool include, bool toggle, string? id, bool initialState) { _definition = owner; _endToken = endToken; _includeRegion = include; _startAndEndAreSame = toggle; Tokens = toggle ? new[] { startToken } : new[] { startToken, endToken }; Id = id; IsInitialStateOn = string.IsNullOrEmpty(id) || initialState; } public IReadOnlyList<IToken> Tokens { get; } public string? Id { get; } public bool IsInitialStateOn { get; } public int HandleMatch(IProcessorState processor, int bufferLength, ref int currentBufferPosition, int token) { if (processor.Config.Flags.TryGetValue(Region.OperationName, out bool flag) && !flag) { processor.WriteToTarget(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; } } } }