JsonEncodingStreamWrapper.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 / cdf / src / WCF / Serialization / System / Runtime / Serialization / Json / JsonEncodingStreamWrapper.cs / 1305376 / JsonEncodingStreamWrapper.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------

#pragma warning disable 1634 // Stops compiler from warning about unknown warnings (for Presharp) 

namespace System.Runtime.Serialization.Json 
{ 
    using System.IO;
    using System.ServiceModel; 
    using System.Text;
    using System.Xml;
    using System.Security;
 
    // This wrapper does not support seek.
    // Supports: UTF-8, Unicode, BigEndianUnicode 
    // ASSUMPTION ([....]): This class will only be used for EITHER reading OR writing.  It can be done, it would just mean more buffers. 
    class JsonEncodingStreamWrapper : Stream
    { 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly UnicodeEncoding SafeBEUTF16 = new UnicodeEncoding(true, false, false);
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")] 
        static readonly UnicodeEncoding SafeUTF16 = new UnicodeEncoding(false, false, false); 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" 
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly UTF8Encoding SafeUTF8 = new UTF8Encoding(false, false);

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" 
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly UnicodeEncoding ValidatingBEUTF16 = new UnicodeEncoding(true, false, true); 
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")] 
        static readonly UnicodeEncoding ValidatingUTF16 = new UnicodeEncoding(false, false, true);

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")] 
        static readonly UTF8Encoding ValidatingUTF8 = new UTF8Encoding(false, true);
        const int BufferLength = 128; 
 
        byte[] byteBuffer = new byte[1];
        int byteCount; 
        int byteOffset;
        byte[] bytes;
        char[] chars;
        Decoder dec; 
        Encoder enc;
        Encoding encoding; 
 
        SupportedEncoding encodingCode;
        bool isReading; 

        Stream stream;

        public JsonEncodingStreamWrapper(Stream stream, Encoding encoding, bool isReader) 
        {
            this.isReading = isReader; 
            if (isReader) 
            {
                InitForReading(stream, encoding); 
            }
            else
            {
                if (encoding == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encoding"); 
                } 

                InitForWriting(stream, encoding); 
            }
        }

        enum SupportedEncoding 
        {
            UTF8, 
            UTF16LE, 
            UTF16BE,
            None 
        }

        // This stream wrapper does not support duplex
        public override bool CanRead 
        {
            get 
            { 
                if (!isReading)
                { 
                    return false;
                }

                return this.stream.CanRead; 
            }
        } 
 
        // The encoding conversion and buffering breaks seeking.
        public override bool CanSeek 
        {
            get {return false; }
        }
 
        // Delegate properties
        public override bool CanTimeout 
        { 
            get {return this.stream.CanTimeout; }
        } 

        // This stream wrapper does not support duplex
        public override bool CanWrite
        { 
            get
            { 
                if (isReading) 
                {
                    return false; 
                }

                return this.stream.CanWrite;
            } 
        }
 
        public override long Length 
        {
            get {return this.stream.Length; } 
        }


        // The encoding conversion and buffering breaks seeking. 
        public override long Position
        { 
            get 
            {
#pragma warning suppress 56503 // The contract for non seekable stream is to throw exception 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
            }
            set {throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); }
        } 

        public override int ReadTimeout 
        { 
            get {return this.stream.ReadTimeout; }
            set {this.stream.ReadTimeout = value; } 
        }

        public override int WriteTimeout
        { 
            get {return this.stream.WriteTimeout; }
            set {this.stream.WriteTimeout = value; } 
        } 

