XmlSubtreeReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ Dotnetfx_Vista_SP2 / Dotnetfx_Vista_SP2 / 8.0.50727.4016 / DEVDIV / depot / DevDiv / releases / whidbey / NetFxQFE / ndp / fx / src / Xml / System / Xml / Core / XmlSubtreeReader.cs / 1 / XmlSubtreeReader.cs

                            //------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System; 
using System.Xml;
using System.Xml.Schema; 
using System.Diagnostics;
using System.Collections;
using System.Globalization;
using System.Collections.Generic; 

namespace System.Xml { 
 
    internal sealed class XmlSubtreeReader : XmlWrappingReader, IXmlNamespaceResolver {
// 
// Private types
//
        class NodeData {
            internal XmlNodeType type; 
            internal string localName;
            internal string prefix; 
            internal string name; 
            internal string namespaceUri;
            internal string value; 

            internal NodeData() {
            }
 
            internal void Set( XmlNodeType nodeType, string localName, string prefix, string name, string namespaceUri, string value ) {
                this.type      = nodeType; 
                this.localName = localName; 
                this.prefix    = prefix;
                this.name      = name; 
                this.namespaceUri = namespaceUri;
                this.value     = value;
            }
        } 

        enum State { 
            Initial      = ReadState.Initial, 
            Interactive  = ReadState.Interactive,
            Error        = ReadState.Error, 
            EndOfFile    = ReadState.EndOfFile,
            Closed       = ReadState.Closed,
            PopNamespaceScope,
            ClearNsAttributes, 
            ReadElementContentAsBase64,
            ReadElementContentAsBinHex, 
            ReadContentAsBase64, 
            ReadContentAsBinHex,
        } 

        const int AttributeActiveStates = 0x62; // 00001100010 bin
        const int NamespaceActiveStates = 0x7E2; // 11111100010 bin
 
//
// Fields 
// 
        int              initialDepth;
        State            state; 

        // namespace management
        XmlNamespaceManager  nsManager;
        NodeData[]           nsAttributes; 
        int                  nsAttrCount;
        int                  curNsAttr = -1; 
        string               xmlns; 
        string               xmlnsUri;
 
        // cached nodes
        bool                 useCurNode;
        NodeData             curNode;
        // node used for a text node of ReadAttributeValue or as Initial or EOF node 
        NodeData             tmpNode;
 
// 
// Constants
// 
        internal int InitialNamespaceAttributeCount = 4;

//
// Constructor 
//
        internal XmlSubtreeReader( XmlReader reader ) : base( reader ) { 
            initialDepth = reader.Depth; 
            state  = State.Initial;
            nsManager = new XmlNamespaceManager( reader.NameTable ); 
            xmlns = reader.NameTable.Add( "xmlns" );
            xmlnsUri = reader.NameTable.Add(XmlReservedNs.NsXmlNs);

            tmpNode = new NodeData(); 
            tmpNode.Set( XmlNodeType.None, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty );
 
            SetCurrentNode( tmpNode ); 
        }
 
//
// XmlReader implementation
//
        public override XmlReaderSettings Settings { 
            get {
                return reader.Settings; 
            } 
        }
 
        public override XmlNodeType NodeType {
            get {
                return ( useCurNode ) ? curNode.type : reader.NodeType;
            } 
        }
 
        public override string Name { 
            get {
                return ( useCurNode ) ? curNode.name : reader.Name; 
            }
        }

        public override string LocalName { 
            get {
                return ( useCurNode ) ? curNode.localName : reader.LocalName; 
            } 
        }
 
        public override string NamespaceURI {
            get {
                return ( useCurNode ) ? curNode.namespaceUri : reader.NamespaceURI;
            } 
        }
 
        public override string Prefix { 
            get {
                return ( useCurNode ) ? curNode.prefix : reader.Prefix; 
            }
        }

        public override string Value { 
            get {
                return ( useCurNode ) ? curNode.value : reader.Value; 
            } 
        }
 
        public override int Depth {
            get {
                int depth = reader.Depth - initialDepth;
                if ( curNsAttr != -1 ) { 
                    if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value
                        depth += 2; 
                    } 
                    else {
                        depth++; 
                    }
                }
                return depth;
            } 
        }
 
        public override string BaseURI { 
            get {
                return reader.BaseURI; 
            }
        }

        public override bool CanResolveEntity { 
            get {
                return reader.CanResolveEntity; 
            } 
        }
 
        public override bool EOF {
            get {
                return state == State.EndOfFile || state == State.Closed;
            } 
        }
 
        public override ReadState ReadState { 
            get {
                if ( reader.ReadState == ReadState.Error ) { 
                    return ReadState.Error;
                }
                else {
                    if ( (int)state <= (int)State.Closed ) { 
 	                    return (ReadState)(int)state;
                    } 
                    else { 
                        return ReadState.Interactive;
                    } 
                }
            }
        }
 
        public override XmlNameTable NameTable {
            get { 
                return reader.NameTable; 
            }
        } 

        public override int AttributeCount {
            get {
                return InAttributeActiveState ? reader.AttributeCount + nsAttrCount : 0; 
            }
        } 
 
        public override string GetAttribute( string name ) {
            if ( !InAttributeActiveState ) { 
                return null;
            }
            string attr = reader.GetAttribute( name );
            if ( attr != null ) { 
                return attr;
            } 
            for ( int i = 0; i < nsAttrCount; i++ ) { 
                if ( name == nsAttributes[i].name ) {
                    return nsAttributes[i].value; 
                }
            }
            return null;
        } 

        public override string GetAttribute( string name, string namespaceURI ) { 
            if ( !InAttributeActiveState ) { 
                return null;
            } 
            string attr = reader.GetAttribute( name, namespaceURI );
            if ( attr != null ) {
                return attr;
            } 
            for ( int i = 0; i < nsAttrCount; i++ ) {
                if ( name == nsAttributes[i].localName && namespaceURI == xmlnsUri ) { 
                    return nsAttributes[i].value; 
                }
            } 
            return null;

        }
 
        public override string GetAttribute( int i ) {
            if ( !InAttributeActiveState ) { 
                throw new ArgumentOutOfRangeException("i"); 
            }
            int n = reader.AttributeCount; 
            if ( i < n ) {
                return reader.GetAttribute( i );
            }
            else if ( i - n < nsAttrCount ) { 
                return nsAttributes[i-n].value;
            } 
            else { 
                throw new ArgumentOutOfRangeException( "i" );
            } 
        }

        public override bool MoveToAttribute( string name ) {
            if ( !InAttributeActiveState ) { 
                return false;
            } 
            if ( reader.MoveToAttribute( name ) ) { 
                curNsAttr = -1;
                useCurNode = false; 
                return true;
            }
            for ( int i = 0; i < nsAttrCount; i++ ) {
                if ( name == nsAttributes[i].name ) { 
                    MoveToNsAttribute( i );
                    return true; 
                } 
            }
            return false; 
        }

        public override bool MoveToAttribute( string name, string ns ) {
            if ( !InAttributeActiveState ) { 
                return false;
            } 
            if ( reader.MoveToAttribute( name, ns ) ) { 
                curNsAttr = -1;
                useCurNode = false; 
                return true;
            }
            for ( int i = 0; i < nsAttrCount; i++ ) {
                if ( name == nsAttributes[i].localName && ns == xmlnsUri ) { 
                    MoveToNsAttribute( i );
                    return true; 
                } 
            }
            return false; 
        }

        public override void MoveToAttribute( int i ) {
            if ( !InAttributeActiveState ) { 
                throw new ArgumentOutOfRangeException("i");
            } 
            int n = reader.AttributeCount; 
            if ( i < n ) {
                reader.MoveToAttribute( i ); 
                curNsAttr = -1;
                useCurNode = false;
            }
            else if ( i - n < nsAttrCount ) { 
                MoveToNsAttribute( i - n );
            } 
            else { 
                throw new ArgumentOutOfRangeException( "i" );
            } 
        }

        public override bool MoveToFirstAttribute() {
            if ( !InAttributeActiveState ) { 
                return false;
            } 
            if ( reader.MoveToFirstAttribute() ) { 
                useCurNode = false;
                return true; 
            }
            if ( nsAttrCount > 0 ) {
                MoveToNsAttribute( 0 );
                return true; 
            }
            return false; 
        } 

