diff --git a/crypto/src/util/io/BaseOutputStream.cs b/crypto/src/util/io/BaseOutputStream.cs
index d9a5b92d6..dad9b19a4 100644
--- a/crypto/src/util/io/BaseOutputStream.cs
+++ b/crypto/src/util/io/BaseOutputStream.cs
@@ -10,6 +10,9 @@ namespace Org.BouncyCastle.Utilities.IO
public sealed override bool CanSeek { get { return false; } }
public sealed override bool CanWrite { get { return true; } }
+#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void CopyTo(Stream destination, int bufferSize) { throw new NotSupportedException(); }
+#endif
public override void Flush() {}
public sealed override long Length { get { throw new NotSupportedException(); } }
public sealed override long Position
@@ -35,10 +38,5 @@ namespace Org.BouncyCastle.Utilities.IO
{
Write(buffer, 0, buffer.Length);
}
-
- public override void WriteByte(byte value)
- {
- Write(new byte[]{ value }, 0, 1);
- }
}
}
diff --git a/crypto/src/util/io/FilterStream.cs b/crypto/src/util/io/FilterStream.cs
index 0db82ec88..d9bcbb8ef 100644
--- a/crypto/src/util/io/FilterStream.cs
+++ b/crypto/src/util/io/FilterStream.cs
@@ -15,15 +15,6 @@ namespace Org.BouncyCastle.Utilities.IO
this.s = s;
}
- protected override void Dispose(bool disposing)
- {
- if (disposing)
- {
- s.Dispose();
- }
-
- base.Dispose(disposing);
- }
public override bool CanRead
{
get { return s.CanRead; }
@@ -36,6 +27,10 @@ namespace Org.BouncyCastle.Utilities.IO
{
get { return s.CanWrite; }
}
+ public override void Flush()
+ {
+ s.Flush();
+ }
public override long Length
{
get { return s.Length; }
@@ -45,9 +40,13 @@ namespace Org.BouncyCastle.Utilities.IO
get { return s.Position; }
set { s.Position = value; }
}
- public override void Flush()
+ public override int Read(byte[] buffer, int offset, int count)
{
- s.Flush();
+ return s.Read(buffer, offset, count);
+ }
+ public override int ReadByte()
+ {
+ return s.ReadByte();
}
public override long Seek(long offset, SeekOrigin origin)
{
@@ -57,14 +56,6 @@ namespace Org.BouncyCastle.Utilities.IO
{
s.SetLength(value);
}
- public override int Read(byte[] buffer, int offset, int count)
- {
- return s.Read(buffer, offset, count);
- }
- public override int ReadByte()
- {
- return s.ReadByte();
- }
public override void Write(byte[] buffer, int offset, int count)
{
s.Write(buffer, offset, count);
@@ -73,5 +64,18 @@ namespace Org.BouncyCastle.Utilities.IO
{
s.WriteByte(value);
}
+ protected void Detach(bool disposing)
+ {
+ base.Dispose(disposing);
+ }
+ protected override void Dispose(bool disposing)
+ {
+ if (disposing)
+ {
+ s.Dispose();
+ }
+
+ base.Dispose(disposing);
+ }
}
}
diff --git a/crypto/src/util/io/LimitedInputStream.cs b/crypto/src/util/io/LimitedInputStream.cs
new file mode 100644
index 000000000..d6616eff5
--- /dev/null
+++ b/crypto/src/util/io/LimitedInputStream.cs
@@ -0,0 +1,56 @@
+using Org.BouncyCastle.Utilities.Zlib;
+using System;
+using System.IO;
+
+namespace Org.BouncyCastle.Utilities.IO
+{
+ internal class LimitedInputStream
+ : BaseInputStream
+ {
+ private readonly Stream m_stream;
+ private long m_limit;
+
+ internal LimitedInputStream(Stream stream, long limit)
+ {
+ this.m_stream = stream;
+ this.m_limit = limit;
+ }
+
+ internal long CurrentLimit => m_limit;
+
+ public override int Read(byte[] buffer, int offset, int count)
+ {
+ int numRead = m_stream.Read(buffer, offset, count);
+ if (numRead > 0)
+ {
+ if ((m_limit -= numRead) < 0)
+ throw new StreamOverflowException("Data Overflow");
+ }
+ return numRead;
+ }
+
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ int numRead = m_stream.Read(buffer);
+ if (numRead > 0)
+ {
+ if ((m_limit -= numRead) < 0)
+ throw new StreamOverflowException("Data Overflow");
+ }
+ return numRead;
+ }
+#endif
+
+ public override int ReadByte()
+ {
+ int b = m_stream.ReadByte();
+ if (b >= 0)
+ {
+ if (--m_limit < 0)
+ throw new StreamOverflowException("Data Overflow");
+ }
+ return b;
+ }
+ }
+}
diff --git a/crypto/src/util/io/PushbackStream.cs b/crypto/src/util/io/PushbackStream.cs
index 2ceb64361..15ba70501 100644
--- a/crypto/src/util/io/PushbackStream.cs
+++ b/crypto/src/util/io/PushbackStream.cs
@@ -13,7 +13,20 @@ namespace Org.BouncyCastle.Utilities.IO
{
}
- public override int Read(byte[] buffer, int offset, int count)
+#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void CopyTo(Stream destination, int bufferSize)
+ {
+ if (m_buf != -1)
+ {
+ destination.WriteByte((byte)m_buf);
+ m_buf = -1;
+ }
+
+ s.CopyTo(destination, bufferSize);
+ }
+#endif
+
+ public override int Read(byte[] buffer, int offset, int count)
{
Streams.ValidateBufferArguments(buffer, offset, count);
@@ -27,10 +40,27 @@ namespace Org.BouncyCastle.Utilities.IO
return 1;
}
- return base.Read(buffer, offset, count);
+ return s.Read(buffer, offset, count);
}
- public override int ReadByte()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ if (m_buf != -1)
+ {
+ if (buffer.IsEmpty)
+ return 0;
+
+ buffer[0] = (byte)m_buf;
+ m_buf = -1;
+ return 1;
+ }
+
+ return s.Read(buffer);
+ }
+#endif
+
+ public override int ReadByte()
{
if (m_buf != -1)
{
diff --git a/crypto/src/util/io/Streams.cs b/crypto/src/util/io/Streams.cs
index e1da47fcd..c23332909 100644
--- a/crypto/src/util/io/Streams.cs
+++ b/crypto/src/util/io/Streams.cs
@@ -13,10 +13,7 @@ namespace Org.BouncyCastle.Utilities.IO
public static void Drain(Stream inStr)
{
- byte[] bs = new byte[BufferSize];
- while (inStr.Read(bs, 0, bs.Length) > 0)
- {
- }
+ inStr.CopyTo(Stream.Null, BufferSize);
}
/// <summary>Write the full contents of inStr to the destination stream outStr.</summary>
@@ -25,7 +22,7 @@ namespace Org.BouncyCastle.Utilities.IO
/// <exception cref="IOException">In case of IO failure.</exception>
public static void PipeAll(Stream inStr, Stream outStr)
{
- PipeAll(inStr, outStr, BufferSize);
+ inStr.CopyTo(outStr, BufferSize);
}
/// <summary>Write the full contents of inStr to the destination stream outStr.</summary>
@@ -35,12 +32,7 @@ namespace Org.BouncyCastle.Utilities.IO
/// <exception cref="IOException">In case of IO failure.</exception>
public static void PipeAll(Stream inStr, Stream outStr, int bufferSize)
{
- byte[] bs = new byte[bufferSize];
- int numRead;
- while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0)
- {
- outStr.Write(bs, 0, numRead);
- }
+ inStr.CopyTo(outStr, bufferSize);
}
/// <summary>
@@ -60,17 +52,9 @@ namespace Org.BouncyCastle.Utilities.IO
/// <exception cref="IOException"></exception>
public static long PipeAllLimited(Stream inStr, long limit, Stream outStr)
{
- byte[] bs = new byte[BufferSize];
- long total = 0;
- int numRead;
- while ((numRead = inStr.Read(bs, 0, bs.Length)) > 0)
- {
- if ((limit - total) < numRead)
- throw new StreamOverflowException("Data Overflow");
- total += numRead;
- outStr.Write(bs, 0, numRead);
- }
- return total;
+ var limited = new LimitedInputStream(inStr, limit);
+ limited.CopyTo(outStr, BufferSize);
+ return limit - limited.CurrentLimit;
}
public static byte[] ReadAll(Stream inStr)
@@ -105,7 +89,22 @@ namespace Org.BouncyCastle.Utilities.IO
return totalRead;
}
- public static void ValidateBufferArguments(byte[] buffer, int offset, int count)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public static int ReadFully(Stream inStr, Span<byte> buffer)
+ {
+ int totalRead = 0;
+ while (totalRead < buffer.Length)
+ {
+ int numRead = inStr.Read(buffer[totalRead..]);
+ if (numRead < 1)
+ break;
+ totalRead += numRead;
+ }
+ return totalRead;
+ }
+#endif
+
+ public static void ValidateBufferArguments(byte[] buffer, int offset, int count)
{
if (buffer == null)
throw new ArgumentNullException("buffer");
@@ -120,6 +119,14 @@ namespace Org.BouncyCastle.Utilities.IO
/// <exception cref="IOException"></exception>
public static int WriteBufTo(MemoryStream buf, byte[] output, int offset)
{
+#if NETCOREAPP2_0_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ if (buf.TryGetBuffer(out var buffer))
+ {
+ buffer.CopyTo(output, offset);
+ return buffer.Count;
+ }
+#endif
+
int size = Convert.ToInt32(buf.Length);
buf.WriteTo(new MemoryStream(output, offset, size));
return size;
diff --git a/crypto/src/util/io/TeeInputStream.cs b/crypto/src/util/io/TeeInputStream.cs
index 73ea8fed0..3d45bb4f1 100644
--- a/crypto/src/util/io/TeeInputStream.cs
+++ b/crypto/src/util/io/TeeInputStream.cs
@@ -18,7 +18,6 @@ namespace Org.BouncyCastle.Utilities.IO
this.tee = tee;
}
-#if PORTABLE
protected override void Dispose(bool disposing)
{
if (disposing)
@@ -28,14 +27,6 @@ namespace Org.BouncyCastle.Utilities.IO
}
base.Dispose(disposing);
}
-#else
- public override void Close()
- {
- Platform.Dispose(input);
- Platform.Dispose(tee);
- base.Close();
- }
-#endif
public override int Read(byte[] buffer, int offset, int count)
{
@@ -49,7 +40,21 @@ namespace Org.BouncyCastle.Utilities.IO
return i;
}
- public override int ReadByte()
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override int Read(Span<byte> buffer)
+ {
+ int i = input.Read(buffer);
+
+ if (i > 0)
+ {
+ tee.Write(buffer[..i]);
+ }
+
+ return i;
+ }
+#endif
+
+ public override int ReadByte()
{
int i = input.ReadByte();
diff --git a/crypto/src/util/io/TeeOutputStream.cs b/crypto/src/util/io/TeeOutputStream.cs
index 5f447b18b..fc213ae55 100644
--- a/crypto/src/util/io/TeeOutputStream.cs
+++ b/crypto/src/util/io/TeeOutputStream.cs
@@ -18,7 +18,6 @@ namespace Org.BouncyCastle.Utilities.IO
this.tee = tee;
}
-#if PORTABLE
protected override void Dispose(bool disposing)
{
if (disposing)
@@ -28,14 +27,6 @@ namespace Org.BouncyCastle.Utilities.IO
}
base.Dispose(disposing);
}
-#else
- public override void Close()
- {
- Platform.Dispose(output);
- Platform.Dispose(tee);
- base.Close();
- }
-#endif
public override void Write(byte[] buffer, int offset, int count)
{
@@ -43,7 +34,15 @@ namespace Org.BouncyCastle.Utilities.IO
tee.Write(buffer, offset, count);
}
- public override void WriteByte(byte value)
+#if NETCOREAPP2_1_OR_GREATER || NETSTANDARD2_1_OR_GREATER
+ public override void Write(ReadOnlySpan<byte> buffer)
+ {
+ output.Write(buffer);
+ tee.Write(buffer);
+ }
+#endif
+
+ public override void WriteByte(byte value)
{
output.WriteByte(value);
tee.WriteByte(value);
diff --git a/crypto/src/util/zlib/ZInputStream.cs b/crypto/src/util/zlib/ZInputStream.cs
index 3e6fcc1be..0433a0182 100644
--- a/crypto/src/util/zlib/ZInputStream.cs
+++ b/crypto/src/util/zlib/ZInputStream.cs
@@ -116,34 +116,18 @@ namespace Org.BouncyCastle.Utilities.Zlib
this.z.avail_in = 0;
}
- /*public int available() throws IOException {
- return inf.finished() ? 0 : 1;
- }*/
-
-#if PORTABLE
protected override void Dispose(bool disposing)
{
if (disposing)
{
- if (closed)
- return;
-
- closed = true;
- Platform.Dispose(input);
+ if (!closed)
+ {
+ closed = true;
+ Platform.Dispose(input);
+ }
}
base.Dispose(disposing);
}
-#else
- public override void Close()
- {
- if (closed)
- return;
-
- closed = true;
- Platform.Dispose(input);
- base.Close();
- }
-#endif
public virtual int FlushMode
{
diff --git a/crypto/src/util/zlib/ZOutputStream.cs b/crypto/src/util/zlib/ZOutputStream.cs
index dcb93f97b..301516e57 100644
--- a/crypto/src/util/zlib/ZOutputStream.cs
+++ b/crypto/src/util/zlib/ZOutputStream.cs
@@ -109,49 +109,61 @@ namespace Org.BouncyCastle.Utilities.Zlib
this.z.deflateInit(level, nowrap);
}
-#if PORTABLE
- protected override void Dispose(bool disposing)
+ protected void Detach(bool disposing)
{
if (disposing)
{
- if (closed)
- return;
-
- DoClose();
+ if (!closed)
+ {
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this.closed = true;
+ End();
+ output = null;
+ }
+ }
}
base.Dispose(disposing);
}
-#else
- public override void Close()
- {
- if (closed)
- return;
-
- DoClose();
- base.Close();
- }
-#endif
- private void DoClose()
+ protected override void Dispose(bool disposing)
{
- try
+ if (disposing)
{
- try
- {
- Finish();
- }
- catch (IOException)
+ if (!closed)
{
- // Ignore
+ try
+ {
+ try
+ {
+ Finish();
+ }
+ catch (IOException)
+ {
+ // Ignore
+ }
+ }
+ finally
+ {
+ this.closed = true;
+ End();
+ Platform.Dispose(output);
+ output = null;
+ }
}
}
- finally
- {
- this.closed = true;
- End();
- Platform.Dispose(output);
- output = null;
- }
+ base.Dispose(disposing);
}
public virtual void End()
|