Write and WriteAsync overloads for StringBuilder. (dotnet/coreclr#18281)
authorVance Morrison <vancem@microsoft.com>
Thu, 14 Jun 2018 16:06:08 +0000 (09:06 -0700)
committerStephen Toub <stoub@microsoft.com>
Thu, 14 Jun 2018 16:06:08 +0000 (12:06 -0400)
* Write and WriteAsync overloads for StringBuilder.

Addresses issue https://github.com/dotnet/corefx/issues/30048

Note that tests will come as a separate checking as part of the coreFX repo.

* Review feedback

* Review feedback

* Added WriteLine(StringBuilder overloads (review feedback)

* review feedback

* Fix configureAwait

* bug fix

* Bug fix

* review feedback

Commit migrated from https://github.com/dotnet/coreclr/commit/fb8d7b863365457a11da270d6950c16c082635df

src/libraries/System.Private.CoreLib/src/System/IO/TextWriter.cs

index 2afe907..22a8cd6 100644 (file)
@@ -283,6 +283,21 @@ namespace System.IO
             }
         }
 
+        /// <summary>
+        /// Equivalent to Write(stringBuilder.ToString()) however it uses the
+        /// StringBuilder.GetChunks() method to avoid creating the intermediate string 
+        /// </summary>
+        /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+        public virtual void Write(StringBuilder value)
+        {
+            if (value == null)
+            {
+                throw new ArgumentNullException(nameof(value));
+            }
+            foreach (ReadOnlyMemory<char> chunk in value.GetChunks())
+                Write(chunk);
+        }
+
         // Writes out a formatted string.  Uses the same semantics as
         // String.Format.
         // 
@@ -447,6 +462,16 @@ namespace System.IO
             Write(CoreNewLineStr);
         }
 
+        /// <summary>
+        /// Equivalent to WriteLine(stringBuilder.ToString()) however it uses the
+        /// StringBuilder.GetChunks() method to avoid creating the intermediate string 
+        /// </summary>
+        public virtual void WriteLine(StringBuilder value)
+        {
+            Write(value);
+            WriteLine();
+        }
+
         // Writes the text representation of an object followed by a line
         // terminator to the text stream.
         //
@@ -527,6 +552,28 @@ namespace System.IO
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
 
+        /// <summary>
+        /// Equivalent to WriteAsync(stringBuilder.ToString()) however it uses the
+        /// StringBuilder.GetChunks() method to avoid creating the intermediate string 
+        /// </summary>
+        /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+        public virtual Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+        {
+            // Do the agument checking before 'going async' so you get it early 
+            if (value == null)
+            {
+                throw new ArgumentNullException(nameof(value));
+            }
+            // Then do the rest which may be deferred (done in the returned Task)
+            return WriteAsyncCore(value, cancellationToken);
+
+            async Task WriteAsyncCore(StringBuilder sb, CancellationToken ct)
+            {
+                foreach (ReadOnlyMemory<char> chunk in sb.GetChunks())
+                    await WriteAsync(chunk, ct).ConfigureAwait(false);
+            }
+        }
+
         public Task WriteAsync(char[] buffer)
         {
             if (buffer == null)
@@ -579,6 +626,17 @@ namespace System.IO
             tuple, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
         }
 
+        /// <summary>
+        /// Equivalent to WriteLineAsync(stringBuilder.ToString()) however it uses the
+        /// StringBuilder.GetChunks() method to avoid creating the intermediate string 
+        /// </summary>
+        /// <param name="value">The string (as a StringBuilder) to write to the stream</param>
+        public async virtual Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+        {
+            await WriteAsync(value, cancellationToken).ConfigureAwait(false);
+            await WriteAsync(CoreNewLine, cancellationToken).ConfigureAwait(false);
+        }
+
         public Task WriteLineAsync(char[] buffer)
         {
             if (buffer == null)
@@ -745,6 +803,9 @@ namespace System.IO
             public override void Write(string value) => _out.Write(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
+            public override void Write(StringBuilder value) => _out.Write(value);
+
+            [MethodImpl(MethodImplOptions.Synchronized)]
             public override void Write(object value) => _out.Write(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
@@ -799,6 +860,9 @@ namespace System.IO
             public override void WriteLine(string value) => _out.WriteLine(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
+            public override void WriteLine(StringBuilder value) => _out.WriteLine(value);
+
+            [MethodImpl(MethodImplOptions.Synchronized)]
             public override void WriteLine(object value) => _out.WriteLine(value);
 
             [MethodImpl(MethodImplOptions.Synchronized)]
@@ -832,6 +896,13 @@ namespace System.IO
             }
 
             [MethodImpl(MethodImplOptions.Synchronized)]
+            public override Task WriteAsync(StringBuilder value, CancellationToken cancellationToken = default)
+            {
+                Write(value);
+                return Task.CompletedTask;
+            }
+
+            [MethodImpl(MethodImplOptions.Synchronized)]
             public override Task WriteAsync(char[] buffer, int index, int count)
             {
                 Write(buffer, index, count);
@@ -853,6 +924,13 @@ namespace System.IO
             }
 
             [MethodImpl(MethodImplOptions.Synchronized)]
+            public override Task WriteLineAsync(StringBuilder value, CancellationToken cancellationToken = default)
+            {
+                WriteLine(value);
+                return Task.CompletedTask;
+            }
+
+            [MethodImpl(MethodImplOptions.Synchronized)]
             public override Task WriteLineAsync(char[] buffer, int index, int count)
             {
                 WriteLine(buffer, index, count);