C++: Output C++ enums as enum classes
This commit is contained in:
@@ -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
|
Copyright 2020 Robert Xiao - https://robertxiao.ca
|
||||||
|
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
@@ -152,11 +152,12 @@ namespace Il2CppInspector.Cpp
|
|||||||
if (ti.IsEnum) {
|
if (ti.IsEnum) {
|
||||||
// Enums should be represented using enum syntax
|
// Enums should be represented using enum syntax
|
||||||
// They otherwise behave like value types
|
// They otherwise behave like value types
|
||||||
|
var namer = CreateNamespace().MakeNamer<FieldInfo>((field) => field.Name.ToCIdentifier());
|
||||||
var underlyingType = AsCType(ti.GetEnumUnderlyingType());
|
var underlyingType = AsCType(ti.GetEnumUnderlyingType());
|
||||||
valueType = types.Enum(underlyingType, name);
|
valueType = types.Enum(underlyingType, name);
|
||||||
foreach (var field in ti.DeclaredFields) {
|
foreach (var field in ti.DeclaredFields) {
|
||||||
if (field.Name != "value__")
|
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);
|
boxedType = GenerateObjectStruct(name + "__Boxed", ti);
|
||||||
@@ -530,7 +531,6 @@ namespace Il2CppInspector.Cpp
|
|||||||
|
|
||||||
GlobalsNamespace = CreateNamespace();
|
GlobalsNamespace = CreateNamespace();
|
||||||
GlobalNamer = GlobalsNamespace.MakeNamer<MethodBase>((method) => $"{TypeNamer.GetName(method.DeclaringType)}_{method.Name.ToCIdentifier()}");
|
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
|
// Reserve C/C++ keywords and built-in names
|
||||||
@@ -571,11 +571,10 @@ namespace Il2CppInspector.Cpp
|
|||||||
public CppNamespace.Namer<TypeInfo> TypeNamer { get; private set; }
|
public CppNamespace.Namer<TypeInfo> TypeNamer { get; private set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Namespace for global variables, enum values and methods
|
/// Namespace for global variables and methods
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public CppNamespace GlobalsNamespace { get; private set; }
|
public CppNamespace GlobalsNamespace { get; private set; }
|
||||||
public CppNamespace.Namer<MethodBase> GlobalNamer { get; private set; }
|
public CppNamespace.Namer<MethodBase> GlobalNamer { get; private set; }
|
||||||
public CppNamespace.Namer<FieldInfo> EnumNamer { get; private set; }
|
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
All rights reserved.
|
||||||
*/
|
*/
|
||||||
@@ -78,10 +78,14 @@ namespace Il2CppInspector.Cpp
|
|||||||
// An enum key and value pair
|
// An enum key and value pair
|
||||||
public class CppEnumField : CppField
|
public class CppEnumField : CppField
|
||||||
{
|
{
|
||||||
|
// The enum type this field belongs to
|
||||||
|
public CppEnumType DeclaringType { get; }
|
||||||
|
|
||||||
// The value of this key name
|
// The value of this key name
|
||||||
public object Value { get; }
|
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 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
|
// 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)
|
// Signed number with top bit set (only perform cast if underlying type is signed)
|
||||||
var fieldIsNegative = signed && ((long) Convert.ChangeType(Value, typeof(long))) < 0;
|
var fieldIsNegative = signed && ((long) Convert.ChangeType(Value, typeof(long))) < 0;
|
||||||
|
|
||||||
if (fieldIsNegative)
|
var fieldName = (format.Contains('c')? DeclaringType.Name + "_" : "") + Name;
|
||||||
return $"{Name} = {Value}";
|
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.
|
All rights reserved.
|
||||||
*/
|
*/
|
||||||
@@ -418,13 +418,13 @@ namespace Il2CppInspector.Cpp
|
|||||||
|
|
||||||
public CppEnumType(CppType underlyingType) : base(ComplexValueType.Enum) => UnderlyingType = underlyingType;
|
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
|
// Return the type as a field
|
||||||
public override string ToFieldString(string fieldName, string format = "") {
|
public override string ToFieldString(string fieldName, string format = "") {
|
||||||
// C++
|
// C++
|
||||||
if (!format.Contains('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
|
// For the C-compatible definition, we have an alignment problem when the enum
|
||||||
// does not derive from the architecture integer width.
|
// does not derive from the architecture integer width.
|
||||||
@@ -439,7 +439,7 @@ namespace Il2CppInspector.Cpp
|
|||||||
if (format.Contains('c'))
|
if (format.Contains('c'))
|
||||||
sb.Append($"enum {Name} {{");
|
sb.Append($"enum {Name} {{");
|
||||||
else
|
else
|
||||||
sb.Append($"enum {Name} : {UnderlyingType.Name} {{");
|
sb.Append($"enum class {Name} : {UnderlyingType.Name} {{");
|
||||||
|
|
||||||
foreach (var field in Fields.Values.SelectMany(f => f))
|
foreach (var field in Fields.Values.SelectMany(f => f))
|
||||||
sb.Append("\n " + string.Join("\n ", field.ToString(format).Split('\n')) + ",");
|
sb.Append("\n " + string.Join("\n ", field.ToString(format).Split('\n')) + ",");
|
||||||
|
|||||||
Reference in New Issue
Block a user