        public override bool MoveToNextAttribute() { 
            if ( !InAttributeActiveState ) {
                return false;
            }
            if ( curNsAttr == -1 && reader.MoveToNextAttribute() ) { 
                return true;
            } 
            if ( curNsAttr + 1 < nsAttrCount ) { 
                MoveToNsAttribute( curNsAttr + 1 );
                return true; 
            }
            return false;
        }
 
        public override bool MoveToElement() {
            if ( !InAttributeActiveState ) { 
                return false; 
            }
            curNsAttr = -1; 
            useCurNode = false;
            return reader.MoveToElement();
        }
 
        public override bool ReadAttributeValue() {
            if ( !InAttributeActiveState ) { 
                return false; 
            }
            if ( curNsAttr == -1 ) { 
                return reader.ReadAttributeValue();
            }
            else if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value
                return false; 
            }
            else { 
                Debug.Assert( curNode.type == XmlNodeType.Attribute ); 
                tmpNode.type = XmlNodeType.Text;
                tmpNode.value = curNode.value; 
                SetCurrentNode( tmpNode );
                return true;
            }
        } 

        public override bool Read() { 
 
            switch ( state ) {
                case State.Initial: 
                    useCurNode = false;
                    state = State.Interactive;
                    ProcessNamespaces();
                    return true; 

                case State.Interactive: 
                    curNsAttr = -1; 
                    useCurNode = false;
                    reader.MoveToElement(); 
                    Debug.Assert( reader.Depth >= initialDepth );
                    if ( reader.Depth == initialDepth ) {
                        if ( reader.NodeType == XmlNodeType.EndElement ||
                            ( reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement ) ) { 
                            state = State.EndOfFile;
                            SetEmptyNode(); 
                            return false; 
                        }
                        Debug.Assert( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ); 
                    }
                    if ( reader.Read() ) {
                        ProcessNamespaces();
                        return true; 
                    }
                    else { 
                        SetEmptyNode(); 
                        return false;
                    } 

                case State.EndOfFile:
                case State.Closed:
                    return false; 

                case State.PopNamespaceScope: 
                    nsManager.PopScope(); 
                    goto case State.ClearNsAttributes;
 
                case State.ClearNsAttributes:
                    nsAttrCount = 0;
                    state = State.Interactive;
                    goto case State.Interactive; 

                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex: 
                    if ( !FinishReadElementContentAsBinary() ) {
                        return false; 
                    }
                    return Read();

                case State.ReadContentAsBase64: 
                case State.ReadContentAsBinHex:
                    if ( !FinishReadContentAsBinary() ) { 
                        return false; 
                    }
                    return Read(); 

                default:
                    Debug.Assert( false );
                    return false; 
            }
        } 
 
        public override void Close() {
            if ( state == State.Closed ) { 
                return;
            }
            try {
                // move the underlying reader to the next sibling 
                if ( state != State.EndOfFile ) {
                    reader.MoveToElement(); 
                    Debug.Assert( reader.Depth >= initialDepth ); 
                    // move off the root of the subtree
                    if ( reader.Depth == initialDepth && reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { 
                        reader.Read();
                    }
                    // move to the end of the subtree, do nothing if on empty root element
                    while ( reader.Depth > initialDepth && reader.Read() ) { 
                        /* intentionally empty */
                    } 
                } 
            }
            catch { // never fail... 
            }
            finally {
                curNsAttr = -1;
                useCurNode = false; 
                state = State.Closed;
                SetEmptyNode(); 
            } 
        }
 
        public override void Skip() {

            switch ( state ) {
                case State.Initial: 
                    Read();
                    return; 
 
                case State.Interactive:
                    curNsAttr = -1; 
                    useCurNode = false;
                    reader.MoveToElement();
                    Debug.Assert( reader.Depth >= initialDepth );
                    if ( reader.Depth == initialDepth ) { 
                        if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) {
                            // we are on root of the subtree -> skip to the end element and set to Eof state 
                            if ( reader.Read() ) { 
                                while ( reader.NodeType != XmlNodeType.EndElement && reader.Depth > initialDepth ) {
                                    reader.Skip(); 
                                }
                            }
                        }
                        Debug.Assert( reader.NodeType == XmlNodeType.EndElement || 
                                      reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement ||
                                      reader.ReadState != ReadState.Interactive ); 
                        state = State.EndOfFile; 
                        SetEmptyNode();
                        return; 
                    }

                    if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) {
                        nsManager.PopScope(); 
                    }
                    reader.Skip(); 
                    ProcessNamespaces(); 

                    Debug.Assert( reader.Depth >= initialDepth ); 
                    return;

                case State.Closed:
                case State.EndOfFile: 
                    return;
 
                case State.PopNamespaceScope: 
                    nsManager.PopScope();
                    goto case State.ClearNsAttributes; 

                case State.ClearNsAttributes:
                    nsAttrCount = 0;
                    state = State.Interactive; 
                    goto case State.Interactive;
 
                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex:
                    if ( FinishReadElementContentAsBinary() ) { 
                        Skip();
                    }
                    break;
 
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex: 
                    if ( FinishReadContentAsBinary() ) { 
                        Skip();
                    } 
                    break;

                default:
                    Debug.Assert( false ); 
                    return;
            } 
        } 

        public override object ReadContentAsObject() { 
            try {
                InitReadContentAsType( "ReadContentAsObject" );
                object value = reader.ReadContentAsObject();
                FinishReadContentAsType(); 
                return value;
            } 
            catch { 
                state = State.Error;
                throw; 
            }
        }

        public override bool ReadContentAsBoolean() { 
            try {
                InitReadContentAsType( "ReadContentAsBoolean" ); 
                bool value = reader.ReadContentAsBoolean(); 
                FinishReadContentAsType();
                return value; 
            }
            catch {
                state = State.Error;
                throw; 
            }
        } 
 
        public override DateTime ReadContentAsDateTime() {
            try { 
                InitReadContentAsType( "ReadContentAsDateTime" );
                DateTime value = reader.ReadContentAsDateTime();
                FinishReadContentAsType();
                return value; 
            }
            catch { 
                state = State.Error; 
                throw;
            } 
        }

        public override double ReadContentAsDouble() {
            try { 
                InitReadContentAsType( "ReadContentAsDouble" );
                double value = reader.ReadContentAsDouble(); 
                FinishReadContentAsType(); 
                return value;
            } 
            catch {
                state = State.Error;
                throw;
            } 
        }
 
        public override float ReadContentAsFloat() { 
            try {
                InitReadContentAsType( "ReadContentAsFloat" ); 
                float value = reader.ReadContentAsFloat();
                FinishReadContentAsType();
                return value;
            } 
            catch {
                state = State.Error; 
                throw; 
            }
        } 

        public override decimal ReadContentAsDecimal() {
            try {
                InitReadContentAsType( "ReadContentAsDecimal" ); 
                decimal value = reader.ReadContentAsDecimal();
                FinishReadContentAsType(); 
                return value; 
            }
            catch { 
                state = State.Error;
                throw;
            }
        } 

        public override int ReadContentAsInt() { 
            try { 
                InitReadContentAsType( "ReadContentAsInt" );
                int value = reader.ReadContentAsInt(); 
                FinishReadContentAsType();
                return value;
            }
            catch { 
                state = State.Error;
                throw; 
            } 
        }
 
        public override long ReadContentAsLong() {
            try {
                InitReadContentAsType( "ReadContentAsLong" );
                long value = reader.ReadContentAsLong(); 
                FinishReadContentAsType();
                return value; 
            } 
            catch {
                state = State.Error; 
                throw;
            }
        }
 
        public override string ReadContentAsString() {
            try { 
                InitReadContentAsType( "ReadContentAsString" ); 
                string value = reader.ReadContentAsString();
                FinishReadContentAsType(); 
                return value;
            }
            catch {
                state = State.Error; 
                throw;
            } 
        } 

        public override object ReadContentAs( Type returnType, IXmlNamespaceResolver namespaceResolver ) { 
            try {
                InitReadContentAsType( "ReadContentAs" );
                object value = reader.ReadContentAs( returnType, namespaceResolver );
                FinishReadContentAsType(); 
                return value;
            } 
            catch { 
                state = State.Error;
                throw; 
            }
        }

        public override bool CanReadBinaryContent { 
            get {
                return reader.CanReadBinaryContent; 
            } 
        }
 
        public override int ReadContentAsBase64( byte[] buffer, int index, int count ) {
            switch ( state ) {
                case State.Initial:
                case State.EndOfFile: 
                case State.Closed:
                    return 0; 
 
                case State.ClearNsAttributes:
                case State.PopNamespaceScope: 
                    switch ( NodeType ) {
                        case XmlNodeType.Element:
                            throw CreateReadContentAsException( "ReadContentAsBase64" );
                        case XmlNodeType.EndElement: 
                            return 0;
                        case XmlNodeType.Attribute: 
                        case XmlNodeType.Text: 
                            Debug.Assert( AttributeCount > 0 );
                            return reader.ReadContentAsBase64( buffer, index, count ); 
                        default:
                            Debug.Assert( false );
                            return 0;
                    } 

                case State.Interactive: 
                    state = State.ReadContentAsBase64; 
                    goto case State.ReadContentAsBase64;
 
                case State.ReadContentAsBase64:
                    int read = reader.ReadContentAsBase64( buffer, index, count );
                    if ( read == 0 ) {
                        state = State.Interactive; 
                        ProcessNamespaces();
                    } 
                    return read; 

                case State.ReadContentAsBinHex: 
                case State.ReadElementContentAsBase64:
                case State.ReadElementContentAsBinHex:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
 
                default:
                    Debug.Assert( false ); 
                    return 0; 
            }
        } 

        public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) {
            switch ( state ) {
                case State.Initial: 
                case State.EndOfFile:
                case State.Closed: 
                    return 0; 

                case State.Interactive: 
                case State.PopNamespaceScope:
                case State.ClearNsAttributes:
                    if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBase64 ) ) {
                        return 0; 
                    }
                    goto case State.ReadElementContentAsBase64; 
 
                case State.ReadElementContentAsBase64:
                    int read = reader.ReadContentAsBase64( buffer, index, count ); 
                    if ( read > 0 ) {
                        return read;
                    }
                    if ( NodeType != XmlNodeType.EndElement ) { 
                        throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo );
                    } 
 
                    // pop namespace scope
                    state = State.Interactive; 
                    ProcessNamespaces();

                    // set eof state or move off the end element
                    if ( reader.Depth == initialDepth ) { 
                        state = State.EndOfFile;
                        SetEmptyNode(); 
                    } 
                    else {
                        Read(); 
                    }
                    return 0;

                case State.ReadContentAsBase64: 
                case State.ReadContentAsBinHex:
                case State.ReadElementContentAsBinHex: 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); 

                default: 
                    Debug.Assert( false );
                    return 0;
            }
        } 

        public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) { 
            switch ( state ) { 
                case State.Initial:
                case State.EndOfFile: 
                case State.Closed:
                    return 0;

                case State.ClearNsAttributes: 
                case State.PopNamespaceScope:
                    switch ( NodeType ) { 
                        case XmlNodeType.Element: 
                            throw CreateReadContentAsException( "ReadContentAsBinHex" );
                        case XmlNodeType.EndElement: 
                            return 0;
                        case XmlNodeType.Attribute:
                        case XmlNodeType.Text:
                            Debug.Assert( AttributeCount > 0 ); 
                            return reader.ReadContentAsBinHex( buffer, index, count );
                        default: 
                            Debug.Assert( false ); 
                            return 0;
                    } 

                case State.Interactive:
                    state = State.ReadContentAsBinHex;
                    goto case State.ReadContentAsBinHex; 

                case State.ReadContentAsBinHex: 
                    int read = reader.ReadContentAsBinHex( buffer, index, count ); 
                    if ( read == 0 ) {
                        state = State.Interactive; 
                        ProcessNamespaces();
                    }
                    return read;
 
                case State.ReadContentAsBase64:
                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex: 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
 
                default:
                    Debug.Assert( false );
                    return 0;
            } 
        }
 
        public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) { 
            switch ( state ) {
                case State.Initial: 
                case State.EndOfFile:
                case State.Closed:
                    return 0;
 
                case State.Interactive:
                case State.PopNamespaceScope: 
                case State.ClearNsAttributes: 
                    if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBinHex ) ) {
                        return 0; 
                    }
                    goto case State.ReadElementContentAsBinHex;
                case State.ReadElementContentAsBinHex:
                    int read = reader.ReadContentAsBinHex( buffer, index, count ); 
                    if ( read > 0 ) {
                        return read; 
                    } 
                    if ( NodeType != XmlNodeType.EndElement ) {
                        throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); 
                    }

                    // pop namespace scope
                    state = State.Interactive; 
                    ProcessNamespaces();
 
                    // set eof state or move off the end element 
                    if ( reader.Depth == initialDepth ) {
                        state = State.EndOfFile; 
                        SetEmptyNode();
                    }
                    else {
                        Read(); 
                    }
                    return 0; 
 
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex: 
                case State.ReadElementContentAsBase64:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );

                default: 
                    Debug.Assert( false );
                    return 0; 
            } 
        }
 
        public override bool CanReadValueChunk {
            get {
                return reader.CanReadValueChunk;
            } 
        }
 
        public override int ReadValueChunk( char[] buffer, int index, int count ) { 
            switch ( state ) {
                case State.Initial: 
                case State.EndOfFile:
                case State.Closed:
                case State.Error:
                    return 0; 

                case State.ClearNsAttributes: 
                case State.PopNamespaceScope: 
                    // no need to clean ns attributes or pop scope because the reader when ReadValueChunk is called
                    // - on Element errors 
                    // - on EndElement errors
                    // - on Attribute does not move
                    // and that's all where State.ClearNsAttributes or State.PopnamespaceScope can be set
                    goto case State.Interactive; 

                case State.Interactive: 
                    return reader.ReadValueChunk( buffer, index, count ); 

                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex:
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) ); 

                default: 
                    Debug.Assert( false ); 
                    return 0;
            } 
        }

