XmlTextReaderImpl.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / Core / XmlTextReaderImpl.cs / 1305376 / XmlTextReaderImpl.cs

                            //------------------------------------------------------------------------------
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
//  
// [....]
//----------------------------------------------------------------------------- 
 
using System;
using System.IO; 
using System.Text;
using System.Security;
using System.Threading;
using System.Xml.Schema; 
using System.Collections;
using System.Diagnostics; 
using System.Globalization; 
using System.Collections.Generic;
using System.Runtime.CompilerServices; 
using System.Runtime.Versioning;

#if SILVERLIGHT
using System.Reflection; 
#endif
 
#if SILVERLIGHT 
using BufferBuilder=System.Xml.BufferBuilder;
#else 
using BufferBuilder = System.Text.StringBuilder;
#endif

namespace System.Xml { 

    internal partial class XmlTextReaderImpl : XmlReader, IXmlLineInfo, IXmlNamespaceResolver { 
// 
// Private helper types
// 
        // ParsingFunction = what should the reader do when the next Read() is called
        enum ParsingFunction {
            ElementContent = 0,
            NoData, 
#if !SILVERLIGHT
            OpenUrl, 
#endif 
            SwitchToInteractive,
            SwitchToInteractiveXmlDecl, 
            DocumentContent,
            MoveToElementContent,
            PopElementContext,
            PopEmptyElementContext, 
            ResetAttributesRootLevel,
            Error, 
            Eof, 
            ReaderClosed,
            EntityReference, 
            InIncrementalRead,
#if !SILVERLIGHT  // Needed only for XmlTextReader (reporting of entities)
            FragmentAttribute,
            ReportEndEntity, 
            AfterResolveEntityInContent,
            AfterResolveEmptyEntityInContent, 
#endif 
            XmlDeclarationFragment,
            GoToEof, 
            PartialTextValue,

            // these two states must be last; see InAttributeValueIterator property
            InReadAttributeValue, 
            InReadValueChunk,
            InReadContentAsBinary, 
            InReadElementContentAsBinary, 
        }
 
        enum ParsingMode {
            Full,
            SkipNode,
            SkipContent, 
        }
 
        enum EntityType { 
            CharacterDec,
            CharacterHex, 
            CharacterNamed,
            Expanded,
            Skipped,
            FakeExpanded, 
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities)
            Unexpanded, 
            ExpandedInAttribute, 
#endif
        } 

        enum EntityExpandType {
            All,
            OnlyGeneral, 
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities)
            OnlyCharacter, 
#endif 
        }
 
        enum IncrementalReadState {
            // Following values are used in ReadText, ReadBase64 and ReadBinHex (V1 streaming methods)
            Text,
            StartTag, 
            PI,
            CDATA, 
            Comment, 
            Attributes,
            AttributeValue, 
            ReadData,
            EndElement,
            End,
 
            // Following values are used in ReadTextChunk, ReadContentAsBase64 and ReadBinHexChunk (V2 streaming methods)
            ReadValueChunk_OnCachedValue, 
            ReadValueChunk_OnPartialValue, 

            ReadContentAsBinary_OnCachedValue, 
            ReadContentAsBinary_OnPartialValue,
            ReadContentAsBinary_End,
        }
 
//
// Fields 
// 
        // XmlCharType instance
        XmlCharType xmlCharType = XmlCharType.Instance; 

        // current parsing state (aka. scanner data)
        ParsingState ps;
 
        // parsing function = what to do in the next Read() (3-items-long stack, usually used just 2 level)
        ParsingFunction parsingFunction; 
        ParsingFunction nextParsingFunction; 
        ParsingFunction nextNextParsingFunction;
 
        // stack of nodes
        NodeData[] nodes;

        // current node 
        NodeData curNode;
 
        // current index 
        int  index = 0;
 
        // attributes info
        int  curAttrIndex = -1;
        int  attrCount;
        int  attrHashtable; 
        int  attrDuplWalkCount;
        bool attrNeedNamespaceLookup; 
        bool fullAttrCleanup; 
        NodeData[] attrDuplSortingArray;
 
        // name table
        XmlNameTable nameTable;
        bool         nameTableFromSettings;
 
        // resolver
        XmlResolver         xmlResolver; 
 
#if !SILVERLIGHT // Needed only for XmlTextReader constructors that takes url
        // this is only for constructors that takes url 
        string              url = string.Empty;
        CompressedStack     compressedStack;
#endif
 
        // settings
        bool                normalize; 
        bool                supportNamespaces = true; 
        WhitespaceHandling  whitespaceHandling;
        DtdProcessing       dtdProcessing = DtdProcessing.Parse; 
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities)
        EntityHandling      entityHandling;
#endif
        bool                ignorePIs; 
        bool                ignoreComments;
        bool                checkCharacters; 
        int                 lineNumberOffset; 
        int                 linePositionOffset;
        bool                closeInput; 
        long                maxCharactersInDocument;
        long                maxCharactersFromEntities;

        // this flag enables XmlTextReader backwards compatibility; 
        // when false, the reader has been created via XmlReader.Create
        bool                v1Compat; 
 
        // namespace handling
        XmlNamespaceManager namespaceManager; 
        string lastPrefix = string.Empty;

        // xml context (xml:space, xml:lang, default namespace)
        XmlContext              xmlContext; 

        // stack of parsing states (=stack of entities) 
        private ParsingState[]  parsingStatesStack; 
        private int             parsingStatesStackTop = -1;
 
        // current node base uri and encoding
        string      reportedBaseUri;
        Encoding    reportedEncoding;
 
        // DTD
        IDtdInfo  dtdInfo; 
 
        // fragment parsing
        XmlNodeType         fragmentType = XmlNodeType.Document; 
        XmlParserContext    fragmentParserContext;
#if !SILVERLIGHT // Needed only for XmlTextReader
        bool                fragment;
#endif 

        // incremental read 
        IncrementalReadDecoder      incReadDecoder; 
        IncrementalReadState        incReadState;
        LineInfo                    incReadLineInfo; 
        BinHexDecoder               binHexDecoder;
        Base64Decoder               base64Decoder;
#if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex)
        int                         incReadDepth; 
        int                         incReadLeftStartPos;
        int                         incReadLeftEndPos; 
        IncrementalReadCharsDecoder readCharsDecoder; 
#endif
 
        // ReadAttributeValue helpers
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities)
        int     attributeValueBaseEntityId;
        bool    emptyEntityInAttributeResolved; 
#endif
 
        // Validation helpers 
#if !SILVERLIGHT // No validation in Silverlight
        IValidationEventHandling validationEventHandling; 
        OnDefaultAttributeUseDelegate onDefaultAttributeUse;
#endif

#if !SILVERLIGHT // Needed only for XmlTextReader and XmlValidatingReader 
        bool                    validatingReaderCompatFlag;
#endif 
 
        // misc
        bool            addDefaultAttributesAndNormalize; 
        BufferBuilder   stringBuilder;
        bool            rootElementParsed;
        bool            standalone;
        int             nextEntityId = 1; 
        ParsingMode     parsingMode;
        ReadState       readState = ReadState.Initial; 
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities, ResetState) 
        IDtdEntityInfo  lastEntity;
        bool            afterResetState; 
#endif
        int documentStartBytePos;
        int readValueOffset;
 
        // Counters for security settings
        long charactersInDocument; 
        long charactersFromEntities; 

        // All entities that are currently being processed 
        Dictionary currentEntities;

        // DOM helpers
#if !SILVERLIGHT // Needed only for XmlTextReader (when used from XmlDocument) 
        bool            disableUndeclaredEntityCheck;
#endif 
 
        // Outer XmlReader exposed to the user - either XmlTextReader or XmlTextReaderImpl (when created via XmlReader.Create).
        // Virtual methods called from within XmlTextReaderImpl must be called on the outer reader so in case the user overrides 
        // some of the XmlTextReader methods we will call the overriden version.
        XmlReader       outerReader;

// 
// Atomized string constants
// 
        private string Xml; 
        private string XmlNs;
 
//
// Constants
//
        private const int MaxBytesToMove = 128; 
        private const int ApproxXmlDeclLength = 80;
        private const int NodesInitialSize = 8; 
        private const int InitialAttributesCount = 4; 
        private const int InitialParsingStateStackSize = 2;
        private const int InitialParsingStatesDepth = 2; 
        private const int DtdChidrenInitialSize = 2;
        private const int MaxByteSequenceLen = 6;  // max bytes per character
        private const int MaxAttrDuplWalkCount = 250;
        private const int MinWhitespaceLookahedCount = 4096; 

        private const string XmlDeclarationBegining = "" ) );
            InitFragmentReader( XmlNodeType.XmlDeclaration, context, true );
        } 

        // Initializes a new instance of the XmlTextReaderImpl class with the specified url and XmlNameTable. 
        // This constructor is used when creating XmlTextReaderImpl for V1 XmlTextReader 
#if !SILVERLIGHT
        [ResourceConsumption(ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.Machine)]
#endif
        public XmlTextReaderImpl( string url ) : this( url, new NameTable() ) {
        } 

#if !SILVERLIGHT 
        [ResourceConsumption(ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.Machine)]
#endif 
        public XmlTextReaderImpl( string url, XmlNameTable nt ): this( nt ) {
            if ( url == null ) {
                throw new ArgumentNullException( "url" );
            } 
            if ( url.Length == 0 ) {
                throw new ArgumentException( Res.GetString( Res.Xml_EmptyUrl ), "url" ); 
            } 
            namespaceManager = new XmlNamespaceManager( nt );
 
            compressedStack = CompressedStack.Capture();

            this.url = url;
 
            ps.baseUri = xmlResolver.ResolveUri( null, url );
            ps.baseUriStr = ps.baseUri.ToString(); 
            reportedBaseUri = ps.baseUriStr; 

            parsingFunction = ParsingFunction.OpenUrl; 
        }
#endif

        // Initializes a new instance of the XmlTextReaderImpl class with the specified arguments. 
        // This constructor is used when creating XmlTextReaderImpl via XmlReader.Create
        internal XmlTextReaderImpl( Stream stream, byte[] bytes, int byteCount, XmlReaderSettings settings, Uri baseUri, string baseUriStr, 
                                    XmlParserContext context, bool closeInput ) 
            : this( settings.GetXmlResolver(), settings, context ) {
 
            Encoding enc = null;

            // get BaseUri and Encoding from XmlParserContext
            if ( context != null ) { 
                if ( context.BaseURI != null && context.BaseURI.Length > 0 &&
                    !UriEqual( baseUri, baseUriStr, context.BaseURI, settings.GetXmlResolver() ) ) { 
                    if ( baseUriStr.Length > 0 ) { 
                        Throw( Res.Xml_DoubleBaseUri );
                    } 
                    Debug.Assert( baseUri == null );
                    baseUriStr = context.BaseURI;
                }
                enc = context.Encoding; 
            }
 
            // init ParsingState 
            InitStreamInput( baseUri, baseUriStr, stream, bytes, byteCount, enc );
 
            this.closeInput = closeInput;

            reportedBaseUri = ps.baseUriStr;
            reportedEncoding = ps.encoding; 

            // parse DTD 
            if ( context != null && context.HasDtdInfo ) { 
                ProcessDtdFromParserContext(context);
            } 
        }

        // Initializes a new instance of the XmlTextReaderImpl class with the specified arguments.
        // This constructor is used when creating XmlTextReaderImpl via XmlReader.Create 
        internal XmlTextReaderImpl( TextReader input, XmlReaderSettings settings, string baseUriStr, XmlParserContext context )
            : this( settings.GetXmlResolver(), settings, context ) { 
 
            // get BaseUri from XmlParserContext
            if ( context != null ) { 
                Debug.Assert( baseUriStr == string.Empty, "BaseURI can come either from XmlParserContext or from the constructor argument, not from both" );
                if ( context.BaseURI != null ) {
                    baseUriStr = context.BaseURI;
                } 
            }
 
            // init ParsingState 
            InitTextReaderInput( baseUriStr, input );
 
            this.closeInput = settings.CloseInput;

            reportedBaseUri = ps.baseUriStr;
            reportedEncoding = ps.encoding; 

            // parse DTD 
            if ( context != null && context.HasDtdInfo ) { 
                ProcessDtdFromParserContext( context);
            } 
        }

#if !SILVERLIGHT
        // Initializes a new instance of the XmlTextReaderImpl class for fragment parsing. 
        // This constructor is used by XmlBinaryReader for nested text XML
        internal XmlTextReaderImpl( string xmlFragment, XmlParserContext context, XmlReaderSettings settings ) 
            : this( null, settings, context ) { 
            InitStringInput( string.Empty, Encoding.Unicode, xmlFragment );
            reportedBaseUri = ps.baseUriStr; 
            reportedEncoding = ps.encoding;
        }
#endif
 
//
// XmlReader members 
// 
        // Returns the current settings of the reader
        public override XmlReaderSettings Settings { 
            get {
                XmlReaderSettings settings = new XmlReaderSettings();

                if (nameTableFromSettings) { 
                    settings.NameTable = nameTable;
                } 
 
                switch (fragmentType) {
                    case XmlNodeType.None: settings.ConformanceLevel = ConformanceLevel.Auto; break; 
                    case XmlNodeType.Element: settings.ConformanceLevel = ConformanceLevel.Fragment; break;
                    case XmlNodeType.Document: settings.ConformanceLevel = ConformanceLevel.Document; break;
                    default: Debug.Assert(false); goto case XmlNodeType.None;
                } 
                settings.CheckCharacters = checkCharacters;
                settings.LineNumberOffset = lineNumberOffset; 
                settings.LinePositionOffset = linePositionOffset; 
                settings.IgnoreWhitespace = (whitespaceHandling == WhitespaceHandling.Significant);
                settings.IgnoreProcessingInstructions = ignorePIs; 
                settings.IgnoreComments = ignoreComments;
                settings.DtdProcessing = dtdProcessing;
                settings.MaxCharactersInDocument = maxCharactersInDocument;
                settings.MaxCharactersFromEntities = maxCharactersFromEntities; 

                settings.ReadOnly = true; 
                return settings; 
            }
        } 

        // Returns the type of the current node.
        public override XmlNodeType NodeType {
            get { 
                return curNode.type;
            } 
        } 

        // Returns the name of the current node, including prefix. 
        public override string Name {
            get {
                return curNode.GetNameWPrefix( nameTable );
            } 
        }
 
        // Returns local name of the current node (without prefix) 
        public override string LocalName {
            get { 
                return curNode.localName;
            }
        }
 
        // Returns namespace name of the current node.
        public override string NamespaceURI { 
            get { 
                return curNode.ns;
            } 
        }

        // Returns prefix associated with the current node.
        public override string Prefix { 
            get {
                return curNode.prefix; 
            } 
        }
 
        // Returns the text value of the current node.
        public override string Value {
            get {
                if ( parsingFunction >= ParsingFunction.PartialTextValue ) { 
                    if ( parsingFunction == ParsingFunction.PartialTextValue ) {
                        FinishPartialValue(); 
                        parsingFunction = nextParsingFunction; 
                    }
                    else { 
                        FinishOtherValueIterator();
                    }
                }
                return curNode.StringValue; 
            }
        } 
 
        // Returns the depth of the current node in the XML element stack
        public override int Depth { 
            get {
                return curNode.depth;
            }
        } 

        // Returns the base URI of the current node. 
        public override string BaseURI { 
            get {
                return reportedBaseUri; 
            }
        }

        // Returns true if the current node is an empty element (for example, ). 
        public override bool IsEmptyElement {
            get { 
                return curNode.IsEmptyElement; 
            }
        } 

        // Returns true of the current node is a default attribute declared in DTD.
        public override bool IsDefault {
            get { 
                return curNode.IsDefaultAttribute;
            } 
        } 

#if !SILVERLIGHT 
        // Returns the quote character used in the current attribute declaration
        public override char QuoteChar {
            get {
                return curNode.type == XmlNodeType.Attribute ? curNode.quoteChar : '"'; 
            }
        } 
