//------------------------------------------------------------ // Copyright (c) Microsoft Corporation. All rights reserved. //------------------------------------------------------------ namespace System.Xml { using System; using System.IO; using System.Xml; using System.Collections; using System.Diagnostics; using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Security; using System.Threading; using System.Threading.Tasks; using System.Text; using System.Runtime; public abstract class XmlDictionaryWriter : XmlWriter { // Derived classes that implements WriteBase64Async should override // this flag to true so that the base XmlDictionaryWriter would use the // faster WriteBase64Async APIs instead of the default BeginWrite() implementation. internal virtual bool FastAsync { get { return false; } } internal virtual AsyncCompletionResult WriteBase64Async(AsyncEventArgs state) { throw FxTrace.Exception.AsError(new NotSupportedException()); } public override Task WriteBase64Async(byte[] buffer, int index, int count) { return Task.Factory.FromAsync(this.BeginWriteBase64, this.EndWriteBase64, buffer, index, count, null); } internal virtual IAsyncResult BeginWriteBase64(byte[] buffer, int index, int count, AsyncCallback callback, object state) { return new WriteBase64AsyncResult(buffer, index, count, this, callback, state); } internal virtual void EndWriteBase64(IAsyncResult result) { WriteBase64AsyncResult.End(result); } static public XmlDictionaryWriter CreateBinaryWriter(Stream stream) { return CreateBinaryWriter(stream, null); } static public XmlDictionaryWriter CreateBinaryWriter(Stream stream, IXmlDictionary dictionary) { return CreateBinaryWriter(stream, dictionary, null); } static public XmlDictionaryWriter CreateBinaryWriter(Stream stream, IXmlDictionary dictionary, XmlBinaryWriterSession session) { return CreateBinaryWriter(stream, dictionary, session, true); } static public XmlDictionaryWriter CreateBinaryWriter(Stream stream, IXmlDictionary dictionary, XmlBinaryWriterSession session, bool ownsStream) { XmlBinaryWriter writer = new XmlBinaryWriter(); writer.SetOutput(stream, dictionary, session, ownsStream); return writer; } static public XmlDictionaryWriter CreateTextWriter(Stream stream) { return CreateTextWriter(stream, Encoding.UTF8, true); } static public XmlDictionaryWriter CreateTextWriter(Stream stream, Encoding encoding) { return CreateTextWriter(stream, encoding, true); } static public XmlDictionaryWriter CreateTextWriter(Stream stream, Encoding encoding, bool ownsStream) { XmlUTF8TextWriter writer = new XmlUTF8TextWriter(); writer.SetOutput(stream, encoding, ownsStream); return writer; } static public XmlDictionaryWriter CreateMtomWriter(Stream stream, Encoding encoding, int maxSizeInBytes, string startInfo) { return CreateMtomWriter(stream, encoding, maxSizeInBytes, startInfo, null, null, true, true); } static public XmlDictionaryWriter CreateMtomWriter(Stream stream, Encoding encoding, int maxSizeInBytes, string startInfo, string boundary, string startUri, bool writeMessageHeaders, bool ownsStream) { XmlMtomWriter writer = new XmlMtomWriter(); writer.SetOutput(stream, encoding, maxSizeInBytes, startInfo, boundary, startUri, writeMessageHeaders, ownsStream); return writer; } static public XmlDictionaryWriter CreateDictionaryWriter(XmlWriter writer) { if (writer == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("writer"); XmlDictionaryWriter dictionaryWriter = writer as XmlDictionaryWriter; if (dictionaryWriter == null) { dictionaryWriter = new XmlWrappedWriter(writer); } return dictionaryWriter; } public void WriteStartElement(XmlDictionaryString localName, XmlDictionaryString namespaceUri) { WriteStartElement((string)null, localName, namespaceUri); } public virtual void WriteStartElement(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri) { WriteStartElement(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri)); } public void WriteStartAttribute(XmlDictionaryString localName, XmlDictionaryString namespaceUri) { WriteStartAttribute((string)null, localName, namespaceUri); } public virtual void WriteStartAttribute(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri) { WriteStartAttribute(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri)); } public void WriteAttributeString(XmlDictionaryString localName, XmlDictionaryString namespaceUri, string value) { WriteAttributeString((string)null, localName, namespaceUri, value); } public virtual void WriteXmlnsAttribute(string prefix, string namespaceUri) { if (namespaceUri == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); if (prefix == null) { if (LookupPrefix(namespaceUri) != null) return; #pragma warning suppress 56506 // Microsoft, namespaceUri is already checked prefix = namespaceUri.Length == 0 ? string.Empty : string.Concat("d", namespaceUri.Length.ToString(System.Globalization.NumberFormatInfo.InvariantInfo)); } WriteAttributeString("xmlns", prefix, null, namespaceUri); } public virtual void WriteXmlnsAttribute(string prefix, XmlDictionaryString namespaceUri) { WriteXmlnsAttribute(prefix, XmlDictionaryString.GetString(namespaceUri)); } public virtual void WriteXmlAttribute(string localName, string value) { WriteAttributeString("xml", localName, null, value); } public virtual void WriteXmlAttribute(XmlDictionaryString localName, XmlDictionaryString value) { WriteXmlAttribute(XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(value)); } public void WriteAttributeString(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, string value) { WriteStartAttribute(prefix, localName, namespaceUri); WriteString(value); WriteEndAttribute(); } public void WriteElementString(XmlDictionaryString localName, XmlDictionaryString namespaceUri, string value) { WriteElementString((string)null, localName, namespaceUri, value); } public void WriteElementString(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, string value) { WriteStartElement(prefix, localName, namespaceUri); WriteString(value); WriteEndElement(); } public virtual void WriteString(XmlDictionaryString value) { WriteString(XmlDictionaryString.GetString(value)); } public virtual void WriteQualifiedName(XmlDictionaryString localName, XmlDictionaryString namespaceUri) { if (localName == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("localName")); if (namespaceUri == null) namespaceUri = XmlDictionaryString.Empty; #pragma warning suppress 56506 // Microsoft, XmlDictionaryString.Empty is never null WriteQualifiedName(localName.Value, namespaceUri.Value); } public virtual void WriteValue(XmlDictionaryString value) { WriteValue(XmlDictionaryString.GetString(value)); } public virtual void WriteValue(IStreamProvider value) { if (value == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); Stream stream = value.GetStream(); if (stream == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.XmlInvalidStream))); int blockSize = 256; int bytesRead = 0; byte[] block = new byte[blockSize]; while (true) { bytesRead = stream.Read(block, 0, blockSize); if (bytesRead > 0) WriteBase64(block, 0, bytesRead); else break; if (blockSize < 65536 && bytesRead == blockSize) { blockSize = blockSize * 16; block = new byte[blockSize]; } } value.ReleaseStream(stream); } public virtual Task WriteValueAsync(IStreamProvider value) { return Task.Factory.FromAsync(this.BeginWriteValue, this.EndWriteValue, value, null); } internal virtual IAsyncResult BeginWriteValue(IStreamProvider value, AsyncCallback callback, object state) { if (value == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("value")); if (this.FastAsync) { return new WriteValueFastAsyncResult(this, value, callback, state); } else { return new WriteValueAsyncResult(this, value, callback, state); } } internal virtual void EndWriteValue(IAsyncResult result) { if (this.FastAsync) { WriteValueFastAsyncResult.End(result); } else { WriteValueAsyncResult.End(result); } } class WriteValueFastAsyncResult : AsyncResult { bool completed; int blockSize; byte[] block; int bytesRead; Stream stream; Operation nextOperation; IStreamProvider streamProvider; XmlDictionaryWriter writer; AsyncEventArgs writerAsyncState; XmlWriteBase64AsyncArguments writerAsyncArgs; static AsyncCallback onReadComplete = Fx.ThunkCallback(OnReadComplete); static AsyncEventArgsCallback onWriteComplete; public WriteValueFastAsyncResult(XmlDictionaryWriter writer, IStreamProvider value, AsyncCallback callback, object state) : base(callback, state) { this.streamProvider = value; this.writer = writer; this.stream = value.GetStream(); if (this.stream == null) { throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.XmlInvalidStream))); } this.blockSize = 256; this.bytesRead = 0; this.block = new byte[this.blockSize]; this.nextOperation = Operation.Read; this.ContinueWork(true); } void CompleteAndReleaseStream(bool completedSynchronously, Exception completionException = null) { if (completionException == null) { // only release stream when no exception (mirrors sync behaviour) this.streamProvider.ReleaseStream(this.stream); this.stream = null; } this.Complete(completedSynchronously, completionException); } void ContinueWork(bool completedSynchronously, Exception completionException = null) { // Individual Reads or writes may complete sync or async. A callback however // will always all ContinueWork() with CompletedSynchronously=false this flag // is used to complete this AsyncResult. try { while (true) { if (this.nextOperation == Operation.Read) { if (ReadAsync() != AsyncCompletionResult.Completed) { return; } } else if (this.nextOperation == Operation.Write) { if (WriteAsync() != AsyncCompletionResult.Completed) { return; } } else if (this.nextOperation == Operation.Complete) { break; } } } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } if (completedSynchronously) { throw; } if (completionException == null) { completionException = ex; } } if (!completed) { this.completed = true; this.CompleteAndReleaseStream(completedSynchronously, completionException); } } AsyncCompletionResult ReadAsync() { IAsyncResult result = this.stream.BeginRead(this.block, 0, blockSize, onReadComplete, this); if (result.CompletedSynchronously) { this.HandleReadComplete(result); return AsyncCompletionResult.Completed; } return AsyncCompletionResult.Queued; } void HandleReadComplete(IAsyncResult result) { this.bytesRead = this.stream.EndRead(result); if (this.bytesRead > 0) { this.nextOperation = Operation.Write; } else { this.nextOperation = Operation.Complete; } } static void OnReadComplete(IAsyncResult result) { if (result.CompletedSynchronously) { return; } Exception completionException = null; WriteValueFastAsyncResult thisPtr = (WriteValueFastAsyncResult)result.AsyncState; bool sucess = false; try { thisPtr.HandleReadComplete(result); sucess = true; } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } completionException = ex; } if (!sucess) { thisPtr.nextOperation = Operation.Complete; } thisPtr.ContinueWork(false, completionException); } AsyncCompletionResult WriteAsync() { if (this.writerAsyncState == null) { this.writerAsyncArgs = new XmlWriteBase64AsyncArguments(); this.writerAsyncState = new AsyncEventArgs(); } if (onWriteComplete == null) { onWriteComplete = new AsyncEventArgsCallback(OnWriteComplete); } this.writerAsyncArgs.Buffer = this.block; this.writerAsyncArgs.Offset = 0; this.writerAsyncArgs.Count = this.bytesRead; this.writerAsyncState.Set(onWriteComplete, this.writerAsyncArgs, this); if (this.writer.WriteBase64Async(this.writerAsyncState) == AsyncCompletionResult.Completed) { this.HandleWriteComplete(); this.writerAsyncState.Complete(true); return AsyncCompletionResult.Completed; } return AsyncCompletionResult.Queued; } void HandleWriteComplete() { this.nextOperation = Operation.Read; // Adjust block size for next read if (this.blockSize < 65536 && this.bytesRead == this.blockSize) { this.blockSize = this.blockSize * 16; this.block = new byte[this.blockSize]; } } static void OnWriteComplete(IAsyncEventArgs asyncState) { WriteValueFastAsyncResult thisPtr = (WriteValueFastAsyncResult)asyncState.AsyncState; Exception completionException = null; bool success = false; try { if (asyncState.Exception != null) { completionException = asyncState.Exception; } else { thisPtr.HandleWriteComplete(); success = true; } } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } completionException = ex; } if (!success) { thisPtr.nextOperation = Operation.Complete; } thisPtr.ContinueWork(false, completionException); } internal static void End(IAsyncResult result) { AsyncResult.End(result); } enum Operation { Read, Write, Complete } } class WriteValueAsyncResult : AsyncResult { enum Operation { Read, Write } int blockSize; byte[] block; int bytesRead; Stream stream; Operation operation = Operation.Read; IStreamProvider streamProvider; XmlDictionaryWriter writer; Func writeBlockHandler; static Func handleWriteBlock = HandleWriteBlock; static Func handleWriteBlockAsync = HandleWriteBlockAsync; static AsyncCallback onContinueWork = Fx.ThunkCallback(OnContinueWork); public WriteValueAsyncResult(XmlDictionaryWriter writer, IStreamProvider value, AsyncCallback callback, object state) : base(callback, state) { this.streamProvider = value; this.writer = writer; this.writeBlockHandler = this.writer.Settings != null && this.writer.Settings.Async ? handleWriteBlockAsync : handleWriteBlock; this.stream = value.GetStream(); if (this.stream == null) { throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new XmlException(SR.GetString(SR.XmlInvalidStream))); } this.blockSize = 256; this.bytesRead = 0; this.block = new byte[blockSize]; // bool completeSelf = ContinueWork(null); if (completeSelf) { this.CompleteAndReleaseStream(true, null); } } void AdjustBlockSize() { if (this.blockSize < 65536 && this.bytesRead == this.blockSize) { this.blockSize = this.blockSize * 16; this.block = new byte[this.blockSize]; } } void CompleteAndReleaseStream(bool completedSynchronously, Exception completionException) { if (completionException == null) { // only release stream when no exception (mirrors sync behaviour) this.streamProvider.ReleaseStream(this.stream); this.stream = null; } this.Complete(completedSynchronously, completionException); } //returns whether or not the entire operation is completed bool ContinueWork(IAsyncResult result) { while (true) { if (this.operation == Operation.Read) { if (HandleReadBlock(result)) { // Read completed (sync or async, doesn't matter) if (this.bytesRead > 0) { // allow loop to continue at Write operation = Operation.Write; } else { // Exit loop, entire source stream has been read. return true; } } else { // Read completed async, jump out of loop, callback resumes at writing. return false; } } else { if (this.writeBlockHandler(result, this)) { // Write completed (sync or async, doesn't matter) AdjustBlockSize(); operation = Operation.Read; } else { // Write completed async, jump out of loop, callback should resume at reading return false; } } result = null; } } //returns whether or not I completed. bool HandleReadBlock(IAsyncResult result) { if (result == null) { result = this.stream.BeginRead(this.block, 0, blockSize, onContinueWork, this); if (!result.CompletedSynchronously) { return false; } } this.bytesRead = this.stream.EndRead(result); return true; } //returns whether or not I completed. static bool HandleWriteBlock(IAsyncResult result, WriteValueAsyncResult thisPtr) { if (result == null) { result = thisPtr.writer.BeginWriteBase64(thisPtr.block, 0, thisPtr.bytesRead, onContinueWork, thisPtr); if (!result.CompletedSynchronously) { return false; } } thisPtr.writer.EndWriteBase64(result); return true; } //returns whether or not I completed. static bool HandleWriteBlockAsync(IAsyncResult result, WriteValueAsyncResult thisPtr) { Task task = (Task)result; if (task == null) { task = thisPtr.writer.WriteBase64Async(thisPtr.block, 0, thisPtr.bytesRead); task.AsAsyncResult(onContinueWork, thisPtr); return false; } task.GetAwaiter().GetResult(); return true; } static void OnContinueWork(IAsyncResult result) { // If result is a Task we shouldn't check for Synchronous completion // We should only return if we're in the async completion path and if the result completed synchronously. if (result.CompletedSynchronously && !(result is Task)) { return; } Exception completionException = null; WriteValueAsyncResult thisPtr = (WriteValueAsyncResult)result.AsyncState; bool completeSelf = false; try { completeSelf = thisPtr.ContinueWork(result); } catch (Exception ex) { if (Fx.IsFatal(ex)) { throw; } completeSelf = true; completionException = ex; } if (completeSelf) { thisPtr.CompleteAndReleaseStream(false, completionException); } } public static void End(IAsyncResult result) { AsyncResult.End(result); } } public virtual void WriteValue(UniqueId value) { if (value == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("value"); WriteString(value.ToString()); } public virtual void WriteValue(Guid value) { WriteString(value.ToString()); } public virtual void WriteValue(TimeSpan value) { WriteString(XmlConvert.ToString(value)); } public virtual bool CanCanonicalize { get { return false; } } public virtual void StartCanonicalization(Stream stream, bool includeComments, string[] inclusivePrefixes) { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } public virtual void EndCanonicalization() { throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new NotSupportedException()); } void WriteElementNode(XmlDictionaryReader reader, bool defattr) { XmlDictionaryString localName; XmlDictionaryString namespaceUri; if (reader.TryGetLocalNameAsDictionaryString(out localName) && reader.TryGetNamespaceUriAsDictionaryString(out namespaceUri)) { WriteStartElement(reader.Prefix, localName, namespaceUri); } else { WriteStartElement(reader.Prefix, reader.LocalName, reader.NamespaceURI); } if (defattr || (!reader.IsDefault && (reader.SchemaInfo == null || !reader.SchemaInfo.IsDefault))) { if (reader.MoveToFirstAttribute()) { do { if (reader.TryGetLocalNameAsDictionaryString(out localName) && reader.TryGetNamespaceUriAsDictionaryString(out namespaceUri)) { WriteStartAttribute(reader.Prefix, localName, namespaceUri); } else { WriteStartAttribute(reader.Prefix, reader.LocalName, reader.NamespaceURI); } while (reader.ReadAttributeValue()) { if (reader.NodeType == XmlNodeType.EntityReference) { WriteEntityRef(reader.Name); } else { WriteTextNode(reader, true); } } WriteEndAttribute(); } while (reader.MoveToNextAttribute()); reader.MoveToElement(); } } if (reader.IsEmptyElement) { WriteEndElement(); } } void WriteArrayNode(XmlDictionaryReader reader, string prefix, string localName, string namespaceUri, Type type) { if (type == typeof(bool)) BooleanArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Int16)) Int16ArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Int32)) Int32ArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Int64)) Int64ArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(float)) SingleArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(double)) DoubleArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(decimal)) DecimalArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(DateTime)) DateTimeArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Guid)) GuidArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(TimeSpan)) TimeSpanArrayHelperWithString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else { WriteElementNode(reader, false); reader.Read(); } } void WriteArrayNode(XmlDictionaryReader reader, string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Type type) { if (type == typeof(bool)) BooleanArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Int16)) Int16ArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Int32)) Int32ArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Int64)) Int64ArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(float)) SingleArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(double)) DoubleArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(decimal)) DecimalArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(DateTime)) DateTimeArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(Guid)) GuidArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else if (type == typeof(TimeSpan)) TimeSpanArrayHelperWithDictionaryString.Instance.WriteArray(this, prefix, localName, namespaceUri, reader); else { WriteElementNode(reader, false); reader.Read(); } } void WriteArrayNode(XmlDictionaryReader reader, Type type) { XmlDictionaryString localName; XmlDictionaryString namespaceUri; if (reader.TryGetLocalNameAsDictionaryString(out localName) && reader.TryGetNamespaceUriAsDictionaryString(out namespaceUri)) WriteArrayNode(reader, reader.Prefix, localName, namespaceUri, type); else WriteArrayNode(reader, reader.Prefix, reader.LocalName, reader.NamespaceURI, type); } protected virtual void WriteTextNode(XmlDictionaryReader reader, bool isAttribute) { XmlDictionaryString value; if (reader.TryGetValueAsDictionaryString(out value)) { WriteString(value); } else { WriteString(reader.Value); } if (!isAttribute) { reader.Read(); } } public override void WriteNode(XmlReader reader, bool defattr) { XmlDictionaryReader dictionaryReader = reader as XmlDictionaryReader; if (dictionaryReader != null) WriteNode(dictionaryReader, defattr); else base.WriteNode(reader, defattr); } public virtual void WriteNode(XmlDictionaryReader reader, bool defattr) { if (reader == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("reader")); int d = (reader.NodeType == XmlNodeType.None ? -1 : reader.Depth); do { XmlNodeType nodeType = reader.NodeType; Type type; if (nodeType == XmlNodeType.Text || nodeType == XmlNodeType.Whitespace || nodeType == XmlNodeType.SignificantWhitespace) { // This will advance if necessary, so we don't need to call Read() explicitly WriteTextNode(reader, false); } else if (reader.Depth > d && reader.IsStartArray(out type)) { WriteArrayNode(reader, type); } else { // These will not advance, so we must call Read() explicitly switch (nodeType) { case XmlNodeType.Element: WriteElementNode(reader, defattr); break; case XmlNodeType.CDATA: WriteCData(reader.Value); break; case XmlNodeType.EntityReference: WriteEntityRef(reader.Name); break; case XmlNodeType.XmlDeclaration: case XmlNodeType.ProcessingInstruction: WriteProcessingInstruction(reader.Name, reader.Value); break; case XmlNodeType.DocumentType: WriteDocType(reader.Name, reader.GetAttribute("PUBLIC"), reader.GetAttribute("SYSTEM"), reader.Value); break; case XmlNodeType.Comment: WriteComment(reader.Value); break; case XmlNodeType.EndElement: WriteFullEndElement(); break; } if (!reader.Read()) break; } } while (d < reader.Depth || (d == reader.Depth && reader.NodeType == XmlNodeType.EndElement)); } void CheckArray(Array array, int offset, int count) { if (array == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentNullException("array")); if (offset < 0) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.ValueMustBeNonNegative))); if (offset > array.Length) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("offset", SR.GetString(SR.OffsetExceedsBufferSize, array.Length))); if (count < 0) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.ValueMustBeNonNegative))); if (count > array.Length - offset) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentOutOfRangeException("count", SR.GetString(SR.SizeExceedsRemainingBufferSpace, array.Length - offset))); } // bool public virtual void WriteArray(string prefix, string localName, string namespaceUri, bool[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, bool[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // Int16 public virtual void WriteArray(string prefix, string localName, string namespaceUri, Int16[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int16[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // Int32 public virtual void WriteArray(string prefix, string localName, string namespaceUri, Int32[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int32[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // Int64 public virtual void WriteArray(string prefix, string localName, string namespaceUri, Int64[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Int64[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // float public virtual void WriteArray(string prefix, string localName, string namespaceUri, float[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, float[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // double public virtual void WriteArray(string prefix, string localName, string namespaceUri, double[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, double[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // decimal public virtual void WriteArray(string prefix, string localName, string namespaceUri, decimal[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, decimal[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // DateTime public virtual void WriteArray(string prefix, string localName, string namespaceUri, DateTime[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, DateTime[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // Guid public virtual void WriteArray(string prefix, string localName, string namespaceUri, Guid[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, Guid[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } // TimeSpan public virtual void WriteArray(string prefix, string localName, string namespaceUri, TimeSpan[] array, int offset, int count) { CheckArray(array, offset, count); for (int i = 0; i < count; i++) { WriteStartElement(prefix, localName, namespaceUri); WriteValue(array[offset + i]); WriteEndElement(); } } public virtual void WriteArray(string prefix, XmlDictionaryString localName, XmlDictionaryString namespaceUri, TimeSpan[] array, int offset, int count) { WriteArray(prefix, XmlDictionaryString.GetString(localName), XmlDictionaryString.GetString(namespaceUri), array, offset, count); } class WriteBase64AsyncResult : ScheduleActionItemAsyncResult { byte[] buffer; int index; int count; XmlDictionaryWriter writer; public WriteBase64AsyncResult(byte[] buffer, int index, int count, XmlDictionaryWriter writer, AsyncCallback callback, object state) : base(callback, state) { Fx.Assert(writer != null, "writer should never be null"); this.buffer = buffer; this.index = index; this.count = count; this.writer = writer; Schedule(); } protected override void OnDoWork() { this.writer.WriteBase64(this.buffer, this.index, this.count); } } class XmlWrappedWriter : XmlDictionaryWriter { XmlWriter writer; int depth; int prefix; public XmlWrappedWriter(XmlWriter writer) { this.writer = writer; this.depth = 0; } public override void Close() { writer.Close(); } public override void Flush() { writer.Flush(); } public override string LookupPrefix(string namespaceUri) { return writer.LookupPrefix(namespaceUri); } public override void WriteAttributes(XmlReader reader, bool defattr) { writer.WriteAttributes(reader, defattr); } public override void WriteBase64(byte[] buffer, int index, int count) { writer.WriteBase64(buffer, index, count); } public override void WriteBinHex(byte[] buffer, int index, int count) { writer.WriteBinHex(buffer, index, count); } public override void WriteCData(string text) { writer.WriteCData(text); } public override void WriteCharEntity(char ch) { writer.WriteCharEntity(ch); } public override void WriteChars(char[] buffer, int index, int count) { writer.WriteChars(buffer, index, count); } public override void WriteComment(string text) { writer.WriteComment(text); } public override void WriteDocType(string name, string pubid, string sysid, string subset) { writer.WriteDocType(name, pubid, sysid, subset); } public override void WriteEndAttribute() { writer.WriteEndAttribute(); } public override void WriteEndDocument() { writer.WriteEndDocument(); } public override void WriteEndElement() { writer.WriteEndElement(); this.depth--; } public override void WriteEntityRef(string name) { writer.WriteEntityRef(name); } public override void WriteFullEndElement() { writer.WriteFullEndElement(); } public override void WriteName(string name) { writer.WriteName(name); } public override void WriteNmToken(string name) { writer.WriteNmToken(name); } public override void WriteNode(XmlReader reader, bool defattr) { writer.WriteNode(reader, defattr); } public override void WriteProcessingInstruction(string name, string text) { writer.WriteProcessingInstruction(name, text); } public override void WriteQualifiedName(string localName, string namespaceUri) { writer.WriteQualifiedName(localName, namespaceUri); } public override void WriteRaw(char[] buffer, int index, int count) { writer.WriteRaw(buffer, index, count); } public override void WriteRaw(string data) { writer.WriteRaw(data); } public override void WriteStartAttribute(string prefix, string localName, string namespaceUri) { writer.WriteStartAttribute(prefix, localName, namespaceUri); this.prefix++; } public override void WriteStartDocument() { writer.WriteStartDocument(); } public override void WriteStartDocument(bool standalone) { writer.WriteStartDocument(standalone); } public override void WriteStartElement(string prefix, string localName, string namespaceUri) { writer.WriteStartElement(prefix, localName, namespaceUri); this.depth++; this.prefix = 1; } public override WriteState WriteState { get { return writer.WriteState; } } public override void WriteString(string text) { writer.WriteString(text); } public override void WriteSurrogateCharEntity(char lowChar, char highChar) { writer.WriteSurrogateCharEntity(lowChar, highChar); } public override void WriteWhitespace(string whitespace) { writer.WriteWhitespace(whitespace); } public override void WriteValue(object value) { writer.WriteValue(value); } public override void WriteValue(string value) { writer.WriteValue(value); } public override void WriteValue(bool value) { writer.WriteValue(value); } public override void WriteValue(DateTime value) { writer.WriteValue(value); } public override void WriteValue(double value) { writer.WriteValue(value); } public override void WriteValue(int value) { writer.WriteValue(value); } public override void WriteValue(long value) { writer.WriteValue(value); } #if DECIMAL_FLOAT_API public override void WriteValue(decimal value) { writer.WriteValue(value); } public override void WriteValue(float value) { writer.WriteValue(value); } #endif public override void WriteXmlnsAttribute(string prefix, string namespaceUri) { if (namespaceUri == null) throw System.Runtime.Serialization.DiagnosticUtility.ExceptionUtility.ThrowHelperArgumentNull("namespaceUri"); if (prefix == null) { if (LookupPrefix(namespaceUri) != null) return; if (namespaceUri.Length == 0) { prefix = string.Empty; } else { string depthStr = this.depth.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); string prefixStr = this.prefix.ToString(System.Globalization.NumberFormatInfo.InvariantInfo); prefix = string.Concat("d", depthStr, "p", prefixStr); } } WriteAttributeString("xmlns", prefix, null, namespaceUri); } public override string XmlLang { get { return writer.XmlLang; } } public override XmlSpace XmlSpace { get { return writer.XmlSpace; } } } } }