C++: Output C++ enums as enum classes

This commit is contained in:
Katy Coe
2021-01-04 05:14:11 +01:00
parent 567b6e1d21
commit 956cea0553
3 changed files with 19 additions and 14 deletions

View File

@@ -1,5 +1,5 @@
/*
Copyright 2017-2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
Copyright 2017-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
Copyright 2020 Robert Xiao - https://robertxiao.ca
All rights reserved.
@@ -152,11 +152,12 @@ namespace Il2CppInspector.Cpp
if (ti.IsEnum) {
// Enums should be represented using enum syntax
// They otherwise behave like value types
var namer = CreateNamespace().MakeNamer<FieldInfo>((field) => field.Name.ToCIdentifier());
var underlyingType = AsCType(ti.GetEnumUnderlyingType());
valueType = types.Enum(underlyingType, name);
foreach (var field in ti.DeclaredFields) {
if (field.Name != "value__")
((CppEnumType)valueType).AddField(EnumNamer.GetName(field), field.DefaultValue);
((CppEnumType)valueType).AddField(namer.GetName(field), field.DefaultValue);
}
boxedType = GenerateObjectStruct(name + "__Boxed", ti);
@@ -530,7 +531,6 @@ namespace Il2CppInspector.Cpp
GlobalsNamespace = CreateNamespace();
GlobalNamer = GlobalsNamespace.MakeNamer<MethodBase>((method) => $"{TypeNamer.GetName(method.DeclaringType)}_{method.Name.ToCIdentifier()}");
EnumNamer = GlobalsNamespace.MakeNamer<FieldInfo>((field) => $"{TypeNamer.GetName(field.DeclaringType)}_{field.Name.ToCIdentifier()}");
}
// Reserve C/C++ keywords and built-in names
@@ -571,11 +571,10 @@ namespace Il2CppInspector.Cpp
public CppNamespace.Namer<TypeInfo> TypeNamer { get; private set; }
/// <summary>
/// Namespace for global variables, enum values and methods
/// Namespace for global variables and methods
/// </summary>
public CppNamespace GlobalsNamespace { get; private set; }
public CppNamespace.Namer<MethodBase> GlobalNamer { get; private set; }
public CppNamespace.Namer<FieldInfo> EnumNamer { get; private set; }
#endregion
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
Copyright 2020-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
@@ -78,10 +78,14 @@ namespace Il2CppInspector.Cpp
// An enum key and value pair
public class CppEnumField : CppField
{
// The enum type this field belongs to
public CppEnumType DeclaringType { get; }
// The value of this key name
public object Value { get; }
public CppEnumField(string name, CppType type, object value) : base(name, type) => Value = value;
public CppEnumField(CppEnumType declType, string name, CppType type, object value) : base(name, type)
=> (DeclaringType, Value) = (declType, value);
// We output as hex to avoid unsigned value compiler errors for top bit set values in VS <= 2017
// We'll get compiler warnings instead but it will still compile
@@ -91,10 +95,12 @@ namespace Il2CppInspector.Cpp
// Signed number with top bit set (only perform cast if underlying type is signed)
var fieldIsNegative = signed && ((long) Convert.ChangeType(Value, typeof(long))) < 0;
if (fieldIsNegative)
return $"{Name} = {Value}";
var fieldName = (format.Contains('c')? DeclaringType.Name + "_" : "") + Name;
return string.Format("{0} = 0x{1:x" + Type.SizeBytes * 2 + "}", Name, Value);
if (fieldIsNegative)
return $"{fieldName} = {Value}";
return string.Format("{0} = 0x{1:x" + Type.SizeBytes * 2 + "}", fieldName, Value);
}
}
}

View File

@@ -1,5 +1,5 @@
/*
Copyright 2020 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
Copyright 2020-2021 Katy Coe - http://www.djkaty.com - https://github.com/djkaty
All rights reserved.
*/
@@ -418,13 +418,13 @@ namespace Il2CppInspector.Cpp
public CppEnumType(CppType underlyingType) : base(ComplexValueType.Enum) => UnderlyingType = underlyingType;
public void AddField(string name, object value) => AddField(new CppEnumField(name, UnderlyingType, value));
public void AddField(string name, object value) => AddField(new CppEnumField(this, name, UnderlyingType, value));
// Return the type as a field
public override string ToFieldString(string fieldName, string format = "") {
// C++
if (!format.Contains('c'))
return "enum " + Name + " " + fieldName;
return Name + " " + fieldName;
// For the C-compatible definition, we have an alignment problem when the enum
// does not derive from the architecture integer width.
@@ -439,7 +439,7 @@ namespace Il2CppInspector.Cpp
if (format.Contains('c'))
sb.Append($"enum {Name} {{");
else
sb.Append($"enum {Name} : {UnderlyingType.Name} {{");
sb.Append($"enum class {Name} : {UnderlyingType.Name} {{");
foreach (var field in Fields.Values.SelectMany(f => f))
sb.Append("\n " + string.Join("\n ", field.ToString(format).Split('\n')) + ",");