//
// IDisposable interface 
//
        protected override void Dispose( bool disposing ) { 
            // note: we do not want to dispose the underlying reader 
            this.Close();
        } 

//
// IXmlLineInfo members
// 
        public override int LineNumber {
            get { 
                return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LineNumber; 
            }
        } 

        public override int LinePosition {
            get {
                return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LinePosition; 
            }
        } 
 
        public override string LookupNamespace( string prefix ) {
            return ((IXmlNamespaceResolver)this).LookupNamespace( prefix ); 
        }

//
// IXmlNamespaceResolver implementation 
//
        IDictionary IXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) { 
            if ( !InNamespaceActiveState ) { 
                return new Dictionary();
            } 
            return nsManager.GetNamespacesInScope( scope );
        }

        string IXmlNamespaceResolver.LookupNamespace( string prefix ) { 
            if ( !InNamespaceActiveState ) {
                return null; 
            } 
            return nsManager.LookupNamespace( prefix );
        } 

        string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) {
            if ( !InNamespaceActiveState ) {
                return null; 
            }
            return nsManager.LookupPrefix( namespaceName ); 
        } 

// 
// Internal methods
//

        internal override SchemaInfo DtdSchemaInfo { 
            get {
                return null; 
            } 
        }
 
//
// Private methods
//
        private void ProcessNamespaces() { 
            switch ( reader.NodeType ) {
                case XmlNodeType.Element: 
                    nsManager.PushScope(); 

                    string prefix = reader.Prefix; 
                    string ns = reader.NamespaceURI;
                    if ( nsManager.LookupNamespace( prefix ) != ns ) {
                        AddNamespace( prefix, ns );
                    } 

                    if ( reader.MoveToFirstAttribute() ) { 
                        do { 
                            prefix = reader.Prefix;
                            ns = reader.NamespaceURI; 

                            if ( Ref.Equal( ns, xmlnsUri ) ) {
                                if ( prefix.Length == 0 ) {
                                    nsManager.AddNamespace( string.Empty, reader.Value ); 
                                    RemoveNamespace( string.Empty, xmlns );
                                } 
                                else { 
                                    prefix = reader.LocalName;
                                    nsManager.AddNamespace( prefix, reader.Value ); 
                                    RemoveNamespace( xmlns, prefix );
                                }
                            }
                            else if ( prefix.Length != 0 && nsManager.LookupNamespace( prefix ) != ns ) { 
                                AddNamespace( prefix, ns );
                            } 
                        } while ( reader.MoveToNextAttribute() ); 
                        reader.MoveToElement();
                    } 

                    if ( reader.IsEmptyElement ) {
                        state = State.PopNamespaceScope;
                    } 
                    break;
                case XmlNodeType.EndElement: 
                    state = State.PopNamespaceScope; 
                    break;
            } 
        }

        private void AddNamespace( string prefix, string ns ) {
            nsManager.AddNamespace( prefix, ns ); 

            int index = nsAttrCount++; 
            if ( nsAttributes == null ) { 
                nsAttributes = new NodeData[InitialNamespaceAttributeCount];
            } 
            if ( index == nsAttributes.Length ) {
                NodeData[] newNsAttrs = new NodeData[nsAttributes.Length * 2];
                Array.Copy( nsAttributes, 0, newNsAttrs, 0, index );
                nsAttributes = newNsAttrs; 
            }
 
            if ( nsAttributes[index] == null ) { 
                nsAttributes[index] = new NodeData();
            } 
            if ( prefix.Length == 0 ) {
                nsAttributes[index].Set( XmlNodeType.Attribute, xmlns, string.Empty, xmlns, XmlReservedNs.NsXmlNs, ns );
            }
            else { 
                nsAttributes[index].Set( XmlNodeType.Attribute, prefix, xmlns, string.Concat( xmlns, ":", prefix ), XmlReservedNs.NsXmlNs, ns );
            } 
 
            Debug.Assert( state == State.ClearNsAttributes || state == State.Interactive || state == State.PopNamespaceScope );
            state = State.ClearNsAttributes; 

            curNsAttr = -1;
        }
 
        private void RemoveNamespace( string prefix, string localName ) {
            for ( int i = 0; i < nsAttrCount; i++ ) { 
                if ( Ref.Equal( prefix, nsAttributes[i].prefix ) && 
                     Ref.Equal( localName, nsAttributes[i].localName ) ) {
                         if ( i < nsAttrCount - 1 ) { 
                             // swap
                             NodeData tmpNodeData = nsAttributes[i];
                             nsAttributes[i] = nsAttributes[nsAttrCount - 1];
                             nsAttributes[nsAttrCount - 1] = tmpNodeData; 
                         }
                         nsAttrCount--; 
                         break; 
                 }
            } 
        }

        private void MoveToNsAttribute( int index ) {
            Debug.Assert( index >= 0 && index <= nsAttrCount ); 
            reader.MoveToElement();
            curNsAttr = index; 
            SetCurrentNode( nsAttributes[index] ); 
        }
 
        private bool InitReadElementContentAsBinary( State binaryState ) {
            if ( NodeType != XmlNodeType.Element ) {
                throw reader.CreateReadElementContentAsException( "ReadElementContentAsBase64" );
            } 

            bool isEmpty = IsEmptyElement; 
 
            // move to content or off the empty element
            if ( !Read() || isEmpty ) { 
                return false;
            }
            // special-case child element and end element
            switch ( NodeType ) { 
                case XmlNodeType.Element:
                    throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); 
                case XmlNodeType.EndElement: 
                    // pop scope & move off end element
                    ProcessNamespaces(); 
                    Read();
                    return false;
            }
 
            Debug.Assert( state == State.Interactive );
            state = binaryState; 
            return true; 
        }
 
        private bool FinishReadElementContentAsBinary() {
            Debug.Assert( state == State.ReadElementContentAsBase64 || state == State.ReadElementContentAsBinHex );

            byte[] bytes = new byte[256]; 
            if ( state == State.ReadElementContentAsBase64 ) {
                while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ; 
            } 
            else {
                while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ; 
            }

            if ( NodeType != XmlNodeType.EndElement ) {
                throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); 
            }
 
            // pop namespace scope 
            state = State.Interactive;
            ProcessNamespaces(); 

            // check eof
            if ( reader.Depth == initialDepth ) {
                 state = State.EndOfFile; 
                 SetEmptyNode();
                 return false; 
            } 
            // move off end element
            return Read(); 
        }

        private bool FinishReadContentAsBinary() {
            Debug.Assert( state == State.ReadContentAsBase64 || state == State.ReadContentAsBinHex ); 

            byte[] bytes = new byte[256]; 
            if ( state == State.ReadContentAsBase64 ) { 
                while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ;
            } 
            else {
                while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ;
            }
 
            state = State.Interactive;
            ProcessNamespaces(); 
 
            // check eof
            if ( reader.Depth == initialDepth ) { 
                 state = State.EndOfFile;
                 SetEmptyNode();
                 return false;
            } 
            return true;
        } 
 
        private bool InAttributeActiveState {
            get { 
#if DEBUG
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Initial ) ) );
                Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.Interactive ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Error ) ) ); 
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.EndOfFile ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Closed ) ) ); 
                Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) ); 
                Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) ); 
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) );
#endif 
                return 0 != ( AttributeActiveStates & ( 1 << (int)state ) );
            } 
        } 

        private bool InNamespaceActiveState { 
            get {
#if DEBUG
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Initial ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.Interactive ) ) ); 
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Error ) ) );
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.EndOfFile ) ) ); 
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Closed ) ) ); 
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) ); 
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) ); 
#endif
                return 0 != ( NamespaceActiveStates & ( 1 << (int)state ) ); 
            } 
        }
 
        void SetEmptyNode() {
            Debug.Assert( tmpNode.localName == string.Empty && tmpNode.prefix == string.Empty && tmpNode.name == string.Empty && tmpNode.namespaceUri == string.Empty );
            tmpNode.type = XmlNodeType.None;
            tmpNode.value = string.Empty; 

            curNode = tmpNode; 
            useCurNode = true; 
        }
 
        void SetCurrentNode( NodeData node ) {
            curNode = node;
            useCurNode = true;
        } 

        void InitReadContentAsType( string methodName ) { 
            switch ( state ) { 
                case State.Initial:
                case State.EndOfFile: 
                case State.Closed:
                case State.Error:
                    break;
 
                case State.Interactive:
                    return; 
 
                case State.PopNamespaceScope:
                case State.ClearNsAttributes: 
                    // no need to clean ns attributes or pop scope because the reader when ReadContentAs is called
                    // - on Element errors
                    // - on Attribute does not move
                    // - on EndElement does not move 
                    // and that's all where State.ClearNsAttributes or State.PopNamespacScope can be set
                    return; 
 
                case State.ReadElementContentAsBase64:
                case State.ReadElementContentAsBinHex: 
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) );
 
                default:
                    Debug.Assert( false ); 
                    break; 
            }
            throw CreateReadContentAsException( methodName ); 
        }

        void FinishReadContentAsType() {
            Debug.Assert( state == State.Interactive || 
                          state == State.PopNamespaceScope ||
                          state == State.ClearNsAttributes ); 
 
            switch ( NodeType ) {
                case XmlNodeType.Element: 
                    // new element we moved to - process namespaces
                    ProcessNamespaces();
                    break;
                case XmlNodeType.EndElement: 
                    // end element we've stayed on or have been moved to
                    state = State.PopNamespaceScope; 
                    break; 
                case XmlNodeType.Attribute:
                    // stayed on attribute, do nothing 
                    break;
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.
//------------------------------------------------------------------------------ 
// 
//     Copyright (c) Microsoft Corporation.  All rights reserved.
// 
// [....] 
//-----------------------------------------------------------------------------
 
using System; 
using System.Xml;
using System.Xml.Schema; 
using System.Diagnostics;
using System.Collections;
using System.Globalization;
using System.Collections.Generic; 

namespace System.Xml { 
 
    internal sealed class XmlSubtreeReader : XmlWrappingReader, IXmlNamespaceResolver {
// 
// Private types
//
        class NodeData {
            internal XmlNodeType type; 
            internal string localName;
            internal string prefix; 
            internal string name; 
            internal string namespaceUri;
            internal string value; 

            internal NodeData() {
            }
 
            internal void Set( XmlNodeType nodeType, string localName, string prefix, string name, string namespaceUri, string value ) {
                this.type      = nodeType; 
                this.localName = localName; 
                this.prefix    = prefix;
                this.name      = name; 
                this.namespaceUri = namespaceUri;
                this.value     = value;
            }
        } 

        enum State { 
            Initial      = ReadState.Initial, 
            Interactive  = ReadState.Interactive,
            Error        = ReadState.Error, 
            EndOfFile    = ReadState.EndOfFile,
            Closed       = ReadState.Closed,
            PopNamespaceScope,
            ClearNsAttributes, 
            ReadElementContentAsBase64,
            ReadElementContentAsBinHex, 
            ReadContentAsBase64, 
            ReadContentAsBinHex,
        } 

        const int AttributeActiveStates = 0x62; // 00001100010 bin
        const int NamespaceActiveStates = 0x7E2; // 11111100010 bin
 
//
// Fields 
// 
        int              initialDepth;
        State            state; 

        // namespace management
        XmlNamespaceManager  nsManager;
        NodeData[]           nsAttributes; 
        int                  nsAttrCount;
        int                  curNsAttr = -1; 
        string               xmlns; 
        string               xmlnsUri;
 
        // cached nodes
        bool                 useCurNode;
        NodeData             curNode;
        // node used for a text node of ReadAttributeValue or as Initial or EOF node 
        NodeData             tmpNode;
 
// 
// Constants
// 
        internal int InitialNamespaceAttributeCount = 4;

//
// Constructor 
//
        internal XmlSubtreeReader( XmlReader reader ) : base( reader ) { 
            initialDepth = reader.Depth; 
            state  = State.Initial;
            nsManager = new XmlNamespaceManager( reader.NameTable ); 
            xmlns = reader.NameTable.Add( "xmlns" );
            xmlnsUri = reader.NameTable.Add(XmlReservedNs.NsXmlNs);

            tmpNode = new NodeData(); 
            tmpNode.Set( XmlNodeType.None, string.Empty, string.Empty, string.Empty, string.Empty, string.Empty );
 
            SetCurrentNode( tmpNode ); 
        }
 
//
// XmlReader implementation
//
        public override XmlReaderSettings Settings { 
            get {
                return reader.Settings; 
            } 
        }
 
        public override XmlNodeType NodeType {
            get {
                return ( useCurNode ) ? curNode.type : reader.NodeType;
            } 
        }
 
        public override string Name { 
            get {
                return ( useCurNode ) ? curNode.name : reader.Name; 
            }
        }

        public override string LocalName { 
            get {
                return ( useCurNode ) ? curNode.localName : reader.LocalName; 
            } 
        }
 
        public override string NamespaceURI {
            get {
                return ( useCurNode ) ? curNode.namespaceUri : reader.NamespaceURI;
            } 
        }
 
        public override string Prefix { 
            get {
                return ( useCurNode ) ? curNode.prefix : reader.Prefix; 
            }
        }

        public override string Value { 
            get {
                return ( useCurNode ) ? curNode.value : reader.Value; 
            } 
        }
 
        public override int Depth {
            get {
                int depth = reader.Depth - initialDepth;
                if ( curNsAttr != -1 ) { 
                    if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value
                        depth += 2; 
                    } 
                    else {
                        depth++; 
                    }
                }
                return depth;
            } 
        }
 
        public override string BaseURI { 
            get {
                return reader.BaseURI; 
            }
        }

        public override bool CanResolveEntity { 
            get {
                return reader.CanResolveEntity; 
            } 
        }
 
        public override bool EOF {
            get {
                return state == State.EndOfFile || state == State.Closed;
            } 
        }
 
        public override ReadState ReadState { 
            get {
                if ( reader.ReadState == ReadState.Error ) { 
                    return ReadState.Error;
                }
                else {
                    if ( (int)state <= (int)State.Closed ) { 
 	                    return (ReadState)(int)state;
                    } 
                    else { 
                        return ReadState.Interactive;
                    } 
                }
            }
        }
 
        public override XmlNameTable NameTable {
            get { 
                return reader.NameTable; 
            }
        } 

        public override int AttributeCount {
            get {
                return InAttributeActiveState ? reader.AttributeCount + nsAttrCount : 0; 
            }
        } 
 
        public override string GetAttribute( string name ) {
            if ( !InAttributeActiveState ) { 
                return null;
            }
            string attr = reader.GetAttribute( name );
            if ( attr != null ) { 
                return attr;
            } 
            for ( int i = 0; i < nsAttrCount; i++ ) { 
                if ( name == nsAttributes[i].name ) {
                    return nsAttributes[i].value; 
                }
            }
            return null;
        } 

        public override string GetAttribute( string name, string namespaceURI ) { 
            if ( !InAttributeActiveState ) { 
                return null;
            } 
            string attr = reader.GetAttribute( name, namespaceURI );
            if ( attr != null ) {
                return attr;
            } 
            for ( int i = 0; i < nsAttrCount; i++ ) {
                if ( name == nsAttributes[i].localName && namespaceURI == xmlnsUri ) { 
                    return nsAttributes[i].value; 
                }
            } 
            return null;

        }
 
        public override string GetAttribute( int i ) {
            if ( !InAttributeActiveState ) { 
                throw new ArgumentOutOfRangeException("i"); 
            }
            int n = reader.AttributeCount; 
            if ( i < n ) {
                return reader.GetAttribute( i );
            }
            else if ( i - n < nsAttrCount ) { 
                return nsAttributes[i-n].value;
            } 
            else { 
                throw new ArgumentOutOfRangeException( "i" );
            } 
        }

        public override bool MoveToAttribute( string name ) {
            if ( !InAttributeActiveState ) { 
                return false;
            } 
            if ( reader.MoveToAttribute( name ) ) { 
                curNsAttr = -1;
                useCurNode = false; 
                return true;
            }
            for ( int i = 0; i < nsAttrCount; i++ ) {
                if ( name == nsAttributes[i].name ) { 
                    MoveToNsAttribute( i );
                    return true; 
                } 
            }
            return false; 
        }

        public override bool MoveToAttribute( string name, string ns ) {
            if ( !InAttributeActiveState ) { 
                return false;
            } 
            if ( reader.MoveToAttribute( name, ns ) ) { 
                curNsAttr = -1;
                useCurNode = false; 
                return true;
            }
            for ( int i = 0; i < nsAttrCount; i++ ) {
                if ( name == nsAttributes[i].localName && ns == xmlnsUri ) { 
                    MoveToNsAttribute( i );
                    return true; 
                } 
            }
            return false; 
        }

        public override void MoveToAttribute( int i ) {
            if ( !InAttributeActiveState ) { 
                throw new ArgumentOutOfRangeException("i");
            } 
            int n = reader.AttributeCount; 
            if ( i < n ) {
                reader.MoveToAttribute( i ); 
                curNsAttr = -1;
                useCurNode = false;
            }
            else if ( i - n < nsAttrCount ) { 
                MoveToNsAttribute( i - n );
            } 
            else { 
                throw new ArgumentOutOfRangeException( "i" );
            } 
        }

        public override bool MoveToFirstAttribute() {
            if ( !InAttributeActiveState ) { 
                return false;
            } 
            if ( reader.MoveToFirstAttribute() ) { 
                useCurNode = false;
                return true; 
            }
            if ( nsAttrCount > 0 ) {
                MoveToNsAttribute( 0 );
                return true; 
            }
            return false; 
        } 

        public override bool MoveToNextAttribute() { 
            if ( !InAttributeActiveState ) {
                return false;
            }
            if ( curNsAttr == -1 && reader.MoveToNextAttribute() ) { 
                return true;
            } 
            if ( curNsAttr + 1 < nsAttrCount ) { 
                MoveToNsAttribute( curNsAttr + 1 );
                return true; 
            }
            return false;
        }
 
        public override bool MoveToElement() {
            if ( !InAttributeActiveState ) { 
                return false; 
            }
            curNsAttr = -1; 
            useCurNode = false;
            return reader.MoveToElement();
        }
 
        public override bool ReadAttributeValue() {
            if ( !InAttributeActiveState ) { 
                return false; 
            }
            if ( curNsAttr == -1 ) { 
                return reader.ReadAttributeValue();
            }
            else if ( curNode.type == XmlNodeType.Text ) { // we are on namespace attribute value
                return false; 
            }
            else { 
                Debug.Assert( curNode.type == XmlNodeType.Attribute ); 
                tmpNode.type = XmlNodeType.Text;
                tmpNode.value = curNode.value; 
                SetCurrentNode( tmpNode );
                return true;
            }
        } 

        public override bool Read() { 
 
            switch ( state ) {
                case State.Initial: 
                    useCurNode = false;
                    state = State.Interactive;
                    ProcessNamespaces();
                    return true; 

                case State.Interactive: 
                    curNsAttr = -1; 
                    useCurNode = false;
                    reader.MoveToElement(); 
                    Debug.Assert( reader.Depth >= initialDepth );
                    if ( reader.Depth == initialDepth ) {
                        if ( reader.NodeType == XmlNodeType.EndElement ||
                            ( reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement ) ) { 
                            state = State.EndOfFile;
                            SetEmptyNode(); 
                            return false; 
                        }
                        Debug.Assert( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ); 
                    }
                    if ( reader.Read() ) {
                        ProcessNamespaces();
                        return true; 
                    }
                    else { 
                        SetEmptyNode(); 
                        return false;
                    } 

                case State.EndOfFile:
                case State.Closed:
                    return false; 

                case State.PopNamespaceScope: 
                    nsManager.PopScope(); 
                    goto case State.ClearNsAttributes;
 
                case State.ClearNsAttributes:
                    nsAttrCount = 0;
                    state = State.Interactive;
                    goto case State.Interactive; 

                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex: 
                    if ( !FinishReadElementContentAsBinary() ) {
                        return false; 
                    }
                    return Read();

                case State.ReadContentAsBase64: 
                case State.ReadContentAsBinHex:
                    if ( !FinishReadContentAsBinary() ) { 
                        return false; 
                    }
                    return Read(); 

                default:
                    Debug.Assert( false );
                    return false; 
            }
        } 
 
        public override void Close() {
            if ( state == State.Closed ) { 
                return;
            }
            try {
                // move the underlying reader to the next sibling 
                if ( state != State.EndOfFile ) {
                    reader.MoveToElement(); 
                    Debug.Assert( reader.Depth >= initialDepth ); 
                    // move off the root of the subtree
                    if ( reader.Depth == initialDepth && reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) { 
                        reader.Read();
                    }
                    // move to the end of the subtree, do nothing if on empty root element
                    while ( reader.Depth > initialDepth && reader.Read() ) { 
                        /* intentionally empty */
                    } 
                } 
            }
            catch { // never fail... 
            }
            finally {
                curNsAttr = -1;
                useCurNode = false; 
                state = State.Closed;
                SetEmptyNode(); 
            } 
        }
 
        public override void Skip() {

            switch ( state ) {
                case State.Initial: 
                    Read();
                    return; 
 
                case State.Interactive:
                    curNsAttr = -1; 
                    useCurNode = false;
                    reader.MoveToElement();
                    Debug.Assert( reader.Depth >= initialDepth );
                    if ( reader.Depth == initialDepth ) { 
                        if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) {
                            // we are on root of the subtree -> skip to the end element and set to Eof state 
                            if ( reader.Read() ) { 
                                while ( reader.NodeType != XmlNodeType.EndElement && reader.Depth > initialDepth ) {
                                    reader.Skip(); 
                                }
                            }
                        }
                        Debug.Assert( reader.NodeType == XmlNodeType.EndElement || 
                                      reader.NodeType == XmlNodeType.Element && reader.IsEmptyElement ||
                                      reader.ReadState != ReadState.Interactive ); 
                        state = State.EndOfFile; 
                        SetEmptyNode();
                        return; 
                    }

                    if ( reader.NodeType == XmlNodeType.Element && !reader.IsEmptyElement ) {
                        nsManager.PopScope(); 
                    }
                    reader.Skip(); 
                    ProcessNamespaces(); 

                    Debug.Assert( reader.Depth >= initialDepth ); 
                    return;

                case State.Closed:
                case State.EndOfFile: 
                    return;
 
                case State.PopNamespaceScope: 
                    nsManager.PopScope();
                    goto case State.ClearNsAttributes; 

                case State.ClearNsAttributes:
                    nsAttrCount = 0;
                    state = State.Interactive; 
                    goto case State.Interactive;
 
                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex:
                    if ( FinishReadElementContentAsBinary() ) { 
                        Skip();
                    }
                    break;
 
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex: 
                    if ( FinishReadContentAsBinary() ) { 
                        Skip();
                    } 
                    break;

                default:
                    Debug.Assert( false ); 
                    return;
            } 
        } 

        public override object ReadContentAsObject() { 
            try {
                InitReadContentAsType( "ReadContentAsObject" );
                object value = reader.ReadContentAsObject();
                FinishReadContentAsType(); 
                return value;
            } 
            catch { 
                state = State.Error;
                throw; 
            }
        }

        public override bool ReadContentAsBoolean() { 
            try {
                InitReadContentAsType( "ReadContentAsBoolean" ); 
                bool value = reader.ReadContentAsBoolean(); 
                FinishReadContentAsType();
                return value; 
            }
            catch {
                state = State.Error;
                throw; 
            }
        } 
 
        public override DateTime ReadContentAsDateTime() {
            try { 
                InitReadContentAsType( "ReadContentAsDateTime" );
                DateTime value = reader.ReadContentAsDateTime();
                FinishReadContentAsType();
                return value; 
            }
            catch { 
                state = State.Error; 
                throw;
            } 
        }

        public override double ReadContentAsDouble() {
            try { 
                InitReadContentAsType( "ReadContentAsDouble" );
                double value = reader.ReadContentAsDouble(); 
                FinishReadContentAsType(); 
                return value;
            } 
            catch {
                state = State.Error;
                throw;
            } 
        }
 
        public override float ReadContentAsFloat() { 
            try {
                InitReadContentAsType( "ReadContentAsFloat" ); 
                float value = reader.ReadContentAsFloat();
                FinishReadContentAsType();
                return value;
            } 
            catch {
                state = State.Error; 
                throw; 
            }
        } 

        public override decimal ReadContentAsDecimal() {
            try {
                InitReadContentAsType( "ReadContentAsDecimal" ); 
                decimal value = reader.ReadContentAsDecimal();
                FinishReadContentAsType(); 
                return value; 
            }
            catch { 
                state = State.Error;
                throw;
            }
        } 

        public override int ReadContentAsInt() { 
            try { 
                InitReadContentAsType( "ReadContentAsInt" );
                int value = reader.ReadContentAsInt(); 
                FinishReadContentAsType();
                return value;
            }
            catch { 
                state = State.Error;
                throw; 
            } 
        }
 
        public override long ReadContentAsLong() {
            try {
                InitReadContentAsType( "ReadContentAsLong" );
                long value = reader.ReadContentAsLong(); 
                FinishReadContentAsType();
                return value; 
            } 
            catch {
                state = State.Error; 
                throw;
            }
        }
 
        public override string ReadContentAsString() {
            try { 
                InitReadContentAsType( "ReadContentAsString" ); 
                string value = reader.ReadContentAsString();
                FinishReadContentAsType(); 
                return value;
            }
            catch {
                state = State.Error; 
                throw;
            } 
        } 

        public override object ReadContentAs( Type returnType, IXmlNamespaceResolver namespaceResolver ) { 
            try {
                InitReadContentAsType( "ReadContentAs" );
                object value = reader.ReadContentAs( returnType, namespaceResolver );
                FinishReadContentAsType(); 
                return value;
            } 
            catch { 
                state = State.Error;
                throw; 
            }
        }

        public override bool CanReadBinaryContent { 
            get {
                return reader.CanReadBinaryContent; 
            } 
        }
 
        public override int ReadContentAsBase64( byte[] buffer, int index, int count ) {
            switch ( state ) {
                case State.Initial:
                case State.EndOfFile: 
                case State.Closed:
                    return 0; 
 
                case State.ClearNsAttributes:
                case State.PopNamespaceScope: 
                    switch ( NodeType ) {
                        case XmlNodeType.Element:
                            throw CreateReadContentAsException( "ReadContentAsBase64" );
                        case XmlNodeType.EndElement: 
                            return 0;
                        case XmlNodeType.Attribute: 
                        case XmlNodeType.Text: 
                            Debug.Assert( AttributeCount > 0 );
                            return reader.ReadContentAsBase64( buffer, index, count ); 
                        default:
                            Debug.Assert( false );
                            return 0;
                    } 

                case State.Interactive: 
                    state = State.ReadContentAsBase64; 
                    goto case State.ReadContentAsBase64;
 
                case State.ReadContentAsBase64:
                    int read = reader.ReadContentAsBase64( buffer, index, count );
                    if ( read == 0 ) {
                        state = State.Interactive; 
                        ProcessNamespaces();
                    } 
                    return read; 

                case State.ReadContentAsBinHex: 
                case State.ReadElementContentAsBase64:
                case State.ReadElementContentAsBinHex:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
 
                default:
                    Debug.Assert( false ); 
                    return 0; 
            }
        } 

        public override int ReadElementContentAsBase64( byte[] buffer, int index, int count ) {
            switch ( state ) {
                case State.Initial: 
                case State.EndOfFile:
                case State.Closed: 
                    return 0; 

                case State.Interactive: 
                case State.PopNamespaceScope:
                case State.ClearNsAttributes:
                    if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBase64 ) ) {
                        return 0; 
                    }
                    goto case State.ReadElementContentAsBase64; 
 
                case State.ReadElementContentAsBase64:
                    int read = reader.ReadContentAsBase64( buffer, index, count ); 
                    if ( read > 0 ) {
                        return read;
                    }
                    if ( NodeType != XmlNodeType.EndElement ) { 
                        throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo );
                    } 
 
                    // pop namespace scope
                    state = State.Interactive; 
                    ProcessNamespaces();

                    // set eof state or move off the end element
                    if ( reader.Depth == initialDepth ) { 
                        state = State.EndOfFile;
                        SetEmptyNode(); 
                    } 
                    else {
                        Read(); 
                    }
                    return 0;

                case State.ReadContentAsBase64: 
                case State.ReadContentAsBinHex:
                case State.ReadElementContentAsBinHex: 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) ); 

                default: 
                    Debug.Assert( false );
                    return 0;
            }
        } 

        public override int ReadContentAsBinHex( byte[] buffer, int index, int count ) { 
            switch ( state ) { 
                case State.Initial:
                case State.EndOfFile: 
                case State.Closed:
                    return 0;

                case State.ClearNsAttributes: 
                case State.PopNamespaceScope:
                    switch ( NodeType ) { 
                        case XmlNodeType.Element: 
                            throw CreateReadContentAsException( "ReadContentAsBinHex" );
                        case XmlNodeType.EndElement: 
                            return 0;
                        case XmlNodeType.Attribute:
                        case XmlNodeType.Text:
                            Debug.Assert( AttributeCount > 0 ); 
                            return reader.ReadContentAsBinHex( buffer, index, count );
                        default: 
                            Debug.Assert( false ); 
                            return 0;
                    } 

                case State.Interactive:
                    state = State.ReadContentAsBinHex;
                    goto case State.ReadContentAsBinHex; 

                case State.ReadContentAsBinHex: 
                    int read = reader.ReadContentAsBinHex( buffer, index, count ); 
                    if ( read == 0 ) {
                        state = State.Interactive; 
                        ProcessNamespaces();
                    }
                    return read;
 
                case State.ReadContentAsBase64:
                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex: 
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );
 
                default:
                    Debug.Assert( false );
                    return 0;
            } 
        }
 
        public override int ReadElementContentAsBinHex( byte[] buffer, int index, int count ) { 
            switch ( state ) {
                case State.Initial: 
                case State.EndOfFile:
                case State.Closed:
                    return 0;
 
                case State.Interactive:
                case State.PopNamespaceScope: 
                case State.ClearNsAttributes: 
                    if ( !InitReadElementContentAsBinary( State.ReadElementContentAsBinHex ) ) {
                        return 0; 
                    }
                    goto case State.ReadElementContentAsBinHex;
                case State.ReadElementContentAsBinHex:
                    int read = reader.ReadContentAsBinHex( buffer, index, count ); 
                    if ( read > 0 ) {
                        return read; 
                    } 
                    if ( NodeType != XmlNodeType.EndElement ) {
                        throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); 
                    }

                    // pop namespace scope
                    state = State.Interactive; 
                    ProcessNamespaces();
 
                    // set eof state or move off the end element 
                    if ( reader.Depth == initialDepth ) {
                        state = State.EndOfFile; 
                        SetEmptyNode();
                    }
                    else {
                        Read(); 
                    }
                    return 0; 
 
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex: 
                case State.ReadElementContentAsBase64:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingBinaryContentMethods ) );

                default: 
                    Debug.Assert( false );
                    return 0; 
            } 
        }
 
        public override bool CanReadValueChunk {
            get {
                return reader.CanReadValueChunk;
            } 
        }
 
        public override int ReadValueChunk( char[] buffer, int index, int count ) { 
            switch ( state ) {
                case State.Initial: 
                case State.EndOfFile:
                case State.Closed:
                case State.Error:
                    return 0; 

                case State.ClearNsAttributes: 
                case State.PopNamespaceScope: 
                    // no need to clean ns attributes or pop scope because the reader when ReadValueChunk is called
                    // - on Element errors 
                    // - on EndElement errors
                    // - on Attribute does not move
                    // and that's all where State.ClearNsAttributes or State.PopnamespaceScope can be set
                    goto case State.Interactive; 

                case State.Interactive: 
                    return reader.ReadValueChunk( buffer, index, count ); 

                case State.ReadElementContentAsBase64: 
                case State.ReadElementContentAsBinHex:
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) ); 

                default: 
                    Debug.Assert( false ); 
                    return 0;
            } 
        }

