The Labs \ Source Viewer \ SSCLI \ System.Xml \ NamespaceResolverProxy

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlWellFormedWriter.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.IO;
  17. using System.Text;
  18. using System.Xml;
  19. using System.Xml.XPath;
  20. using System.Xml.Schema;
  21. using System.Diagnostics;
  22. using System.Collections;
  23. using System.Globalization;
  24. using System.Collections.Generic;
  25. // OpenIssue : is it better to cache the current namespace decls for each elem
  26. // as the current code does, or should it just always walk the namespace stack?
  27. namespace System.Xml
  28. {
  29.    
  30.     internal class XmlWellFormedWriter : XmlWriter
  31.     {
  32.         //
  33.         // Private types
  34.         //
  35.         class NamespaceResolverProxy : IXmlNamespaceResolver
  36.         {
  37.             XmlWellFormedWriter wfWriter;
  38.            
  39.             internal NamespaceResolverProxy(XmlWellFormedWriter wfWriter)
  40.             {
  41.                 this.wfWriter = wfWriter;
  42.             }
  43.            
  44.             IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
  45.             {
  46.                 throw new NotImplementedException();
  47.             }
  48.             string IXmlNamespaceResolver.LookupNamespace(string prefix)
  49.             {
  50.                 return wfWriter.LookupNamespace(prefix);
  51.             }
  52.            
  53.             string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
  54.             {
  55.                 return wfWriter.LookupPrefix(namespaceName);
  56.             }
  57.         }
  58.        
  59.         struct ElementScope
  60.         {
  61.             internal int prevNSTop;
  62.             internal string prefix;
  63.             internal string localName;
  64.             internal string namespaceUri;
  65.             internal XmlSpace xmlSpace;
  66.             internal string xmlLang;
  67.            
  68.             internal void Set(string prefix, string localName, string namespaceUri, int prevNSTop)
  69.             {
  70.                 this.prevNSTop = prevNSTop;
  71.                 this.prefix = prefix;
  72.                 this.namespaceUri = namespaceUri;
  73.                 this.localName = localName;
  74.                 this.xmlSpace = (System.Xml.XmlSpace)(int)-1;
  75.                 this.xmlLang = null;
  76.             }
  77.            
  78.             internal void WriteEndElement(XmlRawWriter rawWriter)
  79.             {
  80.                 rawWriter.WriteEndElement(prefix, localName, namespaceUri);
  81.             }
  82.            
  83.             internal void WriteFullEndElement(XmlRawWriter rawWriter)
  84.             {
  85.                 rawWriter.WriteFullEndElement(prefix, localName, namespaceUri);
  86.             }
  87.         }
  88.        
  89.         enum NamespaceKind
  90.         {
  91.             Written,
  92.             NeedToWrite,
  93.             Implied,
  94.             Special
  95.         }
  96.        
  97.         struct Namespace
  98.         {
  99.             internal string prefix;
  100.             internal string namespaceUri;
  101.             internal NamespaceKind kind;
  102.             internal int prevNsIndex;
  103.            
  104.             internal void Set(string prefix, string namespaceUri, NamespaceKind kind)
  105.             {
  106.                 this.prefix = prefix;
  107.                 this.namespaceUri = namespaceUri;
  108.                 this.kind = kind;
  109.                 this.prevNsIndex = -1;
  110.             }
  111.            
  112.             internal void WriteDecl(XmlWriter writer, XmlRawWriter rawWriter)
  113.             {
  114.                 Debug.Assert(kind == NamespaceKind.NeedToWrite);
  115.                 if (null != rawWriter) {
  116.                     rawWriter.WriteNamespaceDeclaration(prefix, namespaceUri);
  117.                 }
  118.                 else {
  119.                     if (prefix.Length == 0) {
  120.                         writer.WriteStartAttribute(string.Empty, "xmlns", XmlReservedNs.NsXmlNs);
  121.                     }
  122.                     else {
  123.                         writer.WriteStartAttribute("xmlns", prefix, XmlReservedNs.NsXmlNs);
  124.                     }
  125.                     writer.WriteString(namespaceUri);
  126.                     writer.WriteEndAttribute();
  127.                 }
  128.             }
  129.         }
  130.        
  131.         struct AttrName
  132.         {
  133.             internal string prefix;
  134.             internal string namespaceUri;
  135.             internal string localName;
  136.             internal int prev;
  137.            
  138.             internal void Set(string prefix, string localName, string namespaceUri)
  139.             {
  140.                 this.prefix = prefix;
  141.                 this.namespaceUri = namespaceUri;
  142.                 this.localName = localName;
  143.                 this.prev = 0;
  144.             }
  145.            
  146.             internal bool IsDuplicate(string prefix, string localName, string namespaceUri)
  147.             {
  148.                 return ((this.localName == localName) && ((this.prefix == prefix) || (this.namespaceUri == namespaceUri)));
  149.             }
  150.         }
  151.        
  152.         enum State
  153.         {
  154.             Start = 0,
  155.             TopLevel = 1,
  156.             Document = 2,
  157.             Element = 3,
  158.             Content = 4,
  159.             B64Content = 5,
  160.             B64Attribute = 6,
  161.             AfterRootEle = 7,
  162.             Attribute = 8,
  163.             SpecialAttr = 9,
  164.             EndDocument = 10,
  165.             RootLevelAttr = 11,
  166.             RootLevelSpecAttr = 12,
  167.             RootLevelB64Attr = 13,
  168.             AfterRootLevelAttr = 14,
  169.             Closed = 15,
  170.             Error = 16,
  171.            
  172.             StartContent = 101,
  173.             StartContentEle = 102,
  174.             StartContentB64 = 103,
  175.             StartDoc = 104,
  176.             StartDocEle = 106,
  177.             EndAttrSEle = 107,
  178.             EndAttrEEle = 108,
  179.             EndAttrSCont = 109,
  180.             EndAttrSAttr = 111,
  181.             PostB64Cont = 112,
  182.             PostB64Attr = 113,
  183.             PostB64RootAttr = 114,
  184.             StartFragEle = 115,
  185.             StartFragCont = 116,
  186.             StartFragB64 = 117,
  187.             StartRootLevelAttr = 118
  188.         }
  189.        
  190.        
  191.         enum Token
  192.         {
  193.             StartDocument,
  194.             EndDocument,
  195.             PI,
  196.             Comment,
  197.             Dtd,
  198.             StartElement,
  199.             EndElement,
  200.             StartAttribute,
  201.             EndAttribute,
  202.             Text,
  203.             CData,
  204.             AtomicValue,
  205.             Base64,
  206.             RawData,
  207.             Whitespace
  208.         }
  209.        
  210.         enum SpecialAttribute
  211.         {
  212.             No = 0,
  213.             DefaultXmlns,
  214.             PrefixedXmlns,
  215.             XmlSpace,
  216.             XmlLang
  217.         }
  218.        
  219.         //
  220.         // Fields
  221.         //
  222.         // underlying writer
  223.         XmlWriter writer;
  224.         XmlRawWriter rawWriter;
  225.         // writer as XmlRawWriter
  226.         IXmlNamespaceResolver predefinedNamespaces;
  227.         // writer as IXmlNamespaceResolver
  228.         // namespace management
  229.         Namespace[] nsStack;
  230.         int nsTop;
  231.         Dictionary<string, int> nsHashtable;
  232.         bool useNsHashtable;
  233.        
  234.         // element scoping
  235.         ElementScope[] elemScopeStack;
  236.         int elemTop;
  237.        
  238.         // attribute tracking
  239.         AttrName[] attrStack;
  240.         int attrCount;
  241.         Dictionary<string, int> attrHashTable;
  242.        
  243.         // special attribute caching (xmlns, xml:space, xml:lang)
  244.         SpecialAttribute specAttr = SpecialAttribute.No;
  245.         StringBuilder attrValue;
  246.         string curDeclPrefix;
  247.        
  248.         // state machine
  249.         State[] stateTable;
  250.         State currentState;
  251.        
  252.         // settings
  253.         bool checkCharacters;
  254.        
  255.         // actual conformance level
  256.         ConformanceLevel conformanceLevel;
  257.        
  258.         // flags
  259.         bool dtdWritten;
  260.         bool xmlDeclFollows;
  261.        
  262.         // char type tables
  263.         XmlCharType xmlCharType = XmlCharType.Instance;
  264.        
  265.         // hash randomizer
  266.         SecureStringHasher hasher;
  267.        
  268.        
  269.         //
  270.         // Constants
  271.         //
  272.         const int ElementStackInitialSize = 8;
  273.         const int NamespaceStackInitialSize = 8;
  274.         const int AttributeArrayInitialSize = 8;
  275.         #if DEBUG
  276.         const int MaxAttrDuplWalkCount = 2;
  277.         const int MaxNamespacesWalkCount = 3;
  278.         #else
  279.         const int MaxAttrDuplWalkCount = 14;
  280.         const int MaxNamespacesWalkCount = 16;
  281.         #endif
  282.        
  283.         static internal readonly string[] stateName = {"Start", "TopLevel", "Document", "Element Start Tag", "Element Content", "Element Content", "Attribute", "EndRootElement", "Attribute", "Special Attribute",
  284.             // State.Start
  285.             // State.TopLevel
  286.             // State.Document
  287.             // State.Element
  288.             // State.Content
  289.             // State.B64Content
  290.             // State.B64Attribute
  291.             // State.AfterRootEle
  292.             // State.Attribute
  293.             // State.SpecialAttr
  294.             // State.EndDocument
  295.             // State.RootLevelAttr
  296.             // State.RootLevelSpecAttr
  297.             // State.RootLevelB64Attr
  298.             // State.AfterRootLevelAttr
  299.             // State.Closed
  300.             // State.Error
  301.         "End Document", "Root Level Attribute Value", "Root Level Special Attribute Value", "Root Level Base64 Attribute Value", "After Root Level Attribute", "Closed", "Error"};
  302.        
  303.         static internal readonly string[] tokenName = {"StartDocument", "EndDocument", "PI", "Comment", "DTD", "StartElement", "EndElement", "StartAttribute", "EndAttribute", "Text",
  304.             // Token.StartDocument
  305.             // Token.EndDocument
  306.             // Token.PI
  307.             // Token.Comment
  308.             // Token.Dtd
  309.             // Token.StartElement
  310.             // Token.EndElement
  311.             // Token.StartAttribut
  312.             // Token.EndAttribute
  313.             // Token.Text
  314.             // Token.CData
  315.             // Token.AtomicValue
  316.             // Token.Base64
  317.             // Token.RawData
  318.             // Token.Whitespace
  319.         "CDATA", "Atomic value", "Base64", "RawData", "Whitespace"};
  320.        
  321.         private static WriteState[] state2WriteState = {WriteState.Start, WriteState.Prolog, WriteState.Prolog, WriteState.Element, WriteState.Content, WriteState.Content, WriteState.Attribute, WriteState.Content, WriteState.Attribute, WriteState.Attribute,
  322.             // State.Start
  323.             // State.TopLevel
  324.             // State.Document
  325.             // State.Element
  326.             // State.Content
  327.             // State.B64Content
  328.             // State.B64Attribute
  329.             // State.AfterRootEle
  330.             // State.Attribute
  331.             // State.SpecialAttr
  332.             // State.EndDocument
  333.             // State.RootLevelAttr
  334.             // State.RootLevelSpecAttr
  335.             // State.RootLevelB64Attr
  336.             // State.AfterRootLevelAttr
  337.             // State.Closed
  338.             // State.Error
  339.         WriteState.Content, WriteState.Attribute, WriteState.Attribute, WriteState.Attribute, WriteState.Attribute, WriteState.Closed, WriteState.Error};
  340.        
  341.         private static readonly State[] StateTableDocument = {State.Document, State.Error, State.Error, State.Error, State.Error, State.PostB64Cont, State.Error, State.Error, State.Error, State.Error,
  342.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  343.         State.Error, State.PostB64Cont, State.Error, State.EndDocument, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  344.         State.Error, State.Error, State.StartDoc, State.TopLevel, State.Document, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.AfterRootEle,
  345.         State.EndAttrSCont, State.EndAttrSCont, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartDoc, State.TopLevel,
  346.         State.Document, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.AfterRootEle, State.EndAttrSCont, State.EndAttrSCont, State.Error, State.Error,
  347.         State.Error, State.Error, State.Error, State.Error, State.StartDoc, State.TopLevel, State.Document, State.Error, State.Error, State.PostB64Cont,
  348.         State.PostB64Attr, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  349.         State.StartDocEle, State.Element, State.Element, State.StartContentEle, State.Element, State.PostB64Cont, State.PostB64Attr, State.Error, State.EndAttrSEle, State.EndAttrSEle,
  350.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartContent,
  351.         State.Content, State.PostB64Cont, State.PostB64Attr, State.Error, State.EndAttrEEle, State.EndAttrEEle, State.Error, State.Error, State.Error, State.Error,
  352.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Attribute, State.Error, State.PostB64Cont, State.PostB64Attr, State.Error,
  353.         State.EndAttrSAttr, State.EndAttrSAttr, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  354.         State.Error, State.Error, State.Error, State.PostB64Cont, State.PostB64Attr, State.Error, State.Element, State.Element, State.Error, State.Error,
  355.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartContent, State.Content, State.PostB64Cont,
  356.         State.PostB64Attr, State.Error, State.Attribute, State.SpecialAttr, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  357.         State.Error, State.Error, State.Error, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.Error, State.EndAttrSCont, State.EndAttrSCont,
  358.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartContent,
  359.         State.Content, State.PostB64Cont, State.PostB64Attr, State.Error, State.Attribute, State.Error, State.Error, State.Error, State.Error, State.Error,
  360.         State.Error, State.Error, State.Error, State.Error, State.Error, State.StartContentB64, State.B64Content, State.B64Content, State.B64Attribute, State.Error,
  361.         State.B64Attribute, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartDoc, State.Error,
  362.         State.Document, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.AfterRootEle, State.Attribute, State.SpecialAttr, State.Error, State.Error,
  363.         State.Error, State.Error, State.Error, State.Error, State.StartDoc, State.TopLevel, State.Document, State.StartContent, State.Content, State.PostB64Cont,
  364.         State.PostB64Attr, State.AfterRootEle, State.Attribute, State.SpecialAttr, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error
  365.             // State.Start State.TopLevel State.Document State.Element State.Content State.B64Content State.B64Attribute State.AfterRootEle State.Attribute, State.SpecialAttr, State.EndDocument, State.RootLevelAttr, State.RootLevelSpecAttr, State.RootLevelB64Attr State.AfterRootLevelAttr, // 16
  366.             /* Token.StartDocument  */            /* Token.EndDocument    */            /* Token.PI            */            /* Token.Comment        */            /* Token.Dtd            */            /* Token.StartElement  */            /* Token.EndElement    */            /* Token.StartAttribute */            /* Token.EndAttribute  */            /* Token.Text          */            /* Token.CData          */            /* Token.AtomicValue    */            /* Token.Base64        */            /* Token.RawData        */            /* Token.Whitespace    */        };
  367.        
  368.         private static readonly State[] StateTableAuto = {State.Document, State.Error, State.Error, State.Error, State.Error, State.PostB64Cont, State.Error, State.Error, State.Error, State.Error,
  369.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  370.         State.Error, State.PostB64Cont, State.Error, State.EndDocument, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  371.         State.Error, State.Error, State.TopLevel, State.TopLevel, State.Error, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.AfterRootEle,
  372.         State.EndAttrSCont, State.EndAttrSCont, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.TopLevel, State.TopLevel,
  373.         State.Error, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.AfterRootEle, State.EndAttrSCont, State.EndAttrSCont, State.Error, State.Error,
  374.         State.Error, State.Error, State.Error, State.Error, State.StartDoc, State.TopLevel, State.Error, State.Error, State.Error, State.PostB64Cont,
  375.         State.PostB64Attr, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error,
  376.         State.StartFragEle, State.Element, State.Error, State.StartContentEle, State.Element, State.PostB64Cont, State.PostB64Attr, State.Element, State.EndAttrSEle, State.EndAttrSEle,
  377.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartContent,
  378.         State.Content, State.PostB64Cont, State.PostB64Attr, State.Error, State.EndAttrEEle, State.EndAttrEEle, State.Error, State.Error, State.Error, State.Error,
  379.         State.Error, State.Error, State.RootLevelAttr, State.Error, State.Error, State.Attribute, State.Error, State.PostB64Cont, State.PostB64Attr, State.Error,
  380.         State.EndAttrSAttr, State.EndAttrSAttr, State.Error, State.StartRootLevelAttr, State.StartRootLevelAttr, State.PostB64RootAttr, State.RootLevelAttr, State.Error, State.Error, State.Error,
  381.         State.Error, State.Error, State.Error, State.PostB64Cont, State.PostB64Attr, State.Error, State.Element, State.Element, State.Error, State.AfterRootLevelAttr,
  382.         State.AfterRootLevelAttr, State.PostB64RootAttr, State.Error, State.Error, State.StartFragCont, State.StartFragCont, State.Error, State.StartContent, State.Content, State.PostB64Cont,
  383.         State.PostB64Attr, State.Content, State.Attribute, State.SpecialAttr, State.Error, State.RootLevelAttr, State.RootLevelSpecAttr, State.PostB64RootAttr, State.Error, State.Error,
  384.         State.StartFragCont, State.StartFragCont, State.Error, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.Content, State.EndAttrSCont, State.EndAttrSCont,
  385.         State.Error, State.Error, State.Error, State.Error, State.Error, State.Error, State.StartFragCont, State.StartFragCont, State.Error, State.StartContent,
  386.         State.Content, State.PostB64Cont, State.PostB64Attr, State.Content, State.Attribute, State.Error, State.Error, State.RootLevelAttr, State.Error, State.PostB64RootAttr,
  387.         State.Error, State.Error, State.StartFragB64, State.StartFragB64, State.Error, State.StartContentB64, State.B64Content, State.B64Content, State.B64Attribute, State.B64Content,
  388.         State.B64Attribute, State.Error, State.Error, State.RootLevelB64Attr, State.Error, State.RootLevelB64Attr, State.Error, State.Error, State.StartFragCont, State.TopLevel,
  389.         State.Error, State.StartContent, State.Content, State.PostB64Cont, State.PostB64Attr, State.Content, State.Attribute, State.SpecialAttr, State.Error, State.RootLevelAttr,
  390.         State.RootLevelSpecAttr, State.PostB64RootAttr, State.AfterRootLevelAttr, State.Error, State.TopLevel, State.TopLevel, State.Error, State.StartContent, State.Content, State.PostB64Cont,
  391.         State.PostB64Attr, State.AfterRootEle, State.Attribute, State.SpecialAttr, State.Error, State.RootLevelAttr, State.RootLevelSpecAttr, State.PostB64RootAttr, State.AfterRootLevelAttr, State.Error
  392.             // State.Start State.TopLevel State.Document State.Element State.Content State.B64Content State.B64Attribute State.AfterRootEle State.Attribute, State.SpecialAttr, State.EndDocument, State.RootLevelAttr, State.RootLevelSpecAttr, State.RootLevelB64Attr, State.AfterRootLevelAttr // 16
  393.             /* Token.StartDocument  */            /* Token.StartDocument  */            /* Token.EndDocument    */            /* Token.EndDocument    */            /* Token.PI            */            /* Token.PI            */            /* Token.Comment        */            /* Token.Comment        */            /* Token.Dtd            */            /* Token.Dtd            */            /* Token.StartElement  */            /* Token.StartElement  */            /* Token.EndElement    */            /* Token.EndElement    */            /* Token.StartAttribute */            /* Token.StartAttribute */            /* Token.EndAttribute  */            /* Token.EndAttribute  */            /* Token.Text          */            /* Token.Text          */            /* Token.CData          */            /* Token.CData          */            /* Token.AtomicValue    */            /* Token.AtomicValue    */            /* Token.Base64        */            /* Token.Base64        */            /* Token.RawData        */            /* Token.RawData        */            /* Token.Whitespace    */            /* Token.Whitespace    */        };
  394.        
  395.         //
  396.         // Constructor & finalizer
  397.         //
  398.         internal XmlWellFormedWriter(XmlWriter writer, XmlWriterSettings settings)
  399.         {
  400.             Debug.Assert(writer != null);
  401.             Debug.Assert(settings != null);
  402.             Debug.Assert(MaxNamespacesWalkCount <= 3);
  403.            
  404.             this.writer = writer;
  405.            
  406.             rawWriter = writer as XmlRawWriter;
  407.             predefinedNamespaces = writer as IXmlNamespaceResolver;
  408.             if (rawWriter != null) {
  409.                 rawWriter.NamespaceResolver = new NamespaceResolverProxy(this);
  410.             }
  411.            
  412.             checkCharacters = settings.CheckCharacters;
  413.            
  414.             conformanceLevel = settings.ConformanceLevel;
  415.             stateTable = (conformanceLevel == ConformanceLevel.Document) ? StateTableDocument : StateTableAuto;
  416.            
  417.             currentState = State.Start;
  418.            
  419.             nsStack = new Namespace[NamespaceStackInitialSize];
  420.             nsStack[0].Set("xmlns", XmlReservedNs.NsXmlNs, NamespaceKind.Special);
  421.             nsStack[1].Set("xml", XmlReservedNs.NsXml, NamespaceKind.Special);
  422.             if (predefinedNamespaces == null) {
  423.                 nsStack[2].Set(string.Empty, string.Empty, NamespaceKind.Implied);
  424.             }
  425.             else {
  426.                 string defaultNs = predefinedNamespaces.LookupNamespace(string.Empty);
  427.                 nsStack[2].Set(string.Empty, (defaultNs == null ? string.Empty : defaultNs), NamespaceKind.Implied);
  428.             }
  429.             nsTop = 2;
  430.            
  431.             elemScopeStack = new ElementScope[ElementStackInitialSize];
  432.             elemScopeStack[0].Set(string.Empty, string.Empty, string.Empty, nsTop);
  433.             elemScopeStack[0].xmlSpace = XmlSpace.None;
  434.             elemScopeStack[0].xmlLang = null;
  435.             elemTop = 0;
  436.            
  437.             attrStack = new AttrName[AttributeArrayInitialSize];
  438.            
  439.             attrValue = new StringBuilder();
  440.            
  441.             hasher = new SecureStringHasher();
  442.         }
  443.        
  444.         //
  445.         // XmlWriter implementation
  446.         //
  447.         public override WriteState WriteState {
  448.             get {
  449.                 if ((int)currentState <= (int)State.Error) {
  450.                     return state2WriteState[(int)currentState];
  451.                 }
  452.                 else {
  453.                     Debug.Assert(false, "Expected currentState <= State.Error ");
  454.                     return WriteState.Error;
  455.                 }
  456.             }
  457.         }
  458.        
  459.         public override XmlWriterSettings Settings {
  460.             get {
  461.                 XmlWriterSettings settings = writer.Settings;
  462.                 settings.ReadOnly = false;
  463.                 settings.ConformanceLevel = conformanceLevel;
  464.                 settings.ReadOnly = true;
  465.                 return settings;
  466.             }
  467.         }
  468.        
  469.         public override void WriteStartDocument()
  470.         {
  471.             WriteStartDocumentImpl(XmlStandalone.Omit);
  472.         }
  473.        
  474.         public override void WriteStartDocument(bool standalone)
  475.         {
  476.             WriteStartDocumentImpl(standalone ? XmlStandalone.Yes : XmlStandalone.No);
  477.         }
  478.        
  479.         public override void WriteEndDocument()
  480.         {
  481.             try {
  482.                 // auto-close all elements
  483.                 while (elemTop > 0) {
  484.                     WriteEndElement();
  485.                 }
  486.                 State prevState = currentState;
  487.                 AdvanceState(Token.EndDocument);
  488.                
  489.                 if (prevState != State.AfterRootEle) {
  490.                     throw new ArgumentException(Res.GetString(Res.Xml_NoRoot));
  491.                 }
  492.                 if (rawWriter == null) {
  493.                     writer.WriteEndDocument();
  494.                 }
  495.             }
  496.             catch {
  497.                 currentState = State.Error;
  498.                 throw;
  499.             }
  500.         }
  501.        
  502.         public override void WriteDocType(string name, string pubid, string sysid, string subset)
  503.         {
  504.             try {
  505.                 if (name == null || name.Length == 0) {
  506.                     throw new ArgumentException(Res.GetString(Res.Xml_EmptyName));
  507.                 }
  508.                 XmlConvert.VerifyQName(name);
  509.                
  510.                 if (conformanceLevel == ConformanceLevel.Fragment) {
  511.                     throw new InvalidOperationException(Res.GetString(Res.Xml_DtdNotAllowedInFragment));
  512.                 }
  513.                
  514.                 AdvanceState(Token.Dtd);
  515.                 if (dtdWritten) {
  516.                     currentState = State.Error;
  517.                     throw new InvalidOperationException(Res.GetString(Res.Xml_DtdAlreadyWritten));
  518.                 }
  519.                
  520.                 if (conformanceLevel == ConformanceLevel.Auto) {
  521.                     conformanceLevel = ConformanceLevel.Document;
  522.                     stateTable = StateTableDocument;
  523.                 }
  524.                
  525.                 int i;
  526.                
  527.                 // check characters
  528.                 if (checkCharacters) {
  529.                     if (pubid != null) {
  530.                         if ((i = xmlCharType.IsPublicId(pubid)) >= 0) {
  531.                             throw new ArgumentException(Res.GetString(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionStr(pubid[i])), "pubid");
  532.                         }
  533.                     }
  534.                     if (sysid != null) {
  535.                         if ((i = xmlCharType.IsOnlyCharData(sysid)) >= 0) {
  536.                             throw new ArgumentException(Res.GetString(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionStr(sysid[i])), "sysid");
  537.                         }
  538.                     }
  539.                     if (subset != null) {
  540.                         if ((i = xmlCharType.IsOnlyCharData(subset)) >= 0) {
  541.                             throw new ArgumentException(Res.GetString(Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionStr(subset[i])), "subset");
  542.                         }
  543.                     }
  544.                 }
  545.                
  546.                 // write doctype
  547.                 writer.WriteDocType(name, pubid, sysid, subset);
  548.                 dtdWritten = true;
  549.             }
  550.             catch {
  551.                 currentState = State.Error;
  552.                 throw;
  553.             }
  554.         }
  555.        
  556.         public override void WriteStartElement(string prefix, string localName, string ns)
  557.         {
  558.             try {
  559.                 // check local name
  560.                 if (localName == null || localName.Length == 0) {
  561.                     throw new ArgumentException(Res.GetString(Res.Xml_EmptyLocalName));
  562.                 }
  563.                 CheckNCName(localName);
  564.                
  565.                 AdvanceState(Token.StartElement);
  566.                
  567.                 // lookup prefix / namespace
  568.                 if (prefix == null) {
  569.                     if (ns != null) {
  570.                         prefix = LookupPrefix(ns);
  571.                     }
  572.                     if (prefix == null) {
  573.                         prefix = string.Empty;
  574.                     }
  575.                 }
  576.                 else if (prefix.Length > 0) {
  577.                     CheckNCName(prefix);
  578.                     if (ns == null) {
  579.                         ns = LookupNamespace(prefix);
  580.                     }
  581.                     if (ns == null || (ns != null && ns.Length == 0)) {
  582.                         throw new ArgumentException(Res.GetString(Res.Xml_PrefixForEmptyNs));
  583.                     }
  584.                 }
  585.                 if (ns == null) {
  586.                     ns = LookupNamespace(prefix);
  587.                     if (ns == null) {
  588.                         Debug.Assert(prefix.Length == 0);
  589.                         ns = string.Empty;
  590.                     }
  591.                 }
  592.                
  593.                 // write start tag
  594.                 writer.WriteStartElement(prefix, localName, ns);
  595.                
  596.                 // push element on stack and add/check namespace
  597.                 int top = ++elemTop;
  598.                 if (top == elemScopeStack.Length) {
  599.                     ElementScope[] newStack = new ElementScope[top * 2];
  600.                     Array.Copy(elemScopeStack, newStack, top);
  601.                     elemScopeStack = newStack;
  602.                 }
  603.                 elemScopeStack[top].Set(prefix, localName, ns, nsTop);
  604.                
  605.                 PushNamespace(prefix, ns, false);
  606.                
  607.                 if (attrCount >= MaxAttrDuplWalkCount) {
  608.                     attrHashTable.Clear();
  609.                 }
  610.                 attrCount = 0;
  611.                
  612.             }
  613.             catch {
  614.                 currentState = State.Error;
  615.                 throw;
  616.             }
  617.         }
  618.        
  619.        
  620.         public override void WriteEndElement()
  621.         {
  622.             try {
  623.                 AdvanceState(Token.EndElement);
  624.                
  625.                 int top = elemTop;
  626.                 if (top == 0) {
  627.                     throw new XmlException(Res.Xml_NoStartTag, string.Empty);
  628.                 }
  629.                
  630.                 // write end tag
  631.                 if (rawWriter != null) {
  632.                     elemScopeStack[top].WriteEndElement(rawWriter);
  633.                 }
  634.                 else {
  635.                     writer.WriteEndElement();
  636.                 }
  637.                
  638.                 // pop namespaces
  639.                 int prevNsTop = elemScopeStack[top].prevNSTop;
  640.                 if (useNsHashtable && prevNsTop < nsTop) {
  641.                     PopNamespaces(prevNsTop + 1, nsTop);
  642.                 }
  643.                 nsTop = prevNsTop;
  644.                 elemTop = --top;
  645.                
  646.                 // check "one root element" condition for ConformanceLevel.Document
  647.                 if (top == 0) {
  648.                     if (conformanceLevel == ConformanceLevel.Document) {
  649.                         currentState = State.AfterRootEle;
  650.                     }
  651.                     else {
  652.                         currentState = State.TopLevel;
  653.                     }
  654.                 }
  655.             }
  656.             catch {
  657.                 currentState = State.Error;
  658.                 throw;
  659.             }
  660.         }
  661.        
  662.         public override void WriteFullEndElement()
  663.         {
  664.             try {
  665.                 AdvanceState(Token.EndElement);
  666.                
  667.                 int top = elemTop;
  668.                 if (top == 0) {
  669.                     throw new XmlException(Res.Xml_NoStartTag, string.Empty);
  670.                 }
  671.                
  672.                 // write end tag
  673.                 if (rawWriter != null) {
  674.                     elemScopeStack[top].WriteFullEndElement(rawWriter);
  675.                 }
  676.                 else {
  677.                     writer.WriteFullEndElement();
  678.                 }
  679.                
  680.                 // pop namespaces
  681.                 int prevNsTop = elemScopeStack[top].prevNSTop;
  682.                 if (useNsHashtable && prevNsTop < nsTop) {
  683.                     PopNamespaces(prevNsTop + 1, nsTop);
  684.                 }
  685.                 nsTop = prevNsTop;
  686.                 elemTop = --top;
  687.                
  688.                 // check "one root element" condition for ConformanceLevel.Document
  689.                 if (top == 0) {
  690.                     if (conformanceLevel == ConformanceLevel.Document) {
  691.                         currentState = State.AfterRootEle;
  692.                     }
  693.                     else {
  694.                         currentState = State.TopLevel;
  695.                     }
  696.                 }
  697.             }
  698.             catch {
  699.                 currentState = State.Error;
  700.                 throw;
  701.             }
  702.         }
  703.        
  704.         public override void WriteStartAttribute(string prefix, string localName, string namespaceName)
  705.         {
  706.             try {
  707.                 // check local name
  708.                 if (localName == null || localName.Length == 0) {
  709.                     if (prefix == "xmlns") {
  710.                         localName = "xmlns";
  711.                         prefix = string.Empty;
  712.                     }
  713.                     else {
  714.                         throw new ArgumentException(Res.GetString(Res.Xml_EmptyLocalName));
  715.                     }
  716.                 }
  717.                 CheckNCName(localName);
  718.                
  719.                 AdvanceState(Token.StartAttribute);
  720.                
  721.                 // lookup prefix / namespace
  722.                 if (prefix == null) {
  723.                     if (namespaceName != null) {
  724.                         // special case prefix=null/localname=xmlns
  725.                         if (!(localName == "xmlns" && namespaceName == XmlReservedNs.NsXmlNs))
  726.                             prefix = LookupPrefix(namespaceName);
  727.                     }
  728.                     if (prefix == null) {
  729.                         prefix = string.Empty;
  730.                     }
  731.                 }
  732.                 if (namespaceName == null) {
  733.                     if (prefix != null && prefix.Length > 0) {
  734.                         namespaceName = LookupNamespace(prefix);
  735.                     }
  736.                     if (namespaceName == null) {
  737.                         namespaceName = string.Empty;
  738.                     }
  739.                 }
  740.                
  741.                 if (prefix.Length == 0) {
  742.                     if (localName[0] == 'x' && localName == "xmlns") {
  743.                         if (namespaceName.Length > 0 && namespaceName != XmlReservedNs.NsXmlNs) {
  744.                             throw new ArgumentException(Res.GetString(Res.Xml_XmlnsPrefix));
  745.                         }
  746.                         curDeclPrefix = String.Empty;
  747.                         SetSpecialAttribute(SpecialAttribute.DefaultXmlns);
  748.                         goto SkipPushAndWrite;
  749.                     }
  750.                     else if (namespaceName.Length > 0) {
  751.                         prefix = LookupPrefix(namespaceName);
  752.                         if (prefix == null || prefix.Length == 0) {
  753.                             prefix = GeneratePrefix();
  754.                         }
  755.                     }
  756.                 }
  757.                 else {
  758.                     if (prefix[0] == 'x') {
  759.                         if (prefix == "xmlns") {
  760.                             if (namespaceName.Length > 0 && namespaceName != XmlReservedNs.NsXmlNs) {
  761.                                 throw new ArgumentException(Res.GetString(Res.Xml_XmlnsPrefix));
  762.                             }
  763.                             curDeclPrefix = localName;
  764.                             SetSpecialAttribute(SpecialAttribute.PrefixedXmlns);
  765.                             goto SkipPushAndWrite;
  766.                         }
  767.                         else if (prefix == "xml") {
  768.                             if (namespaceName.Length > 0 && namespaceName != XmlReservedNs.NsXml) {
  769.                                 throw new ArgumentException(Res.GetString(Res.Xml_XmlPrefix));
  770.                             }
  771.                             switch (localName) {
  772.                                 case "space":
  773.                                     SetSpecialAttribute(SpecialAttribute.XmlSpace);
  774.                                     goto SkipPushAndWrite;
  775.                                     break;
  776.                                 case "lang":
  777.                                     SetSpecialAttribute(SpecialAttribute.XmlLang);
  778.                                     goto SkipPushAndWrite;
  779.                                     break;
  780.                             }
  781.                         }
  782.                     }
  783.                    
  784.                     CheckNCName(prefix);
  785.                    
  786.                     if (namespaceName.Length == 0) {
  787.                         // attributes cannot have default namespace
  788.                         prefix = string.Empty;
  789.                     }
  790.                     else {
  791.                         string definedNs = LookupLocalNamespace(prefix);
  792.                         if (definedNs != null && definedNs != namespaceName) {
  793.                             prefix = GeneratePrefix();
  794.                         }
  795.                     }
  796.                 }
  797.                
  798.                 if (prefix.Length != 0) {
  799.                     PushNamespace(prefix, namespaceName, false);
  800.                 }
  801.                
  802.                 // write attribute name
  803.                 writer.WriteStartAttribute(prefix, localName, namespaceName);
  804.                 SkipPushAndWrite:
  805.                
  806.                 // add attribute to the list and check for duplicates
  807.                 AddAttribute(prefix, localName, namespaceName);
  808.             }
  809.             catch {
  810.                 currentState = State.Error;
  811.                 throw;
  812.             }
  813.         }
  814.        
  815.         public override void WriteEndAttribute()
  816.         {
  817.             try {
  818.                 AdvanceState(Token.EndAttribute);
  819.                
  820.                 if (specAttr != SpecialAttribute.No) {
  821.                     string value;
  822.                     if (attrValue != null) {
  823.                         value = attrValue.ToString();
  824.                         attrValue.Length = 0;
  825.                     }
  826.                     else {
  827.                         value = string.Empty;
  828.                     }
  829.                    
  830.                     switch (specAttr) {
  831.                         case SpecialAttribute.DefaultXmlns:
  832.                             PushNamespace(string.Empty, value, true);
  833.                             if (rawWriter != null) {
  834.                                 rawWriter.WriteNamespaceDeclaration(string.Empty, value);
  835.                             }
  836.                             else {
  837.                                 writer.WriteAttributeString(string.Empty, "xmlns", XmlReservedNs.NsXmlNs, value);
  838.                             }
  839.                             curDeclPrefix = null;
  840.                             break;
  841.                         case SpecialAttribute.PrefixedXmlns:
  842.                             if (value.Length == 0) {
  843.                                 throw new ArgumentException(Res.GetString(Res.Xml_PrefixForEmptyNs));
  844.                             }
  845.                             if (value == XmlReservedNs.NsXmlNs || (value == XmlReservedNs.NsXml && curDeclPrefix != "xml")) {
  846.                                 throw new ArgumentException(Res.GetString(Res.Xml_CanNotBindToReservedNamespace));
  847.                             }
  848.                             PushNamespace(curDeclPrefix, value, true);
  849.                             if (rawWriter != null) {
  850.                                 rawWriter.WriteNamespaceDeclaration(curDeclPrefix, value);
  851.                             }
  852.                             else {
  853.                                 writer.WriteAttributeString("xmlns", curDeclPrefix, XmlReservedNs.NsXmlNs, value);
  854.                             }
  855.                             curDeclPrefix = null;
  856.                             break;
  857.                         case SpecialAttribute.XmlSpace:
  858.                             value = XmlConvert.TrimString(value);
  859.                             if (value == "default") {
  860.                                 elemScopeStack[elemTop].xmlSpace = XmlSpace.Default;
  861.                             }
  862.                             else if (value == "preserve") {
  863.                                 elemScopeStack[elemTop].xmlSpace = XmlSpace.Preserve;
  864.                             }
  865.                             else {
  866.                                 throw new ArgumentException(Res.GetString(Res.Xml_InvalidXmlSpace, value));
  867.                             }
  868.                             writer.WriteAttributeString("xml", "space", XmlReservedNs.NsXml, value);
  869.                             break;
  870.                         case SpecialAttribute.XmlLang:
  871.                             elemScopeStack[elemTop].xmlLang = value;
  872.                             writer.WriteAttributeString("xml", "lang", XmlReservedNs.NsXml, value);
  873.                             break;
  874.                     }
  875.                     specAttr = SpecialAttribute.No;
  876.                 }
  877.                 else {
  878.                     writer.WriteEndAttribute();
  879.                 }
  880.             }
  881.             catch {
  882.                 currentState = State.Error;
  883.                 throw;
  884.             }
  885.         }
  886.        
  887.         public override void WriteCData(string text)
  888.         {
  889.             try {
  890.                 if (text == null) {
  891.                     text = string.Empty;
  892.                 }
  893.                 AdvanceState(Token.CData);
  894.                 writer.WriteCData(text);
  895.             }
  896.             catch {
  897.                 currentState = State.Error;
  898.                 throw;
  899.             }
  900.         }
  901.        
  902.         public override void WriteComment(string text)
  903.         {
  904.             try {
  905.                 if (text == null) {
  906.                     text = string.Empty;
  907.                 }
  908.                 AdvanceState(Token.Comment);
  909.                 writer.WriteComment(text);
  910.             }
  911.             catch {
  912.                 currentState = State.Error;
  913.                 throw;
  914.             }
  915.         }
  916.        
  917.         public override void WriteProcessingInstruction(string name, string text)
  918.         {
  919.             try {
  920.                 // check name
  921.                 if (name == null || name.Length == 0) {
  922.                     throw new ArgumentException(Res.GetString(Res.Xml_EmptyName));
  923.                 }
  924.                 CheckNCName(name);
  925.                
  926.                 // check text
  927.                 if (text == null) {
  928.                     text = string.Empty;
  929.                 }
  930.                
  931.                 // xml declaration is a special case (not a processing instruction, but we allow WriteProcessingInstruction as a convenience)
  932.                 if (name.Length == 3 && string.Compare(name, "xml", StringComparison.OrdinalIgnoreCase) == 0) {
  933.                     if (currentState != State.Start) {
  934.                         throw new ArgumentException(Res.GetString(conformanceLevel == ConformanceLevel.Document ? Res.Xml_DupXmlDecl : Res.Xml_CannotWriteXmlDecl));
  935.                     }
  936.                    
  937.                     xmlDeclFollows = true;
  938.                     AdvanceState(Token.PI);
  939.                    
  940.                     if (rawWriter != null) {
  941.                         // Translate PI into an xml declaration
  942.                         rawWriter.WriteXmlDeclaration(text);
  943.                     }
  944.                     else {
  945.                         writer.WriteProcessingInstruction(name, text);
  946.                     }
  947.                 }
  948.                 else {
  949.                     AdvanceState(Token.PI);
  950.                     writer.WriteProcessingInstruction(name, text);
  951.                 }
  952.             }
  953.             catch {
  954.                 currentState = State.Error;
  955.                 throw;
  956.             }
  957.         }
  958.        
  959.         public override void WriteEntityRef(string name)
  960.         {
  961.             try {
  962.                 // check name
  963.                 if (name == null || name.Length == 0) {
  964.                     throw new ArgumentException(Res.GetString(Res.Xml_EmptyName));
  965.                 }
  966.                 CheckNCName(name);
  967.                
  968.                 AdvanceState(Token.Text);
  969.                 if (SaveAttrValue) {
  970.                     attrValue.Append('&');
  971.                     attrValue.Append(name);
  972.                     attrValue.Append(';');
  973.                 }
  974.                 else {
  975.                     writer.WriteEntityRef(name);
  976.                 }
  977.             }
  978.             catch {
  979.                 currentState = State.Error;
  980.                 throw;
  981.             }
  982.         }
  983.        
  984.         public override void WriteCharEntity(char ch)
  985.         {
  986.             try {
  987.                 if (Char.IsSurrogate(ch)) {
  988.                     throw new ArgumentException(Res.GetString(Res.Xml_InvalidSurrogateMissingLowChar));
  989.                 }
  990.                
  991.                 AdvanceState(Token.Text);
  992.                 if (SaveAttrValue) {
  993.                     attrValue.Append(ch);
  994.                 }
  995.                 else {
  996.                     writer.WriteCharEntity(ch);
  997.                 }
  998.             }
  999.             catch {
  1000.                 currentState = State.Error;
  1001.                 throw;
  1002.             }
  1003.         }
  1004.        
  1005.         public override void WriteSurrogateCharEntity(char lowChar, char highChar)
  1006.         {
  1007.             try {
  1008.                 if (!Char.IsSurrogatePair(highChar, lowChar)) {
  1009.                     throw XmlConvert.CreateInvalidSurrogatePairException(lowChar, highChar);
  1010.                 }
  1011.                
  1012.                 AdvanceState(Token.Text);
  1013.                 if (SaveAttrValue) {
  1014.                     attrValue.Append(highChar);
  1015.                     attrValue.Append(lowChar);
  1016.                 }
  1017.                 else {
  1018.                     writer.WriteSurrogateCharEntity(lowChar, highChar);
  1019.                 }
  1020.             }
  1021.             catch {
  1022.                 currentState = State.Error;
  1023.                 throw;
  1024.             }
  1025.         }
  1026.        
  1027.         public override void WriteWhitespace(string ws)
  1028.         {
  1029.             try {
  1030.                 if (ws == null) {
  1031.                     ws = string.Empty;
  1032.                 }
  1033.                 if (!XmlCharType.Instance.IsOnlyWhitespace(ws)) {
  1034.                     throw new ArgumentException(Res.GetString(Res.Xml_NonWhitespace));
  1035.                 }
  1036.                
  1037.                 AdvanceState(Token.Whitespace);
  1038.                 if (SaveAttrValue) {
  1039.                     attrValue.Append(ws);
  1040.                 }
  1041.                 else {
  1042.                     writer.WriteWhitespace(ws);
  1043.                 }
  1044.             }
  1045.             catch {
  1046.                 currentState = State.Error;
  1047.                 throw;
  1048.             }
  1049.         }
  1050.        
  1051.         public override void WriteString(string text)
  1052.         {
  1053.             try {
  1054.                 if (text == null) {
  1055.                     return;
  1056.                 }
  1057.                
  1058.                 AdvanceState(Token.Text);
  1059.                 if (SaveAttrValue) {
  1060.                     attrValue.Append(text);
  1061.                 }
  1062.                 else {
  1063.                     writer.WriteString(text);
  1064.                 }
  1065.             }
  1066.             catch {
  1067.                 currentState = State.Error;
  1068.                 throw;
  1069.             }
  1070.         }
  1071.        
  1072.         public override void WriteChars(char[] buffer, int index, int count)
  1073.         {
  1074.             try {
  1075.                 if (buffer == null) {
  1076.                     throw new ArgumentNullException("buffer");
  1077.                 }
  1078.                 if (index < 0) {
  1079.                     throw new ArgumentOutOfRangeException("index");
  1080.                 }
  1081.                 if (count < 0) {
  1082.                     throw new ArgumentOutOfRangeException("count");
  1083.                 }
  1084.                 if (count > buffer.Length - index) {
  1085.                     throw new ArgumentOutOfRangeException("count");
  1086.                 }
  1087.                
  1088.                 AdvanceState(Token.Text);
  1089.                 if (SaveAttrValue) {
  1090.                     attrValue.Append(buffer, index, count);
  1091.                 }
  1092.                 else {
  1093.                     writer.WriteChars(buffer, index, count);
  1094.                 }
  1095.             }
  1096.             catch {
  1097.                 currentState = State.Error;
  1098.                 throw;
  1099.             }
  1100.         }
  1101.        
  1102.         public override void WriteRaw(char[] buffer, int index, int count)
  1103.         {
  1104.             try {
  1105.                 if (buffer == null) {
  1106.                     throw new ArgumentNullException("buffer");
  1107.                 }
  1108.                 if (index < 0) {
  1109.                     throw new ArgumentOutOfRangeException("index");
  1110.                 }
  1111.                 if (count < 0) {
  1112.                     throw new ArgumentOutOfRangeException("count");
  1113.                 }
  1114.                 if (count > buffer.Length - index) {
  1115.                     throw new ArgumentOutOfRangeException("count");
  1116.                 }
  1117.                
  1118.                 AdvanceState(Token.RawData);
  1119.                 if (SaveAttrValue) {
  1120.                     attrValue.Append(buffer, index, count);
  1121.                 }
  1122.                 else {
  1123.                     writer.WriteRaw(buffer, index, count);
  1124.                 }
  1125.             }
  1126.             catch {
  1127.                 currentState = State.Error;
  1128.                 throw;
  1129.             }
  1130.         }
  1131.        
  1132.         public override void WriteRaw(string data)
  1133.         {
  1134.             try {
  1135.                 if (data == null) {
  1136.                     return;
  1137.                 }
  1138.                
  1139.                 AdvanceState(Token.RawData);
  1140.                 if (SaveAttrValue) {
  1141.                     attrValue.Append(data);
  1142.                 }
  1143.                 else {
  1144.                     writer.WriteRaw(data);
  1145.                 }
  1146.             }
  1147.             catch {
  1148.                 currentState = State.Error;
  1149.                 throw;
  1150.             }
  1151.         }
  1152.        
  1153.         public override void WriteBase64(byte[] buffer, int index, int count)
  1154.         {
  1155.             try {
  1156.                 if (buffer == null) {
  1157.                     throw new ArgumentNullException("buffer");
  1158.                 }
  1159.                 if (index < 0) {
  1160.                     throw new ArgumentOutOfRangeException("index");
  1161.                 }
  1162.                 if (count < 0) {
  1163.                     throw new ArgumentOutOfRangeException("count");
  1164.                 }
  1165.                 if (count > buffer.Length - index) {
  1166.                     throw new ArgumentOutOfRangeException("count");
  1167.                 }
  1168.                
  1169.                 AdvanceState(Token.Base64);
  1170.                 writer.WriteBase64(buffer, index, count);
  1171.             }
  1172.             catch {
  1173.                 currentState = State.Error;
  1174.                 throw;
  1175.             }
  1176.         }
  1177.        
  1178.         public override void Close()
  1179.         {
  1180.             if (currentState != State.Closed) {
  1181.                 try {
  1182.                     while (currentState != State.Error && elemTop > 0) {
  1183.                         WriteEndElement();
  1184.                     }
  1185.                     writer.Flush();
  1186.                 }
  1187.                 catch {
  1188.                     // never fail
  1189.                 }
  1190.                 finally {
  1191.                     if (rawWriter != null) {
  1192.                         rawWriter.Close(WriteState);
  1193.                     }
  1194.                     else {
  1195.                         writer.Close();
  1196.                     }
  1197.                     currentState = State.Closed;
  1198.                 }
  1199.             }
  1200.         }
  1201.        
  1202.         public override void Flush()
  1203.         {
  1204.             try {
  1205.                 writer.Flush();
  1206.             }
  1207.             catch {
  1208.                 currentState = State.Error;
  1209.                 throw;
  1210.             }
  1211.         }
  1212.        
  1213.         public override string LookupPrefix(string ns)
  1214.         {
  1215.             try {
  1216.                 if (ns == null) {
  1217.                     throw new ArgumentNullException("ns");
  1218.                 }
  1219.                 for (int i = nsTop; i >= 0; i--) {
  1220.                     if (nsStack[i].namespaceUri == ns) {
  1221.                         string prefix = nsStack[i].prefix;
  1222.                         for (i++; i <= nsTop; i++) {
  1223.                             if (nsStack[i].prefix == prefix) {
  1224.                                 return null;
  1225.                             }
  1226.                         }
  1227.                         return prefix;
  1228.                     }
  1229.                 }
  1230.                 return (predefinedNamespaces != null) ? predefinedNamespaces.LookupPrefix(ns) : null;
  1231.             }
  1232.             catch {
  1233.                 currentState = State.Error;
  1234.                 throw;
  1235.             }
  1236.         }
  1237.        
  1238.         public override XmlSpace XmlSpace {
  1239.             get {
  1240.                 int i;
  1241.                 for (i = elemTop; i >= 0 && elemScopeStack[i].xmlSpace == (System.Xml.XmlSpace)(int)-1; i--)
  1242.                     ;
  1243.                 Debug.Assert(i >= 0);
  1244.                 return elemScopeStack[i].xmlSpace;
  1245.             }
  1246.         }
  1247.        
  1248.         public override string XmlLang {
  1249.             get {
  1250.                 int i;
  1251.                 for (i = elemTop; i > 0 && elemScopeStack[i].xmlLang == null; i--)
  1252.                     ;
  1253.                 Debug.Assert(i >= 0);
  1254.                 return elemScopeStack[i].xmlLang;
  1255.             }
  1256.         }
  1257.        
  1258.         public override void WriteQualifiedName(string localName, string ns)
  1259.         {
  1260.             try {
  1261.                 if (localName == null || localName.Length == 0) {
  1262.                     throw new ArgumentException(Res.GetString(Res.Xml_EmptyLocalName));
  1263.                 }
  1264.                 CheckNCName(localName);
  1265.                
  1266.                 AdvanceState(Token.Text);
  1267.                 string prefix = String.Empty;
  1268.                 if (ns != null && ns.Length != 0) {
  1269.                     prefix = LookupPrefix(ns);
  1270.                     if (prefix == null) {
  1271.                         if (currentState != State.Attribute) {
  1272.                             throw new ArgumentException(Res.GetString(Res.Xml_UndefNamespace, ns));
  1273.                         }
  1274.                         prefix = GeneratePrefix();
  1275.                         PushNamespace(prefix, ns, false);
  1276.                     }
  1277.                 }
  1278.                 // if this is a special attribute, then just convert this to text
  1279.                 // otherwise delegate to raw-writer
  1280.                 if (SaveAttrValue || rawWriter == null) {
  1281.                     if (prefix.Length != 0) {
  1282.                         WriteString(prefix);
  1283.                         WriteString(":");
  1284.                     }
  1285.                     WriteString(localName);
  1286.                 }
  1287.                 else {
  1288.                     rawWriter.WriteQualifiedName(prefix, localName, ns);
  1289.                 }
  1290.             }
  1291.             catch {
  1292.                 currentState = State.Error;
  1293.                 throw;
  1294.             }
  1295.         }
  1296.        
  1297.         public override void WriteValue(bool value)
  1298.         {
  1299.             try {
  1300.                 AdvanceState(Token.AtomicValue);
  1301.                 writer.WriteValue(value);
  1302.             }
  1303.             catch {
  1304.                 currentState = State.Error;
  1305.                 throw;
  1306.             }
  1307.         }
  1308.        
  1309.         public override void WriteValue(DateTime value)
  1310.         {
  1311.             try {
  1312.                 AdvanceState(Token.AtomicValue);
  1313.                 writer.WriteValue(value);
  1314.             }
  1315.             catch {
  1316.                 currentState = State.Error;
  1317.                 throw;
  1318.             }
  1319.         }
  1320.        
  1321.         public override void WriteValue(double value)
  1322.         {
  1323.             try {
  1324.                 AdvanceState(Token.AtomicValue);
  1325.                 writer.WriteValue(value);
  1326.             }
  1327.             catch {
  1328.                 currentState = State.Error;
  1329.                 throw;
  1330.             }
  1331.         }
  1332.        
  1333.         public override void WriteValue(float value)
  1334.         {
  1335.             try {
  1336.                 AdvanceState(Token.AtomicValue);
  1337.                 writer.WriteValue(value);
  1338.             }
  1339.             catch {
  1340.                 currentState = State.Error;
  1341.                 throw;
  1342.             }
  1343.         }
  1344.        
  1345.         public override void WriteValue(decimal value)
  1346.         {
  1347.             try {
  1348.                 AdvanceState(Token.AtomicValue);
  1349.                 writer.WriteValue(value);
  1350.             }
  1351.             catch {
  1352.                 currentState = State.Error;
  1353.                 throw;
  1354.             }
  1355.         }
  1356.        
  1357.         public override void WriteValue(int value)
  1358.         {
  1359.             try {
  1360.                 AdvanceState(Token.AtomicValue);
  1361.                 writer.WriteValue(value);
  1362.             }
  1363.             catch {
  1364.                 currentState = State.Error;
  1365.                 throw;
  1366.             }
  1367.         }
  1368.        
  1369.         public override void WriteValue(long value)
  1370.         {
  1371.             try {
  1372.                 AdvanceState(Token.AtomicValue);
  1373.                 writer.WriteValue(value);
  1374.             }
  1375.             catch {
  1376.                 currentState = State.Error;
  1377.                 throw;
  1378.             }
  1379.         }
  1380.        
  1381.         public override void WriteValue(string value)
  1382.         {
  1383.             try {
  1384.                 if (SaveAttrValue) {
  1385.                     AdvanceState(Token.Text);
  1386.                     attrValue.Append(value);
  1387.                 }
  1388.                 else {
  1389.                     AdvanceState(Token.AtomicValue);
  1390.                     writer.WriteValue(value);
  1391.                 }
  1392.             }
  1393.             catch {
  1394.                 currentState = State.Error;
  1395.                 throw;
  1396.             }
  1397.         }
  1398.        
  1399.         public override void WriteValue(object value)
  1400.         {
  1401.             try {
  1402.                 if (SaveAttrValue && value is string) {
  1403.                     AdvanceState(Token.Text);
  1404.                     attrValue.Append(value);
  1405.                 }
  1406.                 else {
  1407.                     AdvanceState(Token.AtomicValue);
  1408.                     writer.WriteValue(value);
  1409.                 }
  1410.             }
  1411.             catch {
  1412.                 currentState = State.Error;
  1413.                 throw;
  1414.             }
  1415.         }
  1416.        
  1417.         public override void WriteBinHex(byte[] buffer, int index, int count)
  1418.         {
  1419.             if (IsClosedOrErrorState) {
  1420.                 throw new InvalidOperationException(Res.GetString(Res.Xml_ClosedOrError));
  1421.             }
  1422.             try {
  1423.                 AdvanceState(Token.Text);
  1424.                 base.WriteBinHex(buffer, index, count);
  1425.             }
  1426.             catch {
  1427.                 currentState = State.Error;
  1428.                 throw;
  1429.             }
  1430.         }
  1431.        
  1432.         //
  1433.         // Internal methods
  1434.         //
  1435.         internal XmlWriter InnerWriter {
  1436.             get { return this.writer; }
  1437.         }
  1438.        
  1439.         //
  1440.         // Private methods
  1441.         //
  1442.         private bool SaveAttrValue {
  1443.             get { return specAttr != SpecialAttribute.No; }
  1444.         }
  1445.        
  1446.         private void SetSpecialAttribute(SpecialAttribute special)
  1447.         {
  1448.             specAttr = special;
  1449.             if (State.Attribute == currentState)
  1450.                 currentState = State.SpecialAttr;
  1451.             else if (State.RootLevelAttr == currentState)
  1452.                 currentState = State.RootLevelSpecAttr;
  1453.             else
  1454.                 Debug.Assert(false, "State.Attribute == currentState || State.RootLevelAttr == currentState");
  1455.         }
  1456.        
  1457.         private void WriteStartDocumentImpl(XmlStandalone standalone)
  1458.         {
  1459.             try {
  1460.                 AdvanceState(Token.StartDocument);
  1461.                
  1462.                 if (conformanceLevel == ConformanceLevel.Auto) {
  1463.                     conformanceLevel = ConformanceLevel.Document;
  1464.                     stateTable = StateTableDocument;
  1465.                 }
  1466.                 else if (conformanceLevel == ConformanceLevel.Fragment) {
  1467.                     throw new InvalidOperationException(Res.GetString(Res.Xml_CannotStartDocumentOnFragment));
  1468.                 }
  1469.                
  1470.                 if (rawWriter != null) {
  1471.                     if (!xmlDeclFollows) {
  1472.                         rawWriter.WriteXmlDeclaration(standalone);
  1473.                     }
  1474.                 }
  1475.                 else {
  1476.                     writer.WriteStartDocument();
  1477.                 }
  1478.             }
  1479.             catch {
  1480.                 currentState = State.Error;
  1481.                 throw;
  1482.             }
  1483.         }
  1484.        
  1485.         private void StartFragment()
  1486.         {
  1487.             conformanceLevel = ConformanceLevel.Fragment;
  1488.             Debug.Assert(stateTable == StateTableAuto);
  1489.         }
  1490.        
  1491.         private void PushNamespace(string prefix, string ns, bool explicitlyDefined)
  1492.         {
  1493.             NamespaceKind kind;
  1494.             int existingNsIndex = LookupNamespaceIndex(prefix);
  1495.            
  1496.             if (existingNsIndex != -1) {
  1497.                 if (existingNsIndex > elemScopeStack[elemTop].prevNSTop) {
  1498.                     // in current scope
  1499.                     if (nsStack[existingNsIndex].namespaceUri != ns) {
  1500.                         throw new XmlException(Res.Xml_RedefinePrefix, new string[] {prefix, nsStack[existingNsIndex].namespaceUri, ns});
  1501.                     }
  1502.                     if (explicitlyDefined) {
  1503.                         if (nsStack[existingNsIndex].kind == NamespaceKind.Written) {
  1504.                             throw DupAttrException((prefix.Length == 0) ? string.Empty : "xmlns", (prefix.Length == 0) ? "xmlns" : prefix);
  1505.                         }
  1506.                         nsStack[existingNsIndex].kind = NamespaceKind.Written;
  1507.                     }
  1508.                     return;
  1509.                 }
  1510.                 else {
  1511.                     if (!explicitlyDefined) {
  1512.                         if (nsStack[existingNsIndex].kind == NamespaceKind.Special) {
  1513.                             if (prefix == "xml") {
  1514.                                 if (ns != nsStack[existingNsIndex].namespaceUri) {
  1515.                                     throw new ArgumentException(Res.GetString(Res.Xml_XmlPrefix));
  1516.                                 }
  1517.                                 else {
  1518.                                     kind = NamespaceKind.Implied;
  1519.                                 }
  1520.                             }
  1521.                             else {
  1522.                                 Debug.Assert(prefix == "xmlns");
  1523.                                 throw new ArgumentException(Res.GetString(Res.Xml_XmlnsPrefix));
  1524.                             }
  1525.                         }
  1526.                         else {
  1527.                             kind = (nsStack[existingNsIndex].namespaceUri == ns) ? NamespaceKind.Implied : NamespaceKind.NeedToWrite;
  1528.                         }
  1529.                         goto AddNamespace;
  1530.                     }
  1531.                 }
  1532.             }
  1533.            
  1534.             if ((ns == XmlReservedNs.NsXml && prefix != "xml") || (ns == XmlReservedNs.NsXmlNs && prefix != "xmlns")) {
  1535.                 throw new ArgumentException(Res.GetString(Res.Xml_NamespaceDeclXmlXmlns, prefix));
  1536.             }
  1537.            
  1538.             if (!explicitlyDefined) {
  1539.                 // not explicitly defined, not found before
  1540.                 // not found - we need to search the underlying writer context and declare it if not found
  1541.                 if (predefinedNamespaces == null) {
  1542.                     kind = NamespaceKind.NeedToWrite;
  1543.                     // should write out
  1544.                 }
  1545.                 else {
  1546.                     string definedNs = predefinedNamespaces.LookupNamespace(prefix);
  1547.                     kind = (definedNs == ns) ? NamespaceKind.Implied : NamespaceKind.NeedToWrite;
  1548.                 }
  1549.             }
  1550.             else {
  1551.                 // explicitly defined
  1552.                 if (prefix.Length > 0 && prefix[0] == 'x') {
  1553.                     if (prefix == "xml") {
  1554.                         if (ns != XmlReservedNs.NsXml) {
  1555.                             throw new ArgumentException(Res.GetString(Res.Xml_XmlPrefix));
  1556.                         }
  1557.                     }
  1558.                     else if (prefix == "xmlns") {
  1559.                         throw new ArgumentException(Res.GetString(Res.Xml_XmlnsPrefix));
  1560.                     }
  1561.                 }
  1562.                 kind = NamespaceKind.Written;
  1563.             }
  1564.             AddNamespace:
  1565.            
  1566.             int top = ++nsTop;
  1567.             if (top == nsStack.Length) {
  1568.                 Namespace[] newStack = new Namespace[top * 2];
  1569.                 Array.Copy(nsStack, newStack, top);
  1570.                 nsStack = newStack;
  1571.             }
  1572.             nsStack[top].Set(prefix, ns, kind);
  1573.            
  1574.             if (useNsHashtable) {
  1575.                 // add last
  1576.                 AddToNamespaceHashtable(nsTop);
  1577.             }
  1578.             else if (nsTop == MaxNamespacesWalkCount) {
  1579.                 // add all
  1580.                 nsHashtable = new Dictionary<string, int>(hasher);
  1581.                 for (int i = 0; i <= nsTop; i++) {
  1582.                     AddToNamespaceHashtable(i);
  1583.                 }
  1584.                 useNsHashtable = true;
  1585.             }
  1586.         }
  1587.        
  1588.         private void AddToNamespaceHashtable(int namespaceIndex)
  1589.         {
  1590.             string prefix = nsStack[namespaceIndex].prefix;
  1591.             int existingNsIndex;
  1592.             if (nsHashtable.TryGetValue(prefix, out existingNsIndex)) {
  1593.                 nsStack[namespaceIndex].prevNsIndex = existingNsIndex;
  1594.             }
  1595.             nsHashtable[prefix] = namespaceIndex;
  1596.         }
  1597.        
  1598.         private int LookupNamespaceIndex(string prefix)
  1599.         {
  1600.             int index;
  1601.             if (useNsHashtable) {
  1602.                 if (nsHashtable.TryGetValue(prefix, out index)) {
  1603.                     return index;
  1604.                 }
  1605.             }
  1606.             else {
  1607.                 for (int i = nsTop; i >= 0; i--) {
  1608.                     if (nsStack[i].prefix == prefix) {
  1609.                         return i;
  1610.                     }
  1611.                 }
  1612.             }
  1613.             return -1;
  1614.         }
  1615.        
  1616.         private void PopNamespaces(int indexFrom, int indexTo)
  1617.         {
  1618.             Debug.Assert(useNsHashtable);
  1619.             Debug.Assert(indexFrom <= indexTo);
  1620.             for (int i = indexTo; i >= indexFrom; i--) {
  1621.                 Debug.Assert(nsHashtable.ContainsKey(nsStack[i].prefix));
  1622.                 if (nsStack[i].prevNsIndex == -1) {
  1623.                     nsHashtable.Remove(nsStack[i].prefix);
  1624.                 }
  1625.                 else {
  1626.                     nsHashtable[nsStack[i].prefix] = nsStack[i].prevNsIndex;
  1627.                 }
  1628.             }
  1629.         }
  1630.        
  1631.         private static XmlException DupAttrException(string prefix, string localName)
  1632.         {
  1633.             StringBuilder sb = new StringBuilder();
  1634.             if (prefix.Length > 0) {
  1635.                 sb.Append(prefix);
  1636.                 sb.Append(':');
  1637.             }
  1638.             sb.Append(localName);
  1639.             return new XmlException(Res.Xml_DupAttributeName, sb.ToString());
  1640.         }
  1641.        
  1642.         // Advance the state machine
  1643.         private void AdvanceState(Token token)
  1644.         {
  1645.             if ((int)currentState >= (int)State.Closed) {
  1646.                 if (currentState == State.Closed || currentState == State.Error) {
  1647.                     throw new InvalidOperationException(Res.GetString(Res.Xml_ClosedOrError));
  1648.                 }
  1649.                 else {
  1650.                     throw new InvalidOperationException(Res.GetString(Res.Xml_WrongToken, tokenName[(int)token], GetStateName(currentState)));
  1651.                 }
  1652.             }
  1653.             Advance:
  1654.            
  1655.             State newState = stateTable[((int)token << 4) + (int)currentState];
  1656.             // [ (int)token * 16 + (int)currentState ];
  1657.            
  1658.             if ((int)newState >= (int)State.Error) {
  1659.                 switch (newState) {
  1660.                     case State.Error:
  1661.                         ThrowInvalidStateTransition(token, currentState);
  1662.                         break;
  1663.                     case State.StartContent:
  1664.                        
  1665.                         StartElementContent();
  1666.                         newState = State.Content;
  1667.                         break;
  1668.                     case State.StartContentEle:
  1669.                        
  1670.                         StartElementContent();
  1671.                         newState = State.Element;
  1672.                         break;
  1673.                     case State.StartContentB64:
  1674.                        
  1675.                         StartElementContent();
  1676.                         newState = State.B64Content;
  1677.                         break;
  1678.                     case State.StartDoc:
  1679.                        
  1680.                         WriteStartDocument();
  1681.                         newState = State.Document;
  1682.                         break;
  1683.                     case State.StartDocEle:
  1684.                        
  1685.                         WriteStartDocument();
  1686.                         newState = State.Element;
  1687.                         break;
  1688.                     case State.EndAttrSEle:
  1689.                        
  1690.                         WriteEndAttribute();
  1691.                         StartElementContent();
  1692.                         newState = State.Element;
  1693.                         break;
  1694.                     case State.EndAttrEEle:
  1695.                        
  1696.                         WriteEndAttribute();
  1697.                         StartElementContent();
  1698.                         newState = State.Content;
  1699.                         break;
  1700.                     case State.EndAttrSCont:
  1701.                        
  1702.                         WriteEndAttribute();
  1703.                         StartElementContent();
  1704.                         newState = State.Content;
  1705.                         break;
  1706.                     case State.EndAttrSAttr:
  1707.                        
  1708.                         WriteEndAttribute();
  1709.                         newState = State.Attribute;
  1710.                         break;
  1711.                     case State.PostB64Cont:
  1712.                        
  1713.                         if (rawWriter != null) {
  1714.                             rawWriter.WriteEndBase64();
  1715.                         }
  1716.                         currentState = State.Content;
  1717.                         goto Advance;
  1718.                         break;
  1719.                     case State.PostB64Attr:
  1720.                        
  1721.                         if (rawWriter != null) {
  1722.                             rawWriter.WriteEndBase64();
  1723.                         }
  1724.                         currentState = State.Attribute;
  1725.                         goto Advance;
  1726.                         break;
  1727.                     case State.PostB64RootAttr:
  1728.                        
  1729.                         if (rawWriter != null) {
  1730.                             rawWriter.WriteEndBase64();
  1731.                         }
  1732.                         currentState = State.RootLevelAttr;
  1733.                         goto Advance;
  1734.                         break;
  1735.                     case State.StartFragEle:
  1736.                        
  1737.                         StartFragment();
  1738.                         newState = State.Element;
  1739.                         break;
  1740.                     case State.StartFragCont:
  1741.                        
  1742.                         StartFragment();
  1743.                         newState = State.Content;
  1744.                         break;
  1745.                     case State.StartFragB64:
  1746.                        
  1747.                         StartFragment();
  1748.                         newState = State.B64Content;
  1749.                         break;
  1750.                     case State.StartRootLevelAttr:
  1751.                        
  1752.                         WriteEndAttribute();
  1753.                         newState = State.RootLevelAttr;
  1754.                         break;
  1755.                     default:
  1756.                        
  1757.                         Debug.Assert(false, "We should not get to this point.");
  1758.                         break;
  1759.                 }
  1760.             }
  1761.            
  1762.             currentState = newState;
  1763.         }
  1764.        
  1765.         private void StartElementContent()
  1766.         {
  1767.             // write namespace declarations
  1768.             int start = elemScopeStack[elemTop].prevNSTop;
  1769.             for (int i = nsTop; i > start; i--) {
  1770.                 if (nsStack[i].kind == NamespaceKind.NeedToWrite) {
  1771.                     nsStack[i].WriteDecl(writer, rawWriter);
  1772.                 }
  1773.             }
  1774.            
  1775.             if (rawWriter != null) {
  1776.                 rawWriter.StartElementContent();
  1777.             }
  1778.         }
  1779.        
  1780.         private static string GetStateName(State state)
  1781.         {
  1782.             if (state >= State.Error) {
  1783.                 Debug.Assert(false, "We should never get to this point. State = " + state);
  1784.                 return "Error";
  1785.             }
  1786.             else {
  1787.                 return stateName[(int)state];
  1788.             }
  1789.         }
  1790.        
  1791.         internal string LookupNamespace(string prefix)
  1792.         {
  1793.             for (int i = nsTop; i >= 0; i--) {
  1794.                 if (nsStack[i].prefix == prefix) {
  1795.                     return nsStack[i].namespaceUri;
  1796.                 }
  1797.             }
  1798.             return (predefinedNamespaces != null) ? predefinedNamespaces.LookupNamespace(prefix) : null;
  1799.         }
  1800.        
  1801.         private string LookupLocalNamespace(string prefix)
  1802.         {
  1803.             for (int i = nsTop; i > elemScopeStack[elemTop].prevNSTop; i--) {
  1804.                 if (nsStack[i].prefix == prefix) {
  1805.                     return nsStack[i].namespaceUri;
  1806.                 }
  1807.             }
  1808.             return null;
  1809.         }
  1810.        
  1811.         private string GeneratePrefix()
  1812.         {
  1813.             string genPrefix = "p" + (nsTop - 2).ToString("d", CultureInfo.InvariantCulture);
  1814.             if (LookupNamespace(genPrefix) == null) {
  1815.                 return genPrefix;
  1816.             }
  1817.             int i = 0;
  1818.            
  1819.             string s;
  1820.             do {
  1821.                 s = string.Concat(genPrefix, i.ToString(CultureInfo.InvariantCulture));
  1822.                 i++;
  1823.             }
  1824.             while (LookupNamespace(s) != null);
  1825.             return s;
  1826.         }
  1827.        
  1828.         unsafe private void CheckNCName(string ncname)
  1829.         {
  1830.             Debug.Assert(ncname != null && ncname.Length > 0);
  1831.             if ((xmlCharType.charProperties[ncname[0]] & XmlCharType.fNCStartName) != 0) {
  1832.                 // if ( xmlCharType.IsStartNCNameChar( ncname[0] ) ) {
  1833.                 int i = 1;
  1834.                 int endPos = ncname.Length;
  1835.                 while (i < endPos) {
  1836.                     if ((xmlCharType.charProperties[ncname[i]] & XmlCharType.fNCName) == 0) {
  1837.                         // if ( !xmlCharType.IsNCNameChar( ncname[i] ) ) {
  1838.                         throw InvalidCharsException(ncname, ncname[i]);
  1839.                     }
  1840.                     i++;
  1841.                 }
  1842.             }
  1843.             else {
  1844.                 throw InvalidCharsException(ncname, ncname[0]);
  1845.             }
  1846.         }
  1847.        
  1848.         private static Exception InvalidCharsException(string name, char badChar)
  1849.         {
  1850.             string[] args = new string[3];
  1851.             args[0] = name;
  1852.             args[1] = badChar.ToString(CultureInfo.InvariantCulture);
  1853.             args[2] = ((int)badChar).ToString("X2", CultureInfo.InvariantCulture);
  1854.             return new ArgumentException(Res.GetString(Res.Xml_InvalidNameCharsDetail, args));
  1855.         }
  1856.        
  1857.         // This method translates speficic state transition errors in more friendly error messages
  1858.         private void ThrowInvalidStateTransition(Token token, State currentState)
  1859.         {
  1860.             string wrongTokenMessage = Res.GetString(Res.Xml_WrongToken, tokenName[(int)token], GetStateName(currentState));
  1861.             switch (currentState) {
  1862.                 case State.AfterRootEle:
  1863.                 case State.Start:
  1864.                     if (conformanceLevel == ConformanceLevel.Document) {
  1865.                         throw new InvalidOperationException(wrongTokenMessage + ' ' + Res.GetString(Res.Xml_ConformanceLevelFragment));
  1866.                     }
  1867.                     break;
  1868.             }
  1869.             throw new InvalidOperationException(wrongTokenMessage);
  1870.         }
  1871.        
  1872.         private bool IsClosedOrErrorState {
  1873.             get { return (int)currentState >= (int)State.Closed; }
  1874.         }
  1875.        
  1876.         private void AddAttribute(string prefix, string localName, string namespaceName)
  1877.         {
  1878.             int top = attrCount++;
  1879.             if (top == attrStack.Length) {
  1880.                 AttrName[] newStack = new AttrName[top * 2];
  1881.                 Array.Copy(attrStack, newStack, top);
  1882.                 attrStack = newStack;
  1883.             }
  1884.             attrStack[top].Set(prefix, localName, namespaceName);
  1885.            
  1886.             if (attrCount < MaxAttrDuplWalkCount) {
  1887.                 // check for duplicates
  1888.                 for (int i = 0; i < top; i++) {
  1889.                     if (attrStack[i].IsDuplicate(prefix, localName, namespaceName)) {
  1890.                         throw DupAttrException(prefix, localName);
  1891.                     }
  1892.                 }
  1893.             }
  1894.             else {
  1895.                 // reached the threshold -> add all attributes to hash table
  1896.                 if (attrCount == MaxAttrDuplWalkCount) {
  1897.                     if (attrHashTable == null) {
  1898.                         attrHashTable = new Dictionary<string, int>(hasher);
  1899.                     }
  1900.                     Debug.Assert(attrHashTable.Count == 0);
  1901.                     for (int i = 0; i < top; i++) {
  1902.                         AddToAttrHashTable(i);
  1903.                     }
  1904.                 }
  1905.                
  1906.                 // add last attribute to hash table and check for duplicates
  1907.                 AddToAttrHashTable(top);
  1908.                 int prev = attrStack[top].prev;
  1909.                 while (prev > 0) {
  1910.                     // indexes are stored incremented by 1, 0 means no entry
  1911.                     prev--;
  1912.                     if (attrStack[prev].IsDuplicate(prefix, localName, namespaceName)) {
  1913.                         throw DupAttrException(prefix, localName);
  1914.                     }
  1915.                     prev = attrStack[prev].prev;
  1916.                 }
  1917.             }
  1918.         }
  1919.        
  1920.         private void AddToAttrHashTable(int attributeIndex)
  1921.         {
  1922.             string localName = attrStack[attributeIndex].localName;
  1923.             int count = attrHashTable.Count;
  1924.             attrHashTable[localName] = 0;
  1925.             // overwrite on collision
  1926.             if (count != attrHashTable.Count) {
  1927.                 return;
  1928.             }
  1929.             // chain to previous attribute in stack with the same localName
  1930.             int prev = attributeIndex - 1;
  1931.             while (prev >= 0) {
  1932.                 if (attrStack[prev].localName == localName) {
  1933.                     break;
  1934.                 }
  1935.                 prev--;
  1936.             }
  1937.             Debug.Assert(prev >= 0 && attrStack[prev].localName == localName);
  1938.             attrStack[attributeIndex].prev = prev + 1;
  1939.             // indexes are stored incremented by 1
  1940.         }
  1941.        
  1942.         //
  1943.         // Internal methods
  1944.         //
  1945.         internal XmlRawWriter RawWriter {
  1946.             get { return rawWriter; }
  1947.         }
  1948.     }
  1949. }

Developer Fusion