exports/WinGetVersion.cs

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
 
using System;
using System.Collections;
using System.Globalization;
using System.Reflection;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Win32;
 
namespace __NAMESPACE_NAME_PLACEHOLDER__
{
    public sealed class __CLASS_NAME_PLACEHOLDER__ : IComparable, IComparable<__CLASS_NAME_PLACEHOLDER__>, IEquatable<__CLASS_NAME_PLACEHOLDER__>
    {
        private const string VersionSansRegEx = @"^(?<major>\d+)(\.(?<minor>\d+))?(\.(?<patch>\d+))?(\.(?<build>\d+))*(\.(?<revision>\d+))*$";
        private const string LabelRegEx = @"^((?<preLabel>[0-9A-Za-z][0-9A-Za-z\-\.]*))?(\+(?<buildLabel>[0-9A-Za-z][0-9A-Za-z\-\.]*))?$";
        private const string LabelUnitRegEx = @"^[0-9A-Za-z][0-9A-Za-z\-\.]*$";
        private const string PreLabelPropertyName = "PSSemVerPreReleaseLabel";
        private const string BuildLabelPropertyName = "PSSemVerBuildLabel";
        private const string TypeNameForVersionWithLabel = "System.Version#IncludeLabel";
 
        private string versionString;
 
        public __CLASS_NAME_PLACEHOLDER__(string version)
        {
            var v = Parse(version);
 
            Major = v.Major;
            Minor = v.Minor;
            Patch = v.Patch;
            Build = v.Build;
            Revision = v.Revision;
             
        }
 
        public __CLASS_NAME_PLACEHOLDER__(int major, int minor, int patch)
        {
            if (major < 0) throw new Exception("invalid major");
            if (minor < 0) throw new Exception("invalid minor");
            if (patch < 0) throw new Exception("invalid patch");
 
            Major = major;
            Minor = minor;
            Patch = patch;
        }
        public __CLASS_NAME_PLACEHOLDER__(int major, int minor, int patch,int build)
        {
            if (major < 0) throw new Exception("invalid major");
            if (minor < 0) throw new Exception("invalid minor");
            if (patch < 0) throw new Exception("invalid patch");
            if (build < 0) throw new Exception("invalid build");
            Major = major;
            Minor = minor;
            Patch = patch;
            Build = build;
             
        }
 
        public __CLASS_NAME_PLACEHOLDER__(int major, int minor, int build, int patch, int revision)
        {
            if (major < 0) throw new Exception("invalid major");
            if (minor < 0) throw new Exception("invalid minor");
            if (patch < 0) throw new Exception("invalid patch");
            if (build < 0) throw new Exception("invalid build");
            if (revision < 0) throw new Exception("invalid revision");
            Major = major;
            Minor = minor;
            Patch = patch;
            Build = build;
            Revision = revision;
    
            // We presume:
            // PreReleaseLabel = null;
            // BuildLabel = null;
        }
 
        public __CLASS_NAME_PLACEHOLDER__(int major, int minor) : this(major, minor, 0) { }
        public __CLASS_NAME_PLACEHOLDER__(int major) : this(major, 0, 0) { }
        public __CLASS_NAME_PLACEHOLDER__(Version version)
        {
            if (version == null) throw new Exception("invalid major");
            if (version.Revision > 0) throw new Exception("invalid major");
 
            Major = version.Major;
            Minor = version.Minor;
            Patch = version.Build;
            
        }
 
        public static implicit operator Version(__CLASS_NAME_PLACEHOLDER__ semver)
        {
            var result = new Version(semver.Major, semver.Minor, semver.Patch);
            return result;
        }
 
        public int Major { get; }
        public int Minor { get; }
        public int Patch { get; }
        public int Build { get; }
        public int Revision { get; }
 
      
        public static __CLASS_NAME_PLACEHOLDER__ Parse(string version)
        {
            if (version == null) throw new Exception("invalid major");
            if (version == string.Empty) throw new Exception("invalid major");
 
            var r = new VersionResult();
            r.Init(true);
            TryParseVersion(version, ref r);
 
            return r._parsedVersion;
        }
 
        public static bool TryParse(string version, out __CLASS_NAME_PLACEHOLDER__ result)
        {
            if (version != null)
            {
                var r = new VersionResult();
                r.Init(false);
 
                if (TryParseVersion(version, ref r))
                {
                    result = r._parsedVersion;
                    return true;
                }
            }
 
            result = null;
            return false;
        }
 
        private static bool TryParseVersion(string version, ref VersionResult result)
        {
            if (version.EndsWith('-') || version.EndsWith('+') || version.EndsWith('.'))
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            string versionSansLabel = null;
            var major = 0;
            var minor = 0;
            var patch = 0;
            var build = 0;
            var revision = 0;
 
         
 
            var match = Regex.Match(versionSansLabel, VersionSansRegEx);
            if (!match.Success)
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            if (!int.TryParse(match.Groups["major"].Value, out major))
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            if (match.Groups["minor"].Success && !int.TryParse(match.Groups["minor"].Value, out minor))
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            if (match.Groups["patch"].Success && !int.TryParse(match.Groups["patch"].Value, out patch))
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            if (match.Groups["build"].Success && !int.TryParse(match.Groups["build"].Value, out build))
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            if (match.Groups["revision"].Success && !int.TryParse(match.Groups["revision"].Value, out revision))
            {
                result.SetFailure(ParseFailureKind.FormatException);
                return false;
            }
 
            result._parsedVersion = new __CLASS_NAME_PLACEHOLDER__(major, minor, patch, build, revision);
            return true;
        }
 
