aboutsummaryrefslogtreecommitdiff
path: root/src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs')
-rw-r--r--src/dtf/WixToolset.Dtf.Resources/VersionInfo.cs270
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
3namespace 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}