forked from ReClassNET/ReClass.NET
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBaseContainerNode.cs
More file actions
228 lines (185 loc) · 5.49 KB
/
Copy pathBaseContainerNode.cs
File metadata and controls
228 lines (185 loc) · 5.49 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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using ReClassNET.Util;
namespace ReClassNET.Nodes
{
public abstract class BaseContainerNode : BaseNode
{
[ContractInvariantMethod]
private void ObjectInvariants()
{
Contract.Invariant(nodes != null);
}
protected readonly List<BaseNode> nodes = new List<BaseNode>();
/// <summary>The child nodes of the node.</summary>
public IEnumerable<BaseNode> Nodes => nodes;
/// <summary>Calculates the offset of every child node.</summary>
public void UpdateOffsets()
{
var offset = IntPtr.Zero;
foreach (var node in Nodes)
{
node.Offset = offset;
offset += node.MemorySize;
}
}
/// <summary>Searches for the node index.</summary>
/// <param name="node">The node to search.</param>
/// <returns>The found node index or -1 if the node was not found.</returns>
public int FindNodeIndex(BaseNode node)
{
Contract.Requires(node != null);
Contract.Ensures(Contract.Result<int>() >= -1);
return Nodes.FindIndex(n => n == node);
}
public bool ReplaceChildNode(BaseNode child, Type nodeType)
{
Contract.Requires(nodeType != null);
Contract.Requires(nodeType.IsSubclassOf(typeof(BaseNode)));
List<BaseNode> dummy = null;
return ReplaceChildNode(child, nodeType, ref dummy);
}
public bool ReplaceChildNode(BaseNode child, Type nodeType, ref List<BaseNode> createdNodes)
{
Contract.Requires(child != null);
Contract.Requires(nodeType != null);
Contract.Requires(nodeType.IsSubclassOf(typeof(BaseNode)));
return ReplaceChildNode(FindNodeIndex(child), nodeType, ref createdNodes);
}
/// <summary>Replaces the child at the specific position with the provided node.</summary>
/// <param name="index">Zero-based position.</param>
/// <param name="nodeType">The type of the node.</param>
/// <param name="createdNodes">[in,out] A list with the created nodes.</param>
/// <returns>True if it succeeds, false if it fails.</returns>
public virtual bool ReplaceChildNode(int index, Type nodeType, ref List<BaseNode> createdNodes)
{
Contract.Requires(nodeType != null);
Contract.Requires(nodeType.IsSubclassOf(typeof(BaseNode)));
if (index < 0 || index >= nodes.Count)
{
return false;
}
var oldNode = nodes[index];
if (!(Activator.CreateInstance(nodeType) is BaseNode node))
{
return false;
}
node.Intialize();
node.CopyFromNode(oldNode);
createdNodes?.Add(node);
node.ParentNode = this;
nodes[index] = node;
var oldSize = oldNode.MemorySize;
var newSize = node.MemorySize;
if (newSize < oldSize)
{
InsertBytes(index + 1, oldSize - newSize, ref createdNodes);
}
/*else if (newSize > oldSize)
{
RemoveNodes(index + 1, newSize - oldSize);
}*/
return true;
}
/// <summary>Adds the specific amount of bytes at the end of the node.</summary>
/// <param name="size">The number of bytes to insert.</param>
public void AddBytes(int size)
{
InsertBytes(nodes.Count, size);
}
public void InsertBytes(BaseNode position, int size)
{
InsertBytes(FindNodeIndex(position), size);
}
/// <summary>Inserts <paramref name="size"/> bytes at the specified position.</summary>
/// <param name="index">Zero-based position.</param>
/// <param name="size">The number of bytes to insert.</param>
public void InsertBytes(int index, int size)
{
List<BaseNode> dummy = null;
InsertBytes(index, size, ref dummy);
}
/// <summary>Inserts <paramref name="size"/> bytes at the specified position.</summary>
/// <param name="index">Zero-based position.</param>
/// <param name="size">The number of bytes to insert.</param>
/// <param name="createdNodes">[in,out] A list with the created nodes.</param>
public virtual void InsertBytes(int index, int size, ref List<BaseNode> createdNodes)
{
if (index < 0 || index > nodes.Count || size == 0)
{
return;
}
var offset = IntPtr.Zero;
if (index > 0)
{
var node = nodes[index - 1];
offset = node.Offset + node.MemorySize;
}
while (size != 0)
{
BaseNode node;
#if RECLASSNET64
if (size >= 8)
{
node = new Hex64Node();
}
else
#endif
if (size >= 4)
{
node = new Hex32Node();
}
else if (size >= 2)
{
node = new Hex16Node();
}
else
{
node = new Hex8Node();
}
node.ParentNode = this;
node.Offset = offset;
nodes.Insert(index, node);
createdNodes?.Add(node);
offset += node.MemorySize;
size -= node.MemorySize;
index++;
}
}
public void AddNode(BaseNode node)
{
Contract.Requires(node != null);
InsertNode(nodes.Count, node);
}
public virtual void InsertNode(BaseNode position, BaseNode node)
{
var index = FindNodeIndex(position);
if (index == -1)
{
throw new ArgumentException();
}
InsertNode(index, node);
}
public virtual void InsertNode(int index, BaseNode node)
{
Contract.Requires(index >= 0);
Contract.Requires(node != null);
node.ParentNode = this;
nodes.Insert(index, node);
}
/// <summary>Removes the specified node.</summary>
/// <param name="node">The node to remove.</param>
/// <returns>True if it succeeds, false if it fails.</returns>
public virtual bool RemoveNode(BaseNode node)
{
Contract.Requires(node != null);
return nodes.Remove(node);
}
/// <summary>Called by a child if it has changed.</summary>
/// <param name="child">The child.</param>
protected internal virtual void ChildHasChanged(BaseNode child)
{
}
}
}