Repository navigation
Expand file tree
/
Copy pathCSharpCodeGenerator.cs
More file actions
126 lines (111 loc) · 3.51 KB
/
Copy pathCSharpCodeGenerator.cs
File metadata and controls
126 lines (111 loc) · 3.51 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using ReClassNET.Extensions;
using ReClassNET.Logger;
using ReClassNET.Nodes;
namespace ReClassNET.CodeGenerator
{
public class CSharpCodeGenerator : ICodeGenerator
{
private static readonly Dictionary<Type, string> typeToTypedefMap = new Dictionary<Type, string>
{
[typeof(DoubleNode)] = "double",
[typeof(FloatNode)] = "float",
[typeof(BoolNode)] = "bool",
[typeof(Int8Node)] = "sbyte",
[typeof(Int16Node)] = "short",
[typeof(Int32Node)] = "int",
[typeof(Int64Node)] = "long",
[typeof(UInt8Node)] = "byte",
[typeof(UInt16Node)] = "ushort",
[typeof(UInt32Node)] = "uint",
[typeof(UInt64Node)] = "ulong",
[typeof(FunctionPtrNode)] = "IntPtr",
[typeof(Utf8TextPtrNode)] = "IntPtr",
[typeof(Utf16TextPtrNode)] = "IntPtr",
[typeof(Utf32TextPtrNode)] = "IntPtr",
[typeof(PointerNode)] = "IntPtr",
[typeof(VirtualMethodTableNode)] = "IntPtr"
};
public Language Language => Language.CSharp;
public string GenerateCode(IEnumerable<ClassNode> classes, ILogger logger)
{
var sb = new StringBuilder();
sb.AppendLine($"// Created with {Constants.ApplicationName} by {Constants.Author}");
sb.AppendLine();
sb.AppendLine("// Warning: The code generator doesn't support all node types!");
sb.AppendLine();
sb.AppendLine("using System.Runtime.InteropServices;");
sb.AppendLine();
sb.Append(
string.Join(
Environment.NewLine + Environment.NewLine,
classes.Select(c =>
{
var csb = new StringBuilder();
csb.AppendLine("[StructLayout(LayoutKind.Explicit)]");
csb.Append($"struct {c.Name}");
if (!string.IsNullOrEmpty(c.Comment))
{
csb.Append($" // {c.Comment}");
}
csb.AppendLine();
csb.AppendLine("{");
csb.AppendLine(
string.Join(
Environment.NewLine + Environment.NewLine,
GetTypeDeclerationsForNodes(c.Nodes, logger)
.Select(t => $"\t{t.Item1}{Environment.NewLine}\t{t.Item2}")
)
);
csb.Append("}");
return csb.ToString();
})
)
);
return sb.ToString();
}
private static IEnumerable<Tuple<string, string>> GetTypeDeclerationsForNodes(IEnumerable<BaseNode> members, ILogger logger)
{
Contract.Requires(members != null);
Contract.Requires(Contract.ForAll(members, m => m != null));
Contract.Requires(logger != null);
Contract.Ensures(Contract.Result<IEnumerable<Tuple<string, string>>>() != null);
Contract.Ensures(Contract.ForAll(Contract.Result<IEnumerable<Tuple<string, string>>>(), t => t != null));
foreach (var member in members.WhereNot(n => n is BaseHexNode))
{
var type = GetTypeForNode(member, logger);
if (type != null)
{
yield return Tuple.Create(
$"[FieldOffset({member.Offset.ToInt32()})]",
$"public {type} {member.Name}; //0x{member.Offset.ToInt32():X04} {member.Comment}".Trim()
);
}
else
{
logger.Log(LogLevel.Warning, $"Skipping node with unhandled type: {member.GetType()}");
}
}
}
private static string GetTypeForNode(BaseNode node, ILogger logger)
{
Contract.Requires(node != null);
Contract.Requires(logger != null);
if (node is BitFieldNode bitFieldNode)
{
var underlayingNode = bitFieldNode.GetUnderlayingNode();
underlayingNode.CopyFromNode(node);
node = underlayingNode;
}
if (typeToTypedefMap.TryGetValue(node.GetType(), out var type))
{
return type;
}
return null;
}
}
}