[release/6.0] Use caching ConsoleStream for both iOS and Android (#59088)
authorgithub-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
Wed, 15 Sep 2021 06:29:51 +0000 (08:29 +0200)
committerGitHub <noreply@github.com>
Wed, 15 Sep 2021 06:29:51 +0000 (08:29 +0200)
Co-authored-by: Steve Pfister <steve.pfister@microsoft.com>
src/libraries/System.Console/src/System.Console.csproj
src/libraries/System.Console/src/System/ConsolePal.Android.cs
src/libraries/System.Console/src/System/ConsolePal.iOS.cs
src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs [new file with mode: 0644]

index c464007..6cbdc48 100644 (file)
@@ -13,6 +13,7 @@
     <Compile Include="System\ConsoleKeyInfo.cs" />
     <Compile Include="System\ConsoleModifiers.cs" />
     <Compile Include="System\IO\ConsoleStream.cs" />
+    <Compile Include="System\IO\CachedConsoleStream.cs" />
     <Compile Include="System\IO\SyncTextReader.cs" />
     <Compile Include="System\IO\Error.cs" />
     <Compile Include="$(CommonPath)System\Text\ConsoleEncoding.cs"
index 3777952..4cecdac 100644 (file)
@@ -7,15 +7,13 @@ using System.Runtime.InteropServices;
 
 namespace System
 {
-    internal sealed unsafe class LogcatStream : ConsoleStream
+    internal sealed unsafe class LogcatStream : CachedConsoleStream
     {
-        public LogcatStream() : base(FileAccess.Write) {}
+        public LogcatStream(Encoding encoding) : base(encoding) {}
 
-        public override int Read(Span<byte> buffer) => throw Error.GetReadNotSupported();
-
-        public override unsafe void Write(ReadOnlySpan<byte> buffer)
+        protected override void Print(ReadOnlySpan<char> line)
         {
-            string log = ConsolePal.OutputEncoding.GetString(buffer);
+            string log = line.ToString();
             Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Info, "DOTNET", log);
         }
     }
@@ -26,9 +24,9 @@ namespace System
 
         public static Stream OpenStandardInput() => throw new PlatformNotSupportedException();
 
-        public static Stream OpenStandardOutput() => new LogcatStream();
+        public static Stream OpenStandardOutput() => new LogcatStream(OutputEncoding);
 
-        public static Stream OpenStandardError() => new LogcatStream();
+        public static Stream OpenStandardError() => new LogcatStream(OutputEncoding);
 
         public static Encoding InputEncoding => throw new PlatformNotSupportedException();
 
index a58d4ba..8794d55 100644 (file)
@@ -8,75 +8,15 @@ using System.Text;
 
 namespace System
 {
-    internal sealed class NSLogStream : ConsoleStream
+    internal sealed class NSLogStream : CachedConsoleStream
     {
-        private readonly StringBuilder _buffer = new StringBuilder();
-        private readonly Encoding _encoding;
-        private readonly Decoder _decoder;
+        public NSLogStream(Encoding encoding) : base(encoding) {}
 
-        public NSLogStream(Encoding encoding) : base(FileAccess.Write)
+        protected override unsafe void Print(ReadOnlySpan<char> line)
         {
-            _encoding = encoding;
-            _decoder = _encoding.GetDecoder();
-        }
-
-        public override int Read(Span<byte> buffer) => throw Error.GetReadNotSupported();
-
-        public override void Write(ReadOnlySpan<byte> buffer)
-        {
-            int maxCharCount = _encoding.GetMaxCharCount(buffer.Length);
-            char[]? pooledBuffer = null;
-            Span<char> charSpan = maxCharCount <= 512 ? stackalloc char[512] : (pooledBuffer = ArrayPool<char>.Shared.Rent(maxCharCount));
-            try
-            {
-                int count = _decoder.GetChars(buffer, charSpan, false);
-                if (count > 0)
-                {
-                    WriteOrCache(_buffer, charSpan.Slice(0, count));
-                }
-            }
-            finally
-            {
-                if (pooledBuffer != null)
-                {
-                    ArrayPool<char>.Shared.Return(pooledBuffer);
-                }
-            }
-        }
-
-        private static void WriteOrCache(StringBuilder cache, Span<char> charBuffer)
-        {
-            int lastNewLine = charBuffer.LastIndexOf('\n');
-            if (lastNewLine != -1)
-            {
-                Span<char> lineSpan = charBuffer.Slice(0, lastNewLine);
-                if (cache.Length > 0)
-                {
-                    Print(cache.Append(lineSpan).ToString());
-                    cache.Clear();
-                }
-                else
-                {
-                    Print(lineSpan);
-                }
-
-                if (lastNewLine + 1 < charBuffer.Length)
-                {
-                    cache.Append(charBuffer.Slice(lastNewLine + 1));
-                }
-
-                return;
-            }
-
-            // no newlines found, add the entire buffer to the cache
-            cache.Append(charBuffer);
-
-            static unsafe void Print(ReadOnlySpan<char> line)
+            fixed (char* ptr = line)
             {
-                fixed (char* ptr = line)
-                {
-                    Interop.Sys.Log((byte*)ptr, line.Length * 2);
-                }
+                Interop.Sys.Log((byte*)ptr, line.Length * 2);
             }
         }
     }
diff --git a/src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs b/src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs
new file mode 100644 (file)
index 0000000..6aacda6
--- /dev/null
@@ -0,0 +1,77 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System.Buffers;
+using System.Diagnostics;
+using System.IO;
+using System.Text;
+
+namespace System.IO
+{
+    internal abstract class CachedConsoleStream : ConsoleStream
+    {
+        private readonly StringBuilder _buffer = new StringBuilder();
+        private readonly Encoding _encoding;
+        private readonly Decoder _decoder;
+
+        public CachedConsoleStream(Encoding encoding) : base(FileAccess.Write)
+        {
+            _encoding = encoding;
+            _decoder = _encoding.GetDecoder();
+        }
+
+        public override int Read(Span<byte> buffer) => throw Error.GetReadNotSupported();
+
+        public override void Write(ReadOnlySpan<byte> buffer)
+        {
+            int maxCharCount = _encoding.GetMaxCharCount(buffer.Length);
+            char[]? pooledBuffer = null;
+            Span<char> charSpan = maxCharCount <= 512 ? stackalloc char[512] : (pooledBuffer = ArrayPool<char>.Shared.Rent(maxCharCount));
+            try
+            {
+                int count = _decoder.GetChars(buffer, charSpan, false);
+                if (count > 0)
+                {
+                    WriteOrCache(this, _buffer, charSpan.Slice(0, count));
+                }
+            }
+            finally
+            {
+                if (pooledBuffer != null)
+                {
+                    ArrayPool<char>.Shared.Return(pooledBuffer);
+                }
+            }
+        }
+
+        protected abstract void Print(ReadOnlySpan<char> line);
+
+        private static void WriteOrCache(CachedConsoleStream stream, StringBuilder cache, Span<char> charBuffer)
+        {
+            int lastNewLine = charBuffer.LastIndexOf('\n');
+            if (lastNewLine != -1)
+            {
+                Span<char> lineSpan = charBuffer.Slice(0, lastNewLine);
+                if (cache.Length > 0)
+                {
+                    stream.Print(cache.Append(lineSpan).ToString());
+                    cache.Clear();
+                }
+                else
+                {
+                    stream.Print(lineSpan);
+                }
+
+                if (lastNewLine + 1 < charBuffer.Length)
+                {
+                    cache.Append(charBuffer.Slice(lastNewLine + 1));
+                }
+
+                return;
+            }
+
+            // no newlines found, add the entire buffer to the cache
+            cache.Append(charBuffer);
+        }
+    }
+}