Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.SqlXml / System / Xml / Xsl / IlGen / StaticDataManager.cs
1 //------------------------------------------------------------------------------
2 // <copyright file="StaticDataManager.cs" company="Microsoft">
3 //     Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 // <owner current="true" primary="true">Microsoft</owner>
6 // <owner current="false">Microsoft</owner>
7 //------------------------------------------------------------------------------
8
9 using System.Collections;
10 using System.Collections.Generic;
11 using System.Diagnostics;
12 using System.Reflection;
13 using System.Xml.Xsl.Qil;
14 using System.Xml.Xsl.Runtime;
15
16 namespace System.Xml.Xsl.IlGen {
17
18     /// <summary>
19     /// This internal class maintains a list of unique values.  Each unique value is assigned a unique ID, which can
20     /// be used to quickly access the value, since it corresponds to the value's position in the list.
21     /// </summary>
22     internal class UniqueList<T> {
23         private Dictionary<T, int> lookup = new Dictionary<T, int>();
24         private List<T> list = new List<T>();
25
26         /// <summary>
27         /// If "value" is already in the list, do not add it.  Return the unique ID of the value in the list.
28         /// </summary>
29         public int Add(T value) {
30             int id;
31
32             if (!this.lookup.ContainsKey(value)) {
33                 // The value does not yet exist, so add it to the list
34                 id = list.Count;
35                 this.lookup.Add(value, id);
36                 this.list.Add(value);
37             }
38             else {
39                 id = this.lookup[value];
40             }
41
42             return id;
43         }
44
45         /// <summary>
46         /// Return an array of the unique values.
47         /// </summary>
48         public T[] ToArray() {
49             return list.ToArray();
50         }
51     }
52
53
54     /// <summary>
55     /// Manages all static data that is used by the runtime.  This includes:
56     ///   1. All NCName and QName atoms that will be used at run-time
57     ///   2. All QName filters that will be used at run-time
58     ///   3. All Xml types that will be used at run-time
59     ///   4. All global variables and parameters
60     /// </summary>
61     internal class StaticDataManager {
62         private UniqueList<string> uniqueNames;
63         private UniqueList<Int32Pair> uniqueFilters;
64         private List<StringPair[]> prefixMappingsList;
65         private List<string> globalNames;
66         private UniqueList<EarlyBoundInfo> earlyInfo;
67         private UniqueList<XmlQueryType> uniqueXmlTypes;
68         private UniqueList<XmlCollation> uniqueCollations;
69
70         /// <summary>
71         /// Add "name" to the list of unique names that are used by this query.  Return the index of
72         /// the unique name in the list.
73         /// </summary>
74         public int DeclareName(string name) {
75             if (this.uniqueNames == null)
76                 this.uniqueNames = new UniqueList<string>();
77
78             return this.uniqueNames.Add(name);
79         }
80
81         /// <summary>
82         /// Return an array of all names that are used by the query (null if no names).
83         /// </summary>
84         public string[] Names {
85             get { return (this.uniqueNames != null) ? this.uniqueNames.ToArray() : null; }
86         }
87
88         /// <summary>
89         /// Add a name filter to the list of unique filters that are used by this query.  Return the index of
90         /// the unique filter in the list.
91         /// </summary>
92         public int DeclareNameFilter(string locName, string nsUri) {
93             if (this.uniqueFilters == null)
94                 this.uniqueFilters = new UniqueList<Int32Pair>();
95
96             return this.uniqueFilters.Add(new Int32Pair(DeclareName(locName), DeclareName(nsUri)));
97         }
98
99         /// <summary>
100         /// Return an array of all name filters, where each name filter is represented as a pair of integer offsets (localName, namespaceUri)
101         /// into the Names array (null if no name filters).
102         /// </summary>
103         public Int32Pair[] NameFilters {
104             get { return (this.uniqueFilters != null) ? this.uniqueFilters.ToArray() : null; }
105         }
106
107         /// <summary>
108         /// Add a list of QilExpression NamespaceDeclarations to an array of strings (prefix followed by namespace URI).
109         /// Return index of the prefix mappings within this array.
110         /// </summary>
111         public int DeclarePrefixMappings(IList<QilNode> list) {
112             StringPair[] prefixMappings;
113
114             // Fill mappings array
115             prefixMappings = new StringPair[list.Count];
116             for (int i = 0; i < list.Count; i++) {
117                 // Each entry in mappings array must be a constant NamespaceDeclaration
118                 QilBinary ndNmspDecl = (QilBinary) list[i];
119                 Debug.Assert(ndNmspDecl != null);
120                 Debug.Assert(ndNmspDecl.Left is QilLiteral && ndNmspDecl.Right is QilLiteral);
121
122                 prefixMappings[i] = new StringPair((string) (QilLiteral) ndNmspDecl.Left, (string) (QilLiteral) ndNmspDecl.Right);
123             }
124
125             // Add mappings to list and return index
126             if (this.prefixMappingsList == null)
127                 this.prefixMappingsList = new List<StringPair[]>();
128
129             this.prefixMappingsList.Add(prefixMappings);
130             return this.prefixMappingsList.Count - 1;
131         }
132
133         /// <summary>
134         /// Return an array of all prefix mappings that are used by the query to compute names (null if no mappings).
135         /// </summary>
136         public StringPair[][] PrefixMappingsList {
137             get { return (this.prefixMappingsList != null) ? this.prefixMappingsList.ToArray() : null; }
138         }
139
140         /// <summary>
141         /// Declare a new global variable or parameter.
142         /// </summary>
143         public int DeclareGlobalValue(string name) {
144             int idx;
145
146             if (this.globalNames == null)
147                 this.globalNames = new List<string>();
148
149             idx = this.globalNames.Count;
150             this.globalNames.Add(name);
151             return idx;
152         }
153
154         /// <summary>
155         /// Return an array containing the names of all global variables and parameters.
156         /// </summary>
157         public string[] GlobalNames {
158             get { return (this.globalNames != null) ? this.globalNames.ToArray() : null; }
159         }
160
161         /// <summary>
162         /// Add early bound information to a list that is used by this query.  Return the index of
163         /// the early bound information in the list.
164         /// </summary>
165         public int DeclareEarlyBound(string namespaceUri, Type ebType) {
166             if (this.earlyInfo == null)
167                 this.earlyInfo = new UniqueList<EarlyBoundInfo>();
168
169             return this.earlyInfo.Add(new EarlyBoundInfo(namespaceUri, ebType));
170         }
171
172         /// <summary>
173         /// Return an array of all early bound information that is used by the query (null if none is used).
174         /// </summary>
175         public EarlyBoundInfo[] EarlyBound {
176             get {
177                 if (this.earlyInfo != null)
178                     return this.earlyInfo.ToArray();
179
180                 return null;
181             }
182         }
183
184         /// <summary>
185         /// Add "type" to the list of unique types that are used by this query.  Return the index of
186         /// the unique type in the list.
187         /// </summary>
188         public int DeclareXmlType(XmlQueryType type) {
189             if (this.uniqueXmlTypes == null)
190                 this.uniqueXmlTypes = new UniqueList<XmlQueryType>();
191
192             XmlQueryTypeFactory.CheckSerializability(type);
193             return this.uniqueXmlTypes.Add(type);
194         }
195
196         /// <summary>
197         /// Return an array of all types that are used by the query (null if no names).
198         /// </summary>
199         public XmlQueryType[] XmlTypes {
200             get { return (this.uniqueXmlTypes != null) ? this.uniqueXmlTypes.ToArray() : null; }
201         }
202
203         /// <summary>
204         /// Add "collation" to the list of unique collations that are used by this query.  Return the index of
205         /// the unique collation in the list.
206         /// </summary>
207         public int DeclareCollation(string collation) {
208             if (this.uniqueCollations == null)
209                 this.uniqueCollations = new UniqueList<XmlCollation>();
210
211             return this.uniqueCollations.Add(XmlCollation.Create(collation));
212         }
213
214         /// <summary>
215         /// Return an array of all collations that are used by the query (null if no names).
216         /// </summary>
217         public XmlCollation[] Collations {
218             get { return (this.uniqueCollations != null) ? this.uniqueCollations.ToArray() : null; }
219         }
220     }
221 }