#endif 

        // Returns the current xml:space scope. 
        public override XmlSpace XmlSpace {
            get {
                return xmlContext.xmlSpace;
            } 
        }
 
        // Returns the current xml:lang scope. 
        public override string XmlLang {
            get { 
                return xmlContext.xmlLang;
            }
        }
 
        // Returns the current read state of the reader
        public override ReadState ReadState { 
            get { 
                return readState;
            } 
        }

        // Returns true if the reader reached end of the input data
        public override bool EOF { 
            get {
                return parsingFunction == ParsingFunction.Eof; 
            } 
        }
 
        // Returns the XmlNameTable associated with this XmlReader
        public override XmlNameTable NameTable {
            get {
                return nameTable; 
            }
        } 
 
        // Returns true if the XmlReader knows how to resolve general entities
        public override bool CanResolveEntity  { 
            get  {
                return true;
            }
        } 

        // Returns the number of attributes on the current node. 
        public override int AttributeCount { 
            get {
                return attrCount; 
            }
        }

        // Returns value of an attribute with the specified Name 
        public override string GetAttribute( string name ) {
            int i; 
            if ( name.IndexOf( ':' ) == -1 ) { 
                i = GetIndexOfAttributeWithoutPrefix( name );
            } 
            else {
                i = GetIndexOfAttributeWithPrefix( name );
            }
            return ( i >= 0 ) ? nodes[i].StringValue : null; 
        }
 
        // Returns value of an attribute with the specified LocalName and NamespaceURI 
        public override string GetAttribute( string localName, string namespaceURI ) {
            namespaceURI = ( namespaceURI == null ) ? string.Empty : nameTable.Get( namespaceURI ); 
            localName = nameTable.Get( localName );
            for ( int i = index + 1; i < index + attrCount + 1; i++ ) {
                if ( Ref.Equal( nodes[i].localName, localName ) && Ref.Equal( nodes[i].ns, namespaceURI ) ) {
                    return nodes[i].StringValue; 
                }
            } 
            return null; 
        }
 
        // Returns value of an attribute at the specified index (position)
        public override string GetAttribute( int i ) {
            if ( i < 0 || i >= attrCount ) {
                throw new ArgumentOutOfRangeException("i"); 
            }
            return nodes[index + i + 1].StringValue; 
        } 

        // Moves to an attribute with the specified Name 
        public override bool MoveToAttribute( string name ) {
            int i;
            if ( name.IndexOf( ':' ) == -1 ) {
                i = GetIndexOfAttributeWithoutPrefix( name ); 
            }
            else { 
                i = GetIndexOfAttributeWithPrefix( name ); 
            }
 
            if ( i >= 0 ) {
                if ( InAttributeValueIterator ) {
                    FinishAttributeValueIterator();
                } 
                curAttrIndex = i - index - 1;
                curNode = nodes[i]; 
                return true; 
            }
            else { 
                return false;
            }
        }
 
        // Moves to an attribute with the specified LocalName and NamespceURI
        public override bool MoveToAttribute( string localName, string namespaceURI ) { 
            namespaceURI = ( namespaceURI == null ) ? string.Empty : nameTable.Get( namespaceURI ); 
            localName = nameTable.Get( localName );
            for ( int i = index + 1; i < index + attrCount + 1; i++ ) { 
                if ( Ref.Equal( nodes[i].localName, localName ) &&
                     Ref.Equal( nodes[i].ns, namespaceURI ) ) {
                    curAttrIndex = i - index - 1;
                    curNode = nodes[i]; 

                    if ( InAttributeValueIterator ) { 
                        FinishAttributeValueIterator(); 
                    }
                    return true; 
                }
            }
            return false;
        } 

        // Moves to an attribute at the specified index (position) 
        public override void MoveToAttribute( int i ) { 
            if ( i < 0 || i >= attrCount ) {
                throw new ArgumentOutOfRangeException( "i" ); 
            }

            if ( InAttributeValueIterator ) {
                FinishAttributeValueIterator(); 
            }
            curAttrIndex = i; 
            curNode = nodes[index + 1 + curAttrIndex]; 
        }
 
        // Moves to the first attribute of the current node
        public override bool MoveToFirstAttribute() {
            if ( attrCount == 0 ) {
                return false; 
            }
 
            if ( InAttributeValueIterator ) { 
                FinishAttributeValueIterator();
            } 

            curAttrIndex = 0;
            curNode = nodes[index + 1];
 
            return true;
        } 
 
        // Moves to the next attribute of the current node
        public override bool MoveToNextAttribute() { 
            if ( curAttrIndex + 1 < attrCount ) {
                if ( InAttributeValueIterator ) {
                    FinishAttributeValueIterator();
                } 
                curNode = nodes[ index + 1 + ++curAttrIndex  ];
                return true; 
            } 
            return false;
        } 

        // If on attribute, moves to the element that contains the attribute node
        public override bool MoveToElement() {
            if ( InAttributeValueIterator ) { 
                FinishAttributeValueIterator();
            } 
            else if ( curNode.type != XmlNodeType.Attribute ) { 
                return false;
            } 
            curAttrIndex = -1;
            curNode = nodes[index];

            return true; 
        }
 
        // Reads next node from the input data 
        public override bool Read() {
            for (;;) { 
                switch ( parsingFunction ) {
                    case ParsingFunction.ElementContent:
                        return ParseElementContent();
                    case ParsingFunction.DocumentContent: 
                        return ParseDocumentContent();
#if !SILVERLIGHT // Needed only for XmlTextReader 
                    case ParsingFunction.OpenUrl: 
                        OpenUrl();
                        Debug.Assert( nextParsingFunction == ParsingFunction.DocumentContent ); 
                        goto case ParsingFunction.SwitchToInteractiveXmlDecl;
#endif
                    case ParsingFunction.SwitchToInteractive:
                        Debug.Assert( !ps.appendMode ); 
                        readState = ReadState.Interactive;
                        parsingFunction = nextParsingFunction; 
                        continue; 
                    case ParsingFunction.SwitchToInteractiveXmlDecl:
                        readState = ReadState.Interactive; 
                        parsingFunction = nextParsingFunction;
                        if ( ParseXmlDeclaration( false ) ) {
                            reportedEncoding = ps.encoding;
                            return true; 
                        }
                        reportedEncoding = ps.encoding; 
                        continue; 
                    case ParsingFunction.ResetAttributesRootLevel:
                        ResetAttributes(); 
                        curNode = nodes[index];
                        parsingFunction = ( index == 0 ) ? ParsingFunction.DocumentContent : ParsingFunction.ElementContent;
                        continue;
                    case ParsingFunction.MoveToElementContent: 
                        ResetAttributes();
                        index++; 
                        curNode = AddNode( index, index ); 
                        parsingFunction = ParsingFunction.ElementContent;
                        continue; 
                    case ParsingFunction.PopElementContext:
                        PopElementContext();
                        parsingFunction = nextParsingFunction;
                        Debug.Assert( parsingFunction == ParsingFunction.ElementContent || 
                                      parsingFunction == ParsingFunction.DocumentContent );
                        continue; 
                    case ParsingFunction.PopEmptyElementContext: 
                        curNode = nodes[index];
                        Debug.Assert( curNode.type == XmlNodeType.Element ); 
                        curNode.IsEmptyElement = false;
                        ResetAttributes();
                        PopElementContext();
                        parsingFunction = nextParsingFunction; 
                        continue;
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities) 
                    case ParsingFunction.EntityReference: 
                        parsingFunction = nextParsingFunction;
                        ParseEntityReference(); 
                        return true;
                    case ParsingFunction.ReportEndEntity:
                        SetupEndEntityNodeInContent();
                        parsingFunction = nextParsingFunction; 
                        return true;
                    case ParsingFunction.AfterResolveEntityInContent: 
                        curNode = AddNode( index, index ); 
                        reportedEncoding = ps.encoding;
                        reportedBaseUri = ps.baseUriStr; 
                        parsingFunction = nextParsingFunction;
                        continue;
                    case ParsingFunction.AfterResolveEmptyEntityInContent:
                        curNode = AddNode( index, index ); 
                        curNode.SetValueNode( XmlNodeType.Text, string.Empty );
                        curNode.SetLineInfo( ps.lineNo, ps.LinePos ); 
                        reportedEncoding = ps.encoding; 
                        reportedBaseUri = ps.baseUriStr;
                        parsingFunction = nextParsingFunction; 
                        return true;
#endif
                    case ParsingFunction.InReadAttributeValue:
                        FinishAttributeValueIterator(); 
                        curNode = nodes[index];
                        continue; 
#if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex) 
                    case ParsingFunction.InIncrementalRead:
                        FinishIncrementalRead(); 
                        return true;
                    case ParsingFunction.FragmentAttribute:
                        return ParseFragmentAttribute();
                    case ParsingFunction.XmlDeclarationFragment: 
                        ParseXmlDeclarationFragment();
                        parsingFunction = ParsingFunction.GoToEof; 
                        return true; 
#endif
                    case ParsingFunction.GoToEof: 
                        OnEof();
                        return false;
                    case ParsingFunction.Error:
                    case ParsingFunction.Eof: 
                    case ParsingFunction.ReaderClosed:
                        return false; 
                    case ParsingFunction.NoData: 
                        ThrowWithoutLineInfo( Res.Xml_MissingRoot );
                        return false; 
                    case ParsingFunction.PartialTextValue:
                        SkipPartialTextValue();
                        continue;
                    case ParsingFunction.InReadValueChunk: 
                        FinishReadValueChunk();
                        continue; 
                    case ParsingFunction.InReadContentAsBinary: 
                        FinishReadContentAsBinary();
                        continue; 
                    case ParsingFunction.InReadElementContentAsBinary:
                        FinishReadElementContentAsBinary();
                        continue;
                    default: 
                        Debug.Assert( false );
                        break; 
                } 
            }
        } 

        // Closes the input stream ot TextReader, changes the ReadState to Closed and sets all properties to zero/string.Empty
        public override void Close() {
            Close( closeInput ); 
        }
 
        // Skips the current node. If on element, skips to the end tag of the element. 
        public override void Skip() {
            if ( readState != ReadState.Interactive ) 
                return;

            if ( InAttributeValueIterator ) {
                FinishAttributeValueIterator(); 
                curNode = nodes[index];
            } 
            else { 
                switch ( parsingFunction ) {
                    case ParsingFunction.InReadAttributeValue: 
                        Debug.Assert( false );
                        break;
#if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex)
                    case ParsingFunction.InIncrementalRead: 
                        FinishIncrementalRead();
                        break; 
#endif 
                    case ParsingFunction.PartialTextValue:
                        SkipPartialTextValue(); 
                        break;
                    case ParsingFunction.InReadValueChunk:
                        FinishReadValueChunk();
                        break; 
                    case ParsingFunction.InReadContentAsBinary:
                        FinishReadContentAsBinary(); 
                        break; 
                    case ParsingFunction.InReadElementContentAsBinary:
                        FinishReadElementContentAsBinary(); 
                        break;
                }
            }
 
            switch ( curNode.type ) {
                // skip subtree 
                case XmlNodeType.Element: 
                    if ( curNode.IsEmptyElement ) {
                        break; 
                    }
                    int initialDepth = index;
                    parsingMode = ParsingMode.SkipContent;
                    // skip content 
                    while ( outerReader.Read() && index > initialDepth ) ;
                    Debug.Assert( curNode.type == XmlNodeType.EndElement ); 
                    Debug.Assert( parsingFunction != ParsingFunction.Eof ); 
                    parsingMode = ParsingMode.Full;
                    break; 
                case XmlNodeType.Attribute:
                    outerReader.MoveToElement();
                    goto case XmlNodeType.Element;
            } 
            // move to following sibling node
            outerReader.Read(); 
            return; 
        }
 
        // Returns NamespaceURI associated with the specified prefix in the current namespace scope.
        public override String LookupNamespace( String prefix ) {
            if ( !supportNamespaces ) {
                return null; 
            }
 
            return namespaceManager.LookupNamespace( prefix ); 
        }
 
        // Iterates through the current attribute value's text and entity references chunks.
        public override bool ReadAttributeValue() {
            if ( parsingFunction != ParsingFunction.InReadAttributeValue ) {
                if ( curNode.type != XmlNodeType.Attribute ) { 
                    return false;
                } 
                if ( readState != ReadState.Interactive || curAttrIndex < 0 ) { 
                    return false;
                } 
                if ( parsingFunction == ParsingFunction.InReadValueChunk ) {
                    FinishReadValueChunk();
                }
                if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { 
                    FinishReadContentAsBinary();
                } 
 
#if SILVERLIGHT
                NodeData simpleValueNode = AddNode( index + attrCount + 1, curNode.depth + 1 ); 
                simpleValueNode.SetValueNode( XmlNodeType.Text, curNode.StringValue );
                simpleValueNode.lineInfo = curNode.lineInfo2;
                simpleValueNode.depth = curNode.depth + 1;
                curNode = simpleValueNode; 

                nextParsingFunction = parsingFunction; 
                parsingFunction = ParsingFunction.InReadAttributeValue; 
#else
                if ( curNode.nextAttrValueChunk == null || entityHandling == EntityHandling.ExpandEntities ) { 
                    NodeData simpleValueNode = AddNode( index + attrCount + 1, curNode.depth + 1 );
                    simpleValueNode.SetValueNode( XmlNodeType.Text, curNode.StringValue );
                    simpleValueNode.lineInfo = curNode.lineInfo2;
                    simpleValueNode.depth = curNode.depth + 1; 
                    curNode = simpleValueNode;
 
                    simpleValueNode.nextAttrValueChunk = null; 
                }
                else { 
                    curNode = curNode.nextAttrValueChunk;

                    // Place the current node at nodes[index + attrCount + 1]. If the node type
                    // is be EntityReference and user calls ResolveEntity, the associated EndEntity 
                    // node will be constructed from the information stored there.
 
                    // This will initialize the (index + attrCount + 1) place in nodes array 
                    AddNode( index + attrCount + 1, index + 2 );
                    nodes[index + attrCount + 1] = curNode; 

                    fullAttrCleanup = true;
                }
                nextParsingFunction = parsingFunction; 
                parsingFunction = ParsingFunction.InReadAttributeValue;
                attributeValueBaseEntityId = ps.entityId; 
#endif 
                return true;
            } 
            else {
#if SILVERLIGHT
                return false;
#else 
                if ( ps.entityId == attributeValueBaseEntityId ) {
                    if ( curNode.nextAttrValueChunk != null ) { 
                        curNode = curNode.nextAttrValueChunk; 
                        nodes[index + attrCount + 1] = curNode;  // if curNode == EntityReference node, it will be picked from here by SetupEndEntityNodeInAttribute
                        return true; 
                    }
                    return false;
                }
                else { 
                    // expanded entity in attribute value
                    return ParseAttributeValueChunk(); 
                } 
#endif
            } 
        }

        // Resolves the current entity reference node
        public override void ResolveEntity() { 
#if SILVERLIGHT // entities are always resolved V2 XmlReader that is Silverlight
            throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); 
#else 
            if ( curNode.type != XmlNodeType.EntityReference ) {
                throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); 
            }

            Debug.Assert( parsingMode == ParsingMode.Full );
 
            // entity in attribute value
            if ( parsingFunction == ParsingFunction.InReadAttributeValue || 
                 parsingFunction == ParsingFunction.FragmentAttribute ) { 
                switch ( HandleGeneralEntityReference( curNode.localName, true, true, curNode.LinePos ) ) {
                    case EntityType.ExpandedInAttribute: 
                    case EntityType.Expanded:
                        if ( ps.charsUsed - ps.charPos == 0 ) {  // entity value == ""
                            emptyEntityInAttributeResolved = true;
                        } 
                        break;
                    case EntityType.FakeExpanded: 
                        emptyEntityInAttributeResolved = true; 
                        break;
                    default: 
                        Debug.Assert( false );
                        throw new XmlException( Res.Xml_InternalError, string.Empty );
                }
            } 
           // entity in element content
            else { 
                switch ( HandleGeneralEntityReference( curNode.localName, false, true, curNode.LinePos ) ) { 
                    case EntityType.ExpandedInAttribute:
                    case EntityType.Expanded: 
                        nextParsingFunction = parsingFunction;
                        if ( ps.charsUsed - ps.charPos == 0 && !ps.entity.IsExternal ) {  // empty internal entity value
                            parsingFunction = ParsingFunction.AfterResolveEmptyEntityInContent;
                        } 
                        else {
                            parsingFunction = ParsingFunction.AfterResolveEntityInContent; 
                        } 
                        break;
                    case EntityType.FakeExpanded: 
                        nextParsingFunction = parsingFunction;
                        parsingFunction = ParsingFunction.AfterResolveEmptyEntityInContent;
                        break;
                    default: 
                        Debug.Assert( false );
                        throw new XmlException( Res.Xml_InternalError, string.Empty ); 
                } 
            }
            ps.entityResolvedManually = true; 
            index++;
#endif
        }
 
#if !SILVERLIGHT // Needed only for XmlTextReader or XmlValidatingReader
        internal XmlReader OuterReader { 
            get { 
                return outerReader;
            } 
            set {
                Debug.Assert( value is XmlTextReader );
                outerReader = value;
            } 
        }
 
        internal void MoveOffEntityReference() { 
            if ( outerReader.NodeType == XmlNodeType.EntityReference &&
                 parsingFunction == ParsingFunction.AfterResolveEntityInContent ) { 
                if ( !outerReader.Read() ) {
                    throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
                }
            } 
        }
 
        public override string ReadString() { 
            Debug.Assert( outerReader is XmlTextReaderImpl );
            MoveOffEntityReference(); 
            return base.ReadString();
        }
