// ----------------------------------------------------------------------------- // file="RegexAnalyzer.InfoScan" // Project: StgSharp // Copyright (c) Nitload. // SPDX-License-Identifier: MIT // ----------------------------------------------------------------------------- using System; using System.Collections.Generic; using System.Linq; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; using System.Text; using System.Threading.Tasks; namespace StgSharp.RegularAnalysis.Text { public partial class RegexAnalyzer { internal static RegexInterpreterInfo ScanInfo( List ir ) { RegexInterpreterInfo info = new(); int process_count = 0; ReadOnlySpan irSpan = CollectionsMarshal.AsSpan(ir); int max_region = 0; int min_length = 0; int single_line_count = 0; ScanSpan(irSpan); return info; void ScanSpan( ReadOnlySpan ir_span ) { do { int count = int.Min(8, ir_span.Length - process_count); ReadOnlySpan window = ir_span.Slice(process_count, count); RegexIRPrefix prefix; if (window[0].CommandMask == RegexIRCommand.Match_Seq) { RegexMatchSeqIR match_seq = Unsafe.As(window[0]); min_length += match_seq.Pattern.Length; prefix = match_seq.Prefix; max_region = int.Max(max_region, prefix.WorkingRegion); if ((prefix.Mask & RegexIRPrefixMask.ObserveMethod) == RegexIRPrefixMask.Observe_Line) { int line_idx = prefix.ObserveSource; RegexIR source = ir[line_idx]; if (!source.SingleLineResultRequired) { source.SingleLineResultIndex = line_idx; single_line_count++; } } process_count++; } else if (window[0] is RegexFindSeqIR find_seq) { min_length += find_seq.Pattern.Length; prefix = find_seq.Prefix; max_region = int.Max(max_region, prefix.WorkingRegion); if ((prefix.Mask & RegexIRPrefixMask.ObserveMethod) == RegexIRPrefixMask.Observe_Line) { int line_idx = prefix.ObserveSource; RegexIR source = ir[line_idx]; if (!source.SingleLineResultRequired) { source.SingleLineResultIndex = line_idx; single_line_count++; } } process_count++; } else if (window[0] is RegexCountSeqIR count_seq) { min_length += count_seq.Pattern.Length * count_seq.Min; prefix = count_seq.Prefix; max_region = int.Max(max_region, prefix.WorkingRegion); if ((prefix.Mask & RegexIRPrefixMask.ObserveMethod) == RegexIRPrefixMask.Observe_Line) { int line_idx = prefix.ObserveSource; RegexIR source = ir[line_idx]; if (!source.SingleLineResultRequired) { source.SingleLineResultIndex = line_idx; single_line_count++; } } process_count++; } else if (window[0] is RegexMatchSetIR) { } } while (process_count < ir.Count); } } internal struct RegexInterpreterInfo { public int RegionCount { get; set; } public int MinPredictLength { get; set; } public int SingleLineResultCount { get; set; } } } }