소스 검색

add Value/StringPatternComparer to equals string and simple pattern expression

add tests for qdr.fnd.core
Dalibor Votruba 2 년 전
부모
커밋
8addd1abd2

+ 1 - 0
qdr.fnd.core.test/GlobalUsings.cs

@@ -0,0 +1 @@
+global using NUnit.Framework;

+ 98 - 0
qdr.fnd.core.test/StringPatternComparerTest.cs

@@ -0,0 +1,98 @@
+using Quadarax.Foundation.Core.Value;
+
+namespace qdr.fnd.core.test
+{
+    public class StringPatternComparerTest
+    {
+
+        private StringPatternComparer? _comparer;
+        private string _testSource = "* Dalibor Votruba 1976 *";
+        [SetUp]
+        public void Setup()
+        {
+            _comparer = new StringPatternComparer();
+        }
+
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsAnyTextAny()
+        {
+            var pattern = "*Dalibor*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsAnySpaceTextAny()
+        {
+            var pattern = "*_Dalibor*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsTrue(result);
+        }
+
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsEscTextAny()
+        {
+            var pattern = "/* Dalibor*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsEscTextSpaceAlphaNumNumAny()
+        {
+            var pattern = "/* Dalibor_?#*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsAnySpaceEscText()
+        {
+            var pattern = "*_/*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsAnyNumericAny()
+        {
+            var pattern = "*#*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void NotEqualsEmptyPattern()
+        {
+            var pattern = string.Empty;
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsFalse(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void NotEqualsOccurences()
+        {
+            var pattern = "*Da#*V*";
+            var result = _comparer?.Equals(_testSource, pattern);
+            Assert.IsFalse(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsEmptySource()
+        {
+            var pattern = string.Empty;
+            var source = string.Empty;
+            var result = _comparer?.Equals(source, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsNullSourceNullPattern()
+        {
+            string? pattern = null;
+            string? source = null;
+            var result = _comparer?.Equals(source, pattern);
+            Assert.IsTrue(result);
+        }
+        [Test(TestOf = typeof(StringPatternComparer))]
+        public void EqualsSourceShorterThanPattern()
+        {
+            var pattern = "*A";
+            var source = "A";
+            var result = _comparer?.Equals(source, pattern);
+            Assert.IsTrue(result);
+        }
+    }
+}

+ 28 - 0
qdr.fnd.core.test/qdr.fnd.core.test.csproj

@@ -0,0 +1,28 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net7.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+
+    <IsPackable>false</IsPackable>
+    <IsTestProject>true</IsTestProject>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.7.1" />
+    <PackageReference Include="NUnit" Version="3.13.3" />
+    <PackageReference Include="NUnit3TestAdapter" Version="4.4.2" />
+    <PackageReference Include="NUnit.Analyzers" Version="3.6.1" />
+    <PackageReference Include="coverlet.collector" Version="3.2.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\qdr.fnd.core\qdr.fnd.core.csproj" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Folder Include="Value\" />
+  </ItemGroup>
+
+</Project>

+ 120 - 0
qdr.fnd.core/Value/StringPatternComparer.cs

@@ -0,0 +1,120 @@
+using System;
+using System.Collections.Generic;
+
+namespace Quadarax.Foundation.Core.Value
+{
+    public class StringPatternComparer:IEqualityComparer<string>
+    {
+        #region *** Constants ***
+
+        public const char CS_DEFAULT_EXCLUSION = '/';
+        public const char CS_DEFAULT_ANYCHARS = '*';
+        public const char CS_DEFAULT_ALPHACHARS = '?';
+        public const char CS_DEFAULT_NUMCHARS = '#';
+        public const char CS_DEFAULT_ALPHANUMCHARS = '%';
+        public const char CS_DEFAULT_SPACECHARS = '_';
+        #endregion
+
+        #region *** Fields ***
+        private readonly char _exclusionChar;
+        private readonly char _anyChars;
+        private readonly char _alphaChars;
+        private readonly char _numChars;
+        private readonly char _spaceChars;
+        private readonly char _alphanumChars;
+        #endregion
+
+        #region *** Constructors ***
+
+        public StringPatternComparer(char exclusionChar = CS_DEFAULT_EXCLUSION, char anyChars = CS_DEFAULT_ANYCHARS,
+            char alphaChars = CS_DEFAULT_ALPHACHARS, char numChars = CS_DEFAULT_NUMCHARS,
+            char alphanumChars = CS_DEFAULT_ALPHANUMCHARS, char spaceChars = CS_DEFAULT_SPACECHARS)
+        {
+            _exclusionChar = exclusionChar;
+            _anyChars = anyChars;
+            _alphaChars = alphaChars;
+            _alphanumChars = alphanumChars;
+            _numChars = numChars;
+            _spaceChars = spaceChars;
+        }
+        #endregion
+
+        #region *** Public Operations ***
+
+        /// <summary>
+        /// Equals method for string pattern comparison. Patterns are:
+        /// Exclusion char: /
+        /// Any chars: * (0 - n)
+        /// Any Alpha chars: ? (0 - n)
+        /// Any numeric chars: # (0 - n)
+        /// Any alphanumeric chars: % (0 - n)
+        /// Any space chars: _ (0 - n)
+        /// </summary>
+        /// <param name="x">First string represents value to compare.</param>
+        /// <param name="y">Second string represents search pattern.</param>
+        /// <returns></returns>
+        public bool Equals(string? x, string? y)
+        {
+            if (string.IsNullOrEmpty(x) && string.IsNullOrEmpty(y)) return true;
+            if (string.IsNullOrEmpty(x) || string.IsNullOrEmpty(y)) return false;
+            
+
+
+            var curIndex = 0;
+            var isExcluded = false;
+            for (var i = 0; i < y.Length; i++)
+            {
+                if (y[i] == _exclusionChar)
+                {
+                    isExcluded = true;
+                    continue;
+                }
+
+                curIndex = IndexOfPattern(x,curIndex, y[i], isExcluded);
+                if (isExcluded)
+                    isExcluded = false;
+
+                if (curIndex == -2 || (curIndex == -1 && i == y.Length - 1))
+                    return false;
+            }
+            return y.Length > 0;
+        }
+
+
+        public int GetHashCode(string obj)
+        {
+            return obj.GetHashCode(StringComparison.InvariantCulture);
+        }
+        #endregion
+        #region *** Private Operations ***
+
+        private int IndexOfPattern(string source, int startIndex, char patternChar, bool isExcluded)
+        {
+            if (startIndex >= source.Length)
+                return -1;
+            if (patternChar == _exclusionChar || patternChar == _anyChars)
+                return startIndex;
+            if (!(patternChar == _alphaChars || patternChar == _numChars || patternChar == _alphanumChars ||
+                  patternChar == _spaceChars) || isExcluded)
+                return source.IndexOf(patternChar, startIndex);
+
+
+            for (var i = startIndex; i < source.Length; i++)
+            {
+                if ((patternChar == _alphaChars && char.IsLetter(source[i]))
+                    || (patternChar == _numChars && char.IsNumber(source[i]))
+                    || (patternChar == _alphanumChars && char.IsLetterOrDigit(source[i]))
+                    || (patternChar == _spaceChars && char.IsWhiteSpace(source[i]))
+                   )
+                    return i;
+            }
+
+            return -2;
+
+        }
+
+
+        #endregion
+
+    }
+}

+ 2 - 1
qdr.fnd.core/releasenotes.md

@@ -2,7 +2,7 @@
 Ordered by version descending
 
 ## 0.0.2.0
-Date:__4.10.2023__
+Date:__17.10.2023__
 - extends Thread/LoopWorker to support external ansync iteration body expression
 - fix Thread/ContiguousWorker to support external ansync iteration body expression
 - add Thread/BasicWorkerContext and extends IWorkerContext to stores CancellationToken
@@ -11,6 +11,7 @@ Date:__4.10.2023__
 - extends Logging/ConsoleLogger to support exclude filter in initialization
 - add Collections/LockedList to support thread safe listng
 - extends Thread/LoopWorker to support custom overlaping iterations
+- add Value/StringPatternComparer to equals string and simple pattern expression
 - fix quality CA
 - minor fixes
 ---

+ 11 - 0
qdr.fnd.sln

@@ -17,6 +17,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.fnd.core.qconsole", "qd
 EndProject
 Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "qdr.fnd.core.web", "qdr.fnd.core.web\qdr.fnd.core.web.csproj", "{E409FF71-FAC0-492A-9C9C-2DCCB52055D9}"
 EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "qdr.fnd.core.test", "qdr.fnd.core.test\qdr.fnd.core.test.csproj", "{B172BF70-17B7-4B8D-8649-EF79254182AB}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Tests", "Tests", "{62EEC894-61DC-4D39-83F6-28FF82F6E758}"
+EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
 		Debug|Any CPU = Debug|Any CPU
@@ -51,10 +55,17 @@ Global
 		{E409FF71-FAC0-492A-9C9C-2DCCB52055D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
 		{E409FF71-FAC0-492A-9C9C-2DCCB52055D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
 		{E409FF71-FAC0-492A-9C9C-2DCCB52055D9}.Release|Any CPU.Build.0 = Release|Any CPU
+		{B172BF70-17B7-4B8D-8649-EF79254182AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{B172BF70-17B7-4B8D-8649-EF79254182AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{B172BF70-17B7-4B8D-8649-EF79254182AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{B172BF70-17B7-4B8D-8649-EF79254182AB}.Release|Any CPU.Build.0 = Release|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
 	EndGlobalSection
+	GlobalSection(NestedProjects) = preSolution
+		{B172BF70-17B7-4B8D-8649-EF79254182AB} = {62EEC894-61DC-4D39-83F6-28FF82F6E758}
+	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {89C7D7E9-6E4B-4A30-A6C8-FDE75DFDEB1B}
 	EndGlobalSection