#endif
 
        public override bool CanReadBinaryContent {
            get { 
                return true; 
            }
        } 

        // Reads and concatenates content nodes, base64-decodes the results and copies the decoded bytes into the provided buffer
        public override int ReadContentAsBase64( byte[] buffer, int index, int count ) {
            // check arguments 
            if ( buffer == null ) {
                throw new ArgumentNullException( "buffer" ); 
            } 
            if ( count < 0 ) {
                throw new ArgumentOutOfRangeException( "count" ); 
            }
            if ( index < 0 ) {
                throw new ArgumentOutOfRangeException( "index" );
            } 
            if ( buffer.Length - index < count ) {
                throw new ArgumentOutOfRangeException( "count" ); 
            } 

            // if not the first call to ReadContentAsBase64 
            if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) {
                // and if we have a correct decoder
                if ( incReadDecoder == base64Decoder ) {
                    // read more binary data 
                    return ReadContentAsBinary( buffer, index, count );
                } 
            } 
            // first call of ReadContentAsBase64 -> initialize (move to first text child (for elements) and initialize incremental read state)
            else { 
                if ( readState != ReadState.Interactive ) {
                    return 0;
                }
                if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
                } 
                if ( !XmlReader.CanReadContentAs( curNode.type ) ) { 
                    throw CreateReadContentAsException( "ReadContentAsBase64" );
                } 
                if ( !InitReadContentAsBinary() ) {
                    return 0;
                }
            } 

            // setup base64 decoder 
            InitBase64Decoder(); 

            // read binary data 
            return ReadContentAsBinary( buffer, index, count );
        }

 
        // Reads and concatenates content nodes, binhex-decodes the results and copies the decoded bytes into the provided buffer
        public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) { 
            // check arguments 
            if ( buffer == null ) {
                throw new ArgumentNullException( "buffer" ); 
            }
            if ( count < 0 ) {
                throw new ArgumentOutOfRangeException( "count" );
            } 
            if ( index < 0 ) {
                throw new ArgumentOutOfRangeException( "index" ); 
            } 
            if ( buffer.Length - index < count ) {
                throw new ArgumentOutOfRangeException( "count" ); 
            }

            // if not the first call to ReadContentAsBinHex
            if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { 
                // and if we have a correct decoder
                if ( incReadDecoder == binHexDecoder ) { 
                    // read more binary data 
                    return ReadContentAsBinary( buffer, index, count );
                } 
            }
            // first call of ReadContentAsBinHex -> initialize (move to first text child (for elements) and initialize incremental read state)
            else {
                if ( readState != ReadState.Interactive ) { 
                    return 0;
                } 
                if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
                } 
                if ( !XmlReader.CanReadContentAs( curNode.type ) ) {
                    throw CreateReadContentAsException( "ReadContentAsBinHex" );
                }
                if ( !InitReadContentAsBinary() ) { 
                    return 0;
                } 
            } 

            // setup binhex decoder (when in first ReadContentAsBinHex call or when mixed with ReadContentAsBase64) 
            InitBinHexDecoder();

            // read binary data
            return ReadContentAsBinary( buffer, index, count ); 
        }
 
        // Reads and concatenates content of an element, base64-decodes the results and copies the decoded bytes into the provided buffer 
        public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) {
            // check arguments 
            if ( buffer == null ) {
                throw new ArgumentNullException( "buffer" );
            }
            if ( count < 0 ) { 
                throw new ArgumentOutOfRangeException( "count" );
            } 
            if ( index < 0 ) { 
                throw new ArgumentOutOfRangeException( "index" );
            } 
            if ( buffer.Length - index < count ) {
                throw new ArgumentOutOfRangeException( "count" );
            }
 
            // if not the first call to ReadContentAsBase64
            if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { 
                // and if we have a correct decoder 
                if ( incReadDecoder == base64Decoder ) {
                    // read more binary data 
                    return ReadElementContentAsBinary( buffer, index, count );
                }
            }
            // first call of ReadElementContentAsBase64 -> initialize 
            else {
                if ( readState != ReadState.Interactive ) { 
                    return 0; 
                }
                if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) { 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
                }
                if ( curNode.type != XmlNodeType.Element ) {
                    throw CreateReadElementContentAsException( "ReadElementContentAsBinHex" ); 
                }
                if ( !InitReadElementContentAsBinary() ) { 
                    return 0; 
                }
            } 

            // setup base64 decoder
            InitBase64Decoder();
 
            // read binary data
            return ReadElementContentAsBinary( buffer, index, count ); 
        } 

 
        // Reads and concatenates content of an element, binhex-decodes the results and copies the decoded bytes into the provided buffer
        public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) {
            // check arguments
            if ( buffer == null ) { 
                throw new ArgumentNullException( "buffer" );
            } 
            if ( count < 0 ) { 
                throw new ArgumentOutOfRangeException( "count" );
            } 
            if ( index < 0 ) {
                throw new ArgumentOutOfRangeException( "index" );
            }
            if ( buffer.Length - index < count ) { 
                throw new ArgumentOutOfRangeException( "count" );
            } 
 
            // if not the first call to ReadContentAsBinHex
            if ( parsingFunction == ParsingFunction.InReadElementContentAsBinary ) { 
                // and if we have a correct decoder
                if ( incReadDecoder == binHexDecoder ) {
                    // read more binary data
                    return ReadElementContentAsBinary( buffer, index, count ); 
                }
            } 
            // first call of ReadContentAsBinHex -> initialize 
            else {
                if ( readState != ReadState.Interactive ) { 
                    return 0;
                }
                if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) {
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); 
                }
                if ( curNode.type != XmlNodeType.Element ) { 
                    throw CreateReadElementContentAsException( "ReadElementContentAsBinHex" ); 
                }
                if ( !InitReadElementContentAsBinary() ) { 
                    return 0;
                }
            }
 
            // setup binhex decoder (when in first ReadContentAsBinHex call or when mixed with ReadContentAsBase64)
            InitBinHexDecoder(); 
 
            // read binary data
            return ReadElementContentAsBinary( buffer, index, count ); 
        }

        // Returns true if ReadValue is supported
        public override bool CanReadValueChunk { 
            get {
                return true; 
            } 
        }
 
        // Iterates over Value property and copies it into the provided buffer
        public override int ReadValueChunk( char[] buffer, int index, int count ) {
            // throw on elements
            if ( !XmlReader.HasValueInternal( curNode.type ) ) { 
                throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidReadValueChunk, curNode.type ) ) ;
            } 
            // check arguments 
            if ( buffer == null ) {
                throw new ArgumentNullException( "buffer" ); 
            }
            if ( count < 0 ) {
                throw new ArgumentOutOfRangeException( "count" );
            } 
            if ( index < 0 ) {
                throw new ArgumentOutOfRangeException( "index" ); 
            } 
            if ( buffer.Length - index < count ) {
                throw new ArgumentOutOfRangeException( "count" ); 
            }

            // first call of ReadValueChunk -> initialize incremental read state
            if ( parsingFunction != ParsingFunction.InReadValueChunk ) { 
                if ( readState != ReadState.Interactive ) {
                    return 0; 
                } 
                if ( parsingFunction == ParsingFunction.PartialTextValue ) {
                    incReadState = IncrementalReadState.ReadValueChunk_OnPartialValue; 
                }
                else {
                    incReadState = IncrementalReadState.ReadValueChunk_OnCachedValue;
                    nextNextParsingFunction = nextParsingFunction; 
                    nextParsingFunction = parsingFunction;
                } 
                parsingFunction = ParsingFunction.InReadValueChunk; 
                readValueOffset = 0;
            } 

            if ( count == 0 ) {
                return 0;
            } 

            // read what is already cached in curNode 
            int readCount = 0; 
            int read = curNode.CopyTo( readValueOffset, buffer, index + readCount, count - readCount );
            readCount += read; 
            readValueOffset += read;

            if ( readCount == count ) {
                // take care of surrogate pairs spanning between buffers 
                char ch = buffer[index + count - 1];
                if ( XmlCharType.IsHighSurrogate(ch) ) { 
                    readCount--; 
                    readValueOffset--;
                    if ( readCount == 0 ) { 
                        Throw( Res.Xml_NotEnoughSpaceForSurrogatePair );
                    }
                }
                return readCount; 
            }
 
            // if on partial value, read the rest of it 
            if ( incReadState == IncrementalReadState.ReadValueChunk_OnPartialValue ) {
                curNode.SetValue( string.Empty ); 

                // read next chunk of text
                bool endOfValue = false;
                int startPos = 0; 
                int endPos = 0;
                while ( readCount < count && !endOfValue ) { 
                    int orChars = 0; 
                    endOfValue = ParseText( out startPos, out endPos, ref orChars );
 
                    int copyCount = count - readCount;
                    if ( copyCount > endPos - startPos ) {
                        copyCount = endPos - startPos;
                    } 
                    BlockCopyChars( ps.chars, startPos, buffer, ( index + readCount ), copyCount );
 
                    readCount += copyCount; 
                    startPos += copyCount;
                } 

 				incReadState = endOfValue ? IncrementalReadState.ReadValueChunk_OnCachedValue : IncrementalReadState.ReadValueChunk_OnPartialValue;

                if ( readCount == count ) { 
                    char ch = buffer[index + count - 1];
                    if ( XmlCharType.IsHighSurrogate(ch) ) { 
                        readCount--; 
                        startPos--;
                        if ( readCount == 0 ) { 
                            Throw( Res.Xml_NotEnoughSpaceForSurrogatePair );
                        }
                    }
                } 

                readValueOffset = 0; 
                curNode.SetValue( ps.chars, startPos, endPos - startPos ); 
            }
            return readCount; 
        }

//
// IXmlLineInfo members 
//
        public bool HasLineInfo() { 
            return true; 
        }
 
        // Returns the line number of the current node
        public int LineNumber {
            get {
                return curNode.LineNo; 
            }
        } 
 
        // Returns the line position of the current node
        public int LinePosition { 
            get {
                return curNode.LinePos;
            }
        } 

// 
// IXmlNamespaceResolver members 
//
        IDictionary IXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) { 
            return this.GetNamespacesInScope( scope );
        }

        string IXmlNamespaceResolver.LookupNamespace(string prefix) { 
            return this.LookupNamespace( prefix );
        } 
 
        string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) {
            return this.LookupPrefix( namespaceName ); 
        }

    // Internal IXmlNamespaceResolver methods
        internal IDictionary GetNamespacesInScope( XmlNamespaceScope scope ) { 
            return namespaceManager.GetNamespacesInScope( scope );
        } 
 
        // NOTE: there already is virtual method for "string LookupNamespace(string prefix)"
 
        internal string LookupPrefix( string namespaceName ) {
            return namespaceManager.LookupPrefix( namespaceName );
        }
 
//
// XmlTextReader members 
        // 
#if !SILVERLIGHT // Needed only for XmlTextReader
        // Disables or enables support of W3C XML 1.0 Namespaces 
        internal bool Namespaces {
            get {
                return supportNamespaces;
            } 
            set {
                if ( readState != ReadState.Initial ) { 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) ); 
                }
                supportNamespaces = value; 
                if ( value ) {
                    if ( namespaceManager is NoNamespaceManager ) {
                        if ( fragment && fragmentParserContext != null && fragmentParserContext.NamespaceManager != null ) {
                            namespaceManager = fragmentParserContext.NamespaceManager; 
                        }
                        else { 
                            namespaceManager = new XmlNamespaceManager( nameTable ); 
                        }
                    } 
                    xmlContext.defaultNamespace = namespaceManager.LookupNamespace( string.Empty );
                }
                else {
                    if ( !( namespaceManager is NoNamespaceManager ) ) { 
                        namespaceManager = new NoNamespaceManager();
                    } 
                    xmlContext.defaultNamespace = string.Empty; 
                }
            } 
        }

        // Enables or disables XML 1.0 normalization (incl. end-of-line normalization and normalization of attributes)
        internal bool Normalization { 
            get {
                Debug.Assert( v1Compat, "XmlTextReaderImpl.Normalization property cannot be accessed on reader created via XmlReader.Create." ); 
                return normalize; 
            }
            set { 
                Debug.Assert( v1Compat, "XmlTextReaderImpl.Normalization property cannot be changed on reader created via XmlReader.Create." );
                if ( readState == ReadState.Closed ) {
                    throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
                } 
                normalize = value;
 
                if ( ps.entity == null || ps.entity.IsExternal ) { 
                    ps.eolNormalized = !value;
                } 
            }
        }

        // Returns the Encoding of the XML document 
        internal Encoding Encoding {
            get { 
                return ( readState == ReadState.Interactive ) ? reportedEncoding : null; 
            }
        } 

        // Spefifies whitespace handling of the XML document, i.e. whether return all namespaces, only significant ones or none
        internal WhitespaceHandling WhitespaceHandling {
            get { 
                Debug.Assert( v1Compat, "XmlTextReaderImpl.WhitespaceHandling property cannot be accessed on reader created via XmlReader.Create." );
                return whitespaceHandling; 
            } 
            set {
                Debug.Assert( v1Compat, "XmlTextReaderImpl.WhitespaceHandling property cannot be changed on reader created via XmlReader.Create." ); 
                if ( readState == ReadState.Closed ) {
                    throw new InvalidOperationException( Res.GetString( Res.Xml_InvalidOperation ) );
                }
 
                if ( (uint)value > (uint)WhitespaceHandling.None ) {
                    throw new XmlException( Res.Xml_WhitespaceHandling, string.Empty ); 
                } 
                whitespaceHandling = value;
            } 
        }

        // Specifies how the DTD is processed in the XML document.
        internal DtdProcessing DtdProcessing { 
            get {
                Debug.Assert( v1Compat, "XmlTextReaderImpl.DtdProcessing property cannot be accessed on reader created via XmlReader.Create." ); 
                return dtdProcessing; 
            }
            set { 
                Debug.Assert( v1Compat, "XmlTextReaderImpl.DtdProcessing property cannot be changed on reader created via XmlReader.Create." );

                if ((uint)value > (uint)DtdProcessing.Parse) {
                    throw new ArgumentOutOfRangeException("value"); 
                }
                dtdProcessing = value; 
            } 
        }
 
        // Spefifies whether general entities should be automatically expanded or not
        internal EntityHandling EntityHandling {
            get {
                return entityHandling; 
            }
            set { 
                if ( value != EntityHandling.ExpandEntities && value != EntityHandling.ExpandCharEntities ) { 
                    throw new XmlException( Res.Xml_EntityHandling, string.Empty );
                } 
                entityHandling = value;
            }
        }
 
        // Specifies XmlResolver used for opening the XML document and other external references
        internal XmlResolver XmlResolver { 
            set { 
                xmlResolver = value;
 
                // invalidate all baseUris on the stack
                ps.baseUri = null;
                for ( int i = 0; i <= parsingStatesStackTop; i++ ) {
                    parsingStatesStack[i].baseUri = null; 
                }
            } 
        } 

        // Reset the state of the reader so the reader is ready to parse another XML document from the same stream. 
        internal void ResetState() {
            Debug.Assert( v1Compat, "XmlTextReaderImpl.ResetState cannot be called on reader created via XmlReader.Create." );

            if ( fragment ) { 
                Throw( new InvalidOperationException( Res.GetString( Res.Xml_InvalidResetStateCall ) ) );
            } 
 
            if ( readState == ReadState.Initial ) {
                return; 
            }

            // Clear
            ResetAttributes(); 
            while ( namespaceManager.PopScope() );
 
            while ( InEntity ) { 
                HandleEntityEnd( true );
            } 

            // Init
            readState = ReadState.Initial;
            parsingFunction = ParsingFunction.SwitchToInteractiveXmlDecl; 
            nextParsingFunction = ParsingFunction.DocumentContent;
 
            curNode = nodes[0]; 
            curNode.Clear( XmlNodeType.None );
            curNode.SetLineInfo( 0, 0 ); 
            index = 0;
            rootElementParsed = false;

            charactersInDocument = 0; 
            charactersFromEntities = 0;
 
            afterResetState = true; 
        }
 
        // returns the remaining unparsed data as TextReader
        internal TextReader GetRemainder() {
            Debug.Assert( v1Compat, "XmlTextReaderImpl.GetRemainder cannot be called on reader created via XmlReader.Create." );
 
            Debug.Assert( stringBuilder.Length == 0 );
            switch ( parsingFunction ) { 
                case ParsingFunction.Eof: 
                case ParsingFunction.ReaderClosed:
                    return new StringReader( string.Empty ); 
                case ParsingFunction.OpenUrl:
                    OpenUrl();
                    break;
                case ParsingFunction.InIncrementalRead: 
                    if ( !InEntity ) {
                        stringBuilder.Append( ps.chars, incReadLeftStartPos, incReadLeftEndPos -  incReadLeftStartPos ); 
                    } 
                    break;
            } 

            while ( InEntity ) {
                HandleEntityEnd( true );
            } 

            ps.appendMode = false; 
            do { 
                stringBuilder.Append( ps.chars, ps.charPos, ps.charsUsed - ps.charPos );
                ps.charPos = ps.charsUsed; 
            } while ( ReadData() != 0 );

            OnEof();
 
            string remainer = stringBuilder.ToString();
            stringBuilder.Length = 0; 
            return new StringReader( remainer ); 
        }
 
        // Reads the contents of an element including markup into a character buffer. Wellformedness checks are limited.
        // This method is designed to read large streams of embedded text by calling it successively.
        internal int ReadChars( char[] buffer, int index, int count ) {
            Debug.Assert( v1Compat, "XmlTextReaderImpl.ReadChars cannot be called on reader created via XmlReader.Create." ); 
            Debug.Assert( outerReader is XmlTextReader );
 
            if ( parsingFunction == ParsingFunction.InIncrementalRead ) { 
                if ( incReadDecoder != readCharsDecoder ) { // mixing ReadChars with ReadBase64 or ReadBinHex
                    if ( readCharsDecoder == null ) { 
                        readCharsDecoder = new IncrementalReadCharsDecoder();
                    }
                    readCharsDecoder.Reset();
                    incReadDecoder = readCharsDecoder; 
                }
                return IncrementalRead( buffer, index, count ); 
            } 
            else {
                if ( curNode.type != XmlNodeType.Element) { 
                    return 0;
                }
                if ( curNode.IsEmptyElement ) {
                    outerReader.Read(); 
                    return 0;
                } 
 
                if ( readCharsDecoder == null ) {
                    readCharsDecoder = new IncrementalReadCharsDecoder(); 
                }

                InitIncrementalRead( readCharsDecoder );
                return IncrementalRead( buffer, index, count ); 
            }
        } 
 
        // Reads the contents of an element including markup and base64-decodes it into a byte buffer. Wellformedness checks are limited.
        // This method is designed to read base64-encoded large streams of bytes by calling it successively. 
        internal int ReadBase64( byte[] array, int offset, int len ) {
            Debug.Assert( v1Compat, "XmlTextReaderImpl.ReadBase64 cannot be called on reader created via XmlReader.Create." );
            Debug.Assert( outerReader is XmlTextReader );
 
            if ( parsingFunction == ParsingFunction.InIncrementalRead ) {
                if ( incReadDecoder != base64Decoder ) { // mixing ReadBase64 with ReadChars or ReadBinHex 
                    InitBase64Decoder(); 
                }
                return IncrementalRead( array, offset, len ); 
            }
            else {
                if ( curNode.type  != XmlNodeType.Element) {
                    return 0; 
                }
                if ( curNode.IsEmptyElement ) { 
                    outerReader.Read(); 
                    return 0;
                } 

                if ( base64Decoder == null ) {
                    base64Decoder = new Base64Decoder();
                } 

                InitIncrementalRead( base64Decoder ); 
                return IncrementalRead( array, offset, len ); 
            }
        } 

        // Reads the contents of an element including markup and binhex-decodes it into a byte buffer. Wellformedness checks are limited.
        // This method is designed to read binhex-encoded large streams of bytes by calling it successively.
        internal int ReadBinHex( byte[] array, int offset, int len ) { 
            Debug.Assert( v1Compat, "XmlTextReaderImpl.ReadBinHex cannot be called on reader created via XmlReader.Create." );
            Debug.Assert( outerReader is XmlTextReader ); 
 
            if ( parsingFunction == ParsingFunction.InIncrementalRead ) {
                if ( incReadDecoder != binHexDecoder ) { // mixing ReadBinHex with ReadChars or ReadBase64 
                    InitBinHexDecoder();
                }
                return IncrementalRead( array, offset, len );
            } 
            else {
                if ( curNode.type  != XmlNodeType.Element) { 
                    return 0; 
                }
                if ( curNode.IsEmptyElement ) { 
                    outerReader.Read();
                    return 0;
                }
 
                if ( binHexDecoder == null ) {
                    binHexDecoder = new BinHexDecoder(); 
                } 

                InitIncrementalRead( binHexDecoder ); 
                return IncrementalRead( array, offset, len );
            }
        }
