XmlBinaryReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / fx / src / Xml / System / Xml / BinaryXml / XmlBinaryReader.cs / 1305376 / XmlBinaryReader.cs

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

    internal sealed class XmlSqlBinaryReader : XmlReader, IXmlNamespaceResolver { 
        internal static readonly Type TypeOfObject = typeof(System.Object);
        internal static readonly Type TypeOfString = typeof(System.String);

        static Type[] TokenTypeMap = null; 

        static byte[] XsdKatmaiTimeScaleToValueLengthMap = new byte[8] { 
        // length scale 
            3, // 0
            3, // 1 
            3, // 2
            4, // 3
            4, // 4
            5, // 5 
            5, // 6
            5, // 7 
        }; 

        enum ScanState { 
            Doc = 0,
            XmlText = 1,
            Attr = 2,
            AttrVal = 3, 
            AttrValPseudoValue = 4,
            Init = 5, 
            Error = 6, 
            EOF = 7,
            Closed = 8 
        }

        static ReadState[] ScanState2ReadState = {
            ReadState.Interactive, 
            ReadState.Interactive,
            ReadState.Interactive, 
            ReadState.Interactive, 
            ReadState.Interactive,
            ReadState.Initial, 
            ReadState.Error,
            ReadState.EndOfFile,
            ReadState.Closed
        }; 

        // Note: also used by XmlBinaryWriter 
        internal struct QName { 
            public string prefix;
            public string localname; 
            public string namespaceUri;

            public QName(string prefix, string lname, string nsUri) {
                this.prefix = prefix; this.localname = lname; this.namespaceUri = nsUri; 
            }
            public void Set(string prefix, string lname, string nsUri) { 
                this.prefix = prefix; this.localname = lname; this.namespaceUri = nsUri; 
            }
 
            public void Clear() {
                this.prefix = this.localname = this.namespaceUri = String.Empty;
            }
 
            public bool MatchNs(string lname, string nsUri) {
                return lname == this.localname && nsUri == this.namespaceUri; 
            } 
            public bool MatchPrefix(string prefix, string lname) {
                return lname == this.localname && prefix == this.prefix; 
            }

            public void CheckPrefixNS(string prefix, string namespaceUri) {
                if (this.prefix == prefix && this.namespaceUri != namespaceUri) 
                    throw new XmlException(Res.XmlBinary_NoRemapPrefix, new String[] { prefix, this.namespaceUri, namespaceUri });
            } 
 
            public override int GetHashCode() {
                return this.prefix.GetHashCode() ^ this.localname.GetHashCode(); 
            }

            public int GetNSHashCode(SecureStringHasher hasher) {
                return hasher.GetHashCode(this.namespaceUri) ^ hasher.GetHashCode(this.localname); 
            }
 
 
            public override bool Equals(object other) {
                if (other is QName) { 
                    QName that = (QName)other;
                    return this == that;
                }
                return false; 
            }
 
            public override string ToString() { 
                if (prefix.Length == 0)
                    return this.localname; 
                else
                    return this.prefix + ":" + this.localname;
            }
 
            public static bool operator ==(QName a, QName b) {
                return ((a.prefix == b.prefix) 
                    && (a.localname == b.localname) 
                    && (a.namespaceUri == b.namespaceUri));
            } 

            public static bool operator !=(QName a, QName b) {
                return !(a == b);
            } 
        };
 
        struct ElemInfo { 
            public QName name;
            public string xmlLang; 
            public XmlSpace xmlSpace;
            public bool xmlspacePreserve;
            public NamespaceDecl nsdecls;
 
            public void Set(QName name, bool xmlspacePreserve) {
                this.name = name; 
                this.xmlLang = null; 
                this.xmlSpace = XmlSpace.None;
                this.xmlspacePreserve = xmlspacePreserve; 
            }
            public NamespaceDecl Clear() {
                NamespaceDecl nsdecls = this.nsdecls;
                this.nsdecls = null; 
                return nsdecls;
            } 
        }; 

        struct AttrInfo { 
            public QName name;
            public string val;
            public int contentPos;
            public int hashCode; 
            public int prevHash;
 
            public void Set(QName n, string v) { 
                this.name = n;
                this.val = v; 
                this.contentPos = 0;
                this.hashCode = 0;
                this.prevHash = 0;
            } 
            public void Set(QName n, int pos) {
                this.name = n; 
                this.val = null; 
                this.contentPos = pos;
                this.hashCode = 0; 
                this.prevHash = 0;
            }

            public void GetLocalnameAndNamespaceUri(out string localname, out string namespaceUri) { 
                localname = this.name.localname;
                namespaceUri = this.name.namespaceUri; 
            } 

            public int GetLocalnameAndNamespaceUriAndHash(SecureStringHasher hasher, out string localname, out string namespaceUri) { 
                localname = this.name.localname;
                namespaceUri = this.name.namespaceUri;
                return this.hashCode = this.name.GetNSHashCode(hasher);
            } 

            public bool MatchNS(string localname, string namespaceUri) { 
                return this.name.MatchNs(localname, namespaceUri); 
            }
 
            public bool MatchHashNS(int hash, string localname, string namespaceUri) {
                return this.hashCode == hash && this.name.MatchNs(localname, namespaceUri);
            }
 
            public void AdjustPosition(int adj) {
                if (this.contentPos != 0) 
                    this.contentPos += adj; 
            }
        } 

        class NamespaceDecl {
            public string prefix;
            public string uri; 
            public NamespaceDecl scopeLink;
            public NamespaceDecl prevLink; 
            public int scope; 
            public bool implied;
 
            public NamespaceDecl(string prefix, string nsuri,
                                NamespaceDecl nextInScope, NamespaceDecl prevDecl,
                                int scope, bool implied) {
                this.prefix = prefix; 
                this.uri = nsuri;
                this.scopeLink = nextInScope; 
                this.prevLink = prevDecl; 
                this.scope = scope;
                this.implied = implied; 
            }
        }

        // symbol and qname tables 
        struct SymbolTables {
            public string[] symtable; 
            public int symCount; 
            public QName[] qnametable;
            public int qnameCount; 
            public void Init() {
                this.symtable = new string[64];
                this.qnametable = new QName[16];
                this.symtable[0] = String.Empty; 
                this.symCount = 1;
                this.qnameCount = 1; 
            } 
        }
        class NestedBinXml { 
            public SymbolTables symbolTables;
            public int docState;
            public NestedBinXml next;
            public NestedBinXml(SymbolTables symbolTables, int docState, NestedBinXml next) { 
                this.symbolTables = symbolTables;
                this.docState = docState; 
                this.next = next; 
            }
        } 

        // input data
        Stream inStrm;
        byte[] data; 
        int pos;
        int mark; 
        int end; 
        long offset; // how much read and shift out of buffer
        bool eof; 
        bool sniffed;
        bool isEmpty; // short-tag element start tag

        int docState; // 0=>auto, 1=>doc/pre-dtd, 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem, 9=>frag 

        // symbol and qname tables 
        SymbolTables symbolTables; 

        XmlNameTable xnt; 
        bool xntFromSettings;
        string xml;
        string xmlns;
        string nsxmlns; 

        // base uri... 
        string baseUri; 

        // current parse state 
        ScanState state;
        XmlNodeType nodetype;
        BinXmlToken token;
        // current attribute 
        int attrIndex;
        // index of current qname 
        QName qnameOther; 
        // saved qname of element (for MoveToElement)
        QName qnameElement; 
        XmlNodeType parentNodeType; // use for MoveToElement()
        // stack of current open element tags
        ElemInfo[] elementStack;
        int elemDepth; 
        // current attributes
        AttrInfo[] attributes; 
        int[] attrHashTbl; 
        int attrCount;
        int posAfterAttrs; 
        // xml:space
        bool xmlspacePreserve;
        // position/parse info for current typed token
        int tokLen; 
        int tokDataPos;
        bool hasTypedValue; 
        System.Type valueType; 
        // if it is a simple string value, we cache it
        string stringValue; 
        // hashtable of current namespaces
        Dictionary namespaces;
        //Hashtable namespaces;
        // linked list of pushed nametables (to support nested binary-xml documents) 
        NestedBinXml prevNameInfo;
        // XmlTextReader to handle embeded text blocks 
        XmlReader textXmlReader; 
        // close input flag
        bool closeInput; 

        bool checkCharacters;
        bool ignoreWhitespace;
        bool ignorePIs; 
        bool ignoreComments;
        DtdProcessing dtdProcessing; 
 
        SecureStringHasher hasher;
        XmlCharType xmlCharType; 
        Encoding unicode;

        // current version of the protocol
        byte version; 

        public XmlSqlBinaryReader(System.IO.Stream stream, byte[] data, int len, string baseUri, bool closeInput, XmlReaderSettings settings) { 
            unicode = System.Text.Encoding.Unicode; 
            xmlCharType = XmlCharType.Instance;
 
            this.xnt = settings.NameTable;
            if (this.xnt == null) {
                this.xnt = new NameTable();
                this.xntFromSettings = false; 
            }
            else { 
                this.xntFromSettings = true; 
            }
            this.xml = this.xnt.Add("xml"); 
            this.xmlns = this.xnt.Add("xmlns");
            this.nsxmlns = this.xnt.Add(XmlReservedNs.NsXmlNs);
            this.baseUri = baseUri;
            this.state = ScanState.Init; 
            this.nodetype = XmlNodeType.None;
            this.token = BinXmlToken.Error; 
            this.elementStack = new ElemInfo[16]; 
            //this.elemDepth = 0;
            this.attributes = new AttrInfo[8]; 
            this.attrHashTbl = new int[8];
            //this.attrCount = 0;
            //this.attrIndex = 0;
            this.symbolTables.Init(); 
            this.qnameOther.Clear();
            this.qnameElement.Clear(); 
            this.xmlspacePreserve = false; 
            this.hasher = new SecureStringHasher();
            this.namespaces = new Dictionary(hasher); 
            AddInitNamespace(String.Empty, String.Empty);
            AddInitNamespace(this.xml, this.xnt.Add(XmlReservedNs.NsXml));
            AddInitNamespace(this.xmlns, this.nsxmlns);
            this.valueType = TypeOfString; 
            // init buffer position, etc
            this.inStrm = stream; 
            if (data != null) { 
                Debug.Assert(len >= 2 && (data[0] == 0xdf && data[1] == 0xff));
                this.data = data; 
                this.end = len;
                this.pos = 2;
                this.sniffed = true;
            } 
            else {
                this.data = new byte[XmlReader.DefaultBufferSize]; 
                this.end = stream.Read(this.data, 0, XmlReader.DefaultBufferSize); 
                this.pos = 0;
                this.sniffed = false; 
            }

            this.mark = -1;
            this.eof = (0 == this.end); 
            this.offset = 0;
            this.closeInput = closeInput; 
            switch (settings.ConformanceLevel) { 
                case ConformanceLevel.Auto:
                    this.docState = 0; break; 
                case ConformanceLevel.Fragment:
                    this.docState = 9; break;
                case ConformanceLevel.Document:
                    this.docState = 1; break; 
            }
            this.checkCharacters = settings.CheckCharacters; 
            this.dtdProcessing = settings.DtdProcessing; 
            this.ignoreWhitespace = settings.IgnoreWhitespace;
            this.ignorePIs = settings.IgnoreProcessingInstructions; 
            this.ignoreComments = settings.IgnoreComments;

            if (TokenTypeMap == null)
                GenerateTokenTypeMap(); 
        }
 
        public override XmlReaderSettings Settings { 
            get {
                XmlReaderSettings settings = new XmlReaderSettings(); 
                if (xntFromSettings) {
                    settings.NameTable = xnt;
                }
                // 0=>auto, 1=>doc/pre-dtd, 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem, 9=>frag 
                switch (this.docState) {
                    case 0: 
                        settings.ConformanceLevel = ConformanceLevel.Auto; break; 
                    case 9:
                        settings.ConformanceLevel = ConformanceLevel.Fragment; break; 
                    default:
                        settings.ConformanceLevel = ConformanceLevel.Document; break;
                }
                settings.CheckCharacters = this.checkCharacters; 
                settings.IgnoreWhitespace = this.ignoreWhitespace;
                settings.IgnoreProcessingInstructions = this.ignorePIs; 
                settings.IgnoreComments = this.ignoreComments; 
                settings.DtdProcessing = this.dtdProcessing;
                settings.CloseInput = this.closeInput; 

                settings.ReadOnly = true;
                return settings;
            } 
        }
 
        public override XmlNodeType NodeType { 
            get {
                return this.nodetype; 
            }
        }

        public override string LocalName { 
            get {
                return this.qnameOther.localname; 
            } 
        }
 
        public override string NamespaceURI {
            get {
                return this.qnameOther.namespaceUri;
            } 
        }
 
        public override string Prefix { 
            get {
                return this.qnameOther.prefix; 
            }
        }

        public override bool HasValue { 
            get {
                if (ScanState.XmlText == this.state) 
                    return this.textXmlReader.HasValue; 
                else
                    return XmlReader.HasValueInternal(this.nodetype); 
            }
        }

        public override string Value { 
            get {
                if (null != this.stringValue) 
                    return stringValue; 
                switch (this.state) {
                    case ScanState.Doc: 
                        switch (this.nodetype) {
                            case XmlNodeType.DocumentType:
                            case XmlNodeType.ProcessingInstruction:
                            case XmlNodeType.Comment: 
                                return this.stringValue = GetString(this.tokDataPos, this.tokLen);
 
                            case XmlNodeType.CDATA: 
                                return this.stringValue = CDATAValue();
 
                            case XmlNodeType.XmlDeclaration:
                                return this.stringValue = XmlDeclValue();

                            case XmlNodeType.Text: 
                            case XmlNodeType.Whitespace:
                            case XmlNodeType.SignificantWhitespace: 
                                return this.stringValue = ValueAsString(this.token); 
                        }
                        break; 

                    case ScanState.XmlText:
                        return this.textXmlReader.Value;
 
                    case ScanState.Attr:
                    case ScanState.AttrValPseudoValue: 
                        return this.stringValue = GetAttributeText(this.attrIndex - 1); 

                    case ScanState.AttrVal: 
                        return this.stringValue = ValueAsString(this.token);
                }
                return String.Empty;
            } 
        }
 
        public override int Depth { 
            get {
                int adj = 0; 
                switch (this.state) {
                    case ScanState.Doc:
                        if (this.nodetype == XmlNodeType.Element
                            || this.nodetype == XmlNodeType.EndElement) 
                            adj = -1;
                        break; 
 
                    case ScanState.XmlText:
                        adj = this.textXmlReader.Depth; 
                        break;

                    case ScanState.Attr:
                        if (this.parentNodeType != XmlNodeType.Element) 
                            adj = 1;
                        break; 
                    case ScanState.AttrVal: 
                    case ScanState.AttrValPseudoValue:
                        if (this.parentNodeType != XmlNodeType.Element) 
                            adj = 1;
                        adj += 1;
                        break;
                    default: 
                        return 0;
                } 
                return this.elemDepth + adj; 
            }
        } 

        public override string BaseURI {
            get {
                return this.baseUri; 
            }
        } 
 
        public override bool IsEmptyElement {
            get { 
                switch (this.state) {
                    case ScanState.Doc:
                    case ScanState.XmlText:
                        return this.isEmpty; 
                    default:
                        return false; 
                } 
            }
        } 

        public override XmlSpace XmlSpace {
            get {
                if (ScanState.XmlText != this.state) { 
                    for (int i = this.elemDepth; i >= 0; i--) {
                        XmlSpace xs = this.elementStack[i].xmlSpace; 
                        if (xs != XmlSpace.None) 
                            return xs;
                    } 
                    return XmlSpace.None;
                }
                else {
                    return this.textXmlReader.XmlSpace; 
                }
            } 
        } 

        public override string XmlLang { 
            get {
                if (ScanState.XmlText != this.state) {
                    for (int i = this.elemDepth; i >= 0; i--) {
                        string xl = this.elementStack[i].xmlLang; 
                        if (null != xl)
                            return xl; 
                    } 
                    return string.Empty;
                } 
                else {
                    return this.textXmlReader.XmlLang;
                }
            } 
        }
 
        public override System.Type ValueType { 
            get {
                return this.valueType; 
            }
        }

        public override int AttributeCount { 
            get {
                switch (this.state) { 
                    case ScanState.Doc: 
                    // for compatibility with XmlTextReader
                    //  we return the attribute count for the element 
                    //  when positioned on an attribute under that
                    //  element...
                    case ScanState.Attr:
                    case ScanState.AttrVal: 
                    case ScanState.AttrValPseudoValue:
                        return this.attrCount; 
                    case ScanState.XmlText: 
                        return this.textXmlReader.AttributeCount;
                    default: 
                        return 0;
                }
            }
        } 

        public override string GetAttribute(string name, string ns) { 
            if (ScanState.XmlText == this.state) { 
                return this.textXmlReader.GetAttribute(name, ns);
            } 
            else {
                if (null == name)
                    throw new ArgumentNullException("name");
                if (null == ns) 
                    ns = String.Empty;
                int index = LocateAttribute(name, ns); 
                if (-1 == index) 
                    return null;
                return GetAttribute(index); 
            }
        }

        public override string GetAttribute(string name) { 
            if (ScanState.XmlText == this.state) {
                return this.textXmlReader.GetAttribute(name); 
            } 
            else {
                int index = LocateAttribute(name); 
                if (-1 == index)
                    return null;
                return GetAttribute(index);
            } 
        }
 
        public override string GetAttribute(int i) { 
            if (ScanState.XmlText == this.state) {
                return this.textXmlReader.GetAttribute(i); 
            }
            else {
                if (i < 0 || i >= this.attrCount)
                    throw new ArgumentOutOfRangeException("i"); 
                return GetAttributeText(i);
            } 
        } 

        public override bool MoveToAttribute(string name, string ns) { 
            if (ScanState.XmlText == this.state) {
                return UpdateFromTextReader(this.textXmlReader.MoveToAttribute(name, ns));
            }
            else { 
                if (null == name)
                    throw new ArgumentNullException("name"); 
                if (null == ns) 
                    ns = String.Empty;
                int index = LocateAttribute(name, ns); 
                if ((-1 != index) && (this.state < ScanState.Init)) {
                    PositionOnAttribute(index + 1);
                    return true;
                } 
                return false;
            } 
        } 

        public override bool MoveToAttribute(string name) { 
            if (ScanState.XmlText == this.state) {
                return UpdateFromTextReader(this.textXmlReader.MoveToAttribute(name));
            }
            else { 
                int index = LocateAttribute(name);
                if ((-1 != index) && (this.state < ScanState.Init)) { 
                    PositionOnAttribute(index + 1); 
                    return true;
                } 
                return false;
            }
        }
 
        public override void MoveToAttribute(int i) {
            if (ScanState.XmlText == this.state) { 
                this.textXmlReader.MoveToAttribute(i); 
                UpdateFromTextReader(true);
            } 
            else {
                if (i < 0 || i >= this.attrCount) {
                    throw new ArgumentOutOfRangeException("i");
                } 
                PositionOnAttribute(i + 1);
            } 
        } 

        public override bool MoveToFirstAttribute() { 
            if (ScanState.XmlText == this.state) {
                return UpdateFromTextReader(this.textXmlReader.MoveToFirstAttribute());
            }
            else { 
                if (this.attrCount == 0)
                    return false; 
                // set up for walking attributes 
                PositionOnAttribute(1);
                return true; 
            }
        }

        public override bool MoveToNextAttribute() { 
            switch (this.state) {
                case ScanState.Doc: 
                case ScanState.Attr: 
                case ScanState.AttrVal:
                case ScanState.AttrValPseudoValue: 
                    if (this.attrIndex >= this.attrCount)
                        return false;
                    PositionOnAttribute(++this.attrIndex);
                    return true; 

                case ScanState.XmlText: 
                    return UpdateFromTextReader(this.textXmlReader.MoveToNextAttribute()); 

                default: 
                    return false;
            }
        }
 
        public override bool MoveToElement() {
            switch (this.state) { 
                case ScanState.Attr: 
                case ScanState.AttrVal:
                case ScanState.AttrValPseudoValue: 
                    this.attrIndex = 0;
                    this.qnameOther = this.qnameElement;
                    if (XmlNodeType.Element == this.parentNodeType)
                        this.token = BinXmlToken.Element; 
                    else if (XmlNodeType.XmlDeclaration == this.parentNodeType)
                        this.token = BinXmlToken.XmlDecl; 
                    else if (XmlNodeType.DocumentType == this.parentNodeType) 
                        this.token = BinXmlToken.DocType;
                    else 
                        Debug.Fail("Unexpected parent NodeType");
                    this.nodetype = this.parentNodeType;
                    this.state = ScanState.Doc;
                    this.pos = this.posAfterAttrs; 
                    this.stringValue = null;
                    return true; 
 
                case ScanState.XmlText:
                    return UpdateFromTextReader(this.textXmlReader.MoveToElement()); 

                default:
                    return false;
            } 
        }
 
        public override bool EOF { 
            get {
                return this.state == ScanState.EOF; 
            }
        }

        public override bool ReadAttributeValue() { 
            this.stringValue = null;
            switch (this.state) { 
                case ScanState.Attr: 
                    if (null == this.attributes[this.attrIndex - 1].val) {
                        this.pos = this.attributes[this.attrIndex - 1].contentPos; 
                        BinXmlToken tok = RescanNextToken();
                        if (BinXmlToken.Attr == tok || BinXmlToken.EndAttrs == tok) {
                            return false;
                        } 
                        this.token = tok;
                        ReScanOverValue(tok); 
                        this.valueType = GetValueType(tok); 
                        this.state = ScanState.AttrVal;
                    } 
                    else {
                        this.token = BinXmlToken.Error;
                        this.valueType = TypeOfString;
                        this.state = ScanState.AttrValPseudoValue; 
                    }
                    this.qnameOther.Clear(); 
                    this.nodetype = XmlNodeType.Text; 
                    return true;
 
                case ScanState.AttrVal:
                    return false;

                case ScanState.XmlText: 
                    return UpdateFromTextReader(this.textXmlReader.ReadAttributeValue());
 
                default: 
                    return false;
            } 
        }

        public override void Close() {
            this.state = ScanState.Closed; 
            this.nodetype = XmlNodeType.None;
            this.token = BinXmlToken.Error; 
            this.stringValue = null; 
            if (null != this.textXmlReader) {
                this.textXmlReader.Close(); 
                this.textXmlReader = null;
            }
            if (null != this.inStrm && closeInput)
                this.inStrm.Close(); 
            this.inStrm = null;
            this.pos = this.end = 0; 
        } 

        public override XmlNameTable NameTable { 
            get {
                return this.xnt;
            }
        } 

        public override string LookupNamespace(string prefix) { 
            if (ScanState.XmlText == this.state) 
                return this.textXmlReader.LookupNamespace(prefix);
            NamespaceDecl decl; 
            if (prefix != null && this.namespaces.TryGetValue(prefix, out decl)) {
                Debug.Assert(decl != null);
                return decl.uri;
            } 
            return null;
        } 
 
        public override void ResolveEntity() {
            throw new NotSupportedException(); 
        }

        public override ReadState ReadState {
            get { 
                return ScanState2ReadState[(int)this.state];
            } 
        } 

        public override bool Read() { 
            try {
                switch (this.state) {
                    case ScanState.Init:
                        return ReadInit(false); 

                    case ScanState.Doc: 
                        return ReadDoc(); 

                    case ScanState.XmlText: 
                        if (this.textXmlReader.Read()) {
                            return UpdateFromTextReader(true);
                        }
                        this.state = ScanState.Doc; 
                        this.nodetype = XmlNodeType.None;
                        this.isEmpty = false; 
                        goto case ScanState.Doc; 

                    case ScanState.Attr: 
                    case ScanState.AttrVal:
                    case ScanState.AttrValPseudoValue:
                        // clean up attribute stuff...
                        MoveToElement(); 
                        goto case ScanState.Doc;
 
                    default: 
                        return false;
                } 
            }
            catch (OverflowException e) {
                this.state = ScanState.Error;
                throw new XmlException(e.Message, e); 
            }
            catch { 
                this.state = ScanState.Error; 
                throw;
            } 
        }

        // Use default implementation of and ReadContentAsString and ReadElementContentAsString
        // (there is no benefit to providing a custom version) 
        // public override bool ReadElementContentAsString( string localName, string namespaceURI )
        // public override bool ReadElementContentAsString() 
        // public override bool ReadContentAsString() 

        // Do setup work for ReadContentAsXXX methods 
        // If ready for a typed value read, returns true, otherwise returns
        //  false to indicate caller should ball back to XmlReader.ReadContentAsXXX
        // Special-Case: returns true and positioned on Element or EndElem to force parse of empty-string
        private bool SetupContentAsXXX(string name) { 
            if (!CanReadContentAs(this.NodeType)) {
                throw CreateReadContentAsException(name); 
            } 
            switch (this.state) {
                case ScanState.Doc: 
                    if (this.NodeType == XmlNodeType.EndElement)
                        return true;
                    if (this.NodeType == XmlNodeType.ProcessingInstruction || this.NodeType == XmlNodeType.Comment) {
                        while (Read() && (this.NodeType == XmlNodeType.ProcessingInstruction || this.NodeType == XmlNodeType.Comment)) 
                            ;
                        if (this.NodeType == XmlNodeType.EndElement) 
                            return true; 
                    }
                    if (this.hasTypedValue) { 
                        return true;
                    }
                    break;
                case ScanState.Attr: 
                    this.pos = this.attributes[this.attrIndex - 1].contentPos;
                    BinXmlToken token = RescanNextToken(); 
                    if (BinXmlToken.Attr == token || BinXmlToken.EndAttrs == token) 
                        break;
                    this.token = token; 
                    ReScanOverValue(token);
                    return true;
                case ScanState.AttrVal:
                    return true; 
                default:
                    break; 
            } 
            return false;
        } 

        private int FinishContentAsXXX(int origPos) {
            if (this.state == ScanState.Doc) {
                // if we are already on a tag, then don't move 
                if (this.NodeType != XmlNodeType.Element && this.NodeType != XmlNodeType.EndElement) {
                // advance over PIs and Comments 
                Loop: 
                    if (Read()) {
                        switch (this.NodeType) { 
                            case XmlNodeType.ProcessingInstruction:
                            case XmlNodeType.Comment:
                                goto Loop;
 
                            case XmlNodeType.Element:
                            case XmlNodeType.EndElement: 
                                break; 

                            default: 
                                throw ThrowNotSupported(Res.XmlBinary_ListsOfValuesNotSupported);
                        }
                    }
                } 
                return this.pos;
            } 
            return origPos; 
        }
 
        public override bool ReadContentAsBoolean() {
            int origPos = this.pos;
            bool value = false;
            try { 
                if (SetupContentAsXXX("ReadContentAsBoolean")) {
                    try { 
                        switch (this.token) { 
                            case BinXmlToken.XSD_BOOLEAN:
                                value = 0 != this.data[this.tokDataPos]; 
                                break;

                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT: 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT: 
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY: 
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_KATMAI_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATETIME:
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_BYTE: 
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG: 
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Boolean"));

                            case BinXmlToken.SQL_CHAR: 
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT: 
                                goto Fallback;

                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem: 
                                return XmlConvert.ToBoolean(String.Empty);
 
                            default: 
                                Debug.Fail("should never happen");
                                goto Fallback; 
                        }
                    }
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, null); 
                    }
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, null); 
                    }
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                }
            }
            finally { 
                this.pos = origPos;
            } 
        Fallback: 
            return base.ReadContentAsBoolean();
        } 

        public override DateTime ReadContentAsDateTime() {
            int origPos = this.pos;
            DateTime value; 
            try {
                if (SetupContentAsXXX("ReadContentAsDateTime")) { 
                    try { 
                        switch (this.token) {
                            case BinXmlToken.SQL_DATETIME: 
                            case BinXmlToken.SQL_SMALLDATETIME:
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME:
                            case BinXmlToken.XSD_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                                value = ValueAsDateTime();
                                break;
 
                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT: 
                            case BinXmlToken.SQL_INT:
                            case BinXmlToken.SQL_BIGINT: 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY: 
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_BINHEX: 
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_BYTE: 
                            case BinXmlToken.XSD_UNSIGNEDSHORT:
                            case BinXmlToken.XSD_UNSIGNEDINT: 
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "DateTime"));
 
                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR: 
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR:
                            case BinXmlToken.SQL_NVARCHAR: 
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback;

                            case BinXmlToken.Element: 
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToDateTime(String.Empty, XmlDateTimeSerializationMode.RoundtripKind); 
 
                            default:
                                Debug.Fail("should never happen"); 
                                goto Fallback;
                        }
                    }
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, null);
                    } 
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, null);
                    } 
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, null);
                    }
 
                    origPos = FinishContentAsXXX(origPos);
                    return value; 
                } 
            }
            finally { 
                this.pos = origPos;
            }
        Fallback:
            return base.ReadContentAsDateTime(); 
        }
 
        public override Double ReadContentAsDouble() { 
            int origPos = this.pos;
            Double value; 
            try {
                if (SetupContentAsXXX("ReadContentAsDouble")) {
                    try {
                        switch (this.token) { 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT: 
                                value = ValueAsDouble(); 
                                break;
 
                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT:
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY: 
                            case BinXmlToken.SQL_SMALLMONEY: 
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC:
                            case BinXmlToken.XSD_DECIMAL:
                            case BinXmlToken.SQL_UUID: 
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY: 
                            case BinXmlToken.SQL_IMAGE: 
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_KATMAI_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATETIME:
                            case BinXmlToken.XSD_KATMAI_TIME:
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX: 
                            case BinXmlToken.XSD_BASE64: 
                            case BinXmlToken.XSD_BOOLEAN:
                            case BinXmlToken.XSD_TIME: 
                            case BinXmlToken.XSD_DATETIME:
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG: 
                            case BinXmlToken.XSD_QNAME: 
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Double"));
 
                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT:
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT: 
                                goto Fallback; 

                            case BinXmlToken.Element: 
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToDouble(String.Empty);

                            default: 
                                Debug.Fail("should never happen");
                                goto Fallback; 
                        } 
                    }
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, null);
                    }
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, null); 
                    }
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, null); 
                    }
 
                    origPos = FinishContentAsXXX(origPos);
                    return value;
                }
            } 
            finally {
                this.pos = origPos; 
            } 
        Fallback:
            return base.ReadContentAsDouble(); 
        }

        public override float ReadContentAsFloat() {
            int origPos = this.pos; 
            float value;
            try { 
                if (SetupContentAsXXX("ReadContentAsFloat")) { 
                    try {
                        switch (this.token) { 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT:
                                value = checked (((float)ValueAsDouble()));
                                break; 

                            case BinXmlToken.SQL_BIT: 
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DATETIME: 
                            case BinXmlToken.SQL_SMALLDATETIME:
                            case BinXmlToken.SQL_DECIMAL: 
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL:
                            case BinXmlToken.SQL_UUID: 
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE: 
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Float")); 

                            case BinXmlToken.SQL_CHAR: 
                            case BinXmlToken.SQL_VARCHAR: 
                            case BinXmlToken.SQL_TEXT:
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback;
 
                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem: 
                                return XmlConvert.ToSingle(String.Empty); 

                            default: 
                                Debug.Fail("should never happen");
                                goto Fallback;
                        }
                    } 
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, null); 
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, null); 
                    }
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, null);
                    } 

                    origPos = FinishContentAsXXX(origPos); 
                    return value; 
                }
            } 
            finally {
                this.pos = origPos;
            }
        Fallback: 
            return base.ReadContentAsFloat();
        } 
 
        public override decimal ReadContentAsDecimal() {
            int origPos = this.pos; 
            decimal value;
            try {
                if (SetupContentAsXXX("ReadContentAsDecimal")) {
                    try { 
                        switch (this.token) {
                            case BinXmlToken.SQL_BIT: 
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DECIMAL: 
                            case BinXmlToken.SQL_NUMERIC:
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.XSD_BYTE: 
                            case BinXmlToken.XSD_UNSIGNEDSHORT:
                            case BinXmlToken.XSD_UNSIGNEDINT: 
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                                value = ValueAsDecimal();
                                break;
 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT: 
                            case BinXmlToken.SQL_DATETIME: 
                            case BinXmlToken.SQL_SMALLDATETIME:
                            case BinXmlToken.SQL_UUID: 
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE: 
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Decimal")); 

                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR:
                            case BinXmlToken.SQL_NVARCHAR: 
                            case BinXmlToken.SQL_NTEXT: 
                                goto Fallback;
 
                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToDecimal(String.Empty);
 
                            default:
                                Debug.Fail("should never happen"); 
                                goto Fallback; 
                        }
                    } 
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, null);
                    }
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, null);
                    } 
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, null);
                    } 

                    origPos = FinishContentAsXXX(origPos);
                    return value;
                } 
            }
            finally { 
                this.pos = origPos; 
            }
        Fallback: 
            return base.ReadContentAsDecimal();
        }

        public override int ReadContentAsInt() { 
            int origPos = this.pos;
            int value; 
            try { 
                if (SetupContentAsXXX("ReadContentAsInt")) {
                    try { 
                        switch (this.token) {
                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT:
                            case BinXmlToken.SQL_SMALLINT: 
                            case BinXmlToken.SQL_INT:
                            case BinXmlToken.SQL_BIGINT: 
                            case BinXmlToken.SQL_MONEY: 
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DECIMAL: 
                            case BinXmlToken.SQL_NUMERIC:
                            case BinXmlToken.XSD_DECIMAL:
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG: 
                                value = checked((int)ValueAsLong()); 
                                break;
 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT:
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY: 
                            case BinXmlToken.SQL_BINARY: 
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME:
                            case BinXmlToken.XSD_KATMAI_TIME:
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                            case BinXmlToken.XSD_BINHEX: 
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME:
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_QNAME: 
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Int32"));
 
                            case BinXmlToken.SQL_CHAR: 
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR:
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback; 

                            case BinXmlToken.Element: 
                            case BinXmlToken.EndElem: 
                                return XmlConvert.ToInt32(String.Empty);
 
                            default:
                                Debug.Fail("should never happen");
                                goto Fallback;
                        } 
                    }
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int32", e, null); 
                    }
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int32", e, null);
                    }
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int32", e, null); 
                    }
 
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                } 
            }
            finally {
                this.pos = origPos;
            } 
        Fallback:
            return base.ReadContentAsInt(); 
        } 

        public override long ReadContentAsLong() { 
            int origPos = this.pos;
            long value;
            try {
                if (SetupContentAsXXX("ReadContentAsLong")) { 
                    try {
                        switch (this.token) { 
                            case BinXmlToken.SQL_BIT: 
                            case BinXmlToken.SQL_TINYINT:
                            case BinXmlToken.SQL_SMALLINT: 
                            case BinXmlToken.SQL_INT:
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                                value = ValueAsLong();
                                break; 

                            case BinXmlToken.SQL_REAL: 
                            case BinXmlToken.SQL_FLOAT: 
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE: 
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_KATMAI_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME:
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64: 
                            case BinXmlToken.XSD_BOOLEAN:
                            case BinXmlToken.XSD_TIME: 
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_QNAME: 
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Int64"));

                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR: 
                            case BinXmlToken.SQL_TEXT:
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR: 
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback; 

                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToInt64(String.Empty); 

                            default: 
                                Debug.Fail("should never happen"); 
                                goto Fallback;
                        } 
                    }
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int64", e, null);
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int64", e, null); 
                    } 
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int64", e, null); 
                    }

                    origPos = FinishContentAsXXX(origPos);
                    return value; 
                }
            } 
            finally { 
                this.pos = origPos;
            } 
        Fallback:
            return base.ReadContentAsLong();
        }
 
        public override object ReadContentAsObject() {
            int origPos = this.pos; 
            try { 
                if (SetupContentAsXXX("ReadContentAsObject")) {
                    object value; 
                    try {
                        if (this.NodeType == XmlNodeType.Element || this.NodeType == XmlNodeType.EndElement)
                            value = String.Empty;
                        else 
                            value = this.ValueAsObject(this.token, false);
                    } 
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Object", e, null);
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Object", e, null);
                    }
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Object", e, null);
                    } 
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                } 
            }
            finally {
                this.pos = origPos;
            } 
            //Fallback:
            return base.ReadContentAsObject(); 
        } 

        public override object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) { 
            int origPos = this.pos;
            try {
                if (SetupContentAsXXX("ReadContentAs")) {
                    object value; 
                    try {
                        if (this.NodeType == XmlNodeType.Element || this.NodeType == XmlNodeType.EndElement) { 
                            value = String.Empty; 
                        }
                        else if (returnType == this.ValueType || returnType == typeof(object)) { 
                            value = this.ValueAsObject(this.token, false);
                        }
                        else {
                            value = this.ValueAs(this.token, returnType, namespaceResolver); 
                        }
                    } 
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, null);
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, null);
                    }
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, null);
                    } 
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                } 
            }
            finally {
                this.pos = origPos;
            } 
            return base.ReadContentAs(returnType, namespaceResolver);
        } 
 
        //////////
        // IXmlNamespaceResolver 

        System.Collections.Generic.IDictionary IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) {
            if (ScanState.XmlText == this.state) {
                IXmlNamespaceResolver resolver = (IXmlNamespaceResolver)this.textXmlReader; 
                return resolver.GetNamespacesInScope(scope);
            } 
            else { 
                Dictionary nstable = new Dictionary();
                if (XmlNamespaceScope.Local == scope) { 
                    // are we even inside an element? (depth==0 is where we have xml, and xmlns declared...)
                    if (this.elemDepth > 0) {
                        NamespaceDecl nsdecl = this.elementStack[this.elemDepth].nsdecls;
                        while (null != nsdecl) { 
                            nstable.Add(nsdecl.prefix, nsdecl.uri);
                            nsdecl = nsdecl.scopeLink; 
                        } 
                    }
                } 
                else {
                    foreach (NamespaceDecl nsdecl in this.namespaces.Values) {
                        // don't add predefined decls unless scope == all, then only add 'xml'
                        if (nsdecl.scope != -1 || (XmlNamespaceScope.All == scope && "xml" == nsdecl.prefix)) { 
                            // xmlns="" only ever reported via scope==local
                            if (nsdecl.prefix.Length > 0 || nsdecl.uri.Length > 0) 
                                nstable.Add(nsdecl.prefix, nsdecl.uri); 
                        }
                    } 
                }
                return nstable;
            }
        } 

        string IXmlNamespaceResolver.LookupPrefix(string namespaceName) { 
            if (ScanState.XmlText == this.state) { 
                IXmlNamespaceResolver resolver = (IXmlNamespaceResolver)this.textXmlReader;
                return resolver.LookupPrefix(namespaceName); 
            }
            else {
                if (null == namespaceName)
                    return null; 

                namespaceName = this.xnt.Get(namespaceName); 
                if (null == namespaceName) 
                    return null;
 
                for (int i = this.elemDepth; i >= 0; i--) {
                    NamespaceDecl nsdecl = this.elementStack[i].nsdecls;
                    while (null != nsdecl) {
                        if ((object)nsdecl.uri == (object)namespaceName) 
                            return nsdecl.prefix;
                        nsdecl = nsdecl.scopeLink; 
                    } 
                }
                return null; 
            }
        }

        ////////// 
        // Internal implementation methods
 
        void VerifyVersion(int requiredVersion, BinXmlToken token) { 
            if (version < requiredVersion) {
                throw ThrowUnexpectedToken(token); 
            }
        }

        void AddInitNamespace(string prefix, string uri) { 
            NamespaceDecl nsdecl = new NamespaceDecl(prefix, uri, this.elementStack[0].nsdecls, null, -1, true);
            this.elementStack[0].nsdecls = nsdecl; 
            this.namespaces.Add(prefix, nsdecl); 
        }
 
        void AddName() {
            string txt = ParseText();
            int symNum = this.symbolTables.symCount++;
            string[] symtable = this.symbolTables.symtable; 
            if (symNum == symtable.Length) {
                string[] n = new string[checked(symNum * 2)]; 
                System.Array.Copy(symtable, 0, n, 0, symNum); 
                this.symbolTables.symtable = symtable = n;
            } 
            symtable[symNum] = xnt.Add(txt);
        }

        void AddQName() { 
            int nsUri = ReadNameRef();
            int prefix = ReadNameRef(); 
            int lname = ReadNameRef(); 
            int qnameNum = this.symbolTables.qnameCount++;
            QName[] qnametable = this.symbolTables.qnametable; 
            if (qnameNum == qnametable.Length) {
                QName[] n = new QName[checked(qnameNum * 2)];
                System.Array.Copy(qnametable, 0, n, 0, qnameNum);
                this.symbolTables.qnametable = qnametable = n; 
            }
            string[] symtable = this.symbolTables.symtable; 
            string prefixStr = symtable[prefix]; 
            string lnameStr;
            string nsUriStr; 
            // xmlns attributes are encodes differently...
            if (lname == 0) { // xmlns attribute
                // for some reason, sqlserver sometimes generates these...
                if (prefix == 0 && nsUri == 0) 
                    return;
                // it is a real namespace decl, make sure it looks valid 
                if (!prefixStr.StartsWith("xmlns", StringComparison.Ordinal)) 
                    goto BadDecl;
                if (5 < prefixStr.Length) { 
                    if (6 == prefixStr.Length || ':' != prefixStr[5])
                        goto BadDecl;
                    lnameStr = this.xnt.Add(prefixStr.Substring(6));
                    prefixStr = this.xmlns; 
                }
                else { 
                    lnameStr = prefixStr; 
                    prefixStr = String.Empty;
                } 
                nsUriStr = this.nsxmlns;
            }
            else {
                lnameStr = symtable[lname]; 
                nsUriStr = symtable[nsUri];
            } 
            qnametable[qnameNum].Set(prefixStr, lnameStr, nsUriStr); 
            return;
        BadDecl: 
            throw new XmlException(Res.Xml_BadNamespaceDecl, (string[])null);
        }

        private void NameFlush() { 
            this.symbolTables.symCount = this.symbolTables.qnameCount = 1;
            Array.Clear(this.symbolTables.symtable, 1, this.symbolTables.symtable.Length - 1); 
            Array.Clear(this.symbolTables.qnametable, 0, this.symbolTables.qnametable.Length); 
        }
 
        private void SkipExtn() {
            int cb = ParseMB32();
            checked{this.pos += cb;}
            Fill(-1); 
        }
 
        private int ReadQNameRef() { 
            int nameNum = ParseMB32();
            if (nameNum < 0 || nameNum >= this.symbolTables.qnameCount) 
                throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
            return nameNum;
        }
 
        private int ReadNameRef() {
            int nameNum = ParseMB32(); 
            if (nameNum < 0 || nameNum >= this.symbolTables.symCount) 
                throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
            return nameNum; 
        }

        // pull more data from input stream
        private bool FillAllowEOF() { 
            if (this.eof)
                return false; 
            byte[] data = this.data; 
            int pos = this.pos;
            int mark = this.mark; 
            int end = this.end;
            if (mark == -1) {
                mark = pos;
            } 
            if (mark >= 0 && mark < end) {
                Debug.Assert(this.mark <= this.end, "Mark should never be past End"); 
                Debug.Assert(this.mark <= this.pos, "Mark should never be after Pos"); 
                int cbKeep = end - mark;
                if (cbKeep > 7 * (data.Length / 8)) { 
                    // grow buffer
                    byte[] newdata = new byte[checked(data.Length * 2)];
                    System.Array.Copy(data, mark, newdata, 0, cbKeep);
                    this.data = data = newdata; 
                }
                else { 
                    System.Array.Copy(data, mark, data, 0, cbKeep); 
                }
                pos -= mark; 
                end -= mark;
                this.tokDataPos -= mark;
                for (int i = 0; i < this.attrCount; i++) {
                    this.attributes[i].AdjustPosition(-mark); 
                    // make sure it is still a valid range
                    Debug.Assert((this.attributes[i].contentPos >= 0) && (this.attributes[i].contentPos <= (end))); 
                } 
                this.pos = pos;
                this.mark = 0; 
                this.offset += mark;
            }
            else {
                Debug.Assert(this.attrCount == 0); 
                this.pos -= end;
                this.mark -= end; 
                this.offset += end; 
                this.tokDataPos -= end;
                end = 0; 
            }
            int cbFill = data.Length - end;
            int cbRead = this.inStrm.Read(data, end, cbFill);
            this.end = end + cbRead; 
            this.eof = !(cbRead > 0);
            return (cbRead > 0); 
        } 

        // require must be < 1/8 buffer, or else Fill might not actually 
        // grab that much data
        void Fill_(int require) {
            Debug.Assert((this.pos + require) >= this.end);
            while (FillAllowEOF() && ((this.pos + require) >= this.end)) 
                ;
            if ((this.pos + require) >= this.end) 
                throw ThrowXmlException(Res.Xml_UnexpectedEOF1); 
        }
 
        // inline the common case
        void Fill(int require) {
            if ((this.pos + require) >= this.end)
                Fill_(require); 
        }
 
        byte ReadByte() { 
            Fill(0);
            return this.data[this.pos++]; 
        }
        ushort ReadUShort() {
            Fill(1);
            int pos = this.pos; byte[] data = this.data; 
            ushort val = (ushort)(data[pos] + (data[pos + 1] << 8));
            this.pos += 2; 
            return val; 
        }
 
        int ParseMB32() {
            byte b = ReadByte();
            if (b > 127)
                return ParseMB32_(b); 
            return b;
        } 
 
        int ParseMB32_(byte b) {
            uint u, t; 
            u = (uint)b & (uint)0x7F;
            Debug.Assert(0 != (b & 0x80));
            b = ReadByte();
            t = (uint)b & (uint)0x7F; 
            u = u + (t << 7);
            if (b > 127) { 
                b = ReadByte(); 
                t = (uint)b & (uint)0x7F;
                u = u + (t << 14); 
                if (b > 127) {
                    b = ReadByte();
                    t = (uint)b & (uint)0x7F;
                    u = u + (t << 21); 
                    if (b > 127) {
                        b = ReadByte(); 
                        // bottom 4 bits are all that are needed, 
                        // but we are mapping to 'int', which only
                        // actually has space for 3 more bits. 
                        t = (uint)b & (uint)0x07;
                        if (b > 7)
                            throw ThrowXmlException(Res.XmlBinary_ValueTooBig);
                        u = u + (t << 28); 
                    }
                } 
            } 
            return (int)u;
        } 

        // this assumes that we have already ensured that all
        // necessary bytes are loaded in to the buffer
        int ParseMB32(int pos) { 
            uint u, t;
            byte[] data = this.data; 
            byte b = data[pos++]; 
            u = (uint)b & (uint)0x7F;
            if (b > 127) { 
                b = data[pos++];
                t = (uint)b & (uint)0x7F;
                u = u + (t << 7);
                if (b > 127) { 
                    b = data[pos++];
                    t = (uint)b & (uint)0x7F; 
                    u = u + (t << 14); 
                    if (b > 127) {
                        b = data[pos++]; 
                        t = (uint)b & (uint)0x7F;
                        u = u + (t << 21);
                        if (b > 127) {
                            b = data[pos++]; 
                            // last byte only has 4 significant digits
                            t = (uint)b & (uint)0x07; 
                            if (b > 7) 
                                throw ThrowXmlException(Res.XmlBinary_ValueTooBig);
                            u = u + (t << 28); 
                        }
                    }
                }
            } 
            return (int)u;
        } 
 
        // we don't actually support MB64, since we use int for
        // all our math anyway... 
        int ParseMB64() {
            byte b = ReadByte();
            if (b > 127)
                return ParseMB32_(b); 
            return b;
        } 
 
        BinXmlToken PeekToken() {
            while ((this.pos >= this.end) && FillAllowEOF()) 
                ;
            if (this.pos >= this.end)
                return BinXmlToken.EOF;
            return (BinXmlToken)this.data[this.pos]; 
        }
 
        BinXmlToken ReadToken() { 
            while ((this.pos >= this.end) && FillAllowEOF())
                ; 
            if (this.pos >= this.end)
                return BinXmlToken.EOF;
            return (BinXmlToken)this.data[this.pos++];
        } 

        BinXmlToken NextToken2(BinXmlToken token) { 
            while (true) { 
                switch (token) {
                    case BinXmlToken.Name: 
                        AddName();
                        break;
                    case BinXmlToken.QName:
                        AddQName(); 
                        break;
                    case BinXmlToken.NmFlush: 
                        NameFlush(); 
                        break;
                    case BinXmlToken.Extn: 
                        SkipExtn();
                        break;
                    default:
                        return token; 
                }
                token = ReadToken(); 
            } 
        }
 
        BinXmlToken NextToken1() {
            BinXmlToken token;
            int pos = this.pos;
            if (pos >= this.end) 
                token = ReadToken();
            else { 
                token = (BinXmlToken)this.data[pos]; 
                this.pos = pos + 1;
            } 
            // BinXmlToken.Name = 0xF0
            // BinXmlToken.QName = 0xEF
            // BinXmlToken.Extn = 0xEA,
            // BinXmlToken.NmFlush = 0xE9, 
            if (token >= BinXmlToken.NmFlush
                && token <= BinXmlToken.Name) 
                return NextToken2(token); 
            return token;
        } 

        BinXmlToken NextToken() {
            int pos = this.pos;
            if (pos < this.end) { 
                BinXmlToken t = (BinXmlToken)this.data[pos];
                if (!(t >= BinXmlToken.NmFlush && t <= BinXmlToken.Name)) { 
                    this.pos = pos + 1; 
                    return t;
                } 
            }
            return NextToken1();
        }
 
        // peek next non-meta token
        BinXmlToken PeekNextToken() { 
            BinXmlToken token = NextToken(); 
            if (BinXmlToken.EOF != token)
                this.pos--; 
            return token;
        }

        // like NextToken() but meta-tokens are skipped (not reinterpreted) 
        BinXmlToken RescanNextToken() {
            BinXmlToken token; 
            while (true) { 
                token = ReadToken();
                switch (token) { 
                    case BinXmlToken.Name: {
                            int cb = ParseMB32();
                            checked{this.pos += 2 * cb;}
                            break; 
                        }
                    case BinXmlToken.QName: 
                        ParseMB32(); 
                        ParseMB32();
                        ParseMB32(); 
                        break;
                    case BinXmlToken.Extn: {
                            int cb = ParseMB32();
                            checked{this.pos += cb;} 
                            break;
                        } 
                    case BinXmlToken.NmFlush: 
                        break;
                    default: 
                        return token;
                }
            }
        } 

        string ParseText() { 
            int oldmark = this.mark; 
            try {
                if (oldmark < 0) 
                    this.mark = this.pos;
                int cch, pos;
                cch = ScanText(out pos);
                return GetString(pos, cch); 
            }
            finally { 
                if (oldmark < 0) 
                    this.mark = -1;
            } 
        }

        int ScanText(out int start) {
            int cch = ParseMB32(); 
            int oldmark = this.mark;
            int begin = this.pos; 
            checked{this.pos += cch * 2;} // cch = num utf-16 chars 
            if (this.pos > this.end)
                Fill(-1); 
            // Fill call might have moved buffer
            start = begin - (oldmark - this.mark);
            return cch;
        } 

        string GetString(int pos, int cch) { 
            Debug.Assert(pos >= 0 && cch >= 0); 
            if (checked(pos + (cch * 2)) > this.end)
                throw new XmlException(Res.Xml_UnexpectedEOF1, (string[])null); 
            if (cch == 0)
                return String.Empty;
            // GetStringUnaligned is _significantly_ faster than unicode.GetString()
            // but since IA64 doesn't support unaligned reads, we can't do it if 
            // the address is not aligned properly.  Since the byte[] will be aligned,
            // we can detect address alignment my just looking at the offset 
            if ((pos & 1) == 0) 
                return GetStringAligned(this.data, pos, cch);
            else 
                return unicode.GetString(this.data, pos, checked(cch * 2));
        }

        unsafe String GetStringAligned(byte[] data, int offset, int cch) { 
            Debug.Assert((offset & 1) == 0);
            fixed (byte* pb = data) { 
                char* p = (char*)(pb + offset); 
                return new String(p, 0, cch);
            } 
        }

        private string GetAttributeText(int i) {
            string val = this.attributes[i].val; 

            if (null != val) 
                return val; 
            else {
                int origPos = this.pos; 
                try {
                    this.pos = this.attributes[i].contentPos;
                    BinXmlToken token = RescanNextToken();
                    if (BinXmlToken.Attr == token || BinXmlToken.EndAttrs == token) { 
                        return "";
                    } 
                    this.token = token; 
                    ReScanOverValue(token);
                    return ValueAsString(token); 
                }
                finally {
                    this.pos = origPos;
                } 
            }
        } 
 
        private int LocateAttribute(string name, string ns) {
            for (int i = 0; i < this.attrCount; i++) { 
                if (this.attributes[i].name.MatchNs(name, ns))
                    return i;
            }
 
            return -1;
        } 
 
        private int LocateAttribute(string name) {
            string prefix, lname; 
            ValidateNames.SplitQName(name, out prefix, out lname);

            for (int i = 0; i < this.attrCount; i++) {
                if (this.attributes[i].name.MatchPrefix(prefix, lname)) 
                    return i;
            } 
 
            return -1;
        } 

        private void PositionOnAttribute(int i) {
            // save element's qname
            this.attrIndex = i; 
            this.qnameOther = this.attributes[i - 1].name;
            if (this.state == ScanState.Doc) { 
                this.parentNodeType = this.nodetype; 
            }
            this.token = BinXmlToken.Attr; 
            this.nodetype = XmlNodeType.Attribute;
            this.state = ScanState.Attr;
            this.valueType = TypeOfObject;
            this.stringValue = null; 
        }
 
        void GrowElements() { 
            int newcount = this.elementStack.Length * 2;
            ElemInfo[] n = new ElemInfo[newcount]; 

            System.Array.Copy(this.elementStack, 0, n, 0, this.elementStack.Length);
            this.elementStack = n;
        } 

        void GrowAttributes() { 
            int newcount = this.attributes.Length * 2; 
            AttrInfo[] n = new AttrInfo[newcount];
 
            System.Array.Copy(this.attributes, 0, n, 0, this.attrCount);
            this.attributes = n;
        }
 
        void ClearAttributes() {
            if (this.attrCount != 0) 
                this.attrCount = 0; 
        }
 
        void PushNamespace(string prefix, string ns, bool implied) {
            if (prefix == "xml")
                return;
            int elemDepth = this.elemDepth; 
            NamespaceDecl curDecl;
            this.namespaces.TryGetValue(prefix, out curDecl); 
            if (null != curDecl) { 
                if (curDecl.uri == ns) {
                    // if we see the nsdecl after we saw the first reference in this scope 
                    // fix up 'implied' flag
                    if (!implied && curDecl.implied
                        && (curDecl.scope == elemDepth)) {
                        curDecl.implied = false; 
                    }
                    return; 
                } 
                // check that this doesn't conflict
                this.qnameElement.CheckPrefixNS(prefix, ns); 
                if (prefix.Length != 0) {
                    for (int i = 0; i < this.attrCount; i++) {
                        if (this.attributes[i].name.prefix.Length != 0)
                            this.attributes[i].name.CheckPrefixNS(prefix, ns); 
                    }
                } 
            } 
            // actually add ns decl
            NamespaceDecl decl = new NamespaceDecl(prefix, ns, 
                this.elementStack[elemDepth].nsdecls,
                curDecl, elemDepth, implied);
            this.elementStack[elemDepth].nsdecls = decl;
            this.namespaces[prefix] = decl; 
        }
 
        void PopNamespaces(NamespaceDecl firstInScopeChain) { 
            NamespaceDecl decl = firstInScopeChain;
            while (null != decl) { 
                if (null == decl.prevLink)
                    this.namespaces.Remove(decl.prefix);
                else
                    this.namespaces[decl.prefix] = decl.prevLink; 
                NamespaceDecl next = decl.scopeLink;
                // unlink chains for better gc behaviour 
                decl.prevLink = null; 
                decl.scopeLink = null;
                decl = next; 
            }
        }

        void GenerateImpliedXmlnsAttrs() { 
            QName name;
            NamespaceDecl decl = this.elementStack[this.elemDepth].nsdecls; 
            while (null != decl) { 
                if (decl.implied) {
                    if (this.attrCount == this.attributes.Length) 
                        GrowAttributes();
                    if (decl.prefix.Length == 0)
                        name = new QName(string.Empty, this.xmlns, this.nsxmlns);
                    else 
                        name = new QName(this.xmlns, xnt.Add(decl.prefix), this.nsxmlns);
                    this.attributes[this.attrCount].Set(name, decl.uri); 
                    this.attrCount++; 
                }
                decl = decl.scopeLink; 
            }
        }

        bool ReadInit(bool skipXmlDecl) { 
            string err = null;
            if (!sniffed) { 
                // check magic header 
                ushort magic = ReadUShort();
                if (magic != 0xFFDF) { 
                    err = Res.XmlBinary_InvalidSignature;
                    goto Error;
                }
            } 

            // check protocol version 
            this.version = ReadByte(); 
            if (version != 0x1 && version != 0x2) {
                err = Res.XmlBinary_InvalidProtocolVersion; 
                goto Error;
            }

            // check encoding marker, 1200 == utf16 
            if (1200 != ReadUShort()) {
                err = Res.XmlBinary_UnsupportedCodePage; 
                goto Error; 
            }
 
            this.state = ScanState.Doc;
            if (BinXmlToken.XmlDecl == PeekToken()) {
                this.pos++;
                this.attributes[0].Set(new QName(string.Empty, this.xnt.Add("version"), string.Empty), ParseText()); 
                this.attrCount = 1;
                if (BinXmlToken.Encoding == PeekToken()) { 
                    this.pos++; 
                    this.attributes[1].Set(new QName(string.Empty, this.xnt.Add("encoding"), string.Empty), ParseText());
                    this.attrCount++; 
                }

                byte standalone = ReadByte();
                switch (standalone) { 
                    case 0:
                        break; 
                    case 1: 
                    case 2:
                        this.attributes[this.attrCount].Set(new QName(string.Empty, this.xnt.Add("standalone"), string.Empty), (standalone == 1) ? "yes" : "no"); 
                        this.attrCount++;
                        break;
                    default:
                        err = Res.XmlBinary_InvalidStandalone; 
                        goto Error;
                } 
                if (!skipXmlDecl) { 
                    QName xmlDeclQName = new QName(String.Empty, this.xnt.Add("xml"), String.Empty);
                    this.qnameOther = this.qnameElement = xmlDeclQName; 
                    this.nodetype = XmlNodeType.XmlDeclaration;
                    this.posAfterAttrs = this.pos;
                    return true;
                } 
                // else ReadDoc will clear the attributes for us
            } 
            return ReadDoc(); 

        Error: 
            this.state = ScanState.Error;
            throw new XmlException(err, (string[])null);
        }
 
        void ScanAttributes() {
            BinXmlToken token; 
            int xmlspace = -1; 
            int xmllang = -1;
 
            this.mark = this.pos;
            string curDeclPrefix = null;
            bool lastWasValue = false;
 
            while (BinXmlToken.EndAttrs != (token = NextToken())) {
                if (BinXmlToken.Attr == token) { 
                    // watch out for nsdecl with no actual content 
                    if (null != curDeclPrefix) {
                        PushNamespace(curDeclPrefix, string.Empty, false); 
                        curDeclPrefix = null;
                    }
                    // do we need to grow the array?
                    if (this.attrCount == this.attributes.Length) 
                        GrowAttributes();
                    // note: ParseMB32 _must_ happen _before_ we grab this.pos... 
                    QName n = this.symbolTables.qnametable[ReadQNameRef()]; 
                    this.attributes[this.attrCount].Set(n, (int)this.pos);
                    if (n.prefix == "xml") { 
                        if (n.localname == "lang") {
                            xmllang = this.attrCount;
                        }
                        else if (n.localname == "space") { 
                            xmlspace = this.attrCount;
                        } 
                    } 
                    else if (Ref.Equal(n.namespaceUri, this.nsxmlns)) {
                        // push namespace when we get the value 
                        curDeclPrefix = n.localname;
                        if (curDeclPrefix == "xmlns")
                            curDeclPrefix = string.Empty;
                    } 
                    else if (n.prefix.Length != 0) {
                        if (n.namespaceUri.Length == 0) 
                            throw new XmlException(Res.Xml_PrefixForEmptyNs, String.Empty); 
                        this.PushNamespace(n.prefix, n.namespaceUri, true);
                    } 
                    else if (n.namespaceUri.Length != 0) {
                        throw ThrowXmlException(Res.XmlBinary_AttrWithNsNoPrefix, n.localname, n.namespaceUri);
                    }
                    this.attrCount++; 
                    lastWasValue = false;
                } 
                else { 
                    // first scan over token to make sure it is a value token
                    ScanOverValue(token, true, true); 
                    // don't allow lists of values
                    if (lastWasValue) {
                        throw ThrowNotSupported(Res.XmlBinary_ListsOfValuesNotSupported);
                    } 

                    // if char checking is on, we need to scan text values to 
                    // validate that they don't use invalid CharData, so we 
                    // might as well store the saved string for quick attr value access
                    string val = this.stringValue; 
                    if (null != val) {
                        this.attributes[this.attrCount - 1].val = val;
                        this.stringValue = null;
                    } 
                    // namespace decls can only have text values, and should only
                    // have a single value, so we just grab it here... 
                    if (null != curDeclPrefix) { 
                        string nsuri = this.xnt.Add(ValueAsString(token));
                        PushNamespace(curDeclPrefix, nsuri, false); 
                        curDeclPrefix = null;
                    }
                    lastWasValue = true;
                } 
            }
 
            if (xmlspace != -1) { 
                string val = GetAttributeText(xmlspace);
                XmlSpace xs = XmlSpace.None; 
                if (val == "preserve")
                    xs = XmlSpace.Preserve;
                else if (val == "default")
                    xs = XmlSpace.Default; 
                this.elementStack[this.elemDepth].xmlSpace = xs;
                this.xmlspacePreserve = (XmlSpace.Preserve == xs); 
            } 
            if (xmllang != -1) {
                this.elementStack[this.elemDepth].xmlLang = GetAttributeText(xmllang); 
            }

            if (this.attrCount < 200)
                SimpleCheckForDuplicateAttributes(); 
            else
                HashCheckForDuplicateAttributes(); 
        } 

        void SimpleCheckForDuplicateAttributes() { 
            for (int i = 0; i < this.attrCount; i++) {
                string localname, namespaceUri;
                this.attributes[i].GetLocalnameAndNamespaceUri(out localname, out namespaceUri);
                for (int j = i + 1; j < this.attrCount; j++) { 
                    if (this.attributes[j].MatchNS(localname, namespaceUri))
                        throw new XmlException(Res.Xml_DupAttributeName, this.attributes[i].name.ToString()); 
                } 
            }
        } 

        void HashCheckForDuplicateAttributes() {
            int tblSize = 256;
            while (tblSize < this.attrCount) 
                tblSize = checked(tblSize * 2);
            if (this.attrHashTbl.Length < tblSize) 
                this.attrHashTbl = new int[tblSize]; 
            for (int i = 0; i < this.attrCount; i++) {
                string localname, namespaceUri; 
                int hash = this.attributes[i].GetLocalnameAndNamespaceUriAndHash(hasher, out localname, out namespaceUri);
                int index = hash & (tblSize - 1);
                int next = this.attrHashTbl[index];
                this.attrHashTbl[index] = i + 1; 
                this.attributes[i].prevHash = next;
                while (next != 0) { 
                    next--; 
                    if (this.attributes[next].MatchHashNS(hash, localname, namespaceUri)) {
                        throw new XmlException(Res.Xml_DupAttributeName, this.attributes[i].name.ToString()); 
                    }
                    next = this.attributes[next].prevHash;
                }
            } 
            Array.Clear(this.attrHashTbl, 0, tblSize);
        } 
 
        string XmlDeclValue() {
            StringBuilder sb = new StringBuilder(); 
            for (int i = 0; i < this.attrCount; i++) {
                if (i > 0)
                    sb.Append(' ');
                sb.Append(this.attributes[i].name.localname); 
                sb.Append("=\"");
                sb.Append(this.attributes[i].val); 
                sb.Append('"'); 
            }
            return sb.ToString(); 
        }

        string CDATAValue() {
            Debug.Assert(this.stringValue == null, "this.stringValue == null"); 
            Debug.Assert(this.token == BinXmlToken.CData, "this.token == BinXmlToken.CData");
            String value = GetString(this.tokDataPos, this.tokLen); 
            StringBuilder sb = null; 
            while (PeekToken() == BinXmlToken.CData) {
                this.pos++; // skip over token byte 
                if (sb == null) {
                    sb = new StringBuilder(value.Length + value.Length / 2);
                    sb.Append(value);
                } 
                sb.Append(ParseText());
            } 
            if (sb != null) 
                value = sb.ToString();
            this.stringValue = value; 
            return value;
        }

        void FinishCDATA() { 
            for (; ; ) {
                switch (PeekToken()) { 
                    case BinXmlToken.CData: 
                        // skip
                        this.pos++; 
                        int pos;
                        ScanText(out pos);
                        // try again
                        break; 
                    case BinXmlToken.EndCData:
                        // done... on to next token... 
                        this.pos++; 
                        return;
                    default: 
                        throw new XmlException(Res.XmlBin_MissingEndCDATA);
                }
            }
        } 

        void FinishEndElement() { 
            NamespaceDecl nsdecls = this.elementStack[this.elemDepth].Clear(); 
            this.PopNamespaces(nsdecls);
            this.elemDepth--; 
        }

        bool ReadDoc() {
            switch (this.nodetype) { 
                case XmlNodeType.CDATA:
                    FinishCDATA(); 
                    break; 
                case XmlNodeType.EndElement:
                    FinishEndElement(); 
                    break;
                case XmlNodeType.Element:
                    if (this.isEmpty) {
                        FinishEndElement(); 
                        this.isEmpty = false;
                    } 
                    break; 
            }
 
        Read:
            // clear existing state
            this.nodetype = XmlNodeType.None;
            this.mark = -1; 
            if (this.qnameOther.localname.Length != 0)
                this.qnameOther.Clear(); 
 
            ClearAttributes();
            this.attrCount = 0; 
            this.valueType = TypeOfString;
            this.stringValue = null;
            this.hasTypedValue = false;
 
            this.token = NextToken();
            switch (this.token) { 
                case BinXmlToken.EOF: 
                    if (this.elemDepth > 0)
                        throw new XmlException(Res.Xml_UnexpectedEOF1, (string[])null); 
                    this.state = ScanState.EOF;
                    return false;

                case BinXmlToken.Element: 
                    ImplReadElement();
                    break; 
 
                case BinXmlToken.EndElem:
                    ImplReadEndElement(); 
                    break;

                case BinXmlToken.DocType:
                    ImplReadDoctype(); 
                    if (this.dtdProcessing == DtdProcessing.Ignore)
                        goto Read; 
                    // nested, don't report doctype 
                    if (prevNameInfo != null)
                        goto Read; 
                    break;

                case BinXmlToken.PI:
                    ImplReadPI(); 
                    if (this.ignorePIs)
                        goto Read; 
                    break; 

                case BinXmlToken.Comment: 
                    ImplReadComment();
                    if (this.ignoreComments)
                        goto Read;
                    break; 

                case BinXmlToken.CData: 
                    ImplReadCDATA(); 
                    break;
 
                case BinXmlToken.Nest:
                    ImplReadNest();
                    // parse first token in nested document
                    sniffed = false; 
                    return ReadInit(true);
 
                case BinXmlToken.EndNest: 
                    if (null == this.prevNameInfo)
                        goto default; 
                    ImplReadEndNest();
                    return ReadDoc();

                case BinXmlToken.XmlText: 
                    ImplReadXmlText();
                    break; 
 
                // text values
                case BinXmlToken.SQL_BIT: 
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT:
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.SQL_REAL:
                case BinXmlToken.SQL_FLOAT: 
                case BinXmlToken.SQL_MONEY: 
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_DATETIME: 
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.SQL_DECIMAL:
                case BinXmlToken.SQL_NUMERIC:
                case BinXmlToken.XSD_DECIMAL: 
                case BinXmlToken.SQL_UUID:
                case BinXmlToken.SQL_VARBINARY: 
                case BinXmlToken.SQL_BINARY: 
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT: 
                case BinXmlToken.XSD_KATMAI_DATE:
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME:
                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                case BinXmlToken.XSD_BINHEX: 
                case BinXmlToken.XSD_BASE64:
                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT:
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR: 
                case BinXmlToken.SQL_NTEXT:
                case BinXmlToken.XSD_BOOLEAN: 
                case BinXmlToken.XSD_TIME: 
                case BinXmlToken.XSD_DATETIME:
                case BinXmlToken.XSD_DATE: 
                case BinXmlToken.XSD_BYTE:
                case BinXmlToken.XSD_UNSIGNEDSHORT:
                case BinXmlToken.XSD_UNSIGNEDINT:
                case BinXmlToken.XSD_UNSIGNEDLONG: 
                case BinXmlToken.XSD_QNAME:
                    ImplReadData(this.token); 
                    if (XmlNodeType.Text == this.nodetype) 
                        CheckAllowContent();
                    else if (this.ignoreWhitespace && !this.xmlspacePreserve) 
                        goto Read; // skip to next token
                    return true;

                default: 
                    throw ThrowUnexpectedToken(token);
            } 
 
            return true;
        } 

        void ImplReadData(BinXmlToken tokenType) {
            Debug.Assert(this.mark < 0);
            this.mark = this.pos; 

            switch (tokenType) { 
                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT: 
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR:
                case BinXmlToken.SQL_NTEXT:
                    this.valueType = TypeOfString; 
                    this.hasTypedValue = false;
                    break; 
                default: 
                    this.valueType = GetValueType(this.token);
                    this.hasTypedValue = true; 
                    break;
            }

            this.nodetype = ScanOverValue(this.token, false, true); 

            // we don't support lists of values 
            BinXmlToken tNext = PeekNextToken(); 
            switch (tNext) {
                case BinXmlToken.SQL_BIT: 
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT:
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.SQL_REAL:
                case BinXmlToken.SQL_FLOAT: 
                case BinXmlToken.SQL_MONEY: 
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_DATETIME: 
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.SQL_DECIMAL:
                case BinXmlToken.SQL_NUMERIC:
                case BinXmlToken.XSD_DECIMAL: 
                case BinXmlToken.SQL_UUID:
                case BinXmlToken.SQL_VARBINARY: 
                case BinXmlToken.SQL_BINARY: 
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT: 
                case BinXmlToken.XSD_KATMAI_DATE:
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME:
                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                case BinXmlToken.XSD_BINHEX: 
                case BinXmlToken.XSD_BASE64:
                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT:
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR: 
                case BinXmlToken.SQL_NTEXT:
                case BinXmlToken.XSD_BOOLEAN: 
                case BinXmlToken.XSD_TIME: 
                case BinXmlToken.XSD_DATETIME:
                case BinXmlToken.XSD_DATE: 
                case BinXmlToken.XSD_BYTE:
                case BinXmlToken.XSD_UNSIGNEDSHORT:
                case BinXmlToken.XSD_UNSIGNEDINT:
                case BinXmlToken.XSD_UNSIGNEDLONG: 
                case BinXmlToken.XSD_QNAME:
                    throw ThrowNotSupported(Res.XmlBinary_ListsOfValuesNotSupported); 
                default: 
                    break;
            } 
        }

        void ImplReadElement() {
            if (3 != this.docState || 9 != this.docState) { 
                switch (this.docState) {
                    case 0: 
                        this.docState = 9; 
                        break;
                    case 1: 
                    case 2:
                        this.docState = 3;
                        break;
                    case -1: 
                        throw ThrowUnexpectedToken(this.token);
                    default: 
                        break; 
                }
            } 
            this.elemDepth++;
            if (this.elemDepth == this.elementStack.Length)
                GrowElements();
            QName qname = this.symbolTables.qnametable[ReadQNameRef()]; 
            this.qnameOther = this.qnameElement = qname;
            this.elementStack[this.elemDepth].Set(qname, this.xmlspacePreserve); 
            this.PushNamespace(qname.prefix, qname.namespaceUri, true); 
            BinXmlToken t = PeekNextToken();
            if (BinXmlToken.Attr == t) { 
                ScanAttributes();
                t = PeekNextToken();
            }
            GenerateImpliedXmlnsAttrs(); 
            if (BinXmlToken.EndElem == t) {
                NextToken(); // move over token... 
                this.isEmpty = true; 
            }
            else if (BinXmlToken.SQL_NVARCHAR == t) { 
                if (this.mark < 0)
                    this.mark = this.pos;
                // skip over token byte
                this.pos++; 
                // is this a zero-length string?  if yes, skip it.
                // (It just indicates that this is _not_ an empty element) 
                // Also make sure that the following token is an EndElem 
                if (0 == ReadByte()) {
                    if (BinXmlToken.EndElem != (BinXmlToken)ReadByte()) { 
                        Debug.Assert(this.pos >= 3);
                        this.pos -= 3; // jump back to start of NVarChar token
                    }
                    else { 
                        Debug.Assert(this.pos >= 1);
                        this.pos -= 1; // jump back to EndElem token 
                    } 
                }
                else { 
                    Debug.Assert(this.pos >= 2);
                    this.pos -= 2; // jump back to start of NVarChar token
                }
            } 
            this.nodetype = XmlNodeType.Element;
            this.valueType = TypeOfObject; 
            this.posAfterAttrs = this.pos; 
        }
 
        void ImplReadEndElement() {
            if (this.elemDepth == 0)
                throw ThrowXmlException(Res.Xml_UnexpectedEndTag);
            int index = this.elemDepth; 
            if (1 == index && 3 == this.docState)
                this.docState = -1; 
            this.qnameOther = this.elementStack[index].name; 
            this.xmlspacePreserve = this.elementStack[index].xmlspacePreserve;
            this.nodetype = XmlNodeType.EndElement; 
        }

        void ImplReadDoctype() {
            if (this.dtdProcessing == DtdProcessing.Prohibit) 
                throw ThrowXmlException(Res.Xml_DtdIsProhibited);
            // 0=>auto, 1=>doc/pre-dtd, 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem, 9=>frag 
            switch (this.docState) { 
                case 0: // 0=>auto
                case 1: // 1=>doc/pre-dtd 
                    break;
                case 9: // 9=>frag
                    throw ThrowXmlException(Res.Xml_DtdNotAllowedInFragment);
                default: // 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem 
                    throw ThrowXmlException(Res.Xml_BadDTDLocation);
            } 
            this.docState = 2; 
            this.qnameOther.localname = ParseText();
            if (BinXmlToken.System == PeekToken()) { 
                this.pos++;
                this.attributes[this.attrCount++].Set(new QName(string.Empty, this.xnt.Add("SYSTEM"), string.Empty), ParseText());
            }
            if (BinXmlToken.Public == PeekToken()) { 
                this.pos++;
                this.attributes[this.attrCount++].Set(new QName(string.Empty, this.xnt.Add("PUBLIC"), string.Empty), ParseText()); 
            } 
            if (BinXmlToken.Subset == PeekToken()) {
                this.pos++; 
                this.mark = this.pos;
                this.tokLen = ScanText(out this.tokDataPos);
            }
            else { 
                this.tokLen = this.tokDataPos = 0;
            } 
            this.nodetype = XmlNodeType.DocumentType; 
            this.posAfterAttrs = this.pos;
        } 

        void ImplReadPI() {
            this.qnameOther.localname = this.symbolTables.symtable[ReadNameRef()];
            this.mark = this.pos; 
            this.tokLen = ScanText(out this.tokDataPos);
            this.nodetype = XmlNodeType.ProcessingInstruction; 
        } 

        void ImplReadComment() { 
            this.nodetype = XmlNodeType.Comment;
            this.mark = this.pos;
            this.tokLen = ScanText(out this.tokDataPos);
        } 

        void ImplReadCDATA() { 
            CheckAllowContent(); 
            this.nodetype = XmlNodeType.CDATA;
            this.mark = this.pos; 
            this.tokLen = ScanText(out this.tokDataPos);
        }

        void ImplReadNest() { 
            CheckAllowContent();
            // push current nametables 
            this.prevNameInfo = new NestedBinXml(this.symbolTables, this.docState, this.prevNameInfo); 
            this.symbolTables.Init();
            this.docState = 0; // auto 
        }

        void ImplReadEndNest() {
            NestedBinXml nested = this.prevNameInfo; 
            this.symbolTables = nested.symbolTables;
            this.docState = nested.docState; 
            this.prevNameInfo = nested.next; 
        }
 
        void ImplReadXmlText() {
            CheckAllowContent();
            string xmltext = ParseText();
            XmlNamespaceManager xnm = new XmlNamespaceManager(this.xnt); 
            foreach (NamespaceDecl decl in this.namespaces.Values) {
                if (decl.scope > 0) { 
#if DEBUG 
                    if ((object)decl.prefix != (object)this.xnt.Get(decl.prefix))
                        throw new Exception("Prefix not interned: \'" + decl.prefix + "\'"); 
                    if ((object)decl.uri != (object)this.xnt.Get(decl.uri))
                        throw new Exception("Uri not interned: \'" + decl.uri + "\'");
#endif
                    xnm.AddNamespace(decl.prefix, decl.uri); 
                }
            } 
            XmlReaderSettings settings = this.Settings; 
            settings.ReadOnly = false;
            settings.NameTable = this.xnt; 
            settings.DtdProcessing = DtdProcessing.Prohibit;
            if (0 != this.elemDepth) {
                settings.ConformanceLevel = ConformanceLevel.Fragment;
            } 
            settings.ReadOnly = true;
            XmlParserContext xpc = new XmlParserContext(this.xnt, xnm, this.XmlLang, this.XmlSpace); 
            this.textXmlReader = new XmlTextReaderImpl(xmltext, xpc, settings); 
            if (!this.textXmlReader.Read()
                || ((this.textXmlReader.NodeType == XmlNodeType.XmlDeclaration) 
                    && !this.textXmlReader.Read())) {
                this.state = ScanState.Doc;
                ReadDoc();
            } 
            else {
                this.state = ScanState.XmlText; 
                UpdateFromTextReader(); 
            }
        } 

        void UpdateFromTextReader() {
            XmlReader r = this.textXmlReader;
            this.nodetype = r.NodeType; 
            this.qnameOther.prefix = r.Prefix;
            this.qnameOther.localname = r.LocalName; 
            this.qnameOther.namespaceUri = r.NamespaceURI; 
            this.valueType = r.ValueType;
            this.isEmpty = r.IsEmptyElement; 
        }

        bool UpdateFromTextReader(bool needUpdate) {
            if (needUpdate) 
                UpdateFromTextReader();
            return needUpdate; 
        } 

        void CheckAllowContent() { 
            switch (this.docState) {
                case 0: // auto
                    this.docState = 9;
                    break; 
                case 9: // conformance = fragment
                case 3: 
                    break; 
                default:
                    throw ThrowXmlException(Res.Xml_InvalidRootData); 
            }
        }

        private void GenerateTokenTypeMap() { 
            Type[] map = new Type[256];
            map[(int)BinXmlToken.XSD_BOOLEAN] = typeof(System.Boolean); 
            map[(int)BinXmlToken.SQL_TINYINT] = typeof(System.Byte); 
            map[(int)BinXmlToken.XSD_BYTE] = typeof(System.SByte);
            map[(int)BinXmlToken.SQL_SMALLINT] = typeof(Int16); 
            map[(int)BinXmlToken.XSD_UNSIGNEDSHORT] = typeof(UInt16);
            map[(int)BinXmlToken.XSD_UNSIGNEDINT] = typeof(UInt32);
            map[(int)BinXmlToken.SQL_REAL] = typeof(Single);
            map[(int)BinXmlToken.SQL_FLOAT] = typeof(Double); 
            map[(int)BinXmlToken.SQL_BIGINT] = typeof(Int64);
            map[(int)BinXmlToken.XSD_UNSIGNEDLONG] = typeof(UInt64); 
            map[(int)BinXmlToken.XSD_QNAME] = typeof(XmlQualifiedName); 
            Type TypeOfInt32 = typeof(System.Int32);
            map[(int)BinXmlToken.SQL_BIT] = TypeOfInt32; 
            map[(int)BinXmlToken.SQL_INT] = TypeOfInt32;
            Type TypeOfDecimal = typeof(System.Decimal);
            map[(int)BinXmlToken.SQL_SMALLMONEY] = TypeOfDecimal;
            map[(int)BinXmlToken.SQL_MONEY] = TypeOfDecimal; 
            map[(int)BinXmlToken.SQL_DECIMAL] = TypeOfDecimal;
            map[(int)BinXmlToken.SQL_NUMERIC] = TypeOfDecimal; 
            map[(int)BinXmlToken.XSD_DECIMAL] = TypeOfDecimal; 
            Type TypeOfDateTime = typeof(System.DateTime);
            map[(int)BinXmlToken.SQL_SMALLDATETIME] = TypeOfDateTime; 
            map[(int)BinXmlToken.SQL_DATETIME] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_TIME] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_DATETIME] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_DATE] = TypeOfDateTime; 
            map[(int)BinXmlToken.XSD_KATMAI_DATE] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_KATMAI_DATETIME] = TypeOfDateTime; 
            map[(int)BinXmlToken.XSD_KATMAI_TIME] = TypeOfDateTime; 
            Type TypeOfDateTimeOffset = typeof( System.DateTimeOffset );
            map[(int)BinXmlToken.XSD_KATMAI_DATEOFFSET] = TypeOfDateTimeOffset; 
            map[(int)BinXmlToken.XSD_KATMAI_DATETIMEOFFSET] = TypeOfDateTimeOffset;
            map[(int)BinXmlToken.XSD_KATMAI_TIMEOFFSET] = TypeOfDateTimeOffset;
            Type TypeOfByteArray = typeof( System.Byte[] );
            map[(int)BinXmlToken.SQL_VARBINARY] = TypeOfByteArray; 
            map[(int)BinXmlToken.SQL_BINARY] = TypeOfByteArray;
            map[(int)BinXmlToken.SQL_IMAGE] = TypeOfByteArray; 
            map[(int)BinXmlToken.SQL_UDT] = TypeOfByteArray; 
            map[(int)BinXmlToken.XSD_BINHEX] = TypeOfByteArray;
            map[(int)BinXmlToken.XSD_BASE64] = TypeOfByteArray; 
            map[(int)BinXmlToken.SQL_CHAR] = TypeOfString;
            map[(int)BinXmlToken.SQL_VARCHAR] = TypeOfString;
            map[(int)BinXmlToken.SQL_TEXT] = TypeOfString;
            map[(int)BinXmlToken.SQL_NCHAR] = TypeOfString; 
            map[(int)BinXmlToken.SQL_NVARCHAR] = TypeOfString;
            map[(int)BinXmlToken.SQL_NTEXT] = TypeOfString; 
            map[(int)BinXmlToken.SQL_UUID] = TypeOfString; 
            if (TokenTypeMap == null)
                TokenTypeMap = map; 
        }

        System.Type GetValueType(BinXmlToken token) {
            Type t = TokenTypeMap[(int)token]; 
            if (t == null)
                throw ThrowUnexpectedToken(token); 
            return t; 
        }
 
        // helper method...
        void ReScanOverValue(BinXmlToken token) {
            ScanOverValue(token, true, false);
        } 

        XmlNodeType ScanOverValue(BinXmlToken token, bool attr, bool checkChars) { 
            if (token == BinXmlToken.SQL_NVARCHAR) { 
                if (this.mark < 0)
                    this.mark = this.pos; 
                this.tokLen = ParseMB32();
                this.tokDataPos = this.pos;
                checked{this.pos += this.tokLen * 2;}
                Fill(-1); 
                // check chars (if this is the first pass and settings.CheckCharacters was set)
                if (checkChars && this.checkCharacters) { 
                    // check for invalid chardata 
                    return CheckText(attr);
                } 
                else if (!attr) { // attribute values are always reported as Text
                    // check for whitespace-only text
                    return CheckTextIsWS();
                } 
                else {
                    return XmlNodeType.Text; 
                } 
            }
            else { 
                return ScanOverAnyValue(token, attr, checkChars);
            }
        }
 
        XmlNodeType ScanOverAnyValue(BinXmlToken token, bool attr, bool checkChars) {
            if (this.mark < 0) 
                this.mark = this.pos; 
            checked {
                switch (token) { 
                    case BinXmlToken.SQL_BIT:
                    case BinXmlToken.SQL_TINYINT:
                    case BinXmlToken.XSD_BOOLEAN:
                    case BinXmlToken.XSD_BYTE: 
                        this.tokDataPos = this.pos;
                        this.tokLen = 1; 
                        this.pos += 1; 
                        break;
 
                    case BinXmlToken.SQL_SMALLINT:
                    case BinXmlToken.XSD_UNSIGNEDSHORT:
                        this.tokDataPos = this.pos;
                        this.tokLen = 2; 
                        this.pos += 2;
                        break; 
 
                    case BinXmlToken.SQL_INT:
                    case BinXmlToken.XSD_UNSIGNEDINT: 
                    case BinXmlToken.SQL_REAL:
                    case BinXmlToken.SQL_SMALLMONEY:
                    case BinXmlToken.SQL_SMALLDATETIME:
                        this.tokDataPos = this.pos; 
                        this.tokLen = 4;
                        this.pos += 4; 
                        break; 

                    case BinXmlToken.SQL_BIGINT: 
                    case BinXmlToken.XSD_UNSIGNEDLONG:
                    case BinXmlToken.SQL_FLOAT:
                    case BinXmlToken.SQL_MONEY:
                    case BinXmlToken.SQL_DATETIME: 
                    case BinXmlToken.XSD_TIME:
                    case BinXmlToken.XSD_DATETIME: 
                    case BinXmlToken.XSD_DATE: 
                        this.tokDataPos = this.pos;
                        this.tokLen = 8; 
                        this.pos += 8;
                        break;

                    case BinXmlToken.SQL_UUID: 
                        this.tokDataPos = this.pos;
                        this.tokLen = 16; 
                        this.pos += 16; 
                        break;
 
                    case BinXmlToken.SQL_DECIMAL:
                    case BinXmlToken.SQL_NUMERIC:
                    case BinXmlToken.XSD_DECIMAL:
                        this.tokDataPos = this.pos; 
                        this.tokLen = ParseMB64();
                        this.pos += this.tokLen; 
                        break; 

                    case BinXmlToken.SQL_VARBINARY: 
                    case BinXmlToken.SQL_BINARY:
                    case BinXmlToken.SQL_IMAGE:
                    case BinXmlToken.SQL_UDT:
                    case BinXmlToken.XSD_BINHEX: 
                    case BinXmlToken.XSD_BASE64:
                        this.tokLen = ParseMB64(); 
                        this.tokDataPos = this.pos; 
                        this.pos += this.tokLen;
                        break; 

                    case BinXmlToken.SQL_CHAR:
                    case BinXmlToken.SQL_VARCHAR:
                    case BinXmlToken.SQL_TEXT: 
                        this.tokLen = ParseMB64();
                        this.tokDataPos = this.pos; 
                        this.pos += this.tokLen; 
                        if (checkChars && this.checkCharacters) {
                            // check for invalid chardata 
                            Fill(-1);
                            string val = ValueAsString(token);
                            XmlConvert.VerifyCharData(val, ExceptionType.ArgumentException, ExceptionType.XmlException);
                            this.stringValue = val; 
                        }
                        break; 
 
                    case BinXmlToken.SQL_NVARCHAR:
                    case BinXmlToken.SQL_NCHAR: 
                    case BinXmlToken.SQL_NTEXT:
                        return ScanOverValue(BinXmlToken.SQL_NVARCHAR, attr, checkChars);

                    case BinXmlToken.XSD_QNAME: 
                        this.tokDataPos = this.pos;
                        ParseMB32(); 
                        break; 

                    case BinXmlToken.XSD_KATMAI_DATE: 
                    case BinXmlToken.XSD_KATMAI_DATETIME:
                    case BinXmlToken.XSD_KATMAI_TIME:
                    case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                    case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                        VerifyVersion(2, token); 
                        this.tokDataPos = this.pos; 
                        this.tokLen = GetXsdKatmaiTokenLength(token);
                        this.pos += tokLen; 
                        break;

                    default:
                        throw ThrowUnexpectedToken(token); 
                }
            } 
            Fill(-1); 
            return XmlNodeType.Text;
        } 

        unsafe XmlNodeType CheckText(bool attr) {
            Debug.Assert(this.checkCharacters, "this.checkCharacters");
            // assert that size is an even number 
            Debug.Assert(0 == ((this.pos - this.tokDataPos) & 1), "Data size should not be odd");
            // grab local copy (perf) 
            XmlCharType xmlCharType = this.xmlCharType; 

            fixed (byte* pb = this.data) { 
                int end = this.pos;
                int pos = this.tokDataPos;

                if (!attr) { 
                    // scan if this is whitespace
                    for (; ; ) { 
                        int posNext = pos + 2; 
                        if (posNext > end)
                            return this.xmlspacePreserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace; 
                        if (pb[pos + 1] != 0 || (xmlCharType.charProperties[pb[pos]] & XmlCharType.fWhitespace) == 0)
                            break;
                        pos = posNext;
                    } 
                }
 
                for (; ; ) { 
                    char ch;
                    for (; ; ) { 
                        int posNext = pos + 2;
                        if (posNext > end)
                            return XmlNodeType.Text;
                        ch = (char)(pb[pos] | ((int)(pb[pos + 1]) << 8)); 
                        if ((xmlCharType.charProperties[ch] & XmlCharType.fCharData) == 0)
                            break; 
                        pos = posNext; 
                    }
 
                    if (!XmlCharType.IsHighSurrogate(ch)) {
                        throw XmlConvert.CreateInvalidCharException(ch, '\0', ExceptionType.XmlException);
                    }
                    else { 
                        if ((pos + 4) > end) {
                            throw ThrowXmlException(Res.Xml_InvalidSurrogateMissingLowChar); 
                        } 
                        char chNext = (char)(pb[pos + 2] | ((int)(pb[pos + 3]) << 8));
                        if (!XmlCharType.IsLowSurrogate(chNext)) { 
                            throw XmlConvert.CreateInvalidSurrogatePairException(ch, chNext);
                        }
                    }
                    pos += 4; 
                }
            } 
        } 

        XmlNodeType CheckTextIsWS() { 
            Debug.Assert(!this.checkCharacters, "!this.checkCharacters");
            byte[] data = this.data;
            // assert that size is an even number
            Debug.Assert(0 == ((this.pos - this.tokDataPos) & 1), "Data size should not be odd"); 
            for (int pos = this.tokDataPos; pos < this.pos; pos += 2) {
                if (0 != data[pos + 1]) 
                    goto NonWSText; 
                switch (data[pos]) {
                    case 0x09: // tab 
                    case 0x0A: // nl
                    case 0x0D: // cr
                    case 0x20: // space
                        break; 
                    default:
                        goto NonWSText; 
                } 
            }
            if (this.xmlspacePreserve) 
                return XmlNodeType.SignificantWhitespace;
            return XmlNodeType.Whitespace;
        NonWSText:
            return XmlNodeType.Text; 
        }
 
        void CheckValueTokenBounds() { 
            if ((this.end - this.tokDataPos) < this.tokLen)
                throw ThrowXmlException(Res.Xml_UnexpectedEOF1); 
        }

        int GetXsdKatmaiTokenLength(BinXmlToken token) {
            byte scale; 
            switch (token) {
                case BinXmlToken.XSD_KATMAI_DATE: 
                    // SQL Katmai type DATE = date(3b) 
                    return 3;
                case BinXmlToken.XSD_KATMAI_TIME: 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                    // SQL Katmai type DATETIME2 = scale(1b) + time(3-5b) + date(3b)
                    Fill(0);
                    scale = this.data[this.pos]; 
                    return 4 + XsdKatmaiTimeScaleToValueLength(scale);
                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    // SQL Katmai type DATETIMEOFFSET = scale(1b) + time(3-5b) + date(3b) + zone(2b) 
                    Fill(0);
                    scale = this.data[this.pos];
                    return 6 + XsdKatmaiTimeScaleToValueLength(scale);
                default: 
                    throw ThrowUnexpectedToken(this.token);
            } 
        } 

        int XsdKatmaiTimeScaleToValueLength(byte scale) { 
            if (scale > 7) {
                throw new XmlException(Res.SqlTypes_ArithOverflow, (string)null);
            }
            return XsdKatmaiTimeScaleToValueLengthMap[scale]; 
        }
 
        long ValueAsLong() { 
            CheckValueTokenBounds();
            switch (this.token) { 
                case BinXmlToken.SQL_BIT:
                case BinXmlToken.SQL_TINYINT: {
                        byte v = this.data[this.tokDataPos];
                        return v; 
                    }
 
                case BinXmlToken.XSD_BYTE: { 
                        sbyte v = unchecked((sbyte)this.data[this.tokDataPos]);
                        return v; 
                    }

                case BinXmlToken.SQL_SMALLINT:
                    return GetInt16(this.tokDataPos); 

                case BinXmlToken.SQL_INT: 
                    return GetInt32(this.tokDataPos); 

                case BinXmlToken.SQL_BIGINT: 
                    return GetInt64(this.tokDataPos);

                case BinXmlToken.XSD_UNSIGNEDSHORT:
                    return GetUInt16(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return GetUInt32(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDLONG: { 
                        ulong v = GetUInt64(this.tokDataPos);
                        return checked((long)v);
                    }
 
                case BinXmlToken.SQL_REAL:
                case BinXmlToken.SQL_FLOAT: { 
                        double v = ValueAsDouble(); 
                        return (long)v;
                    } 

                case BinXmlToken.SQL_MONEY:
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC:
                case BinXmlToken.XSD_DECIMAL: { 
                        Decimal v = ValueAsDecimal(); 
                        return (long)v;
                    } 

                default:
                    throw ThrowUnexpectedToken(this.token);
            } 
        }
 
        ulong ValueAsULong() { 
            if (BinXmlToken.XSD_UNSIGNEDLONG == this.token) {
                CheckValueTokenBounds(); 
                return GetUInt64(this.tokDataPos);
            }
            else {
                throw ThrowUnexpectedToken(this.token); 
            }
        } 
 
        Decimal ValueAsDecimal() {
            CheckValueTokenBounds(); 
            switch (token) {
                case BinXmlToken.SQL_BIT:
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT: 
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.XSD_BYTE: 
                case BinXmlToken.XSD_UNSIGNEDSHORT:
                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return new Decimal(ValueAsLong());

                case BinXmlToken.XSD_UNSIGNEDLONG:
                    return new Decimal(ValueAsULong()); 

                case BinXmlToken.SQL_REAL: 
                    return new Decimal(GetSingle(this.tokDataPos)); 

                case BinXmlToken.SQL_FLOAT: 
                    return new Decimal(GetDouble(this.tokDataPos));

                case BinXmlToken.SQL_SMALLMONEY: {
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt32(this.tokDataPos)); 
                        return v.ToDecimal();
                    } 
                case BinXmlToken.SQL_MONEY: { 
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt64(this.tokDataPos));
                        return v.ToDecimal(); 
                    }

                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC: {
                        BinXmlSqlDecimal v = new BinXmlSqlDecimal(this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL); 
                        return v.ToDecimal(); 
                    }
 
                default:
                    throw ThrowUnexpectedToken(this.token);
            }
        } 

        double ValueAsDouble() { 
            CheckValueTokenBounds(); 
            switch (token) {
                case BinXmlToken.SQL_BIT: 
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT:
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.XSD_BYTE:
                case BinXmlToken.XSD_UNSIGNEDSHORT: 
                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return (double)ValueAsLong();
 
                case BinXmlToken.XSD_UNSIGNEDLONG:
                    return (double)ValueAsULong();

                case BinXmlToken.SQL_REAL: 
                    return GetSingle(this.tokDataPos);
 
                case BinXmlToken.SQL_FLOAT: 
                    return GetDouble(this.tokDataPos);
 
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_MONEY:
                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC:
                    return (double)ValueAsDecimal(); 
 
                default:
                    throw ThrowUnexpectedToken(this.token); 
            }
        }

        DateTime ValueAsDateTime() { 
            CheckValueTokenBounds();
            switch (token) { 
                case BinXmlToken.SQL_DATETIME: { 
                        int pos = this.tokDataPos;
                        int dateticks; uint timeticks; 
                        dateticks = GetInt32(pos);
                        timeticks = GetUInt32(pos + 4);
                        return BinXmlDateTime.SqlDateTimeToDateTime(dateticks, timeticks);
                    } 

                case BinXmlToken.SQL_SMALLDATETIME: { 
                        int pos = this.tokDataPos; 
                        short dateticks; ushort timeticks;
                        dateticks = GetInt16(pos); 
                        timeticks = GetUInt16(pos + 2);
                        return BinXmlDateTime.SqlSmallDateTimeToDateTime(dateticks, timeticks);
                    }
 
                case BinXmlToken.XSD_TIME: {
                        long time = GetInt64(this.tokDataPos); 
                        return BinXmlDateTime.XsdTimeToDateTime(time); 
                    }
 
                case BinXmlToken.XSD_DATE: {
                        long time = GetInt64(this.tokDataPos);
                        return BinXmlDateTime.XsdDateToDateTime(time);
                    } 

                case BinXmlToken.XSD_DATETIME: { 
                        long time = GetInt64(this.tokDataPos); 
                        return BinXmlDateTime.XsdDateTimeToDateTime(time);
                    } 

                case BinXmlToken.XSD_KATMAI_DATE:
                    return BinXmlDateTime.XsdKatmaiDateToDateTime(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                    return BinXmlDateTime.XsdKatmaiDateTimeToDateTime(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_TIME:
                    return BinXmlDateTime.XsdKatmaiTimeToDateTime(this.data, this.tokDataPos); 

                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateOffsetToDateTime(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateTimeOffsetToDateTime(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiTimeOffsetToDateTime(this.data, this.tokDataPos); 

                default:
                    throw ThrowUnexpectedToken(this.token);
            } 
        }
 
        DateTimeOffset ValueAsDateTimeOffset() { 
            CheckValueTokenBounds();
            switch (token) { 
                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateOffsetToDateTimeOffset(this.data, this.tokDataPos);

                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                    return BinXmlDateTime.XsdKatmaiDateTimeOffsetToDateTimeOffset(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                    return BinXmlDateTime.XsdKatmaiTimeOffsetToDateTimeOffset(this.data, this.tokDataPos);
 
                default:
                    throw ThrowUnexpectedToken(this.token);
            }
        } 

 
        string ValueAsDateTimeString() { 
            CheckValueTokenBounds();
            switch (token) { 
                case BinXmlToken.SQL_DATETIME: {
                        int pos = this.tokDataPos;
                        int dateticks; uint timeticks;
                        dateticks = GetInt32(pos); 
                        timeticks = GetUInt32(pos + 4);
                        return BinXmlDateTime.SqlDateTimeToString(dateticks, timeticks); 
                    } 

                case BinXmlToken.SQL_SMALLDATETIME: { 
                        int pos = this.tokDataPos;
                        short dateticks; ushort timeticks;
                        dateticks = GetInt16(pos);
                        timeticks = GetUInt16(pos + 2); 
                        return BinXmlDateTime.SqlSmallDateTimeToString(dateticks, timeticks);
                    } 
 
                case BinXmlToken.XSD_TIME: {
                        long time = GetInt64(this.tokDataPos); 
                        return BinXmlDateTime.XsdTimeToString(time);
                    }

                case BinXmlToken.XSD_DATE: { 
                        long time = GetInt64(this.tokDataPos);
                        return BinXmlDateTime.XsdDateToString(time); 
                    } 

                case BinXmlToken.XSD_DATETIME: { 
                        long time = GetInt64(this.tokDataPos);
                        return BinXmlDateTime.XsdDateTimeToString(time);
                    }
 
                case BinXmlToken.XSD_KATMAI_DATE:
                    return BinXmlDateTime.XsdKatmaiDateToString(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                    return BinXmlDateTime.XsdKatmaiDateTimeToString(this.data, this.tokDataPos); 

                case BinXmlToken.XSD_KATMAI_TIME:
                    return BinXmlDateTime.XsdKatmaiTimeToString(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateOffsetToString(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateTimeOffsetToString(this.data, this.tokDataPos); 

                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiTimeOffsetToString(this.data, this.tokDataPos);
 
                default:
                    throw ThrowUnexpectedToken(this.token); 
            } 
        }
 
        string ValueAsString(BinXmlToken token) {
            try {
                CheckValueTokenBounds();
                switch ( token ) { 
                    case BinXmlToken.SQL_NCHAR:
                    case BinXmlToken.SQL_NVARCHAR: 
                    case BinXmlToken.SQL_NTEXT: 
                        return GetString( this.tokDataPos, this.tokLen );
 
                    case BinXmlToken.XSD_BOOLEAN: {
                            if ( 0 == this.data[this.tokDataPos] )
                                return "false";
                            else 
                                return "true";
                        } 
 
                    case BinXmlToken.SQL_BIT:
                    case BinXmlToken.SQL_TINYINT: 
                    case BinXmlToken.SQL_SMALLINT:
                    case BinXmlToken.SQL_INT:
                    case BinXmlToken.SQL_BIGINT:
                    case BinXmlToken.XSD_BYTE: 
                    case BinXmlToken.XSD_UNSIGNEDSHORT:
                    case BinXmlToken.XSD_UNSIGNEDINT: 
                        return ValueAsLong().ToString( CultureInfo.InvariantCulture ); 

                    case BinXmlToken.XSD_UNSIGNEDLONG: 
                        return ValueAsULong().ToString( CultureInfo.InvariantCulture );

                    case BinXmlToken.SQL_REAL:
                        return XmlConvert.ToString( GetSingle( this.tokDataPos ) ); 

                    case BinXmlToken.SQL_FLOAT: 
                        return XmlConvert.ToString( GetDouble( this.tokDataPos ) ); 

                    case BinXmlToken.SQL_UUID: { 
                            int a; short b, c;
                            int pos = this.tokDataPos;
                            a = GetInt32( pos );
                            b = GetInt16( pos + 4 ); 
                            c = GetInt16( pos + 6 );
                            Guid v = new Guid( a, b, c, data[pos + 8], data[pos + 9], data[pos + 10], data[pos + 11], data[pos + 12], data[pos + 13], data[pos + 14], data[pos + 15] ); 
                            return v.ToString(); 
                        }
 
                    case BinXmlToken.SQL_SMALLMONEY: {
                            BinXmlSqlMoney v = new BinXmlSqlMoney( GetInt32( this.tokDataPos ) );
                            return v.ToString();
                        } 
                    case BinXmlToken.SQL_MONEY: {
                            BinXmlSqlMoney v = new BinXmlSqlMoney( GetInt64( this.tokDataPos ) ); 
                            return v.ToString(); 
                        }
 
                    case BinXmlToken.XSD_DECIMAL:
                    case BinXmlToken.SQL_DECIMAL:
                    case BinXmlToken.SQL_NUMERIC: {
                            BinXmlSqlDecimal v = new BinXmlSqlDecimal( this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL ); 
                            return v.ToString();
                        } 
 
                    case BinXmlToken.SQL_CHAR:
                    case BinXmlToken.SQL_VARCHAR: 
                    case BinXmlToken.SQL_TEXT: {
                            int pos = this.tokDataPos;
                            int codepage = GetInt32( pos );
                            Encoding enc = System.Text.Encoding.GetEncoding( codepage ); 
                            return enc.GetString( this.data, pos + 4, this.tokLen - 4 );
                        } 
 
                    case BinXmlToken.SQL_VARBINARY:
                    case BinXmlToken.SQL_BINARY: 
                    case BinXmlToken.SQL_IMAGE:
                    case BinXmlToken.SQL_UDT:
                    case BinXmlToken.XSD_BASE64: {
                            return Convert.ToBase64String( this.data, this.tokDataPos, this.tokLen ); 
                        }
 
                    case BinXmlToken.XSD_BINHEX: 
                        return BinHexEncoder.Encode( this.data, this.tokDataPos, this.tokLen );
 
                    case BinXmlToken.SQL_DATETIME:
                    case BinXmlToken.SQL_SMALLDATETIME:
                    case BinXmlToken.XSD_TIME:
                    case BinXmlToken.XSD_DATE: 
                    case BinXmlToken.XSD_DATETIME:
                    case BinXmlToken.XSD_KATMAI_DATE: 
                    case BinXmlToken.XSD_KATMAI_DATETIME: 
                    case BinXmlToken.XSD_KATMAI_TIME:
                    case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                    case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                        return ValueAsDateTimeString();
 
                    case BinXmlToken.XSD_QNAME: {
                            int nameNum = ParseMB32( this.tokDataPos ); 
                            if ( nameNum < 0 || nameNum >= this.symbolTables.qnameCount ) 
                                throw new XmlException( Res.XmlBin_InvalidQNameID, String.Empty );
                            QName qname = this.symbolTables.qnametable[nameNum]; 
                            if ( qname.prefix.Length == 0 )
                                return qname.localname;
                            else
                                return String.Concat( qname.prefix, ":", qname.localname ); 
                        }
 
                    default: 
                        throw ThrowUnexpectedToken( this.token );
                } 
            }
            catch {
                this.state = ScanState.Error;
                throw; 
            }
        } 
 
        object ValueAsObject(BinXmlToken token, bool returnInternalTypes) {
            CheckValueTokenBounds(); 
            switch (token) {
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR:
                case BinXmlToken.SQL_NTEXT: 
                    return GetString(this.tokDataPos, this.tokLen);
 
                case BinXmlToken.XSD_BOOLEAN: 
                    return (0 != this.data[this.tokDataPos]);
 
                case BinXmlToken.SQL_BIT:
                    return (Int32)this.data[this.tokDataPos];

                case BinXmlToken.SQL_TINYINT: 
                    return this.data[this.tokDataPos];
 
                case BinXmlToken.SQL_SMALLINT: 
                    return GetInt16(this.tokDataPos);
 
                case BinXmlToken.SQL_INT:
                    return GetInt32(this.tokDataPos);

                case BinXmlToken.SQL_BIGINT: 
                    return GetInt64(this.tokDataPos);
 
                case BinXmlToken.XSD_BYTE: { 
                        sbyte v = unchecked((sbyte)this.data[this.tokDataPos]);
                        return v; 
                    }

                case BinXmlToken.XSD_UNSIGNEDSHORT:
                    return GetUInt16(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return GetUInt32(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDLONG: 
                    return GetUInt64(this.tokDataPos);

                case BinXmlToken.SQL_REAL:
                    return GetSingle(this.tokDataPos); 

                case BinXmlToken.SQL_FLOAT: 
                    return GetDouble(this.tokDataPos); 

                case BinXmlToken.SQL_UUID: { 
                        int a; short b, c;
                        int pos = this.tokDataPos;
                        a = GetInt32(pos);
                        b = GetInt16(pos + 4); 
                        c = GetInt16(pos + 6);
                        Guid v = new Guid(a, b, c, data[pos + 8], data[pos + 9], data[pos + 10], data[pos + 11], data[pos + 12], data[pos + 13], data[pos + 14], data[pos + 15]); 
                        return v.ToString(); 
                    }
 
                case BinXmlToken.SQL_SMALLMONEY: {
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt32(this.tokDataPos));
                        if (returnInternalTypes)
                            return v; 
                        else
                            return v.ToDecimal(); 
                    } 

                case BinXmlToken.SQL_MONEY: { 
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt64(this.tokDataPos));
                        if (returnInternalTypes)
                            return v;
                        else 
                            return v.ToDecimal();
                    } 
 
                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC: {
                        BinXmlSqlDecimal v = new BinXmlSqlDecimal(this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL);
                        if (returnInternalTypes)
                            return v; 
                        else
                            return v.ToDecimal(); 
                    } 

                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT: {
                        int pos = this.tokDataPos;
                        int codepage = GetInt32(pos); 
                        Encoding enc = System.Text.Encoding.GetEncoding(codepage);
                        return enc.GetString(this.data, pos + 4, this.tokLen - 4); 
                    } 

                case BinXmlToken.SQL_VARBINARY: 
                case BinXmlToken.SQL_BINARY:
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT:
                case BinXmlToken.XSD_BASE64: 
                case BinXmlToken.XSD_BINHEX: {
                        byte[] data = new byte[this.tokLen]; 
                        Array.Copy(this.data, this.tokDataPos, data, 0, this.tokLen); 
                        return data;
                    } 

                case BinXmlToken.SQL_DATETIME:
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.XSD_TIME: 
                case BinXmlToken.XSD_DATE:
                case BinXmlToken.XSD_DATETIME: 
                case BinXmlToken.XSD_KATMAI_DATE: 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME: 
                    return ValueAsDateTime();

                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    return ValueAsDateTimeOffset(); 
 
                case BinXmlToken.XSD_QNAME: {
                        int nameNum = ParseMB32(this.tokDataPos); 
                        if (nameNum < 0 || nameNum >= this.symbolTables.qnameCount)
                            throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
                        QName qname = this.symbolTables.qnametable[nameNum];
                        return new XmlQualifiedName(qname.localname, qname.namespaceUri); 
                    }
 
                default: 
                    throw ThrowUnexpectedToken(this.token);
            } 
        }

        XmlValueConverter GetValueConverter(XmlTypeCode typeCode) {
            XmlSchemaSimpleType xsst = DatatypeImplementation.GetSimpleTypeFromTypeCode(typeCode); 
            return xsst.ValueConverter;
        } 
 
        object ValueAs(BinXmlToken token, Type returnType, IXmlNamespaceResolver namespaceResolver) {
            object value; 
            CheckValueTokenBounds();
            switch (token) {
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR: 
                case BinXmlToken.SQL_NTEXT:
                    value = GetValueConverter(XmlTypeCode.UntypedAtomic).ChangeType( 
                        GetString(this.tokDataPos, this.tokLen), 
                        returnType, namespaceResolver);
                    break; 

                case BinXmlToken.XSD_BOOLEAN:
                    value = GetValueConverter(XmlTypeCode.Boolean).ChangeType(
                        (0 != this.data[this.tokDataPos]), 
                        returnType, namespaceResolver);
                    break; 
 
                case BinXmlToken.SQL_BIT:
                    value = GetValueConverter(XmlTypeCode.NonNegativeInteger).ChangeType( 
                        (Int32)this.data[this.tokDataPos],
                        returnType, namespaceResolver);
                    break;
 
                case BinXmlToken.SQL_TINYINT:
                    value = GetValueConverter(XmlTypeCode.UnsignedByte).ChangeType( 
                        this.data[this.tokDataPos], 
                        returnType, namespaceResolver);
                    break; 

                case BinXmlToken.SQL_SMALLINT: {
                        int v = GetInt16(this.tokDataPos);
                        value = GetValueConverter(XmlTypeCode.Short).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    } 
                case BinXmlToken.SQL_INT: {
                        int v = GetInt32(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Int).ChangeType(
                            v, returnType, namespaceResolver);
                        break;
                    } 
                case BinXmlToken.SQL_BIGINT: {
                        long v = GetInt64(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Long).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    }
                case BinXmlToken.XSD_BYTE: {
                        value = GetValueConverter(XmlTypeCode.Byte).ChangeType(
                            (int)unchecked((sbyte)this.data[this.tokDataPos]), 
                            returnType, namespaceResolver);
                        break; 
                    } 
                case BinXmlToken.XSD_UNSIGNEDSHORT: {
                        int v = GetUInt16(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.UnsignedShort).ChangeType(
                            v, returnType, namespaceResolver);
                        break;
                    } 
                case BinXmlToken.XSD_UNSIGNEDINT: {
                        long v = GetUInt32(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.UnsignedInt).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    }
                case BinXmlToken.XSD_UNSIGNEDLONG: {
                        Decimal v = (Decimal)GetUInt64(this.tokDataPos);
                        value = GetValueConverter(XmlTypeCode.UnsignedLong).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    } 
                case BinXmlToken.SQL_REAL: {
                        Single v = GetSingle(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Float).ChangeType(
                            v, returnType, namespaceResolver);
                        break;
                    } 
                case BinXmlToken.SQL_FLOAT: {
                        Double v = GetDouble(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Double).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    }
                case BinXmlToken.SQL_UUID:
                    value = GetValueConverter(XmlTypeCode.String).ChangeType(
                        this.ValueAsString(token), returnType, namespaceResolver); 
                    break;
 
                case BinXmlToken.SQL_SMALLMONEY: 
                    value = GetValueConverter(XmlTypeCode.Decimal).ChangeType(
                        (new BinXmlSqlMoney(GetInt32(this.tokDataPos))).ToDecimal(), 
                        returnType, namespaceResolver);
                    break;

                case BinXmlToken.SQL_MONEY: 
                    value = GetValueConverter(XmlTypeCode.Decimal).ChangeType(
                        (new BinXmlSqlMoney(GetInt64(this.tokDataPos))).ToDecimal(), 
                        returnType, namespaceResolver); 
                    break;
 
                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL:
                case BinXmlToken.SQL_NUMERIC:
                    value = GetValueConverter(XmlTypeCode.Decimal).ChangeType( 
                        (new BinXmlSqlDecimal(this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL)).ToDecimal(),
                        returnType, namespaceResolver); 
                    break; 

                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT: {
                        int pos = this.tokDataPos;
                        int codepage = GetInt32(pos); 
                        Encoding enc = System.Text.Encoding.GetEncoding(codepage);
                        value = GetValueConverter(XmlTypeCode.UntypedAtomic).ChangeType( 
                            enc.GetString(this.data, pos + 4, this.tokLen - 4), 
                            returnType, namespaceResolver);
                        break; 
                    }

                case BinXmlToken.SQL_VARBINARY:
                case BinXmlToken.SQL_BINARY: 
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT: 
                case BinXmlToken.XSD_BASE64: 
                case BinXmlToken.XSD_BINHEX: {
                        byte[] data = new byte[this.tokLen]; 
                        Array.Copy(this.data, this.tokDataPos, data, 0, this.tokLen);
                        value = GetValueConverter(token == BinXmlToken.XSD_BINHEX ? XmlTypeCode.HexBinary : XmlTypeCode.Base64Binary).ChangeType(
                            data, returnType, namespaceResolver);
                        break; 
                    }
 
                case BinXmlToken.SQL_DATETIME: 
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.XSD_DATETIME: 
                case BinXmlToken.XSD_KATMAI_DATE:
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME:
                    value = GetValueConverter(XmlTypeCode.DateTime).ChangeType( 
                        ValueAsDateTime(),
                        returnType, namespaceResolver); 
                    break; 

                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    value = GetValueConverter(XmlTypeCode.DateTime).ChangeType(
                        ValueAsDateTimeOffset(), 
                        returnType, namespaceResolver);
                    break; 
 
                case BinXmlToken.XSD_TIME:
                    value = GetValueConverter(XmlTypeCode.Time).ChangeType( 
                        ValueAsDateTime(),
                        returnType, namespaceResolver);
                    break;
 
                case BinXmlToken.XSD_DATE:
                    value = GetValueConverter(XmlTypeCode.Date).ChangeType( 
                        ValueAsDateTime(), 
                        returnType, namespaceResolver);
                    break; 

                case BinXmlToken.XSD_QNAME: {
                        int nameNum = ParseMB32(this.tokDataPos);
                        if (nameNum < 0 || nameNum >= this.symbolTables.qnameCount) 
                            throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
                        QName qname = this.symbolTables.qnametable[nameNum]; 
                        value = GetValueConverter(XmlTypeCode.QName).ChangeType( 
                            new XmlQualifiedName(qname.localname, qname.namespaceUri),
                            returnType, namespaceResolver); 
                        break;
                    }

                default: 
                    throw ThrowUnexpectedToken(this.token);
            } 
            return value; 
        }
 
        Int16 GetInt16(int pos) {
            byte[] data = this.data;
            return (Int16)(data[pos] | data[pos + 1] << 8);
        } 

        UInt16 GetUInt16(int pos) { 
            byte[] data = this.data; 
            return (UInt16)(data[pos] | data[pos + 1] << 8);
        } 

        Int32 GetInt32(int pos) {
            byte[] data = this.data;
            return (Int32)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24); 
        }
 
        UInt32 GetUInt32(int pos) { 
            byte[] data = this.data;
            return (UInt32)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24); 
        }

        Int64 GetInt64(int pos) {
            byte[] data = this.data; 
            uint lo = (uint)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24);
            uint hi = (uint)(data[pos + 4] | data[pos + 5] << 8 | data[pos + 6] << 16 | data[pos + 7] << 24); 
            return (Int64)((ulong)hi) << 32 | lo; 
        }
 
        UInt64 GetUInt64(int pos) {
            byte[] data = this.data;
            uint lo = (uint)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24);
            uint hi = (uint)(data[pos + 4] | data[pos + 5] << 8 | data[pos + 6] << 16 | data[pos + 7] << 24); 
            return (UInt64)((ulong)hi) << 32 | lo;
        } 
 
        Single GetSingle(int offset) {
            byte[] data = this.data; 
            uint tmp = (uint)(data[offset]
                            | data[offset + 1] << 8
                            | data[offset + 2] << 16
                            | data[offset + 3] << 24); 
            unsafe {
                return *((float*)&tmp); 
            } 
        }
 
        Double GetDouble(int offset) {
            uint lo = (uint)(data[offset + 0]
                            | data[offset + 1] << 8
                            | data[offset + 2] << 16 
                            | data[offset + 3] << 24);
            uint hi = (uint)(data[offset + 4] 
                            | data[offset + 5] << 8 
                            | data[offset + 6] << 16
                            | data[offset + 7] << 24); 
            ulong tmp = ((ulong)hi) << 32 | lo;
            unsafe {
                return *((double*)&tmp);
            } 
        }
 
        Exception ThrowUnexpectedToken(BinXmlToken token) { 
            System.Diagnostics.Debug.WriteLine("Unhandled token: " + token.ToString());
            return ThrowXmlException(Res.XmlBinary_UnexpectedToken); 
        }

        Exception ThrowXmlException(string res) {
            this.state = ScanState.Error; 
            return new XmlException(res, (string[])null);
        } 
 
        // not currently used...
        //Exception ThrowXmlException(string res, string arg1) { 
        //    this.state = ScanState.Error;
        //    return new XmlException(res, new string[] {arg1} );
        //}
 
        Exception ThrowXmlException(string res, string arg1, string arg2) {
            this.state = ScanState.Error; 
            return new XmlException(res, new string[] { arg1, arg2 }); 
        }
 
        Exception ThrowNotSupported(string res) {
            this.state = ScanState.Error;
            return new NotSupportedException(Res.GetString(res));
        } 
    }
} 

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

    internal sealed class XmlSqlBinaryReader : XmlReader, IXmlNamespaceResolver { 
        internal static readonly Type TypeOfObject = typeof(System.Object);
        internal static readonly Type TypeOfString = typeof(System.String);

        static Type[] TokenTypeMap = null; 

        static byte[] XsdKatmaiTimeScaleToValueLengthMap = new byte[8] { 
        // length scale 
            3, // 0
            3, // 1 
            3, // 2
            4, // 3
            4, // 4
            5, // 5 
            5, // 6
            5, // 7 
        }; 

        enum ScanState { 
            Doc = 0,
            XmlText = 1,
            Attr = 2,
            AttrVal = 3, 
            AttrValPseudoValue = 4,
            Init = 5, 
            Error = 6, 
            EOF = 7,
            Closed = 8 
        }

        static ReadState[] ScanState2ReadState = {
            ReadState.Interactive, 
            ReadState.Interactive,
            ReadState.Interactive, 
            ReadState.Interactive, 
            ReadState.Interactive,
            ReadState.Initial, 
            ReadState.Error,
            ReadState.EndOfFile,
            ReadState.Closed
        }; 

        // Note: also used by XmlBinaryWriter 
        internal struct QName { 
            public string prefix;
            public string localname; 
            public string namespaceUri;

            public QName(string prefix, string lname, string nsUri) {
                this.prefix = prefix; this.localname = lname; this.namespaceUri = nsUri; 
            }
            public void Set(string prefix, string lname, string nsUri) { 
                this.prefix = prefix; this.localname = lname; this.namespaceUri = nsUri; 
            }
 
            public void Clear() {
                this.prefix = this.localname = this.namespaceUri = String.Empty;
            }
 
            public bool MatchNs(string lname, string nsUri) {
                return lname == this.localname && nsUri == this.namespaceUri; 
            } 
            public bool MatchPrefix(string prefix, string lname) {
                return lname == this.localname && prefix == this.prefix; 
            }

            public void CheckPrefixNS(string prefix, string namespaceUri) {
                if (this.prefix == prefix && this.namespaceUri != namespaceUri) 
                    throw new XmlException(Res.XmlBinary_NoRemapPrefix, new String[] { prefix, this.namespaceUri, namespaceUri });
            } 
 
            public override int GetHashCode() {
                return this.prefix.GetHashCode() ^ this.localname.GetHashCode(); 
            }

            public int GetNSHashCode(SecureStringHasher hasher) {
                return hasher.GetHashCode(this.namespaceUri) ^ hasher.GetHashCode(this.localname); 
            }
 
 
            public override bool Equals(object other) {
                if (other is QName) { 
                    QName that = (QName)other;
                    return this == that;
                }
                return false; 
            }
 
            public override string ToString() { 
                if (prefix.Length == 0)
                    return this.localname; 
                else
                    return this.prefix + ":" + this.localname;
            }
 
            public static bool operator ==(QName a, QName b) {
                return ((a.prefix == b.prefix) 
                    && (a.localname == b.localname) 
                    && (a.namespaceUri == b.namespaceUri));
            } 

            public static bool operator !=(QName a, QName b) {
                return !(a == b);
            } 
        };
 
        struct ElemInfo { 
            public QName name;
            public string xmlLang; 
            public XmlSpace xmlSpace;
            public bool xmlspacePreserve;
            public NamespaceDecl nsdecls;
 
            public void Set(QName name, bool xmlspacePreserve) {
                this.name = name; 
                this.xmlLang = null; 
                this.xmlSpace = XmlSpace.None;
                this.xmlspacePreserve = xmlspacePreserve; 
            }
            public NamespaceDecl Clear() {
                NamespaceDecl nsdecls = this.nsdecls;
                this.nsdecls = null; 
                return nsdecls;
            } 
        }; 

        struct AttrInfo { 
            public QName name;
            public string val;
            public int contentPos;
            public int hashCode; 
            public int prevHash;
 
            public void Set(QName n, string v) { 
                this.name = n;
                this.val = v; 
                this.contentPos = 0;
                this.hashCode = 0;
                this.prevHash = 0;
            } 
            public void Set(QName n, int pos) {
                this.name = n; 
                this.val = null; 
                this.contentPos = pos;
                this.hashCode = 0; 
                this.prevHash = 0;
            }

            public void GetLocalnameAndNamespaceUri(out string localname, out string namespaceUri) { 
                localname = this.name.localname;
                namespaceUri = this.name.namespaceUri; 
            } 

            public int GetLocalnameAndNamespaceUriAndHash(SecureStringHasher hasher, out string localname, out string namespaceUri) { 
                localname = this.name.localname;
                namespaceUri = this.name.namespaceUri;
                return this.hashCode = this.name.GetNSHashCode(hasher);
            } 

            public bool MatchNS(string localname, string namespaceUri) { 
                return this.name.MatchNs(localname, namespaceUri); 
            }
 
            public bool MatchHashNS(int hash, string localname, string namespaceUri) {
                return this.hashCode == hash && this.name.MatchNs(localname, namespaceUri);
            }
 
            public void AdjustPosition(int adj) {
                if (this.contentPos != 0) 
                    this.contentPos += adj; 
            }
        } 

        class NamespaceDecl {
            public string prefix;
            public string uri; 
            public NamespaceDecl scopeLink;
            public NamespaceDecl prevLink; 
            public int scope; 
            public bool implied;
 
            public NamespaceDecl(string prefix, string nsuri,
                                NamespaceDecl nextInScope, NamespaceDecl prevDecl,
                                int scope, bool implied) {
                this.prefix = prefix; 
                this.uri = nsuri;
                this.scopeLink = nextInScope; 
                this.prevLink = prevDecl; 
                this.scope = scope;
                this.implied = implied; 
            }
        }

        // symbol and qname tables 
        struct SymbolTables {
            public string[] symtable; 
            public int symCount; 
            public QName[] qnametable;
            public int qnameCount; 
            public void Init() {
                this.symtable = new string[64];
                this.qnametable = new QName[16];
                this.symtable[0] = String.Empty; 
                this.symCount = 1;
                this.qnameCount = 1; 
            } 
        }
        class NestedBinXml { 
            public SymbolTables symbolTables;
            public int docState;
            public NestedBinXml next;
            public NestedBinXml(SymbolTables symbolTables, int docState, NestedBinXml next) { 
                this.symbolTables = symbolTables;
                this.docState = docState; 
                this.next = next; 
            }
        } 

        // input data
        Stream inStrm;
        byte[] data; 
        int pos;
        int mark; 
        int end; 
        long offset; // how much read and shift out of buffer
        bool eof; 
        bool sniffed;
        bool isEmpty; // short-tag element start tag

        int docState; // 0=>auto, 1=>doc/pre-dtd, 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem, 9=>frag 

        // symbol and qname tables 
        SymbolTables symbolTables; 

        XmlNameTable xnt; 
        bool xntFromSettings;
        string xml;
        string xmlns;
        string nsxmlns; 

        // base uri... 
        string baseUri; 

        // current parse state 
        ScanState state;
        XmlNodeType nodetype;
        BinXmlToken token;
        // current attribute 
        int attrIndex;
        // index of current qname 
        QName qnameOther; 
        // saved qname of element (for MoveToElement)
        QName qnameElement; 
        XmlNodeType parentNodeType; // use for MoveToElement()
        // stack of current open element tags
        ElemInfo[] elementStack;
        int elemDepth; 
        // current attributes
        AttrInfo[] attributes; 
        int[] attrHashTbl; 
        int attrCount;
        int posAfterAttrs; 
        // xml:space
        bool xmlspacePreserve;
        // position/parse info for current typed token
        int tokLen; 
        int tokDataPos;
        bool hasTypedValue; 
        System.Type valueType; 
        // if it is a simple string value, we cache it
        string stringValue; 
        // hashtable of current namespaces
        Dictionary namespaces;
        //Hashtable namespaces;
        // linked list of pushed nametables (to support nested binary-xml documents) 
        NestedBinXml prevNameInfo;
        // XmlTextReader to handle embeded text blocks 
        XmlReader textXmlReader; 
        // close input flag
        bool closeInput; 

        bool checkCharacters;
        bool ignoreWhitespace;
        bool ignorePIs; 
        bool ignoreComments;
        DtdProcessing dtdProcessing; 
 
        SecureStringHasher hasher;
        XmlCharType xmlCharType; 
        Encoding unicode;

        // current version of the protocol
        byte version; 

        public XmlSqlBinaryReader(System.IO.Stream stream, byte[] data, int len, string baseUri, bool closeInput, XmlReaderSettings settings) { 
            unicode = System.Text.Encoding.Unicode; 
            xmlCharType = XmlCharType.Instance;
 
            this.xnt = settings.NameTable;
            if (this.xnt == null) {
                this.xnt = new NameTable();
                this.xntFromSettings = false; 
            }
            else { 
                this.xntFromSettings = true; 
            }
            this.xml = this.xnt.Add("xml"); 
            this.xmlns = this.xnt.Add("xmlns");
            this.nsxmlns = this.xnt.Add(XmlReservedNs.NsXmlNs);
            this.baseUri = baseUri;
            this.state = ScanState.Init; 
            this.nodetype = XmlNodeType.None;
            this.token = BinXmlToken.Error; 
            this.elementStack = new ElemInfo[16]; 
            //this.elemDepth = 0;
            this.attributes = new AttrInfo[8]; 
            this.attrHashTbl = new int[8];
            //this.attrCount = 0;
            //this.attrIndex = 0;
            this.symbolTables.Init(); 
            this.qnameOther.Clear();
            this.qnameElement.Clear(); 
            this.xmlspacePreserve = false; 
            this.hasher = new SecureStringHasher();
            this.namespaces = new Dictionary(hasher); 
            AddInitNamespace(String.Empty, String.Empty);
            AddInitNamespace(this.xml, this.xnt.Add(XmlReservedNs.NsXml));
            AddInitNamespace(this.xmlns, this.nsxmlns);
            this.valueType = TypeOfString; 
            // init buffer position, etc
            this.inStrm = stream; 
            if (data != null) { 
                Debug.Assert(len >= 2 && (data[0] == 0xdf && data[1] == 0xff));
                this.data = data; 
                this.end = len;
                this.pos = 2;
                this.sniffed = true;
            } 
            else {
                this.data = new byte[XmlReader.DefaultBufferSize]; 
                this.end = stream.Read(this.data, 0, XmlReader.DefaultBufferSize); 
                this.pos = 0;
                this.sniffed = false; 
            }

            this.mark = -1;
            this.eof = (0 == this.end); 
            this.offset = 0;
            this.closeInput = closeInput; 
            switch (settings.ConformanceLevel) { 
                case ConformanceLevel.Auto:
                    this.docState = 0; break; 
                case ConformanceLevel.Fragment:
                    this.docState = 9; break;
                case ConformanceLevel.Document:
                    this.docState = 1; break; 
            }
            this.checkCharacters = settings.CheckCharacters; 
            this.dtdProcessing = settings.DtdProcessing; 
            this.ignoreWhitespace = settings.IgnoreWhitespace;
            this.ignorePIs = settings.IgnoreProcessingInstructions; 
            this.ignoreComments = settings.IgnoreComments;

            if (TokenTypeMap == null)
                GenerateTokenTypeMap(); 
        }
 
        public override XmlReaderSettings Settings { 
            get {
                XmlReaderSettings settings = new XmlReaderSettings(); 
                if (xntFromSettings) {
                    settings.NameTable = xnt;
                }
                // 0=>auto, 1=>doc/pre-dtd, 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem, 9=>frag 
                switch (this.docState) {
                    case 0: 
                        settings.ConformanceLevel = ConformanceLevel.Auto; break; 
                    case 9:
                        settings.ConformanceLevel = ConformanceLevel.Fragment; break; 
                    default:
                        settings.ConformanceLevel = ConformanceLevel.Document; break;
                }
                settings.CheckCharacters = this.checkCharacters; 
                settings.IgnoreWhitespace = this.ignoreWhitespace;
                settings.IgnoreProcessingInstructions = this.ignorePIs; 
                settings.IgnoreComments = this.ignoreComments; 
                settings.DtdProcessing = this.dtdProcessing;
                settings.CloseInput = this.closeInput; 

                settings.ReadOnly = true;
                return settings;
            } 
        }
 
        public override XmlNodeType NodeType { 
            get {
                return this.nodetype; 
            }
        }

        public override string LocalName { 
            get {
                return this.qnameOther.localname; 
            } 
        }
 
        public override string NamespaceURI {
            get {
                return this.qnameOther.namespaceUri;
            } 
        }
 
        public override string Prefix { 
            get {
                return this.qnameOther.prefix; 
            }
        }

        public override bool HasValue { 
            get {
                if (ScanState.XmlText == this.state) 
                    return this.textXmlReader.HasValue; 
                else
                    return XmlReader.HasValueInternal(this.nodetype); 
            }
        }

        public override string Value { 
            get {
                if (null != this.stringValue) 
                    return stringValue; 
                switch (this.state) {
                    case ScanState.Doc: 
                        switch (this.nodetype) {
                            case XmlNodeType.DocumentType:
                            case XmlNodeType.ProcessingInstruction:
                            case XmlNodeType.Comment: 
                                return this.stringValue = GetString(this.tokDataPos, this.tokLen);
 
                            case XmlNodeType.CDATA: 
                                return this.stringValue = CDATAValue();
 
                            case XmlNodeType.XmlDeclaration:
                                return this.stringValue = XmlDeclValue();

                            case XmlNodeType.Text: 
                            case XmlNodeType.Whitespace:
                            case XmlNodeType.SignificantWhitespace: 
                                return this.stringValue = ValueAsString(this.token); 
                        }
                        break; 

                    case ScanState.XmlText:
                        return this.textXmlReader.Value;
 
                    case ScanState.Attr:
                    case ScanState.AttrValPseudoValue: 
                        return this.stringValue = GetAttributeText(this.attrIndex - 1); 

                    case ScanState.AttrVal: 
                        return this.stringValue = ValueAsString(this.token);
                }
                return String.Empty;
            } 
        }
 
        public override int Depth { 
            get {
                int adj = 0; 
                switch (this.state) {
                    case ScanState.Doc:
                        if (this.nodetype == XmlNodeType.Element
                            || this.nodetype == XmlNodeType.EndElement) 
                            adj = -1;
                        break; 
 
                    case ScanState.XmlText:
                        adj = this.textXmlReader.Depth; 
                        break;

                    case ScanState.Attr:
                        if (this.parentNodeType != XmlNodeType.Element) 
                            adj = 1;
                        break; 
                    case ScanState.AttrVal: 
                    case ScanState.AttrValPseudoValue:
                        if (this.parentNodeType != XmlNodeType.Element) 
                            adj = 1;
                        adj += 1;
                        break;
                    default: 
                        return 0;
                } 
                return this.elemDepth + adj; 
            }
        } 

        public override string BaseURI {
            get {
                return this.baseUri; 
            }
        } 
 
        public override bool IsEmptyElement {
            get { 
                switch (this.state) {
                    case ScanState.Doc:
                    case ScanState.XmlText:
                        return this.isEmpty; 
                    default:
                        return false; 
                } 
            }
        } 

        public override XmlSpace XmlSpace {
            get {
                if (ScanState.XmlText != this.state) { 
                    for (int i = this.elemDepth; i >= 0; i--) {
                        XmlSpace xs = this.elementStack[i].xmlSpace; 
                        if (xs != XmlSpace.None) 
                            return xs;
                    } 
                    return XmlSpace.None;
                }
                else {
                    return this.textXmlReader.XmlSpace; 
                }
            } 
        } 

        public override string XmlLang { 
            get {
                if (ScanState.XmlText != this.state) {
                    for (int i = this.elemDepth; i >= 0; i--) {
                        string xl = this.elementStack[i].xmlLang; 
                        if (null != xl)
                            return xl; 
                    } 
                    return string.Empty;
                } 
                else {
                    return this.textXmlReader.XmlLang;
                }
            } 
        }
 
        public override System.Type ValueType { 
            get {
                return this.valueType; 
            }
        }

        public override int AttributeCount { 
            get {
                switch (this.state) { 
                    case ScanState.Doc: 
                    // for compatibility with XmlTextReader
                    //  we return the attribute count for the element 
                    //  when positioned on an attribute under that
                    //  element...
                    case ScanState.Attr:
                    case ScanState.AttrVal: 
                    case ScanState.AttrValPseudoValue:
                        return this.attrCount; 
                    case ScanState.XmlText: 
                        return this.textXmlReader.AttributeCount;
                    default: 
                        return 0;
                }
            }
        } 

        public override string GetAttribute(string name, string ns) { 
            if (ScanState.XmlText == this.state) { 
                return this.textXmlReader.GetAttribute(name, ns);
            } 
            else {
                if (null == name)
                    throw new ArgumentNullException("name");
                if (null == ns) 
                    ns = String.Empty;
                int index = LocateAttribute(name, ns); 
                if (-1 == index) 
                    return null;
                return GetAttribute(index); 
            }
        }

        public override string GetAttribute(string name) { 
            if (ScanState.XmlText == this.state) {
                return this.textXmlReader.GetAttribute(name); 
            } 
            else {
                int index = LocateAttribute(name); 
                if (-1 == index)
                    return null;
                return GetAttribute(index);
            } 
        }
 
        public override string GetAttribute(int i) { 
            if (ScanState.XmlText == this.state) {
                return this.textXmlReader.GetAttribute(i); 
            }
            else {
                if (i < 0 || i >= this.attrCount)
                    throw new ArgumentOutOfRangeException("i"); 
                return GetAttributeText(i);
            } 
        } 

        public override bool MoveToAttribute(string name, string ns) { 
            if (ScanState.XmlText == this.state) {
                return UpdateFromTextReader(this.textXmlReader.MoveToAttribute(name, ns));
            }
            else { 
                if (null == name)
                    throw new ArgumentNullException("name"); 
                if (null == ns) 
                    ns = String.Empty;
                int index = LocateAttribute(name, ns); 
                if ((-1 != index) && (this.state < ScanState.Init)) {
                    PositionOnAttribute(index + 1);
                    return true;
                } 
                return false;
            } 
        } 

        public override bool MoveToAttribute(string name) { 
            if (ScanState.XmlText == this.state) {
                return UpdateFromTextReader(this.textXmlReader.MoveToAttribute(name));
            }
            else { 
                int index = LocateAttribute(name);
                if ((-1 != index) && (this.state < ScanState.Init)) { 
                    PositionOnAttribute(index + 1); 
                    return true;
                } 
                return false;
            }
        }
 
        public override void MoveToAttribute(int i) {
            if (ScanState.XmlText == this.state) { 
                this.textXmlReader.MoveToAttribute(i); 
                UpdateFromTextReader(true);
            } 
            else {
                if (i < 0 || i >= this.attrCount) {
                    throw new ArgumentOutOfRangeException("i");
                } 
                PositionOnAttribute(i + 1);
            } 
        } 

        public override bool MoveToFirstAttribute() { 
            if (ScanState.XmlText == this.state) {
                return UpdateFromTextReader(this.textXmlReader.MoveToFirstAttribute());
            }
            else { 
                if (this.attrCount == 0)
                    return false; 
                // set up for walking attributes 
                PositionOnAttribute(1);
                return true; 
            }
        }

        public override bool MoveToNextAttribute() { 
            switch (this.state) {
                case ScanState.Doc: 
                case ScanState.Attr: 
                case ScanState.AttrVal:
                case ScanState.AttrValPseudoValue: 
                    if (this.attrIndex >= this.attrCount)
                        return false;
                    PositionOnAttribute(++this.attrIndex);
                    return true; 

                case ScanState.XmlText: 
                    return UpdateFromTextReader(this.textXmlReader.MoveToNextAttribute()); 

                default: 
                    return false;
            }
        }
 
        public override bool MoveToElement() {
            switch (this.state) { 
                case ScanState.Attr: 
                case ScanState.AttrVal:
                case ScanState.AttrValPseudoValue: 
                    this.attrIndex = 0;
                    this.qnameOther = this.qnameElement;
                    if (XmlNodeType.Element == this.parentNodeType)
                        this.token = BinXmlToken.Element; 
                    else if (XmlNodeType.XmlDeclaration == this.parentNodeType)
                        this.token = BinXmlToken.XmlDecl; 
                    else if (XmlNodeType.DocumentType == this.parentNodeType) 
                        this.token = BinXmlToken.DocType;
                    else 
                        Debug.Fail("Unexpected parent NodeType");
                    this.nodetype = this.parentNodeType;
                    this.state = ScanState.Doc;
                    this.pos = this.posAfterAttrs; 
                    this.stringValue = null;
                    return true; 
 
                case ScanState.XmlText:
                    return UpdateFromTextReader(this.textXmlReader.MoveToElement()); 

                default:
                    return false;
            } 
        }
 
        public override bool EOF { 
            get {
                return this.state == ScanState.EOF; 
            }
        }

        public override bool ReadAttributeValue() { 
            this.stringValue = null;
            switch (this.state) { 
                case ScanState.Attr: 
                    if (null == this.attributes[this.attrIndex - 1].val) {
                        this.pos = this.attributes[this.attrIndex - 1].contentPos; 
                        BinXmlToken tok = RescanNextToken();
                        if (BinXmlToken.Attr == tok || BinXmlToken.EndAttrs == tok) {
                            return false;
                        } 
                        this.token = tok;
                        ReScanOverValue(tok); 
                        this.valueType = GetValueType(tok); 
                        this.state = ScanState.AttrVal;
                    } 
                    else {
                        this.token = BinXmlToken.Error;
                        this.valueType = TypeOfString;
                        this.state = ScanState.AttrValPseudoValue; 
                    }
                    this.qnameOther.Clear(); 
                    this.nodetype = XmlNodeType.Text; 
                    return true;
 
                case ScanState.AttrVal:
                    return false;

                case ScanState.XmlText: 
                    return UpdateFromTextReader(this.textXmlReader.ReadAttributeValue());
 
                default: 
                    return false;
            } 
        }

        public override void Close() {
            this.state = ScanState.Closed; 
            this.nodetype = XmlNodeType.None;
            this.token = BinXmlToken.Error; 
            this.stringValue = null; 
            if (null != this.textXmlReader) {
                this.textXmlReader.Close(); 
                this.textXmlReader = null;
            }
            if (null != this.inStrm && closeInput)
                this.inStrm.Close(); 
            this.inStrm = null;
            this.pos = this.end = 0; 
        } 

        public override XmlNameTable NameTable { 
            get {
                return this.xnt;
            }
        } 

        public override string LookupNamespace(string prefix) { 
            if (ScanState.XmlText == this.state) 
                return this.textXmlReader.LookupNamespace(prefix);
            NamespaceDecl decl; 
            if (prefix != null && this.namespaces.TryGetValue(prefix, out decl)) {
                Debug.Assert(decl != null);
                return decl.uri;
            } 
            return null;
        } 
 
        public override void ResolveEntity() {
            throw new NotSupportedException(); 
        }

        public override ReadState ReadState {
            get { 
                return ScanState2ReadState[(int)this.state];
            } 
        } 

        public override bool Read() { 
            try {
                switch (this.state) {
                    case ScanState.Init:
                        return ReadInit(false); 

                    case ScanState.Doc: 
                        return ReadDoc(); 

                    case ScanState.XmlText: 
                        if (this.textXmlReader.Read()) {
                            return UpdateFromTextReader(true);
                        }
                        this.state = ScanState.Doc; 
                        this.nodetype = XmlNodeType.None;
                        this.isEmpty = false; 
                        goto case ScanState.Doc; 

                    case ScanState.Attr: 
                    case ScanState.AttrVal:
                    case ScanState.AttrValPseudoValue:
                        // clean up attribute stuff...
                        MoveToElement(); 
                        goto case ScanState.Doc;
 
                    default: 
                        return false;
                } 
            }
            catch (OverflowException e) {
                this.state = ScanState.Error;
                throw new XmlException(e.Message, e); 
            }
            catch { 
                this.state = ScanState.Error; 
                throw;
            } 
        }

        // Use default implementation of and ReadContentAsString and ReadElementContentAsString
        // (there is no benefit to providing a custom version) 
        // public override bool ReadElementContentAsString( string localName, string namespaceURI )
        // public override bool ReadElementContentAsString() 
        // public override bool ReadContentAsString() 

        // Do setup work for ReadContentAsXXX methods 
        // If ready for a typed value read, returns true, otherwise returns
        //  false to indicate caller should ball back to XmlReader.ReadContentAsXXX
        // Special-Case: returns true and positioned on Element or EndElem to force parse of empty-string
        private bool SetupContentAsXXX(string name) { 
            if (!CanReadContentAs(this.NodeType)) {
                throw CreateReadContentAsException(name); 
            } 
            switch (this.state) {
                case ScanState.Doc: 
                    if (this.NodeType == XmlNodeType.EndElement)
                        return true;
                    if (this.NodeType == XmlNodeType.ProcessingInstruction || this.NodeType == XmlNodeType.Comment) {
                        while (Read() && (this.NodeType == XmlNodeType.ProcessingInstruction || this.NodeType == XmlNodeType.Comment)) 
                            ;
                        if (this.NodeType == XmlNodeType.EndElement) 
                            return true; 
                    }
                    if (this.hasTypedValue) { 
                        return true;
                    }
                    break;
                case ScanState.Attr: 
                    this.pos = this.attributes[this.attrIndex - 1].contentPos;
                    BinXmlToken token = RescanNextToken(); 
                    if (BinXmlToken.Attr == token || BinXmlToken.EndAttrs == token) 
                        break;
                    this.token = token; 
                    ReScanOverValue(token);
                    return true;
                case ScanState.AttrVal:
                    return true; 
                default:
                    break; 
            } 
            return false;
        } 

        private int FinishContentAsXXX(int origPos) {
            if (this.state == ScanState.Doc) {
                // if we are already on a tag, then don't move 
                if (this.NodeType != XmlNodeType.Element && this.NodeType != XmlNodeType.EndElement) {
                // advance over PIs and Comments 
                Loop: 
                    if (Read()) {
                        switch (this.NodeType) { 
                            case XmlNodeType.ProcessingInstruction:
                            case XmlNodeType.Comment:
                                goto Loop;
 
                            case XmlNodeType.Element:
                            case XmlNodeType.EndElement: 
                                break; 

                            default: 
                                throw ThrowNotSupported(Res.XmlBinary_ListsOfValuesNotSupported);
                        }
                    }
                } 
                return this.pos;
            } 
            return origPos; 
        }
 
        public override bool ReadContentAsBoolean() {
            int origPos = this.pos;
            bool value = false;
            try { 
                if (SetupContentAsXXX("ReadContentAsBoolean")) {
                    try { 
                        switch (this.token) { 
                            case BinXmlToken.XSD_BOOLEAN:
                                value = 0 != this.data[this.tokDataPos]; 
                                break;

                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT: 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT: 
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY: 
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_KATMAI_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATETIME:
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_BYTE: 
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG: 
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Boolean"));

                            case BinXmlToken.SQL_CHAR: 
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT: 
                                goto Fallback;

                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem: 
                                return XmlConvert.ToBoolean(String.Empty);
 
                            default: 
                                Debug.Fail("should never happen");
                                goto Fallback; 
                        }
                    }
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, null); 
                    }
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Boolean", e, null); 
                    }
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                }
            }
            finally { 
                this.pos = origPos;
            } 
        Fallback: 
            return base.ReadContentAsBoolean();
        } 

        public override DateTime ReadContentAsDateTime() {
            int origPos = this.pos;
            DateTime value; 
            try {
                if (SetupContentAsXXX("ReadContentAsDateTime")) { 
                    try { 
                        switch (this.token) {
                            case BinXmlToken.SQL_DATETIME: 
                            case BinXmlToken.SQL_SMALLDATETIME:
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME:
                            case BinXmlToken.XSD_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                                value = ValueAsDateTime();
                                break;
 
                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT: 
                            case BinXmlToken.SQL_INT:
                            case BinXmlToken.SQL_BIGINT: 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY: 
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_BINHEX: 
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_BYTE: 
                            case BinXmlToken.XSD_UNSIGNEDSHORT:
                            case BinXmlToken.XSD_UNSIGNEDINT: 
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "DateTime"));
 
                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR: 
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR:
                            case BinXmlToken.SQL_NVARCHAR: 
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback;

                            case BinXmlToken.Element: 
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToDateTime(String.Empty, XmlDateTimeSerializationMode.RoundtripKind); 
 
                            default:
                                Debug.Fail("should never happen"); 
                                goto Fallback;
                        }
                    }
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, null);
                    } 
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, null);
                    } 
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "DateTime", e, null);
                    }
 
                    origPos = FinishContentAsXXX(origPos);
                    return value; 
                } 
            }
            finally { 
                this.pos = origPos;
            }
        Fallback:
            return base.ReadContentAsDateTime(); 
        }
 
        public override Double ReadContentAsDouble() { 
            int origPos = this.pos;
            Double value; 
            try {
                if (SetupContentAsXXX("ReadContentAsDouble")) {
                    try {
                        switch (this.token) { 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT: 
                                value = ValueAsDouble(); 
                                break;
 
                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT:
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY: 
                            case BinXmlToken.SQL_SMALLMONEY: 
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC:
                            case BinXmlToken.XSD_DECIMAL:
                            case BinXmlToken.SQL_UUID: 
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY: 
                            case BinXmlToken.SQL_IMAGE: 
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_KATMAI_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATETIME:
                            case BinXmlToken.XSD_KATMAI_TIME:
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX: 
                            case BinXmlToken.XSD_BASE64: 
                            case BinXmlToken.XSD_BOOLEAN:
                            case BinXmlToken.XSD_TIME: 
                            case BinXmlToken.XSD_DATETIME:
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG: 
                            case BinXmlToken.XSD_QNAME: 
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Double"));
 
                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT:
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT: 
                                goto Fallback; 

                            case BinXmlToken.Element: 
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToDouble(String.Empty);

                            default: 
                                Debug.Fail("should never happen");
                                goto Fallback; 
                        } 
                    }
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, null);
                    }
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, null); 
                    }
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Double", e, null); 
                    }
 
                    origPos = FinishContentAsXXX(origPos);
                    return value;
                }
            } 
            finally {
                this.pos = origPos; 
            } 
        Fallback:
            return base.ReadContentAsDouble(); 
        }

        public override float ReadContentAsFloat() {
            int origPos = this.pos; 
            float value;
            try { 
                if (SetupContentAsXXX("ReadContentAsFloat")) { 
                    try {
                        switch (this.token) { 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT:
                                value = checked (((float)ValueAsDouble()));
                                break; 

                            case BinXmlToken.SQL_BIT: 
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DATETIME: 
                            case BinXmlToken.SQL_SMALLDATETIME:
                            case BinXmlToken.SQL_DECIMAL: 
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL:
                            case BinXmlToken.SQL_UUID: 
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE: 
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Float")); 

                            case BinXmlToken.SQL_CHAR: 
                            case BinXmlToken.SQL_VARCHAR: 
                            case BinXmlToken.SQL_TEXT:
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback;
 
                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem: 
                                return XmlConvert.ToSingle(String.Empty); 

                            default: 
                                Debug.Fail("should never happen");
                                goto Fallback;
                        }
                    } 
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, null); 
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, null); 
                    }
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Float", e, null);
                    } 

                    origPos = FinishContentAsXXX(origPos); 
                    return value; 
                }
            } 
            finally {
                this.pos = origPos;
            }
        Fallback: 
            return base.ReadContentAsFloat();
        } 
 
        public override decimal ReadContentAsDecimal() {
            int origPos = this.pos; 
            decimal value;
            try {
                if (SetupContentAsXXX("ReadContentAsDecimal")) {
                    try { 
                        switch (this.token) {
                            case BinXmlToken.SQL_BIT: 
                            case BinXmlToken.SQL_TINYINT: 
                            case BinXmlToken.SQL_SMALLINT:
                            case BinXmlToken.SQL_INT: 
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DECIMAL: 
                            case BinXmlToken.SQL_NUMERIC:
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.XSD_BYTE: 
                            case BinXmlToken.XSD_UNSIGNEDSHORT:
                            case BinXmlToken.XSD_UNSIGNEDINT: 
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                                value = ValueAsDecimal();
                                break;
 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT: 
                            case BinXmlToken.SQL_DATETIME: 
                            case BinXmlToken.SQL_SMALLDATETIME:
                            case BinXmlToken.SQL_UUID: 
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME: 
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE: 
                            case BinXmlToken.XSD_QNAME:
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Decimal")); 

                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR:
                            case BinXmlToken.SQL_NVARCHAR: 
                            case BinXmlToken.SQL_NTEXT: 
                                goto Fallback;
 
                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToDecimal(String.Empty);
 
                            default:
                                Debug.Fail("should never happen"); 
                                goto Fallback; 
                        }
                    } 
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, null);
                    }
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, null);
                    } 
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Decimal", e, null);
                    } 

                    origPos = FinishContentAsXXX(origPos);
                    return value;
                } 
            }
            finally { 
                this.pos = origPos; 
            }
        Fallback: 
            return base.ReadContentAsDecimal();
        }

        public override int ReadContentAsInt() { 
            int origPos = this.pos;
            int value; 
            try { 
                if (SetupContentAsXXX("ReadContentAsInt")) {
                    try { 
                        switch (this.token) {
                            case BinXmlToken.SQL_BIT:
                            case BinXmlToken.SQL_TINYINT:
                            case BinXmlToken.SQL_SMALLINT: 
                            case BinXmlToken.SQL_INT:
                            case BinXmlToken.SQL_BIGINT: 
                            case BinXmlToken.SQL_MONEY: 
                            case BinXmlToken.SQL_SMALLMONEY:
                            case BinXmlToken.SQL_DECIMAL: 
                            case BinXmlToken.SQL_NUMERIC:
                            case BinXmlToken.XSD_DECIMAL:
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG: 
                                value = checked((int)ValueAsLong()); 
                                break;
 
                            case BinXmlToken.SQL_REAL:
                            case BinXmlToken.SQL_FLOAT:
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY: 
                            case BinXmlToken.SQL_BINARY: 
                            case BinXmlToken.SQL_IMAGE:
                            case BinXmlToken.SQL_UDT: 
                            case BinXmlToken.XSD_KATMAI_DATE:
                            case BinXmlToken.XSD_KATMAI_DATETIME:
                            case BinXmlToken.XSD_KATMAI_TIME:
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                            case BinXmlToken.XSD_BINHEX: 
                            case BinXmlToken.XSD_BASE64:
                            case BinXmlToken.XSD_BOOLEAN: 
                            case BinXmlToken.XSD_TIME:
                            case BinXmlToken.XSD_DATETIME:
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_QNAME: 
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Int32"));
 
                            case BinXmlToken.SQL_CHAR: 
                            case BinXmlToken.SQL_VARCHAR:
                            case BinXmlToken.SQL_TEXT: 
                            case BinXmlToken.SQL_NCHAR:
                            case BinXmlToken.SQL_NVARCHAR:
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback; 

                            case BinXmlToken.Element: 
                            case BinXmlToken.EndElem: 
                                return XmlConvert.ToInt32(String.Empty);
 
                            default:
                                Debug.Fail("should never happen");
                                goto Fallback;
                        } 
                    }
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int32", e, null); 
                    }
                    catch (FormatException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int32", e, null);
                    }
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int32", e, null); 
                    }
 
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                } 
            }
            finally {
                this.pos = origPos;
            } 
        Fallback:
            return base.ReadContentAsInt(); 
        } 

        public override long ReadContentAsLong() { 
            int origPos = this.pos;
            long value;
            try {
                if (SetupContentAsXXX("ReadContentAsLong")) { 
                    try {
                        switch (this.token) { 
                            case BinXmlToken.SQL_BIT: 
                            case BinXmlToken.SQL_TINYINT:
                            case BinXmlToken.SQL_SMALLINT: 
                            case BinXmlToken.SQL_INT:
                            case BinXmlToken.SQL_BIGINT:
                            case BinXmlToken.SQL_MONEY:
                            case BinXmlToken.SQL_SMALLMONEY: 
                            case BinXmlToken.SQL_DECIMAL:
                            case BinXmlToken.SQL_NUMERIC: 
                            case BinXmlToken.XSD_DECIMAL: 
                            case BinXmlToken.XSD_BYTE:
                            case BinXmlToken.XSD_UNSIGNEDSHORT: 
                            case BinXmlToken.XSD_UNSIGNEDINT:
                            case BinXmlToken.XSD_UNSIGNEDLONG:
                                value = ValueAsLong();
                                break; 

                            case BinXmlToken.SQL_REAL: 
                            case BinXmlToken.SQL_FLOAT: 
                            case BinXmlToken.SQL_DATETIME:
                            case BinXmlToken.SQL_SMALLDATETIME: 
                            case BinXmlToken.SQL_UUID:
                            case BinXmlToken.SQL_VARBINARY:
                            case BinXmlToken.SQL_BINARY:
                            case BinXmlToken.SQL_IMAGE: 
                            case BinXmlToken.SQL_UDT:
                            case BinXmlToken.XSD_KATMAI_DATE: 
                            case BinXmlToken.XSD_KATMAI_DATETIME: 
                            case BinXmlToken.XSD_KATMAI_TIME:
                            case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                            case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                            case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                            case BinXmlToken.XSD_BINHEX:
                            case BinXmlToken.XSD_BASE64: 
                            case BinXmlToken.XSD_BOOLEAN:
                            case BinXmlToken.XSD_TIME: 
                            case BinXmlToken.XSD_DATETIME: 
                            case BinXmlToken.XSD_DATE:
                            case BinXmlToken.XSD_QNAME: 
                                throw new InvalidCastException(Res.GetString(Res.XmlBinary_CastNotSupported, this.token, "Int64"));

                            case BinXmlToken.SQL_CHAR:
                            case BinXmlToken.SQL_VARCHAR: 
                            case BinXmlToken.SQL_TEXT:
                            case BinXmlToken.SQL_NCHAR: 
                            case BinXmlToken.SQL_NVARCHAR: 
                            case BinXmlToken.SQL_NTEXT:
                                goto Fallback; 

                            case BinXmlToken.Element:
                            case BinXmlToken.EndElem:
                                return XmlConvert.ToInt64(String.Empty); 

                            default: 
                                Debug.Fail("should never happen"); 
                                goto Fallback;
                        } 
                    }
                    catch (InvalidCastException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int64", e, null);
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int64", e, null); 
                    } 
                    catch (OverflowException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Int64", e, null); 
                    }

                    origPos = FinishContentAsXXX(origPos);
                    return value; 
                }
            } 
            finally { 
                this.pos = origPos;
            } 
        Fallback:
            return base.ReadContentAsLong();
        }
 
        public override object ReadContentAsObject() {
            int origPos = this.pos; 
            try { 
                if (SetupContentAsXXX("ReadContentAsObject")) {
                    object value; 
                    try {
                        if (this.NodeType == XmlNodeType.Element || this.NodeType == XmlNodeType.EndElement)
                            value = String.Empty;
                        else 
                            value = this.ValueAsObject(this.token, false);
                    } 
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Object", e, null);
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Object", e, null);
                    }
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, "Object", e, null);
                    } 
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                } 
            }
            finally {
                this.pos = origPos;
            } 
            //Fallback:
            return base.ReadContentAsObject(); 
        } 

        public override object ReadContentAs(Type returnType, IXmlNamespaceResolver namespaceResolver) { 
            int origPos = this.pos;
            try {
                if (SetupContentAsXXX("ReadContentAs")) {
                    object value; 
                    try {
                        if (this.NodeType == XmlNodeType.Element || this.NodeType == XmlNodeType.EndElement) { 
                            value = String.Empty; 
                        }
                        else if (returnType == this.ValueType || returnType == typeof(object)) { 
                            value = this.ValueAsObject(this.token, false);
                        }
                        else {
                            value = this.ValueAs(this.token, returnType, namespaceResolver); 
                        }
                    } 
                    catch (InvalidCastException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, null);
                    } 
                    catch (FormatException e) {
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, null);
                    }
                    catch (OverflowException e) { 
                        throw new XmlException(Res.Xml_ReadContentAsFormatException, returnType.ToString(), e, null);
                    } 
                    origPos = FinishContentAsXXX(origPos); 
                    return value;
                } 
            }
            finally {
                this.pos = origPos;
            } 
            return base.ReadContentAs(returnType, namespaceResolver);
        } 
 
        //////////
        // IXmlNamespaceResolver 

        System.Collections.Generic.IDictionary IXmlNamespaceResolver.GetNamespacesInScope(XmlNamespaceScope scope) {
            if (ScanState.XmlText == this.state) {
                IXmlNamespaceResolver resolver = (IXmlNamespaceResolver)this.textXmlReader; 
                return resolver.GetNamespacesInScope(scope);
            } 
            else { 
                Dictionary nstable = new Dictionary();
                if (XmlNamespaceScope.Local == scope) { 
                    // are we even inside an element? (depth==0 is where we have xml, and xmlns declared...)
                    if (this.elemDepth > 0) {
                        NamespaceDecl nsdecl = this.elementStack[this.elemDepth].nsdecls;
                        while (null != nsdecl) { 
                            nstable.Add(nsdecl.prefix, nsdecl.uri);
                            nsdecl = nsdecl.scopeLink; 
                        } 
                    }
                } 
                else {
                    foreach (NamespaceDecl nsdecl in this.namespaces.Values) {
                        // don't add predefined decls unless scope == all, then only add 'xml'
                        if (nsdecl.scope != -1 || (XmlNamespaceScope.All == scope && "xml" == nsdecl.prefix)) { 
                            // xmlns="" only ever reported via scope==local
                            if (nsdecl.prefix.Length > 0 || nsdecl.uri.Length > 0) 
                                nstable.Add(nsdecl.prefix, nsdecl.uri); 
                        }
                    } 
                }
                return nstable;
            }
        } 

        string IXmlNamespaceResolver.LookupPrefix(string namespaceName) { 
            if (ScanState.XmlText == this.state) { 
                IXmlNamespaceResolver resolver = (IXmlNamespaceResolver)this.textXmlReader;
                return resolver.LookupPrefix(namespaceName); 
            }
            else {
                if (null == namespaceName)
                    return null; 

                namespaceName = this.xnt.Get(namespaceName); 
                if (null == namespaceName) 
                    return null;
 
                for (int i = this.elemDepth; i >= 0; i--) {
                    NamespaceDecl nsdecl = this.elementStack[i].nsdecls;
                    while (null != nsdecl) {
                        if ((object)nsdecl.uri == (object)namespaceName) 
                            return nsdecl.prefix;
                        nsdecl = nsdecl.scopeLink; 
                    } 
                }
                return null; 
            }
        }

        ////////// 
        // Internal implementation methods
 
        void VerifyVersion(int requiredVersion, BinXmlToken token) { 
            if (version < requiredVersion) {
                throw ThrowUnexpectedToken(token); 
            }
        }

        void AddInitNamespace(string prefix, string uri) { 
            NamespaceDecl nsdecl = new NamespaceDecl(prefix, uri, this.elementStack[0].nsdecls, null, -1, true);
            this.elementStack[0].nsdecls = nsdecl; 
            this.namespaces.Add(prefix, nsdecl); 
        }
 
        void AddName() {
            string txt = ParseText();
            int symNum = this.symbolTables.symCount++;
            string[] symtable = this.symbolTables.symtable; 
            if (symNum == symtable.Length) {
                string[] n = new string[checked(symNum * 2)]; 
                System.Array.Copy(symtable, 0, n, 0, symNum); 
                this.symbolTables.symtable = symtable = n;
            } 
            symtable[symNum] = xnt.Add(txt);
        }

        void AddQName() { 
            int nsUri = ReadNameRef();
            int prefix = ReadNameRef(); 
            int lname = ReadNameRef(); 
            int qnameNum = this.symbolTables.qnameCount++;
            QName[] qnametable = this.symbolTables.qnametable; 
            if (qnameNum == qnametable.Length) {
                QName[] n = new QName[checked(qnameNum * 2)];
                System.Array.Copy(qnametable, 0, n, 0, qnameNum);
                this.symbolTables.qnametable = qnametable = n; 
            }
            string[] symtable = this.symbolTables.symtable; 
            string prefixStr = symtable[prefix]; 
            string lnameStr;
            string nsUriStr; 
            // xmlns attributes are encodes differently...
            if (lname == 0) { // xmlns attribute
                // for some reason, sqlserver sometimes generates these...
                if (prefix == 0 && nsUri == 0) 
                    return;
                // it is a real namespace decl, make sure it looks valid 
                if (!prefixStr.StartsWith("xmlns", StringComparison.Ordinal)) 
                    goto BadDecl;
                if (5 < prefixStr.Length) { 
                    if (6 == prefixStr.Length || ':' != prefixStr[5])
                        goto BadDecl;
                    lnameStr = this.xnt.Add(prefixStr.Substring(6));
                    prefixStr = this.xmlns; 
                }
                else { 
                    lnameStr = prefixStr; 
                    prefixStr = String.Empty;
                } 
                nsUriStr = this.nsxmlns;
            }
            else {
                lnameStr = symtable[lname]; 
                nsUriStr = symtable[nsUri];
            } 
            qnametable[qnameNum].Set(prefixStr, lnameStr, nsUriStr); 
            return;
        BadDecl: 
            throw new XmlException(Res.Xml_BadNamespaceDecl, (string[])null);
        }

        private void NameFlush() { 
            this.symbolTables.symCount = this.symbolTables.qnameCount = 1;
            Array.Clear(this.symbolTables.symtable, 1, this.symbolTables.symtable.Length - 1); 
            Array.Clear(this.symbolTables.qnametable, 0, this.symbolTables.qnametable.Length); 
        }
 
        private void SkipExtn() {
            int cb = ParseMB32();
            checked{this.pos += cb;}
            Fill(-1); 
        }
 
        private int ReadQNameRef() { 
            int nameNum = ParseMB32();
            if (nameNum < 0 || nameNum >= this.symbolTables.qnameCount) 
                throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
            return nameNum;
        }
 
        private int ReadNameRef() {
            int nameNum = ParseMB32(); 
            if (nameNum < 0 || nameNum >= this.symbolTables.symCount) 
                throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
            return nameNum; 
        }

        // pull more data from input stream
        private bool FillAllowEOF() { 
            if (this.eof)
                return false; 
            byte[] data = this.data; 
            int pos = this.pos;
            int mark = this.mark; 
            int end = this.end;
            if (mark == -1) {
                mark = pos;
            } 
            if (mark >= 0 && mark < end) {
                Debug.Assert(this.mark <= this.end, "Mark should never be past End"); 
                Debug.Assert(this.mark <= this.pos, "Mark should never be after Pos"); 
                int cbKeep = end - mark;
                if (cbKeep > 7 * (data.Length / 8)) { 
                    // grow buffer
                    byte[] newdata = new byte[checked(data.Length * 2)];
                    System.Array.Copy(data, mark, newdata, 0, cbKeep);
                    this.data = data = newdata; 
                }
                else { 
                    System.Array.Copy(data, mark, data, 0, cbKeep); 
                }
                pos -= mark; 
                end -= mark;
                this.tokDataPos -= mark;
                for (int i = 0; i < this.attrCount; i++) {
                    this.attributes[i].AdjustPosition(-mark); 
                    // make sure it is still a valid range
                    Debug.Assert((this.attributes[i].contentPos >= 0) && (this.attributes[i].contentPos <= (end))); 
                } 
                this.pos = pos;
                this.mark = 0; 
                this.offset += mark;
            }
            else {
                Debug.Assert(this.attrCount == 0); 
                this.pos -= end;
                this.mark -= end; 
                this.offset += end; 
                this.tokDataPos -= end;
                end = 0; 
            }
            int cbFill = data.Length - end;
            int cbRead = this.inStrm.Read(data, end, cbFill);
            this.end = end + cbRead; 
            this.eof = !(cbRead > 0);
            return (cbRead > 0); 
        } 

        // require must be < 1/8 buffer, or else Fill might not actually 
        // grab that much data
        void Fill_(int require) {
            Debug.Assert((this.pos + require) >= this.end);
            while (FillAllowEOF() && ((this.pos + require) >= this.end)) 
                ;
            if ((this.pos + require) >= this.end) 
                throw ThrowXmlException(Res.Xml_UnexpectedEOF1); 
        }
 
        // inline the common case
        void Fill(int require) {
            if ((this.pos + require) >= this.end)
                Fill_(require); 
        }
 
        byte ReadByte() { 
            Fill(0);
            return this.data[this.pos++]; 
        }
        ushort ReadUShort() {
            Fill(1);
            int pos = this.pos; byte[] data = this.data; 
            ushort val = (ushort)(data[pos] + (data[pos + 1] << 8));
            this.pos += 2; 
            return val; 
        }
 
        int ParseMB32() {
            byte b = ReadByte();
            if (b > 127)
                return ParseMB32_(b); 
            return b;
        } 
 
        int ParseMB32_(byte b) {
            uint u, t; 
            u = (uint)b & (uint)0x7F;
            Debug.Assert(0 != (b & 0x80));
            b = ReadByte();
            t = (uint)b & (uint)0x7F; 
            u = u + (t << 7);
            if (b > 127) { 
                b = ReadByte(); 
                t = (uint)b & (uint)0x7F;
                u = u + (t << 14); 
                if (b > 127) {
                    b = ReadByte();
                    t = (uint)b & (uint)0x7F;
                    u = u + (t << 21); 
                    if (b > 127) {
                        b = ReadByte(); 
                        // bottom 4 bits are all that are needed, 
                        // but we are mapping to 'int', which only
                        // actually has space for 3 more bits. 
                        t = (uint)b & (uint)0x07;
                        if (b > 7)
                            throw ThrowXmlException(Res.XmlBinary_ValueTooBig);
                        u = u + (t << 28); 
                    }
                } 
            } 
            return (int)u;
        } 

        // this assumes that we have already ensured that all
        // necessary bytes are loaded in to the buffer
        int ParseMB32(int pos) { 
            uint u, t;
            byte[] data = this.data; 
            byte b = data[pos++]; 
            u = (uint)b & (uint)0x7F;
            if (b > 127) { 
                b = data[pos++];
                t = (uint)b & (uint)0x7F;
                u = u + (t << 7);
                if (b > 127) { 
                    b = data[pos++];
                    t = (uint)b & (uint)0x7F; 
                    u = u + (t << 14); 
                    if (b > 127) {
                        b = data[pos++]; 
                        t = (uint)b & (uint)0x7F;
                        u = u + (t << 21);
                        if (b > 127) {
                            b = data[pos++]; 
                            // last byte only has 4 significant digits
                            t = (uint)b & (uint)0x07; 
                            if (b > 7) 
                                throw ThrowXmlException(Res.XmlBinary_ValueTooBig);
                            u = u + (t << 28); 
                        }
                    }
                }
            } 
            return (int)u;
        } 
 
        // we don't actually support MB64, since we use int for
        // all our math anyway... 
        int ParseMB64() {
            byte b = ReadByte();
            if (b > 127)
                return ParseMB32_(b); 
            return b;
        } 
 
        BinXmlToken PeekToken() {
            while ((this.pos >= this.end) && FillAllowEOF()) 
                ;
            if (this.pos >= this.end)
                return BinXmlToken.EOF;
            return (BinXmlToken)this.data[this.pos]; 
        }
 
        BinXmlToken ReadToken() { 
            while ((this.pos >= this.end) && FillAllowEOF())
                ; 
            if (this.pos >= this.end)
                return BinXmlToken.EOF;
            return (BinXmlToken)this.data[this.pos++];
        } 

        BinXmlToken NextToken2(BinXmlToken token) { 
            while (true) { 
                switch (token) {
                    case BinXmlToken.Name: 
                        AddName();
                        break;
                    case BinXmlToken.QName:
                        AddQName(); 
                        break;
                    case BinXmlToken.NmFlush: 
                        NameFlush(); 
                        break;
                    case BinXmlToken.Extn: 
                        SkipExtn();
                        break;
                    default:
                        return token; 
                }
                token = ReadToken(); 
            } 
        }
 
        BinXmlToken NextToken1() {
            BinXmlToken token;
            int pos = this.pos;
            if (pos >= this.end) 
                token = ReadToken();
            else { 
                token = (BinXmlToken)this.data[pos]; 
                this.pos = pos + 1;
            } 
            // BinXmlToken.Name = 0xF0
            // BinXmlToken.QName = 0xEF
            // BinXmlToken.Extn = 0xEA,
            // BinXmlToken.NmFlush = 0xE9, 
            if (token >= BinXmlToken.NmFlush
                && token <= BinXmlToken.Name) 
                return NextToken2(token); 
            return token;
        } 

        BinXmlToken NextToken() {
            int pos = this.pos;
            if (pos < this.end) { 
                BinXmlToken t = (BinXmlToken)this.data[pos];
                if (!(t >= BinXmlToken.NmFlush && t <= BinXmlToken.Name)) { 
                    this.pos = pos + 1; 
                    return t;
                } 
            }
            return NextToken1();
        }
 
        // peek next non-meta token
        BinXmlToken PeekNextToken() { 
            BinXmlToken token = NextToken(); 
            if (BinXmlToken.EOF != token)
                this.pos--; 
            return token;
        }

        // like NextToken() but meta-tokens are skipped (not reinterpreted) 
        BinXmlToken RescanNextToken() {
            BinXmlToken token; 
            while (true) { 
                token = ReadToken();
                switch (token) { 
                    case BinXmlToken.Name: {
                            int cb = ParseMB32();
                            checked{this.pos += 2 * cb;}
                            break; 
                        }
                    case BinXmlToken.QName: 
                        ParseMB32(); 
                        ParseMB32();
                        ParseMB32(); 
                        break;
                    case BinXmlToken.Extn: {
                            int cb = ParseMB32();
                            checked{this.pos += cb;} 
                            break;
                        } 
                    case BinXmlToken.NmFlush: 
                        break;
                    default: 
                        return token;
                }
            }
        } 

        string ParseText() { 
            int oldmark = this.mark; 
            try {
                if (oldmark < 0) 
                    this.mark = this.pos;
                int cch, pos;
                cch = ScanText(out pos);
                return GetString(pos, cch); 
            }
            finally { 
                if (oldmark < 0) 
                    this.mark = -1;
            } 
        }

        int ScanText(out int start) {
            int cch = ParseMB32(); 
            int oldmark = this.mark;
            int begin = this.pos; 
            checked{this.pos += cch * 2;} // cch = num utf-16 chars 
            if (this.pos > this.end)
                Fill(-1); 
            // Fill call might have moved buffer
            start = begin - (oldmark - this.mark);
            return cch;
        } 

        string GetString(int pos, int cch) { 
            Debug.Assert(pos >= 0 && cch >= 0); 
            if (checked(pos + (cch * 2)) > this.end)
                throw new XmlException(Res.Xml_UnexpectedEOF1, (string[])null); 
            if (cch == 0)
                return String.Empty;
            // GetStringUnaligned is _significantly_ faster than unicode.GetString()
            // but since IA64 doesn't support unaligned reads, we can't do it if 
            // the address is not aligned properly.  Since the byte[] will be aligned,
            // we can detect address alignment my just looking at the offset 
            if ((pos & 1) == 0) 
                return GetStringAligned(this.data, pos, cch);
            else 
                return unicode.GetString(this.data, pos, checked(cch * 2));
        }

        unsafe String GetStringAligned(byte[] data, int offset, int cch) { 
            Debug.Assert((offset & 1) == 0);
            fixed (byte* pb = data) { 
                char* p = (char*)(pb + offset); 
                return new String(p, 0, cch);
            } 
        }

        private string GetAttributeText(int i) {
            string val = this.attributes[i].val; 

            if (null != val) 
                return val; 
            else {
                int origPos = this.pos; 
                try {
                    this.pos = this.attributes[i].contentPos;
                    BinXmlToken token = RescanNextToken();
                    if (BinXmlToken.Attr == token || BinXmlToken.EndAttrs == token) { 
                        return "";
                    } 
                    this.token = token; 
                    ReScanOverValue(token);
                    return ValueAsString(token); 
                }
                finally {
                    this.pos = origPos;
                } 
            }
        } 
 
        private int LocateAttribute(string name, string ns) {
            for (int i = 0; i < this.attrCount; i++) { 
                if (this.attributes[i].name.MatchNs(name, ns))
                    return i;
            }
 
            return -1;
        } 
 
        private int LocateAttribute(string name) {
            string prefix, lname; 
            ValidateNames.SplitQName(name, out prefix, out lname);

            for (int i = 0; i < this.attrCount; i++) {
                if (this.attributes[i].name.MatchPrefix(prefix, lname)) 
                    return i;
            } 
 
            return -1;
        } 

        private void PositionOnAttribute(int i) {
            // save element's qname
            this.attrIndex = i; 
            this.qnameOther = this.attributes[i - 1].name;
            if (this.state == ScanState.Doc) { 
                this.parentNodeType = this.nodetype; 
            }
            this.token = BinXmlToken.Attr; 
            this.nodetype = XmlNodeType.Attribute;
            this.state = ScanState.Attr;
            this.valueType = TypeOfObject;
            this.stringValue = null; 
        }
 
        void GrowElements() { 
            int newcount = this.elementStack.Length * 2;
            ElemInfo[] n = new ElemInfo[newcount]; 

            System.Array.Copy(this.elementStack, 0, n, 0, this.elementStack.Length);
            this.elementStack = n;
        } 

        void GrowAttributes() { 
            int newcount = this.attributes.Length * 2; 
            AttrInfo[] n = new AttrInfo[newcount];
 
            System.Array.Copy(this.attributes, 0, n, 0, this.attrCount);
            this.attributes = n;
        }
 
        void ClearAttributes() {
            if (this.attrCount != 0) 
                this.attrCount = 0; 
        }
 
        void PushNamespace(string prefix, string ns, bool implied) {
            if (prefix == "xml")
                return;
            int elemDepth = this.elemDepth; 
            NamespaceDecl curDecl;
            this.namespaces.TryGetValue(prefix, out curDecl); 
            if (null != curDecl) { 
                if (curDecl.uri == ns) {
                    // if we see the nsdecl after we saw the first reference in this scope 
                    // fix up 'implied' flag
                    if (!implied && curDecl.implied
                        && (curDecl.scope == elemDepth)) {
                        curDecl.implied = false; 
                    }
                    return; 
                } 
                // check that this doesn't conflict
                this.qnameElement.CheckPrefixNS(prefix, ns); 
                if (prefix.Length != 0) {
                    for (int i = 0; i < this.attrCount; i++) {
                        if (this.attributes[i].name.prefix.Length != 0)
                            this.attributes[i].name.CheckPrefixNS(prefix, ns); 
                    }
                } 
            } 
            // actually add ns decl
            NamespaceDecl decl = new NamespaceDecl(prefix, ns, 
                this.elementStack[elemDepth].nsdecls,
                curDecl, elemDepth, implied);
            this.elementStack[elemDepth].nsdecls = decl;
            this.namespaces[prefix] = decl; 
        }
 
        void PopNamespaces(NamespaceDecl firstInScopeChain) { 
            NamespaceDecl decl = firstInScopeChain;
            while (null != decl) { 
                if (null == decl.prevLink)
                    this.namespaces.Remove(decl.prefix);
                else
                    this.namespaces[decl.prefix] = decl.prevLink; 
                NamespaceDecl next = decl.scopeLink;
                // unlink chains for better gc behaviour 
                decl.prevLink = null; 
                decl.scopeLink = null;
                decl = next; 
            }
        }

        void GenerateImpliedXmlnsAttrs() { 
            QName name;
            NamespaceDecl decl = this.elementStack[this.elemDepth].nsdecls; 
            while (null != decl) { 
                if (decl.implied) {
                    if (this.attrCount == this.attributes.Length) 
                        GrowAttributes();
                    if (decl.prefix.Length == 0)
                        name = new QName(string.Empty, this.xmlns, this.nsxmlns);
                    else 
                        name = new QName(this.xmlns, xnt.Add(decl.prefix), this.nsxmlns);
                    this.attributes[this.attrCount].Set(name, decl.uri); 
                    this.attrCount++; 
                }
                decl = decl.scopeLink; 
            }
        }

        bool ReadInit(bool skipXmlDecl) { 
            string err = null;
            if (!sniffed) { 
                // check magic header 
                ushort magic = ReadUShort();
                if (magic != 0xFFDF) { 
                    err = Res.XmlBinary_InvalidSignature;
                    goto Error;
                }
            } 

            // check protocol version 
            this.version = ReadByte(); 
            if (version != 0x1 && version != 0x2) {
                err = Res.XmlBinary_InvalidProtocolVersion; 
                goto Error;
            }

            // check encoding marker, 1200 == utf16 
            if (1200 != ReadUShort()) {
                err = Res.XmlBinary_UnsupportedCodePage; 
                goto Error; 
            }
 
            this.state = ScanState.Doc;
            if (BinXmlToken.XmlDecl == PeekToken()) {
                this.pos++;
                this.attributes[0].Set(new QName(string.Empty, this.xnt.Add("version"), string.Empty), ParseText()); 
                this.attrCount = 1;
                if (BinXmlToken.Encoding == PeekToken()) { 
                    this.pos++; 
                    this.attributes[1].Set(new QName(string.Empty, this.xnt.Add("encoding"), string.Empty), ParseText());
                    this.attrCount++; 
                }

                byte standalone = ReadByte();
                switch (standalone) { 
                    case 0:
                        break; 
                    case 1: 
                    case 2:
                        this.attributes[this.attrCount].Set(new QName(string.Empty, this.xnt.Add("standalone"), string.Empty), (standalone == 1) ? "yes" : "no"); 
                        this.attrCount++;
                        break;
                    default:
                        err = Res.XmlBinary_InvalidStandalone; 
                        goto Error;
                } 
                if (!skipXmlDecl) { 
                    QName xmlDeclQName = new QName(String.Empty, this.xnt.Add("xml"), String.Empty);
                    this.qnameOther = this.qnameElement = xmlDeclQName; 
                    this.nodetype = XmlNodeType.XmlDeclaration;
                    this.posAfterAttrs = this.pos;
                    return true;
                } 
                // else ReadDoc will clear the attributes for us
            } 
            return ReadDoc(); 

        Error: 
            this.state = ScanState.Error;
            throw new XmlException(err, (string[])null);
        }
 
        void ScanAttributes() {
            BinXmlToken token; 
            int xmlspace = -1; 
            int xmllang = -1;
 
            this.mark = this.pos;
            string curDeclPrefix = null;
            bool lastWasValue = false;
 
            while (BinXmlToken.EndAttrs != (token = NextToken())) {
                if (BinXmlToken.Attr == token) { 
                    // watch out for nsdecl with no actual content 
                    if (null != curDeclPrefix) {
                        PushNamespace(curDeclPrefix, string.Empty, false); 
                        curDeclPrefix = null;
                    }
                    // do we need to grow the array?
                    if (this.attrCount == this.attributes.Length) 
                        GrowAttributes();
                    // note: ParseMB32 _must_ happen _before_ we grab this.pos... 
                    QName n = this.symbolTables.qnametable[ReadQNameRef()]; 
                    this.attributes[this.attrCount].Set(n, (int)this.pos);
                    if (n.prefix == "xml") { 
                        if (n.localname == "lang") {
                            xmllang = this.attrCount;
                        }
                        else if (n.localname == "space") { 
                            xmlspace = this.attrCount;
                        } 
                    } 
                    else if (Ref.Equal(n.namespaceUri, this.nsxmlns)) {
                        // push namespace when we get the value 
                        curDeclPrefix = n.localname;
                        if (curDeclPrefix == "xmlns")
                            curDeclPrefix = string.Empty;
                    } 
                    else if (n.prefix.Length != 0) {
                        if (n.namespaceUri.Length == 0) 
                            throw new XmlException(Res.Xml_PrefixForEmptyNs, String.Empty); 
                        this.PushNamespace(n.prefix, n.namespaceUri, true);
                    } 
                    else if (n.namespaceUri.Length != 0) {
                        throw ThrowXmlException(Res.XmlBinary_AttrWithNsNoPrefix, n.localname, n.namespaceUri);
                    }
                    this.attrCount++; 
                    lastWasValue = false;
                } 
                else { 
                    // first scan over token to make sure it is a value token
                    ScanOverValue(token, true, true); 
                    // don't allow lists of values
                    if (lastWasValue) {
                        throw ThrowNotSupported(Res.XmlBinary_ListsOfValuesNotSupported);
                    } 

                    // if char checking is on, we need to scan text values to 
                    // validate that they don't use invalid CharData, so we 
                    // might as well store the saved string for quick attr value access
                    string val = this.stringValue; 
                    if (null != val) {
                        this.attributes[this.attrCount - 1].val = val;
                        this.stringValue = null;
                    } 
                    // namespace decls can only have text values, and should only
                    // have a single value, so we just grab it here... 
                    if (null != curDeclPrefix) { 
                        string nsuri = this.xnt.Add(ValueAsString(token));
                        PushNamespace(curDeclPrefix, nsuri, false); 
                        curDeclPrefix = null;
                    }
                    lastWasValue = true;
                } 
            }
 
            if (xmlspace != -1) { 
                string val = GetAttributeText(xmlspace);
                XmlSpace xs = XmlSpace.None; 
                if (val == "preserve")
                    xs = XmlSpace.Preserve;
                else if (val == "default")
                    xs = XmlSpace.Default; 
                this.elementStack[this.elemDepth].xmlSpace = xs;
                this.xmlspacePreserve = (XmlSpace.Preserve == xs); 
            } 
            if (xmllang != -1) {
                this.elementStack[this.elemDepth].xmlLang = GetAttributeText(xmllang); 
            }

            if (this.attrCount < 200)
                SimpleCheckForDuplicateAttributes(); 
            else
                HashCheckForDuplicateAttributes(); 
        } 

        void SimpleCheckForDuplicateAttributes() { 
            for (int i = 0; i < this.attrCount; i++) {
                string localname, namespaceUri;
                this.attributes[i].GetLocalnameAndNamespaceUri(out localname, out namespaceUri);
                for (int j = i + 1; j < this.attrCount; j++) { 
                    if (this.attributes[j].MatchNS(localname, namespaceUri))
                        throw new XmlException(Res.Xml_DupAttributeName, this.attributes[i].name.ToString()); 
                } 
            }
        } 

        void HashCheckForDuplicateAttributes() {
            int tblSize = 256;
            while (tblSize < this.attrCount) 
                tblSize = checked(tblSize * 2);
            if (this.attrHashTbl.Length < tblSize) 
                this.attrHashTbl = new int[tblSize]; 
            for (int i = 0; i < this.attrCount; i++) {
                string localname, namespaceUri; 
                int hash = this.attributes[i].GetLocalnameAndNamespaceUriAndHash(hasher, out localname, out namespaceUri);
                int index = hash & (tblSize - 1);
                int next = this.attrHashTbl[index];
                this.attrHashTbl[index] = i + 1; 
                this.attributes[i].prevHash = next;
                while (next != 0) { 
                    next--; 
                    if (this.attributes[next].MatchHashNS(hash, localname, namespaceUri)) {
                        throw new XmlException(Res.Xml_DupAttributeName, this.attributes[i].name.ToString()); 
                    }
                    next = this.attributes[next].prevHash;
                }
            } 
            Array.Clear(this.attrHashTbl, 0, tblSize);
        } 
 
        string XmlDeclValue() {
            StringBuilder sb = new StringBuilder(); 
            for (int i = 0; i < this.attrCount; i++) {
                if (i > 0)
                    sb.Append(' ');
                sb.Append(this.attributes[i].name.localname); 
                sb.Append("=\"");
                sb.Append(this.attributes[i].val); 
                sb.Append('"'); 
            }
            return sb.ToString(); 
        }

        string CDATAValue() {
            Debug.Assert(this.stringValue == null, "this.stringValue == null"); 
            Debug.Assert(this.token == BinXmlToken.CData, "this.token == BinXmlToken.CData");
            String value = GetString(this.tokDataPos, this.tokLen); 
            StringBuilder sb = null; 
            while (PeekToken() == BinXmlToken.CData) {
                this.pos++; // skip over token byte 
                if (sb == null) {
                    sb = new StringBuilder(value.Length + value.Length / 2);
                    sb.Append(value);
                } 
                sb.Append(ParseText());
            } 
            if (sb != null) 
                value = sb.ToString();
            this.stringValue = value; 
            return value;
        }

        void FinishCDATA() { 
            for (; ; ) {
                switch (PeekToken()) { 
                    case BinXmlToken.CData: 
                        // skip
                        this.pos++; 
                        int pos;
                        ScanText(out pos);
                        // try again
                        break; 
                    case BinXmlToken.EndCData:
                        // done... on to next token... 
                        this.pos++; 
                        return;
                    default: 
                        throw new XmlException(Res.XmlBin_MissingEndCDATA);
                }
            }
        } 

        void FinishEndElement() { 
            NamespaceDecl nsdecls = this.elementStack[this.elemDepth].Clear(); 
            this.PopNamespaces(nsdecls);
            this.elemDepth--; 
        }

        bool ReadDoc() {
            switch (this.nodetype) { 
                case XmlNodeType.CDATA:
                    FinishCDATA(); 
                    break; 
                case XmlNodeType.EndElement:
                    FinishEndElement(); 
                    break;
                case XmlNodeType.Element:
                    if (this.isEmpty) {
                        FinishEndElement(); 
                        this.isEmpty = false;
                    } 
                    break; 
            }
 
        Read:
            // clear existing state
            this.nodetype = XmlNodeType.None;
            this.mark = -1; 
            if (this.qnameOther.localname.Length != 0)
                this.qnameOther.Clear(); 
 
            ClearAttributes();
            this.attrCount = 0; 
            this.valueType = TypeOfString;
            this.stringValue = null;
            this.hasTypedValue = false;
 
            this.token = NextToken();
            switch (this.token) { 
                case BinXmlToken.EOF: 
                    if (this.elemDepth > 0)
                        throw new XmlException(Res.Xml_UnexpectedEOF1, (string[])null); 
                    this.state = ScanState.EOF;
                    return false;

                case BinXmlToken.Element: 
                    ImplReadElement();
                    break; 
 
                case BinXmlToken.EndElem:
                    ImplReadEndElement(); 
                    break;

                case BinXmlToken.DocType:
                    ImplReadDoctype(); 
                    if (this.dtdProcessing == DtdProcessing.Ignore)
                        goto Read; 
                    // nested, don't report doctype 
                    if (prevNameInfo != null)
                        goto Read; 
                    break;

                case BinXmlToken.PI:
                    ImplReadPI(); 
                    if (this.ignorePIs)
                        goto Read; 
                    break; 

                case BinXmlToken.Comment: 
                    ImplReadComment();
                    if (this.ignoreComments)
                        goto Read;
                    break; 

                case BinXmlToken.CData: 
                    ImplReadCDATA(); 
                    break;
 
                case BinXmlToken.Nest:
                    ImplReadNest();
                    // parse first token in nested document
                    sniffed = false; 
                    return ReadInit(true);
 
                case BinXmlToken.EndNest: 
                    if (null == this.prevNameInfo)
                        goto default; 
                    ImplReadEndNest();
                    return ReadDoc();

                case BinXmlToken.XmlText: 
                    ImplReadXmlText();
                    break; 
 
                // text values
                case BinXmlToken.SQL_BIT: 
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT:
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.SQL_REAL:
                case BinXmlToken.SQL_FLOAT: 
                case BinXmlToken.SQL_MONEY: 
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_DATETIME: 
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.SQL_DECIMAL:
                case BinXmlToken.SQL_NUMERIC:
                case BinXmlToken.XSD_DECIMAL: 
                case BinXmlToken.SQL_UUID:
                case BinXmlToken.SQL_VARBINARY: 
                case BinXmlToken.SQL_BINARY: 
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT: 
                case BinXmlToken.XSD_KATMAI_DATE:
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME:
                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                case BinXmlToken.XSD_BINHEX: 
                case BinXmlToken.XSD_BASE64:
                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT:
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR: 
                case BinXmlToken.SQL_NTEXT:
                case BinXmlToken.XSD_BOOLEAN: 
                case BinXmlToken.XSD_TIME: 
                case BinXmlToken.XSD_DATETIME:
                case BinXmlToken.XSD_DATE: 
                case BinXmlToken.XSD_BYTE:
                case BinXmlToken.XSD_UNSIGNEDSHORT:
                case BinXmlToken.XSD_UNSIGNEDINT:
                case BinXmlToken.XSD_UNSIGNEDLONG: 
                case BinXmlToken.XSD_QNAME:
                    ImplReadData(this.token); 
                    if (XmlNodeType.Text == this.nodetype) 
                        CheckAllowContent();
                    else if (this.ignoreWhitespace && !this.xmlspacePreserve) 
                        goto Read; // skip to next token
                    return true;

                default: 
                    throw ThrowUnexpectedToken(token);
            } 
 
            return true;
        } 

        void ImplReadData(BinXmlToken tokenType) {
            Debug.Assert(this.mark < 0);
            this.mark = this.pos; 

            switch (tokenType) { 
                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT: 
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR:
                case BinXmlToken.SQL_NTEXT:
                    this.valueType = TypeOfString; 
                    this.hasTypedValue = false;
                    break; 
                default: 
                    this.valueType = GetValueType(this.token);
                    this.hasTypedValue = true; 
                    break;
            }

            this.nodetype = ScanOverValue(this.token, false, true); 

            // we don't support lists of values 
            BinXmlToken tNext = PeekNextToken(); 
            switch (tNext) {
                case BinXmlToken.SQL_BIT: 
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT:
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.SQL_REAL:
                case BinXmlToken.SQL_FLOAT: 
                case BinXmlToken.SQL_MONEY: 
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_DATETIME: 
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.SQL_DECIMAL:
                case BinXmlToken.SQL_NUMERIC:
                case BinXmlToken.XSD_DECIMAL: 
                case BinXmlToken.SQL_UUID:
                case BinXmlToken.SQL_VARBINARY: 
                case BinXmlToken.SQL_BINARY: 
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT: 
                case BinXmlToken.XSD_KATMAI_DATE:
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME:
                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                case BinXmlToken.XSD_BINHEX: 
                case BinXmlToken.XSD_BASE64:
                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT:
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR: 
                case BinXmlToken.SQL_NTEXT:
                case BinXmlToken.XSD_BOOLEAN: 
                case BinXmlToken.XSD_TIME: 
                case BinXmlToken.XSD_DATETIME:
                case BinXmlToken.XSD_DATE: 
                case BinXmlToken.XSD_BYTE:
                case BinXmlToken.XSD_UNSIGNEDSHORT:
                case BinXmlToken.XSD_UNSIGNEDINT:
                case BinXmlToken.XSD_UNSIGNEDLONG: 
                case BinXmlToken.XSD_QNAME:
                    throw ThrowNotSupported(Res.XmlBinary_ListsOfValuesNotSupported); 
                default: 
                    break;
            } 
        }

        void ImplReadElement() {
            if (3 != this.docState || 9 != this.docState) { 
                switch (this.docState) {
                    case 0: 
                        this.docState = 9; 
                        break;
                    case 1: 
                    case 2:
                        this.docState = 3;
                        break;
                    case -1: 
                        throw ThrowUnexpectedToken(this.token);
                    default: 
                        break; 
                }
            } 
            this.elemDepth++;
            if (this.elemDepth == this.elementStack.Length)
                GrowElements();
            QName qname = this.symbolTables.qnametable[ReadQNameRef()]; 
            this.qnameOther = this.qnameElement = qname;
            this.elementStack[this.elemDepth].Set(qname, this.xmlspacePreserve); 
            this.PushNamespace(qname.prefix, qname.namespaceUri, true); 
            BinXmlToken t = PeekNextToken();
            if (BinXmlToken.Attr == t) { 
                ScanAttributes();
                t = PeekNextToken();
            }
            GenerateImpliedXmlnsAttrs(); 
            if (BinXmlToken.EndElem == t) {
                NextToken(); // move over token... 
                this.isEmpty = true; 
            }
            else if (BinXmlToken.SQL_NVARCHAR == t) { 
                if (this.mark < 0)
                    this.mark = this.pos;
                // skip over token byte
                this.pos++; 
                // is this a zero-length string?  if yes, skip it.
                // (It just indicates that this is _not_ an empty element) 
                // Also make sure that the following token is an EndElem 
                if (0 == ReadByte()) {
                    if (BinXmlToken.EndElem != (BinXmlToken)ReadByte()) { 
                        Debug.Assert(this.pos >= 3);
                        this.pos -= 3; // jump back to start of NVarChar token
                    }
                    else { 
                        Debug.Assert(this.pos >= 1);
                        this.pos -= 1; // jump back to EndElem token 
                    } 
                }
                else { 
                    Debug.Assert(this.pos >= 2);
                    this.pos -= 2; // jump back to start of NVarChar token
                }
            } 
            this.nodetype = XmlNodeType.Element;
            this.valueType = TypeOfObject; 
            this.posAfterAttrs = this.pos; 
        }
 
        void ImplReadEndElement() {
            if (this.elemDepth == 0)
                throw ThrowXmlException(Res.Xml_UnexpectedEndTag);
            int index = this.elemDepth; 
            if (1 == index && 3 == this.docState)
                this.docState = -1; 
            this.qnameOther = this.elementStack[index].name; 
            this.xmlspacePreserve = this.elementStack[index].xmlspacePreserve;
            this.nodetype = XmlNodeType.EndElement; 
        }

        void ImplReadDoctype() {
            if (this.dtdProcessing == DtdProcessing.Prohibit) 
                throw ThrowXmlException(Res.Xml_DtdIsProhibited);
            // 0=>auto, 1=>doc/pre-dtd, 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem, 9=>frag 
            switch (this.docState) { 
                case 0: // 0=>auto
                case 1: // 1=>doc/pre-dtd 
                    break;
                case 9: // 9=>frag
                    throw ThrowXmlException(Res.Xml_DtdNotAllowedInFragment);
                default: // 2=>doc/pre-elem, 3=>doc/instance -1=>doc/post-elem 
                    throw ThrowXmlException(Res.Xml_BadDTDLocation);
            } 
            this.docState = 2; 
            this.qnameOther.localname = ParseText();
            if (BinXmlToken.System == PeekToken()) { 
                this.pos++;
                this.attributes[this.attrCount++].Set(new QName(string.Empty, this.xnt.Add("SYSTEM"), string.Empty), ParseText());
            }
            if (BinXmlToken.Public == PeekToken()) { 
                this.pos++;
                this.attributes[this.attrCount++].Set(new QName(string.Empty, this.xnt.Add("PUBLIC"), string.Empty), ParseText()); 
            } 
            if (BinXmlToken.Subset == PeekToken()) {
                this.pos++; 
                this.mark = this.pos;
                this.tokLen = ScanText(out this.tokDataPos);
            }
            else { 
                this.tokLen = this.tokDataPos = 0;
            } 
            this.nodetype = XmlNodeType.DocumentType; 
            this.posAfterAttrs = this.pos;
        } 

        void ImplReadPI() {
            this.qnameOther.localname = this.symbolTables.symtable[ReadNameRef()];
            this.mark = this.pos; 
            this.tokLen = ScanText(out this.tokDataPos);
            this.nodetype = XmlNodeType.ProcessingInstruction; 
        } 

        void ImplReadComment() { 
            this.nodetype = XmlNodeType.Comment;
            this.mark = this.pos;
            this.tokLen = ScanText(out this.tokDataPos);
        } 

        void ImplReadCDATA() { 
            CheckAllowContent(); 
            this.nodetype = XmlNodeType.CDATA;
            this.mark = this.pos; 
            this.tokLen = ScanText(out this.tokDataPos);
        }

        void ImplReadNest() { 
            CheckAllowContent();
            // push current nametables 
            this.prevNameInfo = new NestedBinXml(this.symbolTables, this.docState, this.prevNameInfo); 
            this.symbolTables.Init();
            this.docState = 0; // auto 
        }

        void ImplReadEndNest() {
            NestedBinXml nested = this.prevNameInfo; 
            this.symbolTables = nested.symbolTables;
            this.docState = nested.docState; 
            this.prevNameInfo = nested.next; 
        }
 
        void ImplReadXmlText() {
            CheckAllowContent();
            string xmltext = ParseText();
            XmlNamespaceManager xnm = new XmlNamespaceManager(this.xnt); 
            foreach (NamespaceDecl decl in this.namespaces.Values) {
                if (decl.scope > 0) { 
#if DEBUG 
                    if ((object)decl.prefix != (object)this.xnt.Get(decl.prefix))
                        throw new Exception("Prefix not interned: \'" + decl.prefix + "\'"); 
                    if ((object)decl.uri != (object)this.xnt.Get(decl.uri))
                        throw new Exception("Uri not interned: \'" + decl.uri + "\'");
#endif
                    xnm.AddNamespace(decl.prefix, decl.uri); 
                }
            } 
            XmlReaderSettings settings = this.Settings; 
            settings.ReadOnly = false;
            settings.NameTable = this.xnt; 
            settings.DtdProcessing = DtdProcessing.Prohibit;
            if (0 != this.elemDepth) {
                settings.ConformanceLevel = ConformanceLevel.Fragment;
            } 
            settings.ReadOnly = true;
            XmlParserContext xpc = new XmlParserContext(this.xnt, xnm, this.XmlLang, this.XmlSpace); 
            this.textXmlReader = new XmlTextReaderImpl(xmltext, xpc, settings); 
            if (!this.textXmlReader.Read()
                || ((this.textXmlReader.NodeType == XmlNodeType.XmlDeclaration) 
                    && !this.textXmlReader.Read())) {
                this.state = ScanState.Doc;
                ReadDoc();
            } 
            else {
                this.state = ScanState.XmlText; 
                UpdateFromTextReader(); 
            }
        } 

        void UpdateFromTextReader() {
            XmlReader r = this.textXmlReader;
            this.nodetype = r.NodeType; 
            this.qnameOther.prefix = r.Prefix;
            this.qnameOther.localname = r.LocalName; 
            this.qnameOther.namespaceUri = r.NamespaceURI; 
            this.valueType = r.ValueType;
            this.isEmpty = r.IsEmptyElement; 
        }

        bool UpdateFromTextReader(bool needUpdate) {
            if (needUpdate) 
                UpdateFromTextReader();
            return needUpdate; 
        } 

        void CheckAllowContent() { 
            switch (this.docState) {
                case 0: // auto
                    this.docState = 9;
                    break; 
                case 9: // conformance = fragment
                case 3: 
                    break; 
                default:
                    throw ThrowXmlException(Res.Xml_InvalidRootData); 
            }
        }

        private void GenerateTokenTypeMap() { 
            Type[] map = new Type[256];
            map[(int)BinXmlToken.XSD_BOOLEAN] = typeof(System.Boolean); 
            map[(int)BinXmlToken.SQL_TINYINT] = typeof(System.Byte); 
            map[(int)BinXmlToken.XSD_BYTE] = typeof(System.SByte);
            map[(int)BinXmlToken.SQL_SMALLINT] = typeof(Int16); 
            map[(int)BinXmlToken.XSD_UNSIGNEDSHORT] = typeof(UInt16);
            map[(int)BinXmlToken.XSD_UNSIGNEDINT] = typeof(UInt32);
            map[(int)BinXmlToken.SQL_REAL] = typeof(Single);
            map[(int)BinXmlToken.SQL_FLOAT] = typeof(Double); 
            map[(int)BinXmlToken.SQL_BIGINT] = typeof(Int64);
            map[(int)BinXmlToken.XSD_UNSIGNEDLONG] = typeof(UInt64); 
            map[(int)BinXmlToken.XSD_QNAME] = typeof(XmlQualifiedName); 
            Type TypeOfInt32 = typeof(System.Int32);
            map[(int)BinXmlToken.SQL_BIT] = TypeOfInt32; 
            map[(int)BinXmlToken.SQL_INT] = TypeOfInt32;
            Type TypeOfDecimal = typeof(System.Decimal);
            map[(int)BinXmlToken.SQL_SMALLMONEY] = TypeOfDecimal;
            map[(int)BinXmlToken.SQL_MONEY] = TypeOfDecimal; 
            map[(int)BinXmlToken.SQL_DECIMAL] = TypeOfDecimal;
            map[(int)BinXmlToken.SQL_NUMERIC] = TypeOfDecimal; 
            map[(int)BinXmlToken.XSD_DECIMAL] = TypeOfDecimal; 
            Type TypeOfDateTime = typeof(System.DateTime);
            map[(int)BinXmlToken.SQL_SMALLDATETIME] = TypeOfDateTime; 
            map[(int)BinXmlToken.SQL_DATETIME] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_TIME] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_DATETIME] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_DATE] = TypeOfDateTime; 
            map[(int)BinXmlToken.XSD_KATMAI_DATE] = TypeOfDateTime;
            map[(int)BinXmlToken.XSD_KATMAI_DATETIME] = TypeOfDateTime; 
            map[(int)BinXmlToken.XSD_KATMAI_TIME] = TypeOfDateTime; 
            Type TypeOfDateTimeOffset = typeof( System.DateTimeOffset );
            map[(int)BinXmlToken.XSD_KATMAI_DATEOFFSET] = TypeOfDateTimeOffset; 
            map[(int)BinXmlToken.XSD_KATMAI_DATETIMEOFFSET] = TypeOfDateTimeOffset;
            map[(int)BinXmlToken.XSD_KATMAI_TIMEOFFSET] = TypeOfDateTimeOffset;
            Type TypeOfByteArray = typeof( System.Byte[] );
            map[(int)BinXmlToken.SQL_VARBINARY] = TypeOfByteArray; 
            map[(int)BinXmlToken.SQL_BINARY] = TypeOfByteArray;
            map[(int)BinXmlToken.SQL_IMAGE] = TypeOfByteArray; 
            map[(int)BinXmlToken.SQL_UDT] = TypeOfByteArray; 
            map[(int)BinXmlToken.XSD_BINHEX] = TypeOfByteArray;
            map[(int)BinXmlToken.XSD_BASE64] = TypeOfByteArray; 
            map[(int)BinXmlToken.SQL_CHAR] = TypeOfString;
            map[(int)BinXmlToken.SQL_VARCHAR] = TypeOfString;
            map[(int)BinXmlToken.SQL_TEXT] = TypeOfString;
            map[(int)BinXmlToken.SQL_NCHAR] = TypeOfString; 
            map[(int)BinXmlToken.SQL_NVARCHAR] = TypeOfString;
            map[(int)BinXmlToken.SQL_NTEXT] = TypeOfString; 
            map[(int)BinXmlToken.SQL_UUID] = TypeOfString; 
            if (TokenTypeMap == null)
                TokenTypeMap = map; 
        }

        System.Type GetValueType(BinXmlToken token) {
            Type t = TokenTypeMap[(int)token]; 
            if (t == null)
                throw ThrowUnexpectedToken(token); 
            return t; 
        }
 
        // helper method...
        void ReScanOverValue(BinXmlToken token) {
            ScanOverValue(token, true, false);
        } 

        XmlNodeType ScanOverValue(BinXmlToken token, bool attr, bool checkChars) { 
            if (token == BinXmlToken.SQL_NVARCHAR) { 
                if (this.mark < 0)
                    this.mark = this.pos; 
                this.tokLen = ParseMB32();
                this.tokDataPos = this.pos;
                checked{this.pos += this.tokLen * 2;}
                Fill(-1); 
                // check chars (if this is the first pass and settings.CheckCharacters was set)
                if (checkChars && this.checkCharacters) { 
                    // check for invalid chardata 
                    return CheckText(attr);
                } 
                else if (!attr) { // attribute values are always reported as Text
                    // check for whitespace-only text
                    return CheckTextIsWS();
                } 
                else {
                    return XmlNodeType.Text; 
                } 
            }
            else { 
                return ScanOverAnyValue(token, attr, checkChars);
            }
        }
 
        XmlNodeType ScanOverAnyValue(BinXmlToken token, bool attr, bool checkChars) {
            if (this.mark < 0) 
                this.mark = this.pos; 
            checked {
                switch (token) { 
                    case BinXmlToken.SQL_BIT:
                    case BinXmlToken.SQL_TINYINT:
                    case BinXmlToken.XSD_BOOLEAN:
                    case BinXmlToken.XSD_BYTE: 
                        this.tokDataPos = this.pos;
                        this.tokLen = 1; 
                        this.pos += 1; 
                        break;
 
                    case BinXmlToken.SQL_SMALLINT:
                    case BinXmlToken.XSD_UNSIGNEDSHORT:
                        this.tokDataPos = this.pos;
                        this.tokLen = 2; 
                        this.pos += 2;
                        break; 
 
                    case BinXmlToken.SQL_INT:
                    case BinXmlToken.XSD_UNSIGNEDINT: 
                    case BinXmlToken.SQL_REAL:
                    case BinXmlToken.SQL_SMALLMONEY:
                    case BinXmlToken.SQL_SMALLDATETIME:
                        this.tokDataPos = this.pos; 
                        this.tokLen = 4;
                        this.pos += 4; 
                        break; 

                    case BinXmlToken.SQL_BIGINT: 
                    case BinXmlToken.XSD_UNSIGNEDLONG:
                    case BinXmlToken.SQL_FLOAT:
                    case BinXmlToken.SQL_MONEY:
                    case BinXmlToken.SQL_DATETIME: 
                    case BinXmlToken.XSD_TIME:
                    case BinXmlToken.XSD_DATETIME: 
                    case BinXmlToken.XSD_DATE: 
                        this.tokDataPos = this.pos;
                        this.tokLen = 8; 
                        this.pos += 8;
                        break;

                    case BinXmlToken.SQL_UUID: 
                        this.tokDataPos = this.pos;
                        this.tokLen = 16; 
                        this.pos += 16; 
                        break;
 
                    case BinXmlToken.SQL_DECIMAL:
                    case BinXmlToken.SQL_NUMERIC:
                    case BinXmlToken.XSD_DECIMAL:
                        this.tokDataPos = this.pos; 
                        this.tokLen = ParseMB64();
                        this.pos += this.tokLen; 
                        break; 

                    case BinXmlToken.SQL_VARBINARY: 
                    case BinXmlToken.SQL_BINARY:
                    case BinXmlToken.SQL_IMAGE:
                    case BinXmlToken.SQL_UDT:
                    case BinXmlToken.XSD_BINHEX: 
                    case BinXmlToken.XSD_BASE64:
                        this.tokLen = ParseMB64(); 
                        this.tokDataPos = this.pos; 
                        this.pos += this.tokLen;
                        break; 

                    case BinXmlToken.SQL_CHAR:
                    case BinXmlToken.SQL_VARCHAR:
                    case BinXmlToken.SQL_TEXT: 
                        this.tokLen = ParseMB64();
                        this.tokDataPos = this.pos; 
                        this.pos += this.tokLen; 
                        if (checkChars && this.checkCharacters) {
                            // check for invalid chardata 
                            Fill(-1);
                            string val = ValueAsString(token);
                            XmlConvert.VerifyCharData(val, ExceptionType.ArgumentException, ExceptionType.XmlException);
                            this.stringValue = val; 
                        }
                        break; 
 
                    case BinXmlToken.SQL_NVARCHAR:
                    case BinXmlToken.SQL_NCHAR: 
                    case BinXmlToken.SQL_NTEXT:
                        return ScanOverValue(BinXmlToken.SQL_NVARCHAR, attr, checkChars);

                    case BinXmlToken.XSD_QNAME: 
                        this.tokDataPos = this.pos;
                        ParseMB32(); 
                        break; 

                    case BinXmlToken.XSD_KATMAI_DATE: 
                    case BinXmlToken.XSD_KATMAI_DATETIME:
                    case BinXmlToken.XSD_KATMAI_TIME:
                    case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                    case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                        VerifyVersion(2, token); 
                        this.tokDataPos = this.pos; 
                        this.tokLen = GetXsdKatmaiTokenLength(token);
                        this.pos += tokLen; 
                        break;

                    default:
                        throw ThrowUnexpectedToken(token); 
                }
            } 
            Fill(-1); 
            return XmlNodeType.Text;
        } 

        unsafe XmlNodeType CheckText(bool attr) {
            Debug.Assert(this.checkCharacters, "this.checkCharacters");
            // assert that size is an even number 
            Debug.Assert(0 == ((this.pos - this.tokDataPos) & 1), "Data size should not be odd");
            // grab local copy (perf) 
            XmlCharType xmlCharType = this.xmlCharType; 

            fixed (byte* pb = this.data) { 
                int end = this.pos;
                int pos = this.tokDataPos;

                if (!attr) { 
                    // scan if this is whitespace
                    for (; ; ) { 
                        int posNext = pos + 2; 
                        if (posNext > end)
                            return this.xmlspacePreserve ? XmlNodeType.SignificantWhitespace : XmlNodeType.Whitespace; 
                        if (pb[pos + 1] != 0 || (xmlCharType.charProperties[pb[pos]] & XmlCharType.fWhitespace) == 0)
                            break;
                        pos = posNext;
                    } 
                }
 
                for (; ; ) { 
                    char ch;
                    for (; ; ) { 
                        int posNext = pos + 2;
                        if (posNext > end)
                            return XmlNodeType.Text;
                        ch = (char)(pb[pos] | ((int)(pb[pos + 1]) << 8)); 
                        if ((xmlCharType.charProperties[ch] & XmlCharType.fCharData) == 0)
                            break; 
                        pos = posNext; 
                    }
 
                    if (!XmlCharType.IsHighSurrogate(ch)) {
                        throw XmlConvert.CreateInvalidCharException(ch, '\0', ExceptionType.XmlException);
                    }
                    else { 
                        if ((pos + 4) > end) {
                            throw ThrowXmlException(Res.Xml_InvalidSurrogateMissingLowChar); 
                        } 
                        char chNext = (char)(pb[pos + 2] | ((int)(pb[pos + 3]) << 8));
                        if (!XmlCharType.IsLowSurrogate(chNext)) { 
                            throw XmlConvert.CreateInvalidSurrogatePairException(ch, chNext);
                        }
                    }
                    pos += 4; 
                }
            } 
        } 

        XmlNodeType CheckTextIsWS() { 
            Debug.Assert(!this.checkCharacters, "!this.checkCharacters");
            byte[] data = this.data;
            // assert that size is an even number
            Debug.Assert(0 == ((this.pos - this.tokDataPos) & 1), "Data size should not be odd"); 
            for (int pos = this.tokDataPos; pos < this.pos; pos += 2) {
                if (0 != data[pos + 1]) 
                    goto NonWSText; 
                switch (data[pos]) {
                    case 0x09: // tab 
                    case 0x0A: // nl
                    case 0x0D: // cr
                    case 0x20: // space
                        break; 
                    default:
                        goto NonWSText; 
                } 
            }
            if (this.xmlspacePreserve) 
                return XmlNodeType.SignificantWhitespace;
            return XmlNodeType.Whitespace;
        NonWSText:
            return XmlNodeType.Text; 
        }
 
        void CheckValueTokenBounds() { 
            if ((this.end - this.tokDataPos) < this.tokLen)
                throw ThrowXmlException(Res.Xml_UnexpectedEOF1); 
        }

        int GetXsdKatmaiTokenLength(BinXmlToken token) {
            byte scale; 
            switch (token) {
                case BinXmlToken.XSD_KATMAI_DATE: 
                    // SQL Katmai type DATE = date(3b) 
                    return 3;
                case BinXmlToken.XSD_KATMAI_TIME: 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                    // SQL Katmai type DATETIME2 = scale(1b) + time(3-5b) + date(3b)
                    Fill(0);
                    scale = this.data[this.pos]; 
                    return 4 + XsdKatmaiTimeScaleToValueLength(scale);
                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    // SQL Katmai type DATETIMEOFFSET = scale(1b) + time(3-5b) + date(3b) + zone(2b) 
                    Fill(0);
                    scale = this.data[this.pos];
                    return 6 + XsdKatmaiTimeScaleToValueLength(scale);
                default: 
                    throw ThrowUnexpectedToken(this.token);
            } 
        } 

        int XsdKatmaiTimeScaleToValueLength(byte scale) { 
            if (scale > 7) {
                throw new XmlException(Res.SqlTypes_ArithOverflow, (string)null);
            }
            return XsdKatmaiTimeScaleToValueLengthMap[scale]; 
        }
 
        long ValueAsLong() { 
            CheckValueTokenBounds();
            switch (this.token) { 
                case BinXmlToken.SQL_BIT:
                case BinXmlToken.SQL_TINYINT: {
                        byte v = this.data[this.tokDataPos];
                        return v; 
                    }
 
                case BinXmlToken.XSD_BYTE: { 
                        sbyte v = unchecked((sbyte)this.data[this.tokDataPos]);
                        return v; 
                    }

                case BinXmlToken.SQL_SMALLINT:
                    return GetInt16(this.tokDataPos); 

                case BinXmlToken.SQL_INT: 
                    return GetInt32(this.tokDataPos); 

                case BinXmlToken.SQL_BIGINT: 
                    return GetInt64(this.tokDataPos);

                case BinXmlToken.XSD_UNSIGNEDSHORT:
                    return GetUInt16(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return GetUInt32(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDLONG: { 
                        ulong v = GetUInt64(this.tokDataPos);
                        return checked((long)v);
                    }
 
                case BinXmlToken.SQL_REAL:
                case BinXmlToken.SQL_FLOAT: { 
                        double v = ValueAsDouble(); 
                        return (long)v;
                    } 

                case BinXmlToken.SQL_MONEY:
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC:
                case BinXmlToken.XSD_DECIMAL: { 
                        Decimal v = ValueAsDecimal(); 
                        return (long)v;
                    } 

                default:
                    throw ThrowUnexpectedToken(this.token);
            } 
        }
 
        ulong ValueAsULong() { 
            if (BinXmlToken.XSD_UNSIGNEDLONG == this.token) {
                CheckValueTokenBounds(); 
                return GetUInt64(this.tokDataPos);
            }
            else {
                throw ThrowUnexpectedToken(this.token); 
            }
        } 
 
        Decimal ValueAsDecimal() {
            CheckValueTokenBounds(); 
            switch (token) {
                case BinXmlToken.SQL_BIT:
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT: 
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.XSD_BYTE: 
                case BinXmlToken.XSD_UNSIGNEDSHORT:
                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return new Decimal(ValueAsLong());

                case BinXmlToken.XSD_UNSIGNEDLONG:
                    return new Decimal(ValueAsULong()); 

                case BinXmlToken.SQL_REAL: 
                    return new Decimal(GetSingle(this.tokDataPos)); 

                case BinXmlToken.SQL_FLOAT: 
                    return new Decimal(GetDouble(this.tokDataPos));

                case BinXmlToken.SQL_SMALLMONEY: {
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt32(this.tokDataPos)); 
                        return v.ToDecimal();
                    } 
                case BinXmlToken.SQL_MONEY: { 
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt64(this.tokDataPos));
                        return v.ToDecimal(); 
                    }

                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC: {
                        BinXmlSqlDecimal v = new BinXmlSqlDecimal(this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL); 
                        return v.ToDecimal(); 
                    }
 
                default:
                    throw ThrowUnexpectedToken(this.token);
            }
        } 

        double ValueAsDouble() { 
            CheckValueTokenBounds(); 
            switch (token) {
                case BinXmlToken.SQL_BIT: 
                case BinXmlToken.SQL_TINYINT:
                case BinXmlToken.SQL_SMALLINT:
                case BinXmlToken.SQL_INT:
                case BinXmlToken.SQL_BIGINT: 
                case BinXmlToken.XSD_BYTE:
                case BinXmlToken.XSD_UNSIGNEDSHORT: 
                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return (double)ValueAsLong();
 
                case BinXmlToken.XSD_UNSIGNEDLONG:
                    return (double)ValueAsULong();

                case BinXmlToken.SQL_REAL: 
                    return GetSingle(this.tokDataPos);
 
                case BinXmlToken.SQL_FLOAT: 
                    return GetDouble(this.tokDataPos);
 
                case BinXmlToken.SQL_SMALLMONEY:
                case BinXmlToken.SQL_MONEY:
                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC:
                    return (double)ValueAsDecimal(); 
 
                default:
                    throw ThrowUnexpectedToken(this.token); 
            }
        }

        DateTime ValueAsDateTime() { 
            CheckValueTokenBounds();
            switch (token) { 
                case BinXmlToken.SQL_DATETIME: { 
                        int pos = this.tokDataPos;
                        int dateticks; uint timeticks; 
                        dateticks = GetInt32(pos);
                        timeticks = GetUInt32(pos + 4);
                        return BinXmlDateTime.SqlDateTimeToDateTime(dateticks, timeticks);
                    } 

                case BinXmlToken.SQL_SMALLDATETIME: { 
                        int pos = this.tokDataPos; 
                        short dateticks; ushort timeticks;
                        dateticks = GetInt16(pos); 
                        timeticks = GetUInt16(pos + 2);
                        return BinXmlDateTime.SqlSmallDateTimeToDateTime(dateticks, timeticks);
                    }
 
                case BinXmlToken.XSD_TIME: {
                        long time = GetInt64(this.tokDataPos); 
                        return BinXmlDateTime.XsdTimeToDateTime(time); 
                    }
 
                case BinXmlToken.XSD_DATE: {
                        long time = GetInt64(this.tokDataPos);
                        return BinXmlDateTime.XsdDateToDateTime(time);
                    } 

                case BinXmlToken.XSD_DATETIME: { 
                        long time = GetInt64(this.tokDataPos); 
                        return BinXmlDateTime.XsdDateTimeToDateTime(time);
                    } 

                case BinXmlToken.XSD_KATMAI_DATE:
                    return BinXmlDateTime.XsdKatmaiDateToDateTime(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                    return BinXmlDateTime.XsdKatmaiDateTimeToDateTime(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_TIME:
                    return BinXmlDateTime.XsdKatmaiTimeToDateTime(this.data, this.tokDataPos); 

                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateOffsetToDateTime(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateTimeOffsetToDateTime(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiTimeOffsetToDateTime(this.data, this.tokDataPos); 

                default:
                    throw ThrowUnexpectedToken(this.token);
            } 
        }
 
        DateTimeOffset ValueAsDateTimeOffset() { 
            CheckValueTokenBounds();
            switch (token) { 
                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateOffsetToDateTimeOffset(this.data, this.tokDataPos);

                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                    return BinXmlDateTime.XsdKatmaiDateTimeOffsetToDateTimeOffset(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET: 
                    return BinXmlDateTime.XsdKatmaiTimeOffsetToDateTimeOffset(this.data, this.tokDataPos);
 
                default:
                    throw ThrowUnexpectedToken(this.token);
            }
        } 

 
        string ValueAsDateTimeString() { 
            CheckValueTokenBounds();
            switch (token) { 
                case BinXmlToken.SQL_DATETIME: {
                        int pos = this.tokDataPos;
                        int dateticks; uint timeticks;
                        dateticks = GetInt32(pos); 
                        timeticks = GetUInt32(pos + 4);
                        return BinXmlDateTime.SqlDateTimeToString(dateticks, timeticks); 
                    } 

                case BinXmlToken.SQL_SMALLDATETIME: { 
                        int pos = this.tokDataPos;
                        short dateticks; ushort timeticks;
                        dateticks = GetInt16(pos);
                        timeticks = GetUInt16(pos + 2); 
                        return BinXmlDateTime.SqlSmallDateTimeToString(dateticks, timeticks);
                    } 
 
                case BinXmlToken.XSD_TIME: {
                        long time = GetInt64(this.tokDataPos); 
                        return BinXmlDateTime.XsdTimeToString(time);
                    }

                case BinXmlToken.XSD_DATE: { 
                        long time = GetInt64(this.tokDataPos);
                        return BinXmlDateTime.XsdDateToString(time); 
                    } 

                case BinXmlToken.XSD_DATETIME: { 
                        long time = GetInt64(this.tokDataPos);
                        return BinXmlDateTime.XsdDateTimeToString(time);
                    }
 
                case BinXmlToken.XSD_KATMAI_DATE:
                    return BinXmlDateTime.XsdKatmaiDateToString(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                    return BinXmlDateTime.XsdKatmaiDateTimeToString(this.data, this.tokDataPos); 

                case BinXmlToken.XSD_KATMAI_TIME:
                    return BinXmlDateTime.XsdKatmaiTimeToString(this.data, this.tokDataPos);
 
                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateOffsetToString(this.data, this.tokDataPos); 
 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiDateTimeOffsetToString(this.data, this.tokDataPos); 

                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    return BinXmlDateTime.XsdKatmaiTimeOffsetToString(this.data, this.tokDataPos);
 
                default:
                    throw ThrowUnexpectedToken(this.token); 
            } 
        }
 
        string ValueAsString(BinXmlToken token) {
            try {
                CheckValueTokenBounds();
                switch ( token ) { 
                    case BinXmlToken.SQL_NCHAR:
                    case BinXmlToken.SQL_NVARCHAR: 
                    case BinXmlToken.SQL_NTEXT: 
                        return GetString( this.tokDataPos, this.tokLen );
 
                    case BinXmlToken.XSD_BOOLEAN: {
                            if ( 0 == this.data[this.tokDataPos] )
                                return "false";
                            else 
                                return "true";
                        } 
 
                    case BinXmlToken.SQL_BIT:
                    case BinXmlToken.SQL_TINYINT: 
                    case BinXmlToken.SQL_SMALLINT:
                    case BinXmlToken.SQL_INT:
                    case BinXmlToken.SQL_BIGINT:
                    case BinXmlToken.XSD_BYTE: 
                    case BinXmlToken.XSD_UNSIGNEDSHORT:
                    case BinXmlToken.XSD_UNSIGNEDINT: 
                        return ValueAsLong().ToString( CultureInfo.InvariantCulture ); 

                    case BinXmlToken.XSD_UNSIGNEDLONG: 
                        return ValueAsULong().ToString( CultureInfo.InvariantCulture );

                    case BinXmlToken.SQL_REAL:
                        return XmlConvert.ToString( GetSingle( this.tokDataPos ) ); 

                    case BinXmlToken.SQL_FLOAT: 
                        return XmlConvert.ToString( GetDouble( this.tokDataPos ) ); 

                    case BinXmlToken.SQL_UUID: { 
                            int a; short b, c;
                            int pos = this.tokDataPos;
                            a = GetInt32( pos );
                            b = GetInt16( pos + 4 ); 
                            c = GetInt16( pos + 6 );
                            Guid v = new Guid( a, b, c, data[pos + 8], data[pos + 9], data[pos + 10], data[pos + 11], data[pos + 12], data[pos + 13], data[pos + 14], data[pos + 15] ); 
                            return v.ToString(); 
                        }
 
                    case BinXmlToken.SQL_SMALLMONEY: {
                            BinXmlSqlMoney v = new BinXmlSqlMoney( GetInt32( this.tokDataPos ) );
                            return v.ToString();
                        } 
                    case BinXmlToken.SQL_MONEY: {
                            BinXmlSqlMoney v = new BinXmlSqlMoney( GetInt64( this.tokDataPos ) ); 
                            return v.ToString(); 
                        }
 
                    case BinXmlToken.XSD_DECIMAL:
                    case BinXmlToken.SQL_DECIMAL:
                    case BinXmlToken.SQL_NUMERIC: {
                            BinXmlSqlDecimal v = new BinXmlSqlDecimal( this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL ); 
                            return v.ToString();
                        } 
 
                    case BinXmlToken.SQL_CHAR:
                    case BinXmlToken.SQL_VARCHAR: 
                    case BinXmlToken.SQL_TEXT: {
                            int pos = this.tokDataPos;
                            int codepage = GetInt32( pos );
                            Encoding enc = System.Text.Encoding.GetEncoding( codepage ); 
                            return enc.GetString( this.data, pos + 4, this.tokLen - 4 );
                        } 
 
                    case BinXmlToken.SQL_VARBINARY:
                    case BinXmlToken.SQL_BINARY: 
                    case BinXmlToken.SQL_IMAGE:
                    case BinXmlToken.SQL_UDT:
                    case BinXmlToken.XSD_BASE64: {
                            return Convert.ToBase64String( this.data, this.tokDataPos, this.tokLen ); 
                        }
 
                    case BinXmlToken.XSD_BINHEX: 
                        return BinHexEncoder.Encode( this.data, this.tokDataPos, this.tokLen );
 
                    case BinXmlToken.SQL_DATETIME:
                    case BinXmlToken.SQL_SMALLDATETIME:
                    case BinXmlToken.XSD_TIME:
                    case BinXmlToken.XSD_DATE: 
                    case BinXmlToken.XSD_DATETIME:
                    case BinXmlToken.XSD_KATMAI_DATE: 
                    case BinXmlToken.XSD_KATMAI_DATETIME: 
                    case BinXmlToken.XSD_KATMAI_TIME:
                    case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                    case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                    case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                        return ValueAsDateTimeString();
 
                    case BinXmlToken.XSD_QNAME: {
                            int nameNum = ParseMB32( this.tokDataPos ); 
                            if ( nameNum < 0 || nameNum >= this.symbolTables.qnameCount ) 
                                throw new XmlException( Res.XmlBin_InvalidQNameID, String.Empty );
                            QName qname = this.symbolTables.qnametable[nameNum]; 
                            if ( qname.prefix.Length == 0 )
                                return qname.localname;
                            else
                                return String.Concat( qname.prefix, ":", qname.localname ); 
                        }
 
                    default: 
                        throw ThrowUnexpectedToken( this.token );
                } 
            }
            catch {
                this.state = ScanState.Error;
                throw; 
            }
        } 
 
        object ValueAsObject(BinXmlToken token, bool returnInternalTypes) {
            CheckValueTokenBounds(); 
            switch (token) {
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR:
                case BinXmlToken.SQL_NTEXT: 
                    return GetString(this.tokDataPos, this.tokLen);
 
                case BinXmlToken.XSD_BOOLEAN: 
                    return (0 != this.data[this.tokDataPos]);
 
                case BinXmlToken.SQL_BIT:
                    return (Int32)this.data[this.tokDataPos];

                case BinXmlToken.SQL_TINYINT: 
                    return this.data[this.tokDataPos];
 
                case BinXmlToken.SQL_SMALLINT: 
                    return GetInt16(this.tokDataPos);
 
                case BinXmlToken.SQL_INT:
                    return GetInt32(this.tokDataPos);

                case BinXmlToken.SQL_BIGINT: 
                    return GetInt64(this.tokDataPos);
 
                case BinXmlToken.XSD_BYTE: { 
                        sbyte v = unchecked((sbyte)this.data[this.tokDataPos]);
                        return v; 
                    }

                case BinXmlToken.XSD_UNSIGNEDSHORT:
                    return GetUInt16(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDINT: 
                    return GetUInt32(this.tokDataPos); 

                case BinXmlToken.XSD_UNSIGNEDLONG: 
                    return GetUInt64(this.tokDataPos);

                case BinXmlToken.SQL_REAL:
                    return GetSingle(this.tokDataPos); 

                case BinXmlToken.SQL_FLOAT: 
                    return GetDouble(this.tokDataPos); 

                case BinXmlToken.SQL_UUID: { 
                        int a; short b, c;
                        int pos = this.tokDataPos;
                        a = GetInt32(pos);
                        b = GetInt16(pos + 4); 
                        c = GetInt16(pos + 6);
                        Guid v = new Guid(a, b, c, data[pos + 8], data[pos + 9], data[pos + 10], data[pos + 11], data[pos + 12], data[pos + 13], data[pos + 14], data[pos + 15]); 
                        return v.ToString(); 
                    }
 
                case BinXmlToken.SQL_SMALLMONEY: {
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt32(this.tokDataPos));
                        if (returnInternalTypes)
                            return v; 
                        else
                            return v.ToDecimal(); 
                    } 

                case BinXmlToken.SQL_MONEY: { 
                        BinXmlSqlMoney v = new BinXmlSqlMoney(GetInt64(this.tokDataPos));
                        if (returnInternalTypes)
                            return v;
                        else 
                            return v.ToDecimal();
                    } 
 
                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL: 
                case BinXmlToken.SQL_NUMERIC: {
                        BinXmlSqlDecimal v = new BinXmlSqlDecimal(this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL);
                        if (returnInternalTypes)
                            return v; 
                        else
                            return v.ToDecimal(); 
                    } 

                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT: {
                        int pos = this.tokDataPos;
                        int codepage = GetInt32(pos); 
                        Encoding enc = System.Text.Encoding.GetEncoding(codepage);
                        return enc.GetString(this.data, pos + 4, this.tokLen - 4); 
                    } 

                case BinXmlToken.SQL_VARBINARY: 
                case BinXmlToken.SQL_BINARY:
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT:
                case BinXmlToken.XSD_BASE64: 
                case BinXmlToken.XSD_BINHEX: {
                        byte[] data = new byte[this.tokLen]; 
                        Array.Copy(this.data, this.tokDataPos, data, 0, this.tokLen); 
                        return data;
                    } 

                case BinXmlToken.SQL_DATETIME:
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.XSD_TIME: 
                case BinXmlToken.XSD_DATE:
                case BinXmlToken.XSD_DATETIME: 
                case BinXmlToken.XSD_KATMAI_DATE: 
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME: 
                    return ValueAsDateTime();

                case BinXmlToken.XSD_KATMAI_DATEOFFSET:
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET: 
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    return ValueAsDateTimeOffset(); 
 
                case BinXmlToken.XSD_QNAME: {
                        int nameNum = ParseMB32(this.tokDataPos); 
                        if (nameNum < 0 || nameNum >= this.symbolTables.qnameCount)
                            throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
                        QName qname = this.symbolTables.qnametable[nameNum];
                        return new XmlQualifiedName(qname.localname, qname.namespaceUri); 
                    }
 
                default: 
                    throw ThrowUnexpectedToken(this.token);
            } 
        }

        XmlValueConverter GetValueConverter(XmlTypeCode typeCode) {
            XmlSchemaSimpleType xsst = DatatypeImplementation.GetSimpleTypeFromTypeCode(typeCode); 
            return xsst.ValueConverter;
        } 
 
        object ValueAs(BinXmlToken token, Type returnType, IXmlNamespaceResolver namespaceResolver) {
            object value; 
            CheckValueTokenBounds();
            switch (token) {
                case BinXmlToken.SQL_NCHAR:
                case BinXmlToken.SQL_NVARCHAR: 
                case BinXmlToken.SQL_NTEXT:
                    value = GetValueConverter(XmlTypeCode.UntypedAtomic).ChangeType( 
                        GetString(this.tokDataPos, this.tokLen), 
                        returnType, namespaceResolver);
                    break; 

                case BinXmlToken.XSD_BOOLEAN:
                    value = GetValueConverter(XmlTypeCode.Boolean).ChangeType(
                        (0 != this.data[this.tokDataPos]), 
                        returnType, namespaceResolver);
                    break; 
 
                case BinXmlToken.SQL_BIT:
                    value = GetValueConverter(XmlTypeCode.NonNegativeInteger).ChangeType( 
                        (Int32)this.data[this.tokDataPos],
                        returnType, namespaceResolver);
                    break;
 
                case BinXmlToken.SQL_TINYINT:
                    value = GetValueConverter(XmlTypeCode.UnsignedByte).ChangeType( 
                        this.data[this.tokDataPos], 
                        returnType, namespaceResolver);
                    break; 

                case BinXmlToken.SQL_SMALLINT: {
                        int v = GetInt16(this.tokDataPos);
                        value = GetValueConverter(XmlTypeCode.Short).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    } 
                case BinXmlToken.SQL_INT: {
                        int v = GetInt32(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Int).ChangeType(
                            v, returnType, namespaceResolver);
                        break;
                    } 
                case BinXmlToken.SQL_BIGINT: {
                        long v = GetInt64(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Long).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    }
                case BinXmlToken.XSD_BYTE: {
                        value = GetValueConverter(XmlTypeCode.Byte).ChangeType(
                            (int)unchecked((sbyte)this.data[this.tokDataPos]), 
                            returnType, namespaceResolver);
                        break; 
                    } 
                case BinXmlToken.XSD_UNSIGNEDSHORT: {
                        int v = GetUInt16(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.UnsignedShort).ChangeType(
                            v, returnType, namespaceResolver);
                        break;
                    } 
                case BinXmlToken.XSD_UNSIGNEDINT: {
                        long v = GetUInt32(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.UnsignedInt).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    }
                case BinXmlToken.XSD_UNSIGNEDLONG: {
                        Decimal v = (Decimal)GetUInt64(this.tokDataPos);
                        value = GetValueConverter(XmlTypeCode.UnsignedLong).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    } 
                case BinXmlToken.SQL_REAL: {
                        Single v = GetSingle(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Float).ChangeType(
                            v, returnType, namespaceResolver);
                        break;
                    } 
                case BinXmlToken.SQL_FLOAT: {
                        Double v = GetDouble(this.tokDataPos); 
                        value = GetValueConverter(XmlTypeCode.Double).ChangeType( 
                            v, returnType, namespaceResolver);
                        break; 
                    }
                case BinXmlToken.SQL_UUID:
                    value = GetValueConverter(XmlTypeCode.String).ChangeType(
                        this.ValueAsString(token), returnType, namespaceResolver); 
                    break;
 
                case BinXmlToken.SQL_SMALLMONEY: 
                    value = GetValueConverter(XmlTypeCode.Decimal).ChangeType(
                        (new BinXmlSqlMoney(GetInt32(this.tokDataPos))).ToDecimal(), 
                        returnType, namespaceResolver);
                    break;

                case BinXmlToken.SQL_MONEY: 
                    value = GetValueConverter(XmlTypeCode.Decimal).ChangeType(
                        (new BinXmlSqlMoney(GetInt64(this.tokDataPos))).ToDecimal(), 
                        returnType, namespaceResolver); 
                    break;
 
                case BinXmlToken.XSD_DECIMAL:
                case BinXmlToken.SQL_DECIMAL:
                case BinXmlToken.SQL_NUMERIC:
                    value = GetValueConverter(XmlTypeCode.Decimal).ChangeType( 
                        (new BinXmlSqlDecimal(this.data, this.tokDataPos, token == BinXmlToken.XSD_DECIMAL)).ToDecimal(),
                        returnType, namespaceResolver); 
                    break; 

                case BinXmlToken.SQL_CHAR: 
                case BinXmlToken.SQL_VARCHAR:
                case BinXmlToken.SQL_TEXT: {
                        int pos = this.tokDataPos;
                        int codepage = GetInt32(pos); 
                        Encoding enc = System.Text.Encoding.GetEncoding(codepage);
                        value = GetValueConverter(XmlTypeCode.UntypedAtomic).ChangeType( 
                            enc.GetString(this.data, pos + 4, this.tokLen - 4), 
                            returnType, namespaceResolver);
                        break; 
                    }

                case BinXmlToken.SQL_VARBINARY:
                case BinXmlToken.SQL_BINARY: 
                case BinXmlToken.SQL_IMAGE:
                case BinXmlToken.SQL_UDT: 
                case BinXmlToken.XSD_BASE64: 
                case BinXmlToken.XSD_BINHEX: {
                        byte[] data = new byte[this.tokLen]; 
                        Array.Copy(this.data, this.tokDataPos, data, 0, this.tokLen);
                        value = GetValueConverter(token == BinXmlToken.XSD_BINHEX ? XmlTypeCode.HexBinary : XmlTypeCode.Base64Binary).ChangeType(
                            data, returnType, namespaceResolver);
                        break; 
                    }
 
                case BinXmlToken.SQL_DATETIME: 
                case BinXmlToken.SQL_SMALLDATETIME:
                case BinXmlToken.XSD_DATETIME: 
                case BinXmlToken.XSD_KATMAI_DATE:
                case BinXmlToken.XSD_KATMAI_DATETIME:
                case BinXmlToken.XSD_KATMAI_TIME:
                    value = GetValueConverter(XmlTypeCode.DateTime).ChangeType( 
                        ValueAsDateTime(),
                        returnType, namespaceResolver); 
                    break; 

                case BinXmlToken.XSD_KATMAI_DATEOFFSET: 
                case BinXmlToken.XSD_KATMAI_DATETIMEOFFSET:
                case BinXmlToken.XSD_KATMAI_TIMEOFFSET:
                    value = GetValueConverter(XmlTypeCode.DateTime).ChangeType(
                        ValueAsDateTimeOffset(), 
                        returnType, namespaceResolver);
                    break; 
 
                case BinXmlToken.XSD_TIME:
                    value = GetValueConverter(XmlTypeCode.Time).ChangeType( 
                        ValueAsDateTime(),
                        returnType, namespaceResolver);
                    break;
 
                case BinXmlToken.XSD_DATE:
                    value = GetValueConverter(XmlTypeCode.Date).ChangeType( 
                        ValueAsDateTime(), 
                        returnType, namespaceResolver);
                    break; 

                case BinXmlToken.XSD_QNAME: {
                        int nameNum = ParseMB32(this.tokDataPos);
                        if (nameNum < 0 || nameNum >= this.symbolTables.qnameCount) 
                            throw new XmlException(Res.XmlBin_InvalidQNameID, String.Empty);
                        QName qname = this.symbolTables.qnametable[nameNum]; 
                        value = GetValueConverter(XmlTypeCode.QName).ChangeType( 
                            new XmlQualifiedName(qname.localname, qname.namespaceUri),
                            returnType, namespaceResolver); 
                        break;
                    }

                default: 
                    throw ThrowUnexpectedToken(this.token);
            } 
            return value; 
        }
 
        Int16 GetInt16(int pos) {
            byte[] data = this.data;
            return (Int16)(data[pos] | data[pos + 1] << 8);
        } 

        UInt16 GetUInt16(int pos) { 
            byte[] data = this.data; 
            return (UInt16)(data[pos] | data[pos + 1] << 8);
        } 

        Int32 GetInt32(int pos) {
            byte[] data = this.data;
            return (Int32)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24); 
        }
 
        UInt32 GetUInt32(int pos) { 
            byte[] data = this.data;
            return (UInt32)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24); 
        }

        Int64 GetInt64(int pos) {
            byte[] data = this.data; 
            uint lo = (uint)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24);
            uint hi = (uint)(data[pos + 4] | data[pos + 5] << 8 | data[pos + 6] << 16 | data[pos + 7] << 24); 
            return (Int64)((ulong)hi) << 32 | lo; 
        }
 
        UInt64 GetUInt64(int pos) {
            byte[] data = this.data;
            uint lo = (uint)(data[pos] | data[pos + 1] << 8 | data[pos + 2] << 16 | data[pos + 3] << 24);
            uint hi = (uint)(data[pos + 4] | data[pos + 5] << 8 | data[pos + 6] << 16 | data[pos + 7] << 24); 
            return (UInt64)((ulong)hi) << 32 | lo;
        } 
 
        Single GetSingle(int offset) {
            byte[] data = this.data; 
            uint tmp = (uint)(data[offset]
                            | data[offset + 1] << 8
                            | data[offset + 2] << 16
                            | data[offset + 3] << 24); 
            unsafe {
                return *((float*)&tmp); 
            } 
        }
 
        Double GetDouble(int offset) {
            uint lo = (uint)(data[offset + 0]
                            | data[offset + 1] << 8
                            | data[offset + 2] << 16 
                            | data[offset + 3] << 24);
            uint hi = (uint)(data[offset + 4] 
                            | data[offset + 5] << 8 
                            | data[offset + 6] << 16
                            | data[offset + 7] << 24); 
            ulong tmp = ((ulong)hi) << 32 | lo;
            unsafe {
                return *((double*)&tmp);
            } 
        }
 
        Exception ThrowUnexpectedToken(BinXmlToken token) { 
            System.Diagnostics.Debug.WriteLine("Unhandled token: " + token.ToString());
            return ThrowXmlException(Res.XmlBinary_UnexpectedToken); 
        }

        Exception ThrowXmlException(string res) {
            this.state = ScanState.Error; 
            return new XmlException(res, (string[])null);
        } 
 
        // not currently used...
        //Exception ThrowXmlException(string res, string arg1) { 
        //    this.state = ScanState.Error;
        //    return new XmlException(res, new string[] {arg1} );
        //}
 
        Exception ThrowXmlException(string res, string arg1, string arg2) {
            this.state = ScanState.Error; 
            return new XmlException(res, new string[] { arg1, arg2 }); 
        }
 
        Exception ThrowNotSupported(string res) {
            this.state = ScanState.Error;
            return new NotSupportedException(Res.GetString(res));
        } 
    }
} 

// 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