aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Data/IntermediateSymbol.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/WixToolset.Data/IntermediateSymbol.cs')
-rw-r--r--src/WixToolset.Data/IntermediateSymbol.cs256
1 files changed, 256 insertions, 0 deletions
diff --git a/src/WixToolset.Data/IntermediateSymbol.cs b/src/WixToolset.Data/IntermediateSymbol.cs
new file mode 100644
index 00000000..4030df5d
--- /dev/null
+++ b/src/WixToolset.Data/IntermediateSymbol.cs
@@ -0,0 +1,256 @@
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.Data
4{
5 using System;
6 using System.Diagnostics;
7 using SimpleJson;
8
9 [DebuggerDisplay("{DebuggerDisplay,nq}")]
10 public class IntermediateSymbol
11 {
12 private object tags;
13
14 public IntermediateSymbol(IntermediateSymbolDefinition definition) : this(definition, null, null)
15 {
16 }
17
18 public IntermediateSymbol(IntermediateSymbolDefinition definition, SourceLineNumber sourceLineNumber, Identifier id = null)
19 {
20 this.Definition = definition;
21 this.Fields = new IntermediateField[definition.FieldDefinitions.Length];
22 this.SourceLineNumbers = sourceLineNumber;
23 this.Id = id;
24 }
25
26 public IntermediateSymbolDefinition Definition { get; }
27
28 public IntermediateField[] Fields { get; }
29
30 public SourceLineNumber SourceLineNumbers { get; set; }
31
32 public Identifier Id { get; set; }
33
34 public IntermediateField this[int index] => this.Fields[index];
35
36 private string DebuggerDisplay => $"{this.Definition?.Name} {this.Id?.Id}";
37
38 public bool AddTag(string add)
39 {
40 if (this.tags == null)
41 {
42 this.tags = add;
43 }
44 else if (this.tags is string tag)
45 {
46 if (tag == add)
47 {
48 return false;
49 }
50
51 this.tags = new[] { tag, add };
52 }
53 else
54 {
55 var tagsArray = (string[])this.tags;
56 var array = new string[tagsArray.Length + 1];
57
58 for (var i = 0; i < tagsArray.Length; ++i)
59 {
60 if (tagsArray[i] == add)
61 {
62 return false;
63 }
64
65 array[i] = tagsArray[i];
66 }
67
68 array[tagsArray.Length] = add;
69
70 this.tags = array;
71 }
72
73 return true;
74 }
75
76 public bool HasTag(string has)
77 {
78 if (this.tags == null)
79 {
80 return false;
81 }
82 else if (this.tags is string tag)
83 {
84 return tag == has;
85 }
86 else
87 {
88 foreach (var element in (string[])this.tags)
89 {
90 if (element == has)
91 {
92 return true;
93 }
94 }
95 }
96
97 return false;
98 }
99
100 public bool RemoveTag(string remove)
101 {
102 if (this.tags is string tag)
103 {
104 if (tag == remove)
105 {
106 this.tags = null;
107 return true;
108 }
109 }
110 else if (this.tags is string[] tagsArray)
111 {
112 if (tagsArray.Length == 2)
113 {
114 if (tagsArray[0] == remove)
115 {
116 this.tags = tagsArray[1];
117 return true;
118 }
119 else if (tagsArray[1] == remove)
120 {
121 this.tags = tagsArray[0];
122 return true;
123 }
124 }
125 else
126 {
127 var array = new string[tagsArray.Length - 1];
128 var arrayIndex = 0;
129 var found = false;
130
131 for (var i = 0; i < tagsArray.Length; ++i)
132 {
133 if (tagsArray[i] == remove)
134 {
135 found = true;
136 continue;
137 }
138 else if (arrayIndex == array.Length)
139 {
140 break;
141 }
142
143 array[arrayIndex++] = tagsArray[i];
144 }
145
146 if (found)
147 {
148 this.tags = array;
149 return true;
150 }
151 }
152 }
153
154 return false;
155 }
156
157 internal static IntermediateSymbol Deserialize(ISymbolDefinitionCreator creator, Uri baseUri, JsonObject jsonObject)
158 {
159 var definitionName = jsonObject.GetValueOrDefault<string>("type");
160 var idJson = jsonObject.GetValueOrDefault<JsonObject>("id");
161 var sourceLineNumbersJson = jsonObject.GetValueOrDefault<JsonObject>("ln");
162 var fieldsJson = jsonObject.GetValueOrDefault<JsonArray>("fields");
163 var tagsJson = jsonObject.GetValueOrDefault<JsonArray>("tags");
164
165 var id = (idJson == null) ? null : Identifier.Deserialize(idJson);
166 var sourceLineNumbers = (sourceLineNumbersJson == null) ? null : SourceLineNumber.Deserialize(sourceLineNumbersJson);
167
168 // TODO: this isn't sufficient.
169 if (!creator.TryGetSymbolDefinitionByName(definitionName, out var definition))
170 {
171 throw new WixException(ErrorMessages.UnknownSymbolType(definitionName));
172 }
173
174 var symbol = definition.CreateSymbol(sourceLineNumbers, id);
175
176 for (var i = 0; i < fieldsJson.Count && i < symbol.Fields.Length; ++i)
177 {
178 if (fieldsJson[i] is JsonObject fieldJson)
179 {
180 symbol.Fields[i] = IntermediateField.Deserialize(symbol.Definition.FieldDefinitions[i], baseUri, fieldJson);
181 }
182 }
183
184 if (tagsJson == null || tagsJson.Count == 0)
185 {
186 }
187 else if (tagsJson.Count == 1)
188 {
189 symbol.tags = (string)tagsJson[0];
190 }
191 else
192 {
193 var tags = new string[tagsJson.Count];
194
195 for (var i = 0; i < tagsJson.Count; ++i)
196 {
197 tags[i] = (string)tagsJson[i];
198 }
199
200 symbol.tags = tags;
201 }
202
203 return symbol;
204 }
205
206 internal JsonObject Serialize()
207 {
208 var jsonObject = new JsonObject
209 {
210 { "type", this.Definition.Name }
211 };
212
213 var idJson = this.Id?.Serialize();
214 if (idJson != null)
215 {
216 jsonObject.Add("id", idJson);
217 }
218
219 var lnJson = this.SourceLineNumbers?.Serialize();
220 if (lnJson != null)
221 {
222 jsonObject.Add("ln", lnJson);
223 }
224
225 var fieldsJson = new JsonArray(this.Fields.Length);
226
227 foreach (var field in this.Fields)
228 {
229 var fieldJson = field?.Serialize();
230 fieldsJson.Add(fieldJson);
231 }
232
233 jsonObject.Add("fields", fieldsJson);
234
235 if (this.tags is string || this.tags is string[])
236 {
237 JsonArray tagsJson;
238
239 if (this.tags is string tag)
240 {
241 tagsJson = new JsonArray(1) { tag };
242 }
243 else
244 {
245 var array = (string[])this.tags;
246 tagsJson = new JsonArray(array.Length);
247 tagsJson.AddRange(array);
248 }
249
250 jsonObject.Add("tags", tagsJson);
251 }
252
253 return jsonObject;
254 }
255 }
256}