diff --git a/StgSharp.RegularAnalysis/Text/CharSetEmitter.cs b/StgSharp.RegularAnalysis/Text/CharSetEmitter.cs new file mode 100644 index 00000000..f0105bac --- /dev/null +++ b/StgSharp.RegularAnalysis/Text/CharSetEmitter.cs @@ -0,0 +1,115 @@ +//----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +// file="CharSetEmitter" +// Project: StgSharp +// AuthorGroup: Nitload +// Copyright (c) Nitload. All rights reserved. +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +// ----------------------------------------------------------------------- +// ----------------------------------------------------------------------- +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace StgSharp.RegularAnalysis.Text +{ + internal enum CharSetType + { + + None, + Single, + Range, + Set + + } + + internal record struct CharSet( + string value, + CharSetType t, + bool accept + ) + { + + public bool IsAcceptable { get; set; } = accept; + + public CharSetType Type { get; set; } = t; + + public string Value { get; set; } = value; + + } + + internal class CharSetEmitter + { + + public static CharSet[] FigureCharSetType( + ReadOnlySpan source + ) + { + // range or single + bool accept; + if (source[0] == '[') + { + int idx; + accept = source[1] != '^'; + idx = accept ? 1 : 2; + ReadOnlySpan seq = source.Slice(idx, source.Length - idx - 1); + if (seq.IndexOf('-') == -1) + { + return [new CharSet(seq.ToString(), CharSetType.Single, accept)]; + } else + { + List list = []; + for (int i = 0; i < seq.Length && seq.Length > 0; ) + { + int pos = seq.IndexOf('-'); + if (pos > 1) { + list.Add(new(seq[0..(pos - 1)].ToString(), CharSetType.Single, accept)); + } + list.Add(new($"{seq[pos - 1]}{seq[pos + 1]}", CharSetType.Range, accept)); + i = pos + 2; + seq = seq[i..]; + } + return [.. list]; + } + } else if (source[0] == '\\') + { + // set + accept = char.IsAsciiLetterUpper(source[0]); + return char.ToLower(source[0], CultureInfo.InvariantCulture) + switch + { + 's' => [new("s", CharSetType.Set, accept)], + 'w' => [new("w", CharSetType.Set, accept)], + 'd' => [new("d", CharSetType.Set, accept)], + _ => throw new NotSupportedException() + }; + } else + { + // unknown, throw + throw new InvalidCastException($"Unknown char set: {source}"); + } + } + + } +} diff --git a/StgSharp.RegularAnalysis/Text/RegexAnalyzer.IROptimize.cs b/StgSharp.RegularAnalysis/Text/RegexAnalyzer.IROptimize.cs index 56fb2793..a9a15ada 100644 --- a/StgSharp.RegularAnalysis/Text/RegexAnalyzer.IROptimize.cs +++ b/StgSharp.RegularAnalysis/Text/RegexAnalyzer.IROptimize.cs @@ -59,6 +59,7 @@ namespace StgSharp.RegularAnalysis.Text { int process_count = 0; int last = int.Min(origin_span.Length, index + 8); + opt_win_sp.Clear(); origin_span[index..last].CopyTo(opt_win_sp); int result; @@ -140,6 +141,7 @@ namespace StgSharp.RegularAnalysis.Text { int process_count = 0; int last = int.Min(origin_span.Length, index + 8); + opt_win_sp.Clear(); origin_span[index..last].CopyTo(opt_win_sp); if (opt_win_sp[0] is IRegexComplex { IsFullyOptimized: true } skip)