-
Notifications
You must be signed in to change notification settings - Fork 20
Expand file tree
/
Copy pathBlobTreeNode.cs
More file actions
226 lines (210 loc) · 8.91 KB
/
BlobTreeNode.cs
File metadata and controls
226 lines (210 loc) · 8.91 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
using BytecodeApi.Extensions;
using System.Diagnostics;
namespace BytecodeApi.Data;
/// <summary>
/// Represents a tree node within a <see cref="BlobTree" />.
/// </summary>
[DebuggerDisplay($"{nameof(BlobTreeNode)}: Name = {{Name}}, Nodes: {{Nodes.Count}}, Blobs: {{Blobs.Count}}")]
public sealed class BlobTreeNode
{
/// <summary>
/// Gets or sets the name of the <see cref="BlobTreeNode" />.
/// </summary>
public string Name { get; set; }
/// <summary>
/// Gets the collection of nodes associated with this <see cref="BlobTreeNode" />.
/// </summary>
public BlobTreeNodeCollection Nodes { get; }
/// <summary>
/// Gets the collection of <see cref="Data.Blob" /> objects associated with this <see cref="BlobTreeNode" />.
/// </summary>
public BlobCollection Blobs { get; }
/// <summary>
/// Gets or sets the object that contains data about the <see cref="BlobTreeNode" />.
/// </summary>
public object? Tag { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="BlobTreeNode" /> class.
/// </summary>
public BlobTreeNode()
{
Name = "";
Nodes = [];
Blobs = [];
}
/// <summary>
/// Initializes a new instance of the <see cref="BlobTreeNode" /> class with the specified name.
/// </summary>
/// <param name="name">The name of the <see cref="BlobTreeNode" />.</param>
public BlobTreeNode(string name) : this()
{
Check.ArgumentNull(name);
Name = name;
}
/// <summary>
/// Initializes a new instance of the <see cref="BlobTreeNode" /> class with the specified name and elemets.
/// </summary>
/// <param name="name">The name of the <see cref="BlobTreeNode" />.</param>
/// <param name="nodes">A collection of nodes to add to the <see cref="BlobTreeNode" />.</param>
/// <param name="blobs">A collection of blobs to add to the <see cref="BlobTreeNode" />.</param>
public BlobTreeNode(string name, IEnumerable<BlobTreeNode> nodes, IEnumerable<Blob> blobs) : this(name)
{
Check.ArgumentNull(blobs);
Nodes.AddRange(nodes);
Blobs.AddRange(blobs);
}
/// <summary>
/// Retrieves a <see cref="BlobTreeNode" /> with the specified name.
/// </summary>
/// <param name="name">A <see cref="string" /> specifying the name of the <see cref="BlobTreeNode" />.</param>
/// <returns>
/// The <see cref="BlobTreeNode" /> with the specified name, or <see langword="null" /> if no matching node was found.
/// </returns>
public BlobTreeNode? Node(string name)
{
return Node(name, false);
}
/// <summary>
/// Retrieves a <see cref="BlobTreeNode" /> with the specified name.
/// </summary>
/// <param name="name">A <see cref="string" /> specifying the name of the <see cref="BlobTreeNode" />.</param>
/// <param name="ignoreCase"><see langword="true" /> to ignore character casing during name comparison.</param>
/// <returns>
/// The <see cref="BlobTreeNode" /> with the specified name, or <see langword="null" /> if no matching node was found.
/// </returns>
public BlobTreeNode? Node(string name, bool ignoreCase)
{
Check.ArgumentNull(name);
return Nodes.FirstOrDefault(node => node.Name.Equals(name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
}
/// <summary>
/// Retrieves a <see cref="Data.Blob" /> with the specified name.
/// </summary>
/// <param name="name">A <see cref="string" /> specifying the name of the <see cref="Data.Blob" />.</param>
/// <returns>
/// The <see cref="Data.Blob" /> with the specified name, or <see langword="null" /> if no matching blob was found.
/// </returns>
public Blob? Blob(string name)
{
return Blob(name, false);
}
/// <summary>
/// Retrieves a <see cref="Data.Blob" /> with the specified name.
/// </summary>
/// <param name="name">A <see cref="string" /> specifying the name of the <see cref="Data.Blob" />.</param>
/// <param name="ignoreCase"><see langword="true" /> to ignore character casing during name comparison.</param>
/// <returns>
/// The <see cref="Data.Blob" /> with the specified name, or <see langword="null" /> if no matching blob was found.
/// </returns>
public Blob? Blob(string name, bool ignoreCase)
{
Check.ArgumentNull(name);
return Blobs.FirstOrDefault(blob => blob.Name.Equals(name, ignoreCase ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal));
}
/// <summary>
/// Tries to find a node by the specified case sensitive path. The path contains each node name, separated by a backslash. Returns <see langword="null" />, if the <see cref="BlobTreeNode" /> could not be found.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying a case sensitive path. The path contains each node name, separated by a backslash.</param>
/// <returns>
/// The <see cref="BlobTreeNode" /> that was found by the specified path, or <see langword="null" />, if it could not be found.
/// </returns>
public BlobTreeNode? FindNode(string path)
{
return FindNode(path, false);
}
/// <summary>
/// Tries to find a node by the specified path. The path contains each node name, separated by a backslash. Returns <see langword="null" />, if the <see cref="BlobTreeNode" /> could not be found.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying a path. The path contains each node name, separated by a backslash.</param>
/// <param name="ignoreCase"><see langword="true" /> to ignore character casing during name comparison.</param>
/// <returns>
/// The <see cref="BlobTreeNode" /> that was found by the specified path, or <see langword="null" />, if it could not be found.
/// </returns>
public BlobTreeNode? FindNode(string path, bool ignoreCase)
{
Check.ArgumentNull(path);
Check.ArgumentEx.StringNotEmpty(path);
BlobTreeNode? node = this;
foreach (string pathPart in path.Trim('\\').Split('\\'))
{
node = node.Node(pathPart, ignoreCase);
if (node == null) break;
}
return node;
}
/// <summary>
/// Tries to find a blob by the specified case sensitive path. The path contains each node name, separated by a backslash. The last element represents the name of the blob. Returns <see langword="null" />, if the <see cref="Data.Blob" /> could not be found.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying a case sensitive path. The path contains each node name, separated by a backslash. The last element represents the name of the blob.</param>
/// <returns>
/// The <see cref="Data.Blob" /> that was found by the specified path, or <see langword="null" />, if it could not be found.
/// </returns>
public Blob? FindBlob(string path)
{
return FindBlob(path, false);
}
/// <summary>
/// Tries to find a blob by the specified path. The path contains each node name, separated by a backslash. The last element represents the name of the blob. Returns <see langword="null" />, if the <see cref="Data.Blob" /> could not be found.
/// </summary>
/// <param name="path">A <see cref="string" /> specifying a path. The path contains each node name, separated by a backslash. The last element represents the name of the blob.</param>
/// <param name="ignoreCase"><see langword="true" /> to ignore character casing during name comparison.</param>
/// <returns>
/// The <see cref="Data.Blob" /> that was found by the specified path, or <see langword="null" />, if it could not be found.
/// </returns>
public Blob? FindBlob(string path, bool ignoreCase)
{
Check.ArgumentNull(path);
Check.ArgumentEx.StringNotEmpty(path);
path = path.Trim('\\');
if (Path.GetDirectoryName(path) is string nodePath &&
Path.GetFileName(path) is string blobName &&
FindNode(nodePath, ignoreCase) is BlobTreeNode node)
{
return node.Blob(blobName, ignoreCase);
}
else
{
return null;
}
}
/// <summary>
/// Creates a new one-dimensional <see cref="BlobCollection" /> containing all <see cref="Data.Blob" /> objects including the root node and all child nodes recursively.
/// </summary>
/// <returns>
/// The <see cref="BlobCollection" /> this method creates.
/// </returns>
public BlobCollection Flatten()
{
BlobCollection blobs = [];
AddNode(this);
return blobs;
void AddNode(BlobTreeNode node)
{
foreach (BlobTreeNode childNode in node.Nodes)
{
AddNode(childNode);
}
blobs.AddRange(node.Blobs);
}
}
/// <summary>
/// Computes the size, in bytes, of all <see cref="Data.Blob" /> objects within this <see cref="BlobTreeNode" /> recursively.
/// </summary>
/// <returns>
/// The size, in bytes, of all <see cref="Data.Blob" /> objects within this <see cref="BlobTreeNode" /> recursively.
/// </returns>
public long ComputeSize()
{
return Nodes.ComputeSize() + Blobs.ComputeSize();
}
/// <summary>
/// Returns the name of this <see cref="BlobTreeNode" />.
/// </summary>
/// <returns>
/// The name of this <see cref="BlobTreeNode" />.
/// </returns>
public override string ToString()
{
return Name;
}
}