aboutsummaryrefslogtreecommitdiff
path: root/src/WixToolset.Data/Section.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/WixToolset.Data/Section.cs240
1 files changed, 240 insertions, 0 deletions
diff --git a/src/WixToolset.Data/Section.cs b/src/WixToolset.Data/Section.cs
new file mode 100644
index 00000000..6757aa77
--- /dev/null
+++ b/src/WixToolset.Data/Section.cs
@@ -0,0 +1,240 @@
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.Collections.Generic;
7 using System.Diagnostics;
8 using System.Globalization;
9 using System.Linq;
10 using System.Xml;
11
12 /// <summary>
13 /// Section in an object file.
14 /// </summary>
15 public sealed class Section
16 {
17 /// <summary>
18 /// Creates a new section as part of an intermediate.
19 /// </summary>
20 /// <param name="id">Identifier for section.</param>
21 /// <param name="type">Type of section.</param>
22 /// <param name="codepage">Codepage for resulting database.</param>
23 public Section(string id, SectionType type, int codepage)
24 {
25 this.Id = id;
26 this.Type = type;
27 this.Codepage = codepage;
28
29 this.Tables = new TableIndexedCollection();
30 }
31
32 /// <summary>
33 /// Gets the identifier for the section.
34 /// </summary>
35 /// <value>Section identifier.</value>
36 public string Id { get; private set; }
37
38 /// <summary>
39 /// Gets the type of the section.
40 /// </summary>
41 /// <value>Type of section.</value>
42 public SectionType Type { get; private set; }
43
44 /// <summary>
45 /// Gets the codepage for the section.
46 /// </summary>
47 /// <value>Codepage for the section.</value>
48 public int Codepage { get; private set; }
49
50 /// <summary>
51 /// Gets the tables in the section.
52 /// </summary>
53 /// <value>Tables in section.</value>
54 public TableIndexedCollection Tables { get; private set; }
55
56 /// <summary>
57 /// Gets the source line information of the file containing this section.
58 /// </summary>
59 /// <value>The source line information of the file containing this section.</value>
60 public SourceLineNumber SourceLineNumbers { get; private set; }
61
62 /// <summary>
63 /// Gets the identity of the intermediate the section is contained within.
64 /// </summary>
65 public string IntermediateId { get; internal set; }
66
67 /// <summary>
68 /// Gets the identity of the library when the section is contained within one.
69 /// </summary>
70 public string LibraryId { get; internal set; }
71
72 /// <summary>
73 /// Ensures a table is added to the section's table collection.
74 /// </summary>
75 /// <param name="tableDefinition">Table definition for the table.</param>
76 /// <returns>Table in the section.</returns>
77 public Table EnsureTable(TableDefinition tableDefinition)
78 {
79 Table table;
80 if (!this.Tables.TryGetTable(tableDefinition.Name, out table))
81 {
82 table = new Table(this, tableDefinition);
83 this.Tables.Add(table);
84 }
85
86 return table;
87 }
88
89 /// <summary>
90 /// Parse a section from the xml.
91 /// </summary>
92 /// <param name="reader">XmlReader where the intermediate is persisted.</param>
93 /// <param name="tableDefinitions">TableDefinitions to use in the intermediate.</param>
94 /// <returns>The parsed Section.</returns>
95 internal static Section Read(XmlReader reader, TableDefinitionCollection tableDefinitions)
96 {
97 Debug.Assert("section" == reader.LocalName);
98
99 int codepage = 0;
100 bool empty = reader.IsEmptyElement;
101 string id = null;
102 SectionType type = SectionType.Unknown;
103
104 while (reader.MoveToNextAttribute())
105 {
106 switch (reader.Name)
107 {
108 case "codepage":
109 codepage = Convert.ToInt32(reader.Value, CultureInfo.InvariantCulture);
110 break;
111 case "id":
112 id = reader.Value;
113 break;
114 case "type":
115 switch (reader.Value)
116 {
117 case "bundle":
118 type = SectionType.Bundle;
119 break;
120 case "fragment":
121 type = SectionType.Fragment;
122 break;
123 case "module":
124 type = SectionType.Module;
125 break;
126 case "patchCreation":
127 type = SectionType.PatchCreation;
128 break;
129 case "product":
130 type = SectionType.Product;
131 break;
132 case "patch":
133 type = SectionType.Patch;
134 break;
135 default:
136 throw new XmlException();
137 }
138 break;
139 }
140 }
141
142 if (null == id && (SectionType.Unknown != type && SectionType.Fragment != type))
143 {
144 throw new XmlException();
145 }
146
147 if (SectionType.Unknown == type)
148 {
149 throw new XmlException();
150 }
151
152 Section section = new Section(id, type, codepage);
153 section.SourceLineNumbers = SourceLineNumber.CreateFromUri(reader.BaseURI);
154
155 List<Table> tables = new List<Table>();
156 if (!empty)
157 {
158 bool done = false;
159
160 while (!done && reader.Read())
161 {
162 switch (reader.NodeType)
163 {
164 case XmlNodeType.Element:
165 switch (reader.LocalName)
166 {
167 case "table":
168 tables.Add(Table.Read(reader, section, tableDefinitions));
169 break;
170 default:
171 throw new XmlException();
172 }
173 break;
174 case XmlNodeType.EndElement:
175 done = true;
176 break;
177 }
178 }
179
180 if (!done)
181 {
182 throw new XmlException();
183 }
184 }
185
186 section.Tables = new TableIndexedCollection(tables);
187
188 return section;
189 }
190
191 /// <summary>
192 /// Persist the Section to an XmlWriter.
193 /// </summary>
194 /// <param name="writer">XmlWriter which reference will be persisted to.</param>
195 internal void Write(XmlWriter writer)
196 {
197 writer.WriteStartElement("section", Intermediate.XmlNamespaceUri);
198
199 if (null != this.Id)
200 {
201 writer.WriteAttributeString("id", this.Id);
202 }
203
204 switch (this.Type)
205 {
206 case SectionType.Bundle:
207 writer.WriteAttributeString("type", "bundle");
208 break;
209 case SectionType.Fragment:
210 writer.WriteAttributeString("type", "fragment");
211 break;
212 case SectionType.Module:
213 writer.WriteAttributeString("type", "module");
214 break;
215 case SectionType.Product:
216 writer.WriteAttributeString("type", "product");
217 break;
218 case SectionType.PatchCreation:
219 writer.WriteAttributeString("type", "patchCreation");
220 break;
221 case SectionType.Patch:
222 writer.WriteAttributeString("type", "patch");
223 break;
224 }
225
226 if (0 != this.Codepage)
227 {
228 writer.WriteAttributeString("codepage", this.Codepage.ToString());
229 }
230
231 // save the rows in table order
232 foreach (Table table in this.Tables.OrderBy(t => t.Name))
233 {
234 table.Write(writer);
235 }
236
237 writer.WriteEndElement();
238 }
239 }
240}