        public override string ToString()
        {
            if (versionString == null)
            {
                StringBuilder result = new StringBuilder();
 
                result.Append(Major).Append(".").Append(Minor).Append(".").Append(Patch).Append(".").Append(Build).Append(".").Append(Revision);
 
                versionString = result.ToString();
            }
 
            return versionString;
        }
 
        public static int Compare(__CLASS_NAME_PLACEHOLDER__ versionA, __CLASS_NAME_PLACEHOLDER__ versionB)
        {
            if (versionA != null)
            {
                return versionA.CompareTo(versionB);
            }
 
            if (versionB != null)
            {
                return -1;
            }
 
            return 0;
        }
 
        public int CompareTo(object version)
        {
            if (version == null)
            {
                return 1;
            }
 
            if (!(version is __CLASS_NAME_PLACEHOLDER__ v))
            {
                throw new Exception("invalid major");
            }
 
            return CompareTo(v);
        }
        public int CompareTo(__CLASS_NAME_PLACEHOLDER__ value)
        {
            if (value is null)
                return 1;
 
            if (Major != value.Major)
                return Major > value.Major ? 1 : -1;
 
            if (Minor != value.Minor)
                return Minor > value.Minor ? 1 : -1;
 
            if (Patch != value.Patch)
                return Patch > value.Patch ? 1 : -1;
            if (Build != value.Build)
                return Build > value.Build ? 1 : -1;
            if (Revision != value.Revision)
                return Revision > value.Revision ? 1 : -1;
 
            return 1;
        }
 
        public override bool Equals(object obj)
        {
            return Equals(obj as __CLASS_NAME_PLACEHOLDER__);
        }
 
        public bool Equals(__CLASS_NAME_PLACEHOLDER__ other)
        {
            // SymVer 2.0 standard requires to ignore 'BuildLabel' (Build metadata).
            return other != null && (Major == other.Major) && (Minor == other.Minor) && (Patch == other.Patch) && (Build == other.Build) && (Revision == other.Revision);
                    
        }
 
        public override int GetHashCode()
        {
            return this.ToString().GetHashCode();
        }
 
        public static bool operator ==(__CLASS_NAME_PLACEHOLDER__ v1, __CLASS_NAME_PLACEHOLDER__ v2)
        {
            if (v1 is null)
            {
                return v2 is null;
            }
 
            return v1.Equals(v2);
        }
 
        public static bool operator !=(__CLASS_NAME_PLACEHOLDER__ v1, __CLASS_NAME_PLACEHOLDER__ v2)
        {
            return !(v1 == v2);
        }
 
        public static bool operator <(__CLASS_NAME_PLACEHOLDER__ v1, __CLASS_NAME_PLACEHOLDER__ v2)
        {
            return (Compare(v1, v2) < 0);
        }
 
        public static bool operator <=(__CLASS_NAME_PLACEHOLDER__ v1, __CLASS_NAME_PLACEHOLDER__ v2)
        {
            return (Compare(v1, v2) <= 0);
        }
 
        public static bool operator >(__CLASS_NAME_PLACEHOLDER__ v1, __CLASS_NAME_PLACEHOLDER__ v2)
        {
            return (Compare(v1, v2) > 0);
        }
 
        public static bool operator >=(__CLASS_NAME_PLACEHOLDER__ v1, __CLASS_NAME_PLACEHOLDER__ v2)
        {
            return (Compare(v1, v2) >= 0);
        }
 
        internal enum ParseFailureKind
        {
            ArgumentException,
            ArgumentOutOfRangeException,
            FormatException
        }
 
        internal struct VersionResult
        {
            internal __CLASS_NAME_PLACEHOLDER__ _parsedVersion;
            internal ParseFailureKind _failure;
            internal string _exceptionArgument;
            internal bool _canThrow;
 
            internal void Init(bool canThrow)
            {
                _canThrow = canThrow;
            }
 
            internal void SetFailure(ParseFailureKind failure)
            {
                SetFailure(failure, string.Empty);
            }
 
            internal void SetFailure(ParseFailureKind failure, string argument)
            {
                _failure = failure;
                _exceptionArgument = argument;
                if (_canThrow)
                {
                    throw GetVersionParseException();
                }
            }
 
            internal Exception GetVersionParseException()
            {
                switch (_failure)
                {
                    case ParseFailureKind.ArgumentException:
                    {
                        throw new Exception("invalid major");
                    }
                    case ParseFailureKind.ArgumentOutOfRangeException:
                    {
                        throw new Exception("invalid major");
                    }
                    case ParseFailureKind.FormatException:
                    {
                        // Regenerate the FormatException as would be thrown by Int32.Parse()
                        try
                        {
                            Int32.Parse(_exceptionArgument, CultureInfo.InvariantCulture);
                        }
                        catch (FormatException e)
                        {
                            return e;
                        }
                        catch (OverflowException e)
                        {
                            return e;
                        }
                    }
                        break;
                }
 
                throw new Exception("invalid major");
            }
        }
    }
}