XmlStreamNodeWriter.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 / XmlStreamNodeWriter.cs / 1305376 / XmlStreamNodeWriter.cs

                            //------------------------------------------------------------ 
// Copyright (c) Microsoft Corporation.  All rights reserved.
//-----------------------------------------------------------
namespace System.Xml
{ 
    using System.IO;
    using System.Runtime; 
    using System.Runtime.Serialization; 
    using System.Security;
    using System.Text; 

    abstract class XmlStreamNodeWriter : XmlNodeWriter
    {
        Stream stream; 
        byte[] buffer;
        int offset; 
        bool ownsStream; 
        const int bufferLength = 512;
        const int maxEntityLength = 32; 
        const int maxBytesPerChar = 3;
        Encoding encoding;
        static UTF8Encoding UTF8Encoding = new UTF8Encoding(false, true);
 
        protected XmlStreamNodeWriter()
        { 
            this.buffer = new byte[bufferLength]; 
            encoding = XmlStreamNodeWriter.UTF8Encoding;
        } 

        protected void SetOutput(Stream stream, bool ownsStream, Encoding encoding)
        {
            this.stream = stream; 
            this.ownsStream = ownsStream;
            this.offset = 0; 
 
            if (encoding != null)
            { 
                this.encoding = encoding;
            }
        }
 
        // Getting/Setting the Stream exists for fragmenting
        public Stream Stream 
        { 
            get
            { 
                return stream;
            }
            set
            { 
                stream = value;
            } 
        } 

        // StreamBuffer/BufferOffset exists only for the BinaryWriter to fix up nodes 
        public byte[] StreamBuffer
        {
            get
            { 
                return buffer;
            } 
        } 
        public int BufferOffset
        { 
            get
            {
                return offset;
            } 
        }
 
        public int Position 
        {
            get 
            {
                return (int)stream.Position + offset;
            }
        } 

        protected byte[] GetBuffer(int count, out int offset) 
        { 
            Fx.Assert(count >= 0 && count <= bufferLength, "");
            int bufferOffset = this.offset; 
            if (bufferOffset + count <= bufferLength)
            {
                offset = bufferOffset;
            } 
            else
            { 
                FlushBuffer(); 
                offset = 0;
            } 
#if DEBUG
            Fx.Assert(offset + count <= bufferLength, "");
            for (int i = 0; i < count; i++)
            { 
                buffer[offset + i] = (byte)'<';
            } 
#endif 
            return buffer;
        } 

        protected void Advance(int count)
        {
            Fx.Assert(offset + count <= bufferLength, ""); 
            offset += count;
        } 
 
        void EnsureByte()
        { 
            if (offset >= bufferLength)
            {
                FlushBuffer();
            } 
        }
 
        protected void WriteByte(byte b) 
        {
            EnsureByte(); 
            buffer[offset++] = b;
        }

        protected void WriteByte(char ch) 
        {
            Fx.Assert(ch < 0x80, ""); 
            WriteByte((byte)ch); 
        }
 
        protected void WriteBytes(byte b1, byte b2)
        {
            byte[] buffer = this.buffer;
            int offset = this.offset; 
            if (offset + 1 >= bufferLength)
            { 
                FlushBuffer(); 
                offset = 0;
            } 
            buffer[offset + 0] = b1;
            buffer[offset + 1] = b2;
            this.offset += 2;
        } 

        protected void WriteBytes(char ch1, char ch2) 
        { 
            Fx.Assert(ch1 < 0x80 && ch2 < 0x80, "");
            WriteBytes((byte)ch1, (byte)ch2); 
        }

        public void WriteBytes(byte[] byteBuffer, int byteOffset, int byteCount)
        { 
            if (byteCount < bufferLength)
            { 
                int offset; 
                byte[] buffer = GetBuffer(byteCount, out offset);
                Buffer.BlockCopy(byteBuffer, byteOffset, buffer, offset, byteCount); 
                Advance(byteCount);
            }
            else
            { 
                FlushBuffer();
                stream.Write(byteBuffer, byteOffset, byteCount); 
            } 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")]
        [SecurityCritical]
        unsafe protected void UnsafeWriteBytes(byte* bytes, int byteCount)
        { 
            FlushBuffer();
            byte[] buffer = this.buffer; 
            while (byteCount >= bufferLength) 
            {
                for (int i = 0; i < bufferLength; i++) 
                    buffer[i] = bytes[i];
                stream.Write(buffer, 0, bufferLength);
                bytes += bufferLength;
                byteCount -= bufferLength; 
            }
            { 
                for (int i = 0; i < byteCount; i++) 
                    buffer[i] = bytes[i];
                stream.Write(buffer, 0, byteCount); 
            }
        }

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical] 
        unsafe protected void WriteUTF8Char(int ch) 
        {
            if (ch < 0x80) 
            {
                WriteByte((byte)ch);
            }
            else if (ch <= char.MaxValue) 
            {
                char* chars = stackalloc char[1]; 
                chars[0] = (char)ch; 
                UnsafeWriteUTF8Chars(chars, 1);
            } 
            else
            {
                SurrogateChar surrogateChar = new SurrogateChar(ch);
                char* chars = stackalloc char[2]; 
                chars[0] = surrogateChar.HighChar;
                chars[1] = surrogateChar.LowChar; 
                UnsafeWriteUTF8Chars(chars, 2); 
            }
        } 