//
// IDisposable interface 
//
        protected override void Dispose( bool disposing ) { 
            // note: we do not want to dispose the underlying reader 
            this.Close();
        } 

//
// IXmlLineInfo members
// 
        public override int LineNumber {
            get { 
                return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LineNumber; 
            }
        } 

        public override int LinePosition {
            get {
                return ( readerAsIXmlLineInfo == null || useCurNode ) ? 0 : readerAsIXmlLineInfo.LinePosition; 
            }
        } 
 
        public override string LookupNamespace( string prefix ) {
            return ((IXmlNamespaceResolver)this).LookupNamespace( prefix ); 
        }

//
// IXmlNamespaceResolver implementation 
//
        IDictionary IXmlNamespaceResolver.GetNamespacesInScope( XmlNamespaceScope scope ) { 
            if ( !InNamespaceActiveState ) { 
                return new Dictionary();
            } 
            return nsManager.GetNamespacesInScope( scope );
        }

        string IXmlNamespaceResolver.LookupNamespace( string prefix ) { 
            if ( !InNamespaceActiveState ) {
                return null; 
            } 
            return nsManager.LookupNamespace( prefix );
        } 

        string IXmlNamespaceResolver.LookupPrefix( string namespaceName ) {
            if ( !InNamespaceActiveState ) {
                return null; 
            }
            return nsManager.LookupPrefix( namespaceName ); 
        } 