#endif 

        // 
// Helpers for DtdParserProxy 
//
        internal XmlNameTable DtdParserProxy_NameTable { 
            get {
                return nameTable;
            }
        } 

        internal IXmlNamespaceResolver DtdParserProxy_NamespaceResolver { 
            get { 
                return namespaceManager;
            } 
        }

        internal bool DtdParserProxy_DtdValidation {
            get { 
#if SILVERLIGHT
                return false; 
#else 
                return DtdValidation;
#endif 
            }
        }

        internal bool DtdParserProxy_Normalization { 
            get {
                return normalize; 
            } 
        }
 
        internal bool DtdParserProxy_Namespaces {
            get {
                return supportNamespaces;
            } 
        }
 
        internal bool DtdParserProxy_V1CompatibilityMode { 
            get {
                return v1Compat; 
            }
        }

        internal Uri DtdParserProxy_BaseUri { 
            // SxS: ps.baseUri may be initialized in the constructor (public XmlTextReaderImpl( string url, XmlNameTable nt )) based on
            // url provided by the user. Here the property returns ps.BaseUri - so it may expose a path. 
#if !SILVERLIGHT 
            [ResourceConsumption(ResourceScope.Machine)]
            [ResourceExposure(ResourceScope.Machine)] 
#endif
            get {
                if ( ps.baseUriStr.Length > 0 && ps.baseUri == null && xmlResolver != null ) {
                    ps.baseUri = xmlResolver.ResolveUri( null, ps.baseUriStr ); 
                }
                return ps.baseUri; 
            } 
        }
 
        internal bool DtdParserProxy_IsEof {
            get {
                return ps.isEof;
            } 
        }
 
        internal char[] DtdParserProxy_ParsingBuffer { 
            get {
                return ps.chars; 
            }
        }

        internal int DtdParserProxy_ParsingBufferLength { 
            get {
                return ps.charsUsed; 
            } 
        }
 
        internal int DtdParserProxy_CurrentPosition {
            get {
                return ps.charPos;
            } 
            set {
                Debug.Assert( value >= 0 && value <= ps.charsUsed ); 
                ps.charPos = value; 
            }
        } 

        internal int DtdParserProxy_EntityStackLength {
            get {
                return parsingStatesStackTop + 1; 
            }
        } 
 
        internal bool DtdParserProxy_IsEntityEolNormalized {
            get { 
                return ps.eolNormalized;
            }
        }
 
#if !SILVERLIGHT
        internal IValidationEventHandling DtdParserProxy_ValidationEventHandling { 
            get { 
                return validationEventHandling;
            } 
            set {
                validationEventHandling = value;
            }
        } 
#endif
 
        internal void DtdParserProxy_OnNewLine( int pos ) { 
            this.OnNewLine( pos );
        } 

        internal int DtdParserProxy_LineNo {
            get {
                return ps.LineNo; 
            }
        } 
 
        internal int DtdParserProxy_LineStartPosition {
            get { 
                return ps.lineStartPos;
            }
        }
 
        internal int DtdParserProxy_ReadData() {
            return this.ReadData(); 
        } 

        internal int DtdParserProxy_ParseNumericCharRef( BufferBuilder internalSubsetBuilder ) { 
            EntityType entType;
            return this.ParseNumericCharRef( true, internalSubsetBuilder, out entType );
        }
 
        internal int DtdParserProxy_ParseNamedCharRef( bool expand, BufferBuilder internalSubsetBuilder ) {
            return this.ParseNamedCharRef( expand, internalSubsetBuilder ); 
        } 

        internal void DtdParserProxy_ParsePI( BufferBuilder sb ) { 
            if ( sb == null ) {
                ParsingMode pm = parsingMode;
                parsingMode = ParsingMode.SkipNode;
                ParsePI( null ); 
                parsingMode = pm;
            } 
            else { 
                ParsePI( sb );
            } 
        }

        internal void DtdParserProxy_ParseComment( BufferBuilder sb ) {
            Debug.Assert( parsingMode == ParsingMode.Full ); 

            try { 
                if ( sb == null ) { 
                    ParsingMode savedParsingMode = parsingMode;
                    parsingMode = ParsingMode.SkipNode; 
                    ParseCDataOrComment( XmlNodeType.Comment );
                    parsingMode = savedParsingMode;
                }
                else { 
                    NodeData originalCurNode = curNode;
 
                    curNode = AddNode( index + attrCount + 1, index ); 
                    ParseCDataOrComment( XmlNodeType.Comment );
                    curNode.CopyTo( 0, sb ); 

                    curNode = originalCurNode;
                }
            } 
            catch ( XmlException e ) {
#if !SILVERLIGHT 
                if ( e.ResString == Res.Xml_UnexpectedEOF && ps.entity != null ) { 
                    SendValidationEvent( XmlSeverityType.Error, Res.Sch_ParEntityRefNesting, null, ps.LineNo, ps.LinePos );
                } 
                else {
                    throw;
                }
#else 
                throw e;
#endif 
            } 
        }
 
        internal bool DtdParserProxy_PushEntity( IDtdEntityInfo entity, out int entityId ) {
            bool retValue;
            if ( entity.IsExternal ) {
                if ( xmlResolver == null ) { 
                    entityId = -1;
                    return false; 
                } 
                retValue = PushExternalEntity( entity );
            } 
            else {
                PushInternalEntity( entity );
                retValue = true;
            } 
            entityId = ps.entityId;
            return retValue; 
        } 

        internal bool DtdParserProxy_PopEntity( out IDtdEntityInfo oldEntity, out int newEntityId ) { 
            if ( parsingStatesStackTop == -1 ) {
                oldEntity = null;
                newEntityId = -1;
                return false; 
            }
            oldEntity = ps.entity; 
            PopEntity(); 
            newEntityId = ps.entityId;
            return true; 
        }

        // SxS: The caller did not provide any SxS sensitive name or resource. No resource is being exposed either.
        // It is OK to suppress SxS warning. 
#if !SILVERLIGHT
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.None)] 
#endif
        internal bool DtdParserProxy_PushExternalSubset( string systemId, string publicId ) { 
            Debug.Assert( parsingStatesStackTop == -1 );
            Debug.Assert( ( systemId != null && systemId.Length > 0 ) || ( publicId != null && publicId.Length > 0 ) );

            if ( xmlResolver == null ) { 
                return false;
            } 
 
            PushExternalEntityOrSubset( publicId, systemId, ps.baseUriStr, ref ps.baseUri, null );
 
            ps.entity = null;
            ps.entityId = 0;

            Debug.Assert( ps.appendMode ); 
            int initialPos = ps.charPos;
            if ( v1Compat ) { 
                EatWhitespaces( null ); 
            }
            if ( !ParseXmlDeclaration( true ) ) { 
                ps.charPos = initialPos;
            }

            return true; 
        }
 
        internal void DtdParserProxy_PushInternalDtd( string baseUri, string internalDtd ) { 
            Debug.Assert( parsingStatesStackTop == -1 );
 
            PushParsingState();

            RegisterConsumedCharacters(internalDtd.Length, false);
            InitStringInput( baseUri, Encoding.Unicode, internalDtd ); 

            ps.entity = null; 
            ps.entityId = 0; 
            ps.eolNormalized = false;
        } 

        internal void DtdParserProxy_Throw( Exception e ) {
            this.Throw( e );
        } 

        internal void DtdParserProxy_OnSystemId( string systemId, LineInfo keywordLineInfo, LineInfo systemLiteralLineInfo ) { 
            NodeData attr = AddAttributeNoChecks( "SYSTEM", index + 1 ); 
            attr.SetValue( systemId );
            attr.lineInfo = keywordLineInfo; 
            attr.lineInfo2 = systemLiteralLineInfo;
        }

        internal void DtdParserProxy_OnPublicId( string publicId, LineInfo keywordLineInfo, LineInfo publicLiteralLineInfo ) { 
            NodeData attr = AddAttributeNoChecks( "PUBLIC", index + 1 );
            attr.SetValue( publicId ); 
            attr.lineInfo = keywordLineInfo; 
            attr.lineInfo2 = publicLiteralLineInfo;
        } 

//
// Throw methods: Sets the reader current position to pos, sets the error state and throws exception
// 
        void Throw( int pos, string res, string arg ) {
            ps.charPos = pos; 
            Throw( res, arg ); 
        }
 
        void Throw( int pos, string res, string[] args ) {
            ps.charPos = pos;
            Throw( res, args );
        } 

        void Throw( int pos, string res ) { 
            ps.charPos = pos; 
            Throw( res, string.Empty );
        } 

        void Throw( string res ) {
            Throw( res, string.Empty );
        } 

        void Throw( string res, int lineNo, int linePos ) { 
            Throw( new XmlException( res, string.Empty, lineNo, linePos, ps.baseUriStr ) ); 
        }
 
        void Throw( string res, string arg ) {
            Throw( new XmlException( res, arg, ps.LineNo, ps.LinePos, ps.baseUriStr ) );
        }
 
        void Throw( string res, string arg, int lineNo, int linePos ) {
            Throw( new XmlException( res, arg, lineNo, linePos, ps.baseUriStr ) ); 
        } 

        void Throw( string res, string[] args ) { 
            Throw( new XmlException( res, args, ps.LineNo, ps.LinePos, ps.baseUriStr ) );
        }

        void Throw( string res, string arg, Exception innerException ) { 
            Throw( res, new string[] { arg }, innerException );
        } 
 
        void Throw( string res, string[] args, Exception innerException ) {
            Throw( new XmlException( res, args, innerException, ps.LineNo, ps.LinePos, ps.baseUriStr ) ); 
        }

        void Throw( Exception e ) {
            SetErrorState(); 
            XmlException xmlEx = e as XmlException;
            if ( xmlEx != null ) { 
                curNode.SetLineInfo( xmlEx.LineNumber, xmlEx.LinePosition ); 
            }
            throw e; 
        }

        void ReThrow( Exception e, int lineNo, int linePos ) {
            Throw( new XmlException( e.Message, (Exception)null, lineNo, linePos, ps.baseUriStr ) ); 
        }
 
        void ThrowWithoutLineInfo( string res ) { 
            Throw( new XmlException( res, string.Empty, ps.baseUriStr ) );
        } 

        void ThrowWithoutLineInfo( string res, string arg ) {
            Throw( new XmlException( res, arg, ps.baseUriStr ) );
        } 

        void ThrowWithoutLineInfo( string res, string[] args, Exception innerException ) { 
            Throw( new XmlException( res, args, innerException, 0, 0, ps.baseUriStr ) ); 
        }
 
        void ThrowInvalidChar( char[] data, int length, int invCharPos ) {
            Throw( invCharPos, Res.Xml_InvalidCharacter, XmlException.BuildCharExceptionArgs( data, length, invCharPos ) );
        }
 
        private void SetErrorState() {
            parsingFunction = ParsingFunction.Error; 
            readState = ReadState.Error; 
        }
 
#if !SILVERLIGHT
        void SendValidationEvent( XmlSeverityType severity, string code, string arg, int lineNo, int linePos ) {
            SendValidationEvent( severity, new XmlSchemaException( code, arg, ps.baseUriStr, lineNo, linePos ) );
        } 

        void SendValidationEvent(XmlSeverityType severity, XmlSchemaException exception) { 
            if (validationEventHandling != null) { 
                validationEventHandling.SendEvent(exception, severity);
            } 
        }
#endif

// 
// Private implementation methods & properties
// 
        private bool InAttributeValueIterator { 
            [System.Runtime.TargetedPatchingOptOutAttribute("Performance critical to inline across NGen image boundaries")]
            get { 
                return attrCount > 0 && parsingFunction >= ParsingFunction.InReadAttributeValue;
            }
        }
 
        private void FinishAttributeValueIterator() {
            Debug.Assert( InAttributeValueIterator ); 
            if ( parsingFunction == ParsingFunction.InReadValueChunk ) { 
                FinishReadValueChunk();
            } 
            else if ( parsingFunction == ParsingFunction.InReadContentAsBinary ) {
                FinishReadContentAsBinary();
            }
            if ( parsingFunction == ParsingFunction.InReadAttributeValue ) { 
#if !SILVERLIGHT // Needed only for XmlTextReader (reporting of entities)
                while ( ps.entityId != attributeValueBaseEntityId ) { 
                    HandleEntityEnd( false ); 
                }
                emptyEntityInAttributeResolved = false; 
#endif
                parsingFunction = nextParsingFunction;
                nextParsingFunction = ( index > 0 ) ? ParsingFunction.ElementContent : ParsingFunction.DocumentContent;
            } 
        }
 
#if !SILVERLIGHT 
        private bool DtdValidation {
            get { 
                return validationEventHandling != null;
            }
        }
 
        private void InitStreamInput( Stream stream, Encoding encoding ) {
            InitStreamInput( null, string.Empty, stream, null, 0, encoding ); 
        } 

        private void InitStreamInput( string baseUriStr, Stream stream, Encoding encoding ) { 
            Debug.Assert( baseUriStr != null );
            InitStreamInput( null, baseUriStr, stream, null, 0, encoding );
        }
#endif 

        private void InitStreamInput( Uri baseUri, Stream stream, Encoding encoding ) { 
            Debug.Assert( baseUri != null ); 
            InitStreamInput( baseUri, baseUri.ToString(), stream, null, 0, encoding );
        } 

#if !SILVERLIGHT
        private void InitStreamInput( Uri baseUri, string baseUriStr, Stream stream, Encoding encoding ) {
            InitStreamInput( baseUri, baseUriStr, stream, null, 0, encoding ); 
        }
