diff --git a/csharp/Platform.RegularExpressions.Transformer.Tests/RegexEngineTests.cs b/csharp/Platform.RegularExpressions.Transformer.Tests/RegexEngineTests.cs
new file mode 100644
index 0000000..8bfb7bb
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer.Tests/RegexEngineTests.cs
@@ -0,0 +1,179 @@
+using System;
+using Xunit;
+
+namespace Platform.RegularExpressions.Transformer.Tests
+{
+ ///
+ ///
+ /// Represents the regex engine tests.
+ ///
+ ///
+ ///
+ public class RegexEngineTests
+ {
+ ///
+ ///
+ /// Tests that system regex engine creates patterns correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SystemRegexEngine_CreatePattern_Test()
+ {
+ var engine = new SystemRegexEngine();
+ var pattern = engine.CreatePattern(@"hello\s+world");
+
+ Assert.NotNull(pattern);
+ Assert.Equal(@"hello\s+world", pattern.Pattern);
+ Assert.Equal("System.Text.RegularExpressions", engine.Name);
+ Assert.True(pattern.IsMatch("hello world"));
+ Assert.True(pattern.IsMatch("hello world"));
+ Assert.False(pattern.IsMatch("helloworld"));
+ }
+
+ ///
+ ///
+ /// Tests that PCRE regex engine creates patterns correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void PcreRegexEngine_CreatePattern_Test()
+ {
+ var engine = new PcreRegexEngine();
+ var pattern = engine.CreatePattern(@"hello\s+world");
+
+ Assert.NotNull(pattern);
+ Assert.Equal(@"hello\s+world", pattern.Pattern);
+ Assert.Equal("PCRE2", engine.Name);
+ Assert.True(pattern.IsMatch("hello world"));
+ Assert.True(pattern.IsMatch("hello world"));
+ Assert.False(pattern.IsMatch("helloworld"));
+ }
+
+ ///
+ ///
+ /// Tests that system regex engine creates patterns with timeout correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SystemRegexEngine_CreatePatternWithTimeout_Test()
+ {
+ var engine = new SystemRegexEngine();
+ var timeout = TimeSpan.FromSeconds(30);
+ var pattern = engine.CreatePattern(@"test", timeout);
+
+ Assert.NotNull(pattern);
+ Assert.Equal(@"test", pattern.Pattern);
+ Assert.Equal(timeout, pattern.MatchTimeout);
+ }
+
+ ///
+ ///
+ /// Tests that PCRE regex engine creates patterns with timeout correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void PcreRegexEngine_CreatePatternWithTimeout_Test()
+ {
+ var engine = new PcreRegexEngine();
+ var timeout = TimeSpan.FromSeconds(30);
+ var pattern = engine.CreatePattern(@"test", timeout);
+
+ Assert.NotNull(pattern);
+ Assert.Equal(@"test", pattern.Pattern);
+ Assert.Equal(timeout, pattern.MatchTimeout);
+ }
+
+ ///
+ ///
+ /// Tests that regex engine factory creates engines correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void RegexEngineFactory_CreateEngine_Test()
+ {
+ var systemEngine = RegexEngineFactory.CreateEngine(RegexEngineType.SystemRegex);
+ var pcreEngine = RegexEngineFactory.CreateEngine(RegexEngineType.PCRE2);
+
+ Assert.IsType(systemEngine);
+ Assert.IsType(pcreEngine);
+ Assert.Equal("System.Text.RegularExpressions", systemEngine.Name);
+ Assert.Equal("PCRE2", pcreEngine.Name);
+ }
+
+ ///
+ ///
+ /// Tests that default engine setting works correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void RegexEngineFactory_DefaultEngine_Test()
+ {
+ // Save original default
+ var originalDefault = RegexEngineFactory.DefaultEngine;
+
+ try
+ {
+ // Test setting PCRE2 as default
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.PCRE2);
+ Assert.IsType(RegexEngineFactory.DefaultEngine);
+ Assert.Equal(RegexEngineType.PCRE2, RegexEngineFactory.GetDefaultEngineType());
+
+ // Test setting System as default
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
+ Assert.IsType(RegexEngineFactory.DefaultEngine);
+ Assert.Equal(RegexEngineType.SystemRegex, RegexEngineFactory.GetDefaultEngineType());
+ }
+ finally
+ {
+ // Restore original default
+ RegexEngineFactory.DefaultEngine = originalDefault;
+ }
+ }
+
+ ///
+ ///
+ /// Tests that pattern replacement works correctly with both engines.
+ ///
+ ///
+ ///
+ [Theory]
+ [InlineData(typeof(SystemRegexEngine))]
+ [InlineData(typeof(PcreRegexEngine))]
+ public void RegexPattern_Replace_Test(Type engineType)
+ {
+ var engine = (IRegexEngine)Activator.CreateInstance(engineType)!;
+ var pattern = engine.CreatePattern(@"\b\d{4}\b");
+
+ var input = "The year 2024 was amazing, unlike 2023.";
+ var result = pattern.Replace(input, "XXXX");
+
+ Assert.Equal("The year XXXX was amazing, unlike XXXX.", result);
+ }
+
+ ///
+ ///
+ /// Tests that pattern WithTimeout works correctly.
+ ///
+ ///
+ ///
+ [Fact]
+ public void RegexPattern_WithTimeout_Test()
+ {
+ var engine = new SystemRegexEngine();
+ var pattern = engine.CreatePattern(@"test");
+ var newTimeout = TimeSpan.FromMinutes(2);
+
+ var newPattern = pattern.WithTimeout(newTimeout);
+
+ Assert.NotEqual(pattern.MatchTimeout, newPattern.MatchTimeout);
+ Assert.Equal(newTimeout, newPattern.MatchTimeout);
+ Assert.Equal(pattern.Pattern, newPattern.Pattern);
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleEngineTests.cs b/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleEngineTests.cs
new file mode 100644
index 0000000..2747325
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleEngineTests.cs
@@ -0,0 +1,215 @@
+using System;
+using System.Text.RegularExpressions;
+using Xunit;
+
+namespace Platform.RegularExpressions.Transformer.Tests
+{
+ ///
+ ///
+ /// Represents the substitution rule engine tests.
+ ///
+ ///
+ ///
+ public class SubstitutionRuleEngineTests
+ {
+ ///
+ ///
+ /// Tests that SubstitutionRule works with SystemRegex engine.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SubstitutionRule_SystemRegexEngine_Test()
+ {
+ var engine = new SystemRegexEngine();
+ var pattern = engine.CreatePattern(@"hello");
+ var rule = new SubstitutionRule(pattern, "hi");
+
+ Assert.NotNull(rule.MatchPattern);
+ Assert.Equal("hello", rule.MatchPattern.Pattern);
+ Assert.Equal("hi", rule.SubstitutionPattern);
+ Assert.IsType(rule.MatchPattern);
+ }
+
+ ///
+ ///
+ /// Tests that SubstitutionRule works with PCRE2 engine.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SubstitutionRule_PcreEngine_Test()
+ {
+ var engine = new PcreRegexEngine();
+ var pattern = engine.CreatePattern(@"hello");
+ var rule = new SubstitutionRule(pattern, "hi");
+
+ Assert.NotNull(rule.MatchPattern);
+ Assert.Equal("hello", rule.MatchPattern.Pattern);
+ Assert.Equal("hi", rule.SubstitutionPattern);
+ Assert.IsType(rule.MatchPattern);
+ }
+
+ ///
+ ///
+ /// Tests that SubstitutionRule implicit conversion uses default engine.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SubstitutionRule_ImplicitConversion_UsesDefaultEngine_Test()
+ {
+ // Save original default
+ var originalDefault = RegexEngineFactory.DefaultEngine;
+
+ try
+ {
+ // Test with System regex as default
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
+ SubstitutionRule rule1 = ("hello", "hi");
+ Assert.IsType(rule1.MatchPattern);
+
+ // Test with PCRE2 as default
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.PCRE2);
+ SubstitutionRule rule2 = ("hello", "hi");
+ Assert.IsType(rule2.MatchPattern);
+ }
+ finally
+ {
+ // Restore original default
+ RegexEngineFactory.DefaultEngine = originalDefault;
+ }
+ }
+
+ ///
+ ///
+ /// Tests that legacy Regex constructor still works.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SubstitutionRule_LegacyRegexConstructor_Test()
+ {
+ var regex = new Regex("hello");
+ var rule = new SubstitutionRule(regex, "hi");
+
+ Assert.NotNull(rule.MatchPattern);
+ Assert.Equal("hello", rule.MatchPattern.Pattern);
+ Assert.Equal("hi", rule.SubstitutionPattern);
+ Assert.NotNull(rule.LegacyMatchPattern);
+ Assert.Equal("hello", rule.LegacyMatchPattern.ToString());
+ }
+
+ ///
+ ///
+ /// Tests backward compatibility through LegacyMatchPattern property.
+ ///
+ ///
+ ///
+ [Fact]
+ public void SubstitutionRule_LegacyMatchPattern_BackwardCompatibility_Test()
+ {
+ // Test with SystemRegexPattern
+ var systemEngine = new SystemRegexEngine();
+ var systemPattern = systemEngine.CreatePattern(@"test");
+ var systemRule = new SubstitutionRule(systemPattern, "replacement");
+
+ Assert.NotNull(systemRule.LegacyMatchPattern);
+ Assert.IsType(systemRule.LegacyMatchPattern);
+ Assert.Equal("test", systemRule.LegacyMatchPattern.ToString());
+
+ // Test with PcreRegexPattern
+ var pcreEngine = new PcreRegexEngine();
+ var pcrePattern = pcreEngine.CreatePattern(@"test");
+ var pcreRule = new SubstitutionRule(pcrePattern, "replacement");
+
+ Assert.NotNull(pcreRule.LegacyMatchPattern);
+ Assert.IsType(pcreRule.LegacyMatchPattern);
+ Assert.Equal("test", pcreRule.LegacyMatchPattern.ToString());
+ }
+
+ ///
+ ///
+ /// Tests that TextTransformer works with different regex engines.
+ ///
+ ///
+ ///
+ [Theory]
+ [InlineData(typeof(SystemRegexEngine))]
+ [InlineData(typeof(PcreRegexEngine))]
+ public void TextTransformer_WithDifferentEngines_Test(Type engineType)
+ {
+ var engine = (IRegexEngine)Activator.CreateInstance(engineType)!;
+ var pattern = engine.CreatePattern(@"\b\d{4}\b");
+ var rule = new SubstitutionRule(pattern, "YEAR");
+
+ var transformer = new TextTransformer(new[] { rule });
+ var input = "In 2024, we had great success.";
+ var result = transformer.Transform(input);
+
+ Assert.Equal("In YEAR, we had great success.", result);
+ }
+
+ ///
+ ///
+ /// Tests that both engines produce equivalent results for common patterns.
+ ///
+ ///
+ ///
+ [Theory]
+ [InlineData(@"\d+", "abc123def", "XXX", "abcXXXdef")]
+ [InlineData(@"\s+", "hello world", "_", "hello_world")]
+ [InlineData(@"[A-Z]+", "Hello WORLD Test", "***", "***ello *** ***est")]
+ public void BothEngines_ProduceEquivalentResults_Test(string pattern, string input, string replacement, string expected)
+ {
+ var systemEngine = new SystemRegexEngine();
+ var pcreEngine = new PcreRegexEngine();
+
+ var systemPattern = systemEngine.CreatePattern(pattern);
+ var pcrePattern = pcreEngine.CreatePattern(pattern);
+
+ var systemResult = systemPattern.Replace(input, replacement);
+ var pcreResult = pcrePattern.Replace(input, replacement);
+
+ Assert.Equal(expected, systemResult);
+ Assert.Equal(expected, pcreResult);
+ Assert.Equal(systemResult, pcreResult);
+ }
+
+ ///
+ ///
+ /// Tests that engine switching works correctly during runtime.
+ ///
+ ///
+ ///
+ [Fact]
+ public void RegexEngine_SwitchingDuringRuntime_Test()
+ {
+ // Save original default
+ var originalDefault = RegexEngineFactory.DefaultEngine;
+
+ try
+ {
+ // Create rules with specific engines to demonstrate both engines work
+ var systemEngine = new SystemRegexEngine();
+ var pcreEngine = new PcreRegexEngine();
+
+ var rule1 = new SubstitutionRule(systemEngine.CreatePattern(@"\d+"), "123");
+ var rule2 = new SubstitutionRule(pcreEngine.CreatePattern(@"[A-Z]"), "X");
+
+ var transformer = new TextTransformer(new[] { rule1, rule2 });
+ var result = transformer.Transform("A1B2C");
+
+ // The rules are applied sequentially, so "A1B2C" becomes:
+ // 1. rule1 applies: "A1B2C" -> "A123B123C" (1,2 -> 123)
+ // 2. rule2 applies: "A123B123C" -> "X123X123X" (A,B,C -> X)
+ Assert.Equal("X123X123X", result);
+ }
+ finally
+ {
+ // Restore original default
+ RegexEngineFactory.DefaultEngine = originalDefault;
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleTests.cs b/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleTests.cs
index 2c9e2fc..42b3d81 100644
--- a/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleTests.cs
+++ b/csharp/Platform.RegularExpressions.Transformer.Tests/SubstitutionRuleTests.cs
@@ -21,7 +21,7 @@ public class SubstitutionRuleTests
public void OptionsOverrideTest()
{
SubstitutionRule rule = (new Regex(@"^\s*?\#pragma[\sa-zA-Z0-9\/]+$"), "", 0);
- Assert.Equal(RegexOptions.Compiled | RegexOptions.Multiline, rule.MatchPattern.Options);
+ Assert.Equal(RegexOptions.Compiled | RegexOptions.Multiline, rule.LegacyMatchPattern.Options);
}
}
}
diff --git a/csharp/Platform.RegularExpressions.Transformer/IRegexEngine.cs b/csharp/Platform.RegularExpressions.Transformer/IRegexEngine.cs
new file mode 100644
index 0000000..4a3c18c
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/IRegexEngine.cs
@@ -0,0 +1,66 @@
+using System;
+using System.Runtime.CompilerServices;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Defines the regex engine interface for creating regex patterns.
+ ///
+ ///
+ ///
+ public interface IRegexEngine
+ {
+ ///
+ ///
+ /// Gets the name of the regex engine.
+ ///
+ ///
+ ///
+ string Name
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get;
+ }
+
+ ///
+ ///
+ /// Creates a regex pattern from the specified pattern string.
+ ///
+ ///
+ ///
+ ///
+ /// The regex pattern string.
+ ///
+ ///
+ ///
+ /// A regex pattern instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ IRegexPattern CreatePattern(string pattern);
+
+ ///
+ ///
+ /// Creates a regex pattern from the specified pattern string with timeout.
+ ///
+ ///
+ ///
+ ///
+ /// The regex pattern string.
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ ///
+ /// A regex pattern instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ IRegexPattern CreatePattern(string pattern, TimeSpan timeout);
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/IRegexPattern.cs b/csharp/Platform.RegularExpressions.Transformer/IRegexPattern.cs
new file mode 100644
index 0000000..5a3a6e3
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/IRegexPattern.cs
@@ -0,0 +1,95 @@
+using System;
+using System.Runtime.CompilerServices;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Defines the regex pattern interface that abstracts different regex engines.
+ ///
+ ///
+ ///
+ public interface IRegexPattern
+ {
+ ///
+ ///
+ /// Gets the pattern string value.
+ ///
+ ///
+ ///
+ string Pattern
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get;
+ }
+
+ ///
+ ///
+ /// Gets the timeout value.
+ ///
+ ///
+ ///
+ TimeSpan MatchTimeout
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get;
+ }
+
+ ///
+ ///
+ /// Determines whether the specified input matches the pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ ///
+ /// True if the pattern matches; otherwise, false.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ bool IsMatch(string input);
+
+ ///
+ ///
+ /// Replaces all matches in the input string with the replacement pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ ///
+ /// The replacement pattern.
+ ///
+ ///
+ ///
+ /// The modified string with replacements.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ string Replace(string input, string replacement);
+
+ ///
+ ///
+ /// Creates a new regex pattern with overridden options.
+ ///
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ ///
+ /// A new regex pattern with the specified timeout.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ IRegexPattern WithTimeout(TimeSpan timeout);
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/ISubstitutionRule.cs b/csharp/Platform.RegularExpressions.Transformer/ISubstitutionRule.cs
index f24e825..fefad51 100644
--- a/csharp/Platform.RegularExpressions.Transformer/ISubstitutionRule.cs
+++ b/csharp/Platform.RegularExpressions.Transformer/ISubstitutionRule.cs
@@ -19,7 +19,7 @@ public interface ISubstitutionRule
///
///
///
- Regex MatchPattern
+ IRegexPattern MatchPattern
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
@@ -48,5 +48,17 @@ int MaximumRepeatCount
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
}
+
+ ///
+ ///
+ /// Gets the legacy System.Text.RegularExpressions.Regex pattern for backward compatibility.
+ ///
+ ///
+ ///
+ Regex LegacyMatchPattern
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get;
+ }
}
}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/PcreRegexEngine.cs b/csharp/Platform.RegularExpressions.Transformer/PcreRegexEngine.cs
new file mode 100644
index 0000000..f86d2d7
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/PcreRegexEngine.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Runtime.CompilerServices;
+using PCRE;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Represents a regex engine implementation using PCRE.NET.
+ ///
+ ///
+ ///
+ public class PcreRegexEngine : IRegexEngine
+ {
+ ///
+ ///
+ /// The default PCRE options for the PCRE regex engine.
+ ///
+ ///
+ ///
+ public static readonly PcreOptions DefaultPcreOptions = PcreOptions.Compiled | PcreOptions.MultiLine;
+
+ ///
+ ///
+ /// The default match timeout for the PCRE regex engine.
+ ///
+ ///
+ ///
+ public static readonly TimeSpan DefaultMatchTimeout = TimeSpan.FromMinutes(5);
+
+ private readonly PcreOptions _options;
+ private readonly TimeSpan _defaultTimeout;
+
+ ///
+ ///
+ /// Gets the name of the regex engine.
+ ///
+ ///
+ ///
+ public string Name
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => "PCRE2";
+ }
+
+ ///
+ ///
+ /// Initializes a new instance.
+ ///
+ ///
+ ///
+ ///
+ /// The default PCRE options.
+ ///
+ ///
+ ///
+ /// The default match timeout.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public PcreRegexEngine(PcreOptions options, TimeSpan defaultTimeout)
+ {
+ _options = options;
+ _defaultTimeout = defaultTimeout;
+ }
+
+ ///
+ ///
+ /// Initializes a new instance with default options.
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public PcreRegexEngine() : this(DefaultPcreOptions, DefaultMatchTimeout)
+ {
+ }
+
+ ///
+ ///
+ /// Creates a regex pattern from the specified pattern string.
+ ///
+ ///
+ ///
+ ///
+ /// The regex pattern string.
+ ///
+ ///
+ ///
+ /// A regex pattern instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public IRegexPattern CreatePattern(string pattern)
+ {
+ var regex = new PcreRegex(pattern, _options);
+ return new PcreRegexPattern(regex, _defaultTimeout);
+ }
+
+ ///
+ ///
+ /// Creates a regex pattern from the specified pattern string with timeout.
+ ///
+ ///
+ ///
+ ///
+ /// The regex pattern string.
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ ///
+ /// A regex pattern instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public IRegexPattern CreatePattern(string pattern, TimeSpan timeout)
+ {
+ var regex = new PcreRegex(pattern, _options);
+ return new PcreRegexPattern(regex, timeout);
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/PcreRegexPattern.cs b/csharp/Platform.RegularExpressions.Transformer/PcreRegexPattern.cs
new file mode 100644
index 0000000..6909aa7
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/PcreRegexPattern.cs
@@ -0,0 +1,160 @@
+using System;
+using System.Runtime.CompilerServices;
+using PCRE;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Represents a regex pattern implementation using PCRE.NET.
+ ///
+ ///
+ ///
+ public class PcreRegexPattern : IRegexPattern
+ {
+ private readonly PcreRegex _regex;
+ private readonly TimeSpan _timeout;
+
+ ///
+ ///
+ /// Gets the pattern string value.
+ ///
+ ///
+ ///
+ public string Pattern
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _regex.ToString();
+ }
+
+ ///
+ ///
+ /// Gets the timeout value.
+ ///
+ ///
+ ///
+ public TimeSpan MatchTimeout
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _timeout;
+ }
+
+ ///
+ ///
+ /// Gets the underlying PCRE.NET regex instance.
+ ///
+ ///
+ ///
+ public PcreRegex UnderlyingRegex
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _regex;
+ }
+
+ ///
+ ///
+ /// Initializes a new instance.
+ ///
+ ///
+ ///
+ ///
+ /// The underlying PCRE regex instance.
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public PcreRegexPattern(PcreRegex regex, TimeSpan timeout)
+ {
+ _regex = regex ?? throw new ArgumentNullException(nameof(regex));
+ _timeout = timeout;
+ }
+
+ ///
+ ///
+ /// Determines whether the specified input matches the pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ ///
+ /// True if the pattern matches; otherwise, false.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsMatch(string input)
+ {
+ if (input == null)
+ return false;
+
+ return _regex.IsMatch(input);
+ }
+
+ ///
+ ///
+ /// Replaces all matches in the input string with the replacement pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ ///
+ /// The replacement pattern.
+ ///
+ ///
+ ///
+ /// The modified string with replacements.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public string Replace(string input, string replacement)
+ {
+ if (input == null)
+ return null;
+
+ return _regex.Replace(input, replacement);
+ }
+
+ ///
+ ///
+ /// Creates a new regex pattern with overridden options.
+ ///
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ ///
+ /// A new regex pattern with the specified timeout.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public IRegexPattern WithTimeout(TimeSpan timeout)
+ {
+ return new PcreRegexPattern(_regex, timeout);
+ }
+
+ ///
+ ///
+ /// Returns the string representation of the regex pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The pattern string.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override string ToString() => _regex.ToString();
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/Platform.RegularExpressions.Transformer.csproj b/csharp/Platform.RegularExpressions.Transformer/Platform.RegularExpressions.Transformer.csproj
index e39f96a..a13f2fe 100644
--- a/csharp/Platform.RegularExpressions.Transformer/Platform.RegularExpressions.Transformer.csproj
+++ b/csharp/Platform.RegularExpressions.Transformer/Platform.RegularExpressions.Transformer.csproj
@@ -4,12 +4,12 @@
LinksPlatform's Platform.RegularExpressions.Transformer Class Library
Konstantin Diachenko
Platform.RegularExpressions.Transformer
- 0.3.4
+ 0.4.0
Konstantin Diachenko
net8
Platform.RegularExpressions.Transformer
Platform.RegularExpressions.Transformer
- LinksPlatform;RegularExpressions.Transformer;IContext;ISubstitutionRule;ITransformer;Context;RegexExtensions;SubstitutionRule;Transformer;TransformerCLI
+ LinksPlatform;RegularExpressions.Transformer;IContext;ISubstitutionRule;ITransformer;Context;RegexExtensions;SubstitutionRule;Transformer;TransformerCLI;PCRE;PCRE2;RegexEngine;RegexEngineFactory
https://raw.githubusercontent.com/linksplatform/Documentation/18469f4d033ee9a5b7b84caab9c585acab2ac519/doc/Avatar-rainbow-icon-64x64.png
https://linksplatform.github.io/RegularExpressions.Transformer
Unlicensed
@@ -23,7 +23,7 @@
true
snupkg
latest
- Update target framework from net7 to net8.
+ Add support for PCRE2 regex engine. Users can now switch between System.Text.RegularExpressions and PCRE2 engines using RegexEngineFactory. Includes backward compatibility with existing code.
true
enable
@@ -34,6 +34,7 @@
+
diff --git a/csharp/Platform.RegularExpressions.Transformer/RegexEngineFactory.cs b/csharp/Platform.RegularExpressions.Transformer/RegexEngineFactory.cs
new file mode 100644
index 0000000..2501a8f
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/RegexEngineFactory.cs
@@ -0,0 +1,94 @@
+using System;
+using System.Runtime.CompilerServices;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Represents a factory for creating regex engines.
+ ///
+ ///
+ ///
+ public static class RegexEngineFactory
+ {
+ private static IRegexEngine? _defaultEngine;
+
+ ///
+ ///
+ /// Gets or sets the default regex engine used throughout the application.
+ ///
+ ///
+ ///
+ public static IRegexEngine DefaultEngine
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _defaultEngine ??= CreateEngine(RegexEngineType.SystemRegex);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ set => _defaultEngine = value ?? throw new ArgumentNullException(nameof(value));
+ }
+
+ ///
+ ///
+ /// Creates a regex engine of the specified type.
+ ///
+ ///
+ ///
+ ///
+ /// The type of regex engine to create.
+ ///
+ ///
+ ///
+ /// A regex engine instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IRegexEngine CreateEngine(RegexEngineType engineType)
+ {
+ return engineType switch
+ {
+ RegexEngineType.SystemRegex => new SystemRegexEngine(),
+ RegexEngineType.PCRE2 => new PcreRegexEngine(),
+ _ => throw new ArgumentOutOfRangeException(nameof(engineType), engineType, "Unknown regex engine type")
+ };
+ }
+
+ ///
+ ///
+ /// Sets the default regex engine type for the application.
+ ///
+ ///
+ ///
+ ///
+ /// The type of regex engine to use as default.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void SetDefaultEngine(RegexEngineType engineType)
+ {
+ DefaultEngine = CreateEngine(engineType);
+ }
+
+ ///
+ ///
+ /// Gets the current default engine type.
+ ///
+ ///
+ ///
+ ///
+ /// The current default engine type.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static RegexEngineType GetDefaultEngineType()
+ {
+ return DefaultEngine switch
+ {
+ SystemRegexEngine => RegexEngineType.SystemRegex,
+ PcreRegexEngine => RegexEngineType.PCRE2,
+ _ => RegexEngineType.SystemRegex
+ };
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/RegexEngineType.cs b/csharp/Platform.RegularExpressions.Transformer/RegexEngineType.cs
new file mode 100644
index 0000000..ee153e9
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/RegexEngineType.cs
@@ -0,0 +1,31 @@
+using System.Runtime.CompilerServices;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Represents the available regex engine types.
+ ///
+ ///
+ ///
+ public enum RegexEngineType
+ {
+ ///
+ ///
+ /// System.Text.RegularExpressions engine (default .NET regex engine).
+ ///
+ ///
+ ///
+ SystemRegex = 0,
+
+ ///
+ ///
+ /// PCRE2 engine (Perl Compatible Regular Expressions).
+ ///
+ ///
+ ///
+ PCRE2 = 1
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/RegexExtensions.cs b/csharp/Platform.RegularExpressions.Transformer/RegexExtensions.cs
index fd56eb9..c7651a3 100644
--- a/csharp/Platform.RegularExpressions.Transformer/RegexExtensions.cs
+++ b/csharp/Platform.RegularExpressions.Transformer/RegexExtensions.cs
@@ -45,5 +45,21 @@ public static Regex OverrideOptions(this Regex regex, RegexOptions options, Time
}
return new Regex(regex.ToString(), options, matchTimeout);
}
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static IRegexPattern OverrideOptions(this IRegexPattern pattern, RegexOptions options, TimeSpan matchTimeout)
+ {
+ if (pattern == null)
+ {
+ return null;
+ }
+
+ if (pattern is SystemRegexPattern systemPattern)
+ {
+ return new SystemRegexPattern(systemPattern.UnderlyingRegex.OverrideOptions(options, matchTimeout));
+ }
+
+ return pattern.WithTimeout(matchTimeout);
+ }
}
}
diff --git a/csharp/Platform.RegularExpressions.Transformer/SubstitutionRule.cs b/csharp/Platform.RegularExpressions.Transformer/SubstitutionRule.cs
index 150343a..7866928 100644
--- a/csharp/Platform.RegularExpressions.Transformer/SubstitutionRule.cs
+++ b/csharp/Platform.RegularExpressions.Transformer/SubstitutionRule.cs
@@ -37,7 +37,7 @@ public class SubstitutionRule : ISubstitutionRule
///
///
///
- public Regex MatchPattern
+ public IRegexPattern MatchPattern
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
@@ -45,6 +45,28 @@ public Regex MatchPattern
set;
}
+ ///
+ ///
+ /// Gets the legacy System.Text.RegularExpressions.Regex pattern for backward compatibility.
+ ///
+ ///
+ ///
+ public Regex LegacyMatchPattern
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ if (MatchPattern is SystemRegexPattern systemPattern)
+ {
+ return systemPattern.UnderlyingRegex;
+ }
+
+ // For PCRE patterns, create a fallback System.Text.RegularExpressions.Regex
+ // This maintains backward compatibility but may not have exact feature parity
+ return new Regex(MatchPattern.Pattern, SubstitutionRule.DefaultMatchPatternRegexOptions, MatchPattern.MatchTimeout);
+ }
+ }
+
///
///
/// Gets or sets the substitution pattern value.
@@ -65,7 +87,7 @@ public string SubstitutionPattern
///
///
///
- public Regex PathPattern
+ public IRegexPattern? PathPattern
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get;
@@ -73,6 +95,30 @@ public Regex PathPattern
set;
}
+ ///
+ ///
+ /// Gets the legacy System.Text.RegularExpressions.Regex path pattern for backward compatibility.
+ ///
+ ///
+ ///
+ public Regex? LegacyPathPattern
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get
+ {
+ if (PathPattern == null)
+ return null;
+
+ if (PathPattern is SystemRegexPattern systemPattern)
+ {
+ return systemPattern.UnderlyingRegex;
+ }
+
+ // For PCRE patterns, create a fallback System.Text.RegularExpressions.Regex
+ return new Regex(PathPattern.Pattern, SubstitutionRule.DefaultMatchPatternRegexOptions, PathPattern.MatchTimeout);
+ }
+ }
+
///
///
/// Gets or sets the maximum repeat count value.
@@ -105,6 +151,49 @@ public int MaximumRepeatCount
/// A maximum repeat count.
///
///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public SubstitutionRule(IRegexPattern matchPattern, string substitutionPattern, int maximumRepeatCount)
+ {
+ MatchPattern = matchPattern;
+ SubstitutionPattern = substitutionPattern;
+ MaximumRepeatCount = maximumRepeatCount;
+ }
+
+ ///
+ ///
+ /// Initializes a new instance.
+ ///
+ ///
+ ///
+ ///
+ /// A match pattern.
+ ///
+ ///
+ ///
+ /// A substitution pattern.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public SubstitutionRule(IRegexPattern matchPattern, string substitutionPattern) : this(matchPattern, substitutionPattern, 0) { }
+
+ ///
+ ///
+ /// Initializes a new instance with legacy System.Text.RegularExpressions.Regex.
+ ///
+ ///
+ ///
+ ///
+ /// A match pattern.
+ ///
+ ///
+ ///
+ /// A substitution pattern.
+ ///
+ ///
+ ///
+ /// A maximum repeat count.
+ ///
+ ///
///
/// A match pattern options.
///
@@ -116,7 +205,9 @@ public int MaximumRepeatCount
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public SubstitutionRule(Regex matchPattern, string substitutionPattern, int maximumRepeatCount, RegexOptions? matchPatternOptions, TimeSpan? matchTimeout)
{
- MatchPattern = matchPattern;
+ var engine = RegexEngineFactory.DefaultEngine;
+ var pattern = engine.CreatePattern(matchPattern.ToString(), matchTimeout ?? matchPattern.MatchTimeout);
+ MatchPattern = pattern;
SubstitutionPattern = substitutionPattern;
MaximumRepeatCount = maximumRepeatCount;
OverrideMatchPatternOptions(matchPatternOptions ?? matchPattern.Options, matchTimeout ?? matchPattern.MatchTimeout);
@@ -124,7 +215,7 @@ public SubstitutionRule(Regex matchPattern, string substitutionPattern, int maxi
///
///
- /// Initializes a new instance.
+ /// Initializes a new instance with legacy System.Text.RegularExpressions.Regex.
///
///
///
@@ -149,7 +240,7 @@ public SubstitutionRule(Regex matchPattern, string substitutionPattern, int maxi
///
///
- /// Initializes a new instance.
+ /// Initializes a new instance with legacy System.Text.RegularExpressions.Regex.
///
///
///
@@ -170,7 +261,7 @@ public SubstitutionRule(Regex matchPattern, string substitutionPattern, int maxi
///
///
- /// Initializes a new instance.
+ /// Initializes a new instance with legacy System.Text.RegularExpressions.Regex.
///
///
///
@@ -186,17 +277,23 @@ public SubstitutionRule(Regex matchPattern, string substitutionPattern, int maxi
public SubstitutionRule(Regex matchPattern, string substitutionPattern) : this(matchPattern, substitutionPattern, 0) { }
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(new Regex(tuple.Item1), tuple.Item2);
+ public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(RegexEngineFactory.DefaultEngine.CreatePattern(tuple.Item1), tuple.Item2);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(tuple.Item1, tuple.Item2);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(new Regex(tuple.Item1), tuple.Item2, tuple.Item3);
+ public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(RegexEngineFactory.DefaultEngine.CreatePattern(tuple.Item1), tuple.Item2, tuple.Item3);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(tuple.Item1, tuple.Item2, tuple.Item3);
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(tuple.Item1, tuple.Item2);
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static implicit operator SubstitutionRule(ValueTuple tuple) => new SubstitutionRule(tuple.Item1, tuple.Item2, tuple.Item3);
+
///
///
/// Overrides the match pattern options using the specified options.
@@ -212,7 +309,17 @@ public SubstitutionRule(Regex matchPattern, string substitutionPattern) : this(m
///
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OverrideMatchPatternOptions(RegexOptions options, TimeSpan matchTimeout) => MatchPattern = MatchPattern.OverrideOptions(options, matchTimeout);
+ public void OverrideMatchPatternOptions(RegexOptions options, TimeSpan matchTimeout)
+ {
+ if (MatchPattern is SystemRegexPattern systemPattern)
+ {
+ MatchPattern = new SystemRegexPattern(systemPattern.UnderlyingRegex.OverrideOptions(options, matchTimeout));
+ }
+ else
+ {
+ MatchPattern = MatchPattern.WithTimeout(matchTimeout);
+ }
+ }
///
///
@@ -229,7 +336,20 @@ public SubstitutionRule(Regex matchPattern, string substitutionPattern) : this(m
///
///
[MethodImpl(MethodImplOptions.AggressiveInlining)]
- public void OverridePathPatternOptions(RegexOptions options, TimeSpan matchTimeout) => PathPattern = PathPattern.OverrideOptions(options, matchTimeout);
+ public void OverridePathPatternOptions(RegexOptions options, TimeSpan matchTimeout)
+ {
+ if (PathPattern == null)
+ return;
+
+ if (PathPattern is SystemRegexPattern systemPattern)
+ {
+ PathPattern = new SystemRegexPattern(systemPattern.UnderlyingRegex.OverrideOptions(options, matchTimeout));
+ }
+ else
+ {
+ PathPattern = PathPattern.WithTimeout(matchTimeout);
+ }
+ }
///
///
@@ -246,7 +366,7 @@ public override string ToString()
{
var sb = new StringBuilder();
sb.Append('"');
- sb.Append(MatchPattern.ToString());
+ sb.Append(MatchPattern?.ToString() ?? "");
sb.Append('"');
sb.Append(" -> ");
sb.Append('"');
diff --git a/csharp/Platform.RegularExpressions.Transformer/SystemRegexEngine.cs b/csharp/Platform.RegularExpressions.Transformer/SystemRegexEngine.cs
new file mode 100644
index 0000000..06edf97
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/SystemRegexEngine.cs
@@ -0,0 +1,126 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Represents a regex engine implementation using System.Text.RegularExpressions.
+ ///
+ ///
+ ///
+ public class SystemRegexEngine : IRegexEngine
+ {
+ ///
+ ///
+ /// The default regex options for the System regex engine.
+ ///
+ ///
+ ///
+ public static readonly RegexOptions DefaultRegexOptions = RegexOptions.Compiled | RegexOptions.Multiline;
+
+ ///
+ ///
+ /// The default match timeout for the System regex engine.
+ ///
+ ///
+ ///
+ public static readonly TimeSpan DefaultMatchTimeout = TimeSpan.FromMinutes(5);
+
+ private readonly RegexOptions _options;
+ private readonly TimeSpan _defaultTimeout;
+
+ ///
+ ///
+ /// Gets the name of the regex engine.
+ ///
+ ///
+ ///
+ public string Name
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => "System.Text.RegularExpressions";
+ }
+
+ ///
+ ///
+ /// Initializes a new instance.
+ ///
+ ///
+ ///
+ ///
+ /// The default regex options.
+ ///
+ ///
+ ///
+ /// The default match timeout.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public SystemRegexEngine(RegexOptions options, TimeSpan defaultTimeout)
+ {
+ _options = options;
+ _defaultTimeout = defaultTimeout;
+ }
+
+ ///
+ ///
+ /// Initializes a new instance with default options.
+ ///
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public SystemRegexEngine() : this(DefaultRegexOptions, DefaultMatchTimeout)
+ {
+ }
+
+ ///
+ ///
+ /// Creates a regex pattern from the specified pattern string.
+ ///
+ ///
+ ///
+ ///
+ /// The regex pattern string.
+ ///
+ ///
+ ///
+ /// A regex pattern instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public IRegexPattern CreatePattern(string pattern)
+ {
+ var regex = new Regex(pattern, _options, _defaultTimeout);
+ return new SystemRegexPattern(regex);
+ }
+
+ ///
+ ///
+ /// Creates a regex pattern from the specified pattern string with timeout.
+ ///
+ ///
+ ///
+ ///
+ /// The regex pattern string.
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ ///
+ /// A regex pattern instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public IRegexPattern CreatePattern(string pattern, TimeSpan timeout)
+ {
+ var regex = new Regex(pattern, _options, timeout);
+ return new SystemRegexPattern(regex);
+ }
+ }
+}
\ No newline at end of file
diff --git a/csharp/Platform.RegularExpressions.Transformer/SystemRegexPattern.cs b/csharp/Platform.RegularExpressions.Transformer/SystemRegexPattern.cs
new file mode 100644
index 0000000..a9f216c
--- /dev/null
+++ b/csharp/Platform.RegularExpressions.Transformer/SystemRegexPattern.cs
@@ -0,0 +1,143 @@
+using System;
+using System.Runtime.CompilerServices;
+using System.Text.RegularExpressions;
+
+#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
+
+namespace Platform.RegularExpressions.Transformer
+{
+ ///
+ ///
+ /// Represents a regex pattern implementation using System.Text.RegularExpressions.
+ ///
+ ///
+ ///
+ public class SystemRegexPattern : IRegexPattern
+ {
+ private readonly Regex _regex;
+
+ ///
+ ///
+ /// Gets the pattern string value.
+ ///
+ ///
+ ///
+ public string Pattern
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _regex.ToString();
+ }
+
+ ///
+ ///
+ /// Gets the timeout value.
+ ///
+ ///
+ ///
+ public TimeSpan MatchTimeout
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _regex.MatchTimeout;
+ }
+
+ ///
+ ///
+ /// Gets the underlying System.Text.RegularExpressions.Regex instance.
+ ///
+ ///
+ ///
+ public Regex UnderlyingRegex
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ get => _regex;
+ }
+
+ ///
+ ///
+ /// Initializes a new instance.
+ ///
+ ///
+ ///
+ ///
+ /// The underlying regex instance.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public SystemRegexPattern(Regex regex)
+ {
+ _regex = regex ?? throw new ArgumentNullException(nameof(regex));
+ }
+
+ ///
+ ///
+ /// Determines whether the specified input matches the pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ ///
+ /// True if the pattern matches; otherwise, false.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public bool IsMatch(string input) => _regex.IsMatch(input);
+
+ ///
+ ///
+ /// Replaces all matches in the input string with the replacement pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The input string.
+ ///
+ ///
+ ///
+ /// The replacement pattern.
+ ///
+ ///
+ ///
+ /// The modified string with replacements.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public string Replace(string input, string replacement) => _regex.Replace(input, replacement);
+
+ ///
+ ///
+ /// Creates a new regex pattern with overridden options.
+ ///
+ ///
+ ///
+ ///
+ /// The match timeout.
+ ///
+ ///
+ ///
+ /// A new regex pattern with the specified timeout.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public IRegexPattern WithTimeout(TimeSpan timeout)
+ {
+ var newRegex = new Regex(_regex.ToString(), _regex.Options, timeout);
+ return new SystemRegexPattern(newRegex);
+ }
+
+ ///
+ ///
+ /// Returns the string representation of the regex pattern.
+ ///
+ ///
+ ///
+ ///
+ /// The pattern string.
+ ///
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public override string ToString() => _regex.ToString();
+ }
+}
\ No newline at end of file
diff --git a/examples/RegexEngineDemo.cs b/examples/RegexEngineDemo.cs
new file mode 100644
index 0000000..7fb0d99
--- /dev/null
+++ b/examples/RegexEngineDemo.cs
@@ -0,0 +1,116 @@
+using System;
+using Platform.RegularExpressions.Transformer;
+
+namespace Platform.RegularExpressions.Transformer.Examples
+{
+ ///
+ /// Demonstrates how to use the new PCRE2 regex engine support alongside System.Text.RegularExpressions
+ ///
+ public class RegexEngineDemo
+ {
+ public static void Main(string[] args)
+ {
+ Console.WriteLine("=== PCRE2 Regex Engine Support Demo ===");
+ Console.WriteLine();
+
+ // 1. Default behavior (uses System.Text.RegularExpressions)
+ Console.WriteLine("1. Using default System.Text.RegularExpressions engine:");
+ DemonstrateSystemRegexEngine();
+ Console.WriteLine();
+
+ // 2. Switching to PCRE2 engine
+ Console.WriteLine("2. Switching to PCRE2 engine:");
+ DemonstratePcreEngine();
+ Console.WriteLine();
+
+ // 3. Using both engines in same transformation
+ Console.WriteLine("3. Using both engines in the same transformation:");
+ DemonstrateMixedEngines();
+ Console.WriteLine();
+
+ // 4. Engine switching at runtime
+ Console.WriteLine("4. Runtime engine switching:");
+ DemonstrateRuntimeSwitching();
+ }
+
+ private static void DemonstrateSystemRegexEngine()
+ {
+ // Default engine is System.Text.RegularExpressions
+ SubstitutionRule rule = (@"\b\d{4}\b", "YEAR");
+ var transformer = new TextTransformer(new[] { rule });
+
+ string input = "The years 2023 and 2024 were eventful.";
+ string result = transformer.Transform(input);
+
+ Console.WriteLine($"Input: {input}");
+ Console.WriteLine($"Output: {result}");
+ Console.WriteLine($"Engine: {RegexEngineFactory.DefaultEngine.Name}");
+ }
+
+ private static void DemonstratePcreEngine()
+ {
+ // Switch to PCRE2 engine
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.PCRE2);
+
+ SubstitutionRule rule = (@"\b[A-Z]{3}\b", "***");
+ var transformer = new TextTransformer(new[] { rule });
+
+ string input = "The CEO met with CTO and CFO.";
+ string result = transformer.Transform(input);
+
+ Console.WriteLine($"Input: {input}");
+ Console.WriteLine($"Output: {result}");
+ Console.WriteLine($"Engine: {RegexEngineFactory.DefaultEngine.Name}");
+
+ // Reset to default
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
+ }
+
+ private static void DemonstrateMixedEngines()
+ {
+ // Create engines explicitly
+ var systemEngine = new SystemRegexEngine();
+ var pcreEngine = new PcreRegexEngine();
+
+ // Create rules using different engines
+ var rule1 = new SubstitutionRule(systemEngine.CreatePattern(@"\d+"), "###");
+ var rule2 = new SubstitutionRule(pcreEngine.CreatePattern(@"[A-Z]+"), "XXX");
+
+ var transformer = new TextTransformer(new[] { rule1, rule2 });
+
+ string input = "Order 123 for PRODUCT ABC";
+ string result = transformer.Transform(input);
+
+ Console.WriteLine($"Input: {input}");
+ Console.WriteLine($"Output: {result}");
+ Console.WriteLine($"Rule 1 Engine: {rule1.MatchPattern.GetType().Name} (System.Text.RegularExpressions)");
+ Console.WriteLine($"Rule 2 Engine: {rule2.MatchPattern.GetType().Name} (PCRE2)");
+ }
+
+ private static void DemonstrateRuntimeSwitching()
+ {
+ Console.WriteLine("Creating rules with different engines at runtime...");
+
+ // Start with System engine
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
+ SubstitutionRule rule1 = (@"hello", "hi");
+ Console.WriteLine($"Rule1 created with: {RegexEngineFactory.DefaultEngine.Name}");
+
+ // Switch to PCRE2 engine
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.PCRE2);
+ SubstitutionRule rule2 = (@"world", "universe");
+ Console.WriteLine($"Rule2 created with: {RegexEngineFactory.DefaultEngine.Name}");
+
+ var transformer = new TextTransformer(new[] { rule1, rule2 });
+
+ string input = "hello world";
+ string result = transformer.Transform(input);
+
+ Console.WriteLine($"Input: {input}");
+ Console.WriteLine($"Output: {result}");
+
+ // Reset to default
+ RegexEngineFactory.SetDefaultEngine(RegexEngineType.SystemRegex);
+ }
+ }
+}
\ No newline at end of file