// 
// Internal methods
//

        internal override SchemaInfo DtdSchemaInfo { 
            get {
                return null; 
            } 
        }
 
//
// Private methods
//
        private void ProcessNamespaces() { 
            switch ( reader.NodeType ) {
                case XmlNodeType.Element: 
                    nsManager.PushScope(); 

                    string prefix = reader.Prefix; 
                    string ns = reader.NamespaceURI;
                    if ( nsManager.LookupNamespace( prefix ) != ns ) {
                        AddNamespace( prefix, ns );
                    } 

                    if ( reader.MoveToFirstAttribute() ) { 
                        do { 
                            prefix = reader.Prefix;
                            ns = reader.NamespaceURI; 

                            if ( Ref.Equal( ns, xmlnsUri ) ) {
                                if ( prefix.Length == 0 ) {
                                    nsManager.AddNamespace( string.Empty, reader.Value ); 
                                    RemoveNamespace( string.Empty, xmlns );
                                } 
                                else { 
                                    prefix = reader.LocalName;
                                    nsManager.AddNamespace( prefix, reader.Value ); 
                                    RemoveNamespace( xmlns, prefix );
                                }
                            }
                            else if ( prefix.Length != 0 && nsManager.LookupNamespace( prefix ) != ns ) { 
                                AddNamespace( prefix, ns );
                            } 
                        } while ( reader.MoveToNextAttribute() ); 
                        reader.MoveToElement();
                    } 

                    if ( reader.IsEmptyElement ) {
                        state = State.PopNamespaceScope;
                    } 
                    break;
                case XmlNodeType.EndElement: 
                    state = State.PopNamespaceScope; 
                    break;
            } 
        }

        private void AddNamespace( string prefix, string ns ) {
            nsManager.AddNamespace( prefix, ns ); 

            int index = nsAttrCount++; 
            if ( nsAttributes == null ) { 
                nsAttributes = new NodeData[InitialNamespaceAttributeCount];
            } 
            if ( index == nsAttributes.Length ) {
                NodeData[] newNsAttrs = new NodeData[nsAttributes.Length * 2];
                Array.Copy( nsAttributes, 0, newNsAttrs, 0, index );
                nsAttributes = newNsAttrs; 
            }
 
            if ( nsAttributes[index] == null ) { 
                nsAttributes[index] = new NodeData();
            } 
            if ( prefix.Length == 0 ) {
                nsAttributes[index].Set( XmlNodeType.Attribute, xmlns, string.Empty, xmlns, XmlReservedNs.NsXmlNs, ns );
            }
            else { 
                nsAttributes[index].Set( XmlNodeType.Attribute, prefix, xmlns, string.Concat( xmlns, ":", prefix ), XmlReservedNs.NsXmlNs, ns );
            } 
 
            Debug.Assert( state == State.ClearNsAttributes || state == State.Interactive || state == State.PopNamespaceScope );
            state = State.ClearNsAttributes; 

            curNsAttr = -1;
        }
 
        private void RemoveNamespace( string prefix, string localName ) {
            for ( int i = 0; i < nsAttrCount; i++ ) { 
                if ( Ref.Equal( prefix, nsAttributes[i].prefix ) && 
                     Ref.Equal( localName, nsAttributes[i].localName ) ) {
                         if ( i < nsAttrCount - 1 ) { 
                             // swap
                             NodeData tmpNodeData = nsAttributes[i];
                             nsAttributes[i] = nsAttributes[nsAttrCount - 1];
                             nsAttributes[nsAttrCount - 1] = tmpNodeData; 
                         }
                         nsAttrCount--; 
                         break; 
                 }
            } 
        }

        private void MoveToNsAttribute( int index ) {
            Debug.Assert( index >= 0 && index <= nsAttrCount ); 
            reader.MoveToElement();
            curNsAttr = index; 
            SetCurrentNode( nsAttributes[index] ); 
        }
 
        private bool InitReadElementContentAsBinary( State binaryState ) {
            if ( NodeType != XmlNodeType.Element ) {
                throw reader.CreateReadElementContentAsException( "ReadElementContentAsBase64" );
            } 

            bool isEmpty = IsEmptyElement; 
 
            // move to content or off the empty element
            if ( !Read() || isEmpty ) { 
                return false;
            }
            // special-case child element and end element
            switch ( NodeType ) { 
                case XmlNodeType.Element:
                    throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); 
                case XmlNodeType.EndElement: 
                    // pop scope & move off end element
                    ProcessNamespaces(); 
                    Read();
                    return false;
            }
 
            Debug.Assert( state == State.Interactive );
            state = binaryState; 
            return true; 
        }
 
        private bool FinishReadElementContentAsBinary() {
            Debug.Assert( state == State.ReadElementContentAsBase64 || state == State.ReadElementContentAsBinHex );

            byte[] bytes = new byte[256]; 
            if ( state == State.ReadElementContentAsBase64 ) {
                while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ; 
            } 
            else {
                while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ; 
            }

            if ( NodeType != XmlNodeType.EndElement ) {
                throw new XmlException( Res.Xml_InvalidNodeType, reader.NodeType.ToString(), reader as IXmlLineInfo ); 
            }
 
            // pop namespace scope 
            state = State.Interactive;
            ProcessNamespaces(); 

            // check eof
            if ( reader.Depth == initialDepth ) {
                 state = State.EndOfFile; 
                 SetEmptyNode();
                 return false; 
            } 
            // move off end element
            return Read(); 
        }

        private bool FinishReadContentAsBinary() {
            Debug.Assert( state == State.ReadContentAsBase64 || state == State.ReadContentAsBinHex ); 

            byte[] bytes = new byte[256]; 
            if ( state == State.ReadContentAsBase64 ) { 
                while ( reader.ReadContentAsBase64( bytes, 0, 256 ) > 0 ) ;
            } 
            else {
                while ( reader.ReadContentAsBinHex( bytes, 0, 256 ) > 0 ) ;
            }
 
            state = State.Interactive;
            ProcessNamespaces(); 
 
            // check eof
            if ( reader.Depth == initialDepth ) { 
                 state = State.EndOfFile;
                 SetEmptyNode();
                 return false;
            } 
            return true;
        } 
 
        private bool InAttributeActiveState {
            get { 
#if DEBUG
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Initial ) ) );
                Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.Interactive ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Error ) ) ); 
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.EndOfFile ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.Closed ) ) ); 
                Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) ); 
                Debug.Assert( 0 != ( AttributeActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) ); 
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) );
                Debug.Assert( 0 == ( AttributeActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) );
