public IEnumerable <FlexMatch> Matches(FlexString input, string pattern, RegexOptions options = RegexOptions.None, TimeSpan timeout = default, string captureGroup = null) { Timeout t = timeout == default ? Timeout.Unlimited : Timeout.Start(timeout); int lastUtf8Index = 0; int lastUtf16Index = 0; foreach (Match2 match in Regex2.Matches(input, pattern, options, t)) { yield return(ToFlex(match, input, ref lastUtf8Index, ref lastUtf16Index)); } }
public void Regex2_Timeout() { byte[] buffer = null; var sample = String8.Convert("using Microsoft.VisualStudio.TestTools.UnitTesting;", ref buffer); // Long timeout: Verify all matches returned var timeout = Timeout.Start(TimeSpan.FromSeconds(10)); Assert.Equal(51, Regex2.Matches(sample, ".", RegexOptions.None, timeout).Count()); Assert.False(timeout.IsExpired); // Tiny timeout: Verify early stop timeout = Timeout.Start(TimeSpan.FromTicks(1)); Assert.NotEqual(51, Regex2.Matches(sample, ".", RegexOptions.None, timeout).Count()); Assert.True(timeout.IsExpired); }
private static void Run() { const string content = @" { ""title"": ""Interesting"", ""message"": ""Nothing Found"" }"; for (int i = 0; i < 100; ++i) { int count = 0; byte[] buffer = null; var content8 = String8.Convert(content, ref buffer); foreach (Match2 match in Regex2.Matches(content8, "\\\"message\\\": ?\\\"[^\\\"]*\\\"")) { count++; } } }
public void Regex2_MultiThreaded() { const string content = @" { ""title"": ""Interesting"", ""message"": ""Nothing Found"" }"; Parallel.For(0, 1000, (_) => { int count = 0; byte[] buffer = null; var content8 = String8.Convert(content, ref buffer); foreach (Match2 match in Regex2.Matches(content8, "\\\"message\\\": ?\\\"[^\\\"]*\\\"")) { count++; } }); }
public void Regex2_Basics() { byte[] buffer = null, buffer2 = null; var sample = String8.Convert("using Microsoft.VisualStudio.TestTools.UnitTesting;", ref buffer2); // Null and Empty Assert.Throws <ArgumentNullException>(() => Regex2.IsMatch(sample, null)); Assert.Throws <ArgumentNullException>(() => Regex2.IsMatch(sample, "")); Assert.False(Regex2.IsMatch(String8.Empty, "[A-Z]")); Assert.Throws <ArgumentNullException>(() => Regex2.Matches(sample, null).FirstOrDefault()); Assert.Throws <ArgumentNullException>(() => Regex2.Matches(sample, "").FirstOrDefault()); // Basic Expressions Assert.True(Regex2.IsMatch(String8.Convert("Interesting", ref buffer), "[A-Z]")); Assert.False(Regex2.IsMatch(String8.Convert("1234567890", ref buffer), "[A-Z]")); // Regex Parse Errors Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, "(unclosedParen")); Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, "[unclosedBrace")); Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, "(['\"])matching quote backreference\\k1")); // Corrected Regex Parse Errors (named groups have names removed by Regex2 Assert.True(Regex2.IsMatch(sample, "(?<namedGroup>Tes)tTools")); // Match Index and Length, Multiple Matches Assert.Equal("(5, 11: ' Microsoft.'), (15, 14: '.VisualStudio.'), (28, 11: '.TestTools.'), (38, 13: '.UnitTesting;')", string.Join(", ", Regex2.Matches(sample, "[ \\.][^\\.]+[\\.;]").Select((m) => MatchToString(m, sample)))); // Overlapping Matches Assert.Equal("(5, 46: ' Microsoft.VisualStudio.TestTools.UnitTesting;'), (15, 36: '.VisualStudio.TestTools.UnitTesting;'), (28, 23: '.TestTools.UnitTesting;'), (38, 13: '.UnitTesting;')", string.Join(", ", Regex2.Matches(sample, "[ \\.].+[\\.;]").Select((m) => MatchToString(m, sample)))); // Internal String8.String8 range checks Assert.Throws <ArgumentNullException>(() => Regex2.IsMatch(new String8(null, sample.Index, sample.Length), "[A-Z]")); Assert.Throws <ArgumentOutOfRangeException>(() => Regex2.IsMatch(new String8(sample.Array, -1, sample.Length), "[A-Z]")); Assert.Throws <ArgumentOutOfRangeException>(() => Regex2.IsMatch(new String8(sample.Array, 0, sample.Length + 1), "[A-Z]")); Assert.Throws <ArgumentOutOfRangeException>(() => Regex2.IsMatch(new String8(sample.Array, sample.Length - 2, 3), "[A-Z]")); // IgnoreCase option Assert.True(Regex2.IsMatch(sample, @"[^\.]+Tools")); Assert.False(Regex2.IsMatch(sample, @"[^\.]+TOOLS")); Assert.True(Regex2.IsMatch(sample, @"[^\.]+TOOLS", RegexOptions.IgnoreCase)); // Singleline option var moreLines = String8.Convert("using Microsoft\r\n\t.VisualStudio\r\n\t.TestTools\r\n\t.UnitTesting;", ref buffer); Assert.False(Regex2.IsMatch(moreLines, "using (.+)VisualStudio")); Assert.True(Regex2.IsMatch(moreLines, "using (.+)VisualStudio", RegexOptions.Singleline)); // Multiple options Assert.True(Regex2.IsMatch(moreLines, "using (.+)VISUALSTUDIO", RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.Singleline)); // Ignored options don't throw and work with other options Assert.False(Regex2.IsMatch(sample, @"[^\.]+TOOLS", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture)); Assert.True(Regex2.IsMatch(sample, @"[^\.]+TOOLS", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture)); // Unsupported Options throw Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, @"[^\.]+Tools", RegexOptions.Multiline)); Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, @"[^\.]+Tools", RegexOptions.IgnorePatternWhitespace)); Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, @"[^\.]+Tools", RegexOptions.RightToLeft)); Assert.Throws <ArgumentException>(() => Regex2.IsMatch(sample, @"[^\.]+Tools", RegexOptions.ECMAScript)); // Insensitive case Assert.True(Regex2.IsMatch(String8.Convert("aA", ref buffer), "(?i)A(?-i)A")); Assert.True(Regex2.IsMatch(String8.Convert("AA", ref buffer), "(?i)A(?-i)A")); Assert.False(Regex2.IsMatch(String8.Convert("aa", ref buffer), "(?i)A(?-i)A")); Assert.False(Regex2.IsMatch(String8.Convert("Aa", ref buffer), "(?i)A(?-i)A")); }