| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | using System; |
| | | 5 | | using System.Collections.Generic; |
| | | 6 | | using System.Xml; |
| | | 7 | | using CoreWCF.Channels; |
| | | 8 | | using CoreWCF.Runtime; |
| | | 9 | | |
| | | 10 | | namespace CoreWCF |
| | | 11 | | { |
| | | 12 | | internal class XmlBuffer |
| | | 13 | | { |
| | | 14 | | private readonly List<Section> _sections; |
| | | 15 | | private byte[] _buffer; |
| | | 16 | | private int _offset; |
| | | 17 | | private BufferedOutputStream _stream; |
| | | 18 | | private BufferState _bufferState; |
| | | 19 | | private XmlDictionaryWriter _writer; |
| | | 20 | | private XmlDictionaryReaderQuotas _quotas; |
| | | 21 | | |
| | | 22 | | private enum BufferState |
| | | 23 | | { |
| | | 24 | | Created, |
| | | 25 | | Writing, |
| | | 26 | | Reading, |
| | | 27 | | } |
| | | 28 | | |
| | | 29 | | private struct Section |
| | | 30 | | { |
| | | 31 | | public Section(int offset, int size, XmlDictionaryReaderQuotas quotas) |
| | | 32 | | { |
| | 18484 | 33 | | Offset = offset; |
| | 18484 | 34 | | Size = size; |
| | 18484 | 35 | | Quotas = quotas; |
| | 18484 | 36 | | } |
| | | 37 | | |
| | 38068 | 38 | | public int Offset { get; } |
| | | 39 | | |
| | 38068 | 40 | | public int Size { get; } |
| | | 41 | | |
| | 38068 | 42 | | public XmlDictionaryReaderQuotas Quotas { get; } |
| | | 43 | | } |
| | | 44 | | |
| | 3132 | 45 | | public XmlBuffer(int maxBufferSize) |
| | | 46 | | { |
| | 3132 | 47 | | if (maxBufferSize < 0) |
| | | 48 | | { |
| | 0 | 49 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException(nameof(maxBuff |
| | 0 | 50 | | SRCommon.ValueMustBeNonNegative)); |
| | | 51 | | } |
| | | 52 | | |
| | 3132 | 53 | | int initialBufferSize = Math.Min(512, maxBufferSize); |
| | 3132 | 54 | | _stream = new BufferManagerOutputStream(SRCommon.XmlBufferQuotaExceeded, initialBufferSize, maxBufferSize, |
| | 3132 | 55 | | BufferManager.CreateBufferManager(0, int.MaxValue)); |
| | 3132 | 56 | | _sections = new List<Section>(1); |
| | 3132 | 57 | | } |
| | | 58 | | |
| | | 59 | | public int BufferSize |
| | | 60 | | { |
| | | 61 | | get |
| | | 62 | | { |
| | | 63 | | Fx.Assert(_bufferState == BufferState.Reading, "Buffer size should only be retrieved during Reading stat |
| | 2937 | 64 | | return _buffer.Length; |
| | | 65 | | } |
| | | 66 | | } |
| | | 67 | | |
| | | 68 | | public int SectionCount |
| | | 69 | | { |
| | 18289 | 70 | | get { return _sections.Count; } |
| | | 71 | | } |
| | | 72 | | |
| | | 73 | | public XmlDictionaryWriter OpenSection(XmlDictionaryReaderQuotas quotas) |
| | | 74 | | { |
| | 18484 | 75 | | if (_bufferState != BufferState.Created) |
| | | 76 | | { |
| | 0 | 77 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException()); |
| | | 78 | | } |
| | | 79 | | |
| | 18484 | 80 | | _bufferState = BufferState.Writing; |
| | 18484 | 81 | | _quotas = new XmlDictionaryReaderQuotas(); |
| | 18484 | 82 | | quotas.CopyTo(_quotas); |
| | 18484 | 83 | | if (_writer != null) |
| | | 84 | | |
| | | 85 | | { |
| | | 86 | | // We always want to Dispose of the writer now; previously, writers could be reassigned |
| | | 87 | | |
| | | 88 | | // to a new stream, with a new dictionary and session. |
| | | 89 | | |
| | 0 | 90 | | XmlDictionaryWriter thisWriter = _writer; |
| | | 91 | | |
| | 0 | 92 | | thisWriter.Dispose(); |
| | | 93 | | |
| | 0 | 94 | | _writer = null; |
| | | 95 | | } |
| | | 96 | | |
| | 18484 | 97 | | _writer = XmlDictionaryWriter.CreateBinaryWriter(_stream, XD.Dictionary, null, true); |
| | 18484 | 98 | | return _writer; |
| | | 99 | | } |
| | | 100 | | |
| | | 101 | | public void CloseSection() |
| | | 102 | | { |
| | 18484 | 103 | | if (_bufferState != BufferState.Writing) |
| | | 104 | | { |
| | 0 | 105 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException()); |
| | | 106 | | } |
| | | 107 | | |
| | 18484 | 108 | | _writer.Dispose(); |
| | 18484 | 109 | | _writer = null; |
| | 18484 | 110 | | _bufferState = BufferState.Created; |
| | 18484 | 111 | | int size = (int)_stream.Length - _offset; |
| | 18484 | 112 | | _sections.Add(new Section(_offset, size, _quotas)); |
| | 18484 | 113 | | _offset += size; |
| | 18484 | 114 | | } |
| | | 115 | | |
| | | 116 | | public void Close() |
| | | 117 | | { |
| | 3132 | 118 | | if (_bufferState != BufferState.Created) |
| | | 119 | | { |
| | 0 | 120 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException()); |
| | | 121 | | } |
| | | 122 | | |
| | 3132 | 123 | | _bufferState = BufferState.Reading; |
| | 3132 | 124 | | _buffer = _stream.ToArray(out int bufferSize); |
| | 3132 | 125 | | _writer = null; |
| | 3132 | 126 | | _stream = null; |
| | 3132 | 127 | | } |
| | | 128 | | |
| | | 129 | | private Exception CreateInvalidStateException() |
| | | 130 | | { |
| | 0 | 131 | | return new InvalidOperationException(SR.XmlBufferInInvalidState); |
| | | 132 | | } |
| | | 133 | | |
| | | 134 | | public XmlDictionaryReader GetReader(int sectionIndex) |
| | | 135 | | { |
| | 38068 | 136 | | if (_bufferState != BufferState.Reading) |
| | | 137 | | { |
| | 0 | 138 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException()); |
| | | 139 | | } |
| | | 140 | | |
| | 38068 | 141 | | Section section = _sections[sectionIndex]; |
| | 38068 | 142 | | XmlDictionaryReader reader = XmlDictionaryReader.CreateBinaryReader(_buffer, section.Offset, section.Size, X |
| | 38068 | 143 | | reader.MoveToContent(); |
| | 38068 | 144 | | return reader; |
| | | 145 | | } |
| | | 146 | | |
| | | 147 | | public void WriteTo(int sectionIndex, XmlWriter writer) |
| | | 148 | | { |
| | 0 | 149 | | if (_bufferState != BufferState.Reading) |
| | | 150 | | { |
| | 0 | 151 | | throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(CreateInvalidStateException()); |
| | | 152 | | } |
| | | 153 | | |
| | 0 | 154 | | XmlDictionaryReader reader = GetReader(sectionIndex); |
| | | 155 | | try |
| | | 156 | | { |
| | 0 | 157 | | writer.WriteNode(reader, false); |
| | 0 | 158 | | } |
| | | 159 | | finally |
| | | 160 | | { |
| | 0 | 161 | | reader.Dispose(); |
| | 0 | 162 | | } |
| | 0 | 163 | | } |
| | | 164 | | } |
| | | 165 | | } |