Files
Il2CppInspectorRedux/Il2CppInspector.Common/Outputs/UnityHeaders/UnityVersion.cs
Robert Xiao 34f0d4ceef Add header files for every known Unity version.
We want to get types into the IDA output, and to do that we need
accurate types for the Il2Cpp structures. Unfortunately, some crucial
types like Il2CppClass change between versions without any corresponding
metadata changes, meaning that we have to manually identify the version
outside of the Inspector somehow (e.g. by looking at the version number
embedded in Unity asset files). This patch adds header files for *every*
known Unity version from 5.3.0 to 2019.3.8, merging them into version
ranges where header files don't change.

It also adds front-end support for supplying the version number in both
the CLI and GUI. The GUI is given the ability to guess the version
number approximately to reduce the number of choices presented to the
user.
2020-06-29 22:10:45 +02:00

103 lines
3.9 KiB
C#

using System;
using System.Text.RegularExpressions;
namespace Il2CppInspector.Outputs.UnityHeaders
{
public class UnityVersion : IComparable<UnityVersion>, IEquatable<UnityVersion>
{
public enum BuildTypeEnum
{
Unspecified,
Alpha,
Beta,
ReleaseCandidate,
Final,
Patch,
}
public static string BuildTypeToString(BuildTypeEnum buildType) => buildType switch
{
BuildTypeEnum.Unspecified => "",
BuildTypeEnum.Alpha => "a",
BuildTypeEnum.Beta => "b",
BuildTypeEnum.ReleaseCandidate => "rc",
BuildTypeEnum.Final => "f",
BuildTypeEnum.Patch => "p",
_ => throw new ArgumentException(),
};
public static BuildTypeEnum StringToBuildType(string s) => s switch
{
"" => BuildTypeEnum.Unspecified,
"a" => BuildTypeEnum.Alpha,
"b" => BuildTypeEnum.Beta,
"rc" => BuildTypeEnum.ReleaseCandidate,
"f" => BuildTypeEnum.Final,
"p" => BuildTypeEnum.Patch,
_ => throw new ArgumentException("Unknown build type " + s),
};
public int Major { get; }
public int Minor { get; }
public int Update { get; }
public BuildTypeEnum BuildType { get; }
public int BuildNumber { get; }
public UnityVersion(string versionString) {
var match = Regex.Match(versionString, @"^(\d+)\.(\d+)(?:\.(\d+))?(?:([a-zA-Z]+)(\d+))?$");
if (!match.Success)
throw new ArgumentException($"'${versionString}' is not a valid Unity version number.");
Major = int.Parse(match.Groups[1].Value);
Minor = int.Parse(match.Groups[2].Value);
Update = match.Groups[3].Success ? int.Parse(match.Groups[3].Value) : 0;
BuildType = match.Groups[4].Success ? StringToBuildType(match.Groups[4].Value) : BuildTypeEnum.Unspecified;
BuildNumber = match.Groups[5].Success ? int.Parse(match.Groups[5].Value) : 0;
}
public static implicit operator UnityVersion(string versionString) => new UnityVersion(versionString);
public override string ToString() {
var res = $"{Major}.{Minor}.{Update}";
if (BuildType != BuildTypeEnum.Unspecified)
res += $"{BuildTypeToString(BuildType)}{BuildNumber}";
return res;
}
public int CompareTo(UnityVersion other) {
int res;
if (0 != (res = Major.CompareTo(other.Major)))
return res;
if (0 != (res = Minor.CompareTo(other.Minor)))
return res;
if (0 != (res = Update.CompareTo(other.Update)))
return res;
// same major.minor.update - if one of these is suffix-less, they compare equal
// yes, this makes the compare function non-transitive; don't use it to sort things
if (BuildType == BuildTypeEnum.Unspecified || other.BuildType == BuildTypeEnum.Unspecified)
return 0;
if (0 != (res = BuildType.CompareTo(other.BuildType)))
return res;
if (0 != (res = BuildNumber.CompareTo(other.BuildNumber)))
return res;
return 0;
}
public override bool Equals(object obj) {
return Equals(obj as UnityVersion);
}
public bool Equals(UnityVersion other) {
return other != null &&
Major == other.Major &&
Minor == other.Minor &&
Update == other.Update &&
BuildType == other.BuildType &&
BuildNumber == other.BuildNumber;
}
public override int GetHashCode() {
return HashCode.Combine(Major, Minor, Update, BuildType, BuildNumber);
}
}
}