The Labs \ Source Viewer \ SSCLI \ System.Xml.Xsl.IlGen \ UniqueList

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

Developer Fusion