        public static ArraySegment ProcessBuffer(byte[] buffer, int offset, int count, Encoding encoding) 
        {
            try
            {
                SupportedEncoding expectedEnc = GetSupportedEncoding(encoding); 
                SupportedEncoding dataEnc;
                if (count < 2) 
                { 
                    dataEnc = SupportedEncoding.UTF8;
                } 
                else
                {
                    dataEnc = ReadEncoding(buffer[offset], buffer[offset + 1]);
                } 
                if ((expectedEnc != SupportedEncoding.None) && (expectedEnc != dataEnc))
                { 
                    ThrowExpectedEncodingMismatch(expectedEnc, dataEnc); 
                }
 
                // Fastpath: UTF-8
                if (dataEnc == SupportedEncoding.UTF8)
                {
                    return new ArraySegment(buffer, offset, count); 
                }
 
                // Convert to UTF-8 
                return
                    new ArraySegment(ValidatingUTF8.GetBytes(GetEncoding(dataEnc).GetChars(buffer, offset, count))); 
            }
            catch (DecoderFallbackException e)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonInvalidBytes), e));
            } 
        } 

        public override void Close() 
        {
            Flush();
            base.Close();
            this.stream.Close(); 
        }
 
        public override void Flush() 
        {
            this.stream.Flush(); 
        }

        public override int Read(byte[] buffer, int offset, int count)
        { 
            try
            { 
                if (byteCount == 0) 
                {
                    if (encodingCode == SupportedEncoding.UTF8) 
                    {
                        return this.stream.Read(buffer, offset, count);
                    }
 
                    // No more bytes than can be turned into characters
                    byteOffset = 0; 
                    byteCount = this.stream.Read(bytes, byteCount, (chars.Length - 1) * 2); 

                    // Check for end of stream 
                    if (byteCount == 0)
                    {
                        return 0;
                    } 

                    // Fix up incomplete chars 
                    CleanupCharBreak(); 

                    // Change encoding 
                    int charCount = this.encoding.GetChars(bytes, 0, byteCount, chars, 0);
                    byteCount = Encoding.UTF8.GetBytes(chars, 0, charCount, bytes, 0);
                }
 
                // Give them bytes
                if (byteCount < count) 
                { 
                    count = byteCount;
                } 
                Buffer.BlockCopy(bytes, byteOffset, buffer, offset, count);
                byteOffset += count;
                byteCount -= count;
                return count; 
            }
            catch (DecoderFallbackException ex) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonInvalidBytes), ex)); 
            }
        }

        public override int ReadByte() 
        {
            if (byteCount == 0 && encodingCode == SupportedEncoding.UTF8) 
            { 
                return this.stream.ReadByte();
            } 
            if (Read(byteBuffer, 0, 1) == 0)
            {
                return -1;
            } 
            return byteBuffer[0];
        } 
 
        public override long Seek(long offset, SeekOrigin origin)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
        }

        // Delegate methods 
        public override void SetLength(long value)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); 
        }
 
        public override void Write(byte[] buffer, int offset, int count)
        {
            // Optimize UTF-8 case
            if (encodingCode == SupportedEncoding.UTF8) 
            {
                this.stream.Write(buffer, offset, count); 
                return; 
            }
 
            while (count > 0)
            {
                int size = chars.Length < count ? chars.Length : count;
                int charCount = dec.GetChars(buffer, offset, size, chars, 0, false); 
                byteCount = enc.GetBytes(chars, 0, charCount, bytes, 0, false);
                this.stream.Write(bytes, 0, byteCount); 
                offset += size; 
                count -= size;
            } 
        }

        public override void WriteByte(byte b)
        { 
            if (encodingCode == SupportedEncoding.UTF8)
            { 
                this.stream.WriteByte(b); 
                return;
            } 
            byteBuffer[0] = b;
            Write(byteBuffer, 0, 1);
        }
 
        static Encoding GetEncoding(SupportedEncoding e)
        { 
            switch (e) 
            {
                case SupportedEncoding.UTF8: 
                    return ValidatingUTF8;

                case SupportedEncoding.UTF16LE:
                    return ValidatingUTF16; 

                case SupportedEncoding.UTF16BE: 
                    return ValidatingBEUTF16; 

                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonEncodingNotSupported)));
            }
        } 

        static string GetEncodingName(SupportedEncoding enc) 
        { 
            switch (enc)
            { 
                case SupportedEncoding.UTF8:
                    return "utf-8";

                case SupportedEncoding.UTF16LE: 
                    return "utf-16LE";
 
                case SupportedEncoding.UTF16BE: 
                    return "utf-16BE";
 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonEncodingNotSupported)));
            } 
        }
 
        static SupportedEncoding GetSupportedEncoding(Encoding encoding) 
        {
            if (encoding == null) 
            {
                return SupportedEncoding.None;
            }
            if (encoding.WebName == ValidatingUTF8.WebName) 
            {
                return SupportedEncoding.UTF8; 
            } 
            else if (encoding.WebName == ValidatingUTF16.WebName)
            { 
                return SupportedEncoding.UTF16LE;
            }
            else if (encoding.WebName == ValidatingBEUTF16.WebName)
            { 
                return SupportedEncoding.UTF16BE;
            } 
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonEncodingNotSupported)));
            }
        }
 
        static SupportedEncoding ReadEncoding(byte b1, byte b2)
        { 
            if (b1 == 0x00 && b2 != 0x00) 
            {
                return SupportedEncoding.UTF16BE; 
            }
            else if (b1 != 0x00 && b2 == 0x00)
            {
                // 857 It's possible to misdetect UTF-32LE as UTF-16LE, but that's OK. 
                return SupportedEncoding.UTF16LE;
            } 
            else if (b1 == 0x00 && b2 == 0x00) 
            {
                // UTF-32BE not supported 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonInvalidBytes)));
            }
            else
            { 
                return SupportedEncoding.UTF8;
            } 
        } 

        static void ThrowExpectedEncodingMismatch(SupportedEncoding expEnc, SupportedEncoding actualEnc) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonExpectedEncoding, GetEncodingName(expEnc), GetEncodingName(actualEnc))));
        }
 
        void CleanupCharBreak()
        { 
            int max = byteOffset + byteCount; 

            // Read on 2 byte boundaries 
            if ((byteCount % 2) != 0)
            {
                int b = this.stream.ReadByte();
                if (b < 0) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonUnexpectedEndOfFile))); 
                }
 
                bytes[max++] = (byte) b;
                byteCount++;
            }
 
            // Don't cut off a surrogate character
            int w; 
            if (encodingCode == SupportedEncoding.UTF16LE) 
            {
                w = bytes[max - 2] + (bytes[max - 1] << 8); 
            }
            else
            {
                w = bytes[max - 1] + (bytes[max - 2] << 8); 
            }
            if ((w & 0xDC00) != 0xDC00 && w >= 0xD800 && w <= 0xDBFF) // First 16-bit number of surrogate pair 
            { 
                int b1 = this.stream.ReadByte();
                int b2 = this.stream.ReadByte(); 
                if (b2 < 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonUnexpectedEndOfFile))); 
                }
                bytes[max++] = (byte) b1; 
                bytes[max++] = (byte) b2; 
                byteCount += 2;
            } 
        }

        void EnsureBuffers()
        { 
            EnsureByteBuffer();
            if (chars == null) 
            { 
                chars = new char[BufferLength];
            } 
        }

        void EnsureByteBuffer()
        { 
            if (bytes != null)
            { 
                return; 
            }
 
            bytes = new byte[BufferLength * 4];
            byteOffset = 0;
            byteCount = 0;
        } 

        void FillBuffer(int count) 
        { 
            count -= byteCount;
            while (count > 0) 
            {
                int read = stream.Read(bytes, byteOffset + byteCount, count);
                if (read == 0)
                { 
                    break;
                } 
 
                byteCount += read;
                count -= read; 
            }
        }

        void InitForReading(Stream inputStream, Encoding expectedEncoding) 
        {
            try 
            { 
                this.stream = new BufferedStream(inputStream);
 
                SupportedEncoding expectedEnc = GetSupportedEncoding(expectedEncoding);
                SupportedEncoding dataEnc = ReadEncoding();
                if ((expectedEnc != SupportedEncoding.None) && (expectedEnc != dataEnc))
                { 
                    ThrowExpectedEncodingMismatch(expectedEnc, dataEnc);
                } 
 
                // Fastpath: UTF-8 (do nothing)
                if (dataEnc != SupportedEncoding.UTF8) 
                {
                    // Convert to UTF-8
                    EnsureBuffers();
                    FillBuffer((BufferLength - 1) * 2); 
                    this.encodingCode = dataEnc;
                    this.encoding = GetEncoding(dataEnc); 
                    CleanupCharBreak(); 
                    int count = this.encoding.GetChars(bytes, byteOffset, byteCount, chars, 0);
                    byteOffset = 0; 
                    byteCount = ValidatingUTF8.GetBytes(chars, 0, count, bytes, 0);
                }
            }
            catch (DecoderFallbackException ex) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonInvalidBytes), ex)); 
            }
        } 

        void InitForWriting(Stream outputStream, Encoding writeEncoding)
        {
            this.encoding = writeEncoding; 
            this.stream = new BufferedStream(outputStream);
 
            // Set the encoding code 
            this.encodingCode = GetSupportedEncoding(writeEncoding);
 
            if (this.encodingCode != SupportedEncoding.UTF8)
            {
                EnsureBuffers();
                dec = ValidatingUTF8.GetDecoder(); 
                enc = this.encoding.GetEncoder();
            } 
        } 

        SupportedEncoding ReadEncoding() 
        {
            int b1 = this.stream.ReadByte();
            int b2 = this.stream.ReadByte();
 
            EnsureByteBuffer();
 
            SupportedEncoding e; 

            if (b1 == -1) 
            {
                e = SupportedEncoding.UTF8;
                byteCount = 0;
            } 
            else if (b2 == -1)
            { 
                e = SupportedEncoding.UTF8; 
                bytes[0] = (byte) b1;
                byteCount = 1; 
            }
            else
            {
                e = ReadEncoding((byte) b1, (byte) b2); 
                bytes[0] = (byte) b1;
                bytes[1] = (byte) b2; 
                byteCount = 2; 
            }
 
            return e;
        }
    }
} 

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

