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

  1. //------------------------------------------------------------------------------
  2. // <copyright file="XmlTextReaderImpl.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.Security;
  19. using System.Threading;
  20. using System.Xml.Schema;
  21. using System.Collections;
  22. using System.Diagnostics;
  23. using System.Globalization;
  24. using System.Collections.Generic;
  25. namespace System.Xml
  26. {
  27.    
  28.     internal partial class XmlTextReaderImpl : XmlReader, IXmlLineInfo, IXmlNamespaceResolver
  29.     {
  30.         //
  31.         // Private helper types
  32.         //
  33.         // ParsingFunction = what should the reader do when the next Read() is called
  34.         enum ParsingFunction
  35.         {
  36.             ElementContent = 0,
  37.             NoData,
  38.             OpenUrl,
  39.             SwitchToInteractive,
  40.             SwitchToInteractiveXmlDecl,
  41.             DocumentContent,
  42.             MoveToElementContent,
  43.             PopElementContext,
  44.             PopEmptyElementContext,
  45.             ResetAttributesRootLevel,
  46.             Error,
  47.             Eof,
  48.             ReaderClosed,
  49.             EntityReference,
  50.             InIncrementalRead,
  51.             FragmentAttribute,
  52.             ReportEndEntity,
  53.             AfterResolveEntityInContent,
  54.             AfterResolveEmptyEntityInContent,
  55.             XmlDeclarationFragment,
  56.             GoToEof,
  57.             PartialTextValue,
  58.            
  59.             // these two states must be last; see InAttributeValueIterator property
  60.             InReadAttributeValue,
  61.             InReadValueChunk,
  62.             InReadContentAsBinary,
  63.             InReadElementContentAsBinary
  64.         }
  65.        
  66.         enum ParsingMode
  67.         {
  68.             Full,
  69.             SkipNode,
  70.             SkipContent
  71.         }
  72.        
  73.         enum EntityType
  74.         {
  75.             CharacterDec,
  76.             CharacterHex,
  77.             CharacterNamed,
  78.             Expanded,
  79.             ExpandedInAttribute,
  80.             Skipped,
  81.             Unexpanded,
  82.             FakeExpanded
  83.         }
  84.        
  85.         enum EntityExpandType
  86.         {
  87.             OnlyGeneral,
  88.             OnlyCharacter,
  89.             All
  90.         }
  91.        
  92.         enum IncrementalReadState
  93.         {
  94.             // Following values are used in ReadText, ReadBase64 and ReadBinHex (V1 streaming methods)
  95.             Text,
  96.             StartTag,
  97.             PI,
  98.             CDATA,
  99.             Comment,
  100.             Attributes,
  101.             AttributeValue,
  102.             ReadData,
  103.             EndElement,
  104.             End,
  105.            
  106.             // Following values are used in ReadTextChunk, ReadContentAsBase64 and ReadBinHexChunk (V2 streaming methods)
  107.             ReadValueChunk_OnCachedValue,
  108.             ReadValueChunk_OnPartialValue,
  109.            
  110.             ReadContentAsBinary_OnCachedValue,
  111.             ReadContentAsBinary_OnPartialValue,
  112.             ReadContentAsBinary_End
  113.         }
  114.        
  115.         //
  116.         // Fields
  117.         //
  118.         // XmlCharType instance
  119.         XmlCharType xmlCharType = XmlCharType.Instance;
  120.        
  121.         // current parsing state (aka. scanner data)
  122.         ParsingState ps;
  123.        
  124.         // parsing function = what to do in the next Read() (3-items-long stack, usually used just 2 level)
  125.         ParsingFunction parsingFunction;
  126.         ParsingFunction nextParsingFunction;
  127.         ParsingFunction nextNextParsingFunction;
  128.        
  129.         // stack of nodes
  130.         NodeData[] nodes;
  131.        
  132.         // current node
  133.         NodeData curNode;
  134.        
  135.         // current index
  136.         int index = 0;
  137.        
  138.         // attributes info
  139.         int curAttrIndex = -1;
  140.         int attrCount;
  141.         int attrHashtable;
  142.         int attrDuplWalkCount;
  143.         bool attrNeedNamespaceLookup;
  144.         bool fullAttrCleanup;
  145.         NodeData[] attrDuplSortingArray;
  146.        
  147.         // name table
  148.         XmlNameTable nameTable;
  149.         bool nameTableFromSettings;
  150.        
  151.         // resolver
  152.         XmlResolver xmlResolver;
  153.        
  154.         // this is only for constructors that takes url
  155.         string url = string.Empty;
  156.         CompressedStack compressedStack;
  157.        
  158.         // settings
  159.         bool normalize;
  160.         bool supportNamespaces = true;
  161.         WhitespaceHandling whitespaceHandling;
  162.         bool prohibitDtd;
  163.         EntityHandling entityHandling;
  164.         bool ignorePIs;
  165.         bool ignoreComments;
  166.         bool checkCharacters;
  167.         int lineNumberOffset;
  168.         int linePositionOffset;
  169.         bool closeInput;
  170.        
  171.         // this flag enables XmlTextReader backwards compatibility;
  172.         // when false, the reader has been created via XmlReader.Create
  173.         bool v1Compat;
  174.        
  175.         // namespace handling
  176.         XmlNamespaceManager namespaceManager;
  177.         string lastPrefix = string.Empty;
  178.        
  179.         // xml context (xml:space, xml:lang, default namespace)
  180.         XmlContext xmlContext;
  181.        
  182.         // stack of parsing states (=stack of entities)
  183.         private ParsingState[] parsingStatesStack;
  184.         private int parsingStatesStackTop = -1;
  185.        
  186.         // current node base uri and encoding
  187.         string reportedBaseUri;
  188.         Encoding reportedEncoding;
  189.        
  190.         // DTD
  191.         DtdParserProxy dtdParserProxy;
  192.        
  193.         // fragment parsing
  194.         XmlNodeType fragmentType = XmlNodeType.Document;
  195.         bool fragment;
  196.         XmlParserContext fragmentParserContext;
  197.        
  198.         // incremental read
  199.         IncrementalReadDecoder incReadDecoder;
  200.         IncrementalReadState incReadState;
  201.         int incReadDepth;
  202.         int incReadLeftStartPos;
  203.         int incReadLeftEndPos;
  204.         LineInfo incReadLineInfo;
  205.         IncrementalReadCharsDecoder readCharsDecoder;
  206.         BinHexDecoder binHexDecoder;
  207.         Base64Decoder base64Decoder;
  208.        
  209.         // ReadAttributeValue helpers
  210.         int attributeValueBaseEntityId;
  211.         bool emptyEntityInAttributeResolved;
  212.        
  213.         // XmlValidatingReader helpers
  214.         ValidationEventHandler validationEventHandler;
  215.         bool validatingReaderCompatFlag;
  216.         bool addDefaultAttributesAndNormalize;
  217.         XmlQualifiedName qName;
  218.        
  219.         // misc
  220.         BufferBuilder stringBuilder;
  221.         bool rootElementParsed;
  222.         bool standalone;
  223.         int nextEntityId = 1;
  224.         ParsingMode parsingMode;
  225.         ReadState readState = ReadState.Initial;
  226.         SchemaEntity lastEntity;
  227.         bool afterResetState;
  228.         int documentStartBytePos;
  229.         int readValueOffset;
  230.        
  231.         // DOM helpers
  232.         bool disableUndeclaredEntityCheck;
  233.        
  234.         // Outer XmlReader exposed to the user - either XmlTextReader or XmlTextReaderImpl (when created via XmlReader.Create).
  235.         // Virtual methods called from within XmlTextReaderImpl must be called on the outer reader so in case the user overrides
  236.         // some of the XmlTextReader methods we will call the overriden version.
  237.         XmlReader outerReader;
  238.        
  239.         //
  240.         // Atomized string constants
  241.         //
  242.         private string Xml;
  243.         private string XmlNs;
  244.        
  245.         //
  246.         // Constants
  247.         //
  248.         private const int MaxBytesToMove = 128;
  249.         private const int ApproxXmlDeclLength = 80;
  250.         private const int NodesInitialSize = 8;
  251.         private const int InitialAttributesCount = 4;
  252.         private const int InitialParsingStateStackSize = 2;
  253.         private const int InitialParsingStatesDepth = 2;
  254.         private const int DtdChidrenInitialSize = 2;
  255.         private const int MaxByteSequenceLen = 6;
  256.         // max bytes per character
  257.         private const int MaxAttrDuplWalkCount = 250;
  258.         private const int MinWhitespaceLookahedCount = 4096;
  259.        
  260.         private const string XmlDeclarationBegining = "<?xml";
  261.        
  262.         internal const int SurHighStart = 55296;
  263.         internal const int SurHighEnd = 56319;
  264.         internal const int SurLowStart = 56320;
  265.         internal const int SurLowEnd = 57343;
  266.        
  267.         //
  268.         // Constructors
  269.         //
  270.         internal XmlTextReaderImpl()
  271.         {
  272.             curNode = new NodeData();
  273.             parsingFunction = ParsingFunction.NoData;
  274.         }
  275.        
  276.         // Initializes a new instance of the XmlTextReaderImpl class with the specified XmlNameTable.
  277.         // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader
  278.         internal XmlTextReaderImpl(XmlNameTable nt)
  279.         {
  280.             Debug.Assert(nt != null);
  281.            
  282.             v1Compat = true;
  283.             outerReader = this;
  284.            
  285.             nameTable = nt;
  286.             nt.Add(string.Empty);
  287.            
  288.             xmlResolver = new XmlUrlResolver();
  289.            
  290.             Xml = nt.Add("xml");
  291.             XmlNs = nt.Add("xmlns");
  292.            
  293.             Debug.Assert(index == 0);
  294.             nodes = new NodeData[NodesInitialSize];
  295.             nodes[0] = new NodeData();
  296.             curNode = nodes[0];
  297.            
  298.             stringBuilder = new BufferBuilder();
  299.             xmlContext = new XmlContext();
  300.            
  301.             parsingFunction = ParsingFunction.SwitchToInteractiveXmlDecl;
  302.             nextParsingFunction = ParsingFunction.DocumentContent;
  303.            
  304.             entityHandling = EntityHandling.ExpandCharEntities;
  305.             whitespaceHandling = WhitespaceHandling.All;
  306.             closeInput = true;
  307.            
  308.             ps.lineNo = 1;
  309.             ps.lineStartPos = -1;
  310.         }
  311.        
  312.         // This constructor is used when creating XmlTextReaderImpl reader via "XmlReader.Create(..)"
  313.         private XmlTextReaderImpl(XmlResolver resolver, XmlReaderSettings settings, XmlParserContext context)
  314.         {
  315.             v1Compat = false;
  316.             outerReader = this;
  317.            
  318.             xmlContext = new XmlContext();
  319.            
  320.             // create or get nametable and namespace manager from XmlParserContext
  321.             XmlNameTable nt = settings.NameTable;
  322.             if (context == null) {
  323.                 if (nt == null) {
  324.                     nt = new NameTable();
  325.                     Debug.Assert(nameTableFromSettings == false);
  326.                 }
  327.                 else {
  328.                     nameTableFromSettings = true;
  329.                 }
  330.                 nameTable = nt;
  331.                 namespaceManager = new XmlNamespaceManager(nt);
  332.             }
  333.             else {
  334.                 SetupFromParserContext(context, settings);
  335.                 nt = nameTable;
  336.             }
  337.            
  338.             nt.Add(string.Empty);
  339.             Xml = nt.Add("xml");
  340.             XmlNs = nt.Add("xmlns");
  341.            
  342.             xmlResolver = resolver;
  343.            
  344.             Debug.Assert(index == 0);
  345.            
  346.             nodes = new NodeData[NodesInitialSize];
  347.             nodes[0] = new NodeData();
  348.             curNode = nodes[0];
  349.            
  350.             stringBuilder = new BufferBuilder();
  351.            
  352.             entityHandling = EntityHandling.ExpandEntities;
  353.             whitespaceHandling = (settings.IgnoreWhitespace) ? WhitespaceHandling.Significant : WhitespaceHandling.All;
  354.             normalize = true;
  355.             ignorePIs = settings.IgnoreProcessingInstructions;
  356.             ignoreComments = settings.IgnoreComments;
  357.             checkCharacters = settings.CheckCharacters;
  358.             lineNumberOffset = settings.LineNumberOffset;
  359.             linePositionOffset = settings.LinePositionOffset;
  360.             ps.lineNo = lineNumberOffset + 1;
  361.             ps.lineStartPos = -linePositionOffset - 1;
  362.             curNode.SetLineInfo(ps.LineNo - 1, ps.LinePos - 1);
  363.             prohibitDtd = settings.ProhibitDtd;
  364.            
  365.             fragmentParserContext = context;
  366.            
  367.             parsingFunction = ParsingFunction.SwitchToInteractiveXmlDecl;
  368.             nextParsingFunction = ParsingFunction.DocumentContent;
  369.            
  370.             switch (settings.ConformanceLevel) {
  371.                 case ConformanceLevel.Auto:
  372.                     fragmentType = XmlNodeType.None;
  373.                     fragment = true;
  374.                     break;
  375.                 case ConformanceLevel.Fragment:
  376.                     fragmentType = XmlNodeType.Element;
  377.                     fragment = true;
  378.                     break;
  379.                 case ConformanceLevel.Document:
  380.                     fragmentType = XmlNodeType.Document;
  381.                     break;
  382.                 default:
  383.                     Debug.Assert(false);
  384.                     goto case ConformanceLevel.Document;
  385.                     break;
  386.             }
  387.         }
  388.        
  389.         // Initializes a new instance of the XmlTextReaderImpl class with the specified stream, baseUri and nametable
  390.         // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader
  391.         internal XmlTextReaderImpl(Stream input) : this(string.Empty, input, new NameTable())
  392.         {
  393.         }
  394.         internal XmlTextReaderImpl(Stream input, XmlNameTable nt) : this(string.Empty, input, nt)
  395.         {
  396.         }
  397.         internal XmlTextReaderImpl(string url, Stream input) : this(url, input, new NameTable())
  398.         {
  399.         }
  400.         internal XmlTextReaderImpl(string url, Stream input, XmlNameTable nt) : this(nt)
  401.         {
  402.             namespaceManager = new XmlNamespaceManager(nt);
  403.             if (url == null || url.Length == 0) {
  404.                 InitStreamInput(input, null);
  405.             }
  406.             else {
  407.                 InitStreamInput(url, input, null);
  408.             }
  409.             reportedBaseUri = ps.baseUriStr;
  410.             reportedEncoding = ps.encoding;
  411.         }
  412.        
  413.         // Initializes a new instance of the XmlTextReaderImpl class with the specified TextReader, baseUri and XmlNameTable.
  414.         // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader
  415.         internal XmlTextReaderImpl(TextReader input) : this(string.Empty, input, new NameTable())
  416.         {
  417.         }
  418.         internal XmlTextReaderImpl(TextReader input, XmlNameTable nt) : this(string.Empty, input, nt)
  419.         {
  420.         }
  421.         internal XmlTextReaderImpl(string url, TextReader input) : this(url, input, new NameTable())
  422.         {
  423.         }
  424.         internal XmlTextReaderImpl(string url, TextReader input, XmlNameTable nt) : this(nt)
  425.         {
  426.             namespaceManager = new XmlNamespaceManager(nt);
  427.             reportedBaseUri = (url != null) ? url : string.Empty;
  428.             InitTextReaderInput(reportedBaseUri, input);
  429.             reportedEncoding = ps.encoding;
  430.         }
  431.        
  432.         // Initializes a new instance of XmlTextReaderImpl class for parsing fragments with the specified stream, fragment type and parser context
  433.         // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader
  434.         internal XmlTextReaderImpl(Stream xmlFragment, XmlNodeType fragType, XmlParserContext context) : this((context != null && context.NameTable != null) ? context.NameTable : new NameTable())
  435.         {
  436.            
  437.             Encoding enc = (context != null) ? context.Encoding : null;
  438.             if (context == null || context.BaseURI == null || context.BaseURI.Length == 0) {
  439.                 InitStreamInput(xmlFragment, enc);
  440.             }
  441.             else {
  442.                 InitStreamInput(xmlResolver.ResolveUri(null, context.BaseURI), xmlFragment, enc);
  443.             }
  444.             InitFragmentReader(fragType, context, false);
  445.            
  446.             reportedBaseUri = ps.baseUriStr;
  447.             reportedEncoding = ps.encoding;
  448.         }
  449.        
  450.         // Initializes a new instance of XmlTextRreaderImpl class for parsing fragments with the specified string, fragment type and parser context
  451.         // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader
  452.         internal XmlTextReaderImpl(string xmlFragment, XmlNodeType fragType, XmlParserContext context) : this(null == context || null == context.NameTable ? new NameTable() : context.NameTable)
  453.         {
  454.            
  455.             if (context == null) {
  456.                 InitStringInput(string.Empty, Encoding.Unicode, xmlFragment);
  457.             }
  458.             else {
  459.                 reportedBaseUri = context.BaseURI;
  460.                 InitStringInput(context.BaseURI, Encoding.Unicode, xmlFragment);
  461.             }
  462.             InitFragmentReader(fragType, context, false);
  463.             reportedEncoding = ps.encoding;
  464.         }
  465.        
  466.         // Following constructor assumes that the fragment node type == XmlDecl
  467.         // We handle this node type separately because there is not real way to determine what the
  468.         // "innerXml" of an XmlDecl is. This internal function is required by DOM. When(if) we handle/allow
  469.         // all nodetypes in InnerXml then we should support them as part of fragment constructor as well.
  470.         // Until then, this internal function will have to do.
  471.         internal XmlTextReaderImpl(string xmlFragment, XmlParserContext context) : this(null == context || null == context.NameTable ? new NameTable() : context.NameTable)
  472.         {
  473.             InitStringInput((context == null) ? string.Empty : context.BaseURI, Encoding.Unicode, string.Concat("<?xml ", xmlFragment, "?>"));
  474.             InitFragmentReader(XmlNodeType.XmlDeclaration, context, true);
  475.         }
  476.        
  477.         // Initializes a new instance of the XmlTextReaderImpl class with the specified url and XmlNameTable.
  478.         // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader
  479.         public XmlTextReaderImpl(string url) : this(url, new NameTable())
  480.         {
  481.         }
  482.         public XmlTextReaderImpl(string url, XmlNameTable nt) : this(nt)
  483.         {
  484.             if (url == null) {
  485.                 throw new ArgumentNullException("url");
  486.             }
  487.             if (url.Length == 0) {
  488.                 throw new ArgumentException(Res.GetString(Res.Xml_EmptyUrl), "url");
  489.             }
  490.             namespaceManager = new XmlNamespaceManager(nt);
  491.            
  492.             compressedStack = CompressedStack.Capture();
  493.            
  494.             this.url = url;
  495.            
  496.             ps.baseUri = xmlResolver.ResolveUri(null, url);
  497.             ps.baseUriStr = ps.baseUri.ToString();
  498.             reportedBaseUri = ps.baseUriStr;
  499.            
  500.             parsingFunction = ParsingFunction.OpenUrl;
  501.         }
  502.        
  503.         // Initializes a new instance of the XmlTextReaderImpl class with the specified arguments.
  504.         // This constructor is used when creating XmlTextReaderImpl via XmlReader.Create
  505.         internal XmlTextReaderImpl(Stream stream, byte[] bytes, int byteCount, XmlReaderSettings settings, Uri baseUri, string baseUriStr, XmlParserContext context, bool closeInput) : this(settings.GetXmlResolver(), settings, context)
  506.         {
  507.            
  508.             Encoding enc = null;
  509.            
  510.             // get BaseUri and Encoding from XmlParserContext
  511.             if (context != null) {
  512.                 if (context.BaseURI != null && context.BaseURI.Length > 0 && !UriEqual(baseUri, baseUriStr, context.BaseURI, settings.GetXmlResolver())) {
  513.                     if (baseUriStr.Length > 0) {
  514.                         Throw(Res.Xml_DoubleBaseUri);
  515.                     }
  516.                     Debug.Assert(baseUri == null);
  517.                     baseUriStr = context.BaseURI;
  518.                 }
  519.                 enc = context.Encoding;
  520.             }
  521.            
  522.             // init ParsingState
  523.             InitStreamInput(baseUri, baseUriStr, stream, bytes, byteCount, enc);
  524.            
  525.             this.closeInput = closeInput;
  526.            
  527.             reportedBaseUri = ps.baseUriStr;
  528.             reportedEncoding = ps.encoding;
  529.            
  530.             // parse DTD
  531.             if (context != null && context.HasDtdInfo) {
  532.                 if (prohibitDtd) {
  533.                     ThrowWithoutLineInfo(Res.Xml_DtdIsProhibitedEx, string.Empty);
  534.                 }
  535.                 ParseDtdFromParserContext();
  536.             }
  537.         }
  538.        
  539.         // Initializes a new instance of the XmlTextReaderImpl class with the specified arguments.
  540.         // This constructor is used when creating XmlTextReaderImpl via XmlReader.Create
  541.         internal XmlTextReaderImpl(TextReader input, XmlReaderSettings settings, string baseUriStr, XmlParserContext context) : this(settings.GetXmlResolver(), settings, context)
  542.         {
  543.            
  544.             // get BaseUri from XmlParserContext
  545.             if (context != null) {
  546.                 Debug.Assert(baseUriStr == string.Empty, "BaseURI can come either from XmlParserContext or from the constructor argument, not from both");
  547.                 if (context.BaseURI != null) {
  548.                     baseUriStr = context.BaseURI;
  549.                 }
  550.             }
  551.            
  552.             // init ParsingState
  553.             InitTextReaderInput(baseUriStr, input);
  554.            
  555.             this.closeInput = settings.CloseInput;
  556.            
  557.             reportedBaseUri = ps.baseUriStr;
  558.             reportedEncoding = ps.encoding;
  559.            
  560.             // parse DTD
  561.             if (context != null && context.HasDtdInfo) {
  562.                 if (prohibitDtd) {
  563.                     ThrowWithoutLineInfo(Res.Xml_DtdIsProhibitedEx, string.Empty);
  564.                 }
  565.                 ParseDtdFromParserContext();
  566.             }
  567.         }
  568.        
  569.         // Initializes a new instance of the XmlTextReaderImpl class for fragment parsing.
  570.         // This constructor is used by XmlBinaryReader for nested text XML
  571.         internal XmlTextReaderImpl(string xmlFragment, XmlParserContext context, XmlReaderSettings settings) : this(null, settings, context)
  572.         {
  573.             InitStringInput(string.Empty, Encoding.Unicode, xmlFragment);
  574.             reportedBaseUri = ps.baseUriStr;
  575.             reportedEncoding = ps.encoding;
  576.         }
  577.        
  578.         //
  579.         // XmlReader members
  580.         //
  581.         // Returns the current settings of the reader
  582.         public override XmlReaderSettings Settings {
  583.             get {
  584.                 if (v1Compat) {
  585.                     return null;
  586.                 }
  587.                
  588.                 XmlReaderSettings settings = new XmlReaderSettings();
  589.                
  590.                 if (nameTableFromSettings) {
  591.                     settings.NameTable = nameTable;
  592.                 }
  593.                
  594.                 switch (fragmentType) {
  595.                     case XmlNodeType.None:
  596.                         settings.ConformanceLevel = ConformanceLevel.Auto;
  597.                         break;
  598.                     case XmlNodeType.Element:
  599.                         settings.ConformanceLevel = ConformanceLevel.Fragment;
  600.                         break;
  601.                     case XmlNodeType.Document:
  602.                         settings.ConformanceLevel = ConformanceLevel.Document;
  603.                         break;
  604.                     default:
  605.                         Debug.Assert(false);
  606.                         goto case XmlNodeType.None;
  607.                         break;
  608.                 }
  609.                 settings.CheckCharacters = checkCharacters;
  610.                 settings.LineNumberOffset = lineNumberOffset;
  611.                 settings.LinePositionOffset = linePositionOffset;
  612.                 settings.IgnoreWhitespace = (whitespaceHandling == WhitespaceHandling.Significant);
  613.                 settings.IgnoreProcessingInstructions = ignorePIs;
  614.                 settings.IgnoreComments = ignoreComments;
  615.                 settings.ProhibitDtd = prohibitDtd;
  616.                
  617.                 settings.ReadOnly = true;
  618.                 return settings;
  619.             }
  620.         }
  621.        
  622.         // Returns the type of the current node.
  623.         public override XmlNodeType NodeType {
  624.             get { return curNode.type; }
  625.         }
  626.        
  627.         // Returns the name of the current node, including prefix.
  628.         public override string Name {
  629.             get { return curNode.GetNameWPrefix(nameTable); }
  630.         }
  631.        
  632.         // Returns local name of the current node (without prefix)
  633.         public override string LocalName {
  634.             get { return curNode.localName; }
  635.         }
  636.        
  637.         // Returns namespace name of the current node.
  638.         public override string NamespaceURI {
  639.             get { return curNode.ns; }
  640.         }
  641.        
  642.         // Returns prefix associated with the current node.
  643.         public override string Prefix {
  644.             get { return curNode.prefix; }
  645.         }
  646.        
  647.         // Returns true if the current node can have Value property != string.Empty.
  648.         public override bool HasValue {
  649.             get { return XmlReader.HasValueInternal(curNode.type); }
  650.         }
  651.        
  652.         // Returns the text value of the current node.
  653.         public override string Value {
  654.             get {
  655.                 if (parsingFunction >= ParsingFunction.PartialTextValue) {
  656.                     if (parsingFunction == ParsingFunction.PartialTextValue) {
  657.                         FinishPartialValue();
  658.                         parsingFunction = nextParsingFunction;
  659.                     }
  660.                     else {
  661.                         FinishOtherValueIterator();
  662.                     }
  663.                 }
  664.                 return curNode.StringValue;
  665.             }
  666.         }
  667.        
  668.         // Returns the depth of the current node in the XML element stack
  669.         public override int Depth {
  670.             get { return curNode.depth; }
  671.         }
  672.        
  673.         // Returns the base URI of the current node.
  674.         public override string BaseURI {
  675.             get { return reportedBaseUri; }
  676.         }
  677.        
  678.         // Returns true if the current node is an empty element (for example, <MyElement/>).
  679.         public override bool IsEmptyElement {
  680.             get { return curNode.IsEmptyElement; }
  681.         }
  682.        
  683.         // Returns true of the current node is a default attribute declared in DTD.
  684.         public override bool IsDefault {
  685.             get { return curNode.IsDefaultAttribute; }
  686.         }
  687.        
  688.         // Returns the quote character used in the current attribute declaration
  689.         public override char QuoteChar {
  690.             get { return curNode.type == XmlNodeType.Attribute ? curNode.quoteChar : '"'; }
  691.         }
  692.        
  693.         // Returns the current xml:space scope.
  694.         public override XmlSpace XmlSpace {
  695.             get { return xmlContext.xmlSpace; }
  696.         }
  697.        
  698.         // Returns the current xml:lang scope.</para>
  699.         public override string XmlLang {
  700.             get { return xmlContext.xmlLang; }
  701.         }
  702.        
  703.         // Returns the current read state of the reader
  704.         public override ReadState ReadState {
  705.             get { return readState; }
  706.         }
  707.        
  708.         // Returns true if the reader reached end of the input data
  709.         public override bool EOF {
  710.             get { return parsingFunction == ParsingFunction.Eof; }
  711.         }
  712.        
  713.         // Returns the XmlNameTable associated with this XmlReader
  714.         public override XmlNameTable NameTable {
  715.             get { return nameTable; }
  716.         }
  717.        
  718.         // Returns true if the XmlReader knows how to resolve general entities
  719.         public override bool CanResolveEntity {
  720.             get { return true; }
  721.         }
  722.        
  723.         // Returns the number of attributes on the current node.
  724.         public override int AttributeCount {
  725.             get { return attrCount; }
  726.         }
  727.        
  728.         // Returns value of an attribute with the specified Name
  729.         public override string GetAttribute(string name)
  730.         {
  731.             int i;
  732.             if (name.IndexOf(':') == -1) {
  733.                 i = GetIndexOfAttributeWithoutPrefix(name);
  734.             }
  735.             else {
  736.                 i = GetIndexOfAttributeWithPrefix(name);
  737.             }
  738.             return (i >= 0) ? nodes[i].StringValue : null;
  739.         }
  740.        
  741.         // Returns value of an attribute with the specified LocalName and NamespaceURI
  742.         public override string GetAttribute(string localName, string namespaceURI)
  743.         {
  744.             namespaceURI = (namespaceURI == null) ? string.Empty : nameTable.Get(namespaceURI);
  745.             localName = nameTable.Get(localName);
  746.             for (int i = index + 1; i < index + attrCount + 1; i++) {
  747.                 if (Ref.Equal(nodes[i].localName, localName) && Ref.Equal(nodes[i].ns, namespaceURI)) {
  748.                     return nodes[i].StringValue;
  749.                 }
  750.             }
  751.             return null;
  752.         }
  753.        
  754.         // Returns value of an attribute at the specified index (position)
  755.         public override string GetAttribute(int i)
  756.         {
  757.             if (i < 0 || i >= attrCount) {
  758.                 throw new ArgumentOutOfRangeException("i");
  759.             }
  760.             return nodes[index + i + 1].StringValue;
  761.         }
  762.        
  763.         // Moves to an attribute with the specified Name
  764.         public override bool MoveToAttribute(string name)
  765.         {
  766.             int i;
  767.             if (name.IndexOf(':') == -1) {
  768.                 i = GetIndexOfAttributeWithoutPrefix(name);
  769.             }
  770.             else {
  771.                 i = GetIndexOfAttributeWithPrefix(name);
  772.             }
  773.            
  774.             if (i >= 0) {
  775.                 if (InAttributeValueIterator) {
  776.                     FinishAttributeValueIterator();
  777.                 }
  778.                 curAttrIndex = i - index - 1;
  779.                 curNode = nodes[i];
  780.                 return true;
  781.             }
  782.             else {
  783.                 return false;
  784.             }
  785.         }
  786.        
  787.         // Moves to an attribute with the specified LocalName and NamespceURI
  788.         public override bool MoveToAttribute(string localName, string namespaceURI)
  789.         {
  790.             namespaceURI = (namespaceURI == null) ? string.Empty : nameTable.Get(namespaceURI);
  791.             localName = nameTable.Get(localName);
  792.             for (int i = index + 1; i < index + attrCount + 1; i++) {
  793.                 if (Ref.Equal(nodes[i].localName, localName) && Ref.Equal(nodes[i].ns, namespaceURI)) {
  794.                     curAttrIndex = i - index - 1;
  795.                     curNode = nodes[i];
  796.                    
  797.                     if (InAttributeValueIterator) {
  798.                         FinishAttributeValueIterator();
  799.                     }
  800.                     return true;
  801.                 }
  802.             }
  803.             return false;
  804.         }
  805.        
  806.         // Moves to an attribute at the specified index (position)
  807.         public override void MoveToAttribute(int i)
  808.         {
  809.             if (i < 0 || i >= attrCount) {
  810.                 throw new ArgumentOutOfRangeException("i");
  811.             }
  812.            
  813.             if (InAttributeValueIterator) {
  814.                 FinishAttributeValueIterator();
  815.             }
  816.             curAttrIndex = i;
  817.             curNode = nodes[index + 1 + curAttrIndex];
  818.         }
  819.        
  820.         // Moves to the first attribute of the current node
  821.         public override bool MoveToFirstAttribute()
  822.         {
  823.             if (attrCount == 0) {
  824.                 return false;
  825.             }
  826.            
  827.             if (InAttributeValueIterator) {
  828.                 FinishAttributeValueIterator();
  829.             }
  830.            
  831.             curAttrIndex = 0;
  832.             curNode = nodes[index + 1];
  833.            
  834.             return true;
  835.         }
  836.        
  837.         // Moves to the next attribute of the current node
  838.         public override bool MoveToNextAttribute()
  839.         {
  840.             if (curAttrIndex + 1 < attrCount) {
  841.                 if (InAttributeValueIterator) {
  842.                     FinishAttributeValueIterator();
  843.                 }
  844.                 curNode = nodes[index + 1 + ++curAttrIndex];
  845.                 return true;
  846.             }
  847.             return false;
  848.         }
  849.        
  850.         // If on attribute, moves to the element that contains the attribute node
  851.         public override bool MoveToElement()
  852.         {
  853.             if (InAttributeValueIterator) {
  854.                 FinishAttributeValueIterator();
  855.             }
  856.             else if (curNode.type != XmlNodeType.Attribute) {
  857.                 return false;
  858.             }
  859.             curAttrIndex = -1;
  860.             curNode = nodes[index];
  861.            
  862.             return true;
  863.         }
  864.        
  865.         // Reads next node from the input data
  866.         public override bool Read()
  867.         {
  868.             for (;;) {
  869.                 switch (parsingFunction) {
  870.                     case ParsingFunction.ElementContent:
  871.                         return ParseElementContent();
  872.                     case ParsingFunction.DocumentContent:
  873.                         return ParseDocumentContent();
  874.                     case ParsingFunction.OpenUrl:
  875.                         OpenUrl();
  876.                         Debug.Assert(nextParsingFunction == ParsingFunction.DocumentContent);
  877.                         goto case ParsingFunction.SwitchToInteractiveXmlDecl;
  878.                         break;
  879.                     case ParsingFunction.SwitchToInteractive:
  880.                         Debug.Assert(!ps.appendMode);
  881.                         readState = ReadState.Interactive;
  882.                         parsingFunction = nextParsingFunction;
  883.                         continue;
  884.                     case ParsingFunction.SwitchToInteractiveXmlDecl:
  885.                         readState = ReadState.Interactive;
  886.                         parsingFunction = nextParsingFunction;
  887.                         if (ParseXmlDeclaration(false)) {
  888.                             reportedEncoding = ps.encoding;
  889.                             return true;
  890.                         }
  891.                         reportedEncoding = ps.encoding;
  892.                         continue;
  893.                     case ParsingFunction.ResetAttributesRootLevel:
  894.                         ResetAttributes();
  895.                         curNode = nodes[index];
  896.                         parsingFunction = (index == 0) ? ParsingFunction.DocumentContent : ParsingFunction.ElementContent;
  897.                         continue;
  898.                     case ParsingFunction.MoveToElementContent:
  899.                         ResetAttributes();
  900.                         index++;
  901.                         curNode = AddNode(index, index);
  902.                         parsingFunction = ParsingFunction.ElementContent;
  903.                         continue;
  904.                     case ParsingFunction.PopElementContext:
  905.                         PopElementContext();
  906.                         parsingFunction = nextParsingFunction;
  907.                         Debug.Assert(parsingFunction == ParsingFunction.ElementContent || parsingFunction == ParsingFunction.DocumentContent);
  908.                         continue;
  909.                     case ParsingFunction.PopEmptyElementContext:
  910.                         curNode = nodes[index];
  911.                         Debug.Assert(curNode.type == XmlNodeType.Element);
  912.                         curNode.IsEmptyElement = false;
  913.                         ResetAttributes();
  914.                         PopElementContext();
  915.                         parsingFunction = nextParsingFunction;
  916.                         continue;
  917.                     case ParsingFunction.EntityReference:
  918.                         parsingFunction = nextParsingFunction;
  919.                         ParseEntityReference();
  920.                         return true;
  921.                     case ParsingFunction.ReportEndEntity:
  922.                         SetupEndEntityNodeInContent();
  923.                         parsingFunction = nextParsingFunction;
  924.                         return true;
  925.                     case ParsingFunction.AfterResolveEntityInContent:
  926.                         curNode = AddNode(index, index);
  927.                         reportedEncoding = ps.encoding;
  928.                         reportedBaseUri = ps.baseUriStr;
  929.                         parsingFunction = nextParsingFunction;
  930.                         continue;
  931.                     case ParsingFunction.AfterResolveEmptyEntityInContent:
  932.                         curNode = AddNode(index, index);
  933.                         curNode.SetValueNode(XmlNodeType.Text, string.Empty);
  934.                         curNode.SetLineInfo(ps.lineNo, ps.LinePos);
  935.                         reportedEncoding = ps.encoding;
  936.                         reportedBaseUri = ps.baseUriStr;
  937.                         parsingFunction = nextParsingFunction;
  938.                         return true;
  939.                     case ParsingFunction.InReadAttributeValue:
  940.                         FinishAttributeValueIterator();
  941.                         curNode = nodes[index];
  942.                         continue;
  943.                     case ParsingFunction.InIncrementalRead:
  944.                         FinishIncrementalRead();
  945.                         return true;
  946.                     case ParsingFunction.FragmentAttribute:
  947.                         return ParseFragmentAttribute();
  948.                     case ParsingFunction.XmlDeclarationFragment:
  949.                         ParseXmlDeclarationFragment();
  950.                         parsingFunction = ParsingFunction.GoToEof;
  951.                         return true;
  952.                     case ParsingFunction.GoToEof:
  953.                         OnEof();
  954.                         return false;
  955.                     case ParsingFunction.Error:
  956.                     case ParsingFunction.Eof:
  957.                     case ParsingFunction.ReaderClosed:
  958.                         return false;
  959.                     case ParsingFunction.NoData:
  960.                         ThrowWithoutLineInfo(Res.Xml_MissingRoot);
  961.                         return false;
  962.                     case ParsingFunction.PartialTextValue:
  963.                         SkipPartialTextValue();
  964.                         continue;
  965.                     case ParsingFunction.InReadValueChunk:
  966.                         FinishReadValueChunk();
  967.                         continue;
  968.                     case ParsingFunction.InReadContentAsBinary:
  969.                         FinishReadContentAsBinary();
  970.                         continue;
  971.                     case ParsingFunction.InReadElementContentAsBinary:
  972.                         FinishReadElementContentAsBinary();
  973.                         continue;
  974.                     default:
  975.                         Debug.Assert(false);
  976.                         break;
  977.                 }
  978.             }
  979.         }
  980.        
  981.         // Closes the input stream ot TextReader, changes the ReadState to Closed and sets all properties to zero/string.Empty
  982.         public override void Close()
  983.         {
  984.             Close(closeInput);
  985.         }
  986.        
  987.         // Skips the current node. If on element, skips to the end tag of the element.
  988.         public override void Skip()
  989.         {
  990.             if (readState != ReadState.Interactive)
  991.                 return;
  992.            
  993.             if (InAttributeValueIterator) {
  994.                 FinishAttributeValueIterator();
  995.                 curNode = nodes[index];
  996.             }
  997.             else {
  998.                 switch (parsingFunction) {
  999.                     case ParsingFunction.InReadAttributeValue:
  1000.                         Debug.Assert(false);
  1001.                         break;
  1002.                     case ParsingFunction.InIncrementalRead:
  1003.                         FinishIncrementalRead();
  1004.                         break;
  1005.                     case ParsingFunction.PartialTextValue:
  1006.                         SkipPartialTextValue();
  1007.                         break;
  1008.                     case ParsingFunction.InReadValueChunk:
  1009.                         FinishReadValueChunk();
  1010.                         break;
  1011.                     case ParsingFunction.InReadContentAsBinary:
  1012.                         FinishReadContentAsBinary();
  1013.                         break;
  1014.                     case ParsingFunction.InReadElementContentAsBinary:
  1015.                         FinishReadElementContentAsBinary();
  1016.                         break;
  1017.                 }
  1018.             }
  1019.            
  1020.             switch (curNode.type) {
  1021.                 case XmlNodeType.Element:
  1022.                     // skip subtree
  1023.                     if (curNode.IsEmptyElement) {
  1024.                         break;
  1025.                     }
  1026.                     int initialDepth = index;
  1027.                     parsingMode = ParsingMode.SkipContent;
  1028.                     // skip content
  1029.                     while (outerReader.Read() && index > initialDepth)
  1030.                         ;
  1031.                     Debug.Assert(curNode.type == XmlNodeType.EndElement);
  1032.                     Debug.Assert(parsingFunction != ParsingFunction.Eof);
  1033.                     parsingMode = ParsingMode.Full;
  1034.                     break;
  1035.                 case XmlNodeType.Attribute:
  1036.                     outerReader.MoveToElement();
  1037.                     goto case XmlNodeType.Element;
  1038.                     break;
  1039.             }
  1040.             // move to following sibling node
  1041.             outerReader.Read();
  1042.             return;
  1043.         }
  1044.        
  1045.         // Returns NamespaceURI associated with the specified prefix in the current namespace scope.
  1046.         public override string LookupNamespace(string prefix)
  1047.         {
  1048.             if (!supportNamespaces) {
  1049.                 return null;
  1050.             }
  1051.            
  1052.             return namespaceManager.LookupNamespace(prefix);
  1053.         }
  1054.        
  1055.         // Iterates through the current attribute value's text and entity references chunks.
  1056.         public override bool ReadAttributeValue()
  1057.         {
  1058.             if (parsingFunction != ParsingFunction.InReadAttributeValue) {
  1059.                 if (curNode.type != XmlNodeType.Attribute) {
  1060.                     return false;
  1061.                 }
  1062.                 if (readState != ReadState.Interactive || curAttrIndex < 0) {
  1063.                     return false;
  1064.                 }
  1065.                 if (parsingFunction == ParsingFunction.InReadValueChunk) {
  1066.                     FinishReadValueChunk();
  1067.                 }
  1068.                 if (parsingFunction == ParsingFunction.InReadContentAsBinary) {
  1069.                     FinishReadContentAsBinary();
  1070.                 }
  1071.                
  1072.                 if (curNode.nextAttrValueChunk == null || entityHandling == EntityHandling.ExpandEntities) {
  1073.                     NodeData simpleValueNode = AddNode(index + attrCount + 1, curNode.depth + 1);
  1074.                     simpleValueNode.SetValueNode(XmlNodeType.Text, curNode.StringValue);
  1075.                     simpleValueNode.lineInfo = curNode.lineInfo2;
  1076.                     simpleValueNode.depth = curNode.depth + 1;
  1077.                     simpleValueNode.nextAttrValueChunk = null;
  1078.                     curNode = simpleValueNode;
  1079.                 }
  1080.                 else {
  1081.                     curNode = curNode.nextAttrValueChunk;
  1082.                    
  1083.                     // Place the current node at nodes[index + attrCount + 1]. If the node type
  1084.                     // is be EntityReference and user calls ResolveEntity, the associated EndEntity
  1085.                     // node will be constructed from the information stored there.
  1086.                    
  1087.                     // This will initialize the (index + attrCount + 1) place in nodes array
  1088.                     AddNode(index + attrCount + 1, index + 2);
  1089.                     nodes[index + attrCount + 1] = curNode;
  1090.                    
  1091.                     fullAttrCleanup = true;
  1092.                 }
  1093.                 nextParsingFunction = parsingFunction;
  1094.                 parsingFunction = ParsingFunction.InReadAttributeValue;
  1095.                 attributeValueBaseEntityId = ps.entityId;
  1096.                 return true;
  1097.             }
  1098.             else {
  1099.                 if (ps.entityId == attributeValueBaseEntityId) {
  1100.                     if (curNode.nextAttrValueChunk != null) {
  1101.                         curNode = curNode.nextAttrValueChunk;
  1102.                         nodes[index + attrCount + 1] = curNode;
  1103.                         // if curNode == EntityReference node, it will be picked from here by SetupEndEntityNodeInAttribute
  1104.                         return true;
  1105.                     }
  1106.                     return false;
  1107.                 }
  1108.                 else {
  1109.                     // expanded entity in attribute value
  1110.                     return ParseAttributeValueChunk();
  1111.                 }
  1112.             }
  1113.         }
  1114.        
  1115.         // Resolves the current entity reference node
  1116.         public override void ResolveEntity()
  1117.         {
  1118.             if (curNode.type != XmlNodeType.EntityReference) {
  1119.                 throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  1120.             }
  1121.            
  1122.             Debug.Assert(parsingMode == ParsingMode.Full);
  1123.            
  1124.             // entity in attribute value
  1125.             if (parsingFunction == ParsingFunction.InReadAttributeValue || parsingFunction == ParsingFunction.FragmentAttribute) {
  1126.                 switch (HandleGeneralEntityReference(curNode.localName, true, true, curNode.LinePos)) {
  1127.                     case EntityType.ExpandedInAttribute:
  1128.                     case EntityType.Expanded:
  1129.                         if (ps.charsUsed - ps.charPos == 0) {
  1130.                             // entity value == ""
  1131.                             emptyEntityInAttributeResolved = true;
  1132.                         }
  1133.                         break;
  1134.                     case EntityType.FakeExpanded:
  1135.                         emptyEntityInAttributeResolved = true;
  1136.                         break;
  1137.                     default:
  1138.                         Debug.Assert(false);
  1139.                         throw new XmlException(Res.Xml_InternalError);
  1140.                         break;
  1141.                 }
  1142.             }
  1143.             // entity in element content
  1144.             else {
  1145.                 switch (HandleGeneralEntityReference(curNode.localName, false, true, curNode.LinePos)) {
  1146.                     case EntityType.ExpandedInAttribute:
  1147.                     case EntityType.Expanded:
  1148.                         nextParsingFunction = parsingFunction;
  1149.                         if (ps.charsUsed - ps.charPos == 0 && !ps.entity.IsExternal) {
  1150.                             // empty internal entity value
  1151.                             parsingFunction = ParsingFunction.AfterResolveEmptyEntityInContent;
  1152.                         }
  1153.                         else {
  1154.                             parsingFunction = ParsingFunction.AfterResolveEntityInContent;
  1155.                         }
  1156.                         break;
  1157.                     case EntityType.FakeExpanded:
  1158.                         nextParsingFunction = parsingFunction;
  1159.                         parsingFunction = ParsingFunction.AfterResolveEmptyEntityInContent;
  1160.                         break;
  1161.                     default:
  1162.                         Debug.Assert(false);
  1163.                         throw new XmlException(Res.Xml_InternalError);
  1164.                         break;
  1165.                 }
  1166.             }
  1167.             ps.entityResolvedManually = true;
  1168.             index++;
  1169.         }
  1170.        
  1171.         internal XmlReader OuterReader {
  1172.             get { return outerReader; }
  1173.             set {
  1174.                 Debug.Assert(value is XmlTextReader);
  1175.                 outerReader = value;
  1176.             }
  1177.         }
  1178.         internal void MoveOffEntityReference()
  1179.         {
  1180.             if (outerReader.NodeType == XmlNodeType.EntityReference && parsingFunction == ParsingFunction.AfterResolveEntityInContent) {
  1181.                 if (!outerReader.Read()) {
  1182.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  1183.                 }
  1184.             }
  1185.         }
  1186.        
  1187.         public override string ReadString()
  1188.         {
  1189.             Debug.Assert(outerReader is XmlTextReaderImpl);
  1190.             MoveOffEntityReference();
  1191.             return base.ReadString();
  1192.         }
  1193.        
  1194.         public override bool CanReadBinaryContent {
  1195.             get { return true; }
  1196.         }
  1197.        
  1198.         // Reads and concatenates content nodes, base64-decodes the results and copies the decoded bytes into the provided buffer
  1199.         public override int ReadContentAsBase64(byte[] buffer, int index, int count)
  1200.         {
  1201.             // check arguments
  1202.             if (buffer == null) {
  1203.                 throw new ArgumentNullException("buffer");
  1204.             }
  1205.             if (count < 0) {
  1206.                 throw new ArgumentOutOfRangeException("count");
  1207.             }
  1208.             if (index < 0) {
  1209.                 throw new ArgumentOutOfRangeException("index");
  1210.             }
  1211.             if (buffer.Length - index < count) {
  1212.                 throw new ArgumentOutOfRangeException("count");
  1213.             }
  1214.            
  1215.             // if not the first call to ReadContentAsBase64
  1216.             if (parsingFunction == ParsingFunction.InReadContentAsBinary) {
  1217.                 // and if we have a correct decoder
  1218.                 if (incReadDecoder == base64Decoder) {
  1219.                     // read more binary data
  1220.                     return ReadContentAsBinary(buffer, index, count);
  1221.                 }
  1222.             }
  1223.             // first call of ReadContentAsBase64 -> initialize (move to first text child (for elements) and initialize incremental read state)
  1224.             else {
  1225.                 if (readState != ReadState.Interactive) {
  1226.                     return 0;
  1227.                 }
  1228.                 if (parsingFunction == ParsingFunction.InReadElementContentAsBinary) {
  1229.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  1230.                 }
  1231.                 if (!XmlReader.CanReadContentAs(curNode.type)) {
  1232.                     throw CreateReadContentAsException("ReadContentAsBase64");
  1233.                 }
  1234.                 if (!InitReadContentAsBinary()) {
  1235.                     return 0;
  1236.                 }
  1237.             }
  1238.            
  1239.             // setup base64 decoder
  1240.             InitBase64Decoder();
  1241.            
  1242.             // read binary data
  1243.             return ReadContentAsBinary(buffer, index, count);
  1244.         }
  1245.        
  1246.        
  1247.         // Reads and concatenates content nodes, binhex-decodes the results and copies the decoded bytes into the provided buffer
  1248.         public override int ReadContentAsBinHex(byte[] buffer, int index, int count)
  1249.         {
  1250.             // check arguments
  1251.             if (buffer == null) {
  1252.                 throw new ArgumentNullException("buffer");
  1253.             }
  1254.             if (count < 0) {
  1255.                 throw new ArgumentOutOfRangeException("count");
  1256.             }
  1257.             if (index < 0) {
  1258.                 throw new ArgumentOutOfRangeException("index");
  1259.             }
  1260.             if (buffer.Length - index < count) {
  1261.                 throw new ArgumentOutOfRangeException("count");
  1262.             }
  1263.            
  1264.             // if not the first call to ReadContentAsBinHex
  1265.             if (parsingFunction == ParsingFunction.InReadContentAsBinary) {
  1266.                 // and if we have a correct decoder
  1267.                 if (incReadDecoder == binHexDecoder) {
  1268.                     // read more binary data
  1269.                     return ReadContentAsBinary(buffer, index, count);
  1270.                 }
  1271.             }
  1272.             // first call of ReadContentAsBinHex -> initialize (move to first text child (for elements) and initialize incremental read state)
  1273.             else {
  1274.                 if (readState != ReadState.Interactive) {
  1275.                     return 0;
  1276.                 }
  1277.                 if (parsingFunction == ParsingFunction.InReadElementContentAsBinary) {
  1278.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  1279.                 }
  1280.                 if (!XmlReader.CanReadContentAs(curNode.type)) {
  1281.                     throw CreateReadContentAsException("ReadContentAsBinHex");
  1282.                 }
  1283.                 if (!InitReadContentAsBinary()) {
  1284.                     return 0;
  1285.                 }
  1286.             }
  1287.            
  1288.             // setup binhex decoder (when in first ReadContentAsBinHex call or when mixed with ReadContentAsBase64)
  1289.             InitBinHexDecoder();
  1290.            
  1291.             // read binary data
  1292.             return ReadContentAsBinary(buffer, index, count);
  1293.         }
  1294.        
  1295.         // Reads and concatenates content of an element, base64-decodes the results and copies the decoded bytes into the provided buffer
  1296.         public override int ReadElementContentAsBase64(byte[] buffer, int index, int count)
  1297.         {
  1298.             // check arguments
  1299.             if (buffer == null) {
  1300.                 throw new ArgumentNullException("buffer");
  1301.             }
  1302.             if (count < 0) {
  1303.                 throw new ArgumentOutOfRangeException("count");
  1304.             }
  1305.             if (index < 0) {
  1306.                 throw new ArgumentOutOfRangeException("index");
  1307.             }
  1308.             if (buffer.Length - index < count) {
  1309.                 throw new ArgumentOutOfRangeException("count");
  1310.             }
  1311.            
  1312.             // if not the first call to ReadContentAsBase64
  1313.             if (parsingFunction == ParsingFunction.InReadElementContentAsBinary) {
  1314.                 // and if we have a correct decoder
  1315.                 if (incReadDecoder == base64Decoder) {
  1316.                     // read more binary data
  1317.                     return ReadElementContentAsBinary(buffer, index, count);
  1318.                 }
  1319.             }
  1320.             // first call of ReadElementContentAsBase64 -> initialize
  1321.             else {
  1322.                 if (readState != ReadState.Interactive) {
  1323.                     return 0;
  1324.                 }
  1325.                 if (parsingFunction == ParsingFunction.InReadContentAsBinary) {
  1326.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  1327.                 }
  1328.                 if (curNode.type != XmlNodeType.Element) {
  1329.                     throw CreateReadElementContentAsException("ReadElementContentAsBinHex");
  1330.                 }
  1331.                 if (!InitReadElementContentAsBinary()) {
  1332.                     return 0;
  1333.                 }
  1334.             }
  1335.            
  1336.             // setup base64 decoder
  1337.             InitBase64Decoder();
  1338.            
  1339.             // read binary data
  1340.             return ReadElementContentAsBinary(buffer, index, count);
  1341.         }
  1342.        
  1343.        
  1344.         // Reads and concatenates content of an element, binhex-decodes the results and copies the decoded bytes into the provided buffer
  1345.         public override int ReadElementContentAsBinHex(byte[] buffer, int index, int count)
  1346.         {
  1347.             // check arguments
  1348.             if (buffer == null) {
  1349.                 throw new ArgumentNullException("buffer");
  1350.             }
  1351.             if (count < 0) {
  1352.                 throw new ArgumentOutOfRangeException("count");
  1353.             }
  1354.             if (index < 0) {
  1355.                 throw new ArgumentOutOfRangeException("index");
  1356.             }
  1357.             if (buffer.Length - index < count) {
  1358.                 throw new ArgumentOutOfRangeException("count");
  1359.             }
  1360.            
  1361.             // if not the first call to ReadContentAsBinHex
  1362.             if (parsingFunction == ParsingFunction.InReadElementContentAsBinary) {
  1363.                 // and if we have a correct decoder
  1364.                 if (incReadDecoder == binHexDecoder) {
  1365.                     // read more binary data
  1366.                     return ReadElementContentAsBinary(buffer, index, count);
  1367.                 }
  1368.             }
  1369.             // first call of ReadContentAsBinHex -> initialize
  1370.             else {
  1371.                 if (readState != ReadState.Interactive) {
  1372.                     return 0;
  1373.                 }
  1374.                 if (parsingFunction == ParsingFunction.InReadContentAsBinary) {
  1375.                     throw new InvalidOperationException(Res.GetString(Res.Xml_MixingBinaryContentMethods));
  1376.                 }
  1377.                 if (curNode.type != XmlNodeType.Element) {
  1378.                     throw CreateReadElementContentAsException("ReadElementContentAsBinHex");
  1379.                 }
  1380.                 if (!InitReadElementContentAsBinary()) {
  1381.                     return 0;
  1382.                 }
  1383.             }
  1384.            
  1385.             // setup binhex decoder (when in first ReadContentAsBinHex call or when mixed with ReadContentAsBase64)
  1386.             InitBinHexDecoder();
  1387.            
  1388.             // read binary data
  1389.             return ReadElementContentAsBinary(buffer, index, count);
  1390.         }
  1391.        
  1392.         // Returns true if ReadValue is supported
  1393.         public override bool CanReadValueChunk {
  1394.             get { return true; }
  1395.         }
  1396.        
  1397.         // Iterates over Value property and copies it into the provided buffer
  1398.         public override int ReadValueChunk(char[] buffer, int index, int count)
  1399.         {
  1400.             // throw on elements
  1401.             if (!XmlReader.HasValueInternal(curNode.type)) {
  1402.                 throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidReadValueChunk, curNode.type));
  1403.             }
  1404.             // check arguments
  1405.             if (buffer == null) {
  1406.                 throw new ArgumentNullException("buffer");
  1407.             }
  1408.             if (count < 0) {
  1409.                 throw new ArgumentOutOfRangeException("count");
  1410.             }
  1411.             if (index < 0) {
  1412.                 throw new ArgumentOutOfRangeException("index");
  1413.             }
  1414.             if (buffer.Length - index < count) {
  1415.                 throw new ArgumentOutOfRangeException("count");
  1416.             }
  1417.            
  1418.             // first call of ReadValueChunk -> initialize incremental read state
  1419.             if (parsingFunction != ParsingFunction.InReadValueChunk) {
  1420.                 if (readState != ReadState.Interactive) {
  1421.                     return 0;
  1422.                 }
  1423.                 if (parsingFunction == ParsingFunction.PartialTextValue) {
  1424.                     incReadState = IncrementalReadState.ReadValueChunk_OnPartialValue;
  1425.                 }
  1426.                 else {
  1427.                     incReadState = IncrementalReadState.ReadValueChunk_OnCachedValue;
  1428.                     nextNextParsingFunction = nextParsingFunction;
  1429.                     nextParsingFunction = parsingFunction;
  1430.                 }
  1431.                 parsingFunction = ParsingFunction.InReadValueChunk;
  1432.                 readValueOffset = 0;
  1433.             }
  1434.            
  1435.             if (count == 0) {
  1436.                 return 0;
  1437.             }
  1438.            
  1439.             // read what is already cached in curNode
  1440.             int readCount = 0;
  1441.             int read = curNode.CopyTo(readValueOffset, buffer, index + readCount, count - readCount);
  1442.             readCount += read;
  1443.             readValueOffset += read;
  1444.            
  1445.             if (readCount == count) {
  1446.                 // take care of suppogate pairs spanning between buffers
  1447.                 char ch = buffer[index + count - 1];
  1448.                 if (ch >= SurHighStart && ch <= SurHighEnd) {
  1449.                     readCount--;
  1450.                     readValueOffset--;
  1451.                     if (readCount == 0) {
  1452.                         Throw(Res.Xml_NotEnoughSpaceForSurrogatePair);
  1453.                     }
  1454.                 }
  1455.                 return readCount;
  1456.             }
  1457.            
  1458.             // if on partial value, read the rest of it
  1459.             if (incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue) {
  1460.                 curNode.SetValue(string.Empty);
  1461.                
  1462.                 // read next chunk of text
  1463.                 bool endOfValue = false;
  1464.                 int startPos = 0;
  1465.                 int endPos = 0;
  1466.                 while (readCount < count && !endOfValue) {
  1467.                     int orChars = 0;
  1468.                     endOfValue = ParseText(out startPos, out endPos, ref orChars);
  1469.                    
  1470.                     int copyCount = count - readCount;
  1471.                     if (copyCount > endPos - startPos) {
  1472.                         copyCount = endPos - startPos;
  1473.                     }
  1474.                     Buffer.BlockCopy(ps.chars, startPos * 2, buffer, (index + readCount) * 2, copyCount * 2);
  1475.                    
  1476.                     readCount += copyCount;
  1477.                     startPos += copyCount;
  1478.                 }
  1479.                
  1480.                 incReadState = endOfValue ? IncrementalReadState.ReadValueChunk_OnCachedValue : IncrementalReadState.ReadValueChunk_OnPartialValue;
  1481.                
  1482.                 if (readCount == count) {
  1483.                     char ch = buffer[index + count - 1];
  1484.                     if (ch >= SurHighStart && ch <= SurHighEnd) {
  1485.                         readCount--;
  1486.                         startPos--;
  1487.                         if (readCount == 0) {
  1488.                             Throw(Res.Xml_NotEnoughSpaceForSurrogatePair);
  1489.                         }
  1490.                     }
  1491.                 }
  1492.                
  1493.                 readValueOffset = 0;
  1494.                 curNode.SetValue(ps.chars, startPos, endPos - startPos);
  1495.             }
  1496.             return readCount;
  1497.         }
  1498.        
  1499.         //
  1500.         // IXmlLineInfo members
  1501.         //
  1502.         public bool HasLineInfo()
  1503.         {
  1504.             return true;
  1505.         }
  1506.        
  1507.         // Returns the line number of the current node
  1508.         public int LineNumber {
  1509.             get { return curNode.LineNo; }
  1510.         }
  1511.        
  1512.         // Returns the line position of the current node
  1513.         public int LinePosition {
  1514.             get { return curNode.LinePos; }
  1515.         }
  1516.        
  1517.         //
  1518.         // IXmlNamespaceResolver members
  1519.         //
  1520.         IDictionary<string, string> IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope)
  1521.         {
  1522.             return this.GetNamespacesInScope(scope);
  1523.         }
  1524.        
  1525.         string IXmlNamespaceResolver.LookupNamespace(string prefix)
  1526.         {
  1527.             return this.LookupNamespace(prefix);
  1528.         }
  1529.        
  1530.         string IXmlNamespaceResolver.LookupPrefix(string namespaceName)
  1531.         {
  1532.             return this.LookupPrefix(namespaceName);
  1533.         }
  1534.        
  1535.         // Internal IXmlNamespaceResolver methods
  1536.         internal IDictionary<string, string> GetNamespacesInScope(XmlNamespaceScope scope)
  1537.         {
  1538.             return namespaceManager.GetNamespacesInScope(scope);
  1539.         }
  1540.        
  1541.         // NOTE: there already is virtual method for "string LookupNamespace(string prefix)"
  1542.        
  1543.         internal string LookupPrefix(string namespaceName)
  1544.         {
  1545.             return namespaceManager.LookupPrefix(namespaceName);
  1546.         }
  1547.        
  1548.         //
  1549.         // XmlTextReader members
  1550.         //
  1551.         // Disables or enables support of W3C XML 1.0 Namespaces
  1552.         internal bool Namespaces {
  1553.             get {
  1554.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.Namespaces property cannot be accessed on reader created via XmlReader.Create.");
  1555.                 return supportNamespaces;
  1556.             }
  1557.             set {
  1558.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.Namespaces property cannot be changed on reader created via XmlReader.Create.");
  1559.                 if (readState != ReadState.Initial) {
  1560.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  1561.                 }
  1562.                 supportNamespaces = value;
  1563.                 if (value) {
  1564.                     if (namespaceManager is NoNamespaceManager) {
  1565.                         if (fragment && fragmentParserContext != null && fragmentParserContext.NamespaceManager != null) {
  1566.                             namespaceManager = fragmentParserContext.NamespaceManager;
  1567.                         }
  1568.                         else {
  1569.                             namespaceManager = new XmlNamespaceManager(nameTable);
  1570.                         }
  1571.                     }
  1572.                     xmlContext.defaultNamespace = namespaceManager.LookupNamespace(string.Empty);
  1573.                 }
  1574.                 else {
  1575.                     if (!(namespaceManager is NoNamespaceManager)) {
  1576.                         namespaceManager = new NoNamespaceManager();
  1577.                     }
  1578.                     xmlContext.defaultNamespace = string.Empty;
  1579.                 }
  1580.             }
  1581.         }
  1582.        
  1583.         // Enables or disables XML 1.0 normalization (incl. end-of-line normalization and normalization of attributes)
  1584.         internal bool Normalization {
  1585.             get {
  1586.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.Normalization property cannot be accessed on reader created via XmlReader.Create.");
  1587.                 return normalize;
  1588.             }
  1589.             set {
  1590.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.Normalization property cannot be changed on reader created via XmlReader.Create.");
  1591.                 if (readState == ReadState.Closed) {
  1592.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  1593.                 }
  1594.                 normalize = value;
  1595.                
  1596.                 if (ps.entity == null || ps.entity.IsExternal) {
  1597.                     ps.eolNormalized = !value;
  1598.                 }
  1599.             }
  1600.         }
  1601.        
  1602.         // Returns the Encoding of the XML document
  1603.         internal Encoding Encoding {
  1604.             get { return (readState == ReadState.Interactive) ? reportedEncoding : null; }
  1605.         }
  1606.        
  1607.         // Spefifies whitespace handling of the XML document, i.e. whether return all namespaces, only significant ones or none
  1608.         internal WhitespaceHandling WhitespaceHandling {
  1609.             get {
  1610.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.WhitespaceHandling property cannot be accessed on reader created via XmlReader.Create.");
  1611.                 return whitespaceHandling;
  1612.             }
  1613.             set {
  1614.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.WhitespaceHandling property cannot be changed on reader created via XmlReader.Create.");
  1615.                 if (readState == ReadState.Closed) {
  1616.                     throw new InvalidOperationException(Res.GetString(Res.Xml_InvalidOperation));
  1617.                 }
  1618.                
  1619.                 if ((uint)value > (uint)WhitespaceHandling.None) {
  1620.                     throw new XmlException(Res.Xml_WhitespaceHandling, string.Empty);
  1621.                 }
  1622.                 whitespaceHandling = value;
  1623.             }
  1624.         }
  1625.        
  1626.         // Specifies whether DTD is prohibited in the XML document. When true, an exceptio will be thrown when a DOCTYPE markup is encountered.
  1627.         internal bool ProhibitDtd {
  1628.             get {
  1629.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.ProhibitDtd property cannot be accessed on reader created via XmlReader.Create.");
  1630.                 return prohibitDtd;
  1631.             }
  1632.             set {
  1633.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.ProhibitDtd property cannot be changed on reader created via XmlReader.Create.");
  1634.                 prohibitDtd = value;
  1635.             }
  1636.         }
  1637.        
  1638.         // Spefifies whether general entities should be automatically expanded or not
  1639.         internal EntityHandling EntityHandling {
  1640.             get {
  1641.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.EntityHandling property cannot be accessed on reader created via XmlReader.Create.");
  1642.                 return entityHandling;
  1643.             }
  1644.             set {
  1645.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.EntityHandling property cannot be changed on reader created via XmlReader.Create.");
  1646.                 if (value != EntityHandling.ExpandEntities && value != EntityHandling.ExpandCharEntities) {
  1647.                     throw new XmlException(Res.Xml_EntityHandling, string.Empty);
  1648.                 }
  1649.                 entityHandling = value;
  1650.             }
  1651.         }
  1652.        
  1653.         // Specifies XmlResolver used for opening the XML document and other external references
  1654.         internal XmlResolver XmlResolver {
  1655.             set {
  1656.                 Debug.Assert(v1Compat, "XmlTextReaderImpl.XmlResolver property cannot be changed on reader created via XmlReader.Create.");
  1657.                 xmlResolver = value;
  1658.                
  1659.                 // invalidate all baseUris on the stack
  1660.                 ps.baseUri = null;
  1661.                 for (int i = 0; i <= parsingStatesStackTop; i++) {
  1662.                     parsingStatesStack[i].baseUri = null;
  1663.                 }
  1664.             }
  1665.         }
  1666.        
  1667.         // Reset the state of the reader so the reader is ready to parse another XML document from the same stream.
  1668.         internal void ResetState()
  1669.         {
  1670.             Debug.Assert(v1Compat, "XmlTextReaderImpl.ResetState cannot be called on reader created via XmlReader.Create.");
  1671.            
  1672.             if (fragment) {
  1673.                 Throw(new InvalidOperationException(Res.GetString(Res.Xml_InvalidResetStateCall)));
  1674.             }
  1675.            
  1676.             if (readState == ReadState.Initial) {
  1677.                 return;
  1678.             }
  1679.            
  1680.             // Clear
  1681.             ResetAttributes();
  1682.             while (namespaceManager.PopScope())
  1683.                 ;
  1684.            
  1685.             while (InEntity) {
  1686.                 HandleEntityEnd(true);
  1687.             }
  1688.            
  1689.             // Init
  1690.             readState = ReadState.Initial;
  1691.             parsingFunction = ParsingFunction.SwitchToInteractiveXmlDecl;
  1692.             nextParsingFunction = ParsingFunction.DocumentContent;
  1693.            
  1694.             curNode = nodes[0];
  1695.             curNode.Clear(XmlNodeType.None);
  1696.             curNode.SetLineInfo(0, 0);
  1697.             index = 0;
  1698.             rootElementParsed = false;
  1699.            
  1700.             afterResetState = true;
  1701.         }
  1702.        
  1703.         // returns the remaining unparsed data as TextReader
  1704.         internal TextReader GetRemainder()
  1705.         {
  1706.             Debug.Assert(v1Compat, "XmlTextReaderImpl.GetRemainder cannot be called on reader created via XmlReader.Create.");
  1707.            
  1708.             Debug.Assert(stringBuilder.Length == 0);
  1709.             switch (parsingFunction) {
  1710.                 case ParsingFunction.Eof:
  1711.                 case ParsingFunction.ReaderClosed:
  1712.                     return new StringReader(string.Empty);
  1713.                 case ParsingFunction.OpenUrl:
  1714.                     OpenUrl();
  1715.                     break;
  1716.                 case ParsingFunction.InIncrementalRead:
  1717.                     if (!InEntity) {
  1718.                         stringBuilder.Append(ps.chars, incReadLeftStartPos, incReadLeftEndPos - incReadLeftStartPos);
  1719.                     }
  1720.                     break;
  1721.             }
  1722.            
  1723.             while (InEntity) {
  1724.                 HandleEntityEnd(true);
  1725.             }
  1726.            
  1727.             ps.appendMode = false;
  1728.             do {
  1729.                 stringBuilder.Append(ps.chars, ps.charPos, ps.charsUsed - ps.charPos);
  1730.                 ps.charPos = ps.charsUsed;
  1731.             }
  1732.             while (ReadData() != 0);
  1733.            
  1734.             OnEof();
  1735.            
  1736.             string remainer = stringBuilder.ToString();
  1737.             stringBuilder.Length = 0;
  1738.             return new StringReader(remainer);
  1739.         }
  1740.        
  1741.         // Reads the contents of an element including markup into a character buffer. Wellformedness checks are limited.
  1742.         // This method is designed to read large streams of embedded text by calling it successively.
  1743.         internal int ReadChars(char[] buffer, int index, int count)
  1744.         {
  1745.             Debug.Assert(v1Compat, "XmlTextReaderImpl.ReadChars cannot be called on reader created via XmlReader.Create.");
  1746.             Debug.Assert(outerReader is XmlTextReader);
  1747.            
  1748.             if (parsingFunction == ParsingFunction.InIncrementalRead) {
  1749.                 if (incReadDecoder != readCharsDecoder) {
  1750.                     // mixing ReadChars with ReadBase64 or ReadBinHex
  1751.                     if (readCharsDecoder == null) {
  1752.                         readCharsDecoder = new IncrementalReadCharsDecoder();
  1753.                     }
  1754.                     readCharsDecoder.Reset();
  1755.                     incReadDecoder = readCharsDecoder;
  1756.                 }
  1757.                 return IncrementalRead(buffer, index, count);
  1758.             }
  1759.             else {
  1760.                 if (curNode.type != XmlNodeType.Element) {
  1761.                     return 0;
  1762.                 }
  1763.                 if (curNode.IsEmptyElement) {
  1764.                     outerReader.Read();
  1765.                     return 0;
  1766.                 }
  1767.                
  1768.                 if (readCharsDecoder == null) {
  1769.                     readCharsDecoder = new IncrementalReadCharsDecoder();
  1770.                 }
  1771.                
  1772.                 InitIncrementalRead(readCharsDecoder);
  1773.                 return IncrementalRead(buffer, index, count);
  1774.             }
  1775.         }
  1776.        
  1777.         // Reads the contents of an element including markup and base64-decodes it into a byte buffer. Wellformedness checks are limited.
  1778.         // This method is designed to read base64-encoded large streams of bytes by calling it successively.
  1779.         internal int ReadBase64(byte[] array, int offset, int len)
  1780.         {
  1781.             Debug.Assert(v1Compat, "XmlTextReaderImpl.ReadBase64 cannot be called on reader created via XmlReader.Create.");
  1782.             Debug.Assert(outerReader is XmlTextReader);
  1783.            
  1784.             if (parsingFunction == ParsingFunction.InIncrementalRead) {
  1785.                 if (incReadDecoder != base64Decoder) {
  1786.                     // mixing ReadBase64 with ReadChars or ReadBinHex
  1787.                     InitBase64Decoder();
  1788.                 }
  1789.                 return IncrementalRead(array, offset, len);
  1790.             }
  1791.             else {
  1792.                 if (curNode.type != XmlNodeType.Element) {
  1793.                     return 0;
  1794.                 }
  1795.                 if (curNode.IsEmptyElement) {
  1796.                     outerReader.Read();
  1797.                     return 0;
  1798.                 }
  1799.                
  1800.                 if (base64Decoder == null) {
  1801.                     base64Decoder = new Base64Decoder();
  1802.                 }
  1803.                
  1804.                 InitIncrementalRead(base64Decoder);
  1805.                 return IncrementalRead(array, offset, len);
  1806.             }
  1807.         }
  1808.        
  1809.         // Reads the contents of an element including markup and binhex-decodes it into a byte buffer. Wellformedness checks are limited.
  1810.         // This method is designed to read binhex-encoded large streams of bytes by calling it successively.
  1811.         internal int ReadBinHex(byte[] array, int offset, int len)
  1812.         {
  1813.             Debug.Assert(v1Compat, "XmlTextReaderImpl.ReadBinHex cannot be called on reader created via XmlReader.Create.");
  1814.             Debug.Assert(outerReader is XmlTextReader);
  1815.            
  1816.             if (parsingFunction == ParsingFunction.InIncrementalRead) {
  1817.                 if (incReadDecoder != binHexDecoder) {
  1818.                     // mixing ReadBinHex with ReadChars or ReadBase64
  1819.                     InitBinHexDecoder();
  1820.                 }
  1821.                 return IncrementalRead(array, offset, len);
  1822.             }
  1823.             else {
  1824.                 if (curNode.type != XmlNodeType.Element) {
  1825.                     return 0;
  1826.                 }
  1827.                 if (curNode.IsEmptyElement) {
  1828.                     outerReader.Read();
  1829.                     return 0;
  1830.                 }
  1831.                
  1832.                 if (binHexDecoder == null) {
  1833.                     binHexDecoder = new BinHexDecoder();
  1834.                 }
  1835.                
  1836.                 InitIncrementalRead(binHexDecoder);
  1837.                 return IncrementalRead(array, offset, len);
  1838.             }
  1839.         }
  1840.        
  1841.         //
  1842.         // Helpers for DtdParserProxy
  1843.         //
  1844.         internal XmlNameTable DtdParserProxy_NameTable {
  1845.             get { return nameTable; }
  1846.         }
  1847.        
  1848.         internal XmlNamespaceManager DtdParserProxy_NamespaceManager {
  1849.             get { return namespaceManager; }
  1850.         }
  1851.        
  1852.         internal bool DtdParserProxy_DtdValidation {
  1853.             get { return DtdValidation; }
  1854.         }
  1855.        
  1856.         internal bool DtdParserProxy_Normalization {
  1857.             get { return normalize; }
  1858.         }
  1859.        
  1860.         internal bool DtdParserProxy_Namespaces {
  1861.             get { return supportNamespaces; }
  1862.         }
  1863.        
  1864.         internal bool DtdParserProxy_V1CompatibilityMode {
  1865.             get { return v1Compat; }
  1866.         }
  1867.        
  1868.         internal Uri DtdParserProxy_BaseUri {
  1869.             get {
  1870.                 if (ps.baseUriStr.Length > 0 && ps.baseUri == null && xmlResolver != null) {
  1871.                     ps.baseUri = xmlResolver.ResolveUri(null, ps.baseUriStr);
  1872.                 }
  1873.                 return ps.baseUri;
  1874.             }
  1875.         }
  1876.        
  1877.         internal bool DtdParserProxy_IsEof {
  1878.             get { return ps.isEof; }
  1879.         }
  1880.        
  1881.         internal char[] DtdParserProxy_ParsingBuffer {
  1882.             get { return ps.chars; }
  1883.         }
  1884.        
  1885.         internal int DtdParserProxy_ParsingBufferLength {
  1886.             get { return ps.charsUsed; }
  1887.         }
  1888.        
  1889.         internal int DtdParserProxy_CurrentPosition {
  1890.             get { return ps.charPos; }
  1891.             set {
  1892.                 Debug.Assert(value >= 0 && value <= ps.charsUsed);
  1893.                 ps.charPos = value;
  1894.             }
  1895.         }
  1896.        
  1897.         internal int DtdParserProxy_EntityStackLength {
  1898.             get { return parsingStatesStackTop + 1; }
  1899.         }
  1900.        
  1901.         internal bool DtdParserProxy_IsEntityEolNormalized {
  1902.             get { return ps.eolNormalized; }
  1903.         }
  1904.        
  1905.         internal ValidationEventHandler DtdParserProxy_EventHandler {
  1906.             get { return validationEventHandler; }
  1907.             set { validationEventHandler = value; }
  1908.         }
  1909.        
  1910.         internal void DtdParserProxy_OnNewLine(int pos)
  1911.         {
  1912.             this.OnNewLine(pos);
  1913.         }
  1914.        
  1915.         internal int DtdParserProxy_LineNo {
  1916.             get { return ps.LineNo; }
  1917.         }
  1918.        
  1919.         internal int DtdParserProxy_LineStartPosition {
  1920.             get { return ps.lineStartPos; }
  1921.         }
  1922.        
  1923.         internal int DtdParserProxy_ReadData()
  1924.         {
  1925.             return this.ReadData();
  1926.         }
  1927.        
  1928.         internal void DtdParserProxy_SendValidationEvent(XmlSeverityType severity, XmlSchemaException exception)
  1929.         {
  1930.             if (DtdValidation) {
  1931.                 this.SendValidationEvent(severity, exception);
  1932.             }
  1933.         }
  1934.        
  1935.         internal int DtdParserProxy_ParseNumericCharRef(BufferBuilder internalSubsetBuilder)
  1936.         {
  1937.             EntityType entType;
  1938.             return this.ParseNumericCharRef(true, internalSubsetBuilder, out entType);
  1939.         }
  1940.        
  1941.         internal int DtdParserProxy_ParseNamedCharRef(bool expand, BufferBuilder internalSubsetBuilder)
  1942.         {
  1943.             return this.ParseNamedCharRef(expand, internalSubsetBuilder);
  1944.         }
  1945.        
  1946.         internal void DtdParserProxy_ParsePI(BufferBuilder sb)
  1947.         {
  1948.             if (sb == null) {
  1949.                 ParsingMode pm = parsingMode;
  1950.                 parsingMode = ParsingMode.SkipNode;
  1951.                 ParsePI(null);
  1952.                 parsingMode = pm;
  1953.             }
  1954.             else {
  1955.                 ParsePI(sb);
  1956.             }
  1957.         }
  1958.        
  1959.         internal void DtdParserProxy_ParseComment(BufferBuilder sb)
  1960.         {
  1961.             Debug.Assert(parsingMode == ParsingMode.Full);
  1962.            
  1963.             try {
  1964.                 if (sb == null) {
  1965.                     ParsingMode savedParsingMode = parsingMode;
  1966.                     parsingMode = ParsingMode.SkipNode;
  1967.                     ParseCDataOrComment(XmlNodeType.Comment);
  1968.                     parsingMode = savedParsingMode;
  1969.                 }
  1970.                 else {
  1971.                     NodeData originalCurNode = curNode;
  1972.                    
  1973.                     curNode = AddNode(index + attrCount + 1, index);
  1974.                     ParseCDataOrComment(XmlNodeType.Comment);
  1975.                     curNode.CopyTo(sb);
  1976.                    
  1977.                     curNode = originalCurNode;
  1978.                 }
  1979.             }
  1980.             catch (XmlException e) {
  1981.                 if (e.ResString == Res.Xml_UnexpectedEOF && ps.entity != null) {
  1982.                     SendValidationEvent(XmlSeverityType.Error, Res.Sch_ParEntityRefNesting, null, ps.LineNo, ps.LinePos);
  1983.                 }
  1984.                 else {
  1985.                     throw;
  1986.                 }
  1987.             }
  1988.         }
  1989.        
  1990.         internal bool DtdParserProxy_PushEntity(SchemaEntity entity, int entityId)
  1991.         {
  1992.             if (entity.IsExternal) {
  1993.                 if (xmlResolver == null) {
  1994.                     return false;
  1995.                 }
  1996.                 return PushExternalEntity(entity, entityId);
  1997.             }
  1998.             else {
  1999.                 PushInternalEntity(entity, entityId);
  2000.                 return true;
  2001.             }
  2002.         }
  2003.        
  2004.         internal bool DtdParserProxy_PopEntity(out SchemaEntity oldEntity, out int newEntityId)
  2005.         {
  2006.             if (parsingStatesStackTop == -1) {
  2007.                 oldEntity = null;
  2008.                 newEntityId = -1;
  2009.                 return false;
  2010.             }
  2011.             oldEntity = ps.entity;
  2012.             PopEntity();
  2013.             newEntityId = ps.entityId;
  2014.             return true;
  2015.         }
  2016.        
  2017.         internal bool DtdParserProxy_PushExternalSubset(string systemId, string publicId)
  2018.         {
  2019.             Debug.Assert(parsingStatesStackTop == -1);
  2020.             Debug.Assert((systemId != null && systemId.Length > 0) || (publicId != null && publicId.Length > 0));
  2021.            
  2022.             if (xmlResolver == null) {
  2023.                 return false;
  2024.             }
  2025.            
  2026.             if (ps.baseUriStr.Length > 0 && ps.baseUri == null) {
  2027.                 ps.baseUri = xmlResolver.ResolveUri(null, ps.baseUriStr);
  2028.             }
  2029.            
  2030.             Uri extSubsetUri;
  2031.             Stream stream = null;
  2032.             if (publicId == null || publicId.Length == 0) {
  2033.                 extSubsetUri = xmlResolver.ResolveUri(ps.baseUri, systemId);
  2034.                 try {
  2035.                     stream = OpenStream(extSubsetUri);
  2036.                 }
  2037.                 catch (Exception e) {
  2038.                     if (v1Compat) {
  2039.                         throw;
  2040.                     }
  2041.                     Throw(new XmlException(Res.Xml_ErrorOpeningExternalDtd, new string[] {extSubsetUri.ToString(), e.Message}, e, 0, 0));
  2042.                 }
  2043.             }
  2044.             else {
  2045.                 try {
  2046.                     extSubsetUri = xmlResolver.ResolveUri(ps.baseUri, publicId);
  2047.                     stream = OpenStream(extSubsetUri);
  2048.                 }
  2049.                 catch (Exception) {
  2050.                     extSubsetUri = xmlResolver.ResolveUri(ps.baseUri, systemId);
  2051.                     try {
  2052.                         stream = OpenStream(extSubsetUri);
  2053.                     }
  2054.                     catch (Exception e) {
  2055.                         if (v1Compat) {
  2056.                             throw;
  2057.                         }
  2058.                         Throw(new XmlException(Res.Xml_ErrorOpeningExternalDtd, new string[] {extSubsetUri.ToString(), e.Message}, e, 0, 0));
  2059.                     }
  2060.                 }
  2061.             }
  2062.            
  2063.             if (stream == null) {
  2064.                 ThrowWithoutLineInfo(Res.Xml_CannotResolveExternalSubset, new string[] {(publicId != null ? publicId : string.Empty), systemId});
  2065.             }
  2066.            
  2067.             PushParsingState();
  2068.            
  2069.             if (v1Compat) {
  2070.                 InitStreamInput(extSubsetUri, stream, null);
  2071.             }
  2072.             else {
  2073.                 InitStreamInput(extSubsetUri, stream, null);
  2074.             }
  2075.            
  2076.             ps.entity = null;
  2077.             ps.entityId = 0;
  2078.            
  2079.             Debug.Assert(ps.appendMode);
  2080.             int initialPos = ps.charPos;
  2081.             if (v1Compat) {
  2082.                 EatWhitespaces(null);
  2083.             }
  2084.             if (!ParseXmlDeclaration(true)) {
  2085.                 ps.charPos = initialPos;
  2086.             }
  2087.            
  2088.             return true;
  2089.         }
  2090.        
  2091.         internal void DtdParserProxy_PushInternalDtd(string baseUri, string internalDtd)
  2092.         {
  2093.             Debug.Assert(parsingStatesStackTop == -1);
  2094.            
  2095.             PushParsingState();
  2096.            
  2097.             InitStringInput(baseUri, Encoding.Unicode, internalDtd);
  2098.            
  2099.             ps.entity = null;
  2100.             ps.entityId = 0;
  2101.             ps.eolNormalized = false;
  2102.         }
  2103.        
  2104.         internal void DtdParserProxy_Throw(Exception e)
  2105.         {
  2106.             this.Throw(e);
  2107.         }
  2108.        
  2109.         internal void DtdParserProxy_OnSystemId(string systemId, LineInfo keywordLineInfo, LineInfo systemLiteralLineInfo)
  2110.         {
  2111.             NodeData attr = AddAttributeNoChecks("SYSTEM", index);
  2112.             attr.SetValue(systemId);
  2113.             attr.lineInfo = keywordLineInfo;
  2114.             attr.lineInfo2 = systemLiteralLineInfo;
  2115.         }
  2116.        
  2117.         internal void DtdParserProxy_OnPublicId(string publicId, LineInfo keywordLineInfo, LineInfo publicLiteralLineInfo)
  2118.         {
  2119.             NodeData attr = AddAttributeNoChecks("PUBLIC", index);
  2120.             attr.SetValue(publicId);
  2121.             attr.lineInfo = keywordLineInfo;
  2122.             attr.lineInfo2 = publicLiteralLineInfo;
  2123.         }
  2124.        
  2125.         //
  2126.         // Throw methods: Sets the reader current position to pos, sets the error state and throws exception
  2127.         //
  2128.         void Throw(int pos, string res, string arg)
  2129.         {
  2130.             ps.charPos = pos;
  2131.             Throw(res, arg);
  2132.         }
  2133.        
  2134.         void Throw(int pos, string res, string[] args)
  2135.         {
  2136.             ps.charPos = pos;
  2137.             Throw(res, args);
  2138.         }
  2139.        
  2140.         void Throw(int pos, string res)
  2141.         {
  2142.             ps.charPos = pos;
  2143.             Throw(res, string.Empty);
  2144.         }
  2145.        
  2146.         void Throw(string res)
  2147.         {
  2148.             Throw(res, string.Empty);
  2149.         }
  2150.        
  2151.         void Throw(string res, int lineNo, int linePos)
  2152.         {
  2153.             Throw(new XmlException(res, string.Empty, lineNo, linePos, ps.baseUriStr));
  2154.         }
  2155.        
  2156.         void Throw(string res, string arg)
  2157.         {
  2158.             Throw(new XmlException(res, arg, ps.LineNo, ps.LinePos, ps.baseUriStr));
  2159.         }
  2160.        
  2161.         void Throw(string res, string arg, int lineNo, int linePos)
  2162.         {
  2163.             Throw(new XmlException(res, arg, lineNo, linePos, ps.baseUriStr));
  2164.         }
  2165.        
  2166.         void Throw(string res, string[] args)
  2167.         {
  2168.             Throw(new XmlException(res, args, ps.LineNo, ps.LinePos, ps.baseUriStr));
  2169.         }
  2170.        
  2171.         void Throw(Exception e)
  2172.         {
  2173.             SetErrorState();
  2174.             XmlException xmlEx = e as XmlException;
  2175.             if (xmlEx != null) {
  2176.                 curNode.SetLineInfo(xmlEx.LineNumber, xmlEx.LinePosition);
  2177.             }
  2178.             throw e;
  2179.         }
  2180.        
  2181.         void ReThrow(Exception e, int lineNo, int linePos)
  2182.         {
  2183.             Throw(new XmlException(e.Message, (Exception)null, lineNo, linePos, ps.baseUriStr));
  2184.         }
  2185.        
  2186.         void ThrowWithoutLineInfo(string res)
  2187.         {
  2188.             Throw(new XmlException(res, string.Empty, ps.baseUriStr));
  2189.         }
  2190.        
  2191.         void ThrowWithoutLineInfo(string res, string arg)
  2192.         {
  2193.             Throw(new XmlException(res, arg, ps.baseUriStr));
  2194.         }
  2195.        
  2196.         void ThrowWithoutLineInfo(string res, string[] args)
  2197.         {
  2198.             Throw(new XmlException(res, args, ps.baseUriStr));
  2199.         }
  2200.        
  2201.         void ThrowInvalidChar(int pos, char invChar)
  2202.         {
  2203.             // special-case binary XML stream wrapped in a TextReader
  2204.             if (pos == 0 && curNode.type == XmlNodeType.None && ps.textReader != null && ps.charsUsed >= 2 && ((ps.chars[0] == 1 && ps.chars[1] == 4) || (ps.chars[0] == 223 || ps.chars[1] == 255))) {
  2205.                 Throw(pos, Res.Xml_BinaryXmlReadAsText, XmlException.BuildCharExceptionStr(invChar));
  2206.             }
  2207.             else {
  2208.                 Throw(pos, Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionStr(invChar));
  2209.             }
  2210.         }
  2211.        
  2212.         private void SetErrorState()
  2213.         {
  2214.             parsingFunction = ParsingFunction.Error;
  2215.             readState = ReadState.Error;
  2216.         }
  2217.        
  2218.         void SendValidationEvent(XmlSeverityType severity, string code, string arg, int lineNo, int linePos)
  2219.         {
  2220.             SendValidationEvent(severity, new XmlSchemaException(code, arg, ps.baseUriStr, lineNo, linePos));
  2221.         }
  2222.        
  2223.         void SendValidationEvent(XmlSeverityType severity, XmlSchemaException exception)
  2224.         {
  2225.             if (validationEventHandler != null) {
  2226.                 validationEventHandler(this, new ValidationEventArgs(exception, severity));
  2227.             }
  2228.         }
  2229.        
  2230.         //
  2231.         // Private implementation methods & properties
  2232.         //
  2233.         private bool InAttributeValueIterator {
  2234.             get { return attrCount > 0 && parsingFunction >= ParsingFunction.InReadAttributeValue; }
  2235.         }
  2236.        
  2237.         private void FinishAttributeValueIterator()
  2238.         {
  2239.             Debug.Assert(InAttributeValueIterator);
  2240.             if (parsingFunction == ParsingFunction.InReadValueChunk) {
  2241.                 FinishReadValueChunk();
  2242.             }
  2243.             else if (parsingFunction == ParsingFunction.InReadContentAsBinary) {
  2244.                 FinishReadContentAsBinary();
  2245.             }
  2246.             if (parsingFunction == ParsingFunction.InReadAttributeValue) {
  2247.                 while (ps.entityId != attributeValueBaseEntityId) {
  2248.                     HandleEntityEnd(false);
  2249.                 }
  2250.                 parsingFunction = nextParsingFunction;
  2251.                 nextParsingFunction = (index > 0) ? ParsingFunction.ElementContent : ParsingFunction.DocumentContent;
  2252.                 emptyEntityInAttributeResolved = false;
  2253.             }
  2254.         }
  2255.        
  2256.         private bool DtdValidation {
  2257.             get { return validationEventHandler != null; }
  2258.         }
  2259.        
  2260.         private void InitStreamInput(Stream stream, Encoding encoding)
  2261.         {
  2262.             InitStreamInput(null, string.Empty, stream, null, 0, encoding);
  2263.         }
  2264.        
  2265.         private void InitStreamInput(string baseUriStr, Stream stream, Encoding encoding)
  2266.         {
  2267.             Debug.Assert(baseUriStr != null);
  2268.             InitStreamInput(null, baseUriStr, stream, null, 0, encoding);
  2269.         }
  2270.        
  2271.         private void InitStreamInput(Uri baseUri, Stream stream, Encoding encoding)
  2272.         {
  2273.             Debug.Assert(baseUri != null);
  2274.             InitStreamInput(baseUri, baseUri.ToString(), stream, null, 0, encoding);
  2275.         }
  2276.        
  2277.         private void InitStreamInput(Uri baseUri, string baseUriStr, Stream stream, Encoding encoding)
  2278.         {
  2279.             InitStreamInput(baseUri, baseUriStr, stream, null, 0, encoding);
  2280.         }
  2281.        
  2282.         private void InitStreamInput(Uri baseUri, string baseUriStr, Stream stream, byte[] bytes, int byteCount, Encoding encoding)
  2283.         {
  2284.            
  2285.             Debug.Assert(ps.charPos == 0 && ps.charsUsed == 0 && ps.textReader == null);
  2286.             Debug.Assert(baseUriStr != null);
  2287.             Debug.Assert(baseUri == null || (baseUri.ToString().Equals(baseUriStr)));
  2288.            
  2289.             ps.stream = stream;
  2290.             ps.baseUri = baseUri;
  2291.             ps.baseUriStr = baseUriStr;
  2292.            
  2293.             // take over the byte buffer allocated in XmlReader.Create, if available
  2294.             int bufferSize;
  2295.             if (bytes != null) {
  2296.                 ps.bytes = bytes;
  2297.                 ps.bytesUsed = byteCount;
  2298.                 bufferSize = ps.bytes.Length;
  2299.             }
  2300.             else {
  2301.                 // allocate the byte buffer
  2302.                 bufferSize = XmlReader.CalcBufferSize(stream);
  2303.                 if (ps.bytes == null || ps.bytes.Length < bufferSize) {
  2304.                     ps.bytes = new byte[bufferSize];
  2305.                 }
  2306.             }
  2307.            
  2308.             // allocate char buffer
  2309.             if (ps.chars == null || ps.chars.Length < bufferSize + 1) {
  2310.                 ps.chars = new char[bufferSize + 1];
  2311.             }
  2312.            
  2313.             // make sure we have at least 4 bytes to detect the encoding (no preamble of System.Text supported encoding is longer than 4 bytes)
  2314.             ps.bytePos = 0;
  2315.             while (ps.bytesUsed < 4 && ps.bytes.Length - ps.bytesUsed > 0) {
  2316.                 int read = stream.Read(ps.bytes, ps.bytesUsed, ps.bytes.Length - ps.bytesUsed);
  2317.                 if (read == 0) {
  2318.                     ps.isStreamEof = true;
  2319.                     break;
  2320.                 }
  2321.                 ps.bytesUsed += read;
  2322.             }
  2323.            
  2324.             // detect & setup encoding
  2325.             if (encoding == null) {
  2326.                 encoding = DetectEncoding();
  2327.             }
  2328.             SetupEncoding(encoding);
  2329.            
  2330.             // eat preamble
  2331.             byte[] preamble = ps.encoding.GetPreamble();
  2332.             int preambleLen = preamble.Length;
  2333.             int i;
  2334.             for (i = 0; i < preambleLen && i < ps.bytesUsed; i++) {
  2335.                 if (ps.bytes[i] != preamble[i]) {
  2336.                     break;
  2337.                 }
  2338.             }
  2339.             if (i == preambleLen) {
  2340.                 ps.bytePos = preambleLen;
  2341.             }
  2342.            
  2343.             documentStartBytePos = ps.bytePos;
  2344.            
  2345.             ps.eolNormalized = !normalize;
  2346.            
  2347.             // decode first characters
  2348.             ps.appendMode = true;
  2349.             ReadData();
  2350.         }
  2351.        
  2352.         private void InitTextReaderInput(string baseUriStr, TextReader input)
  2353.         {
  2354.             Debug.Assert(ps.charPos == 0 && ps.charsUsed == 0 && ps.stream == null);
  2355.             Debug.Assert(baseUriStr != null);
  2356.            
  2357.             ps.textReader = input;
  2358.             ps.baseUriStr = baseUriStr;
  2359.             ps.baseUri = null;
  2360.            
  2361.             if (ps.chars == null) {
  2362.                 ps.chars = new char[XmlReader.DefaultBufferSize + 1];
  2363.             }
  2364.            
  2365.             ps.encoding = Encoding.Unicode;
  2366.             ps.eolNormalized = !normalize;
  2367.            
  2368.             // read first characters
  2369.             ps.appendMode = true;
  2370.             ReadData();
  2371.         }
  2372.        
  2373.         private void InitStringInput(string baseUriStr, Encoding originalEncoding, string str)
  2374.         {
  2375.             Debug.Assert(ps.stream == null && ps.textReader == null);
  2376.             Debug.Assert(ps.charPos == 0 && ps.charsUsed == 0);
  2377.             Debug.Assert(baseUriStr != null);
  2378.            
  2379.             ps.baseUriStr = baseUriStr;
  2380.             ps.baseUri = null;
  2381.            
  2382.             int len = str.Length;
  2383.             ps.chars = new char[len + 1];
  2384.             str.CopyTo(0, ps.chars, 0, str.Length);
  2385.             ps.charsUsed = len;
  2386.             ps.chars[len] = (char)0;
  2387.            
  2388.             ps.encoding = originalEncoding;
  2389.            
  2390.             ps.eolNormalized = !normalize;
  2391.             ps.isEof = true;
  2392.         }
  2393.        
  2394.         private void InitFragmentReader(XmlNodeType fragmentType, XmlParserContext parserContext, bool allowXmlDeclFragment)
  2395.         {
  2396.            
  2397.             fragmentParserContext = parserContext;
  2398.            
  2399.             if (parserContext != null) {
  2400.                 if (parserContext.NamespaceManager != null) {
  2401.                     namespaceManager = parserContext.NamespaceManager;
  2402.                     xmlContext.defaultNamespace = namespaceManager.LookupNamespace(string.Empty);
  2403.                 }
  2404.                 else {
  2405.                     namespaceManager = new XmlNamespaceManager(nameTable);
  2406.                 }
  2407.                
  2408.                 ps.baseUriStr = parserContext.BaseURI;
  2409.                 ps.baseUri = null;
  2410.                 xmlContext.xmlLang = parserContext.XmlLang;
  2411.                 xmlContext.xmlSpace = parserContext.XmlSpace;
  2412.             }
  2413.             else {
  2414.                 namespaceManager = new XmlNamespaceManager(nameTable);
  2415.                 ps.baseUriStr = string.Empty;
  2416.                 ps.baseUri = null;
  2417.             }
  2418.            
  2419.             reportedBaseUri = ps.baseUriStr;
  2420.            
  2421.             switch (fragmentType) {
  2422.                 case XmlNodeType.Attribute:
  2423.                     ps.appendMode = false;
  2424.                     parsingFunction = ParsingFunction.SwitchToInteractive;
  2425.                     nextParsingFunction = ParsingFunction.FragmentAttribute;
  2426.                     break;
  2427.                 case XmlNodeType.Element:
  2428.                     Debug.Assert(parsingFunction == ParsingFunction.SwitchToInteractiveXmlDecl);
  2429.                     nextParsingFunction = ParsingFunction.DocumentContent;
  2430.                     break;
  2431.                 case XmlNodeType.Document:
  2432.                     Debug.Assert(parsingFunction == ParsingFunction.SwitchToInteractiveXmlDecl);
  2433.                     Debug.Assert(nextParsingFunction == ParsingFunction.DocumentContent);
  2434.                     break;
  2435.                 case XmlNodeType.XmlDeclaration:
  2436.                     if (allowXmlDeclFragment) {
  2437.                         ps.appendMode = false;
  2438.                         parsingFunction = ParsingFunction.SwitchToInteractive;
  2439.                         nextParsingFunction = ParsingFunction.XmlDeclarationFragment;
  2440.                         break;
  2441.                     }
  2442.                     else {
  2443.                         goto default;
  2444.                     }
  2445.                     break;
  2446.                 default:
  2447.                     Throw(Res.Xml_PartialContentNodeTypeNotSupportedEx, fragmentType.ToString());
  2448.                     return;
  2449.             }
  2450.             this.fragmentType = fragmentType;
  2451.             this.fragment = true;
  2452.         }
  2453.        
  2454.         private void OpenUrl()
  2455.         {
  2456.             Debug.Assert(url != null && url.Length > 0);
  2457.             Debug.Assert(compressedStack != null);
  2458.            
  2459.             XmlResolver tmpResolver;
  2460.             if (ps.baseUri != null) {
  2461.                 Debug.Assert(xmlResolver != null);
  2462.                 tmpResolver = xmlResolver;
  2463.             }
  2464.             else {
  2465.                 tmpResolver = (xmlResolver == null) ? new XmlUrlResolver() : xmlResolver;
  2466.                 ps.baseUri = tmpResolver.ResolveUri(null, url);
  2467.                 ps.baseUriStr = ps.baseUri.ToString();
  2468.             }
  2469.            
  2470.             try {
  2471.                 CompressedStack.Run(compressedStack, new ContextCallback(OpenUrlDelegate), tmpResolver);
  2472.             }
  2473.             catch {
  2474.                 SetErrorState();
  2475.                 throw;
  2476.             }
  2477.            
  2478.             if (ps.stream == null) {
  2479.                 ThrowWithoutLineInfo(Res.Xml_CannotResolveUrl, ps.baseUriStr);
  2480.             }
  2481.            
  2482.             InitStreamInput(ps.baseUri, ps.baseUriStr, ps.stream, null);
  2483.             reportedEncoding = ps.encoding;
  2484.         }
  2485.        
  2486.         void OpenUrlDelegate(object xmlResolver)
  2487.         {
  2488.             ps.stream = (Stream)((XmlResolver)xmlResolver).GetEntity(ps.baseUri, null, typeof(Stream));
  2489.         }
  2490.        
  2491.         // Stream input only: detect encoding from the first 4 bytes of the byte buffer starting at ps.bytes[ps.bytePos]
  2492.         private Encoding DetectEncoding()
  2493.         {
  2494.             Debug.Assert(ps.bytes != null);
  2495.             Debug.Assert(ps.bytePos == 0);
  2496.            
  2497.             if (ps.bytesUsed < 2) {
  2498.                 return null;
  2499.             }
  2500.             int first2Bytes = ps.bytes[0] << 8 | ps.bytes[1];
  2501.             int next2Bytes = (ps.bytesUsed >= 4) ? (ps.bytes[2] << 8 | ps.bytes[3]) : 0;
  2502.            
  2503.             switch (first2Bytes) {
  2504.                 case 0:
  2505.                     switch (next2Bytes) {
  2506.                         case 65279:
  2507.                             return Ucs4Encoding.UCS4_Bigendian;
  2508.                         case 60:
  2509.                             return Ucs4Encoding.UCS4_Bigendian;
  2510.                         case 65534:
  2511.                             return Ucs4Encoding.UCS4_2143;
  2512.                         case 15360:
  2513.                             return Ucs4Encoding.UCS4_2143;
  2514.                     }
  2515.                     break;
  2516.                 case 65279:
  2517.                     if (next2Bytes == 0) {
  2518.                         return Ucs4Encoding.UCS4_3412;
  2519.                     }
  2520.                     else {
  2521.                         return Encoding.BigEndianUnicode;
  2522.                     }
  2523.                     break;
  2524.                 case 65534:
  2525.                     if (next2Bytes == 0) {
  2526.                         return Ucs4Encoding.UCS4_Littleendian;
  2527.                     }
  2528.                     else {
  2529.                         return Encoding.Unicode;
  2530.                     }
  2531.                     break;
  2532.                 case 15360:
  2533.                     switch (next2Bytes) {
  2534.                         case 0:
  2535.                             return Ucs4Encoding.UCS4_Littleendian;
  2536.                         case 16128:
  2537.                             return Encoding.Unicode;
  2538.                     }
  2539.                     break;
  2540.                 case 60:
  2541.                     switch (next2Bytes) {
  2542.                         case 0:
  2543.                             return Ucs4Encoding.UCS4_3412;
  2544.                         case 63:
  2545.                             return Encoding.BigEndianUnicode;
  2546.                     }
  2547.                     break;
  2548.                 case 19567:
  2549.                     if (next2Bytes == 42900) {
  2550.                         Throw(Res.Xml_UnknownEncoding, "ebcdic");
  2551.                     }
  2552.                     break;
  2553.                 case 61371:
  2554.                     if ((next2Bytes & 65280) == 48896) {
  2555.                         return new UTF8Encoding(true, true);
  2556.                     }
  2557.                     break;
  2558.             }
  2559.             // Default encoding is ASCII (using SafeAsciiDecoder) until we read xml declaration.
  2560.             // If we set UTF8 encoding now, it will throw exceptions (=slow) when decoding non-UTF8-friendly
  2561.             // characters after the xml declaration, which may be perfectly valid in the encoding
  2562.             // specified in xml declaration.
  2563.             return null;
  2564.         }
  2565.        
  2566.         private void SetupEncoding(Encoding encoding)
  2567.         {
  2568.             if (encoding == null) {
  2569.                 Debug.Assert(ps.charPos == 0);
  2570.                 ps.encoding = Encoding.UTF8;
  2571.                 ps.decoder = new SafeAsciiDecoder();
  2572.             }
  2573.             else {
  2574.                 ps.encoding = encoding;
  2575.                 switch (ps.encoding.CodePage) {
  2576.                     case 1200:
  2577.                         ps.decoder = new UTF16Decoder(false);
  2578.                         break;
  2579.                     case 1201:
  2580.                         ps.decoder = new UTF16Decoder(true);
  2581.                         break;
  2582.                     default:
  2583.                         ps.decoder = encoding.GetDecoder();
  2584.                         break;
  2585.                 }
  2586.             }
  2587.         }
  2588.        
  2589.         // Switches the reader's encoding
  2590.         private void SwitchEncoding(Encoding newEncoding)
  2591.         {
  2592.             if ((newEncoding.CodePage != ps.encoding.CodePage || ps.decoder is SafeAsciiDecoder) && !afterResetState) {
  2593.                 Debug.Assert(ps.stream != null);
  2594.                 UnDecodeChars();
  2595.                 ps.appendMode = false;
  2596.                 SetupEncoding(newEncoding);
  2597.                 ReadData();
  2598.             }
  2599.         }
  2600.        
  2601.         // Returns the Encoding object for the given encoding name, if the reader's encoding can be switched to that encoding.
  2602.         // Performs checks whether switching from current encoding to specified encoding is allowed.
  2603.         private Encoding CheckEncoding(string newEncodingName)
  2604.         {
  2605.             // encoding can be switched on stream input only
  2606.             if (ps.stream == null) {
  2607.                 return ps.encoding;
  2608.             }
  2609.            
  2610.             if (0 == String.Compare(newEncodingName, "ucs-2", StringComparison.OrdinalIgnoreCase) || 0 == String.Compare(newEncodingName, "utf-16", StringComparison.OrdinalIgnoreCase) || 0 == String.Compare(newEncodingName, "iso-10646-ucs-2", StringComparison.OrdinalIgnoreCase) || 0 == String.Compare(newEncodingName, "ucs-4", StringComparison.OrdinalIgnoreCase)) {
  2611.                 if (ps.encoding.CodePage != Encoding.BigEndianUnicode.CodePage && ps.encoding.CodePage != Encoding.Unicode.CodePage && 0 != String.Compare(newEncodingName, "ucs-4", StringComparison.OrdinalIgnoreCase)) {
  2612.                     if (afterResetState) {
  2613.                         Throw(Res.Xml_EncodingSwitchAfterResetState, newEncodingName);
  2614.                     }
  2615.                     else {
  2616.                         ThrowWithoutLineInfo(Res.Xml_MissingByteOrderMark);
  2617.                     }
  2618.                 }
  2619.                 return ps.encoding;
  2620.             }
  2621.            
  2622.             Encoding newEncoding = null;
  2623.             if (0 == String.Compare(newEncodingName, "utf-8", StringComparison.OrdinalIgnoreCase)) {
  2624.                 newEncoding = new UTF8Encoding(true, true);
  2625.             }
  2626.             else {
  2627.                 try {
  2628.                     newEncoding = Encoding.GetEncoding(newEncodingName);
  2629.                     if (newEncoding.CodePage == -1) {
  2630.                         Throw(Res.Xml_UnknownEncoding, newEncodingName);
  2631.                     }
  2632.                 }
  2633.                 catch (NotSupportedException) {
  2634.                     Throw(Res.Xml_UnknownEncoding, newEncodingName);
  2635.                 }
  2636.                 catch (ArgumentException) {
  2637.                     Throw(Res.Xml_UnknownEncoding, newEncodingName);
  2638.                 }
  2639.                 Debug.Assert(newEncoding.EncodingName != "UTF-8");
  2640.             }
  2641.            
  2642.             // check for invalid encoding switches after ResetState
  2643.             if (afterResetState && ps.encoding.CodePage != newEncoding.CodePage) {
  2644.                 Throw(Res.Xml_EncodingSwitchAfterResetState, newEncodingName);
  2645.             }
  2646.            
  2647.             return newEncoding;
  2648.         }
  2649.        
  2650.         void UnDecodeChars()
  2651.         {
  2652.             Debug.Assert(ps.stream != null && ps.decoder != null && ps.bytes != null);
  2653.             Debug.Assert(ps.appendMode, "UnDecodeChars cannot be called after ps.appendMode has been changed to false");
  2654.            
  2655.             ps.bytePos = documentStartBytePos;
  2656.             // byte position after preamble
  2657.             if (ps.charPos > 0) {
  2658.                 ps.bytePos += ps.encoding.GetByteCount(ps.chars, 0, ps.charPos);
  2659.             }
  2660.             ps.charsUsed = ps.charPos;
  2661.             ps.isEof = false;
  2662.         }
  2663.        
  2664.         private void SwitchEncodingToUTF8()
  2665.         {
  2666.             SwitchEncoding(new UTF8Encoding(true, true));
  2667.         }
  2668.        
  2669.         // Reads more data to the character buffer, discarding already parsed chars / decoded bytes.
  2670.         int ReadData()
  2671.         {
  2672.             // Append Mode: Append new bytes and characters to the buffers, do not rewrite them. Allocate new buffers
  2673.             // if the current ones are full
  2674.             // Rewrite Mode: Reuse the buffers. If there is less than half of the char buffer left for new data, move
  2675.             // the characters that has not been parsed yet to the front of the buffer. Same for bytes.
  2676.            
  2677.             if (ps.isEof) {
  2678.                 return 0;
  2679.             }
  2680.            
  2681.             int charsRead;
  2682.             if (ps.appendMode) {
  2683.                 // the character buffer is full -> allocate a new one
  2684.                 if (ps.charsUsed == ps.chars.Length - 1) {
  2685.                     // invalidate node values kept in buffer - applies to attribute values only
  2686.                     for (int i = 0; i < attrCount; i++) {
  2687.                         nodes[index + i + 1].OnBufferInvalidated();
  2688.                     }
  2689.                    
  2690.                     char[] newChars = new char[ps.chars.Length * 2];
  2691.                     Buffer.BlockCopy(ps.chars, 0, newChars, 0, ps.chars.Length * 2);
  2692.                     ps.chars = newChars;
  2693.                 }
  2694.                
  2695.                 if (ps.stream != null) {
  2696.                     // the byte buffer is full -> allocate a new one
  2697.                     if (ps.bytesUsed - ps.bytePos < MaxByteSequenceLen) {
  2698.                         if (ps.bytes.Length - ps.bytesUsed < MaxByteSequenceLen) {
  2699.                             byte[] newBytes = new byte[ps.bytes.Length * 2];
  2700.                             Buffer.BlockCopy(ps.bytes, 0, newBytes, 0, ps.bytesUsed);
  2701.                             ps.bytes = newBytes;
  2702.                         }
  2703.                     }
  2704.                 }
  2705.                
  2706.                 charsRead = ps.chars.Length - ps.charsUsed - 1;
  2707.                 if (charsRead > ApproxXmlDeclLength) {
  2708.                     charsRead = ApproxXmlDeclLength;
  2709.                 }
  2710.             }
  2711.             else {
  2712.                 int charsLen = ps.chars.Length;
  2713.                 if (charsLen - ps.charsUsed <= charsLen / 2) {
  2714.                     // invalidate node values kept in buffer - applies to attribute values only
  2715.                     for (int i = 0; i < attrCount; i++) {
  2716.                         nodes[index + i + 1].OnBufferInvalidated();
  2717.                     }
  2718.                    
  2719.                     // move unparsed characters to front, unless the whole buffer contains unparsed characters
  2720.                     int copyCharsCount = ps.charsUsed - ps.charPos;
  2721.                     if (copyCharsCount < charsLen - 1) {
  2722.                         ps.lineStartPos = ps.lineStartPos - ps.charPos;
  2723.                         if (copyCharsCount > 0) {
  2724.                             Buffer.BlockCopy(ps.chars, ps.charPos * 2, ps.chars, 0, copyCharsCount * 2);
  2725.                         }
  2726.                         ps.charPos = 0;
  2727.                         ps.charsUsed = copyCharsCount;
  2728.                     }
  2729.                     else {
  2730.                         char[] newChars = new char[ps.chars.Length * 2];
  2731.                         Buffer.BlockCopy(ps.chars, 0, newChars, 0, ps.chars.Length * 2);
  2732.                         ps.chars = newChars;
  2733.                     }
  2734.                 }
  2735.                
  2736.                 if (ps.stream != null) {
  2737.                     // move undecoded bytes to the front to make some space in the byte buffer
  2738.                     int bytesLeft = ps.bytesUsed - ps.bytePos;
  2739.                     if (bytesLeft <= MaxBytesToMove) {
  2740.                         if (bytesLeft == 0) {
  2741.                             ps.bytesUsed = 0;
  2742.                         }
  2743.                         else {
  2744.                             Buffer.BlockCopy(ps.bytes, ps.bytePos, ps.bytes, 0, bytesLeft);
  2745.                             ps.bytesUsed = bytesLeft;
  2746.                         }
  2747.                         ps.bytePos = 0;
  2748.                     }
  2749.                 }
  2750.                 charsRead = ps.chars.Length - ps.charsUsed - 1;
  2751.             }
  2752.            
  2753.             if (ps.stream != null) {
  2754.                 if (!ps.isStreamEof) {
  2755.                     // read new bytes
  2756.                     if (ps.bytePos == ps.bytesUsed && ps.bytes.Length - ps.bytesUsed > 0) {
  2757.                         int read = ps.stream.Read(ps.bytes, ps.bytesUsed, ps.bytes.Length - ps.bytesUsed);
  2758.                         if (read == 0) {
  2759.                             ps.isStreamEof = true;
  2760.                         }
  2761.                         ps.bytesUsed += read;
  2762.                     }
  2763.                 }
  2764.                
  2765.                 int originalBytePos = ps.bytePos;
  2766.                
  2767.                 // decode chars
  2768.                 charsRead = GetChars(charsRead);
  2769.                 if (charsRead == 0 && ps.bytePos != originalBytePos) {
  2770.                     // GetChars consumed some bytes but it was not enough bytes to form a character -> try again
  2771.                     return ReadData();
  2772.                 }
  2773.             }
  2774.             else if (ps.textReader != null) {
  2775.                 // read chars
  2776.                 charsRead = ps.textReader.Read(ps.chars, ps.charsUsed, ps.chars.Length - ps.charsUsed - 1);
  2777.                 ps.charsUsed += charsRead;
  2778.             }
  2779.             else {
  2780.                 charsRead = 0;
  2781.             }
  2782.            
  2783.             if (charsRead == 0) {
  2784.                 Debug.Assert(ps.charsUsed < ps.chars.Length);
  2785.                 ps.isEof = true;
  2786.             }
  2787.             ps.chars[ps.charsUsed] = (char)0;
  2788.             return charsRead;
  2789.         }
  2790.        
  2791.         // Stream input only: read bytes from stream and decodes them according to the current encoding
  2792.         int GetChars(int maxCharsCount)
  2793.         {
  2794.             Debug.Assert(ps.stream != null && ps.decoder != null && ps.bytes != null);
  2795.             Debug.Assert(maxCharsCount <= ps.chars.Length - ps.charsUsed - 1);
  2796.            
  2797.             // determine the maximum number of bytes we can pass to the decoder
  2798.             int bytesCount = ps.bytesUsed - ps.bytePos;
  2799.             if (bytesCount == 0) {
  2800.                 return 0;
  2801.             }
  2802.            
  2803.             int charsCount;
  2804.             bool completed;
  2805.             try {
  2806.                 // decode chars
  2807.                 ps.decoder.Convert(ps.bytes, ps.bytePos, bytesCount, ps.chars, ps.charsUsed, maxCharsCount, false, out bytesCount, out charsCount, out completed
  2808.                 );
  2809.             }
  2810.             catch (ArgumentException e) {
  2811.                 // Invalid character exception, lets get as many chars as we can:
  2812.                 Debug.Assert(e.ParamName == null, "Expecting 'invalid character in given encoding' exception.");
  2813.                 InvalidCharRecovery(ref bytesCount, out charsCount);
  2814.             }
  2815.            
  2816.             // move pointers and return
  2817.             ps.bytePos += bytesCount;
  2818.             ps.charsUsed += charsCount;
  2819.             Debug.Assert(maxCharsCount >= charsCount);
  2820.             return charsCount;
  2821.         }
  2822.        
  2823.         private void InvalidCharRecovery(ref int bytesCount, out int charsCount)
  2824.         {
  2825.             int charsDecoded = 0;
  2826.             int bytesDecoded = 0;
  2827.             try {
  2828.                 while (bytesDecoded < bytesCount) {
  2829.                     int chDec;
  2830.                     int bDec;
  2831.                     bool completed;
  2832.                     ps.decoder.Convert(ps.bytes, ps.bytePos + bytesDecoded, 1, ps.chars, ps.charsUsed + charsDecoded, 1, false, out bDec, out chDec, out completed
  2833.                     );
  2834.                     charsDecoded += chDec;
  2835.                     bytesDecoded += bDec;
  2836.                 }
  2837.                 Debug.Assert(false, "We should get an exception again.");
  2838.             }
  2839.             catch (ArgumentException) {
  2840.             }
  2841.            
  2842.             if (charsDecoded == 0) {
  2843.                 Throw(ps.charsUsed, Res.Xml_InvalidCharInThisEncoding);
  2844.             }
  2845.             charsCount = charsDecoded;
  2846.             bytesCount = bytesDecoded;
  2847.         }
  2848.        
  2849.         internal void Close(bool closeInput)
  2850.         {
  2851.             if (parsingFunction == ParsingFunction.ReaderClosed) {
  2852.                 return;
  2853.             }
  2854.            
  2855.             while (InEntity) {
  2856.                 PopParsingState();
  2857.             }
  2858.            
  2859.             ps.Close(closeInput);
  2860.            
  2861.             curNode = NodeData.None;
  2862.             parsingFunction = ParsingFunction.ReaderClosed;
  2863.             reportedEncoding = null;
  2864.             reportedBaseUri = string.Empty;
  2865.             readState = ReadState.Closed;
  2866.             fullAttrCleanup = false;
  2867.             ResetAttributes();
  2868.         }
  2869.        
  2870.         void ShiftBuffer(int sourcePos, int destPos, int count)
  2871.         {
  2872.             // PERF: Buffer.BlockCopy is faster than Array.Copy
  2873.             Buffer.BlockCopy(ps.chars, sourcePos * 2, ps.chars, destPos * 2, count * 2);
  2874.         }
  2875.        
  2876.         // Parses the xml or text declaration and switched encoding if needed
  2877.         private bool ParseXmlDeclaration(bool isTextDecl)
  2878.         {
  2879.             while (ps.charsUsed - ps.charPos < 6) {
  2880.                 // minimum "<?xml "
  2881.                 if (ReadData() == 0) {
  2882.                     goto NoXmlDecl;
  2883.                 }
  2884.             }
  2885.            
  2886.             if (!XmlConvert.StrEqual(ps.chars, ps.charPos, 5, XmlDeclarationBegining) || xmlCharType.IsNameChar(ps.chars[ps.charPos + 5])) {
  2887.                 goto NoXmlDecl;
  2888.             }
  2889.            
  2890.             if (!isTextDecl) {
  2891.                 curNode.SetLineInfo(ps.LineNo, ps.LinePos + 2);
  2892.                 curNode.SetNamedNode(XmlNodeType.XmlDeclaration, Xml);
  2893.             }
  2894.             ps.charPos += 5;
  2895.            
  2896.             // parsing of text declarations cannot change global stringBuidler or curNode as we may be in the middle of a text node
  2897.             Debug.Assert(stringBuilder.Length == 0 || isTextDecl);
  2898.             BufferBuilder sb = isTextDecl ? new BufferBuilder() : stringBuilder;
  2899.            
  2900.             // parse version, encoding & standalone attributes
  2901.             int xmlDeclState = 0;
  2902.             // <?xml (0) version='1.0' (1) encoding='__' (2) standalone='__' (3) ?>
  2903.             Encoding encoding = null;
  2904.            
  2905.             for (;;) {
  2906.                 int originalSbLen = sb.Length;
  2907.                 int wsCount = EatWhitespaces(xmlDeclState == 0 ? null : sb);
  2908.                
  2909.                 // end of xml declaration
  2910.                 if (ps.chars[ps.charPos] == '?') {
  2911.                     sb.Length = originalSbLen;
  2912.                    
  2913.                     if (ps.chars[ps.charPos + 1] == '>') {
  2914.                         if (xmlDeclState == 0) {
  2915.                             Throw(isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl);
  2916.                         }
  2917.                        
  2918.                         ps.charPos += 2;
  2919.                         if (!isTextDecl) {
  2920.                             curNode.SetValue(sb.ToString());
  2921.                             sb.Length = 0;
  2922.                            
  2923.                             nextParsingFunction = parsingFunction;
  2924.                             parsingFunction = ParsingFunction.ResetAttributesRootLevel;
  2925.                         }
  2926.                        
  2927.                         // switch to encoding specified in xml declaration
  2928.                         if (encoding == null) {
  2929.                             if (isTextDecl) {
  2930.                                 Throw(Res.Xml_InvalidTextDecl);
  2931.                             }
  2932.                             if (afterResetState) {
  2933.                                 // check for invalid encoding switches to default encoding
  2934.                                 int codePage = ps.encoding.CodePage;
  2935.                                 if (codePage != Encoding.UTF8.CodePage && codePage != Encoding.Unicode.CodePage && codePage != Encoding.BigEndianUnicode.CodePage && !(ps.encoding is Ucs4Encoding)) {
  2936.                                     Throw(Res.Xml_EncodingSwitchAfterResetState, (ps.encoding.GetByteCount("A") == 1) ? "UTF-8" : "UTF-16");
  2937.                                 }
  2938.                             }
  2939.                             if (ps.decoder is SafeAsciiDecoder) {
  2940.                                 SwitchEncodingToUTF8();
  2941.                             }
  2942.                         }
  2943.                         else {
  2944.                             SwitchEncoding(encoding);
  2945.                         }
  2946.                         ps.appendMode = false;
  2947.                         return true;
  2948.                     }
  2949.                     else if (ps.charPos + 1 == ps.charsUsed) {
  2950.                         goto ReadData;
  2951.                     }
  2952.                     else {
  2953.                         ThrowUnexpectedToken("'>'");
  2954.                     }
  2955.                 }
  2956.                
  2957.                 if (wsCount == 0 && xmlDeclState != 0) {
  2958.                     ThrowUnexpectedToken("?>");
  2959.                 }
  2960.                
  2961.                 // read attribute name
  2962.                 int nameEndPos = ParseName();
  2963.                
  2964.                 NodeData attr = null;
  2965.                 switch (ps.chars[ps.charPos]) {
  2966.                     case 'v':
  2967.                         if (XmlConvert.StrEqual(ps.chars, ps.charPos, nameEndPos - ps.charPos, "version") && xmlDeclState == 0) {
  2968.                             if (!isTextDecl) {
  2969.                                 attr = AddAttributeNoChecks("version", 0);
  2970.                             }
  2971.                             break;
  2972.                         }
  2973.                         goto default;
  2974.                         break;
  2975.                     case 'e':
  2976.                         if (XmlConvert.StrEqual(ps.chars, ps.charPos, nameEndPos - ps.charPos, "encoding") && (xmlDeclState == 1 || (isTextDecl && xmlDeclState == 0))) {
  2977.                             if (!isTextDecl) {
  2978.                                 attr = AddAttributeNoChecks("encoding", 0);
  2979.                             }
  2980.                             xmlDeclState = 1;
  2981.                             break;
  2982.                         }
  2983.                         goto default;
  2984.                         break;
  2985.                     case 's':
  2986.                         if (XmlConvert.StrEqual(ps.chars, ps.charPos, nameEndPos - ps.charPos, "standalone") && (xmlDeclState == 1 || xmlDeclState == 2) && !isTextDecl) {
  2987.                             if (!isTextDecl) {
  2988.                                 attr = AddAttributeNoChecks("standalone", 0);
  2989.                             }
  2990.                             xmlDeclState = 2;
  2991.                             break;
  2992.                         }
  2993.                         goto default;
  2994.                         break;
  2995.                     default:
  2996.                         Throw(isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl);
  2997.                         break;
  2998.                 }
  2999.                 if (!isTextDecl) {
  3000.                     attr.SetLineInfo(ps.LineNo, ps.LinePos);
  3001.                 }
  3002.                 sb.Append(ps.chars, ps.charPos, nameEndPos - ps.charPos);
  3003.                 ps.charPos = nameEndPos;
  3004.                
  3005.                 // parse equals and quote char;
  3006.                 if (ps.chars[ps.charPos] != '=') {
  3007.                     EatWhitespaces(sb);
  3008.                     if (ps.chars[ps.charPos] != '=') {
  3009.                         ThrowUnexpectedToken("=");
  3010.                     }
  3011.                 }
  3012.                 sb.Append('=');
  3013.                 ps.charPos++;
  3014.                
  3015.                 char quoteChar = ps.chars[ps.charPos];
  3016.                 if (quoteChar != '"' && quoteChar != '\'') {
  3017.                     EatWhitespaces(sb);
  3018.                     quoteChar = ps.chars[ps.charPos];
  3019.                     if (quoteChar != '"' && quoteChar != '\'') {
  3020.                         ThrowUnexpectedToken("\"", "'");
  3021.                     }
  3022.                 }
  3023.                 sb.Append(quoteChar);
  3024.                 ps.charPos++;
  3025.                 if (!isTextDecl) {
  3026.                     attr.quoteChar = quoteChar;
  3027.                     attr.SetLineInfo2(ps.LineNo, ps.LinePos);
  3028.                 }
  3029.                
  3030.                 // parse attribute value
  3031.                 int pos = ps.charPos;
  3032.                 char[] chars;
  3033.                 Continue:
  3034.                 chars = ps.chars;
  3035.                 unsafe {
  3036.                     while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue) != 0)) {
  3037.                         pos++;
  3038.                     }
  3039.                 }
  3040.                
  3041.                 if (ps.chars[pos] == quoteChar) {
  3042.                     switch (xmlDeclState) {
  3043.                         case 0:
  3044.                             // version
  3045.                             if (XmlConvert.StrEqual(ps.chars, ps.charPos, pos - ps.charPos, "1.0")) {
  3046.                                 if (!isTextDecl) {
  3047.                                     attr.SetValue(ps.chars, ps.charPos, pos - ps.charPos);
  3048.                                 }
  3049.                                 xmlDeclState = 1;
  3050.                             }
  3051.                             else {
  3052.                                 string badVersion = new string(ps.chars, ps.charPos, pos - ps.charPos);
  3053.                                 Throw(Res.Xml_InvalidVersionNumber, badVersion);
  3054.                             }
  3055.                             break;
  3056.                         case 1:
  3057.                             string encName = new string(ps.chars, ps.charPos, pos - ps.charPos);
  3058.                             encoding = CheckEncoding(encName);
  3059.                             if (!isTextDecl) {
  3060.                                 attr.SetValue(encName);
  3061.                             }
  3062.                             xmlDeclState = 2;
  3063.                             break;
  3064.                         case 2:
  3065.                             if (XmlConvert.StrEqual(ps.chars, ps.charPos, pos - ps.charPos, "yes")) {
  3066.                                 this.standalone = true;
  3067.                             }
  3068.                             else if (XmlConvert.StrEqual(ps.chars, ps.charPos, pos - ps.charPos, "no")) {
  3069.                                 this.standalone = false;
  3070.                             }
  3071.                             else {
  3072.                                 Debug.Assert(!isTextDecl);
  3073.                                 Throw(Res.Xml_InvalidXmlDecl, ps.LineNo, ps.LinePos - 1);
  3074.                             }
  3075.                             if (!isTextDecl) {
  3076.                                 attr.SetValue(ps.chars, ps.charPos, pos - ps.charPos);
  3077.                             }
  3078.                             xmlDeclState = 3;
  3079.                             break;
  3080.                         default:
  3081.                             Debug.Assert(false);
  3082.                             break;
  3083.                     }
  3084.                     sb.Append(chars, ps.charPos, pos - ps.charPos);
  3085.                     sb.Append(quoteChar);
  3086.                     ps.charPos = pos + 1;
  3087.                     continue;
  3088.                 }
  3089.                 else if (pos == ps.charsUsed) {
  3090.                     if (ReadData() != 0) {
  3091.                         goto Continue;
  3092.                     }
  3093.                     else {
  3094.                         Throw(Res.Xml_UnclosedQuote);
  3095.                     }
  3096.                 }
  3097.                 else {
  3098.                     Throw(isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl);
  3099.                 }
  3100.                 ReadData:
  3101.                
  3102.                 if (ps.isEof || ReadData() == 0) {
  3103.                     Throw(Res.Xml_UnexpectedEOF1);
  3104.                 }
  3105.             }
  3106.             NoXmlDecl:
  3107.            
  3108.             // no xml declaration
  3109.             if (!isTextDecl) {
  3110.                 parsingFunction = nextParsingFunction;
  3111.             }
  3112.             if (afterResetState) {
  3113.                 // check for invalid encoding switches to default encoding
  3114.                 int codePage = ps.encoding.CodePage;
  3115.                 if (codePage != Encoding.UTF8.CodePage && codePage != Encoding.Unicode.CodePage && codePage != Encoding.BigEndianUnicode.CodePage && !(ps.encoding is Ucs4Encoding)) {
  3116.                     Throw(Res.Xml_EncodingSwitchAfterResetState, (ps.encoding.GetByteCount("A") == 1) ? "UTF-8" : "UTF-16");
  3117.                 }
  3118.             }
  3119.             if (ps.decoder is SafeAsciiDecoder) {
  3120.                 SwitchEncodingToUTF8();
  3121.             }
  3122.             ps.appendMode = false;
  3123.             return false;
  3124.         }
  3125.        
  3126.         // Parses the document content
  3127.         private bool ParseDocumentContent()
  3128.         {
  3129.            
  3130.             for (;;) {
  3131.                 bool needMoreChars = false;
  3132.                 int pos = ps.charPos;
  3133.                 char[] chars = ps.chars;
  3134.                
  3135.                 // some tag
  3136.                 if (chars[pos] == '<') {
  3137.                     needMoreChars = true;
  3138.                     if (ps.charsUsed - pos < 4)
  3139.                         // minimum "<a/>"
  3140.                         goto ReadData;
  3141.                     pos++;
  3142.                     switch (chars[pos]) {
  3143.                         case '?':
  3144.                             // processing instruction
  3145.                             ps.charPos = pos + 1;
  3146.                             if (ParsePI()) {
  3147.                                 return true;
  3148.                             }
  3149.                             continue;
  3150.                         case '!':
  3151.                             pos++;
  3152.                             if (ps.charsUsed - pos < 2)
  3153.                                 // minimum characters expected "--"
  3154.                                 goto ReadData;
  3155.                             // comment
  3156.                             if (chars[pos] == '-') {
  3157.                                 if (chars[pos + 1] == '-') {
  3158.                                     ps.charPos = pos + 2;
  3159.                                     if (ParseComment()) {
  3160.                                         return true;
  3161.                                     }
  3162.                                     continue;
  3163.                                 }
  3164.                                 else {
  3165.                                     ThrowUnexpectedToken(pos + 1, "-");
  3166.                                 }
  3167.                             }
  3168.                             // CDATA section
  3169.                             else if (chars[pos] == '[') {
  3170.                                 if (fragmentType != XmlNodeType.Document) {
  3171.                                     pos++;
  3172.                                     if (ps.charsUsed - pos < 6) {
  3173.                                         goto ReadData;
  3174.                                     }
  3175.                                     if (XmlConvert.StrEqual(chars, pos, 6, "CDATA[")) {
  3176.                                         ps.charPos = pos + 6;
  3177.                                         ParseCData();
  3178.                                         if (fragmentType == XmlNodeType.None) {
  3179.                                             fragmentType = XmlNodeType.Element;
  3180.                                         }
  3181.                                         return true;
  3182.                                     }
  3183.                                     else {
  3184.                                         ThrowUnexpectedToken(pos, "CDATA[");
  3185.                                     }
  3186.                                 }
  3187.                                 else {
  3188.                                     Throw(ps.charPos, Res.Xml_InvalidRootData);
  3189.                                 }
  3190.                             }
  3191.                             // DOCTYPE declaration
  3192.                             else {
  3193.                                 if (fragmentType == XmlNodeType.Document || fragmentType == XmlNodeType.None) {
  3194.                                     fragmentType = XmlNodeType.Document;
  3195.                                     ps.charPos = pos;
  3196.                                     ParseDoctypeDecl();
  3197.                                     return true;
  3198.                                 }
  3199.                                 else {
  3200.                                     if (ParseUnexpectedToken(pos) == "DOCTYPE") {
  3201.                                         Throw(Res.Xml_BadDTDLocation);
  3202.                                     }
  3203.                                     else {
  3204.                                         ThrowUnexpectedToken(pos, "<!--", "<[CDATA[");
  3205.                                     }
  3206.                                 }
  3207.                             }
  3208.                             break;
  3209.                         case '/':
  3210.                             Throw(pos + 1, Res.Xml_UnexpectedEndTag);
  3211.                             break;
  3212.                         default:
  3213.                             // document element start tag
  3214.                             if (rootElementParsed) {
  3215.                                 if (fragmentType == XmlNodeType.Document) {
  3216.                                     Throw(pos, Res.Xml_MultipleRoots);
  3217.                                 }
  3218.                                 if (fragmentType == XmlNodeType.None) {
  3219.                                     fragmentType = XmlNodeType.Element;
  3220.                                 }
  3221.                             }
  3222.                             ps.charPos = pos;
  3223.                             rootElementParsed = true;
  3224.                             ParseElement();
  3225.                             return true;
  3226.                     }
  3227.                 }
  3228.                 else if (chars[pos] == '&') {
  3229.                     if (fragmentType == XmlNodeType.Document) {
  3230.                         Throw(pos, Res.Xml_InvalidRootData);
  3231.                     }
  3232.                     else {
  3233.                         if (fragmentType == XmlNodeType.None) {
  3234.                             fragmentType = XmlNodeType.Element;
  3235.                         }
  3236.                         int i;
  3237.                         switch (HandleEntityReference(false, EntityExpandType.OnlyGeneral, out i)) {
  3238.                             case EntityType.Unexpanded:
  3239.                                 if (parsingFunction == ParsingFunction.EntityReference) {
  3240.                                     parsingFunction = nextParsingFunction;
  3241.                                 }
  3242.                                 ParseEntityReference();
  3243.                                 return true;
  3244.                             case EntityType.CharacterDec:
  3245.                             case EntityType.CharacterHex:
  3246.                             case EntityType.CharacterNamed:
  3247.                                 if (ParseText()) {
  3248.                                     return true;
  3249.                                 }
  3250.                                 continue;
  3251.                             default:
  3252.                                 chars = ps.chars;
  3253.                                 pos = ps.charPos;
  3254.                                 continue;
  3255.                         }
  3256.                     }
  3257.                 }
  3258.                 // end of buffer
  3259.                 else if (pos == ps.charsUsed || (v1Compat && chars[pos] == 0)) {
  3260.                     goto ReadData;
  3261.                 }
  3262.                 // something else -> root level whitespaces
  3263.                 else {
  3264.                     if (fragmentType == XmlNodeType.Document) {
  3265.                         if (ParseRootLevelWhitespace()) {
  3266.                             return true;
  3267.                         }
  3268.                     }
  3269.                     else {
  3270.                         if (ParseText()) {
  3271.                             if (fragmentType == XmlNodeType.None && curNode.type == XmlNodeType.Text) {
  3272.                                 fragmentType = XmlNodeType.Element;
  3273.                             }
  3274.                             return true;
  3275.                         }
  3276.                     }
  3277.                     chars = ps.chars;
  3278.                     pos = ps.charPos;
  3279.                     continue;
  3280.                 }
  3281.                
  3282.                 Debug.Assert(pos == ps.charsUsed && !ps.isEof);
  3283.                 ReadData:
  3284.                
  3285.                 // read new characters into the buffer
  3286.                 if (ReadData() != 0) {
  3287.                     pos = ps.charPos;
  3288.                 }
  3289.                 else {
  3290.                     if (needMoreChars) {
  3291.                         Throw(Res.Xml_InvalidRootData);
  3292.                     }
  3293.                    
  3294.                     if (InEntity) {
  3295.                         if (HandleEntityEnd(true)) {
  3296.                             SetupEndEntityNodeInContent();
  3297.                             return true;
  3298.                         }
  3299.                         continue;
  3300.                     }
  3301.                     Debug.Assert(index == 0);
  3302.                    
  3303.                     if (!rootElementParsed && fragmentType == XmlNodeType.Document) {
  3304.                         ThrowWithoutLineInfo(Res.Xml_MissingRoot);
  3305.                     }
  3306.                     if (fragmentType == XmlNodeType.None) {
  3307.                         fragmentType = rootElementParsed ? XmlNodeType.Document : XmlNodeType.Element;
  3308.                     }
  3309.                     OnEof();
  3310.                     return false;
  3311.                 }
  3312.                
  3313.                 pos = ps.charPos;
  3314.                 chars = ps.chars;
  3315.             }
  3316.         }
  3317.        
  3318.         // Parses element content
  3319.         private bool ParseElementContent()
  3320.         {
  3321.            
  3322.             for (;;) {
  3323.                 int pos = ps.charPos;
  3324.                 char[] chars = ps.chars;
  3325.                
  3326.                 switch (chars[pos]) {
  3327.                     case '<':
  3328.                         // some tag
  3329.                         switch (chars[pos + 1]) {
  3330.                             case '?':
  3331.                                 // processing instruction
  3332.                                 ps.charPos = pos + 2;
  3333.                                 if (ParsePI()) {
  3334.                                     return true;
  3335.                                 }
  3336.                                 continue;
  3337.                             case '!':
  3338.                                 pos += 2;
  3339.                                 if (ps.charsUsed - pos < 2)
  3340.                                     goto ReadData;
  3341.                                 // comment
  3342.                                 if (chars[pos] == '-') {
  3343.                                     if (chars[pos + 1] == '-') {
  3344.                                         ps.charPos = pos + 2;
  3345.                                         if (ParseComment()) {
  3346.                                             return true;
  3347.                                         }
  3348.                                         continue;
  3349.                                     }
  3350.                                     else {
  3351.                                         ThrowUnexpectedToken(pos + 1, "-");
  3352.                                     }
  3353.                                 }
  3354.                                 // CDATA section
  3355.                                 else if (chars[pos] == '[') {
  3356.                                     pos++;
  3357.                                     if (ps.charsUsed - pos < 6) {
  3358.                                         goto ReadData;
  3359.                                     }
  3360.                                     if (XmlConvert.StrEqual(chars, pos, 6, "CDATA[")) {
  3361.                                         ps.charPos = pos + 6;
  3362.                                         ParseCData();
  3363.                                         return true;
  3364.                                     }
  3365.                                     else {
  3366.                                         ThrowUnexpectedToken(pos, "CDATA[");
  3367.                                     }
  3368.                                 }
  3369.                                 else {
  3370.                                    
  3371.                                     if (ParseUnexpectedToken(pos) == "DOCTYPE") {
  3372.                                         Throw(Res.Xml_BadDTDLocation);
  3373.                                     }
  3374.                                     else {
  3375.                                         ThrowUnexpectedToken(pos, "<!--", "<[CDATA[");
  3376.                                     }
  3377.                                 }
  3378.                                 break;
  3379.                             case '/':
  3380.                                 // element end tag
  3381.                                 ps.charPos = pos + 2;
  3382.                                 ParseEndElement();
  3383.                                 return true;
  3384.                             default:
  3385.                                 // end of buffer
  3386.                                 if (pos + 1 == ps.charsUsed) {
  3387.                                     goto ReadData;
  3388.                                 }
  3389.                                 else {
  3390.                                     // element start tag
  3391.                                     ps.charPos = pos + 1;
  3392.                                     ParseElement();
  3393.                                     return true;
  3394.                                 }
  3395.                                 break;
  3396.                         }
  3397.                         break;
  3398.                     case '&':
  3399.                         if (ParseText()) {
  3400.                             return true;
  3401.                         }
  3402.                         continue;
  3403.                     default:
  3404.                         // end of buffer
  3405.                         if (pos == ps.charsUsed) {
  3406.                             goto ReadData;
  3407.                         }
  3408.                         else {
  3409.                             // text node, whitespace or entity reference
  3410.                             if (ParseText()) {
  3411.                                 return true;
  3412.                             }
  3413.                             continue;
  3414.                         }
  3415.                         break;
  3416.                 }
  3417.                 ReadData:
  3418.                
  3419.                 // read new characters into the buffer
  3420.                 if (ReadData() == 0) {
  3421.                     if (ps.charsUsed - ps.charPos != 0) {
  3422.                         ThrowUnclosedElements();
  3423.                     }
  3424.                     if (!InEntity) {
  3425.                         if (index == 0 && fragmentType != XmlNodeType.Document) {
  3426.                             OnEof();
  3427.                             return false;
  3428.                         }
  3429.                         ThrowUnclosedElements();
  3430.                     }
  3431.                     if (HandleEntityEnd(true)) {
  3432.                         SetupEndEntityNodeInContent();
  3433.                         return true;
  3434.                     }
  3435.                 }
  3436.             }
  3437.         }
  3438.        
  3439.         private void ThrowUnclosedElements()
  3440.         {
  3441.             if (index == 0 && curNode.type != XmlNodeType.Element) {
  3442.                 Throw(ps.charsUsed, Res.Xml_UnexpectedEOF1);
  3443.             }
  3444.             else {
  3445.                 int i = (parsingFunction == ParsingFunction.InIncrementalRead) ? index : index - 1;
  3446.                 stringBuilder.Length = 0;
  3447.                 for (; i >= 0; i--) {
  3448.                     NodeData el = nodes[i];
  3449.                     if (el.type != XmlNodeType.Element) {
  3450.                         continue;
  3451.                     }
  3452.                     stringBuilder.Append(el.GetNameWPrefix(nameTable));
  3453.                     if (i > 0) {
  3454.                         stringBuilder.Append(", ");
  3455.                     }
  3456.                     else {
  3457.                         stringBuilder.Append(".");
  3458.                     }
  3459.                 }
  3460.                 Throw(ps.charsUsed, Res.Xml_UnexpectedEOFInElementContent, stringBuilder.ToString());
  3461.             }
  3462.         }
  3463.        
  3464.         // Parses the element start tag
  3465.         private void ParseElement()
  3466.         {
  3467.             int pos = ps.charPos;
  3468.             char[] chars = ps.chars;
  3469.             int colonPos = -1;
  3470.            
  3471.             curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  3472.             ContinueStartName:
  3473.            
  3474.             // PERF: we intentionally don't call ParseQName here to parse the element name unless a special
  3475.             // case occurs (like end of buffer, invalid name char)
  3476.             // check element name start char
  3477.             unsafe {
  3478.                 if (!((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCStartName) != 0)) {
  3479.                     goto ParseQNameSlow;
  3480.                 }
  3481.                 pos++;
  3482.             }
  3483.             ContinueName:
  3484.            
  3485.             unsafe {
  3486.                 // parse element name
  3487.                 while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCName) != 0)) {
  3488.                     pos++;
  3489.                 }
  3490.             }
  3491.            
  3492.             // colon -> save prefix end position and check next char if it's name start char
  3493.             if (chars[pos] == ':') {
  3494.                 if (colonPos != -1) {
  3495.                     if (supportNamespaces) {
  3496.                         Throw(pos, Res.Xml_BadNameChar, XmlException.BuildCharExceptionStr(':'));
  3497.                     }
  3498.                     else {
  3499.                         pos++;
  3500.                         goto ContinueName;
  3501.                     }
  3502.                 }
  3503.                 else {
  3504.                     colonPos = pos;
  3505.                     pos++;
  3506.                     goto ContinueStartName;
  3507.                 }
  3508.             }
  3509.             else if (pos < ps.charsUsed) {
  3510.                 goto SetElement;
  3511.             }
  3512.             ParseQNameSlow:
  3513.            
  3514.             pos = ParseQName(out colonPos);
  3515.             chars = ps.chars;
  3516.             SetElement:
  3517.            
  3518.             // push namespace context
  3519.             namespaceManager.PushScope();
  3520.            
  3521.             // init the NodeData class
  3522.             if (colonPos == -1 || !supportNamespaces) {
  3523.                 curNode.SetNamedNode(XmlNodeType.Element, nameTable.Add(chars, ps.charPos, pos - ps.charPos));
  3524.             }
  3525.             else {
  3526.                 int startPos = ps.charPos;
  3527.                 int prefixLen = colonPos - startPos;
  3528.                 if (prefixLen == lastPrefix.Length && XmlConvert.StrEqual(chars, startPos, prefixLen, lastPrefix)) {
  3529.                     curNode.SetNamedNode(XmlNodeType.Element, nameTable.Add(chars, colonPos + 1, pos - colonPos - 1), lastPrefix, null);
  3530.                 }
  3531.                 else {
  3532.                     curNode.SetNamedNode(XmlNodeType.Element, nameTable.Add(chars, colonPos + 1, pos - colonPos - 1), nameTable.Add(chars, ps.charPos, prefixLen), null);
  3533.                     lastPrefix = curNode.prefix;
  3534.                 }
  3535.             }
  3536.            
  3537.             char ch = chars[pos];
  3538.             // white space after element name -> there are probably some attributes
  3539.             bool isWs;
  3540.             unsafe {
  3541.                 isWs = ((xmlCharType.charProperties[ch] & XmlCharType.fWhitespace) != 0);
  3542.             }
  3543.             if (isWs) {
  3544.                 ps.charPos = pos;
  3545.                 ParseAttributes();
  3546.                 return;
  3547.             }
  3548.             // no attributes
  3549.             else {
  3550.                 // non-empty element
  3551.                 if (ch == '>') {
  3552.                     ps.charPos = pos + 1;
  3553.                     parsingFunction = ParsingFunction.MoveToElementContent;
  3554.                 }
  3555.                 // empty element
  3556.                 else if (ch == '/') {
  3557.                     if (pos + 1 == ps.charsUsed) {
  3558.                         ps.charPos = pos;
  3559.                         if (ReadData() == 0) {
  3560.                             Throw(pos, Res.Xml_UnexpectedEOF, ">");
  3561.                         }
  3562.                         pos = ps.charPos;
  3563.                         chars = ps.chars;
  3564.                     }
  3565.                     if (chars[pos + 1] == '>') {
  3566.                         curNode.IsEmptyElement = true;
  3567.                         nextParsingFunction = parsingFunction;
  3568.                         parsingFunction = ParsingFunction.PopEmptyElementContext;
  3569.                         ps.charPos = pos + 2;
  3570.                     }
  3571.                     else {
  3572.                         ThrowUnexpectedToken(pos, ">");
  3573.                     }
  3574.                 }
  3575.                 // something else after the element name
  3576.                 else {
  3577.                     Throw(pos, Res.Xml_BadNameChar, XmlException.BuildCharExceptionStr(ch));
  3578.                 }
  3579.                
  3580.                 // add default attributes & strip spaces in attributes with type other than CDATA
  3581.                 if (addDefaultAttributesAndNormalize) {
  3582.                     AddDefaultAttributesAndNormalize();
  3583.                 }
  3584.                
  3585.                 // lookup element namespace
  3586.                 ElementNamespaceLookup();
  3587.             }
  3588.         }
  3589.        
  3590.         private void AddDefaultAttributesAndNormalize()
  3591.         {
  3592.             Debug.Assert(curNode.type == XmlNodeType.Element);
  3593.             SchemaElementDecl elementDecl;
  3594.            
  3595.             qName.Init(curNode.localName, curNode.prefix);
  3596.             SchemaInfo dtdSchemaInfo = dtdParserProxy.DtdSchemaInfo;
  3597.             if ((elementDecl = dtdSchemaInfo.GetElementDecl(qName)) == null) {
  3598.                 if ((elementDecl = (SchemaElementDecl)dtdSchemaInfo.UndeclaredElementDecls[qName]) == null) {
  3599.                     return;
  3600.                 }
  3601.             }
  3602.            
  3603.             // fix non-CDATA attribute value
  3604.             if (normalize && elementDecl.HasNonCDataAttribute) {
  3605.                 // go through the attributes and normalize it if not CDATA type
  3606.                 for (int i = index + 1; i < index + 1 + attrCount; i++) {
  3607.                     NodeData attr = nodes[i];
  3608.                     qName.Init(attr.localName, attr.prefix);
  3609.                     SchemaAttDef attrDef = elementDecl.GetAttDef(qName);
  3610.                     if (attrDef != null && attrDef.SchemaType.Datatype.TokenizedType != XmlTokenizedType.CDATA) {
  3611.                         if (DtdValidation && standalone && attrDef.IsDeclaredInExternal) {
  3612.                             // VC constraint:
  3613.                             // The standalone document declaration must have the value "no" if any external markup declarations
  3614.                             // contain declarations of attributes with values subject to normalization, where the attribute appears in
  3615.                             // the document with a value which will change as a result of normalization,
  3616.                             string oldValue = attr.StringValue;
  3617.                             attr.TrimSpacesInValue();
  3618.                            
  3619.                             if (oldValue != attr.StringValue) {
  3620.                                 SendValidationEvent(XmlSeverityType.Error, Res.Sch_StandAloneNormalization, attr.GetNameWPrefix(nameTable), attr.LineNo, attr.LinePos);
  3621.                             }
  3622.                         }
  3623.                         else {
  3624.                             attr.TrimSpacesInValue();
  3625.                         }
  3626.                     }
  3627.                 }
  3628.             }
  3629.            
  3630.             // add default attributes
  3631.             SchemaAttDef[] defaultAttributes = elementDecl.DefaultAttDefs;
  3632.             if (defaultAttributes != null) {
  3633.                 int originalAttrCount = attrCount;
  3634.                 for (int i = 0; i < defaultAttributes.Length; i++) {
  3635.                     SchemaAttDef attrDef = defaultAttributes[i];
  3636.                     if (AddDefaultAttribute(attrDef, true)) {
  3637.                         if (DtdValidation && standalone && attrDef.IsDeclaredInExternal) {
  3638.                             SendValidationEvent(XmlSeverityType.Error, Res.Sch_UnSpecifiedDefaultAttributeInExternalStandalone, attrDef.Name.Name, curNode.LineNo, curNode.LinePos);
  3639.                         }
  3640.                     }
  3641.                 }
  3642.                
  3643.                 if (originalAttrCount == 0 && attrNeedNamespaceLookup) {
  3644.                     AttributeNamespaceLookup();
  3645.                     attrNeedNamespaceLookup = false;
  3646.                 }
  3647.             }
  3648.         }
  3649.        
  3650.         // parses the element end tag
  3651.         private void ParseEndElement()
  3652.         {
  3653.             // check if the end tag name equals start tag name
  3654.             NodeData startTagNode = nodes[index - 1];
  3655.            
  3656.             int prefLen = startTagNode.prefix.Length;
  3657.             int locLen = startTagNode.localName.Length;
  3658.            
  3659.             while (ps.charsUsed - ps.charPos < prefLen + locLen + 1) {
  3660.                 if (ReadData() == 0) {
  3661.                     break;
  3662.                 }
  3663.             }
  3664.            
  3665.             int nameLen;
  3666.             char[] chars = ps.chars;
  3667.             if (startTagNode.prefix.Length == 0) {
  3668.                 if (!XmlConvert.StrEqual(chars, ps.charPos, locLen, startTagNode.localName)) {
  3669.                     ThrowTagMismatch(startTagNode);
  3670.                 }
  3671.                 nameLen = locLen;
  3672.             }
  3673.             else {
  3674.                 int colonPos = ps.charPos + prefLen;
  3675.                 if (!XmlConvert.StrEqual(chars, ps.charPos, prefLen, startTagNode.prefix) || chars[colonPos] != ':' || !XmlConvert.StrEqual(chars, colonPos + 1, locLen, startTagNode.localName)) {
  3676.                     ThrowTagMismatch(startTagNode);
  3677.                 }
  3678.                 nameLen = locLen + prefLen + 1;
  3679.             }
  3680.            
  3681.             int pos;
  3682.             for (;;) {
  3683.                 pos = ps.charPos + nameLen;
  3684.                 chars = ps.chars;
  3685.                
  3686.                 if (pos == ps.charsUsed) {
  3687.                     goto ReadData;
  3688.                 }
  3689.                 unsafe {
  3690.                     if ((((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCName) != 0) || (chars[pos]) == ':')) {
  3691.                         ThrowTagMismatch(startTagNode);
  3692.                     }
  3693.                    
  3694.                     // eat whitespaces
  3695.                     while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fWhitespace) != 0)) {
  3696.                         pos++;
  3697.                     }
  3698.                 }
  3699.                
  3700.                 if (chars[pos] == '>') {
  3701.                     break;
  3702.                 }
  3703.                 else if (pos == ps.charsUsed) {
  3704.                     goto ReadData;
  3705.                 }
  3706.                 else {
  3707.                     ThrowUnexpectedToken(pos, ">");
  3708.                 }
  3709.                
  3710.                 Debug.Assert(false, "We should never get to this point.");
  3711.                 ReadData:
  3712.                
  3713.                 if (ReadData() == 0) {
  3714.                     ThrowUnclosedElements();
  3715.                 }
  3716.             }
  3717.            
  3718.             Debug.Assert(index > 0);
  3719.             index--;
  3720.             curNode = nodes[index];
  3721.            
  3722.             // set the element data
  3723.             Debug.Assert(curNode == startTagNode);
  3724.             startTagNode.SetLineInfo(ps.LineNo, ps.LinePos);
  3725.             startTagNode.type = XmlNodeType.EndElement;
  3726.            
  3727.             ps.charPos = pos + 1;
  3728.            
  3729.             // set next parsing function
  3730.             nextParsingFunction = (index > 0) ? parsingFunction : ParsingFunction.DocumentContent;
  3731.             parsingFunction = ParsingFunction.PopElementContext;
  3732.         }
  3733.        
  3734.         private void ThrowTagMismatch(NodeData startTag)
  3735.         {
  3736.             if (startTag.type == XmlNodeType.Element) {
  3737.                 // parse the bad name
  3738.                 int colonPos;
  3739.                 int endPos = ParseQName(out colonPos);
  3740.                
  3741.                 string[] args = new string[3];
  3742.                 args[0] = startTag.GetNameWPrefix(nameTable);
  3743.                 args[1] = startTag.lineInfo.lineNo.ToString(CultureInfo.InvariantCulture);
  3744.                 args[2] = new string(ps.chars, ps.charPos, endPos - ps.charPos);
  3745.                 Throw(Res.Xml_TagMismatch, args);
  3746.             }
  3747.             else {
  3748.                 Debug.Assert(startTag.type == XmlNodeType.EntityReference);
  3749.                 Throw(Res.Xml_UnexpectedEndTag);
  3750.             }
  3751.         }
  3752.        
  3753.         // Reads the attributes
  3754.         private void ParseAttributes()
  3755.         {
  3756.             int pos = ps.charPos;
  3757.             char[] chars = ps.chars;
  3758.             NodeData attr = null;
  3759.            
  3760.             Debug.Assert(attrCount == 0);
  3761.            
  3762.             for (;;) {
  3763.                 // eat whitespaces
  3764.                 int lineNoDelta = 0;
  3765.                 char tmpch0;
  3766.                 unsafe {
  3767.                     while (((xmlCharType.charProperties[tmpch0 = chars[pos]] & XmlCharType.fWhitespace) != 0)) {
  3768.                         if (tmpch0 == (char)10) {
  3769.                             OnNewLine(pos + 1);
  3770.                             lineNoDelta++;
  3771.                         }
  3772.                         else if (tmpch0 == (char)13) {
  3773.                             if (chars[pos + 1] == (char)10) {
  3774.                                 OnNewLine(pos + 2);
  3775.                                 lineNoDelta++;
  3776.                                 pos++;
  3777.                             }
  3778.                             else if (pos + 1 != ps.charsUsed) {
  3779.                                 OnNewLine(pos + 1);
  3780.                                 lineNoDelta++;
  3781.                             }
  3782.                             else {
  3783.                                 ps.charPos = pos;
  3784.                                 goto ReadData;
  3785.                             }
  3786.                         }
  3787.                         pos++;
  3788.                     }
  3789.                 }
  3790.                
  3791.                 char tmpch1;
  3792.                 bool isNCStartName;
  3793.                 unsafe {
  3794.                     isNCStartName = ((xmlCharType.charProperties[tmpch1 = chars[pos]] & XmlCharType.fNCStartName) != 0);
  3795.                 }
  3796.                 if (!isNCStartName) {
  3797.                     // element end
  3798.                     if (tmpch1 == '>') {
  3799.                         Debug.Assert(curNode.type == XmlNodeType.Element);
  3800.                         ps.charPos = pos + 1;
  3801.                         parsingFunction = ParsingFunction.MoveToElementContent;
  3802.                         goto End;
  3803.                     }
  3804.                     // empty element end
  3805.                     else if (tmpch1 == '/') {
  3806.                         Debug.Assert(curNode.type == XmlNodeType.Element);
  3807.                         if (pos + 1 == ps.charsUsed) {
  3808.                             goto ReadData;
  3809.                         }
  3810.                         if (chars[pos + 1] == '>') {
  3811.                             ps.charPos = pos + 2;
  3812.                             curNode.IsEmptyElement = true;
  3813.                             nextParsingFunction = parsingFunction;
  3814.                             parsingFunction = ParsingFunction.PopEmptyElementContext;
  3815.                             goto End;
  3816.                         }
  3817.                         else {
  3818.                             ThrowUnexpectedToken(pos + 1, ">");
  3819.                         }
  3820.                     }
  3821.                     else if (pos == ps.charsUsed) {
  3822.                         goto ReadData;
  3823.                     }
  3824.                     else if (tmpch1 != ':' || supportNamespaces) {
  3825.                         Throw(pos, Res.Xml_BadStartNameChar, XmlException.BuildCharExceptionStr(tmpch1));
  3826.                     }
  3827.                 }
  3828.                
  3829.                 if (pos == ps.charPos) {
  3830.                     Throw(Res.Xml_ExpectingWhiteSpace, ParseUnexpectedToken());
  3831.                 }
  3832.                 ps.charPos = pos;
  3833.                
  3834.                 // save attribute name line position
  3835.                 int attrNameLinePos = ps.LinePos;
  3836.                
  3837.                 #if DEBUG
  3838.                 int attrNameLineNo = ps.LineNo;
  3839.                 #endif
  3840.                
  3841.                 // parse attribute name
  3842.                 int colonPos = -1;
  3843.                
  3844.                 // PERF: we intentionally don't call ParseQName here to parse the element name unless a special
  3845.                 // case occurs (like end of buffer, invalid name char)
  3846.                 pos++;
  3847.                 ContinueParseName:
  3848.                 // start name char has already been checked
  3849.                 // parse attribute name
  3850.                 char tmpch2;
  3851.                 unsafe {
  3852.                     while (((xmlCharType.charProperties[tmpch2 = chars[pos]] & XmlCharType.fNCName) != 0)) {
  3853.                         pos++;
  3854.                     }
  3855.                 }
  3856.                
  3857.                 // colon -> save prefix end position and check next char if it's name start char
  3858.                 if (tmpch2 == ':') {
  3859.                     if (colonPos != -1) {
  3860.                         if (supportNamespaces) {
  3861.                             Throw(pos, Res.Xml_BadNameChar, XmlException.BuildCharExceptionStr(':'));
  3862.                         }
  3863.                         else {
  3864.                             pos++;
  3865.                             goto ContinueParseName;
  3866.                         }
  3867.                     }
  3868.                     else {
  3869.                         colonPos = pos;
  3870.                         pos++;
  3871.                         unsafe {
  3872.                             if (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCStartName) != 0)) {
  3873.                                 pos++;
  3874.                                 goto ContinueParseName;
  3875.                             }
  3876.                         }
  3877.                         pos = ParseQName(out colonPos);
  3878.                         chars = ps.chars;
  3879.                     }
  3880.                 }
  3881.                 else if (pos == ps.charsUsed) {
  3882.                     pos = ParseQName(out colonPos);
  3883.                     chars = ps.chars;
  3884.                 }
  3885.                
  3886.                 attr = AddAttribute(pos, colonPos);
  3887.                 attr.SetLineInfo(ps.LineNo, attrNameLinePos);
  3888.                
  3889.                 #if DEBUG
  3890.                 Debug.Assert(attrNameLineNo == ps.LineNo);
  3891.                 #endif
  3892.                
  3893.                 // parse equals and quote char;
  3894.                 if (chars[pos] != '=') {
  3895.                     ps.charPos = pos;
  3896.                     EatWhitespaces(null);
  3897.                     pos = ps.charPos;
  3898.                     if (chars[pos] != '=') {
  3899.                         ThrowUnexpectedToken("=");
  3900.                     }
  3901.                 }
  3902.                 pos++;
  3903.                
  3904.                 char quoteChar = chars[pos];
  3905.                 if (quoteChar != '"' && quoteChar != '\'') {
  3906.                     ps.charPos = pos;
  3907.                     EatWhitespaces(null);
  3908.                     pos = ps.charPos;
  3909.                     quoteChar = chars[pos];
  3910.                     if (quoteChar != '"' && quoteChar != '\'') {
  3911.                         ThrowUnexpectedToken("\"", "'");
  3912.                     }
  3913.                 }
  3914.                 pos++;
  3915.                 ps.charPos = pos;
  3916.                
  3917.                 attr.quoteChar = quoteChar;
  3918.                 attr.SetLineInfo2(ps.LineNo, ps.LinePos);
  3919.                
  3920.                 // parse attribute value
  3921.                 char tmpch3;
  3922.                 unsafe {
  3923.                     while (((xmlCharType.charProperties[tmpch3 = chars[pos]] & XmlCharType.fAttrValue) != 0)) {
  3924.                         pos++;
  3925.                     }
  3926.                 }
  3927.                
  3928.                 if (tmpch3 == quoteChar) {
  3929.                     #if DEBUG
  3930.                     if (normalize) {
  3931.                         string val = new string(chars, ps.charPos, pos - ps.charPos);
  3932.                         Debug.Assert(val == XmlComplianceUtil.CDataNormalize(val), "The attribute value is not CDATA normalized!");
  3933.                     }
  3934.                     #endif
  3935.                     attr.SetValue(chars, ps.charPos, pos - ps.charPos);
  3936.                     pos++;
  3937.                     ps.charPos = pos;
  3938.                 }
  3939.                 else {
  3940.                     ParseAttributeValueSlow(pos, quoteChar, attr);
  3941.                     pos = ps.charPos;
  3942.                     chars = ps.chars;
  3943.                 }
  3944.                
  3945.                 // handle special attributes:
  3946.                 if (attr.prefix.Length == 0) {
  3947.                     // default namespace declaration
  3948.                     if (Ref.Equal(attr.localName, XmlNs)) {
  3949.                         OnDefaultNamespaceDecl(attr);
  3950.                     }
  3951.                 }
  3952.                 else {
  3953.                     // prefixed namespace declaration
  3954.                     if (Ref.Equal(attr.prefix, XmlNs)) {
  3955.                         OnNamespaceDecl(attr);
  3956.                     }
  3957.                     // xml: attribute
  3958.                     else if (Ref.Equal(attr.prefix, Xml)) {
  3959.                         OnXmlReservedAttribute(attr);
  3960.                     }
  3961.                 }
  3962.                 continue;
  3963.                 ReadData:
  3964.                
  3965.                 ps.lineNo -= lineNoDelta;
  3966.                 if (ReadData() != 0) {
  3967.                     pos = ps.charPos;
  3968.                     chars = ps.chars;
  3969.                 }
  3970.                 else {
  3971.                     ThrowUnclosedElements();
  3972.                 }
  3973.             }
  3974.             End:
  3975.            
  3976.             if (addDefaultAttributesAndNormalize) {
  3977.                 AddDefaultAttributesAndNormalize();
  3978.             }
  3979.             // lookup namespaces: element
  3980.             ElementNamespaceLookup();
  3981.            
  3982.             // lookup namespaces: attributes
  3983.             if (attrNeedNamespaceLookup) {
  3984.                 AttributeNamespaceLookup();
  3985.                 attrNeedNamespaceLookup = false;
  3986.             }
  3987.            
  3988.             // check duplicate attributes
  3989.             if (attrDuplWalkCount >= MaxAttrDuplWalkCount) {
  3990.                 AttributeDuplCheck();
  3991.             }
  3992.         }
  3993.        
  3994.         private void ElementNamespaceLookup()
  3995.         {
  3996.             Debug.Assert(curNode.type == XmlNodeType.Element);
  3997.             if (curNode.prefix.Length == 0) {
  3998.                 curNode.ns = xmlContext.defaultNamespace;
  3999.             }
  4000.             else {
  4001.                 curNode.ns = LookupNamespace(curNode);
  4002.             }
  4003.         }
  4004.        
  4005.         private void AttributeNamespaceLookup()
  4006.         {
  4007.             for (int i = index + 1; i < index + attrCount + 1; i++) {
  4008.                 NodeData at = nodes[i];
  4009.                 if (at.type == XmlNodeType.Attribute && at.prefix.Length > 0) {
  4010.                     at.ns = LookupNamespace(at);
  4011.                 }
  4012.             }
  4013.         }
  4014.        
  4015.         private void AttributeDuplCheck()
  4016.         {
  4017.             if (attrCount < MaxAttrDuplWalkCount) {
  4018.                 for (int i = index + 1; i < index + 1 + attrCount; i++) {
  4019.                     NodeData attr1 = nodes[i];
  4020.                     for (int j = i + 1; j < index + 1 + attrCount; j++) {
  4021.                         if (Ref.Equal(attr1.localName, nodes[j].localName) && Ref.Equal(attr1.ns, nodes[j].ns)) {
  4022.                             Throw(Res.Xml_DupAttributeName, nodes[j].GetNameWPrefix(nameTable), nodes[j].LineNo, nodes[j].LinePos);
  4023.                         }
  4024.                     }
  4025.                 }
  4026.             }
  4027.             else {
  4028.                 if (attrDuplSortingArray == null || attrDuplSortingArray.Length < attrCount) {
  4029.                     attrDuplSortingArray = new NodeData[attrCount];
  4030.                 }
  4031.                 Array.Copy(nodes, index + 1, attrDuplSortingArray, 0, attrCount);
  4032.                 Array.Sort(attrDuplSortingArray, 0, attrCount);
  4033.                
  4034.                 NodeData attr1 = attrDuplSortingArray[0];
  4035.                 for (int i = 1; i < attrCount; i++) {
  4036.                     NodeData attr2 = attrDuplSortingArray[i];
  4037.                     if (Ref.Equal(attr1.localName, attr2.localName) && Ref.Equal(attr1.ns, attr2.ns)) {
  4038.                         Throw(Res.Xml_DupAttributeName, attr2.GetNameWPrefix(nameTable), attr2.LineNo, attr2.LinePos);
  4039.                     }
  4040.                     attr1 = attr2;
  4041.                 }
  4042.             }
  4043.         }
  4044.        
  4045.         private void OnDefaultNamespaceDecl(NodeData attr)
  4046.         {
  4047.             if (!supportNamespaces) {
  4048.                 return;
  4049.             }
  4050.            
  4051.             string ns = attr.GetAtomizedValue(nameTable);
  4052.             attr.SetValue(ns);
  4053.             attr.ns = nameTable.Add(XmlReservedNs.NsXmlNs);
  4054.            
  4055.             if (!curNode.xmlContextPushed) {
  4056.                 PushXmlContext();
  4057.             }
  4058.             xmlContext.defaultNamespace = ns;
  4059.            
  4060.             AddNamespace(string.Empty, ns, attr);
  4061.         }
  4062.        
  4063.         private void OnNamespaceDecl(NodeData attr)
  4064.         {
  4065.             if (!supportNamespaces) {
  4066.                 return;
  4067.             }
  4068.             string ns = attr.GetAtomizedValue(nameTable);
  4069.             if (ns.Length == 0) {
  4070.                 Throw(Res.Xml_BadNamespaceDecl, attr.lineInfo2.lineNo, attr.lineInfo2.linePos - 1);
  4071.             }
  4072.             attr.SetValue(ns);
  4073.             AddNamespace(attr.localName, ns, attr);
  4074.         }
  4075.        
  4076.         private void OnXmlReservedAttribute(NodeData attr)
  4077.         {
  4078.             switch (attr.localName) {
  4079.                 case "space":
  4080.                     // xml:space
  4081.                     if (!curNode.xmlContextPushed) {
  4082.                         PushXmlContext();
  4083.                     }
  4084.                     switch (XmlConvert.TrimString(attr.StringValue)) {
  4085.                         case "preserve":
  4086.                             xmlContext.xmlSpace = XmlSpace.Preserve;
  4087.                             break;
  4088.                         case "default":
  4089.                             xmlContext.xmlSpace = XmlSpace.Default;
  4090.                             break;
  4091.                         default:
  4092.                             Throw(Res.Xml_InvalidXmlSpace, attr.StringValue, attr.lineInfo.lineNo, attr.lineInfo.linePos);
  4093.                             break;
  4094.                     }
  4095.                     break;
  4096.                 case "lang":
  4097.                     // xml:lang
  4098.                     if (!curNode.xmlContextPushed) {
  4099.                         PushXmlContext();
  4100.                     }
  4101.                     xmlContext.xmlLang = attr.StringValue;
  4102.                     break;
  4103.             }
  4104.         }
  4105.        
  4106.         private void ParseAttributeValueSlow(int curPos, char quoteChar, NodeData attr)
  4107.         {
  4108.             int pos = curPos;
  4109.             char[] chars = ps.chars;
  4110.             int attributeBaseEntityId = ps.entityId;
  4111.             int valueChunkStartPos = 0;
  4112.             LineInfo valueChunkLineInfo = new LineInfo(ps.lineNo, ps.LinePos);
  4113.             NodeData lastChunk = null;
  4114.            
  4115.             Debug.Assert(stringBuilder.Length == 0);
  4116.            
  4117.             for (;;) {
  4118.                 // parse the rest of the attribute value
  4119.                 unsafe {
  4120.                     while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue) != 0)) {
  4121.                         pos++;
  4122.                     }
  4123.                 }
  4124.                
  4125.                 if (pos - ps.charPos > 0) {
  4126.                     stringBuilder.Append(chars, ps.charPos, pos - ps.charPos);
  4127.                     ps.charPos = pos;
  4128.                 }
  4129.                
  4130.                 if (chars[pos] == quoteChar && attributeBaseEntityId == ps.entityId) {
  4131.                     break;
  4132.                 }
  4133.                 else {
  4134.                     switch (chars[pos]) {
  4135.                         case (char)10:
  4136.                             // eol
  4137.                             pos++;
  4138.                             OnNewLine(pos);
  4139.                             if (normalize) {
  4140.                                 stringBuilder.Append((char)32);
  4141.                                 // CDATA normalization of 0xA
  4142.                                 ps.charPos++;
  4143.                             }
  4144.                             continue;
  4145.                         case (char)13:
  4146.                             if (chars[pos + 1] == (char)10) {
  4147.                                 pos += 2;
  4148.                                 if (normalize) {
  4149.                                     stringBuilder.Append(ps.eolNormalized ? " " : " ");
  4150.                                     // CDATA normalization of 0xD 0xA
  4151.                                     ps.charPos = pos;
  4152.                                 }
  4153.                             }
  4154.                             else if (pos + 1 < ps.charsUsed || ps.isEof) {
  4155.                                 pos++;
  4156.                                 if (normalize) {
  4157.                                     stringBuilder.Append((char)32);
  4158.                                     // CDATA normalization of 0xD and 0xD 0xA
  4159.                                     ps.charPos = pos;
  4160.                                 }
  4161.                             }
  4162.                             else {
  4163.                                 goto ReadData;
  4164.                             }
  4165.                             OnNewLine(pos);
  4166.                             continue;
  4167.                         case (char)9:
  4168.                             // tab
  4169.                             pos++;
  4170.                             if (normalize) {
  4171.                                 stringBuilder.Append((char)32);
  4172.                                 // CDATA normalization of 0x9
  4173.                                 ps.charPos++;
  4174.                             }
  4175.                             continue;
  4176.                         case '"':
  4177.                         case '\'':
  4178.                         case '>':
  4179.                             pos++;
  4180.                             continue;
  4181.                         case '<':
  4182.                             // attribute values cannot contain '<'
  4183.                             Throw(pos, Res.Xml_BadAttributeChar, XmlException.BuildCharExceptionStr('<'));
  4184.                             break;
  4185.                         case '&':
  4186.                             // entity referece
  4187.                             if (pos - ps.charPos > 0) {
  4188.                                 stringBuilder.Append(chars, ps.charPos, pos - ps.charPos);
  4189.                             }
  4190.                             ps.charPos = pos;
  4191.                            
  4192.                             int enclosingEntityId = ps.entityId;
  4193.                             LineInfo entityLineInfo = new LineInfo(ps.lineNo, ps.LinePos + 1);
  4194.                             switch (HandleEntityReference(true, EntityExpandType.All, out pos)) {
  4195.                                 case EntityType.CharacterDec:
  4196.                                 case EntityType.CharacterHex:
  4197.                                 case EntityType.CharacterNamed:
  4198.                                     break;
  4199.                                 case EntityType.Unexpanded:
  4200.                                     if (parsingMode == ParsingMode.Full && ps.entityId == attributeBaseEntityId) {
  4201.                                         // construct text value chunk
  4202.                                         int valueChunkLen = stringBuilder.Length - valueChunkStartPos;
  4203.                                         if (valueChunkLen > 0) {
  4204.                                             NodeData textChunk = new NodeData();
  4205.                                             textChunk.lineInfo = valueChunkLineInfo;
  4206.                                             textChunk.depth = attr.depth + 1;
  4207.                                             textChunk.SetValueNode(XmlNodeType.Text, stringBuilder.ToString(valueChunkStartPos, valueChunkLen));
  4208.                                             AddAttributeChunkToList(attr, textChunk, ref lastChunk);
  4209.                                         }
  4210.                                        
  4211.                                         // parse entity name
  4212.                                         ps.charPos++;
  4213.                                         string entityName = ParseEntityName();
  4214.                                        
  4215.                                         // construct entity reference chunk
  4216.                                         NodeData entityChunk = new NodeData();
  4217.                                         entityChunk.lineInfo = entityLineInfo;
  4218.                                         entityChunk.depth = attr.depth + 1;
  4219.                                         entityChunk.SetNamedNode(XmlNodeType.EntityReference, entityName);
  4220.                                         AddAttributeChunkToList(attr, entityChunk, ref lastChunk);
  4221.                                        
  4222.                                         // append entity ref to the attribute value
  4223.                                         stringBuilder.Append('&');
  4224.                                         stringBuilder.Append(entityName);
  4225.                                         stringBuilder.Append(';');
  4226.                                        
  4227.                                         // update info for the next attribute value chunk
  4228.                                         valueChunkStartPos = stringBuilder.Length;
  4229.                                         valueChunkLineInfo.Set(ps.LineNo, ps.LinePos);
  4230.                                        
  4231.                                         fullAttrCleanup = true;
  4232.                                     }
  4233.                                     else {
  4234.                                         ps.charPos++;
  4235.                                         ParseEntityName();
  4236.                                     }
  4237.                                     pos = ps.charPos;
  4238.                                     break;
  4239.                                 case EntityType.ExpandedInAttribute:
  4240.                                     if (parsingMode == ParsingMode.Full && enclosingEntityId == attributeBaseEntityId) {
  4241.                                        
  4242.                                         // construct text value chunk
  4243.                                         int valueChunkLen = stringBuilder.Length - valueChunkStartPos;
  4244.                                         if (valueChunkLen > 0) {
  4245.                                             NodeData textChunk = new NodeData();
  4246.                                             textChunk.lineInfo = valueChunkLineInfo;
  4247.                                             textChunk.depth = attr.depth + 1;
  4248.                                             textChunk.SetValueNode(XmlNodeType.Text, stringBuilder.ToString(valueChunkStartPos, valueChunkLen));
  4249.                                             AddAttributeChunkToList(attr, textChunk, ref lastChunk);
  4250.                                         }
  4251.                                        
  4252.                                         // construct entity reference chunk
  4253.                                         NodeData entityChunk = new NodeData();
  4254.                                         entityChunk.lineInfo = entityLineInfo;
  4255.                                         entityChunk.depth = attr.depth + 1;
  4256.                                         entityChunk.SetNamedNode(XmlNodeType.EntityReference, ps.entity.Name.Name);
  4257.                                         AddAttributeChunkToList(attr, entityChunk, ref lastChunk);
  4258.                                        
  4259.                                         fullAttrCleanup = true;
  4260.                                        
  4261.                                         // Note: info for the next attribute value chunk will be updated once we
  4262.                                         // get out of the expanded entity
  4263.                                     }
  4264.                                     pos = ps.charPos;
  4265.                                     break;
  4266.                                 default:
  4267.                                     pos = ps.charPos;
  4268.                                     break;
  4269.                             }
  4270.                             chars = ps.chars;
  4271.                             continue;
  4272.                         default:
  4273.                             // end of buffer
  4274.                             if (pos == ps.charsUsed) {
  4275.                                 goto ReadData;
  4276.                             }
  4277.                             // surrogate chars
  4278.                             else {
  4279.                                 char ch = chars[pos];
  4280.                                 if (ch >= SurHighStart && ch <= SurHighEnd) {
  4281.                                     if (pos + 1 == ps.charsUsed) {
  4282.                                         goto ReadData;
  4283.                                     }
  4284.                                     pos++;
  4285.                                     if (chars[pos] >= SurLowStart && chars[pos] <= SurLowEnd) {
  4286.                                         pos++;
  4287.                                         continue;
  4288.                                     }
  4289.                                 }
  4290.                                 ThrowInvalidChar(pos, ch);
  4291.                                 break;
  4292.                             }
  4293.                             break;
  4294.                     }
  4295.                 }
  4296.                 ReadData:
  4297.                
  4298.                 // read new characters into the buffer
  4299.                 if (ReadData() == 0) {
  4300.                     if (ps.charsUsed - ps.charPos > 0) {
  4301.                         if (ps.chars[ps.charPos] != (char)13) {
  4302.                             Debug.Assert(false, "We should never get to this point.");
  4303.                             Throw(Res.Xml_UnexpectedEOF1);
  4304.                         }
  4305.                         Debug.Assert(ps.isEof);
  4306.                     }
  4307.                     else {
  4308.                         if (!InEntity) {
  4309.                             if (fragmentType == XmlNodeType.Attribute) {
  4310.                                 if (attributeBaseEntityId != ps.entityId) {
  4311.                                     Throw(Res.Xml_EntityRefNesting);
  4312.                                 }
  4313.                                 break;
  4314.                             }
  4315.                             Throw(Res.Xml_UnclosedQuote);
  4316.                         }
  4317.                         if (HandleEntityEnd(true)) {
  4318.                             // no EndEntity reporting while parsing attributes
  4319.                             Debug.Assert(false);
  4320.                             Throw(Res.Xml_InternalError);
  4321.                         }
  4322.                         // update info for the next attribute value chunk
  4323.                         if (attributeBaseEntityId == ps.entityId) {
  4324.                             valueChunkStartPos = stringBuilder.Length;
  4325.                             valueChunkLineInfo.Set(ps.LineNo, ps.LinePos);
  4326.                         }
  4327.                     }
  4328.                 }
  4329.                
  4330.                 pos = ps.charPos;
  4331.                 chars = ps.chars;
  4332.             }
  4333.            
  4334.             if (attr.nextAttrValueChunk != null) {
  4335.                 // construct last text value chunk
  4336.                 int valueChunkLen = stringBuilder.Length - valueChunkStartPos;
  4337.                 if (valueChunkLen > 0) {
  4338.                     NodeData textChunk = new NodeData();
  4339.                     textChunk.lineInfo = valueChunkLineInfo;
  4340.                     textChunk.depth = attr.depth + 1;
  4341.                     textChunk.SetValueNode(XmlNodeType.Text, stringBuilder.ToString(valueChunkStartPos, valueChunkLen));
  4342.                     AddAttributeChunkToList(attr, textChunk, ref lastChunk);
  4343.                 }
  4344.             }
  4345.            
  4346.             ps.charPos = pos + 1;
  4347.            
  4348.             attr.SetValue(stringBuilder.ToString());
  4349.             stringBuilder.Length = 0;
  4350.         }
  4351.        
  4352.         private void AddAttributeChunkToList(NodeData attr, NodeData chunk, ref NodeData lastChunk)
  4353.         {
  4354.             if (lastChunk == null) {
  4355.                 Debug.Assert(attr.nextAttrValueChunk == null);
  4356.                 lastChunk = chunk;
  4357.                 attr.nextAttrValueChunk = chunk;
  4358.             }
  4359.             else {
  4360.                 lastChunk.nextAttrValueChunk = chunk;
  4361.                 lastChunk = chunk;
  4362.             }
  4363.         }
  4364.        
  4365.         // Parses text or white space node.
  4366.         // Returns true if a node has been parsed and its data set to curNode.
  4367.         // Returns false when a white space has been parsed and ignored (according to current whitespace handling) or when parsing mode is not Full.
  4368.         // Also returns false if there is no text to be parsed.
  4369.         private bool ParseText()
  4370.         {
  4371.             int startPos;
  4372.             int endPos;
  4373.             int orChars = 0;
  4374.            
  4375.             // skip over the text if not in full parsing mode
  4376.             if (parsingMode != ParsingMode.Full) {
  4377.                 while (!ParseText(out startPos, out endPos, ref orChars))
  4378.                     ;
  4379.                 goto IgnoredNode;
  4380.             }
  4381.            
  4382.             curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  4383.             Debug.Assert(stringBuilder.Length == 0);
  4384.            
  4385.             // the whole value is in buffer
  4386.             if (ParseText(out startPos, out endPos, ref orChars)) {
  4387.                 if (endPos - startPos == 0) {
  4388.                     goto IgnoredNode;
  4389.                 }
  4390.                 XmlNodeType nodeType = GetTextNodeType(orChars);
  4391.                 if (nodeType == XmlNodeType.None) {
  4392.                     goto IgnoredNode;
  4393.                 }
  4394.                 Debug.Assert(endPos - startPos > 0);
  4395.                 curNode.SetValueNode(nodeType, ps.chars, startPos, endPos - startPos);
  4396.                 return true;
  4397.             }
  4398.             // only piece of the value was returned
  4399.             else {
  4400.                 // V1 compatibility mode -> cache the whole value
  4401.                 if (v1Compat) {
  4402.                     do {
  4403.                         stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  4404.                     }
  4405.                     while (!ParseText(out startPos, out endPos, ref orChars));
  4406.                     stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  4407.                    
  4408.                     Debug.Assert(stringBuilder.Length > 0);
  4409.                    
  4410.                     XmlNodeType nodeType = GetTextNodeType(orChars);
  4411.                     if (nodeType == XmlNodeType.None) {
  4412.                         stringBuilder.Length = 0;
  4413.                         goto IgnoredNode;
  4414.                     }
  4415.                    
  4416.                     curNode.SetValueNode(nodeType, stringBuilder.ToString());
  4417.                     stringBuilder.Length = 0;
  4418.                     return true;
  4419.                 }
  4420.                 // V2 reader -> do not cache the whole value yet, read only up to 4kB to decide whether the value is a whitespace
  4421.                 else {
  4422.                     bool fullValue = false;
  4423.                    
  4424.                     // if it's a partial text value, not a whitespace -> return
  4425.                     if (orChars > 32) {
  4426.                         Debug.Assert(endPos - startPos > 0);
  4427.                         curNode.SetValueNode(XmlNodeType.Text, ps.chars, startPos, endPos - startPos);
  4428.                         nextParsingFunction = parsingFunction;
  4429.                         parsingFunction = ParsingFunction.PartialTextValue;
  4430.                         return true;
  4431.                     }
  4432.                    
  4433.                     // partial whitespace -> read more data (up to 4kB) to decide if it is a whitespace or a text node
  4434.                     stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  4435.                     do {
  4436.                         fullValue = ParseText(out startPos, out endPos, ref orChars);
  4437.                         stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  4438.                     }
  4439.                     while (!fullValue && orChars <= 32 && stringBuilder.Length < MinWhitespaceLookahedCount);
  4440.                    
  4441.                     // determine the value node type
  4442.                     XmlNodeType nodeType = (stringBuilder.Length < MinWhitespaceLookahedCount) ? GetTextNodeType(orChars) : XmlNodeType.Text;
  4443.                     if (nodeType == XmlNodeType.None) {
  4444.                         // ignored whitespace -> skip over the rest of the value unless we already read it all
  4445.                         stringBuilder.Length = 0;
  4446.                         if (!fullValue) {
  4447.                             while (!ParseText(out startPos, out endPos, ref orChars))
  4448.                                 ;
  4449.                         }
  4450.                         goto IgnoredNode;
  4451.                     }
  4452.                     // set value to curNode
  4453.                     curNode.SetValueNode(nodeType, stringBuilder.ToString());
  4454.                     stringBuilder.Length = 0;
  4455.                    
  4456.                     // change parsing state if the full value was not parsed
  4457.                     if (!fullValue) {
  4458.                         nextParsingFunction = parsingFunction;
  4459.                         parsingFunction = ParsingFunction.PartialTextValue;
  4460.                     }
  4461.                     return true;
  4462.                 }
  4463.             }
  4464.             IgnoredNode:
  4465.            
  4466.             // ignored whitespace at the end of manually resolved entity
  4467.             if (parsingFunction == ParsingFunction.ReportEndEntity) {
  4468.                 SetupEndEntityNodeInContent();
  4469.                 parsingFunction = nextParsingFunction;
  4470.                 return true;
  4471.             }
  4472.             else if (parsingFunction == ParsingFunction.EntityReference) {
  4473.                 parsingFunction = nextNextParsingFunction;
  4474.                 ParseEntityReference();
  4475.                 return true;
  4476.             }
  4477.             return false;
  4478.         }
  4479.        
  4480.         // Parses a chunk of text starting at ps.charPos.
  4481.         // startPos .... start position of the text chunk that has been parsed (can differ from ps.charPos before the call)
  4482.         // endPos ...... end position of the text chunk that has been parsed (can differ from ps.charPos after the call)
  4483.         // ourOrChars .. all parsed character bigger or equal to 0x20 or-ed (|) into a single int. It can be used for whitespace detection
  4484.         // (the text has a non-whitespace character if outOrChars > 0x20).
  4485.         // Returns true when the whole value has been parsed. Return false when it needs to be called again to get a next chunk of value.
  4486.         private bool ParseText(out int startPos, out int endPos, ref int outOrChars)
  4487.         {
  4488.             char[] chars = ps.chars;
  4489.             int pos = ps.charPos;
  4490.             int rcount = 0;
  4491.             int rpos = -1;
  4492.             int orChars = outOrChars;
  4493.             char c;
  4494.            
  4495.             for (;;) {
  4496.                 // parse text content
  4497.                 unsafe {
  4498.                     while (((xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fText) != 0)) {
  4499.                         orChars |= (int)c;
  4500.                         pos++;
  4501.                     }
  4502.                 }
  4503.                
  4504.                 switch (c) {
  4505.                     case (char)9:
  4506.                         pos++;
  4507.                         continue;
  4508.                     case (char)10:
  4509.                         // eol
  4510.                         pos++;
  4511.                         OnNewLine(pos);
  4512.                         continue;
  4513.                     case (char)13:
  4514.                         if (chars[pos + 1] == (char)10) {
  4515.                             if (!ps.eolNormalized && parsingMode == ParsingMode.Full) {
  4516.                                 if (pos - ps.charPos > 0) {
  4517.                                     if (rcount == 0) {
  4518.                                         rcount = 1;
  4519.                                         rpos = pos;
  4520.                                     }
  4521.                                     else {
  4522.                                         ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  4523.                                         rpos = pos - rcount;
  4524.                                         rcount++;
  4525.                                     }
  4526.                                 }
  4527.                                 else {
  4528.                                     ps.charPos++;
  4529.                                 }
  4530.                             }
  4531.                             pos += 2;
  4532.                         }
  4533.                         else if (pos + 1 < ps.charsUsed || ps.isEof) {
  4534.                             if (!ps.eolNormalized) {
  4535.                                 chars[pos] = (char)10;
  4536.                                 // EOL normalization of 0xD
  4537.                             }
  4538.                             pos++;
  4539.                         }
  4540.                         else {
  4541.                             goto ReadData;
  4542.                         }
  4543.                         OnNewLine(pos);
  4544.                         continue;
  4545.                     case '<':
  4546.                         // some tag
  4547.                         goto ReturnPartialValue;
  4548.                         break;
  4549.                     case '&':
  4550.                         // entity reference
  4551.                         // try to parse char entity inline
  4552.                         int charRefEndPos;
  4553.                         int charCount;
  4554.                         EntityType entityType;
  4555.                         if ((charRefEndPos = ParseCharRefInline(pos, out charCount, out entityType)) > 0) {
  4556.                             if (rcount > 0) {
  4557.                                 ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  4558.                             }
  4559.                             rpos = pos - rcount;
  4560.                             rcount += (charRefEndPos - pos - charCount);
  4561.                             pos = charRefEndPos;
  4562.                            
  4563.                             if (!xmlCharType.IsWhiteSpace(chars[charRefEndPos - charCount]) || (v1Compat && entityType == EntityType.CharacterDec)) {
  4564.                                 orChars |= 255;
  4565.                             }
  4566.                         }
  4567.                         else {
  4568.                             if (pos > ps.charPos) {
  4569.                                 goto ReturnPartialValue;
  4570.                             }
  4571.                             switch (HandleEntityReference(false, EntityExpandType.All, out pos)) {
  4572.                                 case EntityType.Unexpanded:
  4573.                                     // make sure we will report EntityReference after the text node
  4574.                                     nextParsingFunction = parsingFunction;
  4575.                                     parsingFunction = ParsingFunction.EntityReference;
  4576.                                     // end the value (returns nothing)
  4577.                                     goto NoValue;
  4578.                                     break;
  4579.                                 case EntityType.CharacterDec:
  4580.                                     if (!v1Compat) {
  4581.                                         goto case EntityType.CharacterHex;
  4582.                                     }
  4583.                                     orChars |= 255;
  4584.                                     break;
  4585.                                 case EntityType.CharacterHex:
  4586.                                 case EntityType.CharacterNamed:
  4587.                                     if (!xmlCharType.IsWhiteSpace(ps.chars[pos - 1])) {
  4588.                                         orChars |= 255;
  4589.                                     }
  4590.                                     break;
  4591.                                 default:
  4592.                                     pos = ps.charPos;
  4593.                                     break;
  4594.                             }
  4595.                             chars = ps.chars;
  4596.                         }
  4597.                         continue;
  4598.                     case ']':
  4599.                         if (ps.charsUsed - pos < 3 && !ps.isEof) {
  4600.                             goto ReadData;
  4601.                         }
  4602.                         if (chars[pos + 1] == ']' && chars[pos + 2] == '>') {
  4603.                             Throw(pos, Res.Xml_CDATAEndInText);
  4604.                         }
  4605.                         orChars |= ']';
  4606.                         pos++;
  4607.                         continue;
  4608.                     default:
  4609.                         // end of buffer
  4610.                         if (pos == ps.charsUsed) {
  4611.                             goto ReadData;
  4612.                         }
  4613.                         // surrogate chars
  4614.                         else {
  4615.                             char ch = chars[pos];
  4616.                             if (ch >= SurHighStart && ch <= SurHighEnd) {
  4617.                                 if (pos + 1 == ps.charsUsed) {
  4618.                                     goto ReadData;
  4619.                                 }
  4620.                                 pos++;
  4621.                                 if (chars[pos] >= SurLowStart && chars[pos] <= SurLowEnd) {
  4622.                                     pos++;
  4623.                                     orChars |= ch;
  4624.                                     continue;
  4625.                                 }
  4626.                             }
  4627.                             int offset = pos - ps.charPos;
  4628.                             if (ZeroEndingStream(pos)) {
  4629.                                 chars = ps.chars;
  4630.                                 pos = ps.charPos + offset;
  4631.                                 goto ReturnPartialValue;
  4632.                             }
  4633.                             else {
  4634.                                 ThrowInvalidChar(ps.charPos + offset, ch);
  4635.                             }
  4636.                             break;
  4637.                         }
  4638.                         break;
  4639.                 }
  4640.                 ReadData:
  4641.                
  4642.                 if (pos > ps.charPos) {
  4643.                     goto ReturnPartialValue;
  4644.                 }
  4645.                 // read new characters into the buffer
  4646.                 if (ReadData() == 0) {
  4647.                     if (ps.charsUsed - ps.charPos > 0) {
  4648.                         if (ps.chars[ps.charPos] != (char)13) {
  4649.                             Debug.Assert(false, "We should never get to this point.");
  4650.                             Throw(Res.Xml_UnexpectedEOF1);
  4651.                         }
  4652.                         Debug.Assert(ps.isEof);
  4653.                     }
  4654.                     else {
  4655.                         if (!InEntity) {
  4656.                             // end the value (returns nothing)
  4657.                             goto NoValue;
  4658.                         }
  4659.                         if (HandleEntityEnd(true)) {
  4660.                             // report EndEntity after the text node
  4661.                             nextParsingFunction = parsingFunction;
  4662.                             parsingFunction = ParsingFunction.ReportEndEntity;
  4663.                             // end the value (returns nothing)
  4664.                             goto NoValue;
  4665.                         }
  4666.                     }
  4667.                 }
  4668.                 pos = ps.charPos;
  4669.                 chars = ps.chars;
  4670.                 continue;
  4671.             }
  4672.             NoValue:
  4673.             startPos = endPos = pos;
  4674.             return true;
  4675.             ReturnPartialValue:
  4676.            
  4677.             if (parsingMode == ParsingMode.Full && rcount > 0) {
  4678.                 ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  4679.             }
  4680.             startPos = ps.charPos;
  4681.             endPos = pos - rcount;
  4682.             ps.charPos = pos;
  4683.             outOrChars = orChars;
  4684.             return c == '<';
  4685.         }
  4686.        
  4687.         // When in ParsingState.PartialTextValue, this method parses and caches the rest of the value and stores it in curNode.
  4688.         void FinishPartialValue()
  4689.         {
  4690.             Debug.Assert(stringBuilder.Length == 0);
  4691.             Debug.Assert(parsingFunction == ParsingFunction.PartialTextValue || (parsingFunction == ParsingFunction.InReadValueChunk && incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue));
  4692.            
  4693.             curNode.CopyTo(readValueOffset, stringBuilder);
  4694.            
  4695.             int startPos;
  4696.             int endPos;
  4697.             int orChars = 0;
  4698.             while (!ParseText(out startPos, out endPos, ref orChars)) {
  4699.                 stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  4700.             }
  4701.             stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  4702.            
  4703.             Debug.Assert(stringBuilder.Length > 0);
  4704.             curNode.SetValue(stringBuilder.ToString());
  4705.             stringBuilder.Length = 0;
  4706.         }
  4707.        
  4708.         void FinishOtherValueIterator()
  4709.         {
  4710.             switch (parsingFunction) {
  4711.                 case ParsingFunction.InReadAttributeValue:
  4712.                     // do nothing, correct value is already in curNode
  4713.                     break;
  4714.                 case ParsingFunction.InReadValueChunk:
  4715.                     if (incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue) {
  4716.                         FinishPartialValue();
  4717.                         incReadState = IncrementalReadState.ReadValueChunk_OnCachedValue;
  4718.                     }
  4719.                     else {
  4720.                         if (readValueOffset > 0) {
  4721.                             curNode.SetValue(curNode.StringValue.Substring(readValueOffset));
  4722.                             readValueOffset = 0;
  4723.                         }
  4724.                     }
  4725.                     break;
  4726.                 case ParsingFunction.InReadContentAsBinary:
  4727.                 case ParsingFunction.InReadElementContentAsBinary:
  4728.                     switch (incReadState) {
  4729.                         case IncrementalReadState.ReadContentAsBinary_OnPartialValue:
  4730.                             FinishPartialValue();
  4731.                             incReadState = IncrementalReadState.ReadContentAsBinary_OnCachedValue;
  4732.                             break;
  4733.                         case IncrementalReadState.ReadContentAsBinary_OnCachedValue:
  4734.                             if (readValueOffset > 0) {
  4735.                                 curNode.SetValue(curNode.StringValue.Substring(readValueOffset));
  4736.                                 readValueOffset = 0;
  4737.                             }
  4738.                             break;
  4739.                         case IncrementalReadState.ReadContentAsBinary_End:
  4740.                             curNode.SetValue(string.Empty);
  4741.                             break;
  4742.                     }
  4743.                     break;
  4744.             }
  4745.         }
  4746.        
  4747.         // When in ParsingState.PartialTextValue, this method skips over the rest of the partial value.
  4748.         void SkipPartialTextValue()
  4749.         {
  4750.             Debug.Assert(parsingFunction == ParsingFunction.PartialTextValue || parsingFunction == ParsingFunction.InReadValueChunk || parsingFunction == ParsingFunction.InReadContentAsBinary || parsingFunction == ParsingFunction.InReadElementContentAsBinary);
  4751.             int startPos;
  4752.             int endPos;
  4753.             int orChars = 0;
  4754.            
  4755.             parsingFunction = nextParsingFunction;
  4756.             while (!ParseText(out startPos, out endPos, ref orChars))
  4757.                 ;
  4758.         }
  4759.        
  4760.         void FinishReadValueChunk()
  4761.         {
  4762.             Debug.Assert(parsingFunction == ParsingFunction.InReadValueChunk);
  4763.            
  4764.             readValueOffset = 0;
  4765.             if (incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue) {
  4766.                 Debug.Assert((index > 0) ? nextParsingFunction == ParsingFunction.ElementContent : nextParsingFunction == ParsingFunction.DocumentContent);
  4767.                 SkipPartialTextValue();
  4768.             }
  4769.             else {
  4770.                 parsingFunction = nextParsingFunction;
  4771.                 nextParsingFunction = nextNextParsingFunction;
  4772.             }
  4773.         }
  4774.        
  4775.         void FinishReadContentAsBinary()
  4776.         {
  4777.             Debug.Assert(parsingFunction == ParsingFunction.InReadContentAsBinary || parsingFunction == ParsingFunction.InReadElementContentAsBinary);
  4778.            
  4779.             readValueOffset = 0;
  4780.             if (incReadState == IncrementalReadState.ReadContentAsBinary_OnPartialValue) {
  4781.                 Debug.Assert((index > 0) ? nextParsingFunction == ParsingFunction.ElementContent : nextParsingFunction == ParsingFunction.DocumentContent);
  4782.                 SkipPartialTextValue();
  4783.             }
  4784.             else {
  4785.                 parsingFunction = nextParsingFunction;
  4786.                 nextParsingFunction = nextNextParsingFunction;
  4787.             }
  4788.             if (incReadState != IncrementalReadState.ReadContentAsBinary_End) {
  4789.                 while (MoveToNextContentNode(true))
  4790.                     ;
  4791.             }
  4792.         }
  4793.        
  4794.         void FinishReadElementContentAsBinary()
  4795.         {
  4796.             FinishReadContentAsBinary();
  4797.            
  4798.             if (curNode.type != XmlNodeType.EndElement) {
  4799.                 Throw(Res.Xml_InvalidNodeType, curNode.type.ToString());
  4800.             }
  4801.             // move off the end element
  4802.             outerReader.Read();
  4803.         }
  4804.        
  4805.         private bool ParseRootLevelWhitespace()
  4806.         {
  4807.             Debug.Assert(stringBuilder.Length == 0);
  4808.            
  4809.             XmlNodeType nodeType = GetWhitespaceType();
  4810.            
  4811.             if (nodeType == XmlNodeType.None) {
  4812.                 EatWhitespaces(null);
  4813.                 if (ps.chars[ps.charPos] == '<' || ps.charsUsed - ps.charPos == 0 || ZeroEndingStream(ps.charPos)) {
  4814.                     return false;
  4815.                 }
  4816.             }
  4817.             else {
  4818.                 curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  4819.                 EatWhitespaces(stringBuilder);
  4820.                 if (ps.chars[ps.charPos] == '<' || ps.charsUsed - ps.charPos == 0 || ZeroEndingStream(ps.charPos)) {
  4821.                     if (stringBuilder.Length > 0) {
  4822.                         curNode.SetValueNode(nodeType, stringBuilder.ToString());
  4823.                         stringBuilder.Length = 0;
  4824.                         return true;
  4825.                     }
  4826.                     return false;
  4827.                 }
  4828.             }
  4829.            
  4830.             if (xmlCharType.IsCharData(ps.chars[ps.charPos])) {
  4831.                 Throw(Res.Xml_InvalidRootData);
  4832.             }
  4833.             else {
  4834.                 ThrowInvalidChar(ps.charPos, ps.chars[ps.charPos]);
  4835.             }
  4836.             return false;
  4837.         }
  4838.        
  4839.         private void ParseEntityReference()
  4840.         {
  4841.             Debug.Assert(ps.chars[ps.charPos] == '&');
  4842.             ps.charPos++;
  4843.            
  4844.             curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  4845.             curNode.SetNamedNode(XmlNodeType.EntityReference, ParseEntityName());
  4846.         }
  4847.        
  4848.         private EntityType HandleEntityReference(bool isInAttributeValue, EntityExpandType expandType, out int charRefEndPos)
  4849.         {
  4850.             Debug.Assert(ps.chars[ps.charPos] == '&');
  4851.            
  4852.             if (ps.charPos + 1 == ps.charsUsed) {
  4853.                 if (ReadData() == 0) {
  4854.                     Throw(Res.Xml_UnexpectedEOF1);
  4855.                 }
  4856.             }
  4857.            
  4858.             // numeric characters reference
  4859.             if (ps.chars[ps.charPos + 1] == '#') {
  4860.                 EntityType entityType;
  4861.                 charRefEndPos = ParseNumericCharRef(expandType != EntityExpandType.OnlyGeneral, null, out entityType);
  4862.                 Debug.Assert(entityType == EntityType.CharacterDec || entityType == EntityType.CharacterHex);
  4863.                 return entityType;
  4864.             }
  4865.             // named reference
  4866.             else {
  4867.                 // named character reference
  4868.                 charRefEndPos = ParseNamedCharRef(expandType != EntityExpandType.OnlyGeneral, null);
  4869.                 if (charRefEndPos >= 0) {
  4870.                     return EntityType.CharacterNamed;
  4871.                 }
  4872.                
  4873.                 // general entity reference
  4874.                 if (expandType != EntityExpandType.OnlyCharacter && (entityHandling == EntityHandling.ExpandEntities || (isInAttributeValue && validatingReaderCompatFlag))) {
  4875.                     // NOTE: XmlValidatingReader compatibility mode: expand all entities in attribute values
  4876.                     // general entity reference
  4877.                     int endPos;
  4878.                    
  4879.                     ps.charPos++;
  4880.                     int savedLinePos = ps.LinePos;
  4881.                     try {
  4882.                         endPos = ParseName();
  4883.                     }
  4884.                     catch (XmlException) {
  4885.                         Throw(Res.Xml_ErrorParsingEntityName, ps.LineNo, savedLinePos);
  4886.                         return EntityType.Skipped;
  4887.                     }
  4888.                    
  4889.                     // check ';'
  4890.                     if (ps.chars[endPos] != ';') {
  4891.                         ThrowUnexpectedToken(endPos, ";");
  4892.                     }
  4893.                    
  4894.                     int entityLinePos = ps.LinePos;
  4895.                     string entityName = nameTable.Add(ps.chars, ps.charPos, endPos - ps.charPos);
  4896.                     ps.charPos = endPos + 1;
  4897.                     charRefEndPos = -1;
  4898.                    
  4899.                     EntityType entType = HandleGeneralEntityReference(entityName, isInAttributeValue, false, entityLinePos);
  4900.                     reportedBaseUri = ps.baseUriStr;
  4901.                     reportedEncoding = ps.encoding;
  4902.                     return entType;
  4903.                 }
  4904.                 else {
  4905.                     return EntityType.Unexpanded;
  4906.                 }
  4907.             }
  4908.         }
  4909.        
  4910.         // returns true == continue parsing
  4911.         // return false == unexpanded external entity, stop parsing and return
  4912.         private EntityType HandleGeneralEntityReference(string name, bool isInAttributeValue, bool pushFakeEntityIfNullResolver, int entityStartLinePos)
  4913.         {
  4914.             SchemaEntity entity = null;
  4915.             XmlQualifiedName qName = new XmlQualifiedName(name);
  4916.            
  4917.             if (dtdParserProxy == null && fragmentParserContext != null && fragmentParserContext.HasDtdInfo && !prohibitDtd) {
  4918.                 ParseDtdFromParserContext();
  4919.             }
  4920.            
  4921.             if (dtdParserProxy == null || ((entity = (SchemaEntity)dtdParserProxy.DtdSchemaInfo.GeneralEntities[qName]) == null)) {
  4922.                 if (disableUndeclaredEntityCheck) {
  4923.                     entity = new SchemaEntity(new XmlQualifiedName(name), false);
  4924.                     entity.Text = string.Empty;
  4925.                 }
  4926.                 else {
  4927.                     Throw(Res.Xml_UndeclaredEntity, name, ps.LineNo, entityStartLinePos);
  4928.                 }
  4929.             }
  4930.            
  4931.             if (entity.IsProcessed) {
  4932.                 Throw(Res.Xml_RecursiveGenEntity, name, ps.LineNo, entityStartLinePos);
  4933.             }
  4934.            
  4935.             if (!entity.NData.IsEmpty) {
  4936.                 if (disableUndeclaredEntityCheck) {
  4937.                     entity = new SchemaEntity(new XmlQualifiedName(name), false);
  4938.                     entity.Text = string.Empty;
  4939.                 }
  4940.                 else {
  4941.                     Throw(Res.Xml_UnparsedEntityRef, name, ps.LineNo, entityStartLinePos);
  4942.                 }
  4943.             }
  4944.            
  4945.             if (standalone && entity.DeclaredInExternal) {
  4946.                 Throw(Res.Xml_ExternalEntityInStandAloneDocument, entity.Name.Name, ps.LineNo, entityStartLinePos);
  4947.             }
  4948.            
  4949.             if (entity.IsExternal) {
  4950.                 if (isInAttributeValue) {
  4951.                     Throw(Res.Xml_ExternalEntityInAttValue, name, ps.LineNo, entityStartLinePos);
  4952.                     return EntityType.Skipped;
  4953.                 }
  4954.                
  4955.                 if (parsingMode == ParsingMode.SkipContent) {
  4956.                     return EntityType.Skipped;
  4957.                 }
  4958.                
  4959.                 if (xmlResolver == null) {
  4960.                     if (pushFakeEntityIfNullResolver) {
  4961.                         PushExternalEntity(entity, ++nextEntityId);
  4962.                         curNode.entityId = ps.entityId;
  4963.                         return EntityType.FakeExpanded;
  4964.                     }
  4965.                     return EntityType.Skipped;
  4966.                 }
  4967.                 else {
  4968.                     PushExternalEntity(entity, ++nextEntityId);
  4969.                     curNode.entityId = ps.entityId;
  4970.                     return (isInAttributeValue && validatingReaderCompatFlag) ? EntityType.ExpandedInAttribute : EntityType.Expanded;
  4971.                 }
  4972.             }
  4973.             else {
  4974.                 if (parsingMode == ParsingMode.SkipContent) {
  4975.                     return EntityType.Skipped;
  4976.                 }
  4977.                
  4978.                 int entityId = nextEntityId++;
  4979.                 PushInternalEntity(entity, entityId);
  4980.                
  4981.                 curNode.entityId = entityId;
  4982.                 return (isInAttributeValue && validatingReaderCompatFlag) ? EntityType.ExpandedInAttribute : EntityType.Expanded;
  4983.             }
  4984.         }
  4985.        
  4986.         private bool InEntity {
  4987.             get { return parsingStatesStackTop >= 0; }
  4988.         }
  4989.        
  4990.         // return true if EndEntity node should be reported. The entity is stored in lastEntity.
  4991.         private bool HandleEntityEnd(bool checkEntityNesting)
  4992.         {
  4993.             if (parsingStatesStackTop == -1) {
  4994.                 Debug.Assert(false);
  4995.                 Throw(Res.Xml_InternalError);
  4996.             }
  4997.            
  4998.             if (ps.entityResolvedManually) {
  4999.                 index--;
  5000.                
  5001.                 if (checkEntityNesting) {
  5002.                     if (ps.entityId != nodes[index].entityId) {
  5003.                         Throw(Res.Xml_IncompleteEntity);
  5004.                     }
  5005.                 }
  5006.                
  5007.                 lastEntity = ps.entity;
  5008.                 // save last entity for the EndEntity node
  5009.                 PopEntity();
  5010.                 curNode.entityId = ps.entityId;
  5011.                 return true;
  5012.             }
  5013.             else {
  5014.                 if (checkEntityNesting) {
  5015.                     if (ps.entityId != nodes[index].entityId) {
  5016.                         Throw(Res.Xml_IncompleteEntity);
  5017.                     }
  5018.                 }
  5019.                
  5020.                 PopEntity();
  5021.                 curNode.entityId = ps.entityId;
  5022.                
  5023.                 reportedEncoding = ps.encoding;
  5024.                 reportedBaseUri = ps.baseUriStr;
  5025.                 return false;
  5026.             }
  5027.         }
  5028.        
  5029.         private void SetupEndEntityNodeInContent()
  5030.         {
  5031.             Debug.Assert(lastEntity != null);
  5032.            
  5033.             reportedEncoding = ps.encoding;
  5034.             reportedBaseUri = ps.baseUriStr;
  5035.            
  5036.             curNode = nodes[index];
  5037.             Debug.Assert(curNode.depth == index);
  5038.             curNode.SetNamedNode(XmlNodeType.EndEntity, lastEntity.Name.Name);
  5039.             curNode.lineInfo.Set(ps.lineNo, ps.LinePos - 1);
  5040.            
  5041.             if (index == 0 && parsingFunction == ParsingFunction.ElementContent) {
  5042.                 parsingFunction = ParsingFunction.DocumentContent;
  5043.             }
  5044.         }
  5045.        
  5046.         private void SetupEndEntityNodeInAttribute()
  5047.         {
  5048.             curNode = nodes[index + attrCount + 1];
  5049.             Debug.Assert(curNode.type == XmlNodeType.EntityReference);
  5050.             Debug.Assert(Ref.Equal(lastEntity.Name.Name, curNode.localName));
  5051.             curNode.lineInfo.linePos += curNode.localName.Length;
  5052.             curNode.type = XmlNodeType.EndEntity;
  5053.         }
  5054.        
  5055.         private bool ParsePI()
  5056.         {
  5057.             return ParsePI(null);
  5058.         }
  5059.        
  5060.         // Parses processing instruction; if piInDtdStringBuilder != null, the processing instruction is in DTD and
  5061.         // it will be saved in the passed string builder (target, whitespace & value).
  5062.         private bool ParsePI(BufferBuilder piInDtdStringBuilder)
  5063.         {
  5064.             if (parsingMode == ParsingMode.Full) {
  5065.                 curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  5066.             }
  5067.            
  5068.             Debug.Assert(stringBuilder.Length == 0);
  5069.            
  5070.             // parse target name
  5071.             int nameEndPos = ParseName();
  5072.             string target = nameTable.Add(ps.chars, ps.charPos, nameEndPos - ps.charPos);
  5073.            
  5074.             if (string.Compare(target, "xml", StringComparison.OrdinalIgnoreCase) == 0) {
  5075.                 Throw(target.Equals("xml") ? Res.Xml_XmlDeclNotFirst : Res.Xml_InvalidPIName, target);
  5076.             }
  5077.             ps.charPos = nameEndPos;
  5078.            
  5079.             if (piInDtdStringBuilder == null) {
  5080.                 if (!ignorePIs && parsingMode == ParsingMode.Full) {
  5081.                     curNode.SetNamedNode(XmlNodeType.ProcessingInstruction, target);
  5082.                 }
  5083.             }
  5084.             else {
  5085.                 piInDtdStringBuilder.Append(target);
  5086.             }
  5087.            
  5088.             // check mandatory whitespace
  5089.             char ch = ps.chars[ps.charPos];
  5090.             Debug.Assert(ps.charPos < ps.charsUsed);
  5091.             if (EatWhitespaces(piInDtdStringBuilder) == 0) {
  5092.                 if (ps.charsUsed - ps.charPos < 2) {
  5093.                     ReadData();
  5094.                 }
  5095.                 if (ch != '?' || ps.chars[ps.charPos + 1] != '>') {
  5096.                     Throw(Res.Xml_BadNameChar, XmlException.BuildCharExceptionStr(ch));
  5097.                 }
  5098.             }
  5099.            
  5100.             // scan processing instruction value
  5101.             int startPos;
  5102.             int endPos;
  5103.             if (ParsePIValue(out startPos, out endPos)) {
  5104.                 if (piInDtdStringBuilder == null) {
  5105.                     if (ignorePIs) {
  5106.                         return false;
  5107.                     }
  5108.                     if (parsingMode == ParsingMode.Full) {
  5109.                         curNode.SetValue(ps.chars, startPos, endPos - startPos);
  5110.                     }
  5111.                 }
  5112.                 else {
  5113.                     piInDtdStringBuilder.Append(ps.chars, startPos, endPos - startPos);
  5114.                 }
  5115.             }
  5116.             else {
  5117.                 BufferBuilder sb;
  5118.                 if (piInDtdStringBuilder == null) {
  5119.                     if (ignorePIs || parsingMode != ParsingMode.Full) {
  5120.                         while (!ParsePIValue(out startPos, out endPos))
  5121.                             ;
  5122.                         return false;
  5123.                     }
  5124.                     sb = stringBuilder;
  5125.                     Debug.Assert(stringBuilder.Length == 0);
  5126.                 }
  5127.                 else {
  5128.                     sb = piInDtdStringBuilder;
  5129.                 }
  5130.                
  5131.                 do {
  5132.                     sb.Append(ps.chars, startPos, endPos - startPos);
  5133.                 }
  5134.                 while (!ParsePIValue(out startPos, out endPos));
  5135.                 sb.Append(ps.chars, startPos, endPos - startPos);
  5136.                
  5137.                 if (piInDtdStringBuilder == null) {
  5138.                     curNode.SetValue(stringBuilder.ToString());
  5139.                     stringBuilder.Length = 0;
  5140.                 }
  5141.             }
  5142.             return true;
  5143.         }
  5144.        
  5145.         private bool ParsePIValue(out int outStartPos, out int outEndPos)
  5146.         {
  5147.             // read new characters into the buffer
  5148.             if (ps.charsUsed - ps.charPos < 2) {
  5149.                 if (ReadData() == 0) {
  5150.                     Throw(ps.charsUsed, Res.Xml_UnexpectedEOF, "PI");
  5151.                 }
  5152.             }
  5153.            
  5154.             int pos = ps.charPos;
  5155.             char[] chars = ps.chars;
  5156.             int rcount = 0;
  5157.             int rpos = -1;
  5158.             for (;;) {
  5159.                 unsafe {
  5160.                     while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fText) != 0) && chars[pos] != '?') {
  5161.                         pos++;
  5162.                     }
  5163.                 }
  5164.                
  5165.                 switch (chars[pos]) {
  5166.                     case '?':
  5167.                         // possibly end of PI
  5168.                         if (chars[pos + 1] == '>') {
  5169.                             if (rcount > 0) {
  5170.                                 Debug.Assert(!ps.eolNormalized);
  5171.                                 ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  5172.                                 outEndPos = pos - rcount;
  5173.                             }
  5174.                             else {
  5175.                                 outEndPos = pos;
  5176.                             }
  5177.                             outStartPos = ps.charPos;
  5178.                             ps.charPos = pos + 2;
  5179.                             return true;
  5180.                         }
  5181.                         else if (pos + 1 == ps.charsUsed) {
  5182.                             goto ReturnPartial;
  5183.                         }
  5184.                         else {
  5185.                             pos++;
  5186.                             continue;
  5187.                         }
  5188.                         break;
  5189.                     case (char)10:
  5190.                         // eol
  5191.                         pos++;
  5192.                         OnNewLine(pos);
  5193.                         continue;
  5194.                     case (char)13:
  5195.                         if (chars[pos + 1] == (char)10) {
  5196.                             if (!ps.eolNormalized && parsingMode == ParsingMode.Full) {
  5197.                                 // EOL normalization of 0xD 0xA
  5198.                                 if (pos - ps.charPos > 0) {
  5199.                                     if (rcount == 0) {
  5200.                                         rcount = 1;
  5201.                                         rpos = pos;
  5202.                                     }
  5203.                                     else {
  5204.                                         ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  5205.                                         rpos = pos - rcount;
  5206.                                         rcount++;
  5207.                                     }
  5208.                                 }
  5209.                                 else {
  5210.                                     ps.charPos++;
  5211.                                 }
  5212.                             }
  5213.                             pos += 2;
  5214.                         }
  5215.                         else if (pos + 1 < ps.charsUsed || ps.isEof) {
  5216.                             if (!ps.eolNormalized) {
  5217.                                 chars[pos] = (char)10;
  5218.                                 // EOL normalization of 0xD
  5219.                             }
  5220.                             pos++;
  5221.                         }
  5222.                         else {
  5223.                             goto ReturnPartial;
  5224.                         }
  5225.                         OnNewLine(pos);
  5226.                         continue;
  5227.                     case '<':
  5228.                     case '&':
  5229.                     case ']':
  5230.                     case (char)9:
  5231.                         pos++;
  5232.                         continue;
  5233.                     default:
  5234.                         // end of buffer
  5235.                         if (pos == ps.charsUsed) {
  5236.                             goto ReturnPartial;
  5237.                         }
  5238.                         // surrogate characters
  5239.                         else {
  5240.                             char ch = chars[pos];
  5241.                             if (ch >= SurHighStart && ch <= SurHighEnd) {
  5242.                                 if (pos + 1 == ps.charsUsed) {
  5243.                                     goto ReturnPartial;
  5244.                                 }
  5245.                                 pos++;
  5246.                                 if (chars[pos] >= SurLowStart && chars[pos] <= SurLowEnd) {
  5247.                                     pos++;
  5248.                                     continue;
  5249.                                 }
  5250.                             }
  5251.                             ThrowInvalidChar(pos, ch);
  5252.                             break;
  5253.                         }
  5254.                         break;
  5255.                 }
  5256.                
  5257.             }
  5258.             ReturnPartial:
  5259.            
  5260.             if (rcount > 0) {
  5261.                 ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  5262.                 outEndPos = pos - rcount;
  5263.             }
  5264.             else {
  5265.                 outEndPos = pos;
  5266.             }
  5267.             outStartPos = ps.charPos;
  5268.             ps.charPos = pos;
  5269.             return false;
  5270.         }
  5271.        
  5272.         private bool ParseComment()
  5273.         {
  5274.             if (ignoreComments) {
  5275.                 ParsingMode oldParsingMode = parsingMode;
  5276.                 parsingMode = ParsingMode.SkipNode;
  5277.                 ParseCDataOrComment(XmlNodeType.Comment);
  5278.                 parsingMode = oldParsingMode;
  5279.                 return false;
  5280.             }
  5281.             else {
  5282.                 ParseCDataOrComment(XmlNodeType.Comment);
  5283.                 return true;
  5284.             }
  5285.         }
  5286.        
  5287.         private void ParseCData()
  5288.         {
  5289.             ParseCDataOrComment(XmlNodeType.CDATA);
  5290.         }
  5291.        
  5292.         // Parses CDATA section or comment
  5293.         private void ParseCDataOrComment(XmlNodeType type)
  5294.         {
  5295.             int startPos;
  5296.             int endPos;
  5297.            
  5298.             if (parsingMode == ParsingMode.Full) {
  5299.                 curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  5300.                 Debug.Assert(stringBuilder.Length == 0);
  5301.                 if (ParseCDataOrComment(type, out startPos, out endPos)) {
  5302.                     curNode.SetValueNode(type, ps.chars, startPos, endPos - startPos);
  5303.                 }
  5304.                 else {
  5305.                     do {
  5306.                         stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  5307.                     }
  5308.                     while (!ParseCDataOrComment(type, out startPos, out endPos));
  5309.                     stringBuilder.Append(ps.chars, startPos, endPos - startPos);
  5310.                     curNode.SetValueNode(type, stringBuilder.ToString());
  5311.                     stringBuilder.Length = 0;
  5312.                 }
  5313.             }
  5314.             else {
  5315.                 while (!ParseCDataOrComment(type, out startPos, out endPos))
  5316.                     ;
  5317.             }
  5318.         }
  5319.        
  5320.         // Parses a chunk of CDATA section or comment. Returns true when the end of CDATA or comment was reached.
  5321.         private bool ParseCDataOrComment(XmlNodeType type, out int outStartPos, out int outEndPos)
  5322.         {
  5323.             if (ps.charsUsed - ps.charPos < 3) {
  5324.                 // read new characters into the buffer
  5325.                 if (ReadData() == 0) {
  5326.                     Throw(Res.Xml_UnexpectedEOF, (type == XmlNodeType.Comment) ? "Comment" : "CDATA");
  5327.                 }
  5328.             }
  5329.            
  5330.             int pos = ps.charPos;
  5331.             char[] chars = ps.chars;
  5332.             int rcount = 0;
  5333.             int rpos = -1;
  5334.             char stopChar = (type == XmlNodeType.Comment) ? '-' : ']';
  5335.            
  5336.             for (;;) {
  5337.                 unsafe {
  5338.                     while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fText) != 0) && chars[pos] != stopChar)
  5339.                         pos++;
  5340.                 }
  5341.                
  5342.                 // posibbly end of comment or cdata section
  5343.                 if (chars[pos] == stopChar) {
  5344.                     if (chars[pos + 1] == stopChar) {
  5345.                         if (chars[pos + 2] == '>') {
  5346.                             if (rcount > 0) {
  5347.                                 Debug.Assert(!ps.eolNormalized);
  5348.                                 ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  5349.                                 outEndPos = pos - rcount;
  5350.                             }
  5351.                             else {
  5352.                                 outEndPos = pos;
  5353.                             }
  5354.                             outStartPos = ps.charPos;
  5355.                             ps.charPos = pos + 3;
  5356.                             return true;
  5357.                         }
  5358.                         else if (pos + 2 == ps.charsUsed) {
  5359.                             goto ReturnPartial;
  5360.                         }
  5361.                         else if (type == XmlNodeType.Comment) {
  5362.                             Throw(pos, Res.Xml_InvalidCommentChars);
  5363.                         }
  5364.                     }
  5365.                     else if (pos + 1 == ps.charsUsed) {
  5366.                         goto ReturnPartial;
  5367.                     }
  5368.                     pos++;
  5369.                     continue;
  5370.                 }
  5371.                 else {
  5372.                     switch (chars[pos]) {
  5373.                         case (char)10:
  5374.                             // eol
  5375.                             pos++;
  5376.                             OnNewLine(pos);
  5377.                             continue;
  5378.                         case (char)13:
  5379.                             if (chars[pos + 1] == (char)10) {
  5380.                                 // EOL normalization of 0xD 0xA - shift the buffer
  5381.                                 if (!ps.eolNormalized && parsingMode == ParsingMode.Full) {
  5382.                                     if (pos - ps.charPos > 0) {
  5383.                                         if (rcount == 0) {
  5384.                                             rcount = 1;
  5385.                                             rpos = pos;
  5386.                                         }
  5387.                                         else {
  5388.                                             ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  5389.                                             rpos = pos - rcount;
  5390.                                             rcount++;
  5391.                                         }
  5392.                                     }
  5393.                                     else {
  5394.                                         ps.charPos++;
  5395.                                     }
  5396.                                 }
  5397.                                 pos += 2;
  5398.                             }
  5399.                             else if (pos + 1 < ps.charsUsed || ps.isEof) {
  5400.                                 if (!ps.eolNormalized) {
  5401.                                     chars[pos] = (char)10;
  5402.                                     // EOL normalization of 0xD
  5403.                                 }
  5404.                                 pos++;
  5405.                             }
  5406.                             else {
  5407.                                 goto ReturnPartial;
  5408.                             }
  5409.                             OnNewLine(pos);
  5410.                             continue;
  5411.                         case '<':
  5412.                         case '&':
  5413.                         case ']':
  5414.                         case (char)9:
  5415.                             pos++;
  5416.                             continue;
  5417.                         default:
  5418.                             // end of buffer
  5419.                             if (pos == ps.charsUsed) {
  5420.                                 goto ReturnPartial;
  5421.                             }
  5422.                             // surrogate characters
  5423.                             char ch = chars[pos];
  5424.                             if (ch >= SurHighStart && ch <= SurHighEnd) {
  5425.                                 if (pos + 1 == ps.charsUsed) {
  5426.                                     goto ReturnPartial;
  5427.                                 }
  5428.                                 pos++;
  5429.                                 if (chars[pos] >= SurLowStart && chars[pos] <= SurLowEnd) {
  5430.                                     pos++;
  5431.                                     continue;
  5432.                                 }
  5433.                             }
  5434.                             ThrowInvalidChar(pos, ch);
  5435.                             break;
  5436.                     }
  5437.                 }
  5438.                 ReturnPartial:
  5439.                
  5440.                 if (rcount > 0) {
  5441.                     ShiftBuffer(rpos + rcount, rpos, pos - rpos - rcount);
  5442.                     outEndPos = pos - rcount;
  5443.                 }
  5444.                 else {
  5445.                     outEndPos = pos;
  5446.                 }
  5447.                 outStartPos = ps.charPos;
  5448.                
  5449.                 ps.charPos = pos;
  5450.                 return false;
  5451.                 // false == parsing of comment or CData section is not finished yet, must be called again
  5452.             }
  5453.         }
  5454.        
  5455.         // Parses DOCTYPE declaration
  5456.         private void ParseDoctypeDecl()
  5457.         {
  5458.             if (prohibitDtd) {
  5459.                 ThrowWithoutLineInfo(v1Compat ? Res.Xml_DtdIsProhibited : Res.Xml_DtdIsProhibitedEx, string.Empty);
  5460.             }
  5461.            
  5462.             // parse 'DOCTYPE'
  5463.             while (ps.charsUsed - ps.charPos < 8) {
  5464.                 if (ReadData() == 0) {
  5465.                     Throw(Res.Xml_UnexpectedEOF, "DOCTYPE");
  5466.                 }
  5467.             }
  5468.             if (!XmlConvert.StrEqual(ps.chars, ps.charPos, 7, "DOCTYPE")) {
  5469.                 ThrowUnexpectedToken((!rootElementParsed && dtdParserProxy == null) ? "DOCTYPE" : "<!--");
  5470.             }
  5471.             if (!xmlCharType.IsWhiteSpace(ps.chars[ps.charPos + 7])) {
  5472.                 Throw(Res.Xml_ExpectingWhiteSpace, ParseUnexpectedToken(ps.charPos + 7));
  5473.             }
  5474.            
  5475.             if (dtdParserProxy != null) {
  5476.                 Throw(ps.charPos - 2, Res.Xml_MultipleDTDsProvided);
  5477.                 // position just before <!DOCTYPE
  5478.             }
  5479.             if (rootElementParsed) {
  5480.                 Throw(ps.charPos - 2, Res.Xml_DtdAfterRootElement);
  5481.             }
  5482.            
  5483.             ps.charPos += 8;
  5484.            
  5485.             EatWhitespaces(null);
  5486.             curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  5487.            
  5488.             // parse DTD
  5489.             dtdParserProxy = new DtdParserProxy(this);
  5490.             dtdParserProxy.Parse(true);
  5491.            
  5492.             SchemaInfo dtdSchemaInfo = dtdParserProxy.DtdSchemaInfo;
  5493.            
  5494.             if ((validatingReaderCompatFlag || !v1Compat) && (dtdSchemaInfo.HasDefaultAttributes || dtdSchemaInfo.HasNonCDataAttributes)) {
  5495.                 addDefaultAttributesAndNormalize = true;
  5496.                 qName = new XmlQualifiedName();
  5497.             }
  5498.            
  5499.             curNode.SetNamedNode(XmlNodeType.DocumentType, dtdSchemaInfo.DocTypeName.ToString());
  5500.             curNode.SetValue(dtdParserProxy.InternalDtdSubset);
  5501.            
  5502.             nextParsingFunction = parsingFunction;
  5503.             parsingFunction = ParsingFunction.ResetAttributesRootLevel;
  5504.         }
  5505.        
  5506.         private int EatWhitespaces(BufferBuilder sb)
  5507.         {
  5508.             int pos = ps.charPos;
  5509.             int wsCount = 0;
  5510.             char[] chars = ps.chars;
  5511.            
  5512.             for (;;) {
  5513.                 for (;;) {
  5514.                     switch (chars[pos]) {
  5515.                         case (char)10:
  5516.                             pos++;
  5517.                             OnNewLine(pos);
  5518.                             continue;
  5519.                         case (char)13:
  5520.                             if (chars[pos + 1] == (char)10) {
  5521.                                 int tmp1 = pos - ps.charPos;
  5522.                                 if (sb != null && !ps.eolNormalized) {
  5523.                                     if (tmp1 > 0) {
  5524.                                         sb.Append(chars, ps.charPos, tmp1);
  5525.                                         wsCount += tmp1;
  5526.                                     }
  5527.                                     ps.charPos = pos + 1;
  5528.                                 }
  5529.                                 pos += 2;
  5530.                             }
  5531.                             else if (pos + 1 < ps.charsUsed || ps.isEof) {
  5532.                                 if (!ps.eolNormalized) {
  5533.                                     chars[pos] = (char)10;
  5534.                                     // EOL normalization of 0xD
  5535.                                 }
  5536.                                 pos++;
  5537.                             }
  5538.                             else {
  5539.                                 goto ReadData;
  5540.                             }
  5541.                             OnNewLine(pos);
  5542.                             continue;
  5543.                         case (char)9:
  5544.                         case (char)32:
  5545.                             pos++;
  5546.                             continue;
  5547.                         default:
  5548.                             if (pos == ps.charsUsed) {
  5549.                                 goto ReadData;
  5550.                             }
  5551.                             else {
  5552.                                 int tmp2 = pos - ps.charPos;
  5553.                                 if (tmp2 > 0) {
  5554.                                     if (sb != null) {
  5555.                                         sb.Append(ps.chars, ps.charPos, tmp2);
  5556.                                     }
  5557.                                     ps.charPos = pos;
  5558.                                     wsCount += tmp2;
  5559.                                 }
  5560.                                 return wsCount;
  5561.                             }
  5562.                             break;
  5563.                     }
  5564.                 }
  5565.                 ReadData:
  5566.                
  5567.                 int tmp3 = pos - ps.charPos;
  5568.                 if (tmp3 > 0) {
  5569.                     if (sb != null) {
  5570.                         sb.Append(ps.chars, ps.charPos, tmp3);
  5571.                     }
  5572.                     ps.charPos = pos;
  5573.                     wsCount += tmp3;
  5574.                 }
  5575.                
  5576.                 if (ReadData() == 0) {
  5577.                     if (ps.charsUsed - ps.charPos == 0) {
  5578.                         return wsCount;
  5579.                     }
  5580.                     if (ps.chars[ps.charPos] != (char)13) {
  5581.                         Debug.Assert(false, "We should never get to this point.");
  5582.                         Throw(Res.Xml_UnexpectedEOF1);
  5583.                     }
  5584.                     Debug.Assert(ps.isEof);
  5585.                 }
  5586.                 pos = ps.charPos;
  5587.                 chars = ps.chars;
  5588.             }
  5589.         }
  5590.        
  5591.         private int ParseCharRefInline(int startPos, out int charCount, out EntityType entityType)
  5592.         {
  5593.             Debug.Assert(ps.chars[startPos] == '&');
  5594.             if (ps.chars[startPos + 1] == '#') {
  5595.                 return ParseNumericCharRefInline(startPos, true, null, out charCount, out entityType);
  5596.             }
  5597.             else {
  5598.                 charCount = 1;
  5599.                 entityType = EntityType.CharacterNamed;
  5600.                 return ParseNamedCharRefInline(startPos, true, null);
  5601.             }
  5602.         }
  5603.        
  5604.         // Parses numeric character entity reference (e.g. &#32; &#x20;).
  5605.         // - replaces the last one or two character of the entity reference (';' and the character before) with the referenced
  5606.         // character or surrogates pair (if expand == true)
  5607.         // - returns position of the end of the character reference, that is of the character next to the original ';'
  5608.         // - if (expand == true) then ps.charPos is changed to point to the replaced character
  5609.         private int ParseNumericCharRef(bool expand, BufferBuilder internalSubsetBuilder, out EntityType entityType)
  5610.         {
  5611.             for (;;) {
  5612.                 int newPos;
  5613.                 int charCount;
  5614.                 switch (newPos = ParseNumericCharRefInline(ps.charPos, expand, internalSubsetBuilder, out charCount, out entityType)) {
  5615.                     case -2:
  5616.                         // read new characters in the buffer
  5617.                         if (ReadData() == 0) {
  5618.                             Throw(Res.Xml_UnexpectedEOF);
  5619.                         }
  5620.                         Debug.Assert(ps.chars[ps.charPos] == '&');
  5621.                         continue;
  5622.                     default:
  5623.                         if (expand) {
  5624.                             ps.charPos = newPos - charCount;
  5625.                         }
  5626.                         return newPos;
  5627.                 }
  5628.             }
  5629.         }
  5630.        
  5631.         // Parses numeric character entity reference (e.g. &#32; &#x20;).
  5632.         // Returns -2 if more data is needed in the buffer
  5633.         // Otherwise
  5634.         // - replaces the last one or two character of the entity reference (';' and the character before) with the referenced
  5635.         // character or surrogates pair (if expand == true)
  5636.         // - returns position of the end of the character reference, that is of the character next to the original ';'
  5637.         private int ParseNumericCharRefInline(int startPos, bool expand, BufferBuilder internalSubsetBuilder, out int charCount, out EntityType entityType)
  5638.         {
  5639.             Debug.Assert(ps.chars[startPos] == '&' && ps.chars[startPos + 1] == '#');
  5640.            
  5641.             int val;
  5642.             int pos;
  5643.             char[] chars;
  5644.            
  5645.             val = 0;
  5646.             string badDigitExceptionString = null;
  5647.             chars = ps.chars;
  5648.             pos = startPos + 2;
  5649.             charCount = 0;
  5650.            
  5651.             if (chars[pos] == 'x') {
  5652.                 pos++;
  5653.                 badDigitExceptionString = Res.Xml_BadHexEntity;
  5654.                 for (;;) {
  5655.                     char ch = chars[pos];
  5656.                     if (ch >= '0' && ch <= '9')
  5657.                         val = val * 16 + ch - '0';
  5658.                     else if (ch >= 'a' && ch <= 'f')
  5659.                         val = val * 16 + 10 + ch - 'a';
  5660.                     else if (ch >= 'A' && ch <= 'F')
  5661.                         val = val * 16 + 10 + ch - 'A';
  5662.                     else
  5663.                         break;
  5664.                     pos++;
  5665.                 }
  5666.                 entityType = EntityType.CharacterHex;
  5667.             }
  5668.             else if (pos < ps.charsUsed) {
  5669.                 badDigitExceptionString = Res.Xml_BadDecimalEntity;
  5670.                 while (chars[pos] >= '0' && chars[pos] <= '9') {
  5671.                     val = val * 10 + chars[pos] - '0';
  5672.                     pos++;
  5673.                 }
  5674.                 entityType = EntityType.CharacterDec;
  5675.             }
  5676.             else {
  5677.                 // need more data in the buffer
  5678.                 entityType = EntityType.Unexpanded;
  5679.                 return -2;
  5680.             }
  5681.            
  5682.             if (chars[pos] != ';') {
  5683.                 if (pos == ps.charsUsed) {
  5684.                     // need more data in the buffer
  5685.                     return -2;
  5686.                 }
  5687.                 else {
  5688.                     Throw(pos, badDigitExceptionString);
  5689.                 }
  5690.             }
  5691.            
  5692.             // simple character
  5693.             if (val <= char.MaxValue) {
  5694.                 char ch = (char)val;
  5695.                 if ((!xmlCharType.IsCharData(ch) || (ch >= SurLowStart && ch <= 57087)) && ((v1Compat && normalize) || (!v1Compat && checkCharacters))) {
  5696.                     ThrowInvalidChar((ps.chars[ps.charPos + 2] == 'x') ? ps.charPos + 3 : ps.charPos + 2, ch);
  5697.                 }
  5698.                
  5699.                 if (expand) {
  5700.                     if (internalSubsetBuilder != null) {
  5701.                         internalSubsetBuilder.Append(ps.chars, ps.charPos, pos - ps.charPos + 1);
  5702.                     }
  5703.                     chars[pos] = ch;
  5704.                 }
  5705.                 charCount = 1;
  5706.                 return pos + 1;
  5707.             }
  5708.             // surrogate
  5709.             else {
  5710.                 int v = val - 65536;
  5711.                 int low = SurLowStart + v % 1024;
  5712.                 int high = SurHighStart + v / 1024;
  5713.                
  5714.                 if (normalize) {
  5715.                     char ch = (char)high;
  5716.                     if (ch >= SurHighStart && ch <= SurHighEnd) {
  5717.                         ch = (char)low;
  5718.                         if (ch >= SurLowStart && ch <= SurLowEnd) {
  5719.                             goto Return;
  5720.                         }
  5721.                     }
  5722.                     ThrowInvalidChar((ps.chars[ps.charPos + 2] == 'x') ? ps.charPos + 3 : ps.charPos + 2, (char)val);
  5723.                 }
  5724.                 Return:
  5725.                
  5726.                 Debug.Assert(pos > 0);
  5727.                 if (expand) {
  5728.                     if (internalSubsetBuilder != null) {
  5729.                         internalSubsetBuilder.Append(ps.chars, ps.charPos, pos - ps.charPos + 1);
  5730.                     }
  5731.                     chars[pos - 1] = (char)high;
  5732.                     chars[pos] = (char)low;
  5733.                 }
  5734.                 charCount = 2;
  5735.                 return pos + 1;
  5736.             }
  5737.         }
  5738.        
  5739.         // Parses named character entity reference (&amp; &apos; &lt; &gt; &quot;).
  5740.         // Returns -1 if the reference is not a character entity reference.
  5741.         // Otherwise
  5742.         // - replaces the last character of the entity reference (';') with the referenced character (if expand == true)
  5743.         // - returns position of the end of the character reference, that is of the character next to the original ';'
  5744.         // - if (expand == true) then ps.charPos is changed to point to the replaced character
  5745.         private int ParseNamedCharRef(bool expand, BufferBuilder internalSubsetBuilder)
  5746.         {
  5747.             for (;;) {
  5748.                 int newPos;
  5749.                 switch (newPos = ParseNamedCharRefInline(ps.charPos, expand, internalSubsetBuilder)) {
  5750.                     case -1:
  5751.                         return -1;
  5752.                     case -2:
  5753.                         // read new characters in the buffer
  5754.                         if (ReadData() == 0) {
  5755.                             return -1;
  5756.                         }
  5757.                         Debug.Assert(ps.chars[ps.charPos] == '&');
  5758.                         continue;
  5759.                     default:
  5760.                         if (expand) {
  5761.                             ps.charPos = newPos - 1;
  5762.                         }
  5763.                         return newPos;
  5764.                 }
  5765.             }
  5766.         }
  5767.        
  5768.         // Parses named character entity reference (&amp; &apos; &lt; &gt; &quot;).
  5769.         // Returns -1 if the reference is not a character entity reference.
  5770.         // Returns -2 if more data is needed in the buffer
  5771.         // Otherwise
  5772.         // - replaces the last character of the entity reference (';') with the referenced character (if expand == true)
  5773.         // - returns position of the end of the character reference, that is of the character next to the original ';'
  5774.         private int ParseNamedCharRefInline(int startPos, bool expand, BufferBuilder internalSubsetBuilder)
  5775.         {
  5776.             Debug.Assert(startPos < ps.charsUsed);
  5777.             Debug.Assert(ps.chars[startPos] == '&');
  5778.             Debug.Assert(ps.chars[startPos + 1] != '#');
  5779.            
  5780.             int pos = startPos + 1;
  5781.             char[] chars = ps.chars;
  5782.             char ch;
  5783.            
  5784.             switch (chars[pos]) {
  5785.                 case 'a':
  5786.                     // &apos; or &amp;
  5787.                     pos++;
  5788.                     // &amp;
  5789.                     if (chars[pos] == 'm') {
  5790.                         if (ps.charsUsed - pos >= 3) {
  5791.                             if (chars[pos + 1] == 'p' && chars[pos + 2] == ';') {
  5792.                                 pos += 3;
  5793.                                 ch = '&';
  5794.                                 goto FoundCharRef;
  5795.                             }
  5796.                             else {
  5797.                                 return -1;
  5798.                             }
  5799.                         }
  5800.                     }
  5801.                     // &apos;
  5802.                     else if (chars[pos] == 'p') {
  5803.                         if (ps.charsUsed - pos >= 4) {
  5804.                             if (chars[pos + 1] == 'o' && chars[pos + 2] == 's' && chars[pos + 3] == ';') {
  5805.                                 pos += 4;
  5806.                                 ch = '\'';
  5807.                                 goto FoundCharRef;
  5808.                             }
  5809.                             else {
  5810.                                 return -1;
  5811.                             }
  5812.                         }
  5813.                     }
  5814.                     else if (pos < ps.charsUsed) {
  5815.                         return -1;
  5816.                     }
  5817.                     break;
  5818.                 case 'q':
  5819.                     // &guot;
  5820.                     if (ps.charsUsed - pos >= 5) {
  5821.                         if (chars[pos + 1] == 'u' && chars[pos + 2] == 'o' && chars[pos + 3] == 't' && chars[pos + 4] == ';') {
  5822.                             pos += 5;
  5823.                             ch = '"';
  5824.                             goto FoundCharRef;
  5825.                         }
  5826.                         else {
  5827.                             return -1;
  5828.                         }
  5829.                     }
  5830.                     break;
  5831.                 case 'l':
  5832.                     // &lt;
  5833.                     if (ps.charsUsed - pos >= 3) {
  5834.                         if (chars[pos + 1] == 't' && chars[pos + 2] == ';') {
  5835.                             pos += 3;
  5836.                             ch = '<';
  5837.                             goto FoundCharRef;
  5838.                         }
  5839.                         else {
  5840.                             return -1;
  5841.                         }
  5842.                     }
  5843.                     break;
  5844.                 case 'g':
  5845.                     // &gt;
  5846.                     if (ps.charsUsed - pos >= 3) {
  5847.                         if (chars[pos + 1] == 't' && chars[pos + 2] == ';') {
  5848.                             pos += 3;
  5849.                             ch = '>';
  5850.                             goto FoundCharRef;
  5851.                         }
  5852.                         else {
  5853.                             return -1;
  5854.                         }
  5855.                     }
  5856.                     break;
  5857.                 default:
  5858.                     return -1;
  5859.             }
  5860.            
  5861.             // need more data in the buffer
  5862.             return -2;
  5863.             FoundCharRef:
  5864.            
  5865.             Debug.Assert(pos > 0);
  5866.             if (expand) {
  5867.                 if (internalSubsetBuilder != null) {
  5868.                     internalSubsetBuilder.Append(ps.chars, ps.charPos, pos - ps.charPos);
  5869.                 }
  5870.                 ps.chars[pos - 1] = ch;
  5871.             }
  5872.             return pos;
  5873.         }
  5874.        
  5875.         private int ParseName()
  5876.         {
  5877.             int colonPos;
  5878.             return ParseQName(false, 0, out colonPos);
  5879.         }
  5880.        
  5881.         private int ParseQName(out int colonPos)
  5882.         {
  5883.             return ParseQName(true, 0, out colonPos);
  5884.         }
  5885.        
  5886.         private int ParseQName(bool isQName, int startOffset, out int colonPos)
  5887.         {
  5888.             int colonOffset = -1;
  5889.             int pos = ps.charPos + startOffset;
  5890.             ContinueStartName:
  5891.            
  5892.             char[] chars = ps.chars;
  5893.            
  5894.             // start name char
  5895.             unsafe {
  5896.                 if (!((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCStartName) != 0)) {
  5897.                     if (pos == ps.charsUsed) {
  5898.                         if (ReadDataInName(ref pos)) {
  5899.                             goto ContinueStartName;
  5900.                         }
  5901.                         Throw(pos, Res.Xml_UnexpectedEOF, "Name");
  5902.                     }
  5903.                     if (chars[pos] != ':' || supportNamespaces) {
  5904.                         Throw(pos, Res.Xml_BadStartNameChar, XmlException.BuildCharExceptionStr(chars[pos]));
  5905.                     }
  5906.                 }
  5907.             }
  5908.             pos++;
  5909.             ContinueName:
  5910.            
  5911.             // parse name
  5912.             unsafe {
  5913.                 while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fNCName) != 0)) {
  5914.                     pos++;
  5915.                 }
  5916.             }
  5917.            
  5918.             // colon
  5919.             if (chars[pos] == ':') {
  5920.                 if ((colonOffset != -1 || !isQName) && supportNamespaces) {
  5921.                     Throw(pos, Res.Xml_BadNameChar, XmlException.BuildCharExceptionStr(':'));
  5922.                 }
  5923.                 colonOffset = pos - ps.charPos;
  5924.                 pos++;
  5925.                 goto ContinueStartName;
  5926.             }
  5927.             // end of buffer
  5928.             else if (pos == ps.charsUsed) {
  5929.                 if (ReadDataInName(ref pos)) {
  5930.                     chars = ps.chars;
  5931.                     goto ContinueName;
  5932.                 }
  5933.                 Throw(pos, Res.Xml_UnexpectedEOF, "Name");
  5934.             }
  5935.            
  5936.             // end of name
  5937.             colonPos = (colonOffset == -1) ? -1 : ps.charPos + colonOffset;
  5938.             return pos;
  5939.         }
  5940.        
  5941.         private bool ReadDataInName(ref int pos)
  5942.         {
  5943.             int offset = pos - ps.charPos;
  5944.             bool newDataRead = (ReadData() != 0);
  5945.             pos = ps.charPos + offset;
  5946.             return newDataRead;
  5947.         }
  5948.        
  5949.         private string ParseEntityName()
  5950.         {
  5951.             int endPos;
  5952.             try {
  5953.                 endPos = ParseName();
  5954.             }
  5955.             catch (XmlException) {
  5956.                 Throw(Res.Xml_ErrorParsingEntityName);
  5957.                 return null;
  5958.             }
  5959.            
  5960.             // check ';'
  5961.             if (ps.chars[endPos] != ';') {
  5962.                 Throw(Res.Xml_ErrorParsingEntityName);
  5963.             }
  5964.            
  5965.             string entityName = nameTable.Add(ps.chars, ps.charPos, endPos - ps.charPos);
  5966.             ps.charPos = endPos + 1;
  5967.             return entityName;
  5968.         }
  5969.        
  5970.        
  5971.         private NodeData AddNode(int nodeIndex, int nodeDepth)
  5972.         {
  5973.             Debug.Assert(nodeIndex < nodes.Length);
  5974.             Debug.Assert(nodes[nodes.Length - 1] == null);
  5975.            
  5976.             NodeData n = nodes[nodeIndex];
  5977.             if (n != null) {
  5978.                 n.depth = nodeDepth;
  5979.                 return n;
  5980.             }
  5981.             return AllocNode(nodeIndex, nodeDepth);
  5982.         }
  5983.        
  5984.         private NodeData AllocNode(int nodeIndex, int nodeDepth)
  5985.         {
  5986.             Debug.Assert(nodeIndex < nodes.Length);
  5987.             if (nodeIndex >= nodes.Length - 1) {
  5988.                 NodeData[] newNodes = new NodeData[nodes.Length * 2];
  5989.                 Array.Copy(nodes, 0, newNodes, 0, nodes.Length);
  5990.                 nodes = newNodes;
  5991.             }
  5992.             Debug.Assert(nodeIndex < nodes.Length);
  5993.            
  5994.             NodeData node = nodes[nodeIndex];
  5995.             if (node == null) {
  5996.                 node = new NodeData();
  5997.                 nodes[nodeIndex] = node;
  5998.             }
  5999.             node.depth = nodeDepth;
  6000.             return node;
  6001.         }
  6002.        
  6003.         private NodeData AddAttributeNoChecks(string name, int attrDepth)
  6004.         {
  6005.             NodeData newAttr = AddNode(index + attrCount + 1, attrDepth);
  6006.             newAttr.SetNamedNode(XmlNodeType.Attribute, nameTable.Add(name));
  6007.             attrCount++;
  6008.             return newAttr;
  6009.         }
  6010.        
  6011.         private NodeData AddAttribute(int endNamePos, int colonPos)
  6012.         {
  6013.             // setup attribute name
  6014.             if (colonPos == -1 || !supportNamespaces) {
  6015.                 string localName = nameTable.Add(ps.chars, ps.charPos, endNamePos - ps.charPos);
  6016.                 return AddAttribute(localName, string.Empty, localName);
  6017.             }
  6018.             else {
  6019.                 attrNeedNamespaceLookup = true;
  6020.                 int startPos = ps.charPos;
  6021.                 int prefixLen = colonPos - startPos;
  6022.                 if (prefixLen == lastPrefix.Length && XmlConvert.StrEqual(ps.chars, startPos, prefixLen, lastPrefix)) {
  6023.                     return AddAttribute(nameTable.Add(ps.chars, colonPos + 1, endNamePos - colonPos - 1), lastPrefix, null);
  6024.                 }
  6025.                 else {
  6026.                     string prefix = nameTable.Add(ps.chars, startPos, prefixLen);
  6027.                     lastPrefix = prefix;
  6028.                     return AddAttribute(nameTable.Add(ps.chars, colonPos + 1, endNamePos - colonPos - 1), prefix, null);
  6029.                 }
  6030.             }
  6031.         }
  6032.        
  6033.         private NodeData AddAttribute(string localName, string prefix, string nameWPrefix)
  6034.         {
  6035.             NodeData newAttr = AddNode(index + attrCount + 1, index + 1);
  6036.            
  6037.             // set attribute name
  6038.             newAttr.SetNamedNode(XmlNodeType.Attribute, localName, prefix, nameWPrefix);
  6039.            
  6040.             // pre-check attribute for duplicate: hash by first local name char
  6041.             int attrHash = 1 << (localName[0] & 31);
  6042.             if ((attrHashtable & attrHash) == 0) {
  6043.                 attrHashtable |= attrHash;
  6044.             }
  6045.             else {
  6046.                 // there are probably 2 attributes beginning with the same letter -> check all previous
  6047.                 // attributes
  6048.                 if (attrDuplWalkCount < MaxAttrDuplWalkCount) {
  6049.                     attrDuplWalkCount++;
  6050.                     for (int i = index + 1; i < index + attrCount + 1; i++) {
  6051.                         NodeData attr = nodes[i];
  6052.                         Debug.Assert(attr.type == XmlNodeType.Attribute);
  6053.                         if (Ref.Equal(attr.localName, newAttr.localName)) {
  6054.                             attrDuplWalkCount = MaxAttrDuplWalkCount;
  6055.                             break;
  6056.                         }
  6057.                     }
  6058.                 }
  6059.             }
  6060.            
  6061.             attrCount++;
  6062.             return newAttr;
  6063.         }
  6064.        
  6065.         private void PopElementContext()
  6066.         {
  6067.             // pop namespace context
  6068.             namespaceManager.PopScope();
  6069.            
  6070.             // pop xml context
  6071.             if (curNode.xmlContextPushed) {
  6072.                 PopXmlContext();
  6073.             }
  6074.         }
  6075.        
  6076.         private void OnNewLine(int pos)
  6077.         {
  6078.             ps.lineNo++;
  6079.             ps.lineStartPos = pos - 1;
  6080.         }
  6081.        
  6082.         private void OnEof()
  6083.         {
  6084.             Debug.Assert(ps.isEof);
  6085.             curNode = nodes[0];
  6086.             curNode.Clear(XmlNodeType.None);
  6087.             curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  6088.            
  6089.             parsingFunction = ParsingFunction.Eof;
  6090.             readState = ReadState.EndOfFile;
  6091.            
  6092.             reportedEncoding = null;
  6093.         }
  6094.        
  6095.         private string LookupNamespace(NodeData node)
  6096.         {
  6097.             string ns = namespaceManager.LookupNamespace(node.prefix);
  6098.             if (ns != null) {
  6099.                 return ns;
  6100.             }
  6101.             else {
  6102.                 Throw(Res.Xml_UnknownNs, node.prefix, node.LineNo, node.LinePos);
  6103.                 return null;
  6104.             }
  6105.         }
  6106.        
  6107.         private void AddNamespace(string prefix, string uri, NodeData attr)
  6108.         {
  6109.             if (uri == XmlReservedNs.NsXmlNs) {
  6110.                 if (Ref.Equal(prefix, XmlNs)) {
  6111.                     Throw(Res.Xml_XmlnsPrefix, (int)attr.lineInfo2.lineNo, (int)attr.lineInfo2.linePos);
  6112.                 }
  6113.                 else {
  6114.                     Throw(Res.Xml_NamespaceDeclXmlXmlns, prefix, (int)attr.lineInfo2.lineNo, (int)attr.lineInfo2.linePos);
  6115.                 }
  6116.             }
  6117.             else if (uri == XmlReservedNs.NsXml) {
  6118.                 if (!Ref.Equal(prefix, Xml) && !v1Compat) {
  6119.                     Throw(Res.Xml_NamespaceDeclXmlXmlns, prefix, (int)attr.lineInfo2.lineNo, (int)attr.lineInfo2.linePos);
  6120.                 }
  6121.             }
  6122.             if (uri.Length == 0 && prefix.Length > 0) {
  6123.                 Throw(Res.Xml_BadNamespaceDecl, (int)attr.lineInfo.lineNo, (int)attr.lineInfo.linePos);
  6124.             }
  6125.            
  6126.             try {
  6127.                 namespaceManager.AddNamespace(prefix, uri);
  6128.             }
  6129.             catch (ArgumentException e) {
  6130.                 Debug.Assert(e.ParamName == null, "Expecting ArgumentException with message Xml_XmlPrefix or Xml_XmlnsPrefix.");
  6131.                 ReThrow(e, (int)attr.lineInfo.lineNo, (int)attr.lineInfo.linePos);
  6132.             }
  6133.             #if DEBUG
  6134.             if (prefix.Length == 0) {
  6135.                 Debug.Assert(xmlContext.defaultNamespace == uri);
  6136.             }
  6137.             #endif
  6138.         }
  6139.        
  6140.         private void ResetAttributes()
  6141.         {
  6142.             if (fullAttrCleanup) {
  6143.                 FullAttributeCleanup();
  6144.             }
  6145.             curAttrIndex = -1;
  6146.             attrCount = 0;
  6147.             attrHashtable = 0;
  6148.             attrDuplWalkCount = 0;
  6149.         }
  6150.        
  6151.         private void FullAttributeCleanup()
  6152.         {
  6153.             for (int i = index + 1; i < index + attrCount + 1; i++) {
  6154.                 NodeData attr = nodes[i];
  6155.                 attr.nextAttrValueChunk = null;
  6156.                 attr.IsDefaultAttribute = false;
  6157.             }
  6158.             fullAttrCleanup = false;
  6159.         }
  6160.        
  6161.         private void PushXmlContext()
  6162.         {
  6163.             xmlContext = new XmlContext(xmlContext);
  6164.             curNode.xmlContextPushed = true;
  6165.         }
  6166.        
  6167.         private void PopXmlContext()
  6168.         {
  6169.             Debug.Assert(curNode.xmlContextPushed);
  6170.             xmlContext = xmlContext.previousContext;
  6171.             curNode.xmlContextPushed = false;
  6172.         }
  6173.        
  6174.         // Returns the whitespace node type according to the current whitespaceHandling setting and xml:space
  6175.         private XmlNodeType GetWhitespaceType()
  6176.         {
  6177.             if (whitespaceHandling != WhitespaceHandling.None) {
  6178.                 if (xmlContext.xmlSpace == XmlSpace.Preserve) {
  6179.                     return XmlNodeType.SignificantWhitespace;
  6180.                 }
  6181.                 if (whitespaceHandling == WhitespaceHandling.All) {
  6182.                     return XmlNodeType.Whitespace;
  6183.                 }
  6184.             }
  6185.             return XmlNodeType.None;
  6186.         }
  6187.        
  6188.         private XmlNodeType GetTextNodeType(int orChars)
  6189.         {
  6190.             if (orChars > 32) {
  6191.                 return XmlNodeType.Text;
  6192.             }
  6193.             else {
  6194.                 return GetWhitespaceType();
  6195.             }
  6196.         }
  6197.        
  6198.         // returns true if real entity has been pushed, false if fake entity (=empty content entity)
  6199.         private bool PushExternalEntity(SchemaEntity entity, int entityId)
  6200.         {
  6201.             Debug.Assert(entity.IsExternal);
  6202.            
  6203.             if (xmlResolver != null) {
  6204.                
  6205.                 Uri entityBaseUri = (entity.BaseURI.Length > 0) ? xmlResolver.ResolveUri(null, entity.BaseURI) : null;
  6206.                 Uri entityUri = xmlResolver.ResolveUri(entityBaseUri, entity.Url);
  6207.                 Stream stream = null;
  6208.                 try {
  6209.                     stream = OpenStream(entityUri);
  6210.                 }
  6211.                 catch (Exception e) {
  6212.                     if (v1Compat) {
  6213.                         throw;
  6214.                     }
  6215.                     Throw(new XmlException(Res.Xml_ErrorOpeningExternalEntity, new string[] {entityUri.ToString(), e.Message}, e, 0, 0));
  6216.                 }
  6217.                
  6218.                 if (stream == null) {
  6219.                     Throw(Res.Xml_CannotResolveEntity, entity.Name.Name);
  6220.                 }
  6221.                
  6222.                 PushParsingState();
  6223.                
  6224.                 if (v1Compat) {
  6225.                     InitStreamInput(entityUri, stream, null);
  6226.                 }
  6227.                 else {
  6228.                     InitStreamInput(entityUri, stream, null);
  6229.                 }
  6230.                
  6231.                 ps.entity = entity;
  6232.                 ps.entityId = entityId;
  6233.                 entity.IsProcessed = true;
  6234.                
  6235.                 Debug.Assert(ps.appendMode);
  6236.                 int initialPos = ps.charPos;
  6237.                 if (v1Compat) {
  6238.                     EatWhitespaces(null);
  6239.                 }
  6240.                 if (!ParseXmlDeclaration(true)) {
  6241.                     ps.charPos = initialPos;
  6242.                 }
  6243.                 return true;
  6244.             }
  6245.             else {
  6246.                 Encoding enc = ps.encoding;
  6247.                
  6248.                 PushParsingState();
  6249.                 InitStringInput(entity.Url, enc, string.Empty);
  6250.                
  6251.                 ps.entity = entity;
  6252.                 ps.entityId = entityId;
  6253.                
  6254.                 return false;
  6255.             }
  6256.         }
  6257.        
  6258.         private void PushInternalEntity(SchemaEntity entity, int entityId)
  6259.         {
  6260.             Debug.Assert(!entity.IsExternal);
  6261.            
  6262.             Encoding enc = ps.encoding;
  6263.            
  6264.             PushParsingState();
  6265.            
  6266.             InitStringInput((entity.DeclaredURI != null) ? entity.DeclaredURI : string.Empty, enc, entity.Text);
  6267.            
  6268.             ps.entity = entity;
  6269.             ps.entityId = entityId;
  6270.             ps.lineNo = entity.Line;
  6271.             ps.lineStartPos = -entity.Pos - 1;
  6272.            
  6273.             ps.eolNormalized = true;
  6274.             entity.IsProcessed = true;
  6275.         }
  6276.        
  6277.         private void PopEntity()
  6278.         {
  6279.             if (ps.entity != null) {
  6280.                 ps.entity.IsProcessed = false;
  6281.             }
  6282.             if (ps.stream != null) {
  6283.                 ps.stream.Close();
  6284.             }
  6285.             PopParsingState();
  6286.             curNode.entityId = ps.entityId;
  6287.         }
  6288.        
  6289.         private void PushParsingState()
  6290.         {
  6291.             if (parsingStatesStack == null) {
  6292.                 parsingStatesStack = new ParsingState[InitialParsingStatesDepth];
  6293.                 Debug.Assert(parsingStatesStackTop == -1);
  6294.             }
  6295.             else if (parsingStatesStackTop + 1 == parsingStatesStack.Length) {
  6296.                 ParsingState[] newParsingStateStack = new ParsingState[parsingStatesStack.Length * 2];
  6297.                 Array.Copy(parsingStatesStack, 0, newParsingStateStack, 0, parsingStatesStack.Length);
  6298.                 parsingStatesStack = newParsingStateStack;
  6299.             }
  6300.             parsingStatesStackTop++;
  6301.             parsingStatesStack[parsingStatesStackTop] = ps;
  6302.            
  6303.             ps.Clear();
  6304.         }
  6305.        
  6306.         private void PopParsingState()
  6307.         {
  6308.             Debug.Assert(parsingStatesStackTop >= 0);
  6309.             ps.Close(true);
  6310.             ps = parsingStatesStack[parsingStatesStackTop--];
  6311.         }
  6312.        
  6313.         private void InitIncrementalRead(IncrementalReadDecoder decoder)
  6314.         {
  6315.             ResetAttributes();
  6316.            
  6317.             decoder.Reset();
  6318.             incReadDecoder = decoder;
  6319.             incReadState = IncrementalReadState.Text;
  6320.             incReadDepth = 1;
  6321.             incReadLeftStartPos = ps.charPos;
  6322.             incReadLineInfo.Set(ps.LineNo, ps.LinePos);
  6323.            
  6324.             parsingFunction = ParsingFunction.InIncrementalRead;
  6325.         }
  6326.        
  6327.         private int IncrementalRead(Array array, int index, int count)
  6328.         {
  6329.             if (array == null) {
  6330.                 throw new ArgumentNullException((incReadDecoder is IncrementalReadCharsDecoder) ? "buffer" : "array");
  6331.             }
  6332.             if (count < 0) {
  6333.                 throw new ArgumentOutOfRangeException((incReadDecoder is IncrementalReadCharsDecoder) ? "count" : "len");
  6334.             }
  6335.             if (index < 0) {
  6336.                 throw new ArgumentOutOfRangeException((incReadDecoder is IncrementalReadCharsDecoder) ? "index" : "offset");
  6337.             }
  6338.             if (array.Length - index < count) {
  6339.                 throw new ArgumentException((incReadDecoder is IncrementalReadCharsDecoder) ? "count" : "len");
  6340.             }
  6341.            
  6342.             if (count == 0) {
  6343.                 return 0;
  6344.             }
  6345.            
  6346.             curNode.lineInfo = incReadLineInfo;
  6347.            
  6348.             incReadDecoder.SetNextOutputBuffer(array, index, count);
  6349.             IncrementalRead();
  6350.             return incReadDecoder.DecodedCount;
  6351.         }
  6352.        
  6353.         private int IncrementalRead()
  6354.         {
  6355.             int charsDecoded = 0;
  6356.             OuterContinue:
  6357.            
  6358.             int charsLeft = incReadLeftEndPos - incReadLeftStartPos;
  6359.             if (charsLeft > 0) {
  6360.                 int count;
  6361.                 try {
  6362.                     count = incReadDecoder.Decode(ps.chars, incReadLeftStartPos, charsLeft);
  6363.                 }
  6364.                 catch (XmlException e) {
  6365.                     ReThrow(e, (int)incReadLineInfo.lineNo, (int)incReadLineInfo.linePos);
  6366.                     return 0;
  6367.                 }
  6368.                 if (count < charsLeft) {
  6369.                     incReadLeftStartPos += count;
  6370.                     incReadLineInfo.linePos += count;
  6371.                     // we have never more then 1 line cached
  6372.                     return count;
  6373.                 }
  6374.                 else {
  6375.                     incReadLeftStartPos = 0;
  6376.                     incReadLeftEndPos = 0;
  6377.                     incReadLineInfo.linePos += count;
  6378.                     if (incReadDecoder.IsFull) {
  6379.                         return count;
  6380.                     }
  6381.                 }
  6382.             }
  6383.            
  6384.             int startPos = 0;
  6385.             int pos = 0;
  6386.            
  6387.             for (;;) {
  6388.                
  6389.                 switch (incReadState) {
  6390.                     case IncrementalReadState.Text:
  6391.                     case IncrementalReadState.Attributes:
  6392.                     case IncrementalReadState.AttributeValue:
  6393.                         break;
  6394.                     case IncrementalReadState.PI:
  6395.                         if (ParsePIValue(out startPos, out pos)) {
  6396.                             Debug.Assert(XmlConvert.StrEqual(ps.chars, ps.charPos - 2, 2, "?>"));
  6397.                             ps.charPos -= 2;
  6398.                             incReadState = IncrementalReadState.Text;
  6399.                         }
  6400.                         goto Append;
  6401.                         break;
  6402.                     case IncrementalReadState.Comment:
  6403.                         if (ParseCDataOrComment(XmlNodeType.Comment, out startPos, out pos)) {
  6404.                             Debug.Assert(XmlConvert.StrEqual(ps.chars, ps.charPos - 3, 3, "-->"));
  6405.                             ps.charPos -= 3;
  6406.                             incReadState = IncrementalReadState.Text;
  6407.                         }
  6408.                         goto Append;
  6409.                         break;
  6410.                     case IncrementalReadState.CDATA:
  6411.                         if (ParseCDataOrComment(XmlNodeType.CDATA, out startPos, out pos)) {
  6412.                             Debug.Assert(XmlConvert.StrEqual(ps.chars, ps.charPos - 3, 3, "]]>"));
  6413.                             ps.charPos -= 3;
  6414.                             incReadState = IncrementalReadState.Text;
  6415.                         }
  6416.                         goto Append;
  6417.                         break;
  6418.                     case IncrementalReadState.EndElement:
  6419.                         parsingFunction = ParsingFunction.PopElementContext;
  6420.                         nextParsingFunction = (index > 0 || fragmentType != XmlNodeType.Document) ? ParsingFunction.ElementContent : ParsingFunction.DocumentContent;
  6421.                         outerReader.Read();
  6422.                         incReadState = IncrementalReadState.End;
  6423.                         goto case IncrementalReadState.End;
  6424.                         break;
  6425.                     case IncrementalReadState.End:
  6426.                         return charsDecoded;
  6427.                     case IncrementalReadState.ReadData:
  6428.                         if (ReadData() == 0) {
  6429.                             ThrowUnclosedElements();
  6430.                         }
  6431.                         incReadState = IncrementalReadState.Text;
  6432.                         startPos = ps.charPos;
  6433.                         pos = startPos;
  6434.                         break;
  6435.                     default:
  6436.                         Debug.Assert(false);
  6437.                         break;
  6438.                 }
  6439.                 Debug.Assert(incReadState == IncrementalReadState.Text || incReadState == IncrementalReadState.Attributes || incReadState == IncrementalReadState.AttributeValue);
  6440.                
  6441.                 char[] chars = ps.chars;
  6442.                 startPos = ps.charPos;
  6443.                 pos = startPos;
  6444.                
  6445.                 for (;;) {
  6446.                     incReadLineInfo.Set(ps.LineNo, ps.LinePos);
  6447.                    
  6448.                     char c;
  6449.                     unsafe {
  6450.                         if (incReadState == IncrementalReadState.Attributes) {
  6451.                             while (((xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fAttrValue) != 0) && c != '/') {
  6452.                                 pos++;
  6453.                             }
  6454.                         }
  6455.                         else {
  6456.                             while (((xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fAttrValue) != 0)) {
  6457.                                 pos++;
  6458.                             }
  6459.                         }
  6460.                     }
  6461.                    
  6462.                     if (chars[pos] == '&' || chars[pos] == (char)9) {
  6463.                         pos++;
  6464.                         continue;
  6465.                     }
  6466.                    
  6467.                     if (pos - startPos > 0) {
  6468.                         goto AppendAndUpdateCharPos;
  6469.                     }
  6470.                    
  6471.                     switch (chars[pos]) {
  6472.                         case (char)10:
  6473.                             // eol
  6474.                             pos++;
  6475.                             OnNewLine(pos);
  6476.                             continue;
  6477.                         case (char)13:
  6478.                             if (chars[pos + 1] == (char)10) {
  6479.                                 pos += 2;
  6480.                             }
  6481.                             else if (pos + 1 < ps.charsUsed) {
  6482.                                 pos++;
  6483.                             }
  6484.                             else {
  6485.                                 goto ReadData;
  6486.                             }
  6487.                             OnNewLine(pos);
  6488.                             continue;
  6489.                         case '<':
  6490.                             // some tag
  6491.                             if (incReadState != IncrementalReadState.Text) {
  6492.                                 pos++;
  6493.                                 continue;
  6494.                             }
  6495.                             if (ps.charsUsed - pos < 2) {
  6496.                                 goto ReadData;
  6497.                             }
  6498.                             switch (chars[pos + 1]) {
  6499.                                 case '?':
  6500.                                     // pi
  6501.                                     pos += 2;
  6502.                                     incReadState = IncrementalReadState.PI;
  6503.                                     goto AppendAndUpdateCharPos;
  6504.                                     break;
  6505.                                 case '!':
  6506.                                     // comment
  6507.                                     if (ps.charsUsed - pos < 4) {
  6508.                                         goto ReadData;
  6509.                                     }
  6510.                                     if (chars[pos + 2] == '-' && chars[pos + 3] == '-') {
  6511.                                         pos += 4;
  6512.                                         incReadState = IncrementalReadState.Comment;
  6513.                                         goto AppendAndUpdateCharPos;
  6514.                                     }
  6515.                                     if (ps.charsUsed - pos < 9) {
  6516.                                         goto ReadData;
  6517.                                     }
  6518.                                     if (XmlConvert.StrEqual(chars, pos + 2, 7, "[CDATA[")) {
  6519.                                         pos += 9;
  6520.                                         incReadState = IncrementalReadState.CDATA;
  6521.                                         goto AppendAndUpdateCharPos;
  6522.                                     }
  6523.                                     else {
  6524.                                         ;
  6525.                                         //Throw( );
  6526.                                     }
  6527.                                     break;
  6528.                                 case '/':
  6529.                                     // end tag
  6530.                                    
  6531.                                     {
  6532.                                         Debug.Assert(ps.charPos - pos == 0);
  6533.                                         int colonPos;
  6534.                                         int endPos = ParseQName(true, 2, out colonPos);
  6535.                                         if (XmlConvert.StrEqual(chars, ps.charPos + 2, endPos - ps.charPos - 2, curNode.GetNameWPrefix(nameTable)) && (ps.chars[endPos] == '>' || xmlCharType.IsWhiteSpace(ps.chars[endPos]))) {
  6536.                                            
  6537.                                             if (--incReadDepth > 0) {
  6538.                                                 pos = endPos + 1;
  6539.                                                 continue;
  6540.                                             }
  6541.                                            
  6542.                                             ps.charPos = endPos;
  6543.                                             if (xmlCharType.IsWhiteSpace(ps.chars[endPos])) {
  6544.                                                 EatWhitespaces(null);
  6545.                                             }
  6546.                                             if (ps.chars[ps.charPos] != '>') {
  6547.                                                 ThrowUnexpectedToken(">");
  6548.                                             }
  6549.                                             ps.charPos++;
  6550.                                            
  6551.                                             incReadState = IncrementalReadState.EndElement;
  6552.                                             goto OuterContinue;
  6553.                                         }
  6554.                                         else {
  6555.                                             pos = endPos;
  6556.                                             continue;
  6557.                                         }
  6558.                                     }
  6559.                                     break;
  6560.                                 default:
  6561.                                     // start tag
  6562.                                    
  6563.                                     {
  6564.                                         Debug.Assert(ps.charPos - pos == 0);
  6565.                                         int colonPos;
  6566.                                         int endPos = ParseQName(true, 1, out colonPos);
  6567.                                         if (XmlConvert.StrEqual(ps.chars, ps.charPos + 1, endPos - ps.charPos - 1, curNode.localName) && (ps.chars[endPos] == '>' || ps.chars[endPos] == '/' || xmlCharType.IsWhiteSpace(ps.chars[endPos]))) {
  6568.                                             incReadDepth++;
  6569.                                             incReadState = IncrementalReadState.Attributes;
  6570.                                             pos = endPos;
  6571.                                             goto AppendAndUpdateCharPos;
  6572.                                         }
  6573.                                         pos = endPos;
  6574.                                         startPos = ps.charPos;
  6575.                                         chars = ps.chars;
  6576.                                         continue;
  6577.                                     }
  6578.                                     break;
  6579.                             }
  6580.                             break;
  6581.                         case '/':
  6582.                             // end of start tag
  6583.                             if (incReadState == IncrementalReadState.Attributes) {
  6584.                                 if (ps.charsUsed - pos < 2) {
  6585.                                     goto ReadData;
  6586.                                 }
  6587.                                 if (chars[pos + 1] == '>') {
  6588.                                     incReadState = IncrementalReadState.Text;
  6589.                                     incReadDepth--;
  6590.                                 }
  6591.                             }
  6592.                             pos++;
  6593.                             continue;
  6594.                         case '>':
  6595.                             // end of start tag
  6596.                             if (incReadState == IncrementalReadState.Attributes) {
  6597.                                 incReadState = IncrementalReadState.Text;
  6598.                             }
  6599.                             pos++;
  6600.                             continue;
  6601.                         case '"':
  6602.                         case '\'':
  6603.                             switch (incReadState) {
  6604.                                 case IncrementalReadState.AttributeValue:
  6605.                                     if (chars[pos] == curNode.quoteChar) {
  6606.                                         incReadState = IncrementalReadState.Attributes;
  6607.                                     }
  6608.                                     break;
  6609.                                 case IncrementalReadState.Attributes:
  6610.                                     curNode.quoteChar = chars[pos];
  6611.                                     incReadState = IncrementalReadState.AttributeValue;
  6612.                                     break;
  6613.                             }
  6614.                             pos++;
  6615.                             continue;
  6616.                         default:
  6617.                             // end of buffer
  6618.                             if (pos == ps.charsUsed) {
  6619.                                 goto ReadData;
  6620.                             }
  6621.                             // surrogate chars or invalid chars are ignored
  6622.                             else {
  6623.                                 pos++;
  6624.                                 continue;
  6625.                             }
  6626.                             break;
  6627.                     }
  6628.                 }
  6629.                 ReadData:
  6630.                
  6631.                 incReadState = IncrementalReadState.ReadData;
  6632.                 AppendAndUpdateCharPos:
  6633.                
  6634.                 ps.charPos = pos;
  6635.                 Append:
  6636.                
  6637.                 // decode characters
  6638.                 int charsParsed = pos - startPos;
  6639.                 if (charsParsed > 0) {
  6640.                     int count;
  6641.                     try {
  6642.                         count = incReadDecoder.Decode(ps.chars, startPos, charsParsed);
  6643.                     }
  6644.                     catch (XmlException e) {
  6645.                         ReThrow(e, (int)incReadLineInfo.lineNo, (int)incReadLineInfo.linePos);
  6646.                         return 0;
  6647.                     }
  6648.                     Debug.Assert(count == charsParsed || incReadDecoder.IsFull, "Check if decoded consumed all characters unless it's full.");
  6649.                     charsDecoded += count;
  6650.                     if (incReadDecoder.IsFull) {
  6651.                         incReadLeftStartPos = startPos + count;
  6652.                         incReadLeftEndPos = pos;
  6653.                         incReadLineInfo.linePos += count;
  6654.                         // we have never more than 1 line cached
  6655.                         return charsDecoded;
  6656.                     }
  6657.                 }
  6658.             }
  6659.         }
  6660.        
  6661.         private void FinishIncrementalRead()
  6662.         {
  6663.             incReadDecoder = new IncrementalReadDummyDecoder();
  6664.             IncrementalRead();
  6665.             Debug.Assert(IncrementalRead() == 0, "Previous call of IncrementalRead should eat up all characters!");
  6666.             incReadDecoder = null;
  6667.         }
  6668.        
  6669.         private bool ParseFragmentAttribute()
  6670.         {
  6671.             Debug.Assert(fragmentType == XmlNodeType.Attribute);
  6672.            
  6673.             // if first call then parse the whole attribute value
  6674.             if (curNode.type == XmlNodeType.None) {
  6675.                 curNode.type = XmlNodeType.Attribute;
  6676.                 curAttrIndex = 0;
  6677.                 ParseAttributeValueSlow(ps.charPos, '"', curNode);
  6678.             }
  6679.             else {
  6680.                 parsingFunction = ParsingFunction.InReadAttributeValue;
  6681.             }
  6682.            
  6683.             // return attribute value chunk
  6684.             if (ReadAttributeValue()) {
  6685.                 Debug.Assert(parsingFunction == ParsingFunction.InReadAttributeValue);
  6686.                 parsingFunction = ParsingFunction.FragmentAttribute;
  6687.                 return true;
  6688.             }
  6689.             else {
  6690.                 OnEof();
  6691.                 return false;
  6692.             }
  6693.         }
  6694.        
  6695.         private bool ParseAttributeValueChunk()
  6696.         {
  6697.             char[] chars = ps.chars;
  6698.             int pos = ps.charPos;
  6699.            
  6700.             curNode = AddNode(index + attrCount + 1, index + 2);
  6701.             curNode.SetLineInfo(ps.LineNo, ps.LinePos);
  6702.            
  6703.             if (emptyEntityInAttributeResolved) {
  6704.                 curNode.SetValueNode(XmlNodeType.Text, string.Empty);
  6705.                 emptyEntityInAttributeResolved = false;
  6706.                 return true;
  6707.             }
  6708.            
  6709.             Debug.Assert(stringBuilder.Length == 0);
  6710.            
  6711.             for (;;) {
  6712.                 unsafe {
  6713.                     while (((xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue) != 0))
  6714.                         pos++;
  6715.                 }
  6716.                
  6717.                 switch (chars[pos]) {
  6718.                     case (char)13:
  6719.                         // eol D
  6720.                         Debug.Assert(ps.eolNormalized, "Entity replacement text for attribute values should be EOL-normalized!");
  6721.                         pos++;
  6722.                         continue;
  6723.                     case (char)10:
  6724.                     case (char)9:
  6725.                         // eol A, tab
  6726.                         if (normalize) {
  6727.                             chars[pos] = (char)32;
  6728.                             // CDATA normalization of 0xA and 0x9
  6729.                         }
  6730.                         pos++;
  6731.                         continue;
  6732.                     case '"':
  6733.                     case '\'':
  6734.                     case '>':
  6735.                         pos++;
  6736.                         continue;
  6737.                     case '<':
  6738.                         // attribute values cannot contain '<'
  6739.                         Throw(pos, Res.Xml_BadAttributeChar, XmlException.BuildCharExceptionStr('<'));
  6740.                         break;
  6741.                     case '&':
  6742.                         // entity reference
  6743.                         if (pos - ps.charPos > 0) {
  6744.                             stringBuilder.Append(chars, ps.charPos, pos - ps.charPos);
  6745.                         }
  6746.                         ps.charPos = pos;
  6747.                        
  6748.                         // expand char entities but not general entities
  6749.                         switch (HandleEntityReference(true, EntityExpandType.OnlyCharacter, out pos)) {
  6750.                             case EntityType.CharacterDec:
  6751.                             case EntityType.CharacterHex:
  6752.                             case EntityType.CharacterNamed:
  6753.                                 chars = ps.chars;
  6754.                                 if (normalize && xmlCharType.IsWhiteSpace(chars[ps.charPos]) && pos - ps.charPos == 1) {
  6755.                                     chars[ps.charPos] = (char)32;
  6756.                                     // CDATA normalization of character references in entities
  6757.                                 }
  6758.                                 break;
  6759.                             case EntityType.Unexpanded:
  6760.                                 if (stringBuilder.Length == 0) {
  6761.                                     curNode.lineInfo.linePos++;
  6762.                                     ps.charPos++;
  6763.                                     curNode.SetNamedNode(XmlNodeType.EntityReference, ParseEntityName());
  6764.                                     return true;
  6765.                                 }
  6766.                                 else {
  6767.                                     goto ReturnText;
  6768.                                 }
  6769.                                 break;
  6770.                             default:
  6771.                                 Debug.Assert(false, "We should never get to this point.");
  6772.                                 break;
  6773.                         }
  6774.                         chars = ps.chars;
  6775.                         continue;
  6776.                     default:
  6777.                         // end of buffer
  6778.                         if (pos == ps.charsUsed) {
  6779.                             goto ReadData;
  6780.                         }
  6781.                         // surrogate chars
  6782.                         else {
  6783.                             char ch = chars[pos];
  6784.                             if (ch >= SurHighStart && ch <= SurHighEnd) {
  6785.                                 if (pos + 1 == ps.charsUsed) {
  6786.                                     goto ReadData;
  6787.                                 }
  6788.                                 pos++;
  6789.                                 if (chars[pos] >= SurLowStart && chars[pos] <= SurLowEnd) {
  6790.                                     pos++;
  6791.                                     continue;
  6792.                                 }
  6793.                             }
  6794.                             ThrowInvalidChar(pos, ch);
  6795.                             break;
  6796.                         }
  6797.                         break;
  6798.                 }
  6799.                 ReadData:
  6800.                
  6801.                 if (pos - ps.charPos > 0) {
  6802.                     stringBuilder.Append(chars, ps.charPos, pos - ps.charPos);
  6803.                     ps.charPos = pos;
  6804.                 }
  6805.                 // read new characters into the buffer
  6806.                 if (ReadData() == 0) {
  6807.                     if (stringBuilder.Length > 0) {
  6808.                         goto ReturnText;
  6809.                     }
  6810.                     else {
  6811.                         if (HandleEntityEnd(false)) {
  6812.                             SetupEndEntityNodeInAttribute();
  6813.                             return true;
  6814.                         }
  6815.                         else {
  6816.                             Debug.Assert(false, "We should never get to this point.");
  6817.                         }
  6818.                     }
  6819.                 }
  6820.                
  6821.                 pos = ps.charPos;
  6822.                 chars = ps.chars;
  6823.             }
  6824.             ReturnText:
  6825.            
  6826.             if (pos - ps.charPos > 0) {
  6827.                 stringBuilder.Append(chars, ps.charPos, pos - ps.charPos);
  6828.                 ps.charPos = pos;
  6829.             }
  6830.             curNode.SetValueNode(XmlNodeType.Text, stringBuilder.ToString());
  6831.             stringBuilder.Length = 0;
  6832.             return true;
  6833.         }
  6834.        
  6835.         private void ParseXmlDeclarationFragment()
  6836.         {
  6837.             try {
  6838.                 ParseXmlDeclaration(false);
  6839.             }
  6840.             catch (XmlException e) {
  6841.                 ReThrow(e, e.LineNumber, e.LinePosition - 6);
  6842.                 // 6 == strlen( "<?xml " );
  6843.             }
  6844.         }
  6845.        
  6846.         private void ThrowUnexpectedToken(int pos, string expectedToken)
  6847.         {
  6848.             ThrowUnexpectedToken(pos, expectedToken, null);
  6849.         }
  6850.        
  6851.         private void ThrowUnexpectedToken(string expectedToken1)
  6852.         {
  6853.             ThrowUnexpectedToken(expectedToken1, null);
  6854.         }
  6855.        
  6856.         private void ThrowUnexpectedToken(int pos, string expectedToken1, string expectedToken2)
  6857.         {
  6858.             ps.charPos = pos;
  6859.             ThrowUnexpectedToken(expectedToken1, expectedToken2);
  6860.         }
  6861.        
  6862.         private void ThrowUnexpectedToken(string expectedToken1, string expectedToken2)
  6863.         {
  6864.             string unexpectedToken = ParseUnexpectedToken();
  6865.             if (expectedToken2 != null) {
  6866.                 Throw(Res.Xml_UnexpectedTokens2, new string[3] {unexpectedToken, expectedToken1, expectedToken2});
  6867.             }
  6868.             else {
  6869.                 Throw(Res.Xml_UnexpectedTokenEx, new string[2] {unexpectedToken, expectedToken1});
  6870.             }
  6871.         }
  6872.        
  6873.         private string ParseUnexpectedToken(int pos)
  6874.         {
  6875.             ps.charPos = pos;
  6876.             return ParseUnexpectedToken();
  6877.         }
  6878.        
  6879.         private string ParseUnexpectedToken()
  6880.         {
  6881.             if (xmlCharType.IsNCNameChar(ps.chars[ps.charPos])) {
  6882.                 int pos = ps.charPos + 1;
  6883.                 while (xmlCharType.IsNCNameChar(ps.chars[pos])) {
  6884.                     pos++;
  6885.                 }
  6886.                 return new string(ps.chars, ps.charPos, pos - ps.charPos);
  6887.             }
  6888.             else {
  6889.                 Debug.Assert(ps.charPos < ps.charsUsed);
  6890.                 return new string(ps.chars, ps.charPos, 1);
  6891.             }
  6892.         }
  6893.        
  6894.         private int GetIndexOfAttributeWithoutPrefix(string name)
  6895.         {
  6896.             name = nameTable.Get(name);
  6897.             if (name == null) {
  6898.                 return -1;
  6899.             }
  6900.             for (int i = index + 1; i < index + attrCount + 1; i++) {
  6901.                 if (Ref.Equal(nodes[i].localName, name) && nodes[i].prefix.Length == 0) {
  6902.                     return i;
  6903.                 }
  6904.             }
  6905.             return -1;
  6906.         }
  6907.        
  6908.         private int GetIndexOfAttributeWithPrefix(string name)
  6909.         {
  6910.             name = nameTable.Add(name);
  6911.             if (name == null) {
  6912.                 return -1;
  6913.             }
  6914.             for (int i = index + 1; i < index + attrCount + 1; i++) {
  6915.                 if (Ref.Equal(nodes[i].GetNameWPrefix(nameTable), name)) {
  6916.                     return i;
  6917.                 }
  6918.             }
  6919.             return -1;
  6920.         }
  6921.        
  6922.         private Stream OpenStream(Uri uri)
  6923.         {
  6924.             // resolve the stream
  6925.             return (Stream)xmlResolver.GetEntity(uri, null, typeof(Stream));
  6926.         }
  6927.        
  6928.         // This method is used to enable parsing of zero-terminated streams. The old XmlTextReader implementation used
  6929.         // to parse such streams, we this one needs to do that as well.
  6930.         // If the last characters decoded from the stream is 0 and the stream is in EOF state, this method will remove
  6931.         // the character from the parsing buffer (decrements ps.charsUsed).
  6932.         // Note that this method calls ReadData() which may change the value of ps.chars and ps.charPos.
  6933.         private bool ZeroEndingStream(int pos)
  6934.         {
  6935.             if (v1Compat && pos == ps.charsUsed - 1 && ps.chars[pos] == (char)0 && ReadData() == 0 && ps.isStreamEof) {
  6936.                 ps.charsUsed--;
  6937.                 return true;
  6938.             }
  6939.             return false;
  6940.         }
  6941.        
  6942.         private void ParseDtdFromParserContext()
  6943.         {
  6944.             Debug.Assert(dtdParserProxy == null && fragmentParserContext != null && fragmentParserContext.HasDtdInfo);
  6945.            
  6946.             dtdParserProxy = new DtdParserProxy(fragmentParserContext.BaseURI, fragmentParserContext.DocTypeName, fragmentParserContext.PublicId, fragmentParserContext.SystemId, fragmentParserContext.InternalSubset, this);
  6947.             dtdParserProxy.Parse(false);
  6948.            
  6949.             SchemaInfo dtdSchemaInfo = dtdParserProxy.DtdSchemaInfo;
  6950.             if ((validatingReaderCompatFlag || !v1Compat) && (dtdSchemaInfo.HasDefaultAttributes || dtdSchemaInfo.HasNonCDataAttributes)) {
  6951.                 addDefaultAttributesAndNormalize = true;
  6952.                 qName = new XmlQualifiedName();
  6953.             }
  6954.         }
  6955.        
  6956.         bool InitReadContentAsBinary()
  6957.         {
  6958.             Debug.Assert(parsingFunction != ParsingFunction.InReadContentAsBinary);
  6959.            
  6960.             if (parsingFunction == ParsingFunction.InReadValueChunk) {
  6961.                 throw new InvalidOperationException(Res.GetString(Res.Xml_MixingReadValueChunkWithBinary));
  6962.             }
  6963.             if (parsingFunction == ParsingFunction.InIncrementalRead) {
  6964.                 throw new InvalidOperationException(Res.GetString(Res.Xml_MixingV1StreamingWithV2Binary));
  6965.             }
  6966.            
  6967.             if (!XmlReader.IsTextualNode(curNode.type)) {
  6968.                 if (!MoveToNextContentNode(false)) {
  6969.                     return false;
  6970.                 }
  6971.             }
  6972.            
  6973.             SetupReadContentAsBinaryState(ParsingFunction.InReadContentAsBinary);
  6974.             incReadLineInfo.Set(curNode.LineNo, curNode.LinePos);
  6975.             return true;
  6976.         }
  6977.        
  6978.         bool InitReadElementContentAsBinary()
  6979.         {
  6980.             Debug.Assert(parsingFunction != ParsingFunction.InReadElementContentAsBinary);
  6981.             Debug.Assert(curNode.type == XmlNodeType.Element);
  6982.            
  6983.             bool isEmpty = curNode.IsEmptyElement;
  6984.            
  6985.             // move to content or off the empty element
  6986.             outerReader.Read();
  6987.             if (isEmpty) {
  6988.                 return false;
  6989.             }
  6990.            
  6991.             // make sure we are on a content node
  6992.             if (!MoveToNextContentNode(false)) {
  6993.                 if (curNode.type != XmlNodeType.EndElement) {
  6994.                     Throw(Res.Xml_InvalidNodeType, curNode.type.ToString());
  6995.                 }
  6996.                 // move off end element
  6997.                 outerReader.Read();
  6998.                 return false;
  6999.             }
  7000.             SetupReadContentAsBinaryState(ParsingFunction.InReadElementContentAsBinary);
  7001.             incReadLineInfo.Set(curNode.LineNo, curNode.LinePos);
  7002.             return true;
  7003.         }
  7004.        
  7005.         bool MoveToNextContentNode(bool moveIfOnContentNode)
  7006.         {
  7007.             do {
  7008.                 switch (curNode.type) {
  7009.                     case XmlNodeType.Attribute:
  7010.                         return !moveIfOnContentNode;
  7011.                     case XmlNodeType.Text:
  7012.                     case XmlNodeType.Whitespace:
  7013.                     case XmlNodeType.SignificantWhitespace:
  7014.                     case XmlNodeType.CDATA:
  7015.                         if (!moveIfOnContentNode) {
  7016.                             return true;
  7017.                         }
  7018.                         break;
  7019.                     case XmlNodeType.ProcessingInstruction:
  7020.                     case XmlNodeType.Comment:
  7021.                     case XmlNodeType.EndEntity:
  7022.                         // skip comments, pis and end entity nodes
  7023.                         break;
  7024.                     case XmlNodeType.EntityReference:
  7025.                         outerReader.ResolveEntity();
  7026.                         break;
  7027.                     default:
  7028.                         return false;
  7029.                 }
  7030.                 moveIfOnContentNode = false;
  7031.             }
  7032.             while (outerReader.Read());
  7033.             return false;
  7034.         }
  7035.        
  7036.         void SetupReadContentAsBinaryState(ParsingFunction inReadBinaryFunction)
  7037.         {
  7038.             if (parsingFunction == ParsingFunction.PartialTextValue) {
  7039.                 incReadState = IncrementalReadState.ReadContentAsBinary_OnPartialValue;
  7040.             }
  7041.             else {
  7042.                 incReadState = IncrementalReadState.ReadContentAsBinary_OnCachedValue;
  7043.                 nextNextParsingFunction = nextParsingFunction;
  7044.                 nextParsingFunction = parsingFunction;
  7045.             }
  7046.             readValueOffset = 0;
  7047.             parsingFunction = inReadBinaryFunction;
  7048.         }
  7049.        
  7050.         void SetupFromParserContext(XmlParserContext context, XmlReaderSettings settings)
  7051.         {
  7052.             Debug.Assert(context != null);
  7053.            
  7054.             // setup nameTable
  7055.             XmlNameTable nt = settings.NameTable;
  7056.             nameTableFromSettings = (nt != null);
  7057.            
  7058.             // get name table from namespace manager in XmlParserContext, if available;
  7059.             if (context.NamespaceManager != null) {
  7060.                 // must be the same as XmlReaderSettings.NameTable, or null
  7061.                 if (nt != null && nt != context.NamespaceManager.NameTable) {
  7062.                     throw new XmlException(Res.Xml_NametableMismatch);
  7063.                 }
  7064.                 // get the namespace manager from context
  7065.                 namespaceManager = context.NamespaceManager;
  7066.                 xmlContext.defaultNamespace = namespaceManager.LookupNamespace(string.Empty);
  7067.                
  7068.                 // get the nametable from ns manager
  7069.                 nt = namespaceManager.NameTable;
  7070.                
  7071.                 Debug.Assert(nt != null);
  7072.                 Debug.Assert(context.NameTable == null || context.NameTable == nt, "This check should have been done in XmlParserContext constructor.");
  7073.             }
  7074.             // get name table directly from XmlParserContext
  7075.             else if (context.NameTable != null) {
  7076.                 // must be the same as XmlReaderSettings.NameTable, or null
  7077.                 if (nt != null && nt != context.NameTable) {
  7078.                     throw new XmlException(Res.Xml_NametableMismatch);
  7079.                 }
  7080.                 nt = context.NameTable;
  7081.             }
  7082.             // no nametable provided -> create a new one
  7083.             else if (nt == null) {
  7084.                 nt = new NameTable();
  7085.                 Debug.Assert(nameTableFromSettings == false);
  7086.             }
  7087.             nameTable = nt;
  7088.            
  7089.             // make sure we have namespace manager
  7090.             if (namespaceManager == null) {
  7091.                 namespaceManager = new XmlNamespaceManager(nt);
  7092.             }
  7093.            
  7094.             // copy xml:space and xml:lang
  7095.             xmlContext.xmlSpace = context.XmlSpace;
  7096.             xmlContext.xmlLang = context.XmlLang;
  7097.         }
  7098.        
  7099.         //
  7100.         // Internal properties for XmlValidatingReader
  7101.         //
  7102.         internal SchemaInfo DtdSchemaInfo {
  7103.             get { return dtdParserProxy == null ? null : dtdParserProxy.DtdSchemaInfo; }
  7104.             set {
  7105.                 Debug.Assert(dtdParserProxy == null);
  7106.                
  7107.                 if (value != null) {
  7108.                     dtdParserProxy = new DtdParserProxy(this, value);
  7109.                     if ((validatingReaderCompatFlag || !v1Compat) && (value.HasDefaultAttributes || value.HasNonCDataAttributes)) {
  7110.                         addDefaultAttributesAndNormalize = true;
  7111.                         qName = new XmlQualifiedName();
  7112.                     }
  7113.                 }
  7114.                 else {
  7115.                     dtdParserProxy = null;
  7116.                 }
  7117.             }
  7118.         }
  7119.        
  7120.         internal bool XmlValidatingReaderCompatibilityMode {
  7121.             set { validatingReaderCompatFlag = value; }
  7122.         }
  7123.        
  7124.         internal ValidationEventHandler ValidationEventHandler {
  7125.             set { validationEventHandler = value; }
  7126.         }
  7127.        
  7128.         internal XmlNodeType FragmentType {
  7129.             get { return fragmentType; }
  7130.         }
  7131.        
  7132.         internal void ChangeCurrentNodeType(XmlNodeType newNodeType)
  7133.         {
  7134.             Debug.Assert(curNode.type == XmlNodeType.Whitespace && newNodeType == XmlNodeType.SignificantWhitespace, "Incorrect node type change!");
  7135.             curNode.type = newNodeType;
  7136.         }
  7137.        
  7138.         internal XmlResolver GetResolver()
  7139.         {
  7140.             return xmlResolver;
  7141.         }
  7142.        
  7143.         internal object InternalSchemaType {
  7144.             get { return curNode.schemaType; }
  7145.             set { curNode.schemaType = value; }
  7146.         }
  7147.        
  7148.         internal object InternalTypedValue {
  7149.             get { return curNode.typedValue; }
  7150.             set { curNode.typedValue = value; }
  7151.         }
  7152.        
  7153.         internal bool StandAlone {
  7154.             get { return standalone; }
  7155.         }
  7156.        
  7157.         internal override XmlNamespaceManager NamespaceManager {
  7158.             get { return namespaceManager; }
  7159.         }
  7160.        
  7161.         internal bool V1Compat {
  7162.             get { return v1Compat; }
  7163.         }
  7164.        
  7165.         internal ConformanceLevel V1ComformanceLevel {
  7166.             get { return fragmentType == XmlNodeType.Element ? ConformanceLevel.Fragment : ConformanceLevel.Document; }
  7167.         }
  7168.        
  7169.         internal bool AddDefaultAttribute(SchemaAttDef attrDef, bool definedInDtd)
  7170.         {
  7171.             string localName = attrDef.Name.Name;
  7172.             string prefix = attrDef.Prefix;
  7173.             string ns = attrDef.Name.Namespace;
  7174.            
  7175.             // DTD default attribute
  7176.             if (definedInDtd) {
  7177.                 if (prefix.Length > 0) {
  7178.                     attrNeedNamespaceLookup = true;
  7179.                 }
  7180.             }
  7181.             // XSD/XDR default attribute
  7182.             else {
  7183.                 // atomize namesspace - Xsd Validator does not need to have the same nametable
  7184.                 ns = nameTable.Add(ns);
  7185.                 if (prefix.Length == 0 && ns.Length > 0) {
  7186.                     prefix = namespaceManager.LookupPrefix(ns);
  7187.                    
  7188.                     Debug.Assert(prefix != null);
  7189.                     if (prefix == null) {
  7190.                         prefix = string.Empty;
  7191.                     }
  7192.                 }
  7193.             }
  7194.            
  7195.             // atomize names - Xsd Validator does not need to have the same nametable
  7196.             localName = nameTable.Add(localName);
  7197.             prefix = nameTable.Add(prefix);
  7198.            
  7199.             // check for duplicates
  7200.             for (int i = index + 1; i < index + 1 + attrCount; i++) {
  7201.                 if ((object)nodes[i].localName == (object)localName && (((object)nodes[i].prefix == (object)prefix) || ((object)nodes[i].ns == (object)ns && ns != null))) {
  7202.                     return false;
  7203.                 }
  7204.             }
  7205.            
  7206.             // check the default attribute value if it has a valid value according to its type
  7207.             if (definedInDtd && DtdValidation && !attrDef.DefaultValueChecked) {
  7208.                 attrDef.CheckDefaultValue(dtdParserProxy.DtdSchemaInfo, dtdParserProxy);
  7209.             }
  7210.            
  7211.             // setup the attribute
  7212.             NodeData attr = AddAttribute(localName, prefix, prefix.Length > 0 ? null : localName);
  7213.             if (!definedInDtd) {
  7214.                 Debug.Assert(ns != null);
  7215.                 attr.ns = ns;
  7216.             }
  7217.             attr.SetValue(attrDef.DefaultValueExpanded);
  7218.             attr.IsDefaultAttribute = true;
  7219.             attr.schemaType = (attrDef.SchemaType == null) ? (object)attrDef.Datatype : (object)attrDef.SchemaType;
  7220.             attr.typedValue = attrDef.DefaultValueTyped;
  7221.             attr.lineInfo.Set(attrDef.LineNum, attrDef.LinePos);
  7222.             attr.lineInfo2.Set(attrDef.ValueLineNum, attrDef.ValueLinePos);
  7223.            
  7224.             // handle special attributes:
  7225.             if (attr.prefix.Length == 0) {
  7226.                 // default namespace declaration
  7227.                 if (Ref.Equal(attr.localName, XmlNs)) {
  7228.                     OnDefaultNamespaceDecl(attr);
  7229.                     if (!definedInDtd) {
  7230.                         // change element default namespace
  7231.                         Debug.Assert(nodes[index].type == XmlNodeType.Element);
  7232.                         if (nodes[index].prefix.Length == 0) {
  7233.                             nodes[index].ns = xmlContext.defaultNamespace;
  7234.                         }
  7235.                     }
  7236.                 }
  7237.             }
  7238.             else {
  7239.                 // prefixed namespace declaration
  7240.                 if (Ref.Equal(attr.prefix, XmlNs)) {
  7241.                     OnNamespaceDecl(attr);
  7242.                     if (!definedInDtd) {
  7243.                         // change namespace of current element and attributes
  7244.                         string pref = attr.localName;
  7245.                         Debug.Assert(nodes[index].type == XmlNodeType.Element);
  7246.                         for (int i = index; i < index + attrCount + 1; i++) {
  7247.                             if (nodes[i].prefix.Equals(pref)) {
  7248.                                 nodes[i].ns = namespaceManager.LookupNamespace(pref);
  7249.                             }
  7250.                         }
  7251.                     }
  7252.                 }
  7253.                 // xml: attribute
  7254.                 else {
  7255.                     if (attrDef.Reserved != SchemaAttDef.Reserve.None) {
  7256.                         OnXmlReservedAttribute(attr);
  7257.                     }
  7258.                 }
  7259.             }
  7260.            
  7261.             fullAttrCleanup = true;
  7262.             return true;
  7263.         }
  7264.        
  7265.         internal bool DisableUndeclaredEntityCheck {
  7266.             set { disableUndeclaredEntityCheck = value; }
  7267.         }
  7268.        
  7269.         int ReadContentAsBinary(byte[] buffer, int index, int count)
  7270.         {
  7271.             Debug.Assert(incReadDecoder != null);
  7272.            
  7273.             if (incReadState == IncrementalReadState.ReadContentAsBinary_End) {
  7274.                 return 0;
  7275.             }
  7276.            
  7277.             incReadDecoder.SetNextOutputBuffer(buffer, index, count);
  7278.            
  7279.             for (;;) {
  7280.                 // read what is already cached in curNode
  7281.                 int charsRead = 0;
  7282.                 try {
  7283.                     charsRead = curNode.CopyToBinary(incReadDecoder, readValueOffset);
  7284.                 }
  7285.                 // add line info to the exception
  7286.                 catch (XmlException e) {
  7287.                     curNode.AdjustLineInfo(readValueOffset, ps.eolNormalized, ref incReadLineInfo);
  7288.                     ReThrow(e, incReadLineInfo.lineNo, incReadLineInfo.linePos);
  7289.                 }
  7290.                 readValueOffset += charsRead;
  7291.                
  7292.                 if (incReadDecoder.IsFull) {
  7293.                     return incReadDecoder.DecodedCount;
  7294.                 }
  7295.                
  7296.                 // if on partial value, read the rest of it
  7297.                 if (incReadState == IncrementalReadState.ReadContentAsBinary_OnPartialValue) {
  7298.                     curNode.SetValue(string.Empty);
  7299.                    
  7300.                     // read next chunk of text
  7301.                     bool endOfValue = false;
  7302.                     int startPos = 0;
  7303.                     int endPos = 0;
  7304.                     while (!incReadDecoder.IsFull && !endOfValue) {
  7305.                         int orChars = 0;
  7306.                        
  7307.                         // store current line info and parse more text
  7308.                         incReadLineInfo.Set(ps.LineNo, ps.LinePos);
  7309.                         endOfValue = ParseText(out startPos, out endPos, ref orChars);
  7310.                        
  7311.                         try {
  7312.                             charsRead = incReadDecoder.Decode(ps.chars, startPos, endPos - startPos);
  7313.                         }
  7314.                         // add line info to the exception
  7315.                         catch (XmlException e) {
  7316.                             ReThrow(e, incReadLineInfo.lineNo, incReadLineInfo.linePos);
  7317.                         }
  7318.                         startPos += charsRead;
  7319.                     }
  7320.                     incReadState = endOfValue ? IncrementalReadState.ReadContentAsBinary_OnCachedValue : IncrementalReadState.ReadContentAsBinary_OnPartialValue;
  7321.                     readValueOffset = 0;
  7322.                    
  7323.                     if (incReadDecoder.IsFull) {
  7324.                         curNode.SetValue(ps.chars, startPos, endPos - startPos);
  7325.                         // adjust line info for the chunk that has been already decoded
  7326.                         AdjustLineInfo(ps.chars, startPos - charsRead, startPos, ps.eolNormalized, ref incReadLineInfo);
  7327.                         curNode.SetLineInfo(incReadLineInfo.lineNo, incReadLineInfo.linePos);
  7328.                         return incReadDecoder.DecodedCount;
  7329.                     }
  7330.                 }
  7331.                
  7332.                 // reset to normal state so we can call Read() to move forward
  7333.                 ParsingFunction tmp = parsingFunction;
  7334.                 parsingFunction = nextParsingFunction;
  7335.                 nextParsingFunction = nextNextParsingFunction;
  7336.                
  7337.                 // move to next textual node in the element content; throw on sub elements
  7338.                 if (!MoveToNextContentNode(true)) {
  7339.                     SetupReadContentAsBinaryState(tmp);
  7340.                     incReadState = IncrementalReadState.ReadContentAsBinary_End;
  7341.                     return incReadDecoder.DecodedCount;
  7342.                 }
  7343.                 SetupReadContentAsBinaryState(tmp);
  7344.                 incReadLineInfo.Set(curNode.LineNo, curNode.LinePos);
  7345.             }
  7346.         }
  7347.        
  7348.         int ReadElementContentAsBinary(byte[] buffer, int index, int count)
  7349.         {
  7350.             if (count == 0) {
  7351.                 return 0;
  7352.             }
  7353.             int decoded = ReadContentAsBinary(buffer, index, count);
  7354.             if (decoded > 0) {
  7355.                 return decoded;
  7356.             }
  7357.            
  7358.             // if 0 bytes returned check if we are on a closing EndElement, throw exception if not
  7359.             if (curNode.type != XmlNodeType.EndElement) {
  7360.                 throw new XmlException(Res.Xml_InvalidNodeType, curNode.type.ToString(), this as IXmlLineInfo);
  7361.             }
  7362.            
  7363.             // reset state
  7364.             parsingFunction = nextParsingFunction;
  7365.             nextParsingFunction = nextNextParsingFunction;
  7366.             Debug.Assert(parsingFunction != ParsingFunction.InReadElementContentAsBinary);
  7367.            
  7368.             // move off the EndElement
  7369.             outerReader.Read();
  7370.             return 0;
  7371.         }
  7372.        
  7373.         void InitBase64Decoder()
  7374.         {
  7375.             if (base64Decoder == null) {
  7376.                 base64Decoder = new Base64Decoder();
  7377.             }
  7378.             else {
  7379.                 base64Decoder.Reset();
  7380.             }
  7381.             incReadDecoder = base64Decoder;
  7382.         }
  7383.        
  7384.         void InitBinHexDecoder()
  7385.         {
  7386.             if (binHexDecoder == null) {
  7387.                 binHexDecoder = new BinHexDecoder();
  7388.             }
  7389.             else {
  7390.                 binHexDecoder.Reset();
  7391.             }
  7392.             incReadDecoder = binHexDecoder;
  7393.         }
  7394.        
  7395.         bool UriEqual(Uri uri1, string uri1Str, string uri2Str, XmlResolver resolver)
  7396.         {
  7397.             if (uri1 == null || resolver == null) {
  7398.                 return uri1Str == uri2Str;
  7399.             }
  7400.             Uri uri2 = resolver.ResolveUri(null, uri2Str);
  7401.             return uri1.Equals(uri2);
  7402.         }
  7403.        
  7404.         static internal void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo)
  7405.         {
  7406.             int lastNewLinePos = -1;
  7407.             int i = startPos;
  7408.             while (i < endPos) {
  7409.                 switch (chars[i]) {
  7410.                     case '\n':
  7411.                         lineInfo.lineNo++;
  7412.                         lastNewLinePos = i;
  7413.                         break;
  7414.                     case '\r':
  7415.                         if (isNormalized) {
  7416.                             break;
  7417.                         }
  7418.                         lineInfo.lineNo++;
  7419.                         lastNewLinePos = i;
  7420.                         if (i + 1 < endPos && chars[i + 1] == '\n') {
  7421.                             i++;
  7422.                             lastNewLinePos++;
  7423.                         }
  7424.                         break;
  7425.                 }
  7426.                 i++;
  7427.             }
  7428.             if (lastNewLinePos >= 0) {
  7429.                 lineInfo.linePos = endPos - lastNewLinePos;
  7430.             }
  7431.         }
  7432.     }
  7433. }

Developer Fusion