C++: Parse array fields
This commit is contained in:
@@ -10,11 +10,9 @@ using System.Collections.Generic;
|
|||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.CompilerServices;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using Il2CppInspector.CppUtils.UnityHeaders;
|
using Il2CppInspector.CppUtils.UnityHeaders;
|
||||||
using Il2CppInspector.Reflection;
|
|
||||||
|
|
||||||
namespace Il2CppInspector.CppUtils
|
namespace Il2CppInspector.CppUtils
|
||||||
{
|
{
|
||||||
@@ -45,6 +43,9 @@ namespace Il2CppInspector.CppUtils
|
|||||||
// Generate pointer to this type
|
// Generate pointer to this type
|
||||||
public CppPointerType AsPointer(int WordSize) => new CppPointerType(WordSize, this);
|
public CppPointerType AsPointer(int WordSize) => new CppPointerType(WordSize, this);
|
||||||
|
|
||||||
|
// Generate array of this type
|
||||||
|
public CppArrayType AsArray(int Length) => new CppArrayType(this, Length);
|
||||||
|
|
||||||
// Generate typedef to this type
|
// Generate typedef to this type
|
||||||
public CppAlias AsAlias(string Name) => new CppAlias(Name, this);
|
public CppAlias AsAlias(string Name) => new CppAlias(Name, this);
|
||||||
|
|
||||||
@@ -61,6 +62,28 @@ namespace Il2CppInspector.CppUtils
|
|||||||
public CppPointerType(int WordSize, CppType elementType) : base(null, WordSize) => ElementType = elementType;
|
public CppPointerType(int WordSize, CppType elementType) : base(null, WordSize) => ElementType = elementType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// An array type
|
||||||
|
public class CppArrayType : CppType
|
||||||
|
{
|
||||||
|
public override string Name => ElementType.Name;
|
||||||
|
|
||||||
|
public int Length { get; }
|
||||||
|
|
||||||
|
public CppType ElementType { get; }
|
||||||
|
|
||||||
|
// Even an array of 1-bit bitfirleds must use at least 1 byte each
|
||||||
|
public override int Size => SizeBytes * 8;
|
||||||
|
|
||||||
|
public override int SizeBytes => ElementType.SizeBytes * Length;
|
||||||
|
|
||||||
|
public CppArrayType(CppType elementType, int length) : base(null) {
|
||||||
|
ElementType = elementType;
|
||||||
|
Length = length;
|
||||||
|
}
|
||||||
|
|
||||||
|
public override string ToString() => ElementType + "[" + Length + "]";
|
||||||
|
}
|
||||||
|
|
||||||
// A typedef alias
|
// A typedef alias
|
||||||
public class CppAlias : CppType
|
public class CppAlias : CppType
|
||||||
{
|
{
|
||||||
@@ -96,7 +119,6 @@ namespace Il2CppInspector.CppUtils
|
|||||||
|
|
||||||
// Add a field to the type. Returns the offset of the field in the type
|
// Add a field to the type. Returns the offset of the field in the type
|
||||||
public int AddField(CppField field) {
|
public int AddField(CppField field) {
|
||||||
// TODO: Use InheritanceStyleEnum to determine whether the field is embedded or a pointer
|
|
||||||
field.Offset = CompoundType == CompoundType.Struct ? Size : 0;
|
field.Offset = CompoundType == CompoundType.Struct ? Size : 0;
|
||||||
|
|
||||||
// If we just came out of a bitfield, move to the next byte if necessary
|
// If we just came out of a bitfield, move to the next byte if necessary
|
||||||
@@ -168,13 +190,17 @@ namespace Il2CppInspector.CppUtils
|
|||||||
internal CppType Type { get; set; }
|
internal CppType Type { get; set; }
|
||||||
|
|
||||||
// C++ representation of field (might be incorrect due to the above)
|
// C++ representation of field (might be incorrect due to the above)
|
||||||
public override string ToString() => $"/* 0x{OffsetBytes:x2} - 0x{OffsetBytes + SizeBytes - 1:x2} (0x{SizeBytes:x2}) */"
|
public override string ToString() =>
|
||||||
// nested anonymous types
|
$"/* 0x{OffsetBytes:x2} - 0x{OffsetBytes + SizeBytes - 1:x2} (0x{SizeBytes:x2}) */"
|
||||||
+ (Type is CppComplexType && Type.Name == "" ? "\n" + Type.ToString()[..^1] + " " + Name :
|
// nested anonymous types
|
||||||
// regular fields
|
+ (Type is CppComplexType && Type.Name == "" ? "\n" + Type.ToString()[..^1] + " " + Name :
|
||||||
$" {Type.Name} {Name}" + (BitfieldSize > 0? $" : {BitfieldSize}" : ""))
|
// regular fields
|
||||||
+ ";"
|
$" {Type.Name} {Name}" + (BitfieldSize > 0? $" : {BitfieldSize}" : ""))
|
||||||
+ (BitfieldSize > 0? $" // bits {BitfieldLSB} - {BitfieldMSB}" : "");
|
// arrays
|
||||||
|
+ (Type is CppArrayType? "[" + ((CppArrayType)Type).Length + "]" : "")
|
||||||
|
+ ";"
|
||||||
|
// bitfields
|
||||||
|
+ (BitfieldSize > 0? $" // bits {BitfieldLSB} - {BitfieldMSB}" : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
// A collection of C++ types
|
// A collection of C++ types
|
||||||
@@ -231,11 +257,12 @@ namespace Il2CppInspector.CppUtils
|
|||||||
var rgxStripKeywords = new Regex(@"\b(?:const|unsigned|volatile)\b");
|
var rgxStripKeywords = new Regex(@"\b(?:const|unsigned|volatile)\b");
|
||||||
var rgxCompressPtrs = new Regex(@"\*\s+\*");
|
var rgxCompressPtrs = new Regex(@"\*\s+\*");
|
||||||
|
|
||||||
|
var rgxArrayField = new Regex(@"(\S+?)\[([0-9]+)\]");
|
||||||
|
|
||||||
var currentType = new Stack<CppComplexType>();
|
var currentType = new Stack<CppComplexType>();
|
||||||
bool inEnum = false;
|
bool inEnum = false;
|
||||||
string line;
|
string line;
|
||||||
|
|
||||||
// TODO: Arrays
|
|
||||||
// TODO: Alignment directives
|
// TODO: Alignment directives
|
||||||
// TODO: enum prefix in field (Il2CppWindowsRuntimeTypeName)
|
// TODO: enum prefix in field (Il2CppWindowsRuntimeTypeName)
|
||||||
// TODO: comma-separated fields
|
// TODO: comma-separated fields
|
||||||
@@ -433,6 +460,15 @@ namespace Il2CppInspector.CppUtils
|
|||||||
var name = field.Groups[2].Captures[0].ToString();
|
var name = field.Groups[2].Captures[0].ToString();
|
||||||
var typeName = field.Groups[1].Captures[0].ToString();
|
var typeName = field.Groups[1].Captures[0].ToString();
|
||||||
|
|
||||||
|
// Array
|
||||||
|
var array = rgxArrayField.Match(name);
|
||||||
|
int arraySize = 0;
|
||||||
|
if (array.Success && array.Groups[2].Captures.Count > 0) {
|
||||||
|
arraySize = int.Parse(array.Groups[2].Captures[0].ToString());
|
||||||
|
name = array.Groups[1].Captures[0].ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bitfield
|
||||||
int bitfield = 0;
|
int bitfield = 0;
|
||||||
if (field.Groups[3].Captures.Count > 0)
|
if (field.Groups[3].Captures.Count > 0)
|
||||||
bitfield = int.Parse(field.Groups[3].Captures[0].ToString());
|
bitfield = int.Parse(field.Groups[3].Captures[0].ToString());
|
||||||
@@ -444,6 +480,10 @@ namespace Il2CppInspector.CppUtils
|
|||||||
type = type.AsPointer(WordSize);
|
type = type.AsPointer(WordSize);
|
||||||
|
|
||||||
var ct = currentType.Peek();
|
var ct = currentType.Peek();
|
||||||
|
|
||||||
|
if (arraySize > 0)
|
||||||
|
type = type.AsArray(arraySize);
|
||||||
|
|
||||||
ct.AddField(new CppField {Name = name, Type = type, BitfieldSize = bitfield});
|
ct.AddField(new CppField {Name = name, Type = type, BitfieldSize = bitfield});
|
||||||
|
|
||||||
if (bitfield == 0)
|
if (bitfield == 0)
|
||||||
|
|||||||
Reference in New Issue
Block a user