#pragma warning disable 1634 // Stops compiler from warning about unknown warnings (for Presharp) 

namespace System.Runtime.Serialization.Json 
{ 
    using System.IO;
    using System.ServiceModel; 
    using System.Text;
    using System.Xml;
    using System.Security;
 
    // This wrapper does not support seek.
    // Supports: UTF-8, Unicode, BigEndianUnicode 
    // ASSUMPTION ([....]): This class will only be used for EITHER reading OR writing.  It can be done, it would just mean more buffers. 
    class JsonEncodingStreamWrapper : Stream
    { 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly UnicodeEncoding SafeBEUTF16 = new UnicodeEncoding(true, false, false);
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")] 
        static readonly UnicodeEncoding SafeUTF16 = new UnicodeEncoding(false, false, false); 

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" 
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly UTF8Encoding SafeUTF8 = new UTF8Encoding(false, false);

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent" 
            + " data from being modified or leaked to other components in appdomain.")]
        static readonly UnicodeEncoding ValidatingBEUTF16 = new UnicodeEncoding(true, false, true); 
 
        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")] 
        static readonly UnicodeEncoding ValidatingUTF16 = new UnicodeEncoding(false, false, true);

        [Fx.Tag.SecurityNote(Miscellaneous = "RequiresReview - Static fields are marked SecurityCritical or readonly to prevent"
            + " data from being modified or leaked to other components in appdomain.")] 
        static readonly UTF8Encoding ValidatingUTF8 = new UTF8Encoding(false, true);
        const int BufferLength = 128; 
 
        byte[] byteBuffer = new byte[1];
        int byteCount; 
        int byteOffset;
        byte[] bytes;
        char[] chars;
        Decoder dec; 
        Encoder enc;
        Encoding encoding; 
 
        SupportedEncoding encodingCode;
        bool isReading; 

        Stream stream;

        public JsonEncodingStreamWrapper(Stream stream, Encoding encoding, bool isReader) 
        {
            this.isReading = isReader; 
            if (isReader) 
            {
                InitForReading(stream, encoding); 
            }
            else
            {
                if (encoding == null) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("encoding"); 
                } 

                InitForWriting(stream, encoding); 
            }
        }

        enum SupportedEncoding 
        {
            UTF8, 
            UTF16LE, 
            UTF16BE,
            None 
        }

        // This stream wrapper does not support duplex
        public override bool CanRead 
        {
            get 
            { 
                if (!isReading)
                { 
                    return false;
                }

                return this.stream.CanRead; 
            }
        } 
 
        // The encoding conversion and buffering breaks seeking.
        public override bool CanSeek 
        {
            get {return false; }
        }
 
        // Delegate properties
        public override bool CanTimeout 
        { 
            get {return this.stream.CanTimeout; }
        } 

        // This stream wrapper does not support duplex
        public override bool CanWrite
        { 
            get
            { 
                if (isReading) 
                {
                    return false; 
                }

                return this.stream.CanWrite;
            } 
        }
 
        public override long Length 
        {
            get {return this.stream.Length; } 
        }


        // The encoding conversion and buffering breaks seeking. 
        public override long Position
        { 
            get 
            {
#pragma warning suppress 56503 // The contract for non seekable stream is to throw exception 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
            }
            set {throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); }
        } 

        public override int ReadTimeout 
        { 
            get {return this.stream.ReadTimeout; }
            set {this.stream.ReadTimeout = value; } 
        }

        public override int WriteTimeout
        { 
            get {return this.stream.WriteTimeout; }
            set {this.stream.WriteTimeout = value; } 
        } 

        public static ArraySegment ProcessBuffer(byte[] buffer, int offset, int count, Encoding encoding) 
        {
            try
            {
                SupportedEncoding expectedEnc = GetSupportedEncoding(encoding); 
                SupportedEncoding dataEnc;
                if (count < 2) 
                { 
                    dataEnc = SupportedEncoding.UTF8;
                } 
                else
                {
                    dataEnc = ReadEncoding(buffer[offset], buffer[offset + 1]);
                } 
                if ((expectedEnc != SupportedEncoding.None) && (expectedEnc != dataEnc))
                { 
                    ThrowExpectedEncodingMismatch(expectedEnc, dataEnc); 
                }
 
                // Fastpath: UTF-8
                if (dataEnc == SupportedEncoding.UTF8)
                {
                    return new ArraySegment(buffer, offset, count); 
                }
 
                // Convert to UTF-8 
                return
                    new ArraySegment(ValidatingUTF8.GetBytes(GetEncoding(dataEnc).GetChars(buffer, offset, count))); 
            }
            catch (DecoderFallbackException e)
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonInvalidBytes), e));
            } 
        } 

        public override void Close() 
        {
            Flush();
            base.Close();
            this.stream.Close(); 
        }
 
        public override void Flush() 
        {
            this.stream.Flush(); 
        }

        public override int Read(byte[] buffer, int offset, int count)
        { 
            try
            { 
                if (byteCount == 0) 
                {
                    if (encodingCode == SupportedEncoding.UTF8) 
                    {
                        return this.stream.Read(buffer, offset, count);
                    }
 
                    // No more bytes than can be turned into characters
                    byteOffset = 0; 
                    byteCount = this.stream.Read(bytes, byteCount, (chars.Length - 1) * 2); 

                    // Check for end of stream 
                    if (byteCount == 0)
                    {
                        return 0;
                    } 

                    // Fix up incomplete chars 
                    CleanupCharBreak(); 

                    // Change encoding 
                    int charCount = this.encoding.GetChars(bytes, 0, byteCount, chars, 0);
                    byteCount = Encoding.UTF8.GetBytes(chars, 0, charCount, bytes, 0);
                }
 
                // Give them bytes
                if (byteCount < count) 
                { 
                    count = byteCount;
                } 
                Buffer.BlockCopy(bytes, byteOffset, buffer, offset, count);
                byteOffset += count;
                byteCount -= count;
                return count; 
            }
            catch (DecoderFallbackException ex) 
            { 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                    new XmlException(SR.GetString(SR.JsonInvalidBytes), ex)); 
            }
        }

        public override int ReadByte() 
        {
            if (byteCount == 0 && encodingCode == SupportedEncoding.UTF8) 
            { 
                return this.stream.ReadByte();
            } 
            if (Read(byteBuffer, 0, 1) == 0)
            {
                return -1;
            } 
            return byteBuffer[0];
        } 
 
        public override long Seek(long offset, SeekOrigin origin)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException());
        }

        // Delegate methods 
        public override void SetLength(long value)
        { 
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); 
        }
 
        public override void Write(byte[] buffer, int offset, int count)
        {
            // Optimize UTF-8 case
            if (encodingCode == SupportedEncoding.UTF8) 
            {
                this.stream.Write(buffer, offset, count); 
                return; 
            }
 
            while (count > 0)
            {
                int size = chars.Length < count ? chars.Length : count;
                int charCount = dec.GetChars(buffer, offset, size, chars, 0, false); 
                byteCount = enc.GetBytes(chars, 0, charCount, bytes, 0, false);
                this.stream.Write(bytes, 0, byteCount); 
                offset += size; 
                count -= size;
            } 
        }

        public override void WriteByte(byte b)
        { 
            if (encodingCode == SupportedEncoding.UTF8)
            { 
                this.stream.WriteByte(b); 
                return;
            } 
            byteBuffer[0] = b;
            Write(byteBuffer, 0, 1);
        }
 
        static Encoding GetEncoding(SupportedEncoding e)
        { 
            switch (e) 
            {
                case SupportedEncoding.UTF8: 
                    return ValidatingUTF8;

                case SupportedEncoding.UTF16LE:
                    return ValidatingUTF16; 

                case SupportedEncoding.UTF16BE: 
                    return ValidatingBEUTF16; 

                default: 
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonEncodingNotSupported)));
            }
        } 

        static string GetEncodingName(SupportedEncoding enc) 
        { 
            switch (enc)
            { 
                case SupportedEncoding.UTF8:
                    return "utf-8";

                case SupportedEncoding.UTF16LE: 
                    return "utf-16LE";
 
                case SupportedEncoding.UTF16BE: 
                    return "utf-16BE";
 
                default:
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonEncodingNotSupported)));
            } 
        }
 
        static SupportedEncoding GetSupportedEncoding(Encoding encoding) 
        {
            if (encoding == null) 
            {
                return SupportedEncoding.None;
            }
            if (encoding.WebName == ValidatingUTF8.WebName) 
            {
                return SupportedEncoding.UTF8; 
            } 
            else if (encoding.WebName == ValidatingUTF16.WebName)
            { 
                return SupportedEncoding.UTF16LE;
            }
            else if (encoding.WebName == ValidatingBEUTF16.WebName)
            { 
                return SupportedEncoding.UTF16BE;
            } 
            else 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonEncodingNotSupported)));
            }
        }
 
        static SupportedEncoding ReadEncoding(byte b1, byte b2)
        { 
            if (b1 == 0x00 && b2 != 0x00) 
            {
                return SupportedEncoding.UTF16BE; 
            }
            else if (b1 != 0x00 && b2 == 0x00)
            {
                // 857 It's possible to misdetect UTF-32LE as UTF-16LE, but that's OK. 
                return SupportedEncoding.UTF16LE;
            } 
            else if (b1 == 0x00 && b2 == 0x00) 
            {
                // UTF-32BE not supported 
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonInvalidBytes)));
            }
            else
            { 
                return SupportedEncoding.UTF8;
            } 
        } 

        static void ThrowExpectedEncodingMismatch(SupportedEncoding expEnc, SupportedEncoding actualEnc) 
        {
            throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.JsonExpectedEncoding, GetEncodingName(expEnc), GetEncodingName(actualEnc))));
        }
 
        void CleanupCharBreak()
        { 
            int max = byteOffset + byteCount; 

            // Read on 2 byte boundaries 
            if ((byteCount % 2) != 0)
            {
                int b = this.stream.ReadByte();
                if (b < 0) 
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                        new XmlException(SR.GetString(SR.JsonUnexpectedEndOfFile))); 
                }
 
                bytes[max++] = (byte) b;
                byteCount++;
            }
 
            // Don't cut off a surrogate character
            int w; 
            if (encodingCode == SupportedEncoding.UTF16LE) 
            {
                w = bytes[max - 2] + (bytes[max - 1] << 8); 
            }
            else
            {
                w = bytes[max - 1] + (bytes[max - 2] << 8); 
            }
            if ((w & 0xDC00) != 0xDC00 && w >= 0xD800 && w <= 0xDBFF) // First 16-bit number of surrogate pair 
            { 
                int b1 = this.stream.ReadByte();
                int b2 = this.stream.ReadByte(); 
                if (b2 < 0)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(
                        new XmlException(SR.GetString(SR.JsonUnexpectedEndOfFile))); 
                }
                bytes[max++] = (byte) b1; 
                bytes[max++] = (byte) b2; 
                byteCount += 2;
            } 
        }

        void EnsureBuffers()
        { 
            EnsureByteBuffer();
            if (chars == null) 
            { 
                chars = new char[BufferLength];
            } 
        }

        void EnsureByteBuffer()
        { 
            if (bytes != null)
            { 
                return; 
            }
 
            bytes = new byte[BufferLength * 4];
            byteOffset = 0;
            byteCount = 0;
        } 

        void FillBuffer(int count) 
        { 
            count -= byteCount;
            while (count > 0) 
            {
                int read = stream.Read(bytes, byteOffset + byteCount, count);
                if (read == 0)
                { 
                    break;
                } 
 
                byteCount += read;
                count -= read; 
            }
        }

        void InitForReading(Stream inputStream, Encoding expectedEncoding) 
        {
            try 
            { 
                this.stream = new BufferedStream(inputStream);
 
                SupportedEncoding expectedEnc = GetSupportedEncoding(expectedEncoding);
                SupportedEncoding dataEnc = ReadEncoding();
                if ((expectedEnc != SupportedEncoding.None) && (expectedEnc != dataEnc))
                { 
                    ThrowExpectedEncodingMismatch(expectedEnc, dataEnc);
                } 
 
                // Fastpath: UTF-8 (do nothing)
                if (dataEnc != SupportedEncoding.UTF8) 
                {
                    // Convert to UTF-8
                    EnsureBuffers();
                    FillBuffer((BufferLength - 1) * 2); 
                    this.encodingCode = dataEnc;
                    this.encoding = GetEncoding(dataEnc); 
                    CleanupCharBreak(); 
                    int count = this.encoding.GetChars(bytes, byteOffset, byteCount, chars, 0);
                    byteOffset = 0; 
                    byteCount = ValidatingUTF8.GetBytes(chars, 0, count, bytes, 0);
                }
            }
            catch (DecoderFallbackException ex) 
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError( 
                    new XmlException(SR.GetString(SR.JsonInvalidBytes), ex)); 
            }
        } 

        void InitForWriting(Stream outputStream, Encoding writeEncoding)
        {
            this.encoding = writeEncoding; 
            this.stream = new BufferedStream(outputStream);
 
            // Set the encoding code 
            this.encodingCode = GetSupportedEncoding(writeEncoding);
 
            if (this.encodingCode != SupportedEncoding.UTF8)
            {
                EnsureBuffers();
                dec = ValidatingUTF8.GetDecoder(); 
                enc = this.encoding.GetEncoder();
            } 
        } 

        SupportedEncoding ReadEncoding() 
        {
            int b1 = this.stream.ReadByte();
            int b2 = this.stream.ReadByte();
 
            EnsureByteBuffer();
 
            SupportedEncoding e; 

            if (b1 == -1) 
            {
                e = SupportedEncoding.UTF8;
                byteCount = 0;
            } 
            else if (b2 == -1)
            { 
                e = SupportedEncoding.UTF8; 
                bytes[0] = (byte) b1;
                byteCount = 1; 
            }
            else
            {
                e = ReadEncoding((byte) b1, (byte) b2); 
                bytes[0] = (byte) b1;
                bytes[1] = (byte) b2; 
                byteCount = 2; 
            }
 
            return e;
        }
    }
} 

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