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