diff --git a/src/libraries/System.Console/src/System.Console.csproj b/src/libraries/System.Console/src/System.Console.csproj
index c464007dc95e95..6cbdc48890bb04 100644
--- a/src/libraries/System.Console/src/System.Console.csproj
+++ b/src/libraries/System.Console/src/System.Console.csproj
@@ -13,6 +13,7 @@
+
buffer) => throw Error.GetReadNotSupported();
-
- public override unsafe void Write(ReadOnlySpan buffer)
+ protected override void Print(ReadOnlySpan line)
{
- string log = ConsolePal.OutputEncoding.GetString(buffer);
+ string log = line.ToString();
Interop.Logcat.AndroidLogPrint(Interop.Logcat.LogLevel.Info, "DOTNET", log);
}
}
@@ -26,9 +24,9 @@ internal static void EnsureConsoleInitialized() { }
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();
diff --git a/src/libraries/System.Console/src/System/ConsolePal.iOS.cs b/src/libraries/System.Console/src/System/ConsolePal.iOS.cs
index a58d4baeb42e23..8794d55aeff86d 100644
--- a/src/libraries/System.Console/src/System/ConsolePal.iOS.cs
+++ b/src/libraries/System.Console/src/System/ConsolePal.iOS.cs
@@ -8,75 +8,15 @@
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 line)
{
- _encoding = encoding;
- _decoder = _encoding.GetDecoder();
- }
-
- public override int Read(Span buffer) => throw Error.GetReadNotSupported();
-
- public override void Write(ReadOnlySpan buffer)
- {
- int maxCharCount = _encoding.GetMaxCharCount(buffer.Length);
- char[]? pooledBuffer = null;
- Span charSpan = maxCharCount <= 512 ? stackalloc char[512] : (pooledBuffer = ArrayPool.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.Shared.Return(pooledBuffer);
- }
- }
- }
-
- private static void WriteOrCache(StringBuilder cache, Span charBuffer)
- {
- int lastNewLine = charBuffer.LastIndexOf('\n');
- if (lastNewLine != -1)
- {
- Span 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 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
index 00000000000000..6aacda65a082a3
--- /dev/null
+++ b/src/libraries/System.Console/src/System/IO/CachedConsoleStream.cs
@@ -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 buffer) => throw Error.GetReadNotSupported();
+
+ public override void Write(ReadOnlySpan buffer)
+ {
+ int maxCharCount = _encoding.GetMaxCharCount(buffer.Length);
+ char[]? pooledBuffer = null;
+ Span charSpan = maxCharCount <= 512 ? stackalloc char[512] : (pooledBuffer = ArrayPool.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.Shared.Return(pooledBuffer);
+ }
+ }
+ }
+
+ protected abstract void Print(ReadOnlySpan line);
+
+ private static void WriteOrCache(CachedConsoleStream stream, StringBuilder cache, Span charBuffer)
+ {
+ int lastNewLine = charBuffer.LastIndexOf('\n');
+ if (lastNewLine != -1)
+ {
+ Span 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);
+ }
+ }
+}