From 90252009d2bb2743b6fd75e4845850d1840f55cc Mon Sep 17 00:00:00 2001 From: David Cantu Date: Thu, 27 Jul 2023 18:45:05 -0500 Subject: [PATCH 1/2] Remove _isBlocked constraint from StreamReader.Peek() --- .../tests/System/IO/ReadOneAtATimeStream.cs | 45 +++++++++++++++++++ .../tests/StreamReader/StreamReaderTests.cs | 24 ++++++++++ .../System.IO/tests/System.IO.Tests.csproj | 1 + .../src/System/IO/StreamReader.cs | 2 +- 4 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs diff --git a/src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs b/src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs new file mode 100644 index 00000000000000..2013928e1bd91b --- /dev/null +++ b/src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs @@ -0,0 +1,45 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +namespace System.IO.Tests +{ + public class ReadOneAtATimeStream : Stream + { + MemoryStream _memoryStream; + + public ReadOneAtATimeStream(byte[] buffer) + { + _memoryStream = new MemoryStream(buffer); + } + + public override bool CanRead => true; + + public override bool CanSeek => false; + + public override bool CanWrite => false; + + public override long Length => _memoryStream.Length; + + public override long Position + { + get => _memoryStream.Position; + set => throw new NotSupportedException(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + if (count == 0 || Position == Length) + { + return 0; + } + + _memoryStream.ReadExactly(buffer, offset, 1); + return 1; + } + + public override void Flush() { } + public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); + public override void SetLength(long value) => throw new NotSupportedException(); + public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); + } +} diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs index 0180c9364b8c79..a0c0a3cc1cb867 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs @@ -174,6 +174,30 @@ public void TestPeek() } } + [Fact] + public void TestPeekReadOneByteAtATime() + { + byte[] testData = new byte[] { 72, 69, 76, 76, 79 }; + + using var stream = new ReadOneAtATimeStream(testData); + using var sr = new StreamReader(stream); + + for (int i = 0; i < testData.Length; i++) + { + Assert.Equal(i, stream.Position); + + int tmp = sr.Peek(); + Assert.Equal(testData[i], tmp); + + tmp = sr.Read(); + Assert.Equal(testData[i], tmp); + } + + Assert.Equal(stream.Position, stream.Length); + Assert.Equal(-1, sr.Peek()); + Assert.Equal(-1, sr.Read()); + } + [Fact] public void ArgumentNullOnNullArray() { diff --git a/src/libraries/System.IO/tests/System.IO.Tests.csproj b/src/libraries/System.IO/tests/System.IO.Tests.csproj index c7286f40f1518e..154fe49849f62e 100644 --- a/src/libraries/System.IO/tests/System.IO.Tests.csproj +++ b/src/libraries/System.IO/tests/System.IO.Tests.csproj @@ -53,6 +53,7 @@ + diff --git a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs index a7e5befbb4c25d..9884c4f880bc0a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs +++ b/src/libraries/System.Private.CoreLib/src/System/IO/StreamReader.cs @@ -320,7 +320,7 @@ public override int Peek() if (_charPos == _charLen) { - if (_isBlocked || ReadBuffer() == 0) + if (ReadBuffer() == 0) { return -1; } From aeddbbca3ffa6a6fa92e127ce734385eca63118b Mon Sep 17 00:00:00 2001 From: David Cantu Date: Fri, 28 Jul 2023 10:56:07 -0500 Subject: [PATCH 2/2] Use DelegateStream instead of introducing a new Stream impl --- .../tests/System/IO/ReadOneAtATimeStream.cs | 45 ------------------- .../tests/StreamReader/StreamReaderTests.cs | 18 +++++++- .../System.IO/tests/System.IO.Tests.csproj | 1 - 3 files changed, 17 insertions(+), 47 deletions(-) delete mode 100644 src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs diff --git a/src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs b/src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs deleted file mode 100644 index 2013928e1bd91b..00000000000000 --- a/src/libraries/Common/tests/System/IO/ReadOneAtATimeStream.cs +++ /dev/null @@ -1,45 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -namespace System.IO.Tests -{ - public class ReadOneAtATimeStream : Stream - { - MemoryStream _memoryStream; - - public ReadOneAtATimeStream(byte[] buffer) - { - _memoryStream = new MemoryStream(buffer); - } - - public override bool CanRead => true; - - public override bool CanSeek => false; - - public override bool CanWrite => false; - - public override long Length => _memoryStream.Length; - - public override long Position - { - get => _memoryStream.Position; - set => throw new NotSupportedException(); - } - - public override int Read(byte[] buffer, int offset, int count) - { - if (count == 0 || Position == Length) - { - return 0; - } - - _memoryStream.ReadExactly(buffer, offset, 1); - return 1; - } - - public override void Flush() { } - public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException(); - public override void SetLength(long value) => throw new NotSupportedException(); - public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException(); - } -} diff --git a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs index a0c0a3cc1cb867..b4a32a21ca4c2e 100644 --- a/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs +++ b/src/libraries/System.IO/tests/StreamReader/StreamReaderTests.cs @@ -178,8 +178,24 @@ public void TestPeek() public void TestPeekReadOneByteAtATime() { byte[] testData = new byte[] { 72, 69, 76, 76, 79 }; + using var ms = new MemoryStream(testData); + + // DelegateStream to read one at a time. + using var stream = new DelegateStream( + positionGetFunc: () => ms.Position, + lengthFunc: () => ms.Length, + canReadFunc: () => true, + readFunc: (buffer, offset, count) => + { + if (count == 0 || ms.Position == ms.Length) + { + return 0; + } + + ms.ReadExactly(buffer, offset, 1); + return 1; + }); - using var stream = new ReadOneAtATimeStream(testData); using var sr = new StreamReader(stream); for (int i = 0; i < testData.Length; i++) diff --git a/src/libraries/System.IO/tests/System.IO.Tests.csproj b/src/libraries/System.IO/tests/System.IO.Tests.csproj index 154fe49849f62e..c7286f40f1518e 100644 --- a/src/libraries/System.IO/tests/System.IO.Tests.csproj +++ b/src/libraries/System.IO/tests/System.IO.Tests.csproj @@ -53,7 +53,6 @@ -