You've already forked linux-packaging-mono
Imported Upstream version 5.10.0.47
Former-commit-id: d0813289fa2d35e1f8ed77530acb4fb1df441bc0
This commit is contained in:
parent
88ff76fe28
commit
e46a49ecf1
@@ -6,6 +6,5 @@
|
||||
<AssemblyKey>ECMA</AssemblyKey>
|
||||
<IsNETCoreApp>true</IsNETCoreApp>
|
||||
<IsUAP>true</IsUAP>
|
||||
<IsNetFxNETStandard>true</IsNetFxNETStandard>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@@ -4,7 +4,6 @@
|
||||
<BuildConfigurations>
|
||||
netcoreapp;
|
||||
uap;
|
||||
netfx;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@@ -7,8 +7,6 @@
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Release|AnyCPU'" />
|
||||
<ItemGroup>
|
||||
|
@@ -5,7 +5,6 @@
|
||||
netcoreapp-Unix;
|
||||
netcoreapp-Windows_NT;
|
||||
uap-Windows_NT;
|
||||
netfx-Windows_NT;
|
||||
</BuildConfigurations>
|
||||
</PropertyGroup>
|
||||
</Project>
|
@@ -33,13 +33,7 @@ internal static partial class Interop
|
||||
[DllImport(Libraries.CompressionNative, EntryPoint = "CompressionNative_InflateEnd")]
|
||||
internal static extern ZLibNative.ErrorCode InflateEnd(ref ZLibNative.ZStream stream);
|
||||
|
||||
internal static unsafe uint crc32(uint crc, byte[] buffer, int offset, int len)
|
||||
{
|
||||
fixed (byte* buf = &buffer[offset])
|
||||
return Crc32(crc, buf, len);
|
||||
}
|
||||
|
||||
[DllImport(Libraries.CompressionNative, EntryPoint = "CompressionNative_Crc32")]
|
||||
private static extern unsafe uint Crc32(uint crc, byte* buffer, int len);
|
||||
internal static extern unsafe uint crc32(uint crc, byte* buffer, int len);
|
||||
}
|
||||
}
|
||||
|
@@ -49,12 +49,6 @@ internal static partial class Interop
|
||||
}
|
||||
}
|
||||
|
||||
internal static unsafe uint crc32(uint crc, byte[] buffer, int offset, int len)
|
||||
{
|
||||
fixed (byte* buf = &buffer[offset])
|
||||
return crc32(crc, buf, len);
|
||||
}
|
||||
|
||||
internal static unsafe ZLibNative.ErrorCode Deflate(ref ZLibNative.ZStream stream, ZLibNative.FlushCode flush)
|
||||
{
|
||||
fixed (ZLibNative.ZStream* streamBytes = &stream)
|
||||
|
@@ -13,12 +13,9 @@
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Unix-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netcoreapp-Windows_NT-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'netfx-Windows_NT-Release|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Debug|AnyCPU'" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'uap-Windows_NT-Release|AnyCPU'" />
|
||||
<ItemGroup>
|
||||
<Compile Include="$(SharedOpenSourcePath)System\IO\Compression\Crc32Helper.cs" />
|
||||
<Compile Include="$(SharedOpenSourcePath)System\IO\Compression\ZipArchive.cs" />
|
||||
<Compile Include="$(SharedOpenSourcePath)System\IO\Compression\ZipArchiveEntry.cs" />
|
||||
<Compile Include="$(SharedOpenSourcePath)System\IO\Compression\ZipArchiveMode.cs" />
|
||||
@@ -52,12 +49,16 @@
|
||||
<Compile Include="System\IO\Compression\CompressionLevel.cs" />
|
||||
<Compile Include="System\IO\Compression\CompressionMode.cs" />
|
||||
<Compile Include="System\IO\Compression\GZipStream.cs" />
|
||||
<Compile Include="System\IO\Compression\Crc32Helper.ZLib.cs" />
|
||||
<Compile Include="System\IO\Compression\DeflateZLib\Deflater.cs" />
|
||||
<Compile Include="System\IO\Compression\DeflateZLib\DeflateStream.cs" />
|
||||
<Compile Include="System\IO\Compression\DeflateZLib\Inflater.cs" />
|
||||
<Compile Include="System\IO\Compression\DeflateZLib\ZLibException.cs" />
|
||||
<Compile Include="System\IO\Compression\DeflateZLib\ZLibNative.cs" />
|
||||
<Compile Include="System\IO\Compression\ZLibException.Serialization.cs" />
|
||||
<Compile Include="System\IO\Compression\ZipArchiveEntry.netcoreapp.cs" />
|
||||
<Compile Include="System\IO\Compression\ZipCustomStreams.netcoreapp.cs" />
|
||||
<Compile Include="System\IO\Compression\PositionPreservingWriteOnlyStreamWrapper.netcoreapp.cs" />
|
||||
<Compile Include="$(CommonPath)\System\IO\PathInternal.cs">
|
||||
<Link>Common\System\IO\PathInternal.cs</Link>
|
||||
</Compile>
|
||||
@@ -65,6 +66,9 @@
|
||||
<Link>Common\System\IO\StreamHelpers.CopyValidation.cs</Link>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(TargetGroup)' == 'netfx'">
|
||||
<Compile Include="System\IO\Compression\Crc32Helper.Managed.cs" />
|
||||
</ItemGroup>
|
||||
<!-- Windows specific files -->
|
||||
<ItemGroup Condition=" '$(TargetsWindows)' == 'true'">
|
||||
<Compile Include="System\IO\Compression\ZipArchiveEntry.Windows.cs" />
|
||||
|
@@ -19,11 +19,8 @@ using System.Diagnostics;
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
/// <summary>
|
||||
/// This class contains a managed Crc32 function as well as an indirection to the Interop.Zlib.Crc32 call.
|
||||
/// Since Desktop compression uses this file alongside the Open ZipArchive, we cannot remove it
|
||||
/// without breaking the Desktop build.
|
||||
///
|
||||
/// Note that in CoreFX the ZlibCrc32 function is always called.
|
||||
/// without breaking the Desktop build. Note that in CoreFX the Zlib Crc32 function is always called.
|
||||
/// </summary>
|
||||
internal static class Crc32Helper
|
||||
{
|
||||
@@ -31,18 +28,45 @@ namespace System.IO.Compression
|
||||
// See RFC1952 for details.
|
||||
public static uint UpdateCrc32(uint crc32, byte[] buffer, int offset, int length)
|
||||
{
|
||||
Debug.Assert((buffer != null) && (offset >= 0) && (length >= 0)
|
||||
&& (offset <= buffer.Length - length), "check the caller");
|
||||
#if FEATURE_ZLIB
|
||||
return Interop.zlib.crc32(crc32, buffer, offset, length);
|
||||
#else
|
||||
return ManagedCrc32(crc32, buffer, offset, length);
|
||||
#endif
|
||||
Debug.Assert((buffer != null) && (offset >= 0) && (length >= 0) && (offset <= buffer.Length - length));
|
||||
Debug.Assert(BitConverter.IsLittleEndian, "ManagedCrc32 Expects Little Endian");
|
||||
|
||||
uint term1, term2, term3 = 0;
|
||||
|
||||
crc32 ^= 0xFFFFFFFFU;
|
||||
int runningLength = (length / 8) * 8;
|
||||
int endBytes = length - runningLength;
|
||||
|
||||
for (int i = 0; i < runningLength / 8; i++)
|
||||
{
|
||||
crc32 ^= unchecked((uint)(buffer[offset] | buffer[offset + 1] << 8 | buffer[offset + 2] << 16 | buffer[offset + 3] << 24));
|
||||
offset += 4;
|
||||
term1 = s_crcTable_7[crc32 & 0x000000FF] ^
|
||||
s_crcTable_6[(crc32 >> 8) & 0x000000FF];
|
||||
term2 = crc32 >> 16;
|
||||
crc32 = term1 ^
|
||||
s_crcTable_5[term2 & 0x000000FF] ^
|
||||
s_crcTable_4[(term2 >> 8) & 0x000000FF];
|
||||
|
||||
term3 = unchecked((uint)(buffer[offset] | buffer[offset + 1] << 8 | buffer[offset + 2] << 16 | buffer[offset + 3] << 24));
|
||||
offset += 4;
|
||||
term1 = s_crcTable_3[term3 & 0x000000FF] ^
|
||||
s_crcTable_2[(term3 >> 8) & 0x000000FF];
|
||||
term2 = term3 >> 16;
|
||||
crc32 ^= term1 ^
|
||||
s_crcTable_1[term2 & 0x000000FF] ^
|
||||
s_crcTable_0[(term2 >> 8) & 0x000000FF];
|
||||
}
|
||||
|
||||
for (int i = 0; i < endBytes; i++)
|
||||
{
|
||||
crc32 = s_crcTable_0[(crc32 ^ buffer[offset++]) & 0x000000FF] ^ (crc32 >> 8);
|
||||
}
|
||||
|
||||
crc32 ^= 0xFFFFFFFFU;
|
||||
return crc32;
|
||||
}
|
||||
|
||||
#if !FEATURE_ZLIB
|
||||
|
||||
// Generated tables for managed crc calculation.
|
||||
// Each table n (starting at 0) contains remainders from the long division of
|
||||
// all possible byte values, shifted by an offset of (n * 4 bits).
|
||||
@@ -480,47 +504,5 @@ namespace System.IO.Compression
|
||||
0x6EAB0882u, 0xA201081Cu, 0xA8C40105u, 0x646E019Bu, 0xEAE10678u,
|
||||
0x264B06E6u
|
||||
};
|
||||
|
||||
private static uint ManagedCrc32(uint crc32, byte[] buffer, int offset, int length)
|
||||
{
|
||||
Debug.Assert(BitConverter.IsLittleEndian, "ManagedCrc32 Expects Little Endian");
|
||||
|
||||
uint term1, term2, term3 = 0;
|
||||
|
||||
crc32 ^= 0xFFFFFFFFU;
|
||||
int runningLength = (length / 8) * 8;
|
||||
int endBytes = length - runningLength;
|
||||
|
||||
for (int i = 0; i < runningLength / 8; i++)
|
||||
{
|
||||
crc32 ^= unchecked((uint)(buffer[offset] | buffer[offset + 1] << 8 | buffer[offset + 2] << 16 | buffer[offset + 3] << 24));
|
||||
offset += 4;
|
||||
term1 = s_crcTable_7[crc32 & 0x000000FF] ^
|
||||
s_crcTable_6[(crc32 >> 8) & 0x000000FF];
|
||||
term2 = crc32 >> 16;
|
||||
crc32 = term1 ^
|
||||
s_crcTable_5[term2 & 0x000000FF] ^
|
||||
s_crcTable_4[(term2 >> 8) & 0x000000FF];
|
||||
|
||||
|
||||
term3 = unchecked((uint)(buffer[offset] | buffer[offset + 1] << 8 | buffer[offset + 2] << 16 | buffer[offset + 3] << 24));
|
||||
offset += 4;
|
||||
term1 = s_crcTable_3[term3 & 0x000000FF] ^
|
||||
s_crcTable_2[(term3 >> 8) & 0x000000FF];
|
||||
term2 = term3 >> 16;
|
||||
crc32 ^= term1 ^
|
||||
s_crcTable_1[term2 & 0x000000FF] ^
|
||||
s_crcTable_0[(term2 >> 8) & 0x000000FF];
|
||||
}
|
||||
|
||||
for (int i = 0; i < endBytes; i++)
|
||||
{
|
||||
crc32 = s_crcTable_0[(crc32 ^ buffer[offset++]) & 0x000000FF] ^ (crc32 >> 8);
|
||||
}
|
||||
|
||||
crc32 ^= 0xFFFFFFFFU;
|
||||
return crc32;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
29
external/corefx/src/System.IO.Compression/src/System/IO/Compression/Crc32Helper.ZLib.cs
vendored
Normal file
29
external/corefx/src/System.IO.Compression/src/System/IO/Compression/Crc32Helper.ZLib.cs
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
internal static class Crc32Helper
|
||||
{
|
||||
// Calculate CRC based on the old CRC and the new bytes
|
||||
public static unsafe uint UpdateCrc32(uint crc32, byte[] buffer, int offset, int length)
|
||||
{
|
||||
Debug.Assert((buffer != null) && (offset >= 0) && (length >= 0) && (offset <= buffer.Length - length));
|
||||
fixed (byte* bufferPtr = buffer)
|
||||
{
|
||||
return Interop.zlib.crc32(crc32, bufferPtr, length);
|
||||
}
|
||||
}
|
||||
|
||||
public static unsafe uint UpdateCrc32(uint crc32, ReadOnlySpan<byte> buffer)
|
||||
{
|
||||
fixed (byte* bufferPtr = &buffer.DangerousGetPinnableReference())
|
||||
{
|
||||
return Interop.zlib.crc32(crc32, bufferPtr, buffer.Length);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -26,22 +26,6 @@ namespace System.IO.Compression
|
||||
private bool _wroteHeader;
|
||||
private bool _wroteBytes;
|
||||
|
||||
public DeflateManagedStream(Stream stream, CompressionMode mode) : this(stream, mode, leaveOpen: false)
|
||||
{
|
||||
}
|
||||
|
||||
// Since a reader is being taken, CompressionMode.Decompress is implied
|
||||
internal DeflateManagedStream(Stream stream, bool leaveOpen, IFileFormatReader reader)
|
||||
{
|
||||
Debug.Assert(reader != null, "The IFileFormatReader passed to the internal DeflateStream constructor must be non-null");
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
if (!stream.CanRead)
|
||||
throw new ArgumentException(SR.NotSupported_UnreadableStream, nameof(stream));
|
||||
|
||||
InitializeInflater(stream, leaveOpen, reader);
|
||||
}
|
||||
|
||||
// A specific constructor to allow decompression of Deflate64
|
||||
internal DeflateManagedStream(Stream stream, ZipArchiveEntry.CompressionMethodValues method)
|
||||
{
|
||||
@@ -53,41 +37,6 @@ namespace System.IO.Compression
|
||||
InitializeInflater(stream, false, null, method);
|
||||
}
|
||||
|
||||
public DeflateManagedStream(Stream stream, CompressionMode mode, bool leaveOpen)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
|
||||
switch (mode)
|
||||
{
|
||||
case CompressionMode.Decompress:
|
||||
InitializeInflater(stream, leaveOpen);
|
||||
break;
|
||||
|
||||
case CompressionMode.Compress:
|
||||
InitializeDeflater(stream, leaveOpen, CompressionLevel.Optimal);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentException(SR.ArgumentOutOfRange_Enum, nameof(mode));
|
||||
}
|
||||
}
|
||||
|
||||
// Implies mode = Compress
|
||||
public DeflateManagedStream(Stream stream, CompressionLevel compressionLevel) : this(stream, compressionLevel, leaveOpen: false)
|
||||
{
|
||||
}
|
||||
|
||||
// Implies mode = Compress
|
||||
public DeflateManagedStream(Stream stream, CompressionLevel compressionLevel, bool leaveOpen)
|
||||
{
|
||||
if (stream == null)
|
||||
throw new ArgumentNullException(nameof(stream));
|
||||
|
||||
InitializeDeflater(stream, leaveOpen, compressionLevel);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Sets up this DeflateManagedStream to be used for Inflation/Decompression
|
||||
/// </summary>
|
||||
@@ -106,23 +55,6 @@ namespace System.IO.Compression
|
||||
_buffer = new byte[DefaultBufferSize];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets up this DeflateManagedStream to be used for Deflation/Compression
|
||||
/// </summary>
|
||||
internal void InitializeDeflater(Stream stream, bool leaveOpen, CompressionLevel compressionLevel)
|
||||
{
|
||||
Debug.Assert(stream != null);
|
||||
if (!stream.CanWrite)
|
||||
throw new ArgumentException(SR.NotSupported_UnwritableStream, nameof(stream));
|
||||
|
||||
_deflater = new DeflaterManaged();
|
||||
|
||||
_stream = stream;
|
||||
_mode = CompressionMode.Compress;
|
||||
_leaveOpen = leaveOpen;
|
||||
_buffer = new byte[DefaultBufferSize];
|
||||
}
|
||||
|
||||
internal void SetFileFormatWriter(IFileFormatWriter writer)
|
||||
{
|
||||
if (writer != null)
|
||||
@@ -131,8 +63,6 @@ namespace System.IO.Compression
|
||||
}
|
||||
}
|
||||
|
||||
public Stream BaseStream => _stream;
|
||||
|
||||
public override bool CanRead
|
||||
{
|
||||
get
|
||||
|
@@ -17,29 +17,5 @@ namespace System.IO.Compression
|
||||
bool ReadFooter(InputBuffer input);
|
||||
void UpdateWithBytesRead(byte[] buffer, int offset, int bytesToCopy);
|
||||
void Validate();
|
||||
|
||||
/// <summary>
|
||||
/// A reader corresponds to an expected file format and contains methods
|
||||
/// to read header/footer data from a file of that format. If the Zlib library
|
||||
/// is instead being used and the file format is supported, we can simply pass
|
||||
/// a supported WindowSize and let Zlib do the header/footer parsing for us.
|
||||
///
|
||||
/// This Property allows getting of a ZLibWindowSize that can be used in place
|
||||
/// of manually parsing the raw data stream.
|
||||
/// </summary>
|
||||
/// <return>
|
||||
/// For raw data, return -8..-15
|
||||
/// For GZip header detection and decoding, return 16..31
|
||||
/// For GZip and Zlib header detection and decoding, return 32..47
|
||||
/// </return>
|
||||
/// <remarks>
|
||||
/// The windowBits parameter for inflation must be greater than or equal to the
|
||||
/// windowBits parameter used in deflation.
|
||||
/// </remarks>
|
||||
/// <remarks>
|
||||
/// If the incorrect header information is used, zlib inflation will likely throw a
|
||||
/// Z_DATA_ERROR exception.
|
||||
///</remarks>
|
||||
int ZLibWindowSize { get; }
|
||||
}
|
||||
}
|
||||
|
@@ -36,12 +36,12 @@ namespace System.IO.Compression
|
||||
|
||||
// Extra bits for length code 257 - 285.
|
||||
private static readonly byte[] s_extraLengthBits =
|
||||
{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,16,56,62 };
|
||||
{ 0,0,0,0,0,0,0,0,1,1,1,1,2,2,2,2,3,3,3,3,4,4,4,4,5,5,5,5,16 };
|
||||
|
||||
// The base length for length code 257 - 285.
|
||||
// The formula to get the real length for a length code is lengthBase[code - 257] + (value stored in extraBits)
|
||||
private static readonly int[] s_lengthBase =
|
||||
{ 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,3,0,0 };
|
||||
{ 3,4,5,6,7,8,9,10,11,13,15,17,19,23,27,31,35,43,51,59,67,83,99,115,131,163,195,227,3};
|
||||
|
||||
// The base distance for distance code 0 - 31
|
||||
// The real distance for a distance code is distanceBasePosition[code] + (value stored in extraBits)
|
||||
@@ -91,17 +91,6 @@ namespace System.IO.Compression
|
||||
|
||||
private IFileFormatReader _formatReader; // class to decode header and footer (e.g. gzip)
|
||||
|
||||
public InflaterManaged(bool deflate64)
|
||||
{
|
||||
_output = new OutputWindow();
|
||||
_input = new InputBuffer();
|
||||
|
||||
_codeList = new byte[HuffmanTree.MaxLiteralTreeElements + HuffmanTree.MaxDistTreeElements];
|
||||
_codeLengthTreeCodeLength = new byte[HuffmanTree.NumberOfCodeLengthTreeElements];
|
||||
_deflate64 = deflate64;
|
||||
Reset();
|
||||
}
|
||||
|
||||
internal InflaterManaged(IFileFormatReader reader, bool deflate64)
|
||||
{
|
||||
_output = new OutputWindow();
|
||||
@@ -118,13 +107,6 @@ namespace System.IO.Compression
|
||||
Reset();
|
||||
}
|
||||
|
||||
public void SetFileFormatReader(IFileFormatReader reader)
|
||||
{
|
||||
_formatReader = reader;
|
||||
_hasFormatReader = true;
|
||||
Reset();
|
||||
}
|
||||
|
||||
private void Reset()
|
||||
{
|
||||
_state = _hasFormatReader ?
|
||||
@@ -139,8 +121,6 @@ namespace System.IO.Compression
|
||||
|
||||
public int AvailableOutput => _output.AvailableBytes;
|
||||
|
||||
public bool NeedsInput() => _input.NeedsInput();
|
||||
|
||||
public int Inflate(byte[] bytes, int offset, int length)
|
||||
{
|
||||
// copy bytes from output to outputbytes if we have available bytes
|
||||
@@ -401,9 +381,10 @@ namespace System.IO.Compression
|
||||
end_of_block_code_seen = false;
|
||||
|
||||
int freeBytes = _output.FreeBytes; // it is a little bit faster than frequently accessing the property
|
||||
while (freeBytes > 258)
|
||||
while (freeBytes > 65536)
|
||||
{
|
||||
// 258 means we can safely do decoding since maximum repeat length is 258
|
||||
// With Deflate64 we can have up to a 64kb length, so we ensure at least that much space is available
|
||||
// in the OutputWindow to avoid overwriting previous unflushed output data.
|
||||
|
||||
int symbol;
|
||||
switch (_state)
|
||||
@@ -506,7 +487,7 @@ namespace System.IO.Compression
|
||||
goto case InflaterState.HaveDistCode;
|
||||
|
||||
case InflaterState.HaveDistCode:
|
||||
// To avoid a table lookup we note that for distanceCode >= 2,
|
||||
// To avoid a table lookup we note that for distanceCode > 3,
|
||||
// extra_bits = (distanceCode-2) >> 1
|
||||
int offset;
|
||||
if (_distanceCode > 3)
|
||||
@@ -524,7 +505,6 @@ namespace System.IO.Compression
|
||||
offset = _distanceCode + 1;
|
||||
}
|
||||
|
||||
Debug.Assert(freeBytes >= 258, "following operation is not safe!");
|
||||
_output.WriteLengthDistance(_length, offset);
|
||||
freeBytes -= _length;
|
||||
_state = InflaterState.DecodeTop;
|
||||
|
@@ -15,10 +15,13 @@ namespace System.IO.Compression
|
||||
/// </summary>
|
||||
internal sealed class OutputWindow
|
||||
{
|
||||
private const int WindowSize = 65536;
|
||||
private const int WindowMask = 65535;
|
||||
// With Deflate64 we can have up to a 65536 length as well as up to a 65538 distance. This means we need a Window that is at
|
||||
// least 131074 bytes long so we have space to retrieve up to a full 64kb in lookback and place it in our buffer without
|
||||
// overwriting existing data. OutputWindow requires that the WindowSize be an exponent of 2, so we round up to 2^18.
|
||||
private const int WindowSize = 262144;
|
||||
private const int WindowMask = 262143;
|
||||
|
||||
private readonly byte[] _window = new byte[WindowSize]; // The window is 2^15 bytes
|
||||
private readonly byte[] _window = new byte[WindowSize]; // The window is 2^18 bytes
|
||||
private int _end; // this is the position to where we should write next byte
|
||||
private int _bytesUsed; // The number of bytes in the output window which is not consumed.
|
||||
|
||||
@@ -34,14 +37,14 @@ namespace System.IO.Compression
|
||||
public void WriteLengthDistance(int length, int distance)
|
||||
{
|
||||
Debug.Assert((_bytesUsed + length) <= WindowSize, "No Enough space");
|
||||
|
||||
|
||||
// move backwards distance bytes in the output stream,
|
||||
// and copy length bytes from this position to the output stream.
|
||||
_bytesUsed += length;
|
||||
int copyStart = (_end - distance) & WindowMask; // start position for coping.
|
||||
|
||||
int border = WindowSize - length;
|
||||
if (copyStart <= border && _end < border)
|
||||
if (copyStart <= border && _end < border)
|
||||
{
|
||||
if (length <= distance)
|
||||
{
|
||||
|
@@ -23,7 +23,7 @@ namespace System.IO.Compression
|
||||
private int _activeAsyncOperation; // 1 == true, 0 == false
|
||||
private bool _wroteBytes;
|
||||
|
||||
public DeflateStream(Stream stream, CompressionMode mode): this(stream, mode, leaveOpen: false)
|
||||
public DeflateStream(Stream stream, CompressionMode mode) : this(stream, mode, leaveOpen: false)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -232,22 +232,38 @@ namespace System.IO.Compression
|
||||
|
||||
public override int Read(byte[] array, int offset, int count)
|
||||
{
|
||||
EnsureDecompressionMode();
|
||||
ValidateParameters(array, offset, count);
|
||||
return ReadCore(new Span<byte>(array, offset, count));
|
||||
}
|
||||
|
||||
public override int Read(Span<byte> destination)
|
||||
{
|
||||
if (GetType() != typeof(DeflateStream))
|
||||
{
|
||||
// DeflateStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
|
||||
// to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
|
||||
// should use the behavior of Read(byte[],int,int) overload.
|
||||
return base.Read(destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReadCore(destination);
|
||||
}
|
||||
}
|
||||
|
||||
internal int ReadCore(Span<byte> destination)
|
||||
{
|
||||
EnsureDecompressionMode();
|
||||
EnsureNotDisposed();
|
||||
EnsureBufferInitialized();
|
||||
|
||||
int bytesRead;
|
||||
int currentOffset = offset;
|
||||
int remainingCount = count;
|
||||
int totalRead = 0;
|
||||
|
||||
while (true)
|
||||
{
|
||||
bytesRead = _inflater.Inflate(array, currentOffset, remainingCount);
|
||||
currentOffset += bytesRead;
|
||||
remainingCount -= bytesRead;
|
||||
|
||||
if (remainingCount == 0)
|
||||
int bytesRead = _inflater.Inflate(destination.Slice(totalRead));
|
||||
totalRead += bytesRead;
|
||||
if (totalRead == destination.Length)
|
||||
{
|
||||
break;
|
||||
}
|
||||
@@ -274,7 +290,7 @@ namespace System.IO.Compression
|
||||
_inflater.SetInput(_buffer, 0, bytes);
|
||||
}
|
||||
|
||||
return count - remainingCount;
|
||||
return totalRead;
|
||||
}
|
||||
|
||||
private void ValidateParameters(byte[] array, int offset, int count)
|
||||
@@ -336,58 +352,73 @@ namespace System.IO.Compression
|
||||
|
||||
public override Task<int> ReadAsync(byte[] array, int offset, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
// We use this checking order for compat to earlier versions:
|
||||
ValidateParameters(array, offset, count);
|
||||
return ReadAsyncMemory(new Memory<byte>(array, offset, count), cancellationToken).AsTask();
|
||||
}
|
||||
|
||||
public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (GetType() != typeof(DeflateStream))
|
||||
{
|
||||
// Ensure that existing streams derived from DeflateStream and that override ReadAsync(byte[],...)
|
||||
// get their existing behaviors when the newer Memory-based overload is used.
|
||||
return base.ReadAsync(destination, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
return ReadAsyncMemory(destination, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal ValueTask<int> ReadAsyncMemory(Memory<byte> destination, CancellationToken cancellationToken)
|
||||
{
|
||||
EnsureDecompressionMode();
|
||||
EnsureNoActiveAsyncOperation();
|
||||
ValidateParameters(array, offset, count);
|
||||
EnsureNotDisposed();
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
{
|
||||
return Task.FromCanceled<int>(cancellationToken);
|
||||
return new ValueTask<int>(Task.FromCanceled<int>(cancellationToken));
|
||||
}
|
||||
|
||||
EnsureBufferInitialized();
|
||||
Task<int> readTask = null;
|
||||
|
||||
bool cleanup = true;
|
||||
AsyncOperationStarting();
|
||||
try
|
||||
{
|
||||
// Try to read decompressed data in output buffer
|
||||
int bytesRead = _inflater.Inflate(array, offset, count);
|
||||
int bytesRead = _inflater.Inflate(destination.Span);
|
||||
if (bytesRead != 0)
|
||||
{
|
||||
// If decompression output buffer is not empty, return immediately.
|
||||
return Task.FromResult(bytesRead);
|
||||
return new ValueTask<int>(bytesRead);
|
||||
}
|
||||
|
||||
if (_inflater.Finished())
|
||||
{
|
||||
// end of compression stream
|
||||
return Task.FromResult(0);
|
||||
return new ValueTask<int>(0);
|
||||
}
|
||||
|
||||
// If there is no data on the output buffer and we are not at
|
||||
// the end of the stream, we need to get more data from the base stream
|
||||
readTask = _stream.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken);
|
||||
if (readTask == null)
|
||||
{
|
||||
throw new InvalidOperationException(SR.NotSupported_UnreadableStream);
|
||||
}
|
||||
|
||||
return ReadAsyncCore(readTask, array, offset, count, cancellationToken);
|
||||
ValueTask<int> readTask = _stream.ReadAsync(_buffer, cancellationToken);
|
||||
cleanup = false;
|
||||
return FinishReadAsyncMemory(readTask, destination, cancellationToken);
|
||||
}
|
||||
finally
|
||||
{
|
||||
// if we haven't started any async work, decrement the counter to end the transaction
|
||||
if (readTask == null)
|
||||
if (cleanup)
|
||||
{
|
||||
AsyncOperationCompleting();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<int> ReadAsyncCore(Task<int> readTask, byte[] array, int offset, int count, CancellationToken cancellationToken)
|
||||
private async ValueTask<int> FinishReadAsyncMemory(
|
||||
ValueTask<int> readTask, Memory<byte> destination, CancellationToken cancellationToken)
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -412,17 +443,13 @@ namespace System.IO.Compression
|
||||
|
||||
// Feed the data from base stream into decompression engine
|
||||
_inflater.SetInput(_buffer, 0, bytesRead);
|
||||
bytesRead = _inflater.Inflate(array, offset, count);
|
||||
bytesRead = _inflater.Inflate(destination.Span);
|
||||
|
||||
if (bytesRead == 0 && !_inflater.Finished())
|
||||
{
|
||||
// We could have read in head information and didn't get any data.
|
||||
// Read from the base stream again.
|
||||
readTask = _stream.ReadAsync(_buffer, 0, _buffer.Length, cancellationToken);
|
||||
if (readTask == null)
|
||||
{
|
||||
throw new InvalidOperationException(SR.NotSupported_UnreadableStream);
|
||||
}
|
||||
readTask = _stream.ReadAsync(_buffer, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -438,18 +465,43 @@ namespace System.IO.Compression
|
||||
|
||||
public override void Write(byte[] array, int offset, int count)
|
||||
{
|
||||
// Validate the state and the parameters
|
||||
EnsureCompressionMode();
|
||||
ValidateParameters(array, offset, count);
|
||||
WriteCore(new ReadOnlySpan<byte>(array, offset, count));
|
||||
}
|
||||
|
||||
public override void Write(ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (GetType() != typeof(DeflateStream))
|
||||
{
|
||||
// DeflateStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
|
||||
// to this Write(ReadOnlySpan<byte>) overload being introduced. In that case, this Write(ReadOnlySpan<byte>) overload
|
||||
// should use the behavior of Write(byte[],int,int) overload.
|
||||
base.Write(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteCore(source);
|
||||
}
|
||||
}
|
||||
|
||||
internal void WriteCore(ReadOnlySpan<byte> source)
|
||||
{
|
||||
EnsureCompressionMode();
|
||||
EnsureNotDisposed();
|
||||
|
||||
// Write compressed the bytes we already passed to the deflater:
|
||||
WriteDeflaterOutput();
|
||||
|
||||
// Pass new bytes through deflater and write them too:
|
||||
_deflater.SetInput(array, offset, count);
|
||||
WriteDeflaterOutput();
|
||||
_wroteBytes = true;
|
||||
unsafe
|
||||
{
|
||||
// Pass new bytes through deflater and write them too:
|
||||
fixed (byte* bufferPtr = &source.DangerousGetPinnableReference())
|
||||
{
|
||||
_deflater.SetInput(bufferPtr, source.Length);
|
||||
WriteDeflaterOutput();
|
||||
_wroteBytes = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void WriteDeflaterOutput()
|
||||
@@ -591,19 +643,36 @@ namespace System.IO.Compression
|
||||
|
||||
public override Task WriteAsync(byte[] array, int offset, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
// We use this checking order for compat to earlier versions:
|
||||
EnsureCompressionMode();
|
||||
EnsureNoActiveAsyncOperation();
|
||||
ValidateParameters(array, offset, count);
|
||||
EnsureNotDisposed();
|
||||
|
||||
if (cancellationToken.IsCancellationRequested)
|
||||
return Task.FromCanceled<int>(cancellationToken);
|
||||
|
||||
return WriteAsyncCore(array, offset, count, cancellationToken);
|
||||
return WriteAsyncMemory(new ReadOnlyMemory<byte>(array, offset, count), cancellationToken);
|
||||
}
|
||||
|
||||
private async Task WriteAsyncCore(byte[] array, int offset, int count, CancellationToken cancellationToken)
|
||||
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
|
||||
{
|
||||
if (GetType() != typeof(DeflateStream))
|
||||
{
|
||||
// Ensure that existing streams derived from DeflateStream and that override WriteAsync(byte[],...)
|
||||
// get their existing behaviors when the newer Memory-based overload is used.
|
||||
return base.WriteAsync(source, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
return WriteAsyncMemory(source, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
internal Task WriteAsyncMemory(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
|
||||
{
|
||||
EnsureCompressionMode();
|
||||
EnsureNoActiveAsyncOperation();
|
||||
EnsureNotDisposed();
|
||||
|
||||
return cancellationToken.IsCancellationRequested ?
|
||||
Task.FromCanceled<int>(cancellationToken) :
|
||||
WriteAsyncMemoryCore(source, cancellationToken);
|
||||
}
|
||||
|
||||
private async Task WriteAsyncMemoryCore(ReadOnlyMemory<byte> source, CancellationToken cancellationToken)
|
||||
{
|
||||
AsyncOperationStarting();
|
||||
try
|
||||
@@ -611,7 +680,7 @@ namespace System.IO.Compression
|
||||
await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
// Pass new bytes through deflater
|
||||
_deflater.SetInput(array, offset, count);
|
||||
_deflater.SetInput(source);
|
||||
|
||||
await WriteDeflaterOutputAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
|
@@ -2,9 +2,9 @@
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
using ZErrorCode = System.IO.Compression.ZLibNative.ErrorCode;
|
||||
@@ -18,7 +18,7 @@ namespace System.IO.Compression
|
||||
internal sealed class Deflater : IDisposable
|
||||
{
|
||||
private ZLibNative.ZLibStreamHandle _zlibStream;
|
||||
private GCHandle _inputBufferHandle;
|
||||
private MemoryHandle _inputBufferHandle;
|
||||
private bool _isDisposed;
|
||||
private const int minWindowBits = -15; // WindowBits must be between -8..-15 to write no header, 8..15 for a
|
||||
private const int maxWindowBits = 31; // zlib header, or 24..31 for a GZip header
|
||||
@@ -83,29 +83,46 @@ namespace System.IO.Compression
|
||||
if (disposing)
|
||||
_zlibStream.Dispose();
|
||||
|
||||
if (_inputBufferHandle.IsAllocated)
|
||||
DeallocateInputBufferHandle();
|
||||
DeallocateInputBufferHandle();
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
public bool NeedsInput() => 0 == _zlibStream.AvailIn;
|
||||
|
||||
internal void SetInput(byte[] inputBuffer, int startIndex, int count)
|
||||
internal unsafe void SetInput(ReadOnlyMemory<byte> inputBuffer)
|
||||
{
|
||||
Debug.Assert(NeedsInput(), "We have something left in previous input!");
|
||||
Debug.Assert(null != inputBuffer);
|
||||
Debug.Assert(startIndex >= 0 && count >= 0 && count + startIndex <= inputBuffer.Length);
|
||||
Debug.Assert(!_inputBufferHandle.IsAllocated);
|
||||
Debug.Assert(_inputBufferHandle.PinnedPointer == null);
|
||||
|
||||
if (0 == count)
|
||||
if (0 == inputBuffer.Length)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (SyncLock)
|
||||
{
|
||||
_inputBufferHandle = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned);
|
||||
_inputBufferHandle = inputBuffer.Retain(pin: true);
|
||||
|
||||
_zlibStream.NextIn = _inputBufferHandle.AddrOfPinnedObject() + startIndex;
|
||||
_zlibStream.NextIn = (IntPtr)_inputBufferHandle.PinnedPointer;
|
||||
_zlibStream.AvailIn = (uint)inputBuffer.Length;
|
||||
}
|
||||
}
|
||||
|
||||
internal unsafe void SetInput(byte* inputBufferPtr, int count)
|
||||
{
|
||||
Debug.Assert(NeedsInput(), "We have something left in previous input!");
|
||||
Debug.Assert(inputBufferPtr != null);
|
||||
Debug.Assert(_inputBufferHandle.PinnedPointer == null);
|
||||
|
||||
if (count == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
lock (SyncLock)
|
||||
{
|
||||
_zlibStream.NextIn = (IntPtr)inputBufferPtr;
|
||||
_zlibStream.AvailIn = (uint)count;
|
||||
}
|
||||
}
|
||||
@@ -116,7 +133,6 @@ namespace System.IO.Compression
|
||||
|
||||
Debug.Assert(null != outputBuffer, "Can't pass in a null output buffer!");
|
||||
Debug.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input");
|
||||
Debug.Assert(_inputBufferHandle.IsAllocated);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -127,8 +143,10 @@ namespace System.IO.Compression
|
||||
finally
|
||||
{
|
||||
// Before returning, make sure to release input buffer if necessary:
|
||||
if (0 == _zlibStream.AvailIn && _inputBufferHandle.IsAllocated)
|
||||
if (0 == _zlibStream.AvailIn)
|
||||
{
|
||||
DeallocateInputBufferHandle();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +174,10 @@ namespace System.IO.Compression
|
||||
Debug.Assert(null != outputBuffer, "Can't pass in a null output buffer!");
|
||||
Debug.Assert(outputBuffer.Length > 0, "Can't pass in an empty output buffer!");
|
||||
Debug.Assert(NeedsInput(), "We have something left in previous input!");
|
||||
Debug.Assert(!_inputBufferHandle.IsAllocated);
|
||||
unsafe
|
||||
{
|
||||
Debug.Assert(_inputBufferHandle.PinnedPointer == null);
|
||||
}
|
||||
|
||||
// Note: we require that NeedsInput() == true, i.e. that 0 == _zlibStream.AvailIn.
|
||||
// If there is still input left we should never be getting here; instead we
|
||||
@@ -174,7 +195,10 @@ namespace System.IO.Compression
|
||||
Debug.Assert(null != outputBuffer, "Can't pass in a null output buffer!");
|
||||
Debug.Assert(outputBuffer.Length > 0, "Can't pass in an empty output buffer!");
|
||||
Debug.Assert(NeedsInput(), "We have something left in previous input!");
|
||||
Debug.Assert(!_inputBufferHandle.IsAllocated);
|
||||
unsafe
|
||||
{
|
||||
Debug.Assert(_inputBufferHandle.PinnedPointer == null);
|
||||
}
|
||||
|
||||
// Note: we require that NeedsInput() == true, i.e. that 0 == _zlibStream.AvailIn.
|
||||
// If there is still input left we should never be getting here; instead we
|
||||
@@ -185,13 +209,11 @@ namespace System.IO.Compression
|
||||
|
||||
private void DeallocateInputBufferHandle()
|
||||
{
|
||||
Debug.Assert(_inputBufferHandle.IsAllocated);
|
||||
|
||||
lock (SyncLock)
|
||||
{
|
||||
_zlibStream.AvailIn = 0;
|
||||
_zlibStream.NextIn = ZLibNative.ZNullPtr;
|
||||
_inputBufferHandle.Free();
|
||||
_inputBufferHandle.Dispose();
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -64,6 +64,18 @@ namespace System.IO.Compression
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe int Inflate(Span<byte> destination)
|
||||
{
|
||||
// If Inflate is called on an invalid or unready inflater, return 0 to indicate no bytes have been read.
|
||||
if (destination.Length == 0)
|
||||
return 0;
|
||||
|
||||
fixed (byte* bufPtr = &destination.DangerousGetPinnableReference())
|
||||
{
|
||||
return InflateVerified(bufPtr, destination.Length);
|
||||
}
|
||||
}
|
||||
|
||||
public unsafe int InflateVerified(byte* bufPtr, int length)
|
||||
{
|
||||
// State is valid; attempt inflation
|
||||
|
@@ -39,14 +39,6 @@ namespace System.IO.Compression
|
||||
/// </summary>
|
||||
public ZLibException() { }
|
||||
|
||||
/// <summary>
|
||||
/// This constructor is provided in compliance with common NetFx design patterns;
|
||||
/// developers should prefer using the constructor
|
||||
/// <code>public ZLibException(string message, string zlibErrorContext, ZLibNative.ErrorCode zlibErrorCode, string zlibErrorMessage)</code>.
|
||||
/// </summary>
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
public ZLibException(string message) : base(message) { }
|
||||
|
||||
/// <summary>
|
||||
/// This constructor is provided in compliance with common NetFx design patterns;
|
||||
/// developers should prefer using the constructor
|
||||
@@ -55,23 +47,5 @@ namespace System.IO.Compression
|
||||
/// <param name="message">The error message that explains the reason for the exception.</param>
|
||||
/// <param name="inner">The exception that is the cause of the current exception, or a <code>null</code>.</param>
|
||||
public ZLibException(string message, Exception innerException) : base(message, innerException) { }
|
||||
|
||||
public string ZLibContext
|
||||
{
|
||||
[SecurityCritical]
|
||||
get { return _zlibErrorContext; }
|
||||
}
|
||||
|
||||
public int ZLibErrorCode
|
||||
{
|
||||
[SecurityCritical]
|
||||
get { return (int)_zlibErrorCode; }
|
||||
}
|
||||
|
||||
public string ZLibErrorMessage
|
||||
{
|
||||
[SecurityCritical]
|
||||
get { return _zlibErrorMessage; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -327,29 +327,6 @@ namespace System.IO.Compression
|
||||
return errC;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This function is equivalent to inflateEnd followed by inflateInit.
|
||||
/// The stream will keep attributes that may have been set by inflateInit2.
|
||||
/// </summary>
|
||||
[SecurityCritical]
|
||||
public ErrorCode InflateReset(int windowBits)
|
||||
{
|
||||
EnsureNotDisposed();
|
||||
EnsureState(State.InitializedForInflate);
|
||||
|
||||
ErrorCode errC = Interop.zlib.InflateEnd(ref _zStream);
|
||||
if (errC != ErrorCode.Ok)
|
||||
{
|
||||
_initializationState = State.Disposed;
|
||||
return errC;
|
||||
}
|
||||
|
||||
errC = Interop.zlib.InflateInit2_(ref _zStream, windowBits);
|
||||
_initializationState = State.InitializedForInflate;
|
||||
|
||||
return errC;
|
||||
}
|
||||
|
||||
// This can work even after XxflateEnd().
|
||||
[SecurityCritical]
|
||||
public string GetErrorMessage() => _zStream.msg != ZNullPtr ? Marshal.PtrToStringAnsi(_zStream.msg) : string.Empty;
|
||||
|
@@ -84,6 +84,22 @@ namespace System.IO.Compression
|
||||
return _deflateStream.Read(array, offset, count);
|
||||
}
|
||||
|
||||
public override int Read(Span<byte> destination)
|
||||
{
|
||||
if (GetType() != typeof(GZipStream))
|
||||
{
|
||||
// GZipStream is not sealed, and a derived type may have overridden Read(byte[], int, int) prior
|
||||
// to this Read(Span<byte>) overload being introduced. In that case, this Read(Span<byte>) overload
|
||||
// should use the behavior of Read(byte[],int,int) overload.
|
||||
return base.Read(destination);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDeflateStream();
|
||||
return _deflateStream.ReadCore(destination);
|
||||
}
|
||||
}
|
||||
|
||||
public override IAsyncResult BeginWrite(byte[] array, int offset, int count, AsyncCallback asyncCallback, object asyncState) =>
|
||||
TaskToApm.Begin(WriteAsync(array, offset, count, CancellationToken.None), asyncCallback, asyncState);
|
||||
|
||||
@@ -96,6 +112,28 @@ namespace System.IO.Compression
|
||||
_deflateStream.Write(array, offset, count);
|
||||
}
|
||||
|
||||
public override void Write(ReadOnlySpan<byte> source)
|
||||
{
|
||||
if (GetType() != typeof(GZipStream))
|
||||
{
|
||||
// GZipStream is not sealed, and a derived type may have overridden Write(byte[], int, int) prior
|
||||
// to this Write(ReadOnlySpan<byte>) overload being introduced. In that case, this Write(ReadOnlySpan<byte>) overload
|
||||
// should use the behavior of Write(byte[],int,int) overload.
|
||||
base.Write(source);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDeflateStream();
|
||||
_deflateStream.WriteCore(source);
|
||||
}
|
||||
}
|
||||
|
||||
public override void CopyTo(Stream destination, int bufferSize)
|
||||
{
|
||||
CheckDeflateStream();
|
||||
_deflateStream.CopyTo(destination, bufferSize);
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
try
|
||||
@@ -120,12 +158,44 @@ namespace System.IO.Compression
|
||||
return _deflateStream.ReadAsync(array, offset, count, cancellationToken);
|
||||
}
|
||||
|
||||
public override ValueTask<int> ReadAsync(Memory<byte> destination, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (GetType() != typeof(GZipStream))
|
||||
{
|
||||
// GZipStream is not sealed, and a derived type may have overridden ReadAsync(byte[], int, int) prior
|
||||
// to this ReadAsync(Memory<byte>) overload being introduced. In that case, this ReadAsync(Memory<byte>) overload
|
||||
// should use the behavior of ReadAsync(byte[],int,int) overload.
|
||||
return base.ReadAsync(destination, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDeflateStream();
|
||||
return _deflateStream.ReadAsyncMemory(destination, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
public override Task WriteAsync(byte[] array, int offset, int count, CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDeflateStream();
|
||||
return _deflateStream.WriteAsync(array, offset, count, cancellationToken);
|
||||
}
|
||||
|
||||
public override Task WriteAsync(ReadOnlyMemory<byte> source, CancellationToken cancellationToken = default(CancellationToken))
|
||||
{
|
||||
if (GetType() != typeof(GZipStream))
|
||||
{
|
||||
// GZipStream is not sealed, and a derived type may have overridden WriteAsync(byte[], int, int) prior
|
||||
// to this WriteAsync(ReadOnlyMemory<byte>) overload being introduced. In that case, this
|
||||
// WriteAsync(ReadOnlyMemory<byte>) overload should use the behavior of Write(byte[],int,int) overload.
|
||||
return base.WriteAsync(source, cancellationToken);
|
||||
}
|
||||
else
|
||||
{
|
||||
CheckDeflateStream();
|
||||
return _deflateStream.WriteAsyncMemory(source, cancellationToken);
|
||||
}
|
||||
}
|
||||
|
||||
public override Task FlushAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
CheckDeflateStream();
|
||||
|
@@ -7,7 +7,7 @@ using System.Threading.Tasks;
|
||||
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
internal sealed class PositionPreservingWriteOnlyStreamWrapper : Stream
|
||||
internal sealed partial class PositionPreservingWriteOnlyStreamWrapper : Stream
|
||||
{
|
||||
private readonly Stream _stream;
|
||||
private long _position;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user