diff options
Diffstat (limited to 'src/mscorlib/src/System/IO/StreamWriter.cs')
-rw-r--r-- | src/mscorlib/src/System/IO/StreamWriter.cs | 765 |
1 files changed, 0 insertions, 765 deletions
diff --git a/src/mscorlib/src/System/IO/StreamWriter.cs b/src/mscorlib/src/System/IO/StreamWriter.cs deleted file mode 100644 index 22eba82605..0000000000 --- a/src/mscorlib/src/System/IO/StreamWriter.cs +++ /dev/null @@ -1,765 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -using System.Text; -using System.Runtime.CompilerServices; -using System.Security.Permissions; -using System.Runtime.Serialization; -using System.Diagnostics; -using System.Diagnostics.Contracts; -using System.Runtime.InteropServices; -using System.Threading.Tasks; - -namespace System.IO -{ - // This class implements a TextWriter for writing characters to a Stream. - // This is designed for character output in a particular Encoding, - // whereas the Stream class is designed for byte input and output. - // - [Serializable] - [ComVisible(true)] - public class StreamWriter : TextWriter - { - // For UTF-8, the values of 1K for the default buffer size and 4K for the - // file stream buffer size are reasonable & give very reasonable - // performance for in terms of construction time for the StreamWriter and - // write perf. Note that for UTF-8, we end up allocating a 4K byte buffer, - // which means we take advantage of adaptive buffering code. - // The performance using UnicodeEncoding is acceptable. - internal const int DefaultBufferSize = 1024; // char[] - private const int DefaultFileStreamBufferSize = 4096; - private const int MinBufferSize = 128; - - // Bit bucket - Null has no backing store. Non closable. - public new static readonly StreamWriter Null = new StreamWriter(Stream.Null, UTF8NoBOM, MinBufferSize, true); - - private Stream stream; - private Encoding encoding; - private Encoder encoder; - private byte[] byteBuffer; - private char[] charBuffer; - private int charPos; - private int charLen; - private bool autoFlush; - private bool haveWrittenPreamble; - private bool closable; - - // We don't guarantee thread safety on StreamWriter, but we should at - // least prevent users from trying to write anything while an Async - // write from the same thread is in progress. - [NonSerialized] - private volatile Task _asyncWriteTask; - - private void CheckAsyncTaskInProgress() - { - // We are not locking the access to _asyncWriteTask because this is not meant to guarantee thread safety. - // We are simply trying to deter calling any Write APIs while an async Write from the same thread is in progress. - - Task t = _asyncWriteTask; - - if (t != null && !t.IsCompleted) - throw new InvalidOperationException(Environment.GetResourceString("InvalidOperation_AsyncIOInProgress")); - } - - // The high level goal is to be tolerant of encoding errors when we read and very strict - // when we write. Hence, default StreamWriter encoding will throw on encoding error. - // Note: when StreamWriter throws on invalid encoding chars (for ex, high surrogate character - // D800-DBFF without a following low surrogate character DC00-DFFF), it will cause the - // internal StreamWriter's state to be irrecoverable as it would have buffered the - // illegal chars and any subsequent call to Flush() would hit the encoding error again. - // Even Close() will hit the exception as it would try to flush the unwritten data. - // Maybe we can add a DiscardBufferedData() method to get out of such situation (like - // StreamReader though for different reason). Either way, the buffered data will be lost! - internal static Encoding UTF8NoBOM { - [FriendAccessAllowed] - get { return EncodingCache.UTF8NoBOM; } - } - - - internal StreamWriter(): base(null) { // Ask for CurrentCulture all the time - } - - public StreamWriter(Stream stream) - : this(stream, UTF8NoBOM, DefaultBufferSize, false) { - } - - public StreamWriter(Stream stream, Encoding encoding) - : this(stream, encoding, DefaultBufferSize, false) { - } - - // Creates a new StreamWriter for the given stream. The - // character encoding is set by encoding and the buffer size, - // in number of 16-bit characters, is set by bufferSize. - // - public StreamWriter(Stream stream, Encoding encoding, int bufferSize) - : this(stream, encoding, bufferSize, false) { - } - - public StreamWriter(Stream stream, Encoding encoding, int bufferSize, bool leaveOpen) - : base(null) // Ask for CurrentCulture all the time - { - if (stream == null || encoding == null) - throw new ArgumentNullException((stream == null ? nameof(stream) : nameof(encoding))); - if (!stream.CanWrite) - throw new ArgumentException(Environment.GetResourceString("Argument_StreamNotWritable")); - if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); - Contract.EndContractBlock(); - - Init(stream, encoding, bufferSize, leaveOpen); - } - - public StreamWriter(String path) - : this(path, false, UTF8NoBOM, DefaultBufferSize) { - } - - public StreamWriter(String path, bool append) - : this(path, append, UTF8NoBOM, DefaultBufferSize) { - } - - public StreamWriter(String path, bool append, Encoding encoding) - : this(path, append, encoding, DefaultBufferSize) { - } - - public StreamWriter(String path, bool append, Encoding encoding, int bufferSize) - : base(null) - { - // Ask for CurrentCulture all the time - if (path == null) - throw new ArgumentNullException(nameof(path)); - if (encoding == null) - throw new ArgumentNullException(nameof(encoding)); - if (path.Length == 0) - throw new ArgumentException(Environment.GetResourceString("Argument_EmptyPath")); - if (bufferSize <= 0) throw new ArgumentOutOfRangeException(nameof(bufferSize), Environment.GetResourceString("ArgumentOutOfRange_NeedPosNum")); - Contract.EndContractBlock(); - - Stream stream = CreateFile(path, append); - Init(stream, encoding, bufferSize, false); - } - - private void Init(Stream streamArg, Encoding encodingArg, int bufferSize, bool shouldLeaveOpen) - { - this.stream = streamArg; - this.encoding = encodingArg; - this.encoder = encoding.GetEncoder(); - if (bufferSize < MinBufferSize) bufferSize = MinBufferSize; - charBuffer = new char[bufferSize]; - byteBuffer = new byte[encoding.GetMaxByteCount(bufferSize)]; - charLen = bufferSize; - // If we're appending to a Stream that already has data, don't write - // the preamble. - if (stream.CanSeek && stream.Position > 0) - haveWrittenPreamble = true; - closable = !shouldLeaveOpen; - } - - private static Stream CreateFile(String path, bool append) { - FileMode mode = append? FileMode.Append: FileMode.Create; - FileStream f = new FileStream(path, mode, FileAccess.Write, FileShare.Read, - DefaultFileStreamBufferSize, FileOptions.SequentialScan, Path.GetFileName(path), false, false); - return f; - } - - public override void Close() { - Dispose(true); - GC.SuppressFinalize(this); - } - - protected override void Dispose(bool disposing) { - try { - // We need to flush any buffered data if we are being closed/disposed. - // Also, we never close the handles for stdout & friends. So we can safely - // write any buffered data to those streams even during finalization, which - // is generally the right thing to do. - if (stream != null) { - // Note: flush on the underlying stream can throw (ex., low disk space) - if (disposing) - { - CheckAsyncTaskInProgress(); - - Flush(true, true); - } - } - } - finally { - // Dispose of our resources if this StreamWriter is closable. - // Note: Console.Out and other such non closable streamwriters should be left alone - if (!LeaveOpen && stream != null) { - try { - // Attempt to close the stream even if there was an IO error from Flushing. - // Note that Stream.Close() can potentially throw here (may or may not be - // due to the same Flush error). In this case, we still need to ensure - // cleaning up internal resources, hence the finally block. - if (disposing) - stream.Close(); - } - finally { - stream = null; - byteBuffer = null; - charBuffer = null; - encoding = null; - encoder = null; - charLen = 0; - base.Dispose(disposing); - } - } - } - } - - public override void Flush() - { - CheckAsyncTaskInProgress(); - - Flush(true, true); - } - - private void Flush(bool flushStream, bool flushEncoder) - { - // flushEncoder should be true at the end of the file and if - // the user explicitly calls Flush (though not if AutoFlush is true). - // This is required to flush any dangling characters from our UTF-7 - // and UTF-8 encoders. - if (stream == null) - __Error.WriterClosed(); - - // Perf boost for Flush on non-dirty writers. - if (charPos==0 && (!flushStream && !flushEncoder)) - return; - - if (!haveWrittenPreamble) { - haveWrittenPreamble = true; - byte[] preamble = encoding.GetPreamble(); - if (preamble.Length > 0) - stream.Write(preamble, 0, preamble.Length); - } - - int count = encoder.GetBytes(charBuffer, 0, charPos, byteBuffer, 0, flushEncoder); - charPos = 0; - if (count > 0) - stream.Write(byteBuffer, 0, count); - // By definition, calling Flush should flush the stream, but this is - // only necessary if we passed in true for flushStream. The Web - // Services guys have some perf tests where flushing needlessly hurts. - if (flushStream) - stream.Flush(); - } - - public virtual bool AutoFlush { - get { return autoFlush; } - - set - { - CheckAsyncTaskInProgress(); - - autoFlush = value; - if (value) Flush(true, false); - } - } - - public virtual Stream BaseStream { - get { return stream; } - } - - internal bool LeaveOpen { - get { return !closable; } - } - - internal bool HaveWrittenPreamble { - set { haveWrittenPreamble= value; } - } - - public override Encoding Encoding { - get { return encoding; } - } - - public override void Write(char value) - { - CheckAsyncTaskInProgress(); - - if (charPos == charLen) Flush(false, false); - charBuffer[charPos] = value; - charPos++; - if (autoFlush) Flush(true, false); - } - - public override void Write(char[] buffer) - { - // This may be faster than the one with the index & count since it - // has to do less argument checking. - if (buffer==null) - return; - - CheckAsyncTaskInProgress(); - - int index = 0; - int count = buffer.Length; - while (count > 0) { - if (charPos == charLen) Flush(false, false); - int n = charLen - charPos; - if (n > count) n = count; - Debug.Assert(n > 0, "StreamWriter::Write(char[]) isn't making progress! This is most likely a race condition in user code."); - Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char)); - charPos += n; - index += n; - count -= n; - } - if (autoFlush) Flush(true, false); - } - - public override void Write(char[] buffer, int index, int count) { - if (buffer==null) - throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - CheckAsyncTaskInProgress(); - - while (count > 0) { - if (charPos == charLen) Flush(false, false); - int n = charLen - charPos; - if (n > count) n = count; - Debug.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code."); - Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char)); - charPos += n; - index += n; - count -= n; - } - if (autoFlush) Flush(true, false); - } - - public override void Write(String value) - { - if (value != null) - { - - CheckAsyncTaskInProgress(); - - int count = value.Length; - int index = 0; - while (count > 0) { - if (charPos == charLen) Flush(false, false); - int n = charLen - charPos; - if (n > count) n = count; - Debug.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code."); - value.CopyTo(index, charBuffer, charPos, n); - charPos += n; - index += n; - count -= n; - } - if (autoFlush) Flush(true, false); - } - } - - #region Task based Async APIs - [ComVisible(false)] - public override Task WriteAsync(char value) - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteAsync(value); - - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: false); - _asyncWriteTask = task; - - return task; - } - - // We pass in private instance fields of this MarshalByRefObject-derived type as local params - // to ensure performant access inside the state machine that corresponds this async method. - // Fields that are written to must be assigned at the end of the method *and* before instance invocations. - private static async Task WriteAsyncInternal(StreamWriter _this, Char value, - Char[] charBuffer, Int32 charPos, Int32 charLen, Char[] coreNewLine, - bool autoFlush, bool appendNewLine) - { - if (charPos == charLen) { - await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - charBuffer[charPos] = value; - charPos++; - - if (appendNewLine) - { - for (Int32 i = 0; i < coreNewLine.Length; i++) // Expect 2 iterations, no point calling BlockCopy - { - if (charPos == charLen) { - await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - charBuffer[charPos] = coreNewLine[i]; - charPos++; - } - } - - if (autoFlush) { - await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - _this.CharPos_Prop = charPos; - } - - [ComVisible(false)] - public override Task WriteAsync(String value) - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteAsync(value); - - if (value != null) - { - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: false); - _asyncWriteTask = task; - - return task; - } - else - { - return Task.CompletedTask; - } - } - - // We pass in private instance fields of this MarshalByRefObject-derived type as local params - // to ensure performant access inside the state machine that corresponds this async method. - // Fields that are written to must be assigned at the end of the method *and* before instance invocations. - private static async Task WriteAsyncInternal(StreamWriter _this, String value, - Char[] charBuffer, Int32 charPos, Int32 charLen, Char[] coreNewLine, - bool autoFlush, bool appendNewLine) - { - Contract.Requires(value != null); - - int count = value.Length; - int index = 0; - - while (count > 0) - { - if (charPos == charLen) { - await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - int n = charLen - charPos; - if (n > count) - n = count; - - Debug.Assert(n > 0, "StreamWriter::Write(String) isn't making progress! This is most likely a race condition in user code."); - - value.CopyTo(index, charBuffer, charPos, n); - - charPos += n; - index += n; - count -= n; - } - - if (appendNewLine) - { - for (Int32 i = 0; i < coreNewLine.Length; i++) // Expect 2 iterations, no point calling BlockCopy - { - if (charPos == charLen) { - await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - charBuffer[charPos] = coreNewLine[i]; - charPos++; - } - } - - if (autoFlush) { - await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - _this.CharPos_Prop = charPos; - } - - [ComVisible(false)] - public override Task WriteAsync(char[] buffer, int index, int count) - { - if (buffer==null) - throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteAsync(buffer, index, count); - - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, buffer, index, count, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: false); - _asyncWriteTask = task; - - return task; - } - - // We pass in private instance fields of this MarshalByRefObject-derived type as local params - // to ensure performant access inside the state machine that corresponds this async method. - // Fields that are written to must be assigned at the end of the method *and* before instance invocations. - private static async Task WriteAsyncInternal(StreamWriter _this, Char[] buffer, Int32 index, Int32 count, - Char[] charBuffer, Int32 charPos, Int32 charLen, Char[] coreNewLine, - bool autoFlush, bool appendNewLine) - { - Contract.Requires(count == 0 || (count > 0 && buffer != null)); - Contract.Requires(index >= 0); - Contract.Requires(count >= 0); - Contract.Requires(buffer == null || (buffer != null && buffer.Length - index >= count)); - - while (count > 0) - { - if (charPos == charLen) { - await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - int n = charLen - charPos; - if (n > count) n = count; - - Debug.Assert(n > 0, "StreamWriter::Write(char[], int, int) isn't making progress! This is most likely a race condition in user code."); - - Buffer.InternalBlockCopy(buffer, index * sizeof(char), charBuffer, charPos * sizeof(char), n * sizeof(char)); - - charPos += n; - index += n; - count -= n; - } - - if (appendNewLine) - { - for (Int32 i = 0; i < coreNewLine.Length; i++) // Expect 2 iterations, no point calling BlockCopy - { - if (charPos == charLen) { - await _this.FlushAsyncInternal(false, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - charBuffer[charPos] = coreNewLine[i]; - charPos++; - } - } - - if (autoFlush) { - await _this.FlushAsyncInternal(true, false, charBuffer, charPos).ConfigureAwait(false); - Debug.Assert(_this.charPos == 0); - charPos = 0; - } - - _this.CharPos_Prop = charPos; - } - - [ComVisible(false)] - public override Task WriteLineAsync() - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteLineAsync(); - - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, null, 0, 0, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true); - _asyncWriteTask = task; - - return task; - } - - - [ComVisible(false)] - public override Task WriteLineAsync(char value) - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteLineAsync(value); - - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true); - _asyncWriteTask = task; - - return task; - } - - - [ComVisible(false)] - public override Task WriteLineAsync(String value) - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteLineAsync(value); - - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, value, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true); - _asyncWriteTask = task; - - return task; - } - - - [ComVisible(false)] - public override Task WriteLineAsync(char[] buffer, int index, int count) - { - if (buffer==null) - throw new ArgumentNullException(nameof(buffer), Environment.GetResourceString("ArgumentNull_Buffer")); - if (index < 0) - throw new ArgumentOutOfRangeException(nameof(index), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (count < 0) - throw new ArgumentOutOfRangeException(nameof(count), Environment.GetResourceString("ArgumentOutOfRange_NeedNonNegNum")); - if (buffer.Length - index < count) - throw new ArgumentException(Environment.GetResourceString("Argument_InvalidOffLen")); - Contract.EndContractBlock(); - - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Write() which a subclass might have overriden. - // To be safe we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Write) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.WriteLineAsync(buffer, index, count); - - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = WriteAsyncInternal(this, buffer, index, count, charBuffer, charPos, charLen, CoreNewLine, autoFlush, appendNewLine: true); - _asyncWriteTask = task; - - return task; - } - - - [ComVisible(false)] - public override Task FlushAsync() - { - // If we have been inherited into a subclass, the following implementation could be incorrect - // since it does not call through to Flush() which a subclass might have overriden. To be safe - // we will only use this implementation in cases where we know it is safe to do so, - // and delegate to our base class (which will call into Flush) when we are not sure. - if (this.GetType() != typeof(StreamWriter)) - return base.FlushAsync(); - - // flushEncoder should be true at the end of the file and if - // the user explicitly calls Flush (though not if AutoFlush is true). - // This is required to flush any dangling characters from our UTF-7 - // and UTF-8 encoders. - if (stream == null) - __Error.WriterClosed(); - - CheckAsyncTaskInProgress(); - - Task task = FlushAsyncInternal(true, true, charBuffer, charPos); - _asyncWriteTask = task; - - return task; - } - - private Int32 CharPos_Prop { - set { this.charPos = value; } - } - - private bool HaveWrittenPreamble_Prop { - set { this.haveWrittenPreamble = value; } - } - - private Task FlushAsyncInternal(bool flushStream, bool flushEncoder, - Char[] sCharBuffer, Int32 sCharPos) { - - // Perf boost for Flush on non-dirty writers. - if (sCharPos == 0 && !flushStream && !flushEncoder) - return Task.CompletedTask; - - Task flushTask = FlushAsyncInternal(this, flushStream, flushEncoder, sCharBuffer, sCharPos, this.haveWrittenPreamble, - this.encoding, this.encoder, this.byteBuffer, this.stream); - - this.charPos = 0; - return flushTask; - } - - - // We pass in private instance fields of this MarshalByRefObject-derived type as local params - // to ensure performant access inside the state machine that corresponds this async method. - private static async Task FlushAsyncInternal(StreamWriter _this, bool flushStream, bool flushEncoder, - Char[] charBuffer, Int32 charPos, bool haveWrittenPreamble, - Encoding encoding, Encoder encoder, Byte[] byteBuffer, Stream stream) - { - if (!haveWrittenPreamble) - { - _this.HaveWrittenPreamble_Prop = true; - byte[] preamble = encoding.GetPreamble(); - if (preamble.Length > 0) - await stream.WriteAsync(preamble, 0, preamble.Length).ConfigureAwait(false); - } - - int count = encoder.GetBytes(charBuffer, 0, charPos, byteBuffer, 0, flushEncoder); - if (count > 0) - await stream.WriteAsync(byteBuffer, 0, count).ConfigureAwait(false); - - // By definition, calling Flush should flush the stream, but this is - // only necessary if we passed in true for flushStream. The Web - // Services guys have some perf tests where flushing needlessly hurts. - if (flushStream) - await stream.FlushAsync().ConfigureAwait(false); - } - #endregion - } // class StreamWriter -} // namespace |