File: System\ServiceModel\XmlBuffer.cs
Project: ndp\cdf\src\WCF\ServiceModel\System.ServiceModel.csproj (System.ServiceModel)
//------------------------------------------------------------
// Copyright (c) Microsoft Corporation.  All rights reserved.
//------------------------------------------------------------
#define BINARY
namespace System.ServiceModel
{
    using System.Collections.Generic;
    using System.Runtime;
    using System.ServiceModel.Channels;
    using System.Xml;
 
    class XmlBuffer
    {
        List<Section> sections;
        byte[] buffer;
        int offset;
        BufferedOutputStream stream;
        BufferState bufferState;
        XmlDictionaryWriter writer;
        XmlDictionaryReaderQuotas quotas;
 
        enum BufferState
        {
            Created,
            Writing,
            Reading,
        }
 
        struct Section
        {
            int offset;
            int size;
            XmlDictionaryReaderQuotas quotas;
 
            public Section(int offset, int size, XmlDictionaryReaderQuotas quotas)
            {
                this.offset = offset;
                this.size = size;
                this.quotas = quotas;
            }
 
            public int Offset
            {
                get { return this.offset; }
            }
 
            public int Size
            {
                get { return this.size; }
            }
 
            public XmlDictionaryReaderQuotas Quotas
            {
                get { return this.quotas; }
            }
        }
 
        public XmlBuffer(int maxBufferSize)
        {
            if (maxBufferSize < 0)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("maxBufferSize", maxBufferSize,
                                                    SR.GetString(SR.ValueMustBeNonNegative)));
            int initialBufferSize = Math.Min(512, maxBufferSize);
            stream = new BufferManagerOutputStream(SR.XmlBufferQuotaExceeded, initialBufferSize, maxBufferSize,
                BufferManager.CreateBufferManager(0, int.MaxValue));
            sections = new List<Section>(1);
        }
 
        public int BufferSize
        {
            get
            {
                Fx.Assert(bufferState == BufferState.Reading, "Buffer size shuold only be retrieved during Reading state");
                return buffer.Length;
            }
        }
 
        public int SectionCount
        {
            get { return this.sections.Count; }
        }
 
        public XmlDictionaryWriter OpenSection(XmlDictionaryReaderQuotas quotas)
        {
            if (bufferState != BufferState.Created)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException());
            bufferState = BufferState.Writing;
            this.quotas = new XmlDictionaryReaderQuotas();
            quotas.CopyTo(this.quotas);
            if (this.writer == null)
            {
                this.writer = XmlDictionaryWriter.CreateBinaryWriter(stream, XD.Dictionary, null, true);
            }
            else
            {
                ((IXmlBinaryWriterInitializer)this.writer).SetOutput(stream, XD.Dictionary, null, true);
            }
            return this.writer;
        }
 
        public void CloseSection()
        {
            if (bufferState != BufferState.Writing)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException());
            this.writer.Close();
            bufferState = BufferState.Created;
            int size = (int)stream.Length - offset;
            sections.Add(new Section(offset, size, this.quotas));
            offset += size;
        }
 
        public void Close()
        {
            if (bufferState != BufferState.Created)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException());
            bufferState = BufferState.Reading;
            int bufferSize;
            buffer = stream.ToArray(out bufferSize);
            writer = null;
            stream = null;
        }
 
        Exception CreateInvalidStateException()
        {
            return new InvalidOperationException(SR.GetString(SR.XmlBufferInInvalidState));
        }
 
        public XmlDictionaryReader GetReader(int sectionIndex)
        {
            if (bufferState != BufferState.Reading)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException());
            Section section = sections[sectionIndex];
            XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(buffer, section.Offset, section.Size, XD.Dictionary, section.Quotas, null, null);
            reader.MoveToContent();
            return reader;
        }
 
        public void WriteTo(int sectionIndex, XmlWriter writer)
        {
            if (bufferState != BufferState.Reading)
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException());
            XmlDictionaryReader reader = GetReader(sectionIndex);
            try
            {
                writer.WriteNode(reader, false);
            }
            finally
            {
                reader.Close();
            }
        }
    }
}