XmlBufferReader.cs source code in C# .NET

Source code for the .NET framework in C#

                        

Code:

/ 4.0 / 4.0 / untmp / DEVDIV_TFS / Dev10 / Releases / RTMRel / ndp / cdf / src / WCF / Serialization / System / Xml / XmlBufferReader.cs / 1305376 / XmlBufferReader.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.Xml
{ 
    using System;
    using System.Collections; 
    using System.Globalization; 
    using System.IO;
    using System.Runtime; 
    using System.Runtime.Serialization;
    using System.Security;
    using System.Text;
 
    class XmlBufferReader
    { 
        XmlDictionaryReader reader; 
        Stream stream;
        byte[] streamBuffer; 
        byte[] buffer;
        int offsetMin;
        int offsetMax;
        IXmlDictionary dictionary; 
        XmlBinaryReaderSession session;
        byte[] guid; 
        int offset; 
        const int maxBytesPerChar = 3;
        char[] chars; 
        int windowOffset;
        int windowOffsetMax;
        ValueHandle listValue;
        static byte[] emptyByteArray = new byte[0]; 
        static XmlBufferReader empty = new XmlBufferReader(emptyByteArray);
 
        public XmlBufferReader(XmlDictionaryReader reader) 
        {
            this.reader = reader; 
        }

        public XmlBufferReader(byte[] buffer)
        { 
            this.reader = null;
            this.buffer = buffer; 
        } 

        static public XmlBufferReader Empty 
        {
            get
            {
                return empty; 
            }
        } 
 
        public byte[] Buffer
        { 
            get
            {
                return buffer;
            } 
        }
 
        public bool IsStreamed 
        {
            get 
            {
                return stream != null;
            }
        } 

        public void SetBuffer(Stream stream, IXmlDictionary dictionary, XmlBinaryReaderSession session) 
        { 
            if (streamBuffer == null)
            { 
                streamBuffer = new byte[128];
            }
            SetBuffer(stream, streamBuffer, 0, 0, dictionary, session);
            this.windowOffset = 0; 
            this.windowOffsetMax = streamBuffer.Length;
        } 
 
        public void SetBuffer(byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session)
        { 
            SetBuffer(null, buffer, offset, count, dictionary, session);
        }

        void SetBuffer(Stream stream, byte[] buffer, int offset, int count, IXmlDictionary dictionary, XmlBinaryReaderSession session) 
        {
            this.stream = stream; 
            this.buffer = buffer; 
            this.offsetMin = offset;
            this.offset = offset; 
            this.offsetMax = offset + count;
            this.dictionary = dictionary;
            this.session = session;
        } 

        public void Close() 
        { 
            if (streamBuffer != null && streamBuffer.Length > 4096)
            { 
                streamBuffer = null;
            }
            if (stream != null)
            { 
                stream.Close();
                this.stream = null; 
            } 
            this.buffer = emptyByteArray;
            this.offset = 0; 
            this.offsetMax = 0;
            this.windowOffset = 0;
            this.windowOffsetMax = 0;
            this.dictionary = null; 
            this.session = null;
        } 
 
        public bool EndOfFile
        { 
            get
            {
                return offset == offsetMax && !TryEnsureByte();
            } 
        }
 
        public byte GetByte() 
        {
            int offset = this.offset; 
            if (offset < offsetMax)
                return buffer[offset];
            else
                return GetByteHard(); 
        }
 
        public void SkipByte() 
        {
            Advance(1); 
        }

        byte GetByteHard()
        { 
            EnsureByte();
            return buffer[offset]; 
        } 

        public byte[] GetBuffer(int count, out int offset) 
        {
            offset = this.offset;
            if (offset <= this.offsetMax - count)
                return buffer; 
            return GetBufferHard(count, out offset);
        } 
 
        public byte[] GetBuffer(int count, out int offset, out int offsetMax)
        { 
            offset = this.offset;
            if (offset <= this.offsetMax - count)
            {
                offsetMax = this.offset + count; 
            }
            else 
            { 
                TryEnsureBytes(Math.Min(count, windowOffsetMax - offset));
                offsetMax = this.offsetMax; 
            }
            return buffer;
        }
 
        public byte[] GetBuffer(out int offset, out int offsetMax)
        { 
            offset = this.offset; 
            offsetMax = this.offsetMax;
            return buffer; 
        }

        byte[] GetBufferHard(int count, out int offset)
        { 
            offset = this.offset;
            EnsureBytes(count); 
            return buffer; 
        }
 
        void EnsureByte()
        {
            if (!TryEnsureByte())
                XmlExceptionHelper.ThrowUnexpectedEndOfFile(reader); 
        }
 
        bool TryEnsureByte() 
        {
            if (stream == null) 
                return false;
            if (offsetMax >= windowOffsetMax)
                XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset);
            if (offsetMax >= buffer.Length) 
                return TryEnsureBytes(1);
            int b = stream.ReadByte(); 
            if (b == -1) 
                return false;
            buffer[offsetMax++] = (byte)b; 
            return true;
        }

        void EnsureBytes(int count) 
        {
            if (!TryEnsureBytes(count)) 
                XmlExceptionHelper.ThrowUnexpectedEndOfFile(reader); 
        }
 
        bool TryEnsureBytes(int count)
        {
            if (stream == null)
                return false; 
            if (offset > int.MaxValue - count)
                XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset); 
            int newOffsetMax = offset + count; 
            if (newOffsetMax < offsetMax)
                return true; 
            if (newOffsetMax > windowOffsetMax)
                XmlExceptionHelper.ThrowMaxBytesPerReadExceeded(reader, windowOffsetMax - windowOffset);
            if (newOffsetMax > buffer.Length)
            { 
                byte[] newBuffer = new byte[Math.Max(newOffsetMax, buffer.Length * 2)];
                System.Buffer.BlockCopy(this.buffer, 0, newBuffer, 0, offsetMax); 
                buffer = newBuffer; 
                streamBuffer = newBuffer;
            } 
            int needed = newOffsetMax - offsetMax;
            while (needed > 0)
            {
                int actual = stream.Read(buffer, offsetMax, needed); 
                if (actual == 0)
                    return false; 
                offsetMax += actual; 
                needed -= actual;
            } 
            return true;
        }

