|
|
@@ -0,0 +1,186 @@
|
|
|
+using System.Diagnostics.CodeAnalysis;
|
|
|
+using System.Text.RegularExpressions;
|
|
|
+
|
|
|
+namespace InABox.Database;
|
|
|
+
|
|
|
+public class VersionNumber : IComparable
|
|
|
+{
|
|
|
+ public int MajorVersion { get; }
|
|
|
+ public int MinorVersion { get; }
|
|
|
+ public string Release { get; }
|
|
|
+
|
|
|
+ public bool IsDevelopmentVersion { get; }
|
|
|
+ public bool IsNewStyle { get; private set; }
|
|
|
+
|
|
|
+ public VersionNumber()
|
|
|
+ {
|
|
|
+ IsDevelopmentVersion = true;
|
|
|
+ MajorVersion = 0;
|
|
|
+ MinorVersion = 0;
|
|
|
+ Release = "0";
|
|
|
+ IsNewStyle = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public VersionNumber(int majorVersion, int minorVersion)
|
|
|
+ {
|
|
|
+ IsDevelopmentVersion = false;
|
|
|
+ MajorVersion = majorVersion;
|
|
|
+ MinorVersion = minorVersion;
|
|
|
+ Release = "0";
|
|
|
+ IsNewStyle = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public VersionNumber(int majorVersion, int minorVersion, int release)
|
|
|
+ {
|
|
|
+ IsDevelopmentVersion = false;
|
|
|
+ MajorVersion = majorVersion;
|
|
|
+ MinorVersion = minorVersion;
|
|
|
+ Release = release.ToString();
|
|
|
+ IsNewStyle = true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public VersionNumber(int majorVersion, int minorVersion, string release)
|
|
|
+ {
|
|
|
+ IsDevelopmentVersion = false;
|
|
|
+ MajorVersion = majorVersion;
|
|
|
+ MinorVersion = minorVersion;
|
|
|
+ Release = release;
|
|
|
+ IsNewStyle = false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private static readonly Regex _format =
|
|
|
+ new Regex(
|
|
|
+ @"^(?<major>\d+)\.(?<minor>\d+)(?:(?<oldstyle>[A-Za-z]+)|\.(?<newstyle>\d+))?$",
|
|
|
+ RegexOptions.Compiled);
|
|
|
+
|
|
|
+
|
|
|
+ public static VersionNumber Parse(string versionStr)
|
|
|
+ {
|
|
|
+ if (!TryParse(versionStr, out var _result))
|
|
|
+ throw new FormatException($"'{versionStr}' is not a valid version!");
|
|
|
+ return _result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool TryParse(string versionStr, [NotNullWhen(true)] out VersionNumber? version)
|
|
|
+ {
|
|
|
+ if (versionStr == "???")
|
|
|
+ {
|
|
|
+ version = new();
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ var match = _format.Match(versionStr);
|
|
|
+ if (!match.Success)
|
|
|
+ {
|
|
|
+ version = null;
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (match.Groups["oldstyle"].Success)
|
|
|
+ {
|
|
|
+ version = new(int.Parse(match.Groups["major"].Value),
|
|
|
+ int.Parse(match.Groups["minor"].Value),
|
|
|
+ match.Groups["release"].Value
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+ if (match.Groups["newstyle"].Success)
|
|
|
+ {
|
|
|
+ version = new(int.Parse(match.Groups["major"].Value),
|
|
|
+ int.Parse(match.Groups["minor"].Value),
|
|
|
+ int.Parse(match.Groups["newstyle"].Value)
|
|
|
+ );
|
|
|
+ }
|
|
|
+ version = new(int.Parse(match.Groups["major"].Value),
|
|
|
+ int.Parse(match.Groups["minor"].Value),
|
|
|
+ 0
|
|
|
+ );
|
|
|
+
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+
|
|
|
+ public int CompareTo(object? obj)
|
|
|
+ {
|
|
|
+ if (obj is not VersionNumber other)
|
|
|
+ throw new ArgumentException($"Object must be of type {nameof(VersionNumber)}");
|
|
|
+ var _result = this < other ? -1 : this == other ? 0 : 1;
|
|
|
+ return _result;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool operator <(VersionNumber a, VersionNumber b)
|
|
|
+ {
|
|
|
+ if (a.IsDevelopmentVersion) return false;
|
|
|
+ if (b.IsDevelopmentVersion) return true;
|
|
|
+
|
|
|
+ if (a.MajorVersion != b.MajorVersion)
|
|
|
+ return a.MajorVersion < b.MajorVersion;
|
|
|
+ if (a.MinorVersion != b.MinorVersion)
|
|
|
+ return a.MinorVersion < b.MinorVersion;
|
|
|
+ if (a.IsNewStyle && b.IsNewStyle)
|
|
|
+ return int.Parse(a.Release) < int.Parse(b.Release);
|
|
|
+ return String.Compare(a.Release,b.Release, StringComparison.OrdinalIgnoreCase) < 0;
|
|
|
+ }
|
|
|
+ public static bool operator >(VersionNumber a, VersionNumber b)
|
|
|
+ {
|
|
|
+ return b < a;
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool operator <=(VersionNumber a, VersionNumber b)
|
|
|
+ {
|
|
|
+ return !(b < a);
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool operator >=(VersionNumber a, VersionNumber b)
|
|
|
+ {
|
|
|
+ return !(a < b);
|
|
|
+ }
|
|
|
+
|
|
|
+ public override bool Equals(object? obj)
|
|
|
+ {
|
|
|
+ if(obj is VersionNumber v)
|
|
|
+ {
|
|
|
+ return this == v;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override int GetHashCode()
|
|
|
+ {
|
|
|
+ if (IsDevelopmentVersion)
|
|
|
+ return 0;
|
|
|
+ return MajorVersion ^ MinorVersion ^ Release.GetHashCode();
|
|
|
+ }
|
|
|
+
|
|
|
+ public static bool operator ==(VersionNumber a, VersionNumber b)
|
|
|
+ {
|
|
|
+ if (a.IsDevelopmentVersion)
|
|
|
+ return b.IsDevelopmentVersion;
|
|
|
+ if (b.IsDevelopmentVersion)
|
|
|
+ return false;
|
|
|
+ return a.MajorVersion == b.MajorVersion
|
|
|
+ && a.MinorVersion == b.MinorVersion
|
|
|
+ && String.Compare(a.Release,b.Release, StringComparison.OrdinalIgnoreCase) == 0;
|
|
|
+ }
|
|
|
+ public static bool operator !=(VersionNumber a, VersionNumber b)
|
|
|
+ {
|
|
|
+ if (a.IsDevelopmentVersion)
|
|
|
+ return !b.IsDevelopmentVersion;
|
|
|
+ if (b.IsDevelopmentVersion)
|
|
|
+ return true;
|
|
|
+ return a.MajorVersion != b.MajorVersion
|
|
|
+ || a.MinorVersion != b.MinorVersion
|
|
|
+ || String.Compare(a.Release, b.Release, StringComparison.OrdinalIgnoreCase) != 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ public override string ToString()
|
|
|
+ {
|
|
|
+ return IsDevelopmentVersion
|
|
|
+ ? "???"
|
|
|
+ : IsNewStyle
|
|
|
+ ? !Release.Equals("0")
|
|
|
+ ? $"{MajorVersion}.{MinorVersion:D2}.{Release}"
|
|
|
+ : $"{MajorVersion}.{MinorVersion:D2}"
|
|
|
+ : $"{MajorVersion}.{MinorVersion:D2}{Release}";
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+}
|