Added VersionStringComparer
This commit is contained in:
86
AMWD.Common/Comparer/VersionStringComparer.cs
Normal file
86
AMWD.Common/Comparer/VersionStringComparer.cs
Normal file
@@ -0,0 +1,86 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AMWD.Common.Comparer
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a method to compare two <see cref="Version"/> strings.
|
||||
/// </summary>
|
||||
#if NET8_0_OR_GREATER
|
||||
public partial class VersionStringComparer : IComparer<string>
|
||||
{
|
||||
private readonly Regex _versionRegex = VersionRegex();
|
||||
#else
|
||||
|
||||
public class VersionStringComparer : IComparer<string>
|
||||
{
|
||||
private readonly Regex _versionRegex = new("([0-9.]+)");
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Compares two <see cref="Version"/> strings and returns a value indicating
|
||||
/// whether one is less than, equal to, or greater than the other.
|
||||
/// </summary>
|
||||
/// <param name="x">The first version string.</param>
|
||||
/// <param name="y">The second version string.</param>
|
||||
/// <returns>
|
||||
/// A signed integer that indicates the relative values of x and y, as shown in the following table:
|
||||
/// <list type="table">
|
||||
/// <listheader>
|
||||
/// <term>Value</term>
|
||||
/// <description>Meaning</description>
|
||||
/// </listheader>
|
||||
/// <item>
|
||||
/// <term>-1</term>
|
||||
/// <description>x is less than y</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>0</term>
|
||||
/// <description>x equals y</description>
|
||||
/// </item>
|
||||
/// <item>
|
||||
/// <term>1</term>
|
||||
/// <description>x is greater than y</description>
|
||||
/// </item>
|
||||
/// </list>
|
||||
/// </returns>
|
||||
public int Compare(string x, string y)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(x) && string.IsNullOrWhiteSpace(y))
|
||||
return 0;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(x))
|
||||
return -1;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(y))
|
||||
return 1;
|
||||
|
||||
string xMainVersion = _versionRegex.Match(x).Groups[1].Value;
|
||||
string yMainVersion = _versionRegex.Match(y).Groups[1].Value;
|
||||
|
||||
string xAppendix = x.ReplaceStart(xMainVersion, "");
|
||||
string yAppendix = y.ReplaceStart(yMainVersion, "");
|
||||
|
||||
if (xMainVersion.IndexOf('.') < 0)
|
||||
xMainVersion += ".0";
|
||||
|
||||
if (yMainVersion.IndexOf('.') < 0)
|
||||
yMainVersion += ".0";
|
||||
|
||||
var xVersion = Version.Parse(xMainVersion);
|
||||
var yVersion = Version.Parse(yMainVersion);
|
||||
|
||||
int versionResult = xVersion.CompareTo(yVersion);
|
||||
if (versionResult != 0)
|
||||
return versionResult;
|
||||
|
||||
return xAppendix.CompareTo(yAppendix);
|
||||
}
|
||||
|
||||
#if NET8_0_OR_GREATER
|
||||
[GeneratedRegex("([0-9.]+)")]
|
||||
private static partial Regex VersionRegex();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
- `ArReader` and `ArWriter` for Unix archives
|
||||
- `TarReader` and `TarWriter` for TAR archives
|
||||
- `VersionStringComparer` to compare version strings (SemVer)
|
||||
|
||||
### Changed
|
||||
|
||||
|
||||
67
UnitTests/Common/Comparer/VersionStringComparerTests.cs
Normal file
67
UnitTests/Common/Comparer/VersionStringComparerTests.cs
Normal file
@@ -0,0 +1,67 @@
|
||||
using AMWD.Common.Comparer;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
|
||||
namespace UnitTests.Common.Comparer
|
||||
{
|
||||
[TestClass]
|
||||
public class VersionStringComparerTests
|
||||
{
|
||||
[DataTestMethod]
|
||||
[DataRow(null, "0")]
|
||||
[DataRow("", "0")]
|
||||
[DataRow("0", "1")]
|
||||
[DataRow("1.0", "1.1")]
|
||||
[DataRow("1.0.0", "1.0.1")]
|
||||
[DataRow("1.0.0.0", "1.0.0.1")]
|
||||
[DataRow("1.0.0.0-RC1", "1.0.0.0-RC2")]
|
||||
public void ShouldBeLessThan(string x, string y)
|
||||
{
|
||||
// Arrange
|
||||
var comparer = new VersionStringComparer();
|
||||
|
||||
// Act
|
||||
int result = comparer.Compare(x, y);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(-1, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow("0", null)]
|
||||
[DataRow("0", "")]
|
||||
[DataRow("1", "0")]
|
||||
[DataRow("1.1", "1.0")]
|
||||
[DataRow("1.0.1", "1.0.0")]
|
||||
[DataRow("1.0.0.1", "1.0.0.0")]
|
||||
[DataRow("1.0.0.0-RC2", "1.0.0.0-RC1")]
|
||||
public void ShouldBeGreaterThan(string x, string y)
|
||||
{
|
||||
// Arrange
|
||||
var comparer = new VersionStringComparer();
|
||||
|
||||
// Act
|
||||
int result = comparer.Compare(x, y);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(1, result);
|
||||
}
|
||||
|
||||
[DataTestMethod]
|
||||
[DataRow(null, null)]
|
||||
[DataRow("", "")]
|
||||
[DataRow("1", "1")]
|
||||
[DataRow("1.2.3", "1.2.3")]
|
||||
[DataRow("1.2.3-alpha", "1.2.3-alpha")]
|
||||
public void ShouldBeEqual(string x, string y)
|
||||
{
|
||||
// Arrange
|
||||
var comparer = new VersionStringComparer();
|
||||
|
||||
// Act
|
||||
int result = comparer.Compare(x, y);
|
||||
|
||||
// Assert
|
||||
Assert.AreEqual(0, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user