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