#if NO 
        void ReadByte(byte b)
        { 
            if (BufferReader.GetByte() != b) 
                XmlExceptionHelper.ThrowTokenExpected(this, ((char)b).ToString(), (char)BufferReader.GetByte());
        } 
#endif
        public void Advance(int count)
        {
            Fx.Assert(this.offset + count <= offsetMax, ""); 
            this.offset += count;
        } 
 
        public void InsertBytes(byte[] buffer, int offset, int count)
        { 
            Fx.Assert(stream != null, "");
            if (offsetMax > buffer.Length - count)
            {
                byte[] newBuffer = new byte[offsetMax + count]; 
                System.Buffer.BlockCopy(this.buffer, 0, newBuffer, 0, this.offsetMax);
                this.buffer = newBuffer; 
                this.streamBuffer = newBuffer; 
            }
            System.Buffer.BlockCopy(this.buffer, this.offset, this.buffer, this.offset + count, this.offsetMax - this.offset); 
            offsetMax += count;
            System.Buffer.BlockCopy(buffer, offset, this.buffer, this.offset, count);
        }
 
        public void SetWindow(int windowOffset, int windowLength)
        { 
            // [0...elementOffset-1][elementOffset..offset][offset..offsetMax-1][offsetMax..buffer.Length] 
            // ^--Elements, Attributes in scope
            //                      ^-- The node just consumed 
            //                                             ^--Data buffered, not consumed
            //                                                                  ^--Unused space
            if (windowOffset > int.MaxValue - windowLength)
                windowLength = int.MaxValue - windowOffset; 

            if (offset != windowOffset) 
            { 
                System.Buffer.BlockCopy(buffer, offset, buffer, windowOffset, offsetMax - offset);
                offsetMax = windowOffset + (offsetMax - offset); 
                offset = windowOffset;
            }
            this.windowOffset = windowOffset;
            this.windowOffsetMax = Math.Max(windowOffset + windowLength, offsetMax); 
        }
 
        public int Offset 
        {
            get 
            {
                return offset;
            }
            set 
            {
                Fx.Assert(value >= offsetMin && value <= offsetMax, ""); 
                this.offset = value; 
            }
        } 

        public int ReadBytes(int count)
        {
            Fx.Assert(count >= 0, ""); 
            int offset = this.offset;
            if (offset > offsetMax - count) 
                EnsureBytes(count); 
            this.offset += count;
            return offset; 
        }

        public int ReadMultiByteUInt31()
        { 
            int i = GetByte();
            Advance(1); 
            if ((i & 0x80) == 0) 
                return i;
            i &= 0x7F; 

            int j = GetByte();
            Advance(1);
            i |= ((j & 0x7F) << 7); 
            if ((j & 0x80) == 0)
                return i; 
 
            int k = GetByte();
            Advance(1); 
            i |= ((k & 0x7F) << 14);
            if ((k & 0x80) == 0)
                return i;
 
            int l = GetByte();
            Advance(1); 
            i |= ((l & 0x7F) << 21); 
            if ((l & 0x80) == 0)
                return i; 

            int m = GetByte();
            Advance(1);
            i |= (m << 28); 
            if ((m & 0xF8) != 0)
                XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 
 
            return i;
        } 

        public int ReadUInt8()
        {
            byte b = GetByte(); 
            Advance(1);
            return b; 
        } 

        public int ReadInt8() 
        {
            return (sbyte)ReadUInt8();
        }
 
        public int ReadUInt16()
        { 
            int offset; 
            byte[] buffer = GetBuffer(2, out offset);
            int i = buffer[offset + 0] + (buffer[offset + 1] << 8); 
            Advance(2);
            return i;
        }
 
        public int ReadInt16()
        { 
            return (Int16)ReadUInt16(); 
        }
 
        public int ReadInt32()
        {
            int offset;
            byte[] buffer = GetBuffer(4, out offset); 
            byte b1 = buffer[offset + 0];
            byte b2 = buffer[offset + 1]; 
            byte b3 = buffer[offset + 2]; 
            byte b4 = buffer[offset + 3];
            Advance(4); 
            return (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
        }

        public int ReadUInt31() 
        {
            int i = ReadInt32(); 
            if (i < 0) 
                XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
            return i; 
        }

        public long ReadInt64()
        { 
            Int64 lo = (UInt32)ReadInt32();
            Int64 hi = (UInt32)ReadInt32(); 
            return (hi << 32) + lo; 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical]
        unsafe public float ReadSingle() 
        {
            int offset; 
            byte[] buffer = GetBuffer(ValueHandleLength.Single, out offset); 
            float value;
            byte* pb = (byte*)&value; 
            Fx.Assert(sizeof(float) == 4, "");
            pb[0] = buffer[offset + 0];
            pb[1] = buffer[offset + 1];
            pb[2] = buffer[offset + 2]; 
            pb[3] = buffer[offset + 3];
            Advance(ValueHandleLength.Single); 
            return value; 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical]
        unsafe public double ReadDouble() 
        {
            int offset; 
            byte[] buffer = GetBuffer(ValueHandleLength.Double, out offset); 
            double value;
            byte* pb = (byte*)&value; 
            Fx.Assert(sizeof(double) == 8, "");
            pb[0] = buffer[offset + 0];
            pb[1] = buffer[offset + 1];
            pb[2] = buffer[offset + 2]; 
            pb[3] = buffer[offset + 3];
            pb[4] = buffer[offset + 4]; 
            pb[5] = buffer[offset + 5]; 
            pb[6] = buffer[offset + 6];
            pb[7] = buffer[offset + 7]; 
            Advance(ValueHandleLength.Double);
            return value;
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 
        [SecuritySafeCritical] 
        unsafe public decimal ReadDecimal()
        { 
            const int SignMask = unchecked((int)0x80000000);
            const int ScaleMask = 0x00FF0000;

            int offset; 
            byte[] buffer = GetBuffer(ValueHandleLength.Decimal, out offset);
            byte b1 = buffer[offset + 0]; 
            byte b2 = buffer[offset + 1]; 
            byte b3 = buffer[offset + 2];
            byte b4 = buffer[offset + 3]; 
            int flags = (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;

            //this logic mirrors the code in Decimal(int []) ctor.
            if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) 
            {
                decimal value; 
                byte* pb = (byte*)&value; 
                for (int i = 0; i < sizeof(decimal); i++)
                    pb[i] = buffer[offset + i]; 

                Advance(ValueHandleLength.Decimal);
                return value;
            } 
            else
            { 
                XmlExceptionHelper.ThrowInvalidBinaryFormat(this.reader); 
            }
 
            //compiler doesn't know that XmlExceptionHelper.ThrowInvalidBinaryFormat always throws,
            //so we have to have a return statement here even though we shouldn't hit this code path...
            Fx.Assert("A decimal value should have been returned or an exception should have been thrown.");
            return default(decimal); 
        }
 
        public UniqueId ReadUniqueId() 
        {
            int offset; 
            byte[] buffer = GetBuffer(ValueHandleLength.UniqueId, out offset);
            UniqueId uniqueId = new UniqueId(buffer, offset);
            Advance(ValueHandleLength.UniqueId);
            return uniqueId; 
        }
 
        public DateTime ReadDateTime() 
        {
            long value = 0; 
            try
            {
                value = ReadInt64();
                return DateTime.FromBinary(value); 
            }
            catch (ArgumentException exception) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception));
            } 
            catch (FormatException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception));
            } 
            catch (OverflowException exception)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "DateTime", exception)); 
            }
        } 

        public TimeSpan ReadTimeSpan()
        {
            long value = 0; 
            try
            { 
                value = ReadInt64(); 
                return TimeSpan.FromTicks(value);
            } 
            catch (ArgumentException exception)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception));
            } 
            catch (FormatException exception)
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception)); 
            }
            catch (OverflowException exception) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(XmlExceptionHelper.CreateConversionException(value.ToString(CultureInfo.InvariantCulture), "TimeSpan", exception));
            }
        } 

        public Guid ReadGuid() 
        { 
            int offset;
            byte[] buffer = GetBuffer(ValueHandleLength.Guid, out offset); 
            Guid guid = GetGuid(offset);
            Advance(ValueHandleLength.Guid);
            return guid;
        } 

        public string ReadUTF8String(int length) 
        { 
            int offset;
            byte[] buffer = GetBuffer(length, out offset); 
            char[] chars = GetCharBuffer(length);
            int charCount = GetChars(offset, length, chars);
            string value = new string(chars, 0, charCount);
            Advance(length); 
            return value;
        } 
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")]
        [SecurityCritical] 
        unsafe public void UnsafeReadArray(byte* dst, byte* dstMax)
        {
            UnsafeReadArray(dst, (int)(dstMax - dst));
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 
        [SecurityCritical] 
        unsafe void UnsafeReadArray(byte* dst, int length)
        { 
            if (stream != null)
            {
                const int chunk = 256;
                while (length >= chunk) 
                {
                    byte[] _buffer = GetBuffer(chunk, out offset); 
                    for (int i = 0; i < chunk; i++) 
                    {
                        *dst++ = _buffer[offset + i]; 
                    }
                    Advance(chunk);
                    length -= chunk;
                } 
            }
 
            if (length > 0) 
            {
                byte[] buffer = GetBuffer(length, out offset); 
                fixed (byte* _src = &buffer[offset])
                {
                    byte* src = _src;
                    byte* dstMax = dst + length; 
                    while (dst < dstMax)
                    { 
                        *dst = *src; 
                        dst++;
                        src++; 
                    }
                }
                Advance(length);
            } 
        }
 
        char[] GetCharBuffer(int count) 
        {
            if (count > 1024) 
                return new char[count];
            if (chars == null || chars.Length < count)
                chars = new char[count];
            return chars; 
        }
 
        int GetChars(int offset, int length, char[] chars) 
        {
            byte[] buffer = this.buffer; 
            for (int i = 0; i < length; i++)
            {
                byte b = buffer[offset + i];
                if (b >= 0x80) 
                    return i + XmlConverter.ToChars(buffer, offset + i, length - i, chars, i);
                chars[i] = (char)b; 
            } 
            return length;
        } 

        int GetChars(int offset, int length, char[] chars, int charOffset)
        {
            byte[] buffer = this.buffer; 
            for (int i = 0; i < length; i++)
            { 
                byte b = buffer[offset + i]; 
                if (b >= 0x80)
                    return i + XmlConverter.ToChars(buffer, offset + i, length - i, chars, charOffset + i); 
                chars[charOffset + i] = (char)b;
            }
            return length;
        } 

        public string GetString(int offset, int length) 
        { 
            char[] chars = GetCharBuffer(length);
            int charCount = GetChars(offset, length, chars); 
            return new string(chars, 0, charCount);
        }

        public string GetUnicodeString(int offset, int length) 
        {
            return XmlConverter.ToStringUnicode(buffer, offset, length); 
        } 

        public string GetString(int offset, int length, XmlNameTable nameTable) 
        {
            char[] chars = GetCharBuffer(length);
            int charCount = GetChars(offset, length, chars);
            return nameTable.Add(chars, 0, charCount); 
        }
 
        public int GetEscapedChars(int offset, int length, char[] chars) 
        {
            byte[] buffer = this.buffer; 
            int charCount = 0;
            int textOffset = offset;
            int offsetMax = offset + length;
            while (true) 
            {
                while (offset < offsetMax && IsAttrChar(buffer[offset])) 
                    offset++; 
                charCount += GetChars(textOffset, offset - textOffset, chars, charCount);
                if (offset == offsetMax) 
                    break;
                textOffset = offset;
                if (buffer[offset] == '&')
                { 
                    while (offset < offsetMax && buffer[offset] != ';')
                        offset++; 
                    offset++; 
                    int ch = GetCharEntity(textOffset, offset - textOffset);
                    textOffset = offset; 
                    if (ch > char.MaxValue)
                    {
                        SurrogateChar surrogate = new SurrogateChar(ch);
                        chars[charCount++] = surrogate.HighChar; 
                        chars[charCount++] = surrogate.LowChar;
                    } 
                    else 
                    {
                        chars[charCount++] = (char)ch; 
                    }
                }
                else if (buffer[offset] == '\n' || buffer[offset] == '\t')
                { 
                    chars[charCount++] = ' ';
                    offset++; 
                    textOffset = offset; 
                }
                else // '\r' 
                {
                    chars[charCount++] = ' ';
                    offset++;
 
                    if (offset < offsetMax && buffer[offset] == '\n')
                        offset++; 
 
                    textOffset = offset;
                } 

            }
            return charCount;
        } 

        bool IsAttrChar(int ch) 
        { 
            switch (ch)
            { 
                case '&':
                case '\r':
                case '\t':
                case '\n': 
                    return false;
 
                default: 
                    return true;
            } 
        }

        public string GetEscapedString(int offset, int length)
        { 
            char[] chars = GetCharBuffer(length);
            int charCount = GetEscapedChars(offset, length, chars); 
            return new string(chars, 0, charCount); 
        }
 
        public string GetEscapedString(int offset, int length, XmlNameTable nameTable)
        {
            char[] chars = GetCharBuffer(length);
            int charCount = GetEscapedChars(offset, length, chars); 
            return nameTable.Add(chars, 0, charCount);
        } 
 
        int GetLessThanCharEntity(int offset, int length)
        { 
            byte[] buffer = this.buffer;
            if (length != 4 ||
                buffer[offset + 1] != (byte)'l' ||
                buffer[offset + 2] != (byte)'t') 
            {
                XmlExceptionHelper.ThrowInvalidCharRef(reader); 
            } 
            return (int)'<';
        } 

        int GetGreaterThanCharEntity(int offset, int length)
        {
            byte[] buffer = this.buffer; 
            if (length != 4 ||
                buffer[offset + 1] != (byte)'g' || 
                buffer[offset + 2] != (byte)'t') 
            {
                XmlExceptionHelper.ThrowInvalidCharRef(reader); 
            }
            return (int)'>';
        }
 
        int GetQuoteCharEntity(int offset, int length)
        { 
            byte[] buffer = this.buffer; 
            if (length != 6 ||
                buffer[offset + 1] != (byte)'q' || 
                buffer[offset + 2] != (byte)'u' ||
                buffer[offset + 3] != (byte)'o' ||
                buffer[offset + 4] != (byte)'t')
            { 
                XmlExceptionHelper.ThrowInvalidCharRef(reader);
            } 
            return (int)'"'; 
        }
 
        int GetAmpersandCharEntity(int offset, int length)
        {
            byte[] buffer = this.buffer;
            if (length != 5 || 
                buffer[offset + 1] != (byte)'a' ||
                buffer[offset + 2] != (byte)'m' || 
                buffer[offset + 3] != (byte)'p') 
            {
                XmlExceptionHelper.ThrowInvalidCharRef(reader); 
            }
            return (int)'&';
        }
 
        int GetApostropheCharEntity(int offset, int length)
        { 
            byte[] buffer = this.buffer; 
            if (length != 6 ||
                buffer[offset + 1] != (byte)'a' || 
                buffer[offset + 2] != (byte)'p' ||
                buffer[offset + 3] != (byte)'o' ||
                buffer[offset + 4] != (byte)'s')
            { 
                XmlExceptionHelper.ThrowInvalidCharRef(reader);
            } 
            return (int)'\''; 
        }
 
        int GetDecimalCharEntity(int offset, int length)
        {
            byte[] buffer = this.buffer;
            Fx.Assert(buffer[offset + 0] == '&', ""); 
            Fx.Assert(buffer[offset + 1] == '#', "");
            Fx.Assert(buffer[offset + length - 1] == ';', ""); 
            int value = 0; 
            for (int i = 2; i < length - 1; i++)
            { 
                byte ch = buffer[offset + i];
                if (ch < (byte)'0' || ch > (byte)'9')
                    XmlExceptionHelper.ThrowInvalidCharRef(reader);
                value = value * 10 + (ch - '0'); 
                if (value > SurrogateChar.MaxValue)
                    XmlExceptionHelper.ThrowInvalidCharRef(reader); 
            } 
            return value;
        } 

        int GetHexCharEntity(int offset, int length)
        {
            byte[] buffer = this.buffer; 
            Fx.Assert(buffer[offset + 0] == '&', "");
            Fx.Assert(buffer[offset + 1] == '#', ""); 
            Fx.Assert(buffer[offset + 2] == 'x', ""); 
            Fx.Assert(buffer[offset + length - 1] == ';', "");
            int value = 0; 
            for (int i = 3; i < length - 1; i++)
            {
                byte ch = buffer[offset + i];
                int digit = 0; 
                if (ch >= '0' && ch <= '9')
                    digit = (ch - '0'); 
                else if (ch >= 'a' && ch <= 'f') 
                    digit = 10 + (ch - 'a');
                else if (ch >= 'A' && ch <= 'F') 
                    digit = 10 + (ch - 'A');
                else
                    XmlExceptionHelper.ThrowInvalidCharRef(reader);
                Fx.Assert(digit >= 0 && digit < 16, ""); 
                value = value * 16 + digit;
                if (value > SurrogateChar.MaxValue) 
                    XmlExceptionHelper.ThrowInvalidCharRef(reader); 
            }
            return value; 
        }

        public int GetCharEntity(int offset, int length)
        { 
            if (length < 3)
                XmlExceptionHelper.ThrowInvalidCharRef(reader); 
            byte[] buffer = this.buffer; 
            Fx.Assert(buffer[offset] == '&', "");
            Fx.Assert(buffer[offset + length - 1] == ';', ""); 
            switch (buffer[offset + 1])
            {
                case (byte)'l':
                    return GetLessThanCharEntity(offset, length); 
                case (byte)'g':
                    return GetGreaterThanCharEntity(offset, length); 
                case (byte)'a': 
                    if (buffer[offset + 2] == (byte)'m')
                        return GetAmpersandCharEntity(offset, length); 
                    else
                        return GetApostropheCharEntity(offset, length);
                case (byte)'q':
                    return GetQuoteCharEntity(offset, length); 
                case (byte)'#':
                    if (buffer[offset + 2] == (byte)'x') 
                        return GetHexCharEntity(offset, length); 
                    else
                        return GetDecimalCharEntity(offset, length); 
                default:
                    XmlExceptionHelper.ThrowInvalidCharRef(reader);
                    return 0;
            } 
        }
 
        public bool IsWhitespaceKey(int key) 
        {
            string s = GetDictionaryString(key).Value; 
            for (int i = 0; i < s.Length; i++)
            {
                if (!XmlConverter.IsWhitespace(s[i]))
                    return false; 
            }
            return true; 
        } 

        public bool IsWhitespaceUTF8(int offset, int length) 
        {
            byte[] buffer = this.buffer;
            for (int i = 0; i < length; i++)
            { 
                if (!XmlConverter.IsWhitespace((char)buffer[offset + i]))
                    return false; 
            } 
            return true;
        } 

        public bool IsWhitespaceUnicode(int offset, int length)
        {
            byte[] buffer = this.buffer; 
            for (int i = 0; i < length; i += sizeof(char))
            { 
                char ch = (char)GetInt16(offset + i); 
                if (!XmlConverter.IsWhitespace(ch))
                    return false; 
            }
            return true;
        }
 
        public bool Equals2(int key1, int key2, XmlBufferReader bufferReader2)
        { 
            // If the keys aren't from the same dictionary, they still might be the same 
            if (key1 == key2)
                return true; 
            else
                return GetDictionaryString(key1).Value == bufferReader2.GetDictionaryString(key2).Value;
        }
 
        public bool Equals2(int key1, XmlDictionaryString xmlString2)
        { 
            if ((key1 & 1) == 0 && xmlString2.Dictionary == dictionary) 
                return xmlString2.Key == (key1 >> 1);
            else 
                return GetDictionaryString(key1).Value == xmlString2.Value;
        }

        public bool Equals2(int offset1, int length1, byte[] buffer2) 
        {
            int length2 = buffer2.Length; 
            if (length1 != length2) 
                return false;
            byte[] buffer1 = this.buffer; 
            for (int i = 0; i < length1; i++)
            {
                if (buffer1[offset1 + i] != buffer2[i])
                    return false; 
            }
            return true; 
        } 

        public bool Equals2(int offset1, int length1, XmlBufferReader bufferReader2, int offset2, int length2) 
        {
            if (length1 != length2)
                return false;
            byte[] buffer1 = this.buffer; 
            byte[] buffer2 = bufferReader2.buffer;
            for (int i = 0; i < length1; i++) 
            { 
                if (buffer1[offset1 + i] != buffer2[offset2 + i])
                    return false; 
            }
            return true;
        }
 
        public bool Equals2(int offset1, int length1, int offset2, int length2)
        { 
            if (length1 != length2) 
                return false;
            if (offset1 == offset2) 
                return true;
            byte[] buffer = this.buffer;
            for (int i = 0; i < length1; i++)
            { 
                if (buffer[offset1 + i] != buffer[offset2 + i])
                    return false; 
            } 
            return true;
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.",
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical] 
        unsafe public bool Equals2(int offset1, int length1, string s2)
        { 
            int byteLength = length1; 
            int charLength = s2.Length;
 
            // N unicode chars will be represented in at least N bytes, but
            // no more than N * 3 bytes.  If the byte count falls outside of this
            // range, then the strings cannot be equal.
            if (byteLength < charLength || byteLength > charLength * maxBytesPerChar) 
                return false;
 
            byte[] buffer = this.buffer; 
            if (length1 < 8)
            { 
                int length = Math.Min(byteLength, charLength);
                int offset = offset1;
                for (int i = 0; i < length; i++)
                { 
                    byte b = buffer[offset + i];
                    if (b >= 0x80) 
                        return XmlConverter.ToString(buffer, offset1, length1) == s2; 
                    if (s2[i] != (char)b)
                        return false; 
                }
                return byteLength == charLength;
            }
            else 
            {
                int length = Math.Min(byteLength, charLength); 
                fixed (byte* _pb = &buffer[offset1]) 
                {
                    byte* pb = _pb; 
                    byte* pbMax = pb + length;
                    fixed (char* _pch = s2)
                    {
                        char* pch = _pch; 
                        // Try to do the fast comparison in ascii space
                        int t = 0; 
                        while (pb < pbMax && *pb < 0x80) 
                        {
                            t = *pb - (byte)*pch; 
                            // The code generated is better if we break out then return
                            if (t != 0)
                                break;
                            pb++; 
                            pch++;
                        } 
                        if (t != 0) 
                            return false;
                        if (pb == pbMax) 
                            return (byteLength == charLength);
                    }
                }
                return XmlConverter.ToString(buffer, offset1, length1) == s2; 
            }
        } 
 
        public int Compare(int offset1, int length1, int offset2, int length2)
        { 
            byte[] buffer = this.buffer;
            int length = Math.Min(length1, length2);
            for (int i = 0; i < length; i++)
            { 
                int s = buffer[offset1 + i] - buffer[offset2 + i];
                if (s != 0) 
                    return s; 
            }
            return length1 - length2; 
        }

        public byte GetByte(int offset)
        { 
            return buffer[offset];
        } 
 
        public int GetInt8(int offset)
        { 
            return (sbyte)GetByte(offset);
        }

        public int GetInt16(int offset) 
        {
            byte[] buffer = this.buffer; 
            return (Int16)(buffer[offset] + (buffer[offset + 1] << 8)); 
        }
 
        public int GetInt32(int offset)
        {
            byte[] buffer = this.buffer;
            byte b1 = buffer[offset + 0]; 
            byte b2 = buffer[offset + 1];
            byte b3 = buffer[offset + 2]; 
            byte b4 = buffer[offset + 3]; 
            return (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
        } 

        public long GetInt64(int offset)
        {
            byte[] buffer = this.buffer; 
            byte b1, b2, b3, b4;
            b1 = buffer[offset + 0]; 
            b2 = buffer[offset + 1]; 
            b3 = buffer[offset + 2];
            b4 = buffer[offset + 3]; 
            Int64 lo = (UInt32)(((((b4 << 8) + b3) << 8) + b2) << 8) + b1;
            b1 = buffer[offset + 4];
            b2 = buffer[offset + 5];
            b3 = buffer[offset + 6]; 
            b4 = buffer[offset + 7];
            Int64 hi = (UInt32)(((((b4 << 8) + b3) << 8) + b2) << 8) + b1; 
            return (hi << 32) + lo; 
        }
 
        public ulong GetUInt64(int offset)
        {
            return (ulong)GetInt64(offset);
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 
        [SecuritySafeCritical]
        unsafe public float GetSingle(int offset) 
        {
            byte[] buffer = this.buffer;
            float value;
            byte* pb = (byte*)&value; 
            Fx.Assert(sizeof(float) == 4, "");
            pb[0] = buffer[offset + 0]; 
            pb[1] = buffer[offset + 1]; 
            pb[2] = buffer[offset + 2];
            pb[3] = buffer[offset + 3]; 
            return value;
        }

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical] 
        unsafe public double GetDouble(int offset) 
        {
            byte[] buffer = this.buffer; 
            double value;
            byte* pb = (byte*)&value;
            Fx.Assert(sizeof(double) == 8, "");
            pb[0] = buffer[offset + 0]; 
            pb[1] = buffer[offset + 1];
            pb[2] = buffer[offset + 2]; 
            pb[3] = buffer[offset + 3]; 
            pb[4] = buffer[offset + 4];
            pb[5] = buffer[offset + 5]; 
            pb[6] = buffer[offset + 6];
            pb[7] = buffer[offset + 7];
            return value;
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")] 
        [SecuritySafeCritical]
        public unsafe decimal GetDecimal(int offset) 
        {
            const int SignMask = unchecked((int)0x80000000);
            const int ScaleMask = 0x00FF0000;
 
            byte[] buffer = this.buffer;
            byte b1 = buffer[offset + 0]; 
            byte b2 = buffer[offset + 1]; 
            byte b3 = buffer[offset + 2];
            byte b4 = buffer[offset + 3]; 
            int flags = (((((b4 << 8) + b3) << 8) + b2) << 8) + b1;

            //this logic mirrors the code in Decimal(int []) ctor.
            if ((flags & ~(SignMask | ScaleMask)) == 0 && (flags & ScaleMask) <= (28 << 16)) 
            {
                decimal value; 
                byte* pb = (byte*)&value; 
                for (int i = 0; i < sizeof(decimal); i++)
                    pb[i] = buffer[offset + i]; 
                return value;
            }
            else
            { 
                XmlExceptionHelper.ThrowInvalidBinaryFormat(this.reader);
            } 
 
            //compiler doesn't know that XmlExceptionHelper.ThrowInvalidBinaryFormat always throws,
            //so we have to have a return statement here even though we shouldn't hit this code path... 
            Fx.Assert("A decimal value should have been returned or an exception should have been thrown.");
            return default(decimal);
        }
 
        public UniqueId GetUniqueId(int offset)
        { 
            return new UniqueId(this.buffer, offset); 
        }
 
        public Guid GetGuid(int offset)
        {
            if (guid == null)
                guid = new byte[16]; 
            System.Buffer.BlockCopy(buffer, offset, guid, 0, guid.Length);
            return new Guid(guid); 
        } 

        public void GetBase64(int srcOffset, byte[] buffer, int dstOffset, int count) 
        {
            System.Buffer.BlockCopy(this.buffer, srcOffset, buffer, dstOffset, count);
        }
 
        public XmlBinaryNodeType GetNodeType()
        { 
            return (XmlBinaryNodeType)GetByte(); 
        }
 
        public void SkipNodeType()
        {
            SkipByte();
        } 

        public object[] GetList(int offset, int count) 
        { 
            int bufferOffset = this.Offset;
            this.Offset = offset; 
            try
            {
                object[] objects = new object[count];
                for (int i = 0; i < count; i++) 
                {
                    XmlBinaryNodeType nodeType = GetNodeType(); 
                    SkipNodeType(); 
                    Fx.Assert(nodeType != XmlBinaryNodeType.StartListText, "");
                    ReadValue(nodeType, listValue); 
                    objects[i] = listValue.ToObject();
                }
                return objects;
            } 
            finally
            { 
                this.Offset = bufferOffset; 
            }
        } 

        public XmlDictionaryString GetDictionaryString(int key)
        {
            IXmlDictionary keyDictionary; 
            if ((key & 1) != 0)
            { 
                keyDictionary = session; 
            }
            else 
            {
                keyDictionary = dictionary;
            }
            XmlDictionaryString s; 
            if (!keyDictionary.TryLookup(key >> 1, out s))
                XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 
            return s; 
        }
 
        public int ReadDictionaryKey()
        {
            int key = ReadMultiByteUInt31();
            if ((key & 1) != 0) 
            {
                if (session == null) 
                    XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 
                int sessionKey = (key >> 1);
                XmlDictionaryString xmlString; 
                if (!session.TryLookup(sessionKey, out xmlString))
                {
                    if (sessionKey < XmlDictionaryString.MinKey || sessionKey > XmlDictionaryString.MaxKey)
                        XmlExceptionHelper.ThrowXmlDictionaryStringIDOutOfRange(this.reader); 
                    XmlExceptionHelper.ThrowXmlDictionaryStringIDUndefinedSession(this.reader, sessionKey);
                } 
            } 
            else
            { 
                if (dictionary == null)
                    XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
                int staticKey = (key >> 1);
                XmlDictionaryString xmlString; 
                if (!dictionary.TryLookup(staticKey, out xmlString))
                { 
                    if (staticKey < XmlDictionaryString.MinKey || staticKey > XmlDictionaryString.MaxKey) 
                        XmlExceptionHelper.ThrowXmlDictionaryStringIDOutOfRange(this.reader);
                    XmlExceptionHelper.ThrowXmlDictionaryStringIDUndefinedStatic(this.reader, staticKey); 
                }
            }

            return key; 
        }
 
        public void ReadValue(XmlBinaryNodeType nodeType, ValueHandle value) 
        {
            switch (nodeType) 
            {
                case XmlBinaryNodeType.EmptyText:
                    value.SetValue(ValueHandleType.Empty);
                    break; 
                case XmlBinaryNodeType.ZeroText:
                    value.SetValue(ValueHandleType.Zero); 
                    break; 
                case XmlBinaryNodeType.OneText:
                    value.SetValue(ValueHandleType.One); 
                    break;
                case XmlBinaryNodeType.TrueText:
                    value.SetValue(ValueHandleType.True);
                    break; 
                case XmlBinaryNodeType.FalseText:
                    value.SetValue(ValueHandleType.False); 
                    break; 
                case XmlBinaryNodeType.BoolText:
                    value.SetValue(ReadUInt8() != 0 ? ValueHandleType.True : ValueHandleType.False); 
                    break;
                case XmlBinaryNodeType.Chars8Text:
                    ReadValue(value, ValueHandleType.UTF8, ReadUInt8());
                    break; 
                case XmlBinaryNodeType.Chars16Text:
                    ReadValue(value, ValueHandleType.UTF8, ReadUInt16()); 
                    break; 
                case XmlBinaryNodeType.Chars32Text:
                    ReadValue(value, ValueHandleType.UTF8, ReadUInt31()); 
                    break;
                case XmlBinaryNodeType.UnicodeChars8Text:
                    ReadUnicodeValue(value, ReadUInt8());
                    break; 
                case XmlBinaryNodeType.UnicodeChars16Text:
                    ReadUnicodeValue(value, ReadUInt16()); 
                    break; 
                case XmlBinaryNodeType.UnicodeChars32Text:
                    ReadUnicodeValue(value, ReadUInt31()); 
                    break;
                case XmlBinaryNodeType.Bytes8Text:
                    ReadValue(value, ValueHandleType.Base64, ReadUInt8());
                    break; 
                case XmlBinaryNodeType.Bytes16Text:
                    ReadValue(value, ValueHandleType.Base64, ReadUInt16()); 
                    break; 
                case XmlBinaryNodeType.Bytes32Text:
                    ReadValue(value, ValueHandleType.Base64, ReadUInt31()); 
                    break;
                case XmlBinaryNodeType.DictionaryText:
                    value.SetDictionaryValue(ReadDictionaryKey());
                    break; 
                case XmlBinaryNodeType.UniqueIdText:
                    ReadValue(value, ValueHandleType.UniqueId, ValueHandleLength.UniqueId); 
                    break; 
                case XmlBinaryNodeType.GuidText:
                    ReadValue(value, ValueHandleType.Guid, ValueHandleLength.Guid); 
                    break;
                case XmlBinaryNodeType.DecimalText:
                    ReadValue(value, ValueHandleType.Decimal, ValueHandleLength.Decimal);
                    break; 
                case XmlBinaryNodeType.Int8Text:
                    ReadValue(value, ValueHandleType.Int8, ValueHandleLength.Int8); 
                    break; 
                case XmlBinaryNodeType.Int16Text:
                    ReadValue(value, ValueHandleType.Int16, ValueHandleLength.Int16); 
                    break;
                case XmlBinaryNodeType.Int32Text:
                    ReadValue(value, ValueHandleType.Int32, ValueHandleLength.Int32);
                    break; 
                case XmlBinaryNodeType.Int64Text:
                    ReadValue(value, ValueHandleType.Int64, ValueHandleLength.Int64); 
                    break; 
                case XmlBinaryNodeType.UInt64Text:
                    ReadValue(value, ValueHandleType.UInt64, ValueHandleLength.UInt64); 
                    break;
                case XmlBinaryNodeType.FloatText:
                    ReadValue(value, ValueHandleType.Single, ValueHandleLength.Single);
                    break; 
                case XmlBinaryNodeType.DoubleText:
                    ReadValue(value, ValueHandleType.Double, ValueHandleLength.Double); 
                    break; 
                case XmlBinaryNodeType.TimeSpanText:
                    ReadValue(value, ValueHandleType.TimeSpan, ValueHandleLength.TimeSpan); 
                    break;
                case XmlBinaryNodeType.DateTimeText:
                    ReadValue(value, ValueHandleType.DateTime, ValueHandleLength.DateTime);
                    break; 
                case XmlBinaryNodeType.StartListText:
                    ReadList(value); 
                    break; 
                case XmlBinaryNodeType.QNameDictionaryText:
                    ReadQName(value); 
                    break;
                default:
                    XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
                    break; 
            }
        } 
 
        void ReadValue(ValueHandle value, ValueHandleType type, int length)
        { 
            int offset = ReadBytes(length);
            value.SetValue(type, offset, length);
        }
 
        void ReadUnicodeValue(ValueHandle value, int length)
        { 
            if ((length & 1) != 0) 
                XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
            ReadValue(value, ValueHandleType.Unicode, length); 
        }

        void ReadList(ValueHandle value)
        { 
            if (listValue == null)
            { 
                listValue = new ValueHandle(this); 
            }
            int count = 0; 
            int offset = this.Offset;
            while (true)
            {
                XmlBinaryNodeType nodeType = GetNodeType(); 
                SkipNodeType();
                if (nodeType == XmlBinaryNodeType.StartListText) 
                    XmlExceptionHelper.ThrowInvalidBinaryFormat(reader); 
                if (nodeType == XmlBinaryNodeType.EndListText)
                    break; 
                ReadValue(nodeType, listValue);
                count++;
            }
            value.SetValue(ValueHandleType.List, offset, count); 
        }
 
        public void ReadQName(ValueHandle value) 
        {
            int prefix = ReadUInt8(); 
            if (prefix >= 26)
                XmlExceptionHelper.ThrowInvalidBinaryFormat(reader);
            int key = ReadDictionaryKey();
            value.SetQNameValue(prefix, key); 
        }
 
        public int[] GetRows() 
        {
            if (buffer == null) 
            {
                return new int[1] { 0 };
            }
 
            ArrayList list = new ArrayList();
            list.Add(offsetMin); 
            for (int i = offsetMin; i < offsetMax; i++) 
            {
                if (buffer[i] == (byte)13 || buffer[i] == (byte)10) 
                {
                    if (i + 1 < offsetMax && buffer[i + 1] == (byte)10)
                        i++;
                    list.Add(i + 1); 
                }
            } 
            return (int[])list.ToArray(typeof(int)); 
        }
    } 
}

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