        protected void WriteUTF8Chars(byte[] chars, int charOffset, int charCount)
        {
            if (charCount < bufferLength) 
            {
                int offset; 
                byte[] buffer = GetBuffer(charCount, out offset); 
                Buffer.BlockCopy(chars, charOffset, buffer, offset, charCount);
                Advance(charCount); 
            }
            else
            {
                FlushBuffer(); 
                stream.Write(chars, charOffset, charCount);
            } 
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code.", 
            Safe = "Unsafe code is effectively encapsulated, all inputs are validated.")]
        [SecuritySafeCritical]
        unsafe protected void WriteUTF8Chars(string value)
        { 
            int count = value.Length;
            if (count > 0) 
            { 
                fixed (char* chars = value)
                { 
                    UnsafeWriteUTF8Chars(chars, count);
                }
            }
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 
        [SecurityCritical] 
        unsafe protected void UnsafeWriteUTF8Chars(char* chars, int charCount)
        { 
            const int charChunkSize = bufferLength / maxBytesPerChar;
            while (charCount > charChunkSize)
            {
                int offset; 
                int chunkSize = charChunkSize;
                if ((int)(chars[chunkSize - 1] & 0xFC00) == 0xD800) // This is a high surrogate 
                    chunkSize--; 
                byte[] buffer = GetBuffer(chunkSize * maxBytesPerChar, out offset);
                Advance(UnsafeGetUTF8Chars(chars, chunkSize, buffer, offset)); 
                charCount -= chunkSize;
                chars += chunkSize;
            }
            if (charCount > 0) 
            {
                int offset; 
                byte[] buffer = GetBuffer(charCount * maxBytesPerChar, out offset); 
                Advance(UnsafeGetUTF8Chars(chars, charCount, buffer, offset));
            } 
        }

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")]
        [SecurityCritical] 
        unsafe protected void UnsafeWriteUnicodeChars(char* chars, int charCount)
        { 
            const int charChunkSize = bufferLength / 2; 
            while (charCount > charChunkSize)
            { 
                int offset;
                int chunkSize = charChunkSize;
                if ((int)(chars[chunkSize - 1] & 0xFC00) == 0xD800) // This is a high surrogate
                    chunkSize--; 
                byte[] buffer = GetBuffer(chunkSize * 2, out offset);
                Advance(UnsafeGetUnicodeChars(chars, chunkSize, buffer, offset)); 
                charCount -= chunkSize; 
                chars += chunkSize;
            } 
            if (charCount > 0)
            {
                int offset;
                byte[] buffer = GetBuffer(charCount * 2, out offset); 
                Advance(UnsafeGetUnicodeChars(chars, charCount, buffer, offset));
            } 
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 
        [SecurityCritical]
        unsafe protected int UnsafeGetUnicodeChars(char* chars, int charCount, byte[] buffer, int offset)
        {
            char* charsMax = chars + charCount; 
            while (chars < charsMax)
            { 
                char value = *chars++; 
                buffer[offset++] = (byte)value;
                value >>= 8; 
                buffer[offset++] = (byte)value;
            }
            return charCount * 2;
        } 

        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 
        [SecurityCritical] 
        unsafe protected int UnsafeGetUTF8Length(char* chars, int charCount)
        { 
            char* charsMax = chars + charCount;
            while (chars < charsMax)
            {
                if (*chars >= 0x80) 
                    break;
 
                chars++; 
            }
 
            if (chars == charsMax)
                return charCount;

            return (int)(chars - (charsMax - charCount)) + encoding.GetByteCount(chars, (int)(charsMax - chars)); 
        }
 
        [Fx.Tag.SecurityNote(Critical = "Contains unsafe code. Caller needs to validate arguments.")] 
        [SecurityCritical]
        unsafe protected int UnsafeGetUTF8Chars(char* chars, int charCount, byte[] buffer, int offset) 
        {
            if (charCount > 0)
            {
                fixed (byte* _bytes = &buffer[offset]) 
                {
                    byte* bytes = _bytes; 
                    byte* bytesMax = &bytes[buffer.Length - offset]; 
                    char* charsMax = &chars[charCount];
 
                    while (true)
                    {
                        while (chars < charsMax && *chars < 0x80)
                        { 
                            *bytes = (byte)*chars;
                            bytes++; 
                            chars++; 
                        }
 
                        if (chars >= charsMax)
                            break;

                        char* charsStart = chars; 
                        while (chars < charsMax && *chars >= 0x80)
                        { 
                            chars++; 
                        }
 
                        bytes += encoding.GetBytes(charsStart, (int)(chars - charsStart), bytes, (int)(bytesMax - bytes));

                        if (chars >= charsMax)
                            break; 
                    }
 
                    return (int)(bytes - _bytes); 
                }
            } 
            return 0;
        }

        protected virtual void FlushBuffer() 
        {
            if (offset != 0) 
            { 
                stream.Write(buffer, 0, offset);
                offset = 0; 
            }
        }

        public override void Flush() 
        {
            FlushBuffer(); 
            stream.Flush(); 
        }
 
        public override void Close()
        {
            if (stream != null)
            { 
                if (ownsStream)
                { 
                    stream.Close(); 
                }
                stream = null; 
            }
        }
    }
} 

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