| File: System\Xml\Xsl\IlGen\StaticDataManager.cs | Web Access |
| Project: src\runtime\src\libraries\System.Private.Xml\src\System.Private.Xml.csproj (System.Private.Xml) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Diagnostics.CodeAnalysis; 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 sealed class UniqueList<T> where T : notnull { private readonly Dictionary<T, int> _lookup = new Dictionary<T, int>(); private readonly 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) { if (!_lookup.TryGetValue(value, out int id)) { // The value does not yet exist, so add it to the list id = _list.Count; _lookup.Add(value, id); _list.Add(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 sealed 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) { _uniqueNames ??= new UniqueList<string>(); return _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 _uniqueNames?.ToArray(); } } /// <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) { _uniqueFilters ??= new UniqueList<Int32Pair>(); return _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 _uniqueFilters?.ToArray(); } } /// <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 _prefixMappingsList ??= new List<StringPair[]>(); _prefixMappingsList.Add(prefixMappings); return _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 _prefixMappingsList?.ToArray(); } } /// <summary> /// Declare a new global variable or parameter. /// </summary> public int DeclareGlobalValue(string name) { int idx; _globalNames ??= new List<string>(); idx = _globalNames.Count; _globalNames.Add(name); return idx; } /// <summary> /// Return an array containing the names of all global variables and parameters. /// </summary> public string[]? GlobalNames { get { return _globalNames?.ToArray(); } } /// <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, [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.PublicParameterlessConstructor)] Type ebType) { _earlyInfo ??= new UniqueList<EarlyBoundInfo>(); return _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 => _earlyInfo?.ToArray(); /// <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) { _uniqueXmlTypes ??= new UniqueList<XmlQueryType>(); XmlQueryTypeFactory.CheckSerializability(type); return _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 _uniqueXmlTypes?.ToArray(); } } /// <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) { _uniqueCollations ??= new UniqueList<XmlCollation>(); return _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 _uniqueCollations?.ToArray(); } } } }