#endif 
 
        private void InitStreamInput( Uri baseUri, string baseUriStr, Stream stream, byte[] bytes, int byteCount, Encoding encoding ) {
 
            Debug.Assert( ps.charPos == 0 && ps.charsUsed == 0 && ps.textReader == null );
            Debug.Assert( baseUriStr != null );
            Debug.Assert( baseUri == null || ( baseUri.ToString().Equals( baseUriStr ) ) );
 
            ps.stream = stream;
            ps.baseUri = baseUri; 
            ps.baseUriStr = baseUriStr; 

            // take over the byte buffer allocated in XmlReader.Create, if available 
            int bufferSize;
            if ( bytes != null ) {
                ps.bytes = bytes;
                ps.bytesUsed = byteCount; 
                bufferSize = ps.bytes.Length;
            } 
            else { 
                // allocate the byte buffer
                bufferSize = XmlReader.CalcBufferSize( stream ); 
                if ( ps.bytes == null || ps.bytes.Length < bufferSize ) {
                    ps.bytes = new byte[ bufferSize ];
                }
            } 

            // allocate char buffer 
            if ( ps.chars == null || ps.chars.Length < bufferSize + 1 ) { 
                ps.chars = new char[ bufferSize + 1 ];
            } 

            // make sure we have at least 4 bytes to detect the encoding (no preamble of System.Text supported encoding is longer than 4 bytes)
            ps.bytePos = 0;
            while ( ps.bytesUsed < 4 && ps.bytes.Length - ps.bytesUsed > 0 ) { 
                int read = stream.Read( ps.bytes, ps.bytesUsed, ps.bytes.Length - ps.bytesUsed );
                if ( read == 0 ) { 
                    ps.isStreamEof = true; 
                    break;
                } 
                ps.bytesUsed += read;
            }

            // detect & setup encoding 
            if ( encoding == null ) {
                encoding = DetectEncoding(); 
            } 
            SetupEncoding( encoding );
 
            // eat preamble
            byte[] preamble = ps.encoding.GetPreamble();
            int preambleLen = preamble.Length;
            int i; 
            for ( i = 0; i < preambleLen && i < ps.bytesUsed; i++ ) {
                if ( ps.bytes[i] != preamble[i] ) { 
                    break; 
                }
            } 
            if ( i == preambleLen ) {
                ps.bytePos = preambleLen;
            }
 
            documentStartBytePos = ps.bytePos;
 
            ps.eolNormalized = !normalize; 

            // decode first characters 
            ps.appendMode = true;
            ReadData();
        }
 
        private void InitTextReaderInput( string baseUriStr, TextReader input ) {
            InitTextReaderInput( baseUriStr, null, input ); 
        } 

        private void InitTextReaderInput( string baseUriStr, Uri baseUri, TextReader input ) { 
            Debug.Assert( ps.charPos == 0 && ps.charsUsed == 0 && ps.stream == null );
            Debug.Assert( baseUriStr != null );

            ps.textReader = input; 
            ps.baseUriStr = baseUriStr;
            ps.baseUri = baseUri; 
 
            if ( ps.chars == null ) {
                ps.chars = new char[ XmlReader.DefaultBufferSize + 1 ]; 
            }

            ps.encoding = Encoding.Unicode;
            ps.eolNormalized = !normalize; 

            // read first characters 
            ps.appendMode = true; 
            ReadData();
        } 

        private void InitStringInput( string baseUriStr, Encoding originalEncoding, string str ) {
            Debug.Assert( ps.stream == null && ps.textReader == null );
            Debug.Assert( ps.charPos == 0 && ps.charsUsed == 0 ); 
            Debug.Assert( baseUriStr != null );
 
            ps.baseUriStr = baseUriStr; 
            ps.baseUri = null;
 
            int len = str.Length;
            ps.chars = new char[ len + 1 ];
            str.CopyTo( 0, ps.chars, 0, str.Length );
            ps.charsUsed = len; 
            ps.chars[len] = (char)0;
 
            ps.encoding = originalEncoding; 

            ps.eolNormalized = !normalize; 
            ps.isEof = true;
        }

#if !SILVERLIGHT 
        private void InitFragmentReader( XmlNodeType fragmentType, XmlParserContext parserContext, bool allowXmlDeclFragment ) {
 
            fragmentParserContext = parserContext; 

            if ( parserContext != null ) { 
                if ( parserContext.NamespaceManager != null ) {
                    namespaceManager = parserContext.NamespaceManager;
                    xmlContext.defaultNamespace = namespaceManager.LookupNamespace( string.Empty );
                } 
                else {
                    namespaceManager = new XmlNamespaceManager( nameTable ); 
                } 

                ps.baseUriStr = parserContext.BaseURI; 
                ps.baseUri = null;
                xmlContext.xmlLang = parserContext.XmlLang;
                xmlContext.xmlSpace = parserContext.XmlSpace;
            } 
            else {
                namespaceManager = new XmlNamespaceManager( nameTable ); 
                ps.baseUriStr = string.Empty; 
                ps.baseUri = null;
            } 

            reportedBaseUri = ps.baseUriStr;

            switch ( fragmentType ) { 
                case XmlNodeType.Attribute:
                    ps.appendMode = false; 
                    parsingFunction = ParsingFunction.SwitchToInteractive; 
                    nextParsingFunction = ParsingFunction.FragmentAttribute;
                    break; 
                case XmlNodeType.Element:
                    Debug.Assert( parsingFunction == ParsingFunction.SwitchToInteractiveXmlDecl );
                    nextParsingFunction = ParsingFunction.DocumentContent;
                    break; 
                case XmlNodeType.Document:
                    Debug.Assert( parsingFunction == ParsingFunction.SwitchToInteractiveXmlDecl ); 
                    Debug.Assert( nextParsingFunction == ParsingFunction.DocumentContent ); 
                    break;
               case XmlNodeType.XmlDeclaration: 
                    if ( allowXmlDeclFragment ) {
                        ps.appendMode = false;
                        parsingFunction = ParsingFunction.SwitchToInteractive;
                        nextParsingFunction = ParsingFunction.XmlDeclarationFragment; 
                        break;
                    } 
                    else { 
                        goto default;
                    } 
                default:
                    Throw( Res.Xml_PartialContentNodeTypeNotSupportedEx, fragmentType.ToString() );
                    return;
            } 
            this.fragmentType = fragmentType;
            this.fragment = true; 
        } 
#endif
 
        private void ProcessDtdFromParserContext(XmlParserContext context) {
            Debug.Assert( context != null && context.HasDtdInfo );

            switch ( dtdProcessing ) { 
                case DtdProcessing.Prohibit:
                    ThrowWithoutLineInfo( Res.Xml_DtdIsProhibitedEx ); 
                    break; 
                case DtdProcessing.Ignore:
                    // do nothing 
                    break;
                case DtdProcessing.Parse:
                    ParseDtdFromParserContext();
                    break; 
                default:
                    Debug.Assert( false, "Unhandled DtdProcessing enumeration value." ); 
                    break; 
            }
        } 

#if !SILVERLIGHT // Needed only for XmlTextReader
        // SxS: This method resolve Uri but does not expose it to the caller. It's OK to suppress the warning.
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.None)]
        private void OpenUrl() { 
            Debug.Assert( url != null && url.Length > 0 ); 
            Debug.Assert( compressedStack != null );
 
            XmlResolver tmpResolver;
            if ( ps.baseUri != null ) {
                Debug.Assert( xmlResolver != null );
                tmpResolver = xmlResolver; 
            }
            else { 
                tmpResolver = ( xmlResolver == null ) ? new XmlUrlResolver() : xmlResolver; 
                ps.baseUri = tmpResolver.ResolveUri( null, url );
                ps.baseUriStr = ps.baseUri.ToString(); 
            }

            try {
                CompressedStack.Run( compressedStack, new ContextCallback( OpenUrlDelegate ), tmpResolver ); 
            }
            catch { 
                SetErrorState(); 
                throw;
            } 

            if ( ps.stream == null ) {
                ThrowWithoutLineInfo( Res.Xml_CannotResolveUrl, ps.baseUriStr );
            } 

            InitStreamInput( ps.baseUri, ps.baseUriStr, ps.stream, null ); 
            reportedEncoding = ps.encoding; 
        }
 
        void OpenUrlDelegate(object xmlResolver) {
            ps.stream = (Stream) ((XmlResolver)xmlResolver).GetEntity( ps.baseUri, null, typeof( Stream ) );
        }
#endif 

        // Stream input only: detect encoding from the first 4 bytes of the byte buffer starting at ps.bytes[ps.bytePos] 
        private Encoding DetectEncoding() { 
            Debug.Assert( ps.bytes != null );
            Debug.Assert( ps.bytePos == 0 ); 

            if ( ps.bytesUsed < 2 ) {
                return null;
            } 
            int first2Bytes = ps.bytes[0] << 8 | ps.bytes[1];
            int next2Bytes = ( ps.bytesUsed >= 4 ) ? ( ps.bytes[2] << 8 | ps.bytes[3] ) : 0; 
 
            switch ( first2Bytes ) {
#if !SILVERLIGHT // Removing USC4 encoding 
                case 0x0000:
                    switch ( next2Bytes ) {
                        case 0xFEFF:
                            return Ucs4Encoding.UCS4_Bigendian; 
                        case 0x003C:
                            return Ucs4Encoding.UCS4_Bigendian; 
                        case 0xFFFE: 
                            return Ucs4Encoding.UCS4_2143;
                        case 0x3C00: 
                            return Ucs4Encoding.UCS4_2143;
                    }
                    break;
#endif 
                case 0xFEFF:
#if SILVERLIGHT // Removing USC4 encoding 
                    return Encoding.BigEndianUnicode; 
#else
                    if (next2Bytes == 0x0000) { 
                        return Ucs4Encoding.UCS4_3412;
                    }
                    else {
                        return Encoding.BigEndianUnicode; 
                    }
#endif 
                case 0xFFFE: 
#if SILVERLIGHT // Removing USC4 encoding
                    return Encoding.Unicode; 
#else
                    if ( next2Bytes == 0x0000 ) {
                        return Ucs4Encoding.UCS4_Littleendian;
                    } 
                    else {
                        return Encoding.Unicode; 
                    } 
#endif
                case 0x3C00: 
#if SILVERLIGHT // Removing USC4 encoding
                    return Encoding.Unicode;
#else
                    if ( next2Bytes == 0x0000 ) { 
                        return Ucs4Encoding.UCS4_Littleendian;
                    } 
                    else { 
                        return Encoding.Unicode;
                    } 
#endif
                case 0x003C:
#if SILVERLIGHT // Removing USC4 encoding
                    return Encoding.BigEndianUnicode; 
#else
                    if ( next2Bytes == 0x0000 ) { 
                        return Ucs4Encoding.UCS4_3412; 
                    }
                    else { 
                        return Encoding.BigEndianUnicode;
                    }
#endif
                case 0x4C6F: 
                    if ( next2Bytes == 0xA794 ) {
                        Throw( Res.Xml_UnknownEncoding, "ebcdic" ); 
                    } 
                    break;
                case 0xEFBB: 
                    if ( ( next2Bytes & 0xFF00 ) == 0xBF00 ) {
                        return new UTF8Encoding( true, true );
                    }
                    break; 
            }
            // Default encoding is ASCII (using SafeAsciiDecoder) until we read xml declaration. 
            // If we set UTF8 encoding now, it will throw exceptions (=slow) when decoding non-UTF8-friendly 
            // characters after the xml declaration, which may be perfectly valid in the encoding
            // specified in xml declaration. 
            return null;
        }

        private void SetupEncoding( Encoding encoding ) { 
            if ( encoding == null ) {
                Debug.Assert( ps.charPos == 0 ); 
                ps.encoding = Encoding.UTF8; 
                ps.decoder = new SafeAsciiDecoder();
            } 
            else {
                ps.encoding = encoding;

                switch ( ps.encoding.WebName ) { // Encoding.Codepage is not supported in Silverlight 
                    case "utf-16":
                        ps.decoder = new UTF16Decoder( false ); 
                        break; 
                    case "utf-16BE":
                        ps.decoder = new UTF16Decoder( true ); 
                        break;
                    default:
                        ps.decoder = encoding.GetDecoder();
                        break; 
                }
            } 
        } 

        // Switches the reader's encoding 
        private void SwitchEncoding( Encoding newEncoding ) {
#if SILVERLIGHT
            if ( ( newEncoding.WebName != ps.encoding.WebName || ps.decoder is SafeAsciiDecoder ) ) {
#else 
            if ( ( newEncoding.WebName != ps.encoding.WebName || ps.decoder is SafeAsciiDecoder ) && !afterResetState) {
#endif 
                Debug.Assert( ps.stream != null ); 
                UnDecodeChars();
                ps.appendMode = false; 
                SetupEncoding( newEncoding );
                ReadData();
            }
        } 

        // Returns the Encoding object for the given encoding name, if the reader's encoding can be switched to that encoding. 
        // Performs checks whether switching from current encoding to specified encoding is allowed. 
        private Encoding CheckEncoding( string newEncodingName ) {
            // encoding can be switched on stream input only 
            if ( ps.stream == null ) {
                return ps.encoding;
            }
 
             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 ) ) {
                if ( ps.encoding.WebName != "utf-16BE" && 
                     ps.encoding.WebName != "utf-16" &&
                     0 != String.Compare( newEncodingName, "ucs-4", StringComparison.OrdinalIgnoreCase ) ) {
#if SILVERLIGHT // Needed only for XmlTextReader
                    ThrowWithoutLineInfo(Res.Xml_MissingByteOrderMark); 
#else
                    if ( afterResetState ) { 
                        Throw( Res.Xml_EncodingSwitchAfterResetState, newEncodingName ); 
                    }
                    else { 
                        ThrowWithoutLineInfo( Res.Xml_MissingByteOrderMark );
                    }
#endif
                } 
                return ps.encoding;
            } 
 
            Encoding newEncoding = null;
            if ( 0 == String.Compare( newEncodingName, "utf-8", StringComparison.OrdinalIgnoreCase ) ) { 
                newEncoding = new UTF8Encoding( true, true );
            }
            else {
                try { 
                    newEncoding = Encoding.GetEncoding( newEncodingName );
                } 
                catch ( NotSupportedException innerEx ) { 
                    Throw( Res.Xml_UnknownEncoding, newEncodingName, innerEx );
                } 
                catch ( ArgumentException innerEx) {
                    Throw( Res.Xml_UnknownEncoding, newEncodingName, innerEx );
                }
#if !SILVERLIGHT 
                Debug.Assert( newEncoding.EncodingName != "UTF-8" );
#endif 
            } 

#if !SILVERLIGHT // Needed only for XmlTextReader 
            // check for invalid encoding switches after ResetState
            if ( afterResetState && ps.encoding.WebName != newEncoding.WebName ) {
                Throw( Res.Xml_EncodingSwitchAfterResetState, newEncodingName );
            } 
