diff options
Diffstat (limited to 'src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs')
-rw-r--r-- | src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs | 270 |
1 files changed, 270 insertions, 0 deletions
diff --git a/src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs b/src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs new file mode 100644 index 00000000..38224d12 --- /dev/null +++ b/src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs | |||
@@ -0,0 +1,270 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | ||
2 | |||
3 | namespace WixToolset.Dtf.Resources | ||
4 | { | ||
5 | using System; | ||
6 | using System.IO; | ||
7 | using System.Text; | ||
8 | using System.Reflection; | ||
9 | using System.Collections; | ||
10 | using System.Collections.Generic; | ||
11 | using System.Globalization; | ||
12 | |||
13 | internal class VersionInfo : ICollection<VersionInfo> | ||
14 | { | ||
15 | private string key; | ||
16 | private bool isString; | ||
17 | private byte[] data; | ||
18 | private List<VersionInfo> children; | ||
19 | |||
20 | public VersionInfo(string key) | ||
21 | : base() | ||
22 | { | ||
23 | if (key == null) | ||
24 | { | ||
25 | throw new ArgumentNullException("key"); | ||
26 | } | ||
27 | |||
28 | this.key = key; | ||
29 | this.children = new List<VersionInfo>(); | ||
30 | } | ||
31 | |||
32 | public string Key | ||
33 | { | ||
34 | get | ||
35 | { | ||
36 | return this.key; | ||
37 | } | ||
38 | |||
39 | set | ||
40 | { | ||
41 | if (value == null) | ||
42 | { | ||
43 | throw new ArgumentNullException("value"); | ||
44 | } | ||
45 | |||
46 | this.key = value; | ||
47 | } | ||
48 | } | ||
49 | |||
50 | public bool IsString | ||
51 | { | ||
52 | get | ||
53 | { | ||
54 | return this.isString; | ||
55 | } | ||
56 | |||
57 | set | ||
58 | { | ||
59 | this.isString = value; | ||
60 | } | ||
61 | } | ||
62 | |||
63 | public byte[] Data | ||
64 | { | ||
65 | get | ||
66 | { | ||
67 | return this.data; | ||
68 | } | ||
69 | |||
70 | set | ||
71 | { | ||
72 | this.data = value; | ||
73 | this.isString = false; | ||
74 | } | ||
75 | } | ||
76 | |||
77 | public void Read(BinaryReader reader) | ||
78 | { | ||
79 | long basePosition = reader.BaseStream.Position; | ||
80 | int verInfoSize = (int) reader.ReadUInt16(); | ||
81 | int valueSize = (int) reader.ReadUInt16(); | ||
82 | bool dataIsString = (reader.ReadUInt16() != 0); | ||
83 | StringBuilder keyStringBuilder = new StringBuilder(); | ||
84 | char c; | ||
85 | while ((c = (char) reader.ReadUInt16()) != 0) | ||
86 | { | ||
87 | keyStringBuilder.Append(c); | ||
88 | } | ||
89 | this.Key = keyStringBuilder.ToString(); | ||
90 | Pad(reader, basePosition); | ||
91 | if (valueSize == 0) | ||
92 | { | ||
93 | this.data = null; | ||
94 | } | ||
95 | else | ||
96 | { | ||
97 | if (dataIsString) valueSize *= 2; // Count is # of chars instead of bytes | ||
98 | this.data = reader.ReadBytes(valueSize); | ||
99 | this.isString = dataIsString; | ||
100 | Pad(reader, basePosition); | ||
101 | } | ||
102 | |||
103 | while (reader.BaseStream.Position - basePosition < verInfoSize) | ||
104 | { | ||
105 | Pad(reader, basePosition); | ||
106 | VersionInfo childVerInfo = new VersionInfo(""); | ||
107 | childVerInfo.Read(reader); | ||
108 | this.children.Add(childVerInfo); | ||
109 | } | ||
110 | } | ||
111 | |||
112 | public void Write(BinaryWriter writer) | ||
113 | { | ||
114 | long basePosition = writer.BaseStream.Position; | ||
115 | writer.Write((ushort) this.Length); | ||
116 | byte[] valueBytes = this.data; | ||
117 | writer.Write((ushort) ((valueBytes != null ? valueBytes.Length : 0) / (this.IsString ? 2 : 1))); | ||
118 | writer.Write((ushort) (this.IsString ? 1 : 0)); | ||
119 | byte[] keyBytes = new byte[Encoding.Unicode.GetByteCount(this.Key) + 2]; | ||
120 | Encoding.Unicode.GetBytes(this.Key, 0, this.Key.Length, keyBytes, 0); | ||
121 | writer.Write(keyBytes); | ||
122 | Pad(writer, basePosition); | ||
123 | if (valueBytes != null) | ||
124 | { | ||
125 | writer.Write(valueBytes); | ||
126 | Pad(writer, basePosition); | ||
127 | } | ||
128 | |||
129 | foreach (VersionInfo childVersionInfo in this.children) | ||
130 | { | ||
131 | Pad(writer, basePosition); | ||
132 | childVersionInfo.Write(writer); | ||
133 | } | ||
134 | } | ||
135 | |||
136 | private static void Pad(BinaryReader reader, long basePosition) | ||
137 | { | ||
138 | long position = reader.BaseStream.Position; | ||
139 | int diff = (int) (position - basePosition) % 4; | ||
140 | if (diff > 0) while (diff++ < 4 && reader.BaseStream.Position < reader.BaseStream.Length) reader.ReadByte(); | ||
141 | } | ||
142 | private static void Pad(BinaryWriter writer, long basePosition) | ||
143 | { | ||
144 | long position = writer.BaseStream.Position; | ||
145 | int diff = (int) (position - basePosition) % 4; | ||
146 | if (diff > 0) while (diff++ < 4) writer.Write((byte) 0); | ||
147 | } | ||
148 | |||
149 | private int Length | ||
150 | { | ||
151 | get | ||
152 | { | ||
153 | int len = 6 + Encoding.Unicode.GetByteCount(this.Key) + 2; | ||
154 | if (len % 4 > 0) len += (4 - len % 4); | ||
155 | len += (this.data != null ? this.data.Length : 0); | ||
156 | if (len % 4 > 0) len += (4 - len % 4); | ||
157 | foreach (VersionInfo childVersionInfo in this.children) | ||
158 | { | ||
159 | if (len % 4 > 0) len += (4 - len % 4); | ||
160 | len += childVersionInfo.Length; | ||
161 | } | ||
162 | return len; | ||
163 | } | ||
164 | } | ||
165 | |||
166 | public static explicit operator VersionInfo(byte[] bytesValue) | ||
167 | { | ||
168 | VersionInfo viValue = new VersionInfo(""); | ||
169 | using (BinaryReader reader = new BinaryReader(new MemoryStream(bytesValue, false))) | ||
170 | { | ||
171 | viValue.Read(reader); | ||
172 | } | ||
173 | return viValue; | ||
174 | } | ||
175 | |||
176 | public static explicit operator byte[](VersionInfo viValue) | ||
177 | { | ||
178 | byte[] bytesValue = new byte[viValue.Length]; | ||
179 | using (BinaryWriter writer = new BinaryWriter(new MemoryStream(bytesValue, true))) | ||
180 | { | ||
181 | viValue.Write(writer); | ||
182 | } | ||
183 | return bytesValue; | ||
184 | } | ||
185 | |||
186 | public VersionInfo this[string itemKey] | ||
187 | { | ||
188 | get | ||
189 | { | ||
190 | int index = this.IndexOf(itemKey); | ||
191 | if (index < 0) return null; | ||
192 | return this.children[index]; | ||
193 | } | ||
194 | } | ||
195 | |||
196 | public void Add(VersionInfo item) | ||
197 | { | ||
198 | this.children.Add(item); | ||
199 | } | ||
200 | |||
201 | public bool Remove(VersionInfo item) | ||
202 | { | ||
203 | return this.children.Remove(item); | ||
204 | } | ||
205 | |||
206 | public bool Remove(string itemKey) | ||
207 | { | ||
208 | int index = this.IndexOf(itemKey); | ||
209 | if (index >= 0) | ||
210 | { | ||
211 | this.children.RemoveAt(index); | ||
212 | return true; | ||
213 | } | ||
214 | else | ||
215 | { | ||
216 | return false; | ||
217 | } | ||
218 | } | ||
219 | |||
220 | private int IndexOf(string itemKey) | ||
221 | { | ||
222 | for (int i = 0; i < this.children.Count; i++) | ||
223 | { | ||
224 | if (this.children[i].Key == itemKey) return i; | ||
225 | } | ||
226 | return -1; | ||
227 | } | ||
228 | |||
229 | public bool Contains(VersionInfo item) | ||
230 | { | ||
231 | return this.children.Contains(item); | ||
232 | } | ||
233 | |||
234 | public void CopyTo(VersionInfo[] array, int index) | ||
235 | { | ||
236 | this.children.CopyTo(array, index); | ||
237 | } | ||
238 | |||
239 | public void Clear() | ||
240 | { | ||
241 | this.children.Clear(); | ||
242 | } | ||
243 | |||
244 | public int Count | ||
245 | { | ||
246 | get | ||
247 | { | ||
248 | return this.children.Count; | ||
249 | } | ||
250 | } | ||
251 | |||
252 | public bool IsReadOnly | ||
253 | { | ||
254 | get | ||
255 | { | ||
256 | return false; | ||
257 | } | ||
258 | } | ||
259 | |||
260 | public IEnumerator<VersionInfo> GetEnumerator() | ||
261 | { | ||
262 | return this.children.GetEnumerator(); | ||
263 | } | ||
264 | |||
265 | IEnumerator IEnumerable.GetEnumerator() | ||
266 | { | ||
267 | return this.GetEnumerator(); | ||
268 | } | ||
269 | } | ||
270 | } | ||