#endif 
                return 0 != ( AttributeActiveStates & ( 1 << (int)state ) );
            } 
        } 

        private bool InNamespaceActiveState { 
            get {
#if DEBUG
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Initial ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.Interactive ) ) ); 
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Error ) ) );
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.EndOfFile ) ) ); 
                Debug.Assert( 0 == ( NamespaceActiveStates & ( 1 << (int)State.Closed ) ) ); 
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.PopNamespaceScope ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ClearNsAttributes ) ) ); 
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBase64 ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadElementContentAsBinHex ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBase64 ) ) );
                Debug.Assert( 0 != ( NamespaceActiveStates & ( 1 << (int)State.ReadContentAsBinHex ) ) ); 
#endif
                return 0 != ( NamespaceActiveStates & ( 1 << (int)state ) ); 
            } 
        }
 
        void SetEmptyNode() {
            Debug.Assert( tmpNode.localName == string.Empty && tmpNode.prefix == string.Empty && tmpNode.name == string.Empty && tmpNode.namespaceUri == string.Empty );
            tmpNode.type = XmlNodeType.None;
            tmpNode.value = string.Empty; 

            curNode = tmpNode; 
            useCurNode = true; 
        }
 
        void SetCurrentNode( NodeData node ) {
            curNode = node;
            useCurNode = true;
        } 

        void InitReadContentAsType( string methodName ) { 
            switch ( state ) { 
                case State.Initial:
                case State.EndOfFile: 
                case State.Closed:
                case State.Error:
                    break;
 
                case State.Interactive:
                    return; 
 
                case State.PopNamespaceScope:
                case State.ClearNsAttributes: 
                    // no need to clean ns attributes or pop scope because the reader when ReadContentAs is called
                    // - on Element errors
                    // - on Attribute does not move
                    // - on EndElement does not move 
                    // and that's all where State.ClearNsAttributes or State.PopNamespacScope can be set
                    return; 
 
                case State.ReadElementContentAsBase64:
                case State.ReadElementContentAsBinHex: 
                case State.ReadContentAsBase64:
                case State.ReadContentAsBinHex:
                    throw new InvalidOperationException( Res.GetString( Res.Xml_MixingReadValueChunkWithBinary ) );
 
                default:
                    Debug.Assert( false ); 
                    break; 
            }
            throw CreateReadContentAsException( methodName ); 
        }

        void FinishReadContentAsType() {
            Debug.Assert( state == State.Interactive || 
                          state == State.PopNamespaceScope ||
                          state == State.ClearNsAttributes ); 
 
            switch ( NodeType ) {
                case XmlNodeType.Element: 
                    // new element we moved to - process namespaces
                    ProcessNamespaces();
                    break;
                case XmlNodeType.EndElement: 
                    // end element we've stayed on or have been moved to
                    state = State.PopNamespaceScope; 
                    break; 
                case XmlNodeType.Attribute:
                    // stayed on attribute, do nothing 
                    break;
            }
        }
    } 
}

// File provided for Reference Use Only by Microsoft Corporation (c) 2007.

                        

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