#endif
 
            return newEncoding; 
        }
 
        void UnDecodeChars() {
            Debug.Assert( ps.stream != null && ps.decoder != null && ps.bytes != null );
            Debug.Assert( ps.appendMode, "UnDecodeChars cannot be called after ps.appendMode has been changed to false" );
 
            Debug.Assert(ps.charsUsed >= ps.charPos, "The current position must be in the valid character range.");
            if (maxCharactersInDocument > 0) { 
                // We're returning back in the input (potentially) so we need to fixup 
                //   the character counters to avoid counting some of them twice.
                // The following code effectively rolls-back all decoded characters 
                //   after the ps.charPos (which typically points to the first character
                //   after the XML decl).
                Debug.Assert(charactersInDocument >= ps.charsUsed - ps.charPos,
                    "We didn't correctly count some of the decoded characters against the MaxCharactersInDocument."); 
                charactersInDocument -= ps.charsUsed - ps.charPos;
            } 
            if (maxCharactersFromEntities > 0) { 
                if (InEntity) {
                    Debug.Assert(charactersFromEntities >= ps.charsUsed - ps.charPos, 
                        "We didn't correctly count some of the decoded characters against the MaxCharactersFromEntities.");
                    charactersFromEntities -= ps.charsUsed - ps.charPos;
                }
            } 

            ps.bytePos = documentStartBytePos; // byte position after preamble 
            if ( ps.charPos > 0 ) { 
                ps.bytePos += ps.encoding.GetByteCount( ps.chars, 0, ps.charPos );
            } 
            ps.charsUsed = ps.charPos;
            ps.isEof = false;
        }
 
        private void SwitchEncodingToUTF8() {
            SwitchEncoding( new UTF8Encoding( true, true ) ); 
        } 

        // Reads more data to the character buffer, discarding already parsed chars / decoded bytes. 
        int ReadData() {
            // Append Mode:  Append new bytes and characters to the buffers, do not rewrite them. Allocate new buffers
            //               if the current ones are full
            // Rewrite Mode: Reuse the buffers. If there is less than half of the char buffer left for new data, move 
            //               the characters that has not been parsed yet to the front of the buffer. Same for bytes.
 
            if ( ps.isEof ) { 
                return 0;
            } 

            int charsRead;
            if ( ps.appendMode ) {
                // the character buffer is full -> allocate a new one 
                if ( ps.charsUsed == ps.chars.Length - 1 ) {
                    // invalidate node values kept in buffer - applies to attribute values only 
                    for ( int i = 0; i < attrCount; i++ ) { 
                        nodes[index + i + 1].OnBufferInvalidated();
                    } 

                    char[] newChars = new char[ ps.chars.Length * 2 ];
                    BlockCopyChars( ps.chars, 0, newChars, 0, ps.chars.Length );
                    ps.chars = newChars; 
                }
 
                if ( ps.stream != null ) { 
                    // the byte buffer is full -> allocate a new one
                    if ( ps.bytesUsed - ps.bytePos < MaxByteSequenceLen ) { 
                        if ( ps.bytes.Length - ps.bytesUsed < MaxByteSequenceLen ) {
                            byte[] newBytes = new byte[ ps.bytes.Length * 2 ];
                            BlockCopy( ps.bytes, 0, newBytes, 0, ps.bytesUsed );
                            ps.bytes = newBytes; 
                        }
                    } 
                } 

                charsRead = ps.chars.Length - ps.charsUsed - 1; 
                if ( charsRead > ApproxXmlDeclLength ) {
                    charsRead = ApproxXmlDeclLength;
                }
            } 
            else {
                int charsLen = ps.chars.Length; 
                if ( charsLen - ps.charsUsed <= charsLen/2 ) { 
                    // invalidate node values kept in buffer - applies to attribute values only
                    for ( int i = 0; i < attrCount; i++ ) { 
                        nodes[index + i + 1].OnBufferInvalidated();
                    }

                    // move unparsed characters to front, unless the whole buffer contains unparsed characters 
                    int copyCharsCount = ps.charsUsed - ps.charPos;
                    if ( copyCharsCount < charsLen - 1 ) { 
                        ps.lineStartPos = ps.lineStartPos - ps.charPos; 
                        if ( copyCharsCount > 0 ) {
                            BlockCopyChars( ps.chars, ps.charPos, ps.chars, 0, copyCharsCount ); 
                        }
                        ps.charPos = 0;
                        ps.charsUsed = copyCharsCount;
                    } 
                    else {
                        char[] newChars = new char[ ps.chars.Length * 2 ]; 
                        BlockCopyChars( ps.chars, 0, newChars, 0, ps.chars.Length ); 
                        ps.chars = newChars;
                    } 
                }

                if ( ps.stream != null ) {
                    // move undecoded bytes to the front to make some space in the byte buffer 
                    int bytesLeft = ps.bytesUsed - ps.bytePos;
                    if ( bytesLeft <= MaxBytesToMove  ) { 
                        if ( bytesLeft == 0 ) { 
                            ps.bytesUsed = 0;
                        } 
                        else {
                            BlockCopy( ps.bytes, ps.bytePos, ps.bytes, 0, bytesLeft );
                            ps.bytesUsed = bytesLeft;
                        } 
                        ps.bytePos = 0;
                    } 
                } 
                charsRead = ps.chars.Length - ps.charsUsed - 1;
            } 

            if ( ps.stream != null ) {
                if ( !ps.isStreamEof ) {
                    // read new bytes 
                    if ( ps.bytePos == ps.bytesUsed && ps.bytes.Length - ps.bytesUsed > 0 ) {
                        int read = ps.stream.Read( ps.bytes, ps.bytesUsed, ps.bytes.Length - ps.bytesUsed ); 
                        if ( read == 0 ) { 
                            ps.isStreamEof = true;
                        } 
                        ps.bytesUsed += read;
                    }
                }
 
                int originalBytePos = ps.bytePos;
 
                // decode chars 
                charsRead = GetChars( charsRead );
                if ( charsRead == 0 && ps.bytePos != originalBytePos ) { 
                    // GetChars consumed some bytes but it was not enough bytes to form a character -> try again
                    return ReadData();
                }
            } 
            else if ( ps.textReader != null ) {
                // read chars 
                charsRead = ps.textReader.Read( ps.chars, ps.charsUsed, ps.chars.Length - ps.charsUsed - 1 ); 
                ps.charsUsed += charsRead;
            } 
            else {
                charsRead = 0;
            }
 
            RegisterConsumedCharacters(charsRead, InEntity);
 
            if ( charsRead == 0 ) { 
                Debug.Assert ( ps.charsUsed < ps.chars.Length );
                ps.isEof = true; 
            }
            ps.chars[ ps.charsUsed ] = (char)0;
            return charsRead;
        } 

        // Stream input only: read bytes from stream and decodes them according to the current encoding 
        int GetChars( int maxCharsCount ) { 
            Debug.Assert( ps.stream != null && ps.decoder != null && ps.bytes != null );
            Debug.Assert( maxCharsCount <= ps.chars.Length - ps.charsUsed - 1 ); 

            // determine the maximum number of bytes we can pass to the decoder
            int bytesCount = ps.bytesUsed - ps.bytePos;
            if ( bytesCount == 0 ) { 
                return 0;
            } 
 
            int charsCount;
            bool completed; 
            try {
                // decode chars
                ps.decoder.Convert( ps.bytes, ps.bytePos, bytesCount, ps.chars, ps.charsUsed, maxCharsCount, false, out bytesCount, out charsCount, out completed );
            } 
            catch ( ArgumentException ) {
                InvalidCharRecovery( ref bytesCount, out charsCount ); 
            } 

            // move pointers and return 
            ps.bytePos += bytesCount;
            ps.charsUsed += charsCount;
            Debug.Assert( maxCharsCount >= charsCount );
            return charsCount; 
        }
 
        private void InvalidCharRecovery( ref int bytesCount, out int charsCount ) { 
            int charsDecoded = 0;
            int bytesDecoded = 0; 
            try {
                while ( bytesDecoded <  bytesCount ) {
                    int chDec;
                    int bDec; 
                    bool completed;
                    ps.decoder.Convert( ps.bytes, ps.bytePos + bytesDecoded, 1, ps.chars, ps.charsUsed + charsDecoded, 1, false, out bDec, out chDec, out completed ); 
                    charsDecoded += chDec; 
                    bytesDecoded += bDec;
                } 
                Debug.Assert( false, "We should get an exception again." );
            }
            catch ( ArgumentException ) {
            } 

            if ( charsDecoded == 0 ) { 
                Throw( ps.charsUsed, Res.Xml_InvalidCharInThisEncoding ); 
            }
            charsCount = charsDecoded; 
            bytesCount = bytesDecoded;
        }

        internal void Close( bool closeInput ) { 
            if ( parsingFunction == ParsingFunction.ReaderClosed ) {
                return; 
            } 

            while ( InEntity ) { 
                PopParsingState();
            }

            ps.Close( closeInput ); 

            curNode = NodeData.None; 
            parsingFunction = ParsingFunction.ReaderClosed; 
            reportedEncoding = null;
            reportedBaseUri = string.Empty; 
            readState = ReadState.Closed;
            fullAttrCleanup = false;
            ResetAttributes();
        } 

        void ShiftBuffer( int sourcePos, int destPos, int count ) { 
            BlockCopyChars( ps.chars, sourcePos, ps.chars, destPos, count ); 
        }
 
        // Parses the xml or text declaration and switched encoding if needed
        private bool ParseXmlDeclaration( bool isTextDecl ) {
            while ( ps.charsUsed - ps.charPos < 6 ) {  // minimum "
            Encoding encoding = null;
 
            for (;;) {
                int originalSbLen = sb.Length; 
                int wsCount = EatWhitespaces( xmlDeclState == 0 ? null : sb ); 

                // end of xml declaration 
                if ( ps.chars[ps.charPos] == '?' ) {
                    sb.Length = originalSbLen;

                    if ( ps.chars[ps.charPos + 1] == '>' ) { 
                        if ( xmlDeclState == 0 ) {
                            Throw( isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl ); 
                        } 

                        ps.charPos += 2; 
                        if ( !isTextDecl ) {
                            curNode.SetValue( sb.ToString() );
                            sb.Length = 0;
 
                            nextParsingFunction = parsingFunction;
                            parsingFunction = ParsingFunction.ResetAttributesRootLevel; 
                        } 

                        // switch to encoding specified in xml declaration 
                        if ( encoding == null ) {
                            if ( isTextDecl ) {
                                Throw( Res.Xml_InvalidTextDecl );
                            } 
#if !SILVERLIGHT // Needed only for XmlTextReader
                            if ( afterResetState ) { 
                                // check for invalid encoding switches to default encoding 
                                string encodingName = ps.encoding.WebName;
                                if ( encodingName != "utf-8" && encodingName != "utf-16" && 
                                     encodingName != "utf-16BE" && !( ps.encoding is Ucs4Encoding ) ) {
                                    Throw( Res.Xml_EncodingSwitchAfterResetState, ( ps.encoding.GetByteCount( "A" ) == 1 ) ? "UTF-8" : "UTF-16" );
                                }
                            } 
#endif
                            if ( ps.decoder is SafeAsciiDecoder ) { 
                                SwitchEncodingToUTF8(); 
                            }
                        } 
                        else {
                            SwitchEncoding( encoding );
                        }
                        ps.appendMode = false; 
                        return true;
                    } 
                    else if ( ps.charPos + 1 == ps.charsUsed ) { 
                        goto ReadData;
                    } 
                    else {
                        ThrowUnexpectedToken( "'>'" );
                    }
                } 

                if ( wsCount == 0 && xmlDeclState != 0 ) { 
                    ThrowUnexpectedToken( "?>" ); 
                }
 
                // read attribute name
                int nameEndPos = ParseName();

                NodeData attr = null; 
                switch ( ps.chars[ps.charPos] ) {
                    case 'v': 
                        if ( XmlConvert.StrEqual( ps.chars, ps.charPos, nameEndPos - ps.charPos, "version" ) && xmlDeclState == 0 ) { 
                            if ( !isTextDecl ) {
                                attr = AddAttributeNoChecks( "version", 1 ); 
                            }
                            break;
                        }
                        goto default; 
                    case 'e':
                        if ( XmlConvert.StrEqual( ps.chars, ps.charPos, nameEndPos - ps.charPos, "encoding" ) && 
                            ( xmlDeclState == 1 || ( isTextDecl && xmlDeclState == 0 ) ) ) { 
                            if ( !isTextDecl ) {
                                attr = AddAttributeNoChecks( "encoding", 1 ); 
                            }
                            xmlDeclState = 1;
                            break;
                        } 
                        goto default;
                    case 's': 
                        if ( XmlConvert.StrEqual( ps.chars, ps.charPos, nameEndPos - ps.charPos, "standalone" ) && 
                             ( xmlDeclState == 1 || xmlDeclState == 2 ) && !isTextDecl ) {
                            if ( !isTextDecl ) { 
                                attr = AddAttributeNoChecks( "standalone", 1 );
                            }
                            xmlDeclState = 2;
                            break; 
                        }
                        goto default; 
                    default: 
                        Throw( isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl );
                        break; 
                }
                if ( !isTextDecl ) {
                    attr.SetLineInfo( ps.LineNo, ps.LinePos );
                } 
                sb.Append( ps.chars, ps.charPos, nameEndPos - ps.charPos );
                ps.charPos = nameEndPos; 
 
                // parse equals and quote char;
                if ( ps.chars[ps.charPos] != '=' ) { 
                    EatWhitespaces( sb );
                    if ( ps.chars[ps.charPos] != '=' ) {
                        ThrowUnexpectedToken( "=" );
                    } 
                }
                sb.Append( '=' ); 
                ps.charPos++; 

                char quoteChar = ps.chars[ps.charPos]; 
                if ( quoteChar != '"' && quoteChar != '\'' ) {
                    EatWhitespaces( sb );
                    quoteChar = ps.chars[ps.charPos];
                    if ( quoteChar != '"' && quoteChar != '\'' ) { 
                        ThrowUnexpectedToken( "\"", "'" );
                    } 
                } 
                sb.Append( quoteChar );
                ps.charPos++; 
                if ( !isTextDecl ) {
                    attr.quoteChar = quoteChar;
                    attr.SetLineInfo2( ps.LineNo, ps.LinePos );
                } 

                // parse attribute value 
                int pos = ps.charPos; 
                char[] chars;
            Continue: 
                chars = ps.chars;
#if SILVERLIGHT
                while (xmlCharType.IsAttributeValueChar(chars[pos])) {
                    pos++; 
                }
#else // Optimization due to the lack of inlining when a method uses byte* 
                unsafe { 
                    while ( ( (xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue) != 0) ) {
                        pos++; 
                    }
                }
#endif
 
                if ( ps.chars[pos] == quoteChar ) {
                    switch ( xmlDeclState ) { 
                        // version 
                        case 0:
#if XML10_FIFTH_EDITION 
                            //  VersionNum ::= '1.' [0-9]+   (starting with XML Fifth Edition)
                            if ( pos - ps.charPos >= 3 &&
                                 ps.chars[ps.charPos] == '1' &&
                                 ps.chars[ps.charPos + 1] == '.' && 
                                 XmlCharType.IsOnlyDigits( ps.chars, ps.charPos + 2, pos - ps.charPos - 2 ) ) {
#else 
                            // VersionNum  ::=  '1.0'        (XML Fourth Edition and earlier) 
                            if ( XmlConvert.StrEqual( ps.chars, ps.charPos, pos - ps.charPos, "1.0" ) ) {
#endif 
                                if ( !isTextDecl ) {
                                    attr.SetValue( ps.chars, ps.charPos, pos - ps.charPos );
                                }
                                xmlDeclState = 1; 
                            }
                            else { 
                                string badVersion = new string( ps.chars, ps.charPos, pos - ps.charPos ); 
                                Throw( Res.Xml_InvalidVersionNumber, badVersion );
                            } 
                            break;
                        case 1:
                            string encName = new string( ps.chars, ps.charPos, pos - ps.charPos );
                            encoding = CheckEncoding( encName ); 
                            if ( !isTextDecl ) {
                                attr.SetValue( encName ); 
                            } 
                            xmlDeclState = 2;
                            break; 
                        case 2:
                            if ( XmlConvert.StrEqual( ps.chars, ps.charPos, pos - ps.charPos, "yes" ) ) {
                                this.standalone = true;
                            } 
                            else if ( XmlConvert.StrEqual( ps.chars, ps.charPos, pos - ps.charPos, "no" ) ) {
                                this.standalone = false; 
                            } 
                            else {
                                Debug.Assert( !isTextDecl ); 
                                Throw( Res.Xml_InvalidXmlDecl, ps.LineNo, ps.LinePos - 1 );
                            }
                            if ( !isTextDecl ) {
                                attr.SetValue( ps.chars, ps.charPos, pos - ps.charPos ); 
                            }
                            xmlDeclState = 3; 
                            break; 
                        default:
                            Debug.Assert( false ); 
                            break;
                    }
                    sb.Append( chars, ps.charPos, pos - ps.charPos );
                    sb.Append( quoteChar ); 
                    ps.charPos = pos + 1;
                    continue; 
                } 
                else if ( pos == ps.charsUsed ) {
                    if ( ReadData() != 0 ) { 
                        goto Continue;
                    }
                    else {
                        Throw( Res.Xml_UnclosedQuote ); 
                    }
                } 
                else { 
                    Throw( isTextDecl ? Res.Xml_InvalidTextDecl : Res.Xml_InvalidXmlDecl );
                } 

            ReadData:
                if ( ps.isEof || ReadData() == 0 ) {
                    Throw( Res.Xml_UnexpectedEOF1 ); 
                }
            } 
 
        NoXmlDecl:
            // no xml declaration 
            if ( !isTextDecl ) {
                parsingFunction = nextParsingFunction;
            }
#if !SILVERLIGHT // Needed only for XmlTextReader 
            if ( afterResetState ) {
                // check for invalid encoding switches to default encoding 
                string encodingName = ps.encoding.WebName; 
                if ( encodingName != "utf-8" && encodingName != "utf-16" &&
                    encodingName != "utf-16BE" && !( ps.encoding is Ucs4Encoding ) ) { 
                    Throw( Res.Xml_EncodingSwitchAfterResetState, ( ps.encoding.GetByteCount( "A" ) == 1 ) ? "UTF-8" : "UTF-16" );
                }
            }
#endif 
            if ( ps.decoder is SafeAsciiDecoder ) {
                SwitchEncodingToUTF8(); 
            } 
            ps.appendMode = false;
            return false; 
        }

        // Parses the document content
        private bool ParseDocumentContent() { 

            for (;;) { 
                bool needMoreChars = false; 
                int pos = ps.charPos;
                char[] chars = ps.chars; 

                // some tag
                if ( chars[pos] == '<' ) {
                    needMoreChars = true; 
                    if ( ps.charsUsed - pos < 4 ) // minimum  ""
                        goto ReadData; 
                    pos++; 
                    switch ( chars[pos] ) {
                        // processing instruction 
                        case '?':
                            ps.charPos = pos + 1;
                            if ( ParsePI() ) {
                                return true; 
                            }
                            continue; 
                        case '!': 
                            pos++;
                            if ( ps.charsUsed - pos < 2 ) // minimum characters expected "--" 
                                goto ReadData;
                            // comment
                            if ( chars[pos] == '-' ) {
                                if ( chars[pos+1] == '-' ) { 
                                    ps.charPos = pos + 2;
                                    if ( ParseComment() ) { 
                                        return true; 
                                    }
                                    continue; 
                                }
                                else {
                                    ThrowUnexpectedToken( pos + 1, "-" );
                                } 
                            }
                            // CDATA section 
                            else if ( chars[pos] == '[' ) { 
                                if ( fragmentType != XmlNodeType.Document ) {
                                    pos++; 
                                    if ( ps.charsUsed - pos < 6 ) {
                                        goto ReadData;
                                    }
                                    if ( XmlConvert.StrEqual( chars, pos, 6, "CDATA[" ) ) { 
                                        ps.charPos = pos + 6;
                                        ParseCData(); 
                                        if ( fragmentType == XmlNodeType.None ) { 
                                            fragmentType = XmlNodeType.Element;
                                        } 
                                        return true;
                                    }
                                    else {
                                        ThrowUnexpectedToken( pos, "CDATA[" ); 
                                    }
                                } 
                                else { 
                                    Throw( ps.charPos, Res.Xml_InvalidRootData );
                                } 
                            }
                            // DOCTYPE declaration
                            else {
                                if ( fragmentType == XmlNodeType.Document || fragmentType == XmlNodeType.None ) { 
                                    fragmentType = XmlNodeType.Document;
                                    ps.charPos = pos; 
                                    if ( ParseDoctypeDecl() ) { 
                                        return true;
                                    } 
                                    continue;
                                }
                                else {
                                    if ( ParseUnexpectedToken( pos ) == "DOCTYPE" ) { 
                                        Throw( Res.Xml_BadDTDLocation );
                                    } 
                                    else { 
                                        ThrowUnexpectedToken( pos, "" ) );
                            ps.charPos -= 3; 
                            incReadState = IncrementalReadState.Text;
                        }
                        goto Append;
                    case IncrementalReadState.CDATA: 
                        if ( ParseCDataOrComment( XmlNodeType.CDATA, out startPos, out pos ) ) {
                            Debug.Assert( XmlConvert.StrEqual( ps.chars, ps.charPos - 3, 3, "]]>" ) ); 
                            ps.charPos -= 3; 
                            incReadState = IncrementalReadState.Text;
                        } 
                        goto Append;
                    case IncrementalReadState.EndElement:
                        parsingFunction = ParsingFunction.PopElementContext;
                        nextParsingFunction = ( index > 0 || fragmentType != XmlNodeType.Document ) ? ParsingFunction.ElementContent 
																								    : ParsingFunction.DocumentContent;
                        outerReader.Read(); 
                        incReadState = IncrementalReadState.End; 
                        goto case IncrementalReadState.End;
                    case IncrementalReadState.End: 
                        return charsDecoded;
                    case IncrementalReadState.ReadData:
                        if ( ReadData() == 0 ) {
                            ThrowUnclosedElements(); 
                        }
                        incReadState = IncrementalReadState.Text; 
                        startPos = ps.charPos; 
                        pos = startPos;
                        break; 
                    default:
                        Debug.Assert( false );
                        break;
                } 
                Debug.Assert( incReadState == IncrementalReadState.Text ||
                              incReadState == IncrementalReadState.Attributes || 
                              incReadState == IncrementalReadState.AttributeValue ); 

                char[] chars = ps.chars; 
                startPos = ps.charPos;
                pos = startPos;

                for (;;) { 
                    incReadLineInfo.Set( ps.LineNo, ps.LinePos );
 
                    char c; 
                    unsafe {
                        if ( incReadState == IncrementalReadState.Attributes ) { 
                            while ( ( ( xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fAttrValue ) != 0 ) && c != '/' ) {
                                pos++;
                            }
                        } 
                        else {
                            while ( ( ( xmlCharType.charProperties[c = chars[pos]] & XmlCharType.fAttrValue ) != 0 ) ) { 
                                pos++; 
                            }
                        } 
                    }

                    if ( chars[pos] == '&' || chars[pos] == (char)0x9 ) {
                        pos++; 
                        continue;
                    } 
 
                    if ( pos - startPos > 0 ) {
                        goto AppendAndUpdateCharPos; 
                    }

                    switch ( chars[pos] ) {
                        // eol 
                        case (char)0xA:
                            pos++; 
                            OnNewLine( pos ); 
                            continue;
                        case (char)0xD: 
                            if ( chars[pos+1] == (char)0xA ) {
                                pos += 2;
                            }
                            else if ( pos+1 < ps.charsUsed ) { 
                                pos++;
                            } 
                            else { 
                                goto ReadData;
                            } 
                            OnNewLine( pos );
                            continue;
                        // some tag
                        case '<': 
                            if ( incReadState != IncrementalReadState.Text ) {
                                pos++; 
                                continue; 
                            }
                            if ( ps.charsUsed - pos < 2 ) { 
                                goto ReadData;
                            }
                            switch ( chars[pos+1] ) {
                                // pi 
                                case '?':
                                    pos += 2; 
                                    incReadState = IncrementalReadState.PI; 
                                    goto AppendAndUpdateCharPos;
                                // comment 
                                case '!':
                                    if ( ps.charsUsed - pos < 4 ) {
                                        goto ReadData;
                                    } 
                                    if ( chars[pos+2] == '-' && chars[pos+3] == '-' ) {
                                        pos += 4; 
                                        incReadState = IncrementalReadState.Comment; 
                                        goto AppendAndUpdateCharPos;
                                    } 
                                    if ( ps.charsUsed - pos < 9 ) {
                                        goto ReadData;
                                    }
                                    if ( XmlConvert.StrEqual( chars, pos + 2, 7, "[CDATA[" ) ) { 
                                        pos += 9;
                                        incReadState = IncrementalReadState.CDATA; 
                                        goto AppendAndUpdateCharPos; 
                                    }
                                    else { 
                                        ;//Throw( );
                                    }
                                    break;
                                // end tag 
                                case '/':
                                { 
                                    Debug.Assert( ps.charPos - pos == 0 ); 
                                    Debug.Assert( ps.charPos - startPos == 0);
 
                                    int colonPos;
                                    // ParseQName can flush the buffer, so we need to update the startPos, pos and chars after calling it
                                    int endPos = ParseQName( true, 2, out colonPos );
                                    if ( XmlConvert.StrEqual( chars, ps.charPos + 2, endPos - ps.charPos - 2, curNode.GetNameWPrefix( nameTable ) ) && 
                                        ( ps.chars[endPos] == '>' || xmlCharType.IsWhiteSpace( ps.chars[endPos] ) ) ) {
 
                                        if ( --incReadDepth > 0 ) { 
                                            pos = endPos + 1;
                                            continue; 
                                        }

                                        ps.charPos = endPos;
                                        if ( xmlCharType.IsWhiteSpace( ps.chars[endPos] ) ) { 
                                            EatWhitespaces( null );
                                        } 
                                        if ( ps.chars[ps.charPos] != '>' ) { 
                                            ThrowUnexpectedToken( ">" );
                                        } 
                                        ps.charPos++;

                                        incReadState = IncrementalReadState.EndElement;
                                        goto OuterContinue; 
                                    }
                                    else { 
                                        pos = endPos; 
                                        startPos = ps.charPos;
                                        chars = ps.chars; 
                                        continue;
                                    }
                                }
                                // start tag 
                                default:
                                { 
                                    Debug.Assert( ps.charPos - pos == 0 ); 
                                    Debug.Assert( ps.charPos - startPos == 0 );
 
                                    int colonPos;
                                    // ParseQName can flush the buffer, so we need to update the startPos, pos and chars after calling it
                                    int endPos = ParseQName( true, 1, out colonPos );
                                    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] ) ) ) {
                                        incReadDepth++; 
                                        incReadState = IncrementalReadState.Attributes; 
                                        pos = endPos;
                                        goto AppendAndUpdateCharPos; 
                                    }
                                    pos = endPos;
                                    startPos = ps.charPos;
                                    chars = ps.chars; 
                                    continue;
                                } 
                            } 
                            break;
                        // end of start tag 
                        case '/':
                            if ( incReadState == IncrementalReadState.Attributes ) {
                                if ( ps.charsUsed - pos < 2 ) {
                                    goto ReadData; 
                                }
                                if ( chars[pos+1] == '>' ) { 
                                    incReadState = IncrementalReadState.Text; 
                                    incReadDepth--;
                                } 
                            }
                            pos++;
                            continue;
                        // end of start tag 
                        case '>':
                            if ( incReadState == IncrementalReadState.Attributes ) { 
                                incReadState = IncrementalReadState.Text; 
                            }
                            pos++; 
                            continue;
                        case '"':
                        case '\'':
                            switch ( incReadState ) { 
                                case IncrementalReadState.AttributeValue:
                                    if ( chars[pos] == curNode.quoteChar ) { 
                                        incReadState = IncrementalReadState.Attributes; 
                                    }
                                    break; 
                                case IncrementalReadState.Attributes:
                                    curNode.quoteChar = chars[pos];
                                    incReadState = IncrementalReadState.AttributeValue;
                                    break; 
                            }
                            pos++; 
                            continue; 
                        default:
                            // end of buffer 
                            if ( pos == ps.charsUsed ) {
                                goto ReadData;
                            }
                            // surrogate chars or invalid chars are ignored 
                            else {
                                pos++; 
                                continue; 
                            }
                    } 
                }

            ReadData:
                incReadState = IncrementalReadState.ReadData; 

            AppendAndUpdateCharPos: 
                ps.charPos = pos; 

            Append: 
                // decode characters
                int charsParsed = pos - startPos;
                if ( charsParsed > 0 ) {
                    int count; 
                    try {
                        count = incReadDecoder.Decode( ps.chars, startPos, charsParsed ); 
                    } 
                    catch ( XmlException e ) {
                        ReThrow( e, (int)incReadLineInfo.lineNo, (int)incReadLineInfo.linePos ); 
                        return 0;
                    }
                    Debug.Assert( count == charsParsed || incReadDecoder.IsFull, "Check if decoded consumed all characters unless it's full." );
                    charsDecoded += count; 
                    if ( incReadDecoder.IsFull ) {
                        incReadLeftStartPos = startPos + count; 
                        incReadLeftEndPos = pos; 
                        incReadLineInfo.linePos += count; // we have never more than 1 line cached
                        return charsDecoded; 
                    }
                }
            }
        } 

        private void FinishIncrementalRead() { 
            incReadDecoder = new IncrementalReadDummyDecoder(); 
            IncrementalRead();
            Debug.Assert( IncrementalRead() == 0, "Previous call of IncrementalRead should eat up all characters!" ); 
            incReadDecoder = null;
        }

        private bool ParseFragmentAttribute() { 
            Debug.Assert( fragmentType == XmlNodeType.Attribute );
 
            // if first call then parse the whole attribute value 
            if ( curNode.type == XmlNodeType.None ) {
                curNode.type = XmlNodeType.Attribute; 
                curAttrIndex = 0;
                ParseAttributeValueSlow( ps.charPos, ' ', curNode ); // The quote char is intentionally empty (space) because we need to parse ' and " into the attribute value
            }
            else { 
                parsingFunction = ParsingFunction.InReadAttributeValue;
            } 
 
            // return attribute value chunk
            if ( ReadAttributeValue() ) { 
                Debug.Assert( parsingFunction == ParsingFunction.InReadAttributeValue );
                parsingFunction = ParsingFunction.FragmentAttribute;
                return true;
            } 
            else {
                OnEof(); 
                return false; 
            }
        } 

#endif

#if !SILVERLIGHT // Needed only for XmlTextReader (ReadChars, ReadBase64, ReadBinHex) 
        private bool ParseAttributeValueChunk() {
            char[] chars = ps.chars; 
            int pos  = ps.charPos; 

            curNode = AddNode( index + attrCount + 1, index + 2 ); 
            curNode.SetLineInfo( ps.LineNo, ps.LinePos );

            if ( emptyEntityInAttributeResolved ) {
                curNode.SetValueNode( XmlNodeType.Text, string.Empty ); 
                emptyEntityInAttributeResolved = false;
                return true; 
            } 

            Debug.Assert( stringBuilder.Length == 0 ); 

            for (;;) {
                unsafe {
                    while ( ( ( xmlCharType.charProperties[chars[pos]] & XmlCharType.fAttrValue ) != 0 ) ) 
                        pos++;
                } 
 
                switch ( chars[pos] ) {
                    // eol D 
                    case (char)0xD:
                        Debug.Assert( ps.eolNormalized, "Entity replacement text for attribute values should be EOL-normalized!" );
                        pos++;
                        continue; 
                    // eol A, tab
                    case (char)0xA: 
                    case (char)0x9: 
                        if ( normalize ) {
                            chars[pos] = (char)0x20;  // CDATA normalization of 0xA and 0x9 
                        }
                        pos++;
                        continue;
                    case '"': 
                    case '\'':
                    case '>': 
                        pos++; 
                        continue;
                    // attribute values cannot contain '<' 
                    case '<':
                        Throw( pos, Res.Xml_BadAttributeChar, XmlException.BuildCharExceptionArgs( '<', '\0' ) );
                        break;
                    // entity reference 
                    case '&':
                        if ( pos - ps.charPos > 0 ) { 
                            stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); 
                        }
                        ps.charPos = pos; 

                        // expand char entities but not general entities
                        switch ( HandleEntityReference( true, EntityExpandType.OnlyCharacter, out pos ) ) {
                            case EntityType.CharacterDec: 
                            case EntityType.CharacterHex:
                            case EntityType.CharacterNamed: 
                                chars = ps.chars; 
                                if ( normalize && xmlCharType.IsWhiteSpace( chars[ps.charPos] ) && pos - ps.charPos == 1 ) {
                                    chars[ps.charPos] = (char)0x20;  // CDATA normalization of character references in entities 
                                }
                                break;
                            case EntityType.Unexpanded:
                                if ( stringBuilder.Length == 0 ) { 
                                    curNode.lineInfo.linePos++;
                                    ps.charPos++; 
                                    curNode.SetNamedNode( XmlNodeType.EntityReference, ParseEntityName() ); 
                                    return true;
                                } 
                                else {
                                    goto ReturnText;
                                }
                            default: 
                                Debug.Assert( false, "We should never get to this point." );
                                break; 
                        } 
                        chars = ps.chars;
                        continue; 
                    default:
                        // end of buffer
                        if ( pos == ps.charsUsed ) {
                            goto ReadData; 
                        }
                        // surrogate chars 
                        else { 
                            char ch = chars[pos];
                            if ( XmlCharType.IsHighSurrogate(ch) ) { 
                                if ( pos + 1 == ps.charsUsed ) {
                                    goto ReadData;
                                }
                                pos++; 
                                if ( XmlCharType.IsLowSurrogate( chars[pos] ) ) {
                                    pos++; 
                                    continue; 
                                }
                            } 
                            ThrowInvalidChar( chars, ps.charsUsed, pos );
                            break;
                        }
                } 

            ReadData: 
                if ( pos - ps.charPos > 0 ) { 
                    stringBuilder.Append( chars, ps.charPos, pos - ps.charPos );
                    ps.charPos = pos; 
                }
                // read new characters into the buffer
                if ( ReadData() == 0 ) {
                    if ( stringBuilder.Length > 0 ) { 
                        goto ReturnText;
                    } 
                    else { 
                        if ( HandleEntityEnd( false ) ) {
                            SetupEndEntityNodeInAttribute(); 
                            return true;
                        }
                        else {
                            Debug.Assert( false, "We should never get to this point." ); 
                        }
                    } 
                } 

                pos = ps.charPos; 
                chars = ps.chars;
            }

        ReturnText: 
            if ( pos - ps.charPos > 0 ) {
                stringBuilder.Append( chars, ps.charPos, pos - ps.charPos ); 
                ps.charPos = pos; 
            }
            curNode.SetValueNode( XmlNodeType.Text, stringBuilder.ToString() ); 
            stringBuilder.Length = 0;
            return true;
        }
 
        private void ParseXmlDeclarationFragment() {
            try { 
                ParseXmlDeclaration( false ); 
            }
            catch ( XmlException e ) { 
                ReThrow( e, e.LineNumber, e.LinePosition - 6 ); // 6 == strlen( " create a new one 
            else if ( nt == null ) {
                nt = new NameTable();
                Debug.Assert( nameTableFromSettings == false );
            } 
            nameTable = nt;
 
            // make sure we have namespace manager 
            if ( namespaceManager == null ) {
                namespaceManager = new XmlNamespaceManager( nt ); 
            }

            // copy xml:space and xml:lang
            xmlContext.xmlSpace = context.XmlSpace; 
            xmlContext.xmlLang = context.XmlLang;
        } 
 
//
// DtdInfo 
//
#if !SILVERLIGHT
        internal override IDtdInfo DtdInfo {
            get { 
                return dtdInfo;
            } 
        } 

        internal void SetDtdInfo(IDtdInfo newDtdInfo) { 
            Debug.Assert( dtdInfo == null );

            dtdInfo = newDtdInfo;
            if ( dtdInfo != null ) { 
                if ( ( validatingReaderCompatFlag || !v1Compat ) && ( dtdInfo.HasDefaultAttributes || dtdInfo.HasNonCDataAttributes ) ) {
                    addDefaultAttributesAndNormalize = true; 
                } 
            }
        } 
#endif

        //
// Validation support 
//
 
#if !SILVERLIGHT // no validation in Silverlight 
        internal IValidationEventHandling ValidationEventHandling {
            set { 
                validationEventHandling = value;
            }
        }
 
        internal OnDefaultAttributeUseDelegate OnDefaultAttributeUse {
            set { onDefaultAttributeUse = value; } 
        } 
#endif
 
//
// Internal properties for XmlValidatingReader
//
#if !SILVERLIGHT // Needed only for XmlValidatingReader 

        internal bool XmlValidatingReaderCompatibilityMode { 
            set { 
                validatingReaderCompatFlag = value;
 
                // Fix for VSWhidbey 516556; These namespaces must be added to the nametable for back compat reasons.
                if ( value ) {
                    nameTable.Add( XmlReservedNs.NsXs ); // Note: this is equal to XmlReservedNs.NsXsd in Everett
                    nameTable.Add( XmlReservedNs.NsXsi ); 
                    nameTable.Add( XmlReservedNs.NsDataType );
                } 
            } 
        }
 
        internal XmlNodeType FragmentType {
            get {
                return fragmentType;
            } 
        }
 
        internal void ChangeCurrentNodeType( XmlNodeType newNodeType ) { 
            Debug.Assert( curNode.type == XmlNodeType.Whitespace && newNodeType == XmlNodeType.SignificantWhitespace, "Incorrect node type change!" );
            curNode.type = newNodeType; 
        }

        internal XmlResolver GetResolver() {
            return xmlResolver; 
        }
 
        internal object InternalSchemaType { 
            get {
                return curNode.schemaType; 
            }
            set {
                curNode.schemaType = value;
            } 
        }
 
        internal object InternalTypedValue { 
            get {
                return curNode.typedValue; 
            }
            set {
                curNode.typedValue = value;
            } 
        }
 
        internal bool StandAlone { 
            get {
                return standalone; 
            }
        }

        internal override XmlNamespaceManager NamespaceManager { 
            get {
                return namespaceManager; 
            } 
        }
 
        internal bool V1Compat {
            get {
                return v1Compat;
            } 
        }
 
        internal ConformanceLevel V1ComformanceLevel { 
            get {
                return fragmentType == XmlNodeType.Element ? ConformanceLevel.Fragment : ConformanceLevel.Document; 
            }
        }

#endif 
        private bool AddDefaultAttributeDtd(IDtdDefaultAttributeInfo defAttrInfo, bool definedInDtd, NodeData[] nameSortedNodeData) {
 
            if ( defAttrInfo.Prefix.Length > 0 ) { 
                attrNeedNamespaceLookup = true;
            } 

            string localName = defAttrInfo.LocalName;
            string prefix = defAttrInfo.Prefix;
 
            // check for duplicates
            if (nameSortedNodeData != null) { 
                if (Array.BinarySearch(nameSortedNodeData, defAttrInfo, DtdDefaultAttributeInfoToNodeDataComparer.Instance) >= 0) { 
                    return false;
                } 
            }
            else {
                for (int i = index + 1; i < index + 1 + attrCount; i++) {
                    if ((object)nodes[i].localName == (object)localName && 
                        (object)nodes[i].prefix == (object)prefix) {
                        return false; 
                    } 
                }
            } 

            NodeData attr = AddDefaultAttributeInternal( defAttrInfo.LocalName, null, defAttrInfo.Prefix, defAttrInfo.DefaultValueExpanded,
                                                         defAttrInfo.LineNumber, defAttrInfo.LinePosition,
                                                         defAttrInfo.ValueLineNumber, defAttrInfo.ValueLinePosition, defAttrInfo.IsXmlAttribute ); 

            Debug.Assert(attr != null); 
 
#if !SILVERLIGHT
            if (DtdValidation) { 
                if (onDefaultAttributeUse != null) {
                    onDefaultAttributeUse(defAttrInfo, this);
                }
                attr.typedValue = defAttrInfo.DefaultValueTyped; 
            }
#endif 
            return attr != null; 
        }
 
#if !SILVERLIGHT // Needed only for XmlValidatingReader
        internal bool AddDefaultAttributeNonDtd( SchemaAttDef attrDef ) {

            // atomize names - Xsd Validator does not need to have the same nametable 
            string localName = nameTable.Add( attrDef.Name.Name );
            string prefix = nameTable.Add( attrDef.Prefix ); 
            string ns = nameTable.Add( attrDef.Name.Namespace ); 

            // atomize namespace - Xsd Validator does not need to have the same nametable 
            if ( prefix.Length == 0 && ns.Length > 0 ) {
                prefix = namespaceManager.LookupPrefix( ns );

                Debug.Assert( prefix != null ); 
                if ( prefix == null ) {
                    prefix = string.Empty; 
                } 
            }
 
           // find out if the attribute is already there
            for (int i = index + 1; i < index + 1 + attrCount; i++) {
                if ((object)nodes[i].localName == (object)localName &&
                    (((object)nodes[i].prefix == (object)prefix) || ((object)nodes[i].ns == (object)ns && ns != null))) { 
                    return false;
                } 
            } 

            // attribute does not exist -> we need to add it 
            NodeData attr = AddDefaultAttributeInternal( localName, ns, prefix, attrDef.DefaultValueExpanded,
                                                         attrDef.LineNumber, attrDef.LinePosition,
                                                         attrDef.ValueLineNumber, attrDef.ValueLinePosition, attrDef.Reserved != SchemaAttDef.Reserve.None );
            Debug.Assert(attr != null); 

            attr.schemaType = (attrDef.SchemaType == null) ? (object)attrDef.Datatype : (object)attrDef.SchemaType; 
            attr.typedValue = attrDef.DefaultValueTyped; 
            return true;
        } 
#endif

        private NodeData AddDefaultAttributeInternal(string localName, string ns, string prefix, string value,
                                                     int lineNo, int linePos, int valueLineNo, int valueLinePos, bool isXmlAttribute) { 
            // setup the attribute
            NodeData attr = AddAttribute( localName, prefix, prefix.Length > 0 ? null : localName ); 
            if ( ns != null ) { 
                attr.ns = ns;
            } 

            attr.SetValue( value );
            attr.IsDefaultAttribute = true;
            attr.lineInfo.Set( lineNo, linePos ); 
            attr.lineInfo2.Set( valueLineNo, valueLinePos );
 
            // handle special attributes: 
            if ( attr.prefix.Length == 0 ) {
                // default namespace declaration 
                if ( Ref.Equal( attr.localName, XmlNs ) ) {
                    OnDefaultNamespaceDecl( attr );
                    if ( !attrNeedNamespaceLookup ) {
                        // change element default namespace 
                        Debug.Assert( nodes[index].type == XmlNodeType.Element );
                        if ( nodes[index].prefix.Length == 0 ) { 
                            nodes[index].ns = xmlContext.defaultNamespace; 
                        }
                    } 
                }
            }
            else {
                // prefixed namespace declaration 
                if ( Ref.Equal( attr.prefix, XmlNs ) ) {
                    OnNamespaceDecl( attr ); 
                    if ( !attrNeedNamespaceLookup ) { 
                        // change namespace of current element and attributes
                        string pref = attr.localName; 
                        Debug.Assert( nodes[index].type == XmlNodeType.Element );
                        for ( int i = index; i < index + attrCount + 1; i++ ) {
                            if ( nodes[i].prefix.Equals( pref ) ) {
                                nodes[i].ns = namespaceManager.LookupNamespace( pref ); 
                            }
                        } 
                    } 
                }
                // xml: attribute 
                else {
                    if ( isXmlAttribute ) {
                        OnXmlReservedAttribute( attr );
                    } 
                }
            } 
 
            fullAttrCleanup = true;
            return attr; 
        }

#if !SILVERLIGHT // Needed only for XmlTextReader (when used from XmlDocument)
        internal bool DisableUndeclaredEntityCheck { 
            set {
                disableUndeclaredEntityCheck = value; 
            } 
        }
#endif 

        int ReadContentAsBinary( byte[] buffer, int index, int count ) {
            Debug.Assert( incReadDecoder != null );
 
            if ( incReadState == IncrementalReadState.ReadContentAsBinary_End ) {
                return 0; 
            } 

            incReadDecoder.SetNextOutputBuffer( buffer, index, count ); 

            for (;;) {
                // read what is already cached in curNode
                int charsRead = 0; 
                try {
                    charsRead = curNode.CopyToBinary( incReadDecoder, readValueOffset ); 
                } 
                // add line info to the exception
                catch ( XmlException e ) { 
                    curNode.AdjustLineInfo( readValueOffset, ps.eolNormalized, ref incReadLineInfo );
                    ReThrow( e, incReadLineInfo.lineNo, incReadLineInfo.linePos );
                }
                readValueOffset += charsRead; 

                if ( incReadDecoder.IsFull ) { 
                    return incReadDecoder.DecodedCount; 
                }
 
                // if on partial value, read the rest of it
                if ( incReadState == IncrementalReadState.ReadContentAsBinary_OnPartialValue ) {
                    curNode.SetValue( string.Empty );
 
                    // read next chunk of text
                    bool endOfValue = false; 
                    int startPos = 0; 
                    int endPos = 0;
                    while ( !incReadDecoder.IsFull && !endOfValue ) { 
                        int orChars = 0;

                        // store current line info and parse more text
                        incReadLineInfo.Set( ps.LineNo, ps.LinePos ); 
                        endOfValue = ParseText( out startPos, out endPos, ref orChars );
 
                        try { 
                            charsRead = incReadDecoder.Decode( ps.chars, startPos, endPos - startPos );
                        } 
                        // add line info to the exception
                        catch ( XmlException e ) {
                            ReThrow( e, incReadLineInfo.lineNo, incReadLineInfo.linePos);
                        } 
                        startPos += charsRead;
                    } 
                    incReadState = endOfValue ? IncrementalReadState.ReadContentAsBinary_OnCachedValue : IncrementalReadState.ReadContentAsBinary_OnPartialValue; 
                    readValueOffset = 0;
 
                    if ( incReadDecoder.IsFull ) {
                        curNode.SetValue( ps.chars, startPos, endPos - startPos );
                        // adjust line info for the chunk that has been already decoded
                        AdjustLineInfo( ps.chars, startPos - charsRead, startPos, ps.eolNormalized, ref incReadLineInfo ); 
                        curNode.SetLineInfo( incReadLineInfo.lineNo, incReadLineInfo.linePos );
                        return incReadDecoder.DecodedCount; 
                    } 
                }
 
                // reset to normal state so we can call Read() to move forward
                ParsingFunction tmp = parsingFunction;
                parsingFunction = nextParsingFunction;
                nextParsingFunction = nextNextParsingFunction; 

                // move to next textual node in the element content; throw on sub elements 
                if ( !MoveToNextContentNode( true ) ) { 
                    SetupReadContentAsBinaryState( tmp );
                    incReadState = IncrementalReadState.ReadContentAsBinary_End; 
                    return incReadDecoder.DecodedCount;
                }
                SetupReadContentAsBinaryState( tmp );
                incReadLineInfo.Set( curNode.LineNo, curNode.LinePos ); 
            }
        } 
 
        int ReadElementContentAsBinary( byte[] buffer, int index, int count ) {
            if ( count == 0 ) { 
                return 0;
            }
            int decoded = ReadContentAsBinary( buffer, index, count );
            if ( decoded > 0 ) { 
                return decoded;
            } 
 
            // if 0 bytes returned check if we are on a closing EndElement, throw exception if not
            if ( curNode.type != XmlNodeType.EndElement ) { 
                throw new XmlException( Res.Xml_InvalidNodeType, curNode.type.ToString(), this as IXmlLineInfo );
            }

            // reset state 
            parsingFunction = nextParsingFunction;
            nextParsingFunction = nextNextParsingFunction; 
            Debug.Assert( parsingFunction != ParsingFunction.InReadElementContentAsBinary ); 

            // move off the EndElement 
            outerReader.Read();
            return 0;
        }
 
        void InitBase64Decoder() {
            if ( base64Decoder == null ) { 
                base64Decoder = new Base64Decoder(); 
            }
            else { 
                base64Decoder.Reset();
            }
            incReadDecoder = base64Decoder;
        } 

        void InitBinHexDecoder() { 
            if ( binHexDecoder == null ) { 
                binHexDecoder = new BinHexDecoder();
            } 
            else {
                binHexDecoder.Reset();
            }
            incReadDecoder = binHexDecoder; 
        }
 
        // SxS: URIs are resolved only to be compared. No resource exposure. It's OK to suppress the SxS warning. 
#if !SILVERLIGHT
        [ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)] 
        [ResourceExposure(ResourceScope.None)]
#endif
        bool UriEqual( Uri uri1, string uri1Str, string uri2Str, XmlResolver resolver ) {
            if (resolver == null) { 
                return uri1Str == uri2Str;
            } 
            if (uri1 == null){ 
                uri1 = resolver.ResolveUri( null, uri1Str );
            } 
            Uri uri2 = resolver.ResolveUri( null, uri2Str );
            return uri1.Equals(uri2);
        }
 
        /// 
        /// This method should be called every time the reader is about to consume some number of 
        ///   characters from the input. It will count it agains the security counters and 
        ///   may throw if some of the security limits are exceeded.
        ///  
        /// Number of characters to be consumed.
        /// true if the characters are result of entity expansion.
        void RegisterConsumedCharacters(long characters, bool inEntityReference) {
            Debug.Assert(characters >= 0); 
            if (maxCharactersInDocument > 0) {
                long newCharactersInDocument = charactersInDocument + characters; 
                if (newCharactersInDocument < charactersInDocument) { 
                    // Integer overflow while counting
                    ThrowWithoutLineInfo(Res.Xml_LimitExceeded, "MaxCharactersInDocument"); 
                }
                else {
                    charactersInDocument = newCharactersInDocument;
                } 
                if (charactersInDocument > maxCharactersInDocument) {
                    // The limit was exceeded for the total number of characters in the document 
                    ThrowWithoutLineInfo(Res.Xml_LimitExceeded, "MaxCharactersInDocument"); 
                }
            } 

            if (maxCharactersFromEntities > 0 && inEntityReference) {
                long newCharactersFromEntities = charactersFromEntities + characters;
                if (newCharactersFromEntities < charactersFromEntities) { 
                    // Integer overflow while counting
                    ThrowWithoutLineInfo(Res.Xml_LimitExceeded, "MaxCharactersFromEntities"); 
                } 
                else {
                    charactersFromEntities = newCharactersFromEntities; 
                }
                if ( charactersFromEntities > maxCharactersFromEntities) {
                    // The limit was exceeded for the number of characters from entities
                    ThrowWithoutLineInfo(Res.Xml_LimitExceeded, "MaxCharactersFromEntities"); 
                }
            } 
        } 

#if SILVERLIGHT && !SILVERLIGHT_DISABLE_SECURITY 
        [System.Security.SecuritySafeCritical]
#endif
        static internal unsafe void AdjustLineInfo(char[] chars, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) {
            Debug.Assert(startPos >= 0); 
            Debug.Assert(endPos < chars.Length);
            Debug.Assert(startPos <= endPos); 
 
            fixed (char* pChars = &chars[startPos]) {
                AdjustLineInfo(pChars, endPos - startPos, isNormalized, ref lineInfo); 
            }
        }

#if SILVERLIGHT && !SILVERLIGHT_DISABLE_SECURITY 
        [System.Security.SecuritySafeCritical]
#endif 
        static internal unsafe void AdjustLineInfo(string str, int startPos, int endPos, bool isNormalized, ref LineInfo lineInfo) { 
            Debug.Assert(startPos >= 0);
            Debug.Assert(endPos < str.Length); 
            Debug.Assert(startPos <= endPos);

            fixed (char* pChars = str) {
                AdjustLineInfo(pChars + startPos, endPos - startPos, isNormalized, ref lineInfo); 
            }
        } 
 
#if SILVERLIGHT
        [System.Security.SecurityCritical] 
#endif
        static internal unsafe void AdjustLineInfo(char* pChars, int length, bool isNormalized, ref LineInfo lineInfo) {
            int lastNewLinePos = -1;
            for (int i = 0; i < length; i++) { 
                switch (pChars[i]) {
                    case '\n': 
                        lineInfo.lineNo++; 
                        lastNewLinePos = i;
                        break; 
                    case '\r':
                        if (isNormalized) {
                            break;
                        } 
                        lineInfo.lineNo++;
                        lastNewLinePos = i; 
                        if (i + 1 < length && pChars[i + 1] == '\n') { 
                            i++;
                            lastNewLinePos++; 
                        }
                        break;
                }
            } 
            if (lastNewLinePos >= 0) {
                lineInfo.linePos = length - lastNewLinePos; 
            } 
        }
 
        // StripSpaces removes spaces at the beginning and at the end of the value and replaces sequences of spaces with a single space
        internal static string StripSpaces( string value ) {
            int len = value.Length;
            if ( len <= 0 ) { 
               return string.Empty;
            } 
 
            int startPos = 0;
            StringBuilder norValue = null; 

            while ( value[startPos] == 0x20 ) {
                startPos++;
                if ( startPos == len ) { 
                    return " ";
                } 
            } 

            int i; 
            for ( i = startPos; i < len; i++ ) {
                if ( value[i] == 0x20 ) {
                    int j = i + 1;
                    while ( j < len && value[j] == 0x20 ) { 
                        j++;
                    } 
                    if ( j == len ) { 
                        if ( norValue == null ) {
                            return value.Substring( startPos, i - startPos ); 
                        }
                        else {
                            norValue.Append( value, startPos, i - startPos );
                            return norValue.ToString(); 
                        }
                   } 
                   if ( j > i + 1 ) { 
                        if ( norValue == null ) {
                            norValue = new StringBuilder( len ); 
                        }
                        norValue.Append( value, startPos, i - startPos + 1 );
                        startPos = j;
                        i = j - 1; 
                    }
                } 
            } 
            if ( norValue == null ) {
                return ( startPos == 0 ) ? value : value.Substring( startPos, len - startPos ); 
            }
            else {
                if ( i > startPos ) {
                   norValue.Append( value, startPos, i - startPos ); 
               }
                return norValue.ToString(); 
            } 
        }
 
        // StripSpaces removes spaces at the beginning and at the end of the value and replaces sequences of spaces with a single space
        internal static void StripSpaces( char[] value, int index, ref int len ) {
            if ( len <= 0 ) {
               return; 
            }
 
            int startPos = index; 
            int endPos = index + len;
 
            while ( value[startPos] == 0x20 ) {
                startPos++;
                if ( startPos == endPos ) {
                    len = 1; 
                    return;
                } 
            } 

            int offset = startPos - index; 
            int i;
            for ( i = startPos; i < endPos; i++ ) {
                char ch;
                if ( ( ch = value[i] ) == 0x20 ) { 
                    int j = i + 1;
                    while ( j < endPos && value[j] == 0x20 ) { 
                        j++; 
                    }
                    if ( j == endPos ) { 
                        offset += ( j - i );
                        break;
                    }
                    if ( j > i+1 ) { 
                        offset += ( j - i - 1 );
                        i = j - 1; 
                    } 
                }
                value[i-offset] = ch; 
            }
            len -= offset;
        }
 
        internal static void BlockCopyChars(char[] src, int srcOffset, char[] dst, int dstOffset, int count) {
            // PERF: Buffer.BlockCopy is faster than Array.Copy 
#if SILVERLIGHT 
            Array.Copy( src, srcOffset, dst, dstOffset, count );
#else 
            Buffer.BlockCopy( src, srcOffset * sizeof(char), dst, dstOffset * sizeof(char), count * sizeof(char) );
#endif
        }
 
        internal static void BlockCopy( byte[] src, int srcOffset, byte[] dst, int dstOffset, int count ) {
#if SILVERLIGHT 
            Array.Copy( src, srcOffset, dst, dstOffset, count ); 
#else
            Buffer.BlockCopy(src, srcOffset, dst, dstOffset, count); 
#endif
        }

    } 
}
 

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
// Copyright (c) Microsoft Corporation. All rights reserved.
                        

                        

Link Menu

Network programming in C#, Network Programming in VB.NET, Network Programming in .NET
This book is available now!
Buy at Amazon US or
Buy at Amazon UK