You've already forked linux-packaging-mono
Imported Upstream version 4.6.0.125
Former-commit-id: a2155e9bd80020e49e72e86c44da02a8ac0e57a4
This commit is contained in:
parent
a569aebcfd
commit
e79aa3c0ed
@@ -0,0 +1,44 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
using System;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static partial class AppContextDefaultValues
|
||||
{
|
||||
static partial void PopulateDefaultValuesPartial(string platformIdentifier, string profile, int version)
|
||||
{
|
||||
// When defining a new switch you should add it to the last known version.
|
||||
// For instance, if you are adding a switch in .NET 4.6 (the release after 4.5.2) you should defined your switch
|
||||
// like this:
|
||||
// if (version <= 40502) ...
|
||||
// This ensures that all previous versions of that platform (up-to 4.5.2) will get the old behavior by default
|
||||
// NOTE: When adding a default value for a switch please make sure that the default value is added to ALL of the existing platforms!
|
||||
// NOTE: When adding a new if statement for the version please ensure that ALL previous switches are enabled (ie. don't use else if)
|
||||
switch (platformIdentifier)
|
||||
{
|
||||
case ".NETCore":
|
||||
case ".NETFramework":
|
||||
{
|
||||
if (version <= 40502)
|
||||
{
|
||||
LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case "WindowsPhone":
|
||||
case "WindowsPhoneApp":
|
||||
{
|
||||
if (version <= 80100)
|
||||
{
|
||||
LocalAppContext.DefineSwitchDefault(LocalAppContextSwitches.DontEnableSchUseStrongCryptoName, true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
3
mcs/class/referencesource/System/sys/AssemblyInfo.cs
Normal file
3
mcs/class/referencesource/System/sys/AssemblyInfo.cs
Normal file
@@ -0,0 +1,3 @@
|
||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Net.Http, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293", AllInternalsVisible=false)]
|
||||
[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("System.Net.Http.WebRequest, PublicKey=002400000480000094000000060200000024000052534131000400000100010007d1fa57c4aed9f0a32e84aa0faefd0de9e8fd6aec8f87fb03766c834c99921eb23be79ad9d5dcc1dd9ad236132102900b723cf980957fc4e177108fc607774f29e8320e92ea05ece4e821c0a5efe8f1645c4c0c93c1ab99285d622caa652c1dfad63d745d6f2de5f17e5eaf0fc4963d261c8a12436518206dc093344d5ad293", AllInternalsVisible=false)]
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// ==--==
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class LocalAppContextSwitches
|
||||
{
|
||||
|
||||
#region System.Net quirks
|
||||
private static int _dontEnableSchUseStrongCrypto;
|
||||
internal const string DontEnableSchUseStrongCryptoName = @"Switch.System.Net.DontEnableSchUseStrongCrypto";
|
||||
|
||||
public static bool DontEnableSchUseStrongCrypto
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return LocalAppContext.GetCachedSwitchValue(DontEnableSchUseStrongCryptoName, ref _dontEnableSchUseStrongCrypto);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region System.Net.WebSockets.HttpListenerAsyncEventArgs
|
||||
private static int _allocateOverlappedOnDemand;
|
||||
internal const string AllocateOverlappedOnDemandName = @"Switch.System.Net.WebSockets.HttpListenerAsyncEventArgs.AllocateOverlappedOnDemand";
|
||||
|
||||
public static bool AllocateOverlappedOnDemand
|
||||
{
|
||||
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||
get
|
||||
{
|
||||
return LocalAppContext.GetCachedSwitchValue(AllocateOverlappedOnDemandName, ref _allocateOverlappedOnDemand);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
e2edd217f5c9701cb6bbca71a0dad8b5d6b0d648
|
||||
@@ -0,0 +1,16 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
#if !SILVERLIGHT
|
||||
[assembly:StringFreezingAttribute()]
|
||||
|
||||
[assembly:DefaultDependencyAttribute(LoadHint.Always)]
|
||||
|
||||
[assembly:System.Runtime.InteropServices.TypeLibVersion(2, 4)]
|
||||
|
||||
#if !FEATURE_PAL
|
||||
// Opts into the VS loading icons from the Icon Satellite assembly
|
||||
[assembly: System.Drawing.BitmapSuffixInSatelliteAssemblyAttribute()]
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -0,0 +1,21 @@
|
||||
using System;
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
/// <summary>
|
||||
/// Specifies that the attributed code should be excluded from code coverage
|
||||
/// collection. Placing this attribute on a class/struct excludes all
|
||||
/// enclosed methods and properties from code coverage collection.
|
||||
/// </summary>
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Constructor | AttributeTargets.Method | AttributeTargets.Property | AttributeTargets.Event,
|
||||
Inherited = false,
|
||||
AllowMultiple = false
|
||||
)]
|
||||
public sealed class ExcludeFromCodeCoverageAttribute : Attribute
|
||||
{
|
||||
public ExcludeFromCodeCoverageAttribute()
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
using System.ComponentModel;
|
||||
using System.Security;
|
||||
using System.Security.Permissions;
|
||||
using System.Security.Principal;
|
||||
using Microsoft.Win32;
|
||||
using Microsoft.Win32.SafeHandles;
|
||||
|
||||
namespace System
|
||||
{
|
||||
internal static class EnvironmentHelpers
|
||||
{
|
||||
private static volatile bool s_IsAppContainerProcess;
|
||||
private static volatile bool s_IsAppContainerProcessInitalized;
|
||||
|
||||
public static bool IsAppContainerProcess {
|
||||
get {
|
||||
if(!s_IsAppContainerProcessInitalized) {
|
||||
if(Environment.OSVersion.Platform != PlatformID.Win32NT) {
|
||||
s_IsAppContainerProcess = false;
|
||||
} else if(Environment.OSVersion.Version.Major < 6 || (Environment.OSVersion.Version.Major == 6 && Environment.OSVersion.Version.Minor <= 1)) {
|
||||
// Windows 7 or older.
|
||||
s_IsAppContainerProcess = false;
|
||||
} else {
|
||||
s_IsAppContainerProcess = HasAppContainerToken();
|
||||
}
|
||||
|
||||
s_IsAppContainerProcessInitalized = true;
|
||||
}
|
||||
|
||||
return s_IsAppContainerProcess;
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
[SecurityPermission(SecurityAction.Assert, Flags = SecurityPermissionFlag.UnmanagedCode | SecurityPermissionFlag.ControlPrincipal)]
|
||||
private static unsafe bool HasAppContainerToken() {
|
||||
int* dwIsAppContainerPtr = stackalloc int[1];
|
||||
uint dwLength = 0;
|
||||
|
||||
using (WindowsIdentity wi = WindowsIdentity.GetCurrent(TokenAccessLevels.Query)) {
|
||||
if (!UnsafeNativeMethods.GetTokenInformation(wi.Token, UnsafeNativeMethods.TokenIsAppContainer, new IntPtr(dwIsAppContainerPtr), sizeof(int), out dwLength)) {
|
||||
throw new Win32Exception();
|
||||
}
|
||||
}
|
||||
|
||||
return (*dwIsAppContainerPtr != 0);
|
||||
}
|
||||
|
||||
internal static bool IsWindowsVistaOrAbove()
|
||||
{
|
||||
// Method should match the logic of the internal Environment.IsWindowsVista property in mscorlib
|
||||
// If this method turns out to be heavily used we might want to cache at least part of this value.
|
||||
OperatingSystem os = Environment.OSVersion;
|
||||
return os.Platform == PlatformID.Win32NT && os.Version.Major >= 6;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace System.IO.Compression {
|
||||
internal enum BlockType {
|
||||
Uncompressed = 0,
|
||||
Static = 1,
|
||||
Dynamic = 2
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
///------------------------------------------------------------------------------
|
||||
/// <copyright file="CompressionLevel.cs" company="Microsoft">
|
||||
/// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
/// </copyright>
|
||||
///
|
||||
/// <owner>gpaperin</owner>
|
||||
///------------------------------------------------------------------------------
|
||||
|
||||
|
||||
namespace System.IO.Compression {
|
||||
|
||||
/// <summary>
|
||||
/// Defines a tradeoff between fast vs. strong compression. The specific meaning depends of the Deflater implementation.
|
||||
/// </summary>
|
||||
|
||||
// This is an abstract concept and NOT the ZLib compression level.
|
||||
// There may or may not be any correspondance with the a possible implementation-specific level-parameter of the deflater.
|
||||
public enum CompressionLevel {
|
||||
|
||||
Optimal = 0,
|
||||
Fastest = 1,
|
||||
NoCompression = 2
|
||||
|
||||
} // internal enum CompressionLevel
|
||||
|
||||
} // namespace System.IO.Compression
|
||||
|
||||
// CompressionLevel.cs
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
public enum CompressionMode {
|
||||
Decompress = 0,
|
||||
Compress = 1
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
internal enum CompressionTracingSwitchLevel {
|
||||
Off = 0,
|
||||
Informational = 1,
|
||||
Verbose = 2
|
||||
}
|
||||
|
||||
// No tracing on Silverlight nor Windows Phone 7.
|
||||
internal class CompressionTracingSwitch
|
||||
#if !FEATURE_NETCORE
|
||||
: Switch
|
||||
#endif // !FEATURE_NETCORE
|
||||
{
|
||||
internal readonly static CompressionTracingSwitch tracingSwitch =
|
||||
new CompressionTracingSwitch("CompressionSwitch", "Compression Library Tracing Switch");
|
||||
|
||||
internal CompressionTracingSwitch(string displayName, string description)
|
||||
#if !FEATURE_NETCORE
|
||||
: base(displayName, description)
|
||||
#endif // !FEATURE_NETCORE
|
||||
{
|
||||
}
|
||||
|
||||
public static bool Verbose {
|
||||
get {
|
||||
#if FEATURE_NETCORE
|
||||
return false;
|
||||
#else
|
||||
return tracingSwitch.SwitchSetting >= (int)CompressionTracingSwitchLevel.Verbose;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Informational {
|
||||
get {
|
||||
#if FEATURE_NETCORE
|
||||
return false;
|
||||
#else
|
||||
return tracingSwitch.SwitchSetting >= (int)CompressionTracingSwitchLevel.Informational;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if ENABLE_TRACING
|
||||
public void SetSwitchSetting(CompressionTracingSwitchLevel level) {
|
||||
if (level < CompressionTracingSwitchLevel.Off || level > CompressionTracingSwitchLevel.Verbose) {
|
||||
throw new ArgumentOutOfRangeException("level");
|
||||
}
|
||||
this.SwitchSetting = (int)level;
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
internal class CopyEncoder {
|
||||
|
||||
// padding for copy encoder formatting
|
||||
// - 1 byte for header
|
||||
// - 4 bytes for len, nlen
|
||||
private const int PaddingSize = 5;
|
||||
|
||||
// max uncompressed deflate block size is 64K.
|
||||
private const int MaxUncompressedBlockSize = 65536;
|
||||
|
||||
|
||||
// null input means write an empty payload with formatting info. This is needed for the final block.
|
||||
public void GetBlock(DeflateInput input, OutputBuffer output, bool isFinal) {
|
||||
Debug.Assert(output != null);
|
||||
Debug.Assert(output.FreeBytes >= PaddingSize);
|
||||
|
||||
// determine number of bytes to write
|
||||
int count = 0;
|
||||
if (input != null) {
|
||||
|
||||
// allow space for padding and bits not yet flushed to buffer
|
||||
count = Math.Min(input.Count, output.FreeBytes - PaddingSize - output.BitsInBuffer);
|
||||
|
||||
// we don't expect the output buffer to ever be this big (currently 4K), but we'll check this
|
||||
// just in case that changes.
|
||||
if (count > MaxUncompressedBlockSize - PaddingSize) {
|
||||
count = MaxUncompressedBlockSize - PaddingSize;
|
||||
}
|
||||
}
|
||||
|
||||
// write header and flush bits
|
||||
if (isFinal) {
|
||||
output.WriteBits(FastEncoderStatics.BFinalNoCompressionHeaderBitCount,
|
||||
FastEncoderStatics.BFinalNoCompressionHeader);
|
||||
}
|
||||
else {
|
||||
output.WriteBits(FastEncoderStatics.NoCompressionHeaderBitCount,
|
||||
FastEncoderStatics.NoCompressionHeader);
|
||||
}
|
||||
|
||||
// now we're aligned
|
||||
output.FlushBits();
|
||||
|
||||
// write len, nlen
|
||||
WriteLenNLen((ushort)count, output);
|
||||
|
||||
// write uncompressed bytes
|
||||
if (input != null && count > 0) {
|
||||
output.WriteBytes(input.Buffer, input.StartIndex, count);
|
||||
input.ConsumeBytes(count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void WriteLenNLen(ushort len, OutputBuffer output) {
|
||||
|
||||
// len
|
||||
output.WriteUInt16(len);
|
||||
|
||||
// nlen
|
||||
ushort onesComp = (ushort)(~(ushort)len);
|
||||
output.WriteUInt16(onesComp);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
|
||||
namespace System.IO.Compression
|
||||
{
|
||||
using System.Diagnostics;
|
||||
|
||||
|
||||
internal static class Crc32Helper
|
||||
{
|
||||
|
||||
// Table for CRC calculation
|
||||
static readonly uint[] crcTable = new uint[256] {
|
||||
0x00000000u, 0x77073096u, 0xee0e612cu, 0x990951bau, 0x076dc419u,
|
||||
0x706af48fu, 0xe963a535u, 0x9e6495a3u, 0x0edb8832u, 0x79dcb8a4u,
|
||||
0xe0d5e91eu, 0x97d2d988u, 0x09b64c2bu, 0x7eb17cbdu, 0xe7b82d07u,
|
||||
0x90bf1d91u, 0x1db71064u, 0x6ab020f2u, 0xf3b97148u, 0x84be41deu,
|
||||
0x1adad47du, 0x6ddde4ebu, 0xf4d4b551u, 0x83d385c7u, 0x136c9856u,
|
||||
0x646ba8c0u, 0xfd62f97au, 0x8a65c9ecu, 0x14015c4fu, 0x63066cd9u,
|
||||
0xfa0f3d63u, 0x8d080df5u, 0x3b6e20c8u, 0x4c69105eu, 0xd56041e4u,
|
||||
0xa2677172u, 0x3c03e4d1u, 0x4b04d447u, 0xd20d85fdu, 0xa50ab56bu,
|
||||
0x35b5a8fau, 0x42b2986cu, 0xdbbbc9d6u, 0xacbcf940u, 0x32d86ce3u,
|
||||
0x45df5c75u, 0xdcd60dcfu, 0xabd13d59u, 0x26d930acu, 0x51de003au,
|
||||
0xc8d75180u, 0xbfd06116u, 0x21b4f4b5u, 0x56b3c423u, 0xcfba9599u,
|
||||
0xb8bda50fu, 0x2802b89eu, 0x5f058808u, 0xc60cd9b2u, 0xb10be924u,
|
||||
0x2f6f7c87u, 0x58684c11u, 0xc1611dabu, 0xb6662d3du, 0x76dc4190u,
|
||||
0x01db7106u, 0x98d220bcu, 0xefd5102au, 0x71b18589u, 0x06b6b51fu,
|
||||
0x9fbfe4a5u, 0xe8b8d433u, 0x7807c9a2u, 0x0f00f934u, 0x9609a88eu,
|
||||
0xe10e9818u, 0x7f6a0dbbu, 0x086d3d2du, 0x91646c97u, 0xe6635c01u,
|
||||
0x6b6b51f4u, 0x1c6c6162u, 0x856530d8u, 0xf262004eu, 0x6c0695edu,
|
||||
0x1b01a57bu, 0x8208f4c1u, 0xf50fc457u, 0x65b0d9c6u, 0x12b7e950u,
|
||||
0x8bbeb8eau, 0xfcb9887cu, 0x62dd1ddfu, 0x15da2d49u, 0x8cd37cf3u,
|
||||
0xfbd44c65u, 0x4db26158u, 0x3ab551ceu, 0xa3bc0074u, 0xd4bb30e2u,
|
||||
0x4adfa541u, 0x3dd895d7u, 0xa4d1c46du, 0xd3d6f4fbu, 0x4369e96au,
|
||||
0x346ed9fcu, 0xad678846u, 0xda60b8d0u, 0x44042d73u, 0x33031de5u,
|
||||
0xaa0a4c5fu, 0xdd0d7cc9u, 0x5005713cu, 0x270241aau, 0xbe0b1010u,
|
||||
0xc90c2086u, 0x5768b525u, 0x206f85b3u, 0xb966d409u, 0xce61e49fu,
|
||||
0x5edef90eu, 0x29d9c998u, 0xb0d09822u, 0xc7d7a8b4u, 0x59b33d17u,
|
||||
0x2eb40d81u, 0xb7bd5c3bu, 0xc0ba6cadu, 0xedb88320u, 0x9abfb3b6u,
|
||||
0x03b6e20cu, 0x74b1d29au, 0xead54739u, 0x9dd277afu, 0x04db2615u,
|
||||
0x73dc1683u, 0xe3630b12u, 0x94643b84u, 0x0d6d6a3eu, 0x7a6a5aa8u,
|
||||
0xe40ecf0bu, 0x9309ff9du, 0x0a00ae27u, 0x7d079eb1u, 0xf00f9344u,
|
||||
0x8708a3d2u, 0x1e01f268u, 0x6906c2feu, 0xf762575du, 0x806567cbu,
|
||||
0x196c3671u, 0x6e6b06e7u, 0xfed41b76u, 0x89d32be0u, 0x10da7a5au,
|
||||
0x67dd4accu, 0xf9b9df6fu, 0x8ebeeff9u, 0x17b7be43u, 0x60b08ed5u,
|
||||
0xd6d6a3e8u, 0xa1d1937eu, 0x38d8c2c4u, 0x4fdff252u, 0xd1bb67f1u,
|
||||
0xa6bc5767u, 0x3fb506ddu, 0x48b2364bu, 0xd80d2bdau, 0xaf0a1b4cu,
|
||||
0x36034af6u, 0x41047a60u, 0xdf60efc3u, 0xa867df55u, 0x316e8eefu,
|
||||
0x4669be79u, 0xcb61b38cu, 0xbc66831au, 0x256fd2a0u, 0x5268e236u,
|
||||
0xcc0c7795u, 0xbb0b4703u, 0x220216b9u, 0x5505262fu, 0xc5ba3bbeu,
|
||||
0xb2bd0b28u, 0x2bb45a92u, 0x5cb36a04u, 0xc2d7ffa7u, 0xb5d0cf31u,
|
||||
0x2cd99e8bu, 0x5bdeae1du, 0x9b64c2b0u, 0xec63f226u, 0x756aa39cu,
|
||||
0x026d930au, 0x9c0906a9u, 0xeb0e363fu, 0x72076785u, 0x05005713u,
|
||||
0x95bf4a82u, 0xe2b87a14u, 0x7bb12baeu, 0x0cb61b38u, 0x92d28e9bu,
|
||||
0xe5d5be0du, 0x7cdcefb7u, 0x0bdbdf21u, 0x86d3d2d4u, 0xf1d4e242u,
|
||||
0x68ddb3f8u, 0x1fda836eu, 0x81be16cdu, 0xf6b9265bu, 0x6fb077e1u,
|
||||
0x18b74777u, 0x88085ae6u, 0xff0f6a70u, 0x66063bcau, 0x11010b5cu,
|
||||
0x8f659effu, 0xf862ae69u, 0x616bffd3u, 0x166ccf45u, 0xa00ae278u,
|
||||
0xd70dd2eeu, 0x4e048354u, 0x3903b3c2u, 0xa7672661u, 0xd06016f7u,
|
||||
0x4969474du, 0x3e6e77dbu, 0xaed16a4au, 0xd9d65adcu, 0x40df0b66u,
|
||||
0x37d83bf0u, 0xa9bcae53u, 0xdebb9ec5u, 0x47b2cf7fu, 0x30b5ffe9u,
|
||||
0xbdbdf21cu, 0xcabac28au, 0x53b39330u, 0x24b4a3a6u, 0xbad03605u,
|
||||
0xcdd70693u, 0x54de5729u, 0x23d967bfu, 0xb3667a2eu, 0xc4614ab8u,
|
||||
0x5d681b02u, 0x2a6f2b94u, 0xb40bbe37u, 0xc30c8ea1u, 0x5a05df1bu,
|
||||
0x2d02ef8du
|
||||
};
|
||||
|
||||
// Calculate CRC based on the old CRC and the new bytes
|
||||
// See RFC1952 for details.
|
||||
static public 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");
|
||||
|
||||
crc32 ^= 0xffffffffU;
|
||||
|
||||
while (--length >= 0)
|
||||
{
|
||||
crc32 = crcTable[(crc32 ^ buffer[offset++]) & 0xFF] ^ (crc32 >> 8);
|
||||
}
|
||||
|
||||
crc32 ^= 0xffffffffU;
|
||||
return crc32;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
namespace System.IO.Compression {
|
||||
using System.Diagnostics;
|
||||
|
||||
internal class DeflateInput {
|
||||
private byte[] buffer;
|
||||
private int count;
|
||||
private int startIndex;
|
||||
|
||||
internal byte[] Buffer {
|
||||
get {
|
||||
return buffer;
|
||||
}
|
||||
set {
|
||||
buffer = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal int Count {
|
||||
get {
|
||||
return count;
|
||||
}
|
||||
set {
|
||||
count = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal int StartIndex {
|
||||
get {
|
||||
return startIndex;
|
||||
}
|
||||
set {
|
||||
startIndex = value;
|
||||
}
|
||||
}
|
||||
|
||||
internal void ConsumeBytes(int n) {
|
||||
Debug.Assert(n <= count, "Should use more bytes than what we have in the buffer");
|
||||
startIndex += n;
|
||||
count -= n;
|
||||
Debug.Assert(startIndex + count <= buffer.Length, "Input buffer is in invalid state!");
|
||||
}
|
||||
|
||||
internal InputState DumpState() {
|
||||
InputState savedState;
|
||||
savedState.count = count;
|
||||
savedState.startIndex = startIndex;
|
||||
return savedState;
|
||||
}
|
||||
|
||||
internal void RestoreState(InputState state) {
|
||||
count = state.count;
|
||||
startIndex = state.startIndex;
|
||||
}
|
||||
|
||||
internal struct InputState {
|
||||
internal int count;
|
||||
internal int startIndex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,130 @@
|
||||
namespace System.IO.Compression {
|
||||
using System.Threading;
|
||||
|
||||
internal class DeflateStreamAsyncResult : IAsyncResult {
|
||||
public byte[] buffer;
|
||||
public int offset;
|
||||
public int count;
|
||||
// disable csharp compiler warning #0414: field assigned unused value
|
||||
#pragma warning disable 0414
|
||||
public bool isWrite;
|
||||
#pragma warning restore 0414
|
||||
|
||||
private object m_AsyncObject; // Caller's async object.
|
||||
private object m_AsyncState; // Caller's state object.
|
||||
private AsyncCallback m_AsyncCallback; // Caller's callback method.
|
||||
|
||||
private object m_Result; // Final IO result to be returned byt the End*() method.
|
||||
internal bool m_CompletedSynchronously; // true if the operation completed synchronously.
|
||||
private int m_InvokedCallback; // 0 is callback is not called
|
||||
private int m_Completed; // 0 if not completed >0 otherwise.
|
||||
private object m_Event; // lazy allocated event to be returned in the IAsyncResult for the client to wait on
|
||||
|
||||
public DeflateStreamAsyncResult(object asyncObject, object asyncState,
|
||||
AsyncCallback asyncCallback,
|
||||
byte[] buffer, int offset, int count) {
|
||||
|
||||
this.buffer = buffer;
|
||||
this.offset = offset;
|
||||
this.count = count;
|
||||
m_CompletedSynchronously = true;
|
||||
m_AsyncObject = asyncObject;
|
||||
m_AsyncState = asyncState;
|
||||
m_AsyncCallback = asyncCallback;
|
||||
}
|
||||
|
||||
// Interface method to return the caller's state object.
|
||||
public object AsyncState {
|
||||
get {
|
||||
return m_AsyncState;
|
||||
}
|
||||
}
|
||||
|
||||
// Interface property to return a WaitHandle that can be waited on for I/O completion.
|
||||
// This property implements lazy event creation.
|
||||
// the event object is only created when this property is accessed,
|
||||
// since we're internally only using callbacks, as long as the user is using
|
||||
// callbacks as well we will not create an event at all.
|
||||
public WaitHandle AsyncWaitHandle {
|
||||
get {
|
||||
// save a copy of the completion status
|
||||
int savedCompleted = m_Completed;
|
||||
if (m_Event == null) {
|
||||
// lazy allocation of the event:
|
||||
// if this property is never accessed this object is never created
|
||||
Interlocked.CompareExchange(ref m_Event, new ManualResetEvent(savedCompleted != 0), null);
|
||||
}
|
||||
|
||||
ManualResetEvent castedEvent = (ManualResetEvent)m_Event;
|
||||
if (savedCompleted == 0 && m_Completed != 0) {
|
||||
// if, while the event was created in the reset state,
|
||||
// the IO operation completed, set the event here.
|
||||
castedEvent.Set();
|
||||
}
|
||||
return castedEvent;
|
||||
}
|
||||
}
|
||||
|
||||
// Interface property, returning synchronous completion status.
|
||||
public bool CompletedSynchronously {
|
||||
get {
|
||||
return m_CompletedSynchronously;
|
||||
}
|
||||
}
|
||||
|
||||
// Interface property, returning completion status.
|
||||
public bool IsCompleted {
|
||||
get {
|
||||
return m_Completed != 0;
|
||||
}
|
||||
}
|
||||
|
||||
// Internal property for setting the IO result.
|
||||
internal object Result {
|
||||
get {
|
||||
return m_Result;
|
||||
}
|
||||
}
|
||||
|
||||
internal void Close() {
|
||||
if (m_Event != null) {
|
||||
((ManualResetEvent)m_Event).Close();
|
||||
}
|
||||
}
|
||||
|
||||
internal void InvokeCallback(bool completedSynchronously, object result) {
|
||||
Complete(completedSynchronously, result);
|
||||
}
|
||||
|
||||
internal void InvokeCallback(object result) {
|
||||
Complete(result);
|
||||
}
|
||||
|
||||
// Internal method for setting completion.
|
||||
// As a side effect, we'll signal the WaitHandle event and clean up.
|
||||
private void Complete(bool completedSynchronously, object result) {
|
||||
m_CompletedSynchronously = completedSynchronously;
|
||||
Complete(result);
|
||||
}
|
||||
|
||||
private void Complete(object result) {
|
||||
m_Result = result;
|
||||
|
||||
// Set IsCompleted and the event only after the usercallback method.
|
||||
Interlocked.Increment(ref m_Completed);
|
||||
|
||||
if (m_Event != null) {
|
||||
((ManualResetEvent)m_Event).Set();
|
||||
}
|
||||
|
||||
if (Interlocked.Increment(ref m_InvokedCallback) == 1) {
|
||||
if (m_AsyncCallback != null) {
|
||||
m_AsyncCallback(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,295 @@
|
||||
// ==++==
|
||||
//
|
||||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
//
|
||||
// zlib.h -- interface of the 'zlib' general purpose compression library
|
||||
// version 1.2.1, November 17th, 2003
|
||||
//
|
||||
// Copyright (C) 1995-2003 Jean-loup Gailly and Mark Adler
|
||||
//
|
||||
// This software is provided 'as-is', without any express or implied
|
||||
// warranty. In no event will the authors be held liable for any damages
|
||||
// arising from the use of this software.
|
||||
//
|
||||
// Permission is granted to anyone to use this software for any purpose,
|
||||
// including commercial applications, and to alter it and redistribute it
|
||||
// freely, subject to the following restrictions:
|
||||
//
|
||||
// 1. The origin of this software must not be misrepresented; you must not
|
||||
// claim that you wrote the original software. If you use this software
|
||||
// in a product, an acknowledgment in the product documentation would be
|
||||
// appreciated but is not required.
|
||||
// 2. Altered source versions must be plainly marked as such, and must not be
|
||||
// misrepresented as being the original software.
|
||||
// 3. This notice may not be removed or altered from any source distribution.
|
||||
//
|
||||
//
|
||||
// ==--==
|
||||
// Compression engine
|
||||
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
|
||||
namespace System.IO.Compression {
|
||||
|
||||
internal class DeflaterManaged : IDeflater {
|
||||
|
||||
private const int MinBlockSize = 256;
|
||||
private const int MaxHeaderFooterGoo = 120;
|
||||
private const int CleanCopySize = DeflateStream.DefaultBufferSize - MaxHeaderFooterGoo;
|
||||
private const double BadCompressionThreshold = 1.0;
|
||||
|
||||
private FastEncoder deflateEncoder;
|
||||
private CopyEncoder copyEncoder;
|
||||
|
||||
private DeflateInput input;
|
||||
private OutputBuffer output;
|
||||
private DeflaterState processingState;
|
||||
private DeflateInput inputFromHistory;
|
||||
|
||||
internal DeflaterManaged() {
|
||||
deflateEncoder = new FastEncoder();
|
||||
copyEncoder = new CopyEncoder();
|
||||
input = new DeflateInput();
|
||||
output = new OutputBuffer();
|
||||
|
||||
processingState = DeflaterState.NotStarted;
|
||||
}
|
||||
|
||||
private bool NeedsInput() {
|
||||
// Convenience method to call NeedsInput privately without a cast.
|
||||
return ((IDeflater) this).NeedsInput();
|
||||
}
|
||||
|
||||
bool IDeflater.NeedsInput() {
|
||||
return input.Count == 0 && deflateEncoder.BytesInHistory == 0;
|
||||
}
|
||||
|
||||
// Sets the input to compress. The only buffer copy occurs when the input is copied
|
||||
// to the FastEncoderWindow
|
||||
void IDeflater.SetInput(byte[] inputBuffer, int startIndex, int count) {
|
||||
|
||||
Debug.Assert(input.Count == 0, "We have something left in previous input!");
|
||||
|
||||
input.Buffer = inputBuffer;
|
||||
input.Count = count;
|
||||
input.StartIndex = startIndex;
|
||||
|
||||
if (count > 0 && count < MinBlockSize) {
|
||||
// user is writing small buffers. If buffer size is below MinBlockSize, we
|
||||
// need to switch to a small data mode, to avoid block headers and footers
|
||||
// dominating the output.
|
||||
switch (processingState) {
|
||||
case DeflaterState.NotStarted :
|
||||
case DeflaterState.CheckingForIncompressible:
|
||||
// clean states, needs a block header first
|
||||
processingState = DeflaterState.StartingSmallData;
|
||||
break;
|
||||
case DeflaterState.CompressThenCheck:
|
||||
// already has correct block header
|
||||
processingState = DeflaterState.HandlingSmallData;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int IDeflater.GetDeflateOutput(byte[] outputBuffer) {
|
||||
|
||||
Debug.Assert(outputBuffer != null, "Can't pass in a null output buffer!");
|
||||
Debug.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input");
|
||||
|
||||
output.UpdateBuffer(outputBuffer);
|
||||
|
||||
switch(processingState) {
|
||||
|
||||
case DeflaterState.NotStarted: {
|
||||
// first call. Try to compress but if we get bad compression ratio, switch to uncompressed blocks.
|
||||
Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window");
|
||||
|
||||
// save these in case we need to switch to uncompressed format
|
||||
DeflateInput.InputState initialInputState = input.DumpState();
|
||||
OutputBuffer.BufferState initialOutputState = output.DumpState();
|
||||
|
||||
deflateEncoder.GetBlockHeader(output);
|
||||
deflateEncoder.GetCompressedData(input, output);
|
||||
|
||||
if (!UseCompressed(deflateEncoder.LastCompressionRatio)) {
|
||||
// we're expanding; restore state and switch to uncompressed
|
||||
input.RestoreState(initialInputState);
|
||||
output.RestoreState(initialOutputState);
|
||||
copyEncoder.GetBlock(input, output, false);
|
||||
FlushInputWindows();
|
||||
processingState = DeflaterState.CheckingForIncompressible;
|
||||
}
|
||||
else {
|
||||
processingState = DeflaterState.CompressThenCheck;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case DeflaterState.CompressThenCheck: {
|
||||
// continue assuming data is compressible. If we reach data that indicates otherwise
|
||||
// finish off remaining data in history and decide whether to compress on a
|
||||
// block-by-block basis
|
||||
deflateEncoder.GetCompressedData(input, output);
|
||||
|
||||
if (!UseCompressed(deflateEncoder.LastCompressionRatio)) {
|
||||
processingState = DeflaterState.SlowDownForIncompressible1;
|
||||
inputFromHistory = deflateEncoder.UnprocessedInput;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case DeflaterState.SlowDownForIncompressible1: {
|
||||
// finish off previous compressed block
|
||||
deflateEncoder.GetBlockFooter(output);
|
||||
|
||||
processingState = DeflaterState.SlowDownForIncompressible2;
|
||||
goto case DeflaterState.SlowDownForIncompressible2; // yeah I know, but there's no fallthrough
|
||||
}
|
||||
|
||||
case DeflaterState.SlowDownForIncompressible2: {
|
||||
// clear out data from history, but add them as uncompressed blocks
|
||||
if (inputFromHistory.Count > 0) {
|
||||
copyEncoder.GetBlock(inputFromHistory, output, false);
|
||||
}
|
||||
|
||||
if (inputFromHistory.Count == 0) {
|
||||
// now we're clean
|
||||
deflateEncoder.FlushInput();
|
||||
processingState = DeflaterState.CheckingForIncompressible;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case DeflaterState.CheckingForIncompressible: {
|
||||
// decide whether to compress on a block-by-block basis
|
||||
Debug.Assert(deflateEncoder.BytesInHistory == 0, "have leftover bytes in window");
|
||||
|
||||
// save these in case we need to store as uncompressed
|
||||
DeflateInput.InputState initialInputState = input.DumpState();
|
||||
OutputBuffer.BufferState initialOutputState = output.DumpState();
|
||||
|
||||
// enforce max so we can ensure state between calls
|
||||
deflateEncoder.GetBlock(input, output, CleanCopySize);
|
||||
|
||||
if (!UseCompressed(deflateEncoder.LastCompressionRatio)) {
|
||||
// we're expanding; restore state and switch to uncompressed
|
||||
input.RestoreState(initialInputState);
|
||||
output.RestoreState(initialOutputState);
|
||||
copyEncoder.GetBlock(input, output, false);
|
||||
FlushInputWindows();
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
case DeflaterState.StartingSmallData: {
|
||||
// add compressed header and data, but not footer. Subsequent calls will keep
|
||||
// adding compressed data (no header and no footer). We're doing this to
|
||||
// avoid overhead of header and footer size relative to compressed payload.
|
||||
deflateEncoder.GetBlockHeader(output);
|
||||
|
||||
processingState = DeflaterState.HandlingSmallData;
|
||||
goto case DeflaterState.HandlingSmallData; // yeah I know, but there's no fallthrough
|
||||
}
|
||||
|
||||
case DeflaterState.HandlingSmallData: {
|
||||
// continue adding compressed data
|
||||
deflateEncoder.GetCompressedData(input, output);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return output.BytesWritten;
|
||||
}
|
||||
|
||||
bool IDeflater.Finish(byte[] outputBuffer, out int bytesRead) {
|
||||
Debug.Assert(outputBuffer != null, "Can't pass in a null output buffer!");
|
||||
Debug.Assert(processingState == DeflaterState.NotStarted ||
|
||||
processingState == DeflaterState.CheckingForIncompressible ||
|
||||
processingState == DeflaterState.HandlingSmallData ||
|
||||
processingState == DeflaterState.CompressThenCheck ||
|
||||
processingState == DeflaterState.SlowDownForIncompressible1,
|
||||
"got unexpected processing state = " + processingState);
|
||||
|
||||
Debug.Assert(NeedsInput());
|
||||
|
||||
// no need to add end of block info if we didn't write anything
|
||||
if (processingState == DeflaterState.NotStarted) {
|
||||
bytesRead = 0;
|
||||
return true;
|
||||
}
|
||||
|
||||
output.UpdateBuffer(outputBuffer);
|
||||
|
||||
if (processingState == DeflaterState.CompressThenCheck ||
|
||||
processingState == DeflaterState.HandlingSmallData ||
|
||||
processingState == DeflaterState.SlowDownForIncompressible1) {
|
||||
|
||||
// need to finish off block
|
||||
deflateEncoder.GetBlockFooter(output);
|
||||
}
|
||||
|
||||
// write final block
|
||||
WriteFinal();
|
||||
bytesRead = output.BytesWritten;
|
||||
return true;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose() { }
|
||||
protected void Dispose(bool disposing) { }
|
||||
|
||||
// Is compression ratio under threshold?
|
||||
private bool UseCompressed(double ratio) {
|
||||
return (ratio <= BadCompressionThreshold);
|
||||
}
|
||||
|
||||
private void FlushInputWindows() {
|
||||
deflateEncoder.FlushInput();
|
||||
}
|
||||
|
||||
private void WriteFinal() {
|
||||
copyEncoder.GetBlock(null, output, true);
|
||||
}
|
||||
|
||||
// These states allow us to assume that data is compressible and keep compression ratios at least
|
||||
// as good as historical values, but switch to different handling if that approach may increase the
|
||||
// data. If we detect we're getting a bad compression ratio, we switch to CheckingForIncompressible
|
||||
// state and decide to compress on a block by block basis.
|
||||
//
|
||||
// If we're getting small data buffers, we want to avoid overhead of excessive header and footer
|
||||
// info, so we add one header and keep adding blocks as compressed. This means that if the user uses
|
||||
// small buffers, they won't get the "don't increase size" improvements.
|
||||
//
|
||||
// An earlier iteration of this fix handled that data separately by buffering this data until it
|
||||
// reached a reasonable size, but given that Flush is not implemented on DeflateStream, this meant
|
||||
// data could be flushed only on Dispose. In the future, it would be reasonable to revisit this, in
|
||||
// case this isn't breaking.
|
||||
//
|
||||
// NotStarted -> CheckingForIncompressible, CompressThenCheck, StartingSmallData
|
||||
// CompressThenCheck -> SlowDownForIncompressible1
|
||||
// SlowDownForIncompressible1 -> SlowDownForIncompressible2
|
||||
// SlowDownForIncompressible2 -> CheckingForIncompressible
|
||||
// StartingSmallData -> HandlingSmallData
|
||||
private enum DeflaterState {
|
||||
|
||||
// no bytes to write yet
|
||||
NotStarted,
|
||||
|
||||
// transient states
|
||||
SlowDownForIncompressible1,
|
||||
SlowDownForIncompressible2,
|
||||
StartingSmallData,
|
||||
|
||||
// stable state: may transition to CheckingForIncompressible (via transient states) if it
|
||||
// appears we're expanding data
|
||||
CompressThenCheck,
|
||||
|
||||
// sink states
|
||||
CheckingForIncompressible,
|
||||
HandlingSmallData
|
||||
}
|
||||
|
||||
} // internal class DeflaterManaged
|
||||
} // namespace System.IO.Compression
|
||||
@@ -0,0 +1,280 @@
|
||||
///----------- ----------- ----------- ----------- ----------- ----------- -----------
|
||||
/// <copyright file="DeflaterZLib.cs" company="Microsoft">
|
||||
/// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
/// </copyright>
|
||||
///
|
||||
/// <owner>gpaperin</owner>
|
||||
///----------- ----------- ----------- ----------- ----------- ----------- -----------
|
||||
|
||||
using System.Diagnostics;
|
||||
using System.Diagnostics.Contracts;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
|
||||
using ZErrorCode = System.IO.Compression.ZLibNative.ErrorCode;
|
||||
using ZFlushCode = System.IO.Compression.ZLibNative.FlushCode;
|
||||
|
||||
|
||||
namespace System.IO.Compression {
|
||||
|
||||
#if FEATURE_NETCORE
|
||||
[SecuritySafeCritical]
|
||||
#endif
|
||||
internal class DeflaterZLib : IDeflater {
|
||||
|
||||
private ZLibNative.ZLibStreamHandle _zlibStream;
|
||||
private GCHandle? _inputBufferHandle;
|
||||
private bool _isDisposed;
|
||||
|
||||
// Note, DeflateStream or the deflater do not try to be thread safe.
|
||||
// The lock is just used to make writing to unmanaged structures atomic to make sure
|
||||
// that they do not get inconsistent fields that may lead to an unmanaged memory violation.
|
||||
// To prevent *managed* buffer corruption or other weird behaviour users need to synchronise
|
||||
// on the stream explicitly.
|
||||
private readonly Object syncLock = new Object();
|
||||
|
||||
#region exposed members
|
||||
|
||||
internal DeflaterZLib()
|
||||
|
||||
: this(CompressionLevel.Optimal) {
|
||||
}
|
||||
|
||||
internal DeflaterZLib(CompressionLevel compressionLevel) {
|
||||
|
||||
ZLibNative.CompressionLevel zlibCompressionLevel;
|
||||
int windowBits;
|
||||
int memLevel;
|
||||
ZLibNative.CompressionStrategy strategy;
|
||||
|
||||
switch (compressionLevel) {
|
||||
|
||||
// Note that ZLib currently exactly correspond to the optimal values.
|
||||
// However, we have determined the optimal values by intependent measurements across
|
||||
// a range of all possible ZLib parameters and over a set of different data.
|
||||
// We stress that by using explicitly the values obtained by the measurements rather than
|
||||
// ZLib defaults even if they happened to be the same.
|
||||
// For ZLib 1.2.3 we have (copied from ZLibNative.cs):
|
||||
// ZLibNative.CompressionLevel.DefaultCompression = 6;
|
||||
// ZLibNative.Deflate_DefaultWindowBits = -15;
|
||||
// ZLibNative.Deflate_DefaultMemLevel = 8;
|
||||
|
||||
|
||||
case CompressionLevel.Optimal:
|
||||
zlibCompressionLevel = (ZLibNative.CompressionLevel) 6;
|
||||
windowBits = -15;
|
||||
memLevel = 8;
|
||||
strategy = ZLibNative.CompressionStrategy.DefaultStrategy;
|
||||
break;
|
||||
|
||||
case CompressionLevel.Fastest:
|
||||
zlibCompressionLevel = (ZLibNative.CompressionLevel) 1;
|
||||
windowBits = -15;
|
||||
memLevel = 8;
|
||||
strategy = ZLibNative.CompressionStrategy.DefaultStrategy;
|
||||
break;
|
||||
|
||||
case CompressionLevel.NoCompression:
|
||||
zlibCompressionLevel = (ZLibNative.CompressionLevel) 0;
|
||||
windowBits = -15;
|
||||
memLevel = 7;
|
||||
strategy = ZLibNative.CompressionStrategy.DefaultStrategy;
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new ArgumentOutOfRangeException("compressionLevel");
|
||||
}
|
||||
|
||||
_isDisposed = false;
|
||||
DeflateInit(zlibCompressionLevel, windowBits, memLevel, strategy);
|
||||
}
|
||||
|
||||
void IDisposable.Dispose() {
|
||||
Dispose(true);
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
protected virtual void Dispose(bool disposing) {
|
||||
|
||||
if (disposing && !_isDisposed) {
|
||||
|
||||
if (_inputBufferHandle.HasValue)
|
||||
DeallocateInputBufferHandle();
|
||||
|
||||
_zlibStream.Dispose();
|
||||
_isDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
private bool NeedsInput() {
|
||||
// Convenience method to call NeedsInput privately without a cast.
|
||||
return ((IDeflater) this).NeedsInput();
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
bool IDeflater.NeedsInput() {
|
||||
return 0 == _zlibStream.AvailIn;
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
void IDeflater.SetInput(byte[] inputBuffer, int startIndex, int count) {
|
||||
|
||||
Contract.Assert(NeedsInput(), "We have something left in previous input!");
|
||||
Contract.Assert(null != inputBuffer);
|
||||
Contract.Assert(startIndex >= 0 && count >= 0 && count + startIndex <= inputBuffer.Length);
|
||||
Contract.Assert(!_inputBufferHandle.HasValue);
|
||||
|
||||
if (0 == count)
|
||||
return;
|
||||
|
||||
lock (syncLock) {
|
||||
|
||||
_inputBufferHandle = GCHandle.Alloc(inputBuffer, GCHandleType.Pinned);
|
||||
|
||||
_zlibStream.NextIn = _inputBufferHandle.Value.AddrOfPinnedObject() + startIndex;
|
||||
_zlibStream.AvailIn = (uint) count;
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
int IDeflater.GetDeflateOutput(byte[] outputBuffer) {
|
||||
|
||||
Contract.Ensures(Contract.Result<int>() >= 0 && Contract.Result<int>() <= outputBuffer.Length);
|
||||
|
||||
Contract.Assert(null != outputBuffer, "Can't pass in a null output buffer!");
|
||||
Contract.Assert(!NeedsInput(), "GetDeflateOutput should only be called after providing input");
|
||||
Contract.Assert(_inputBufferHandle.HasValue);
|
||||
Contract.Assert(_inputBufferHandle.Value.IsAllocated);
|
||||
|
||||
try {
|
||||
int bytesRead;
|
||||
ReadDeflateOutput(outputBuffer, ZFlushCode.NoFlush, out bytesRead);
|
||||
return bytesRead;
|
||||
|
||||
} finally {
|
||||
// Before returning, make sure to release input buffer if necesary:
|
||||
if (0 == _zlibStream.AvailIn && _inputBufferHandle.HasValue)
|
||||
DeallocateInputBufferHandle();
|
||||
}
|
||||
}
|
||||
|
||||
private ZErrorCode ReadDeflateOutput(byte[] outputBuffer, ZFlushCode flushCode, out int bytesRead) {
|
||||
|
||||
lock (syncLock) {
|
||||
|
||||
GCHandle outputBufferHndl = GCHandle.Alloc(outputBuffer, GCHandleType.Pinned);
|
||||
|
||||
try {
|
||||
|
||||
|
||||
_zlibStream.NextOut = outputBufferHndl.AddrOfPinnedObject();
|
||||
_zlibStream.AvailOut = (uint) outputBuffer.Length;
|
||||
|
||||
ZErrorCode errC = Deflate(flushCode);
|
||||
bytesRead = outputBuffer.Length - (int) _zlibStream.AvailOut;
|
||||
|
||||
return errC;
|
||||
|
||||
} finally {
|
||||
outputBufferHndl.Free();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool IDeflater.Finish(byte[] outputBuffer, out int bytesRead) {
|
||||
|
||||
Contract.Assert(null != outputBuffer, "Can't pass in a null output buffer!");
|
||||
Contract.Assert(NeedsInput(), "We have something left in previous input!");
|
||||
Contract.Assert(!_inputBufferHandle.HasValue);
|
||||
|
||||
// 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
|
||||
// should be calling GetDeflateOutput.
|
||||
|
||||
ZErrorCode errC = ReadDeflateOutput(outputBuffer, ZFlushCode.Finish, out bytesRead);
|
||||
return errC == ZErrorCode.StreamEnd;
|
||||
}
|
||||
|
||||
#endregion // exposed functions
|
||||
|
||||
|
||||
#region helpers & native call wrappers
|
||||
|
||||
private void DeallocateInputBufferHandle() {
|
||||
|
||||
Contract.Assert(_inputBufferHandle.HasValue);
|
||||
Contract.Assert(_inputBufferHandle.Value.IsAllocated);
|
||||
|
||||
lock(syncLock) {
|
||||
_zlibStream.AvailIn = 0;
|
||||
_zlibStream.NextIn = ZLibNative.ZNullPtr;
|
||||
_inputBufferHandle.Value.Free();
|
||||
_inputBufferHandle = null;
|
||||
}
|
||||
}
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private void DeflateInit(ZLibNative.CompressionLevel compressionLevel, int windowBits, int memLevel,
|
||||
ZLibNative.CompressionStrategy strategy) {
|
||||
|
||||
ZErrorCode errC;
|
||||
try {
|
||||
errC = ZLibNative.CreateZLibStreamForDeflate(out _zlibStream, compressionLevel,
|
||||
windowBits, memLevel, strategy);
|
||||
} catch (Exception cause) {
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorDLLLoadError), cause);
|
||||
}
|
||||
|
||||
switch (errC) {
|
||||
|
||||
case ZErrorCode.Ok:
|
||||
return;
|
||||
|
||||
case ZErrorCode.MemError:
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorNotEnoughMemory), "deflateInit2_", (int) errC, _zlibStream.GetErrorMessage());
|
||||
|
||||
case ZErrorCode.VersionError:
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorVersionMismatch), "deflateInit2_", (int) errC, _zlibStream.GetErrorMessage());
|
||||
|
||||
case ZErrorCode.StreamError:
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorIncorrectInitParameters), "deflateInit2_", (int) errC, _zlibStream.GetErrorMessage());
|
||||
|
||||
default:
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorUnexpected), "deflateInit2_", (int) errC, _zlibStream.GetErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
[SecuritySafeCritical]
|
||||
private ZErrorCode Deflate(ZFlushCode flushCode) {
|
||||
|
||||
ZErrorCode errC;
|
||||
try {
|
||||
errC = _zlibStream.Deflate(flushCode);
|
||||
} catch (Exception cause) {
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorDLLLoadError), cause);
|
||||
}
|
||||
|
||||
switch (errC) {
|
||||
|
||||
case ZErrorCode.Ok:
|
||||
case ZErrorCode.StreamEnd:
|
||||
return errC;
|
||||
|
||||
case ZErrorCode.BufError:
|
||||
return errC; // This is a recoverable error
|
||||
|
||||
case ZErrorCode.StreamError:
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorInconsistentStream), "deflate", (int) errC, _zlibStream.GetErrorMessage());
|
||||
|
||||
default:
|
||||
throw new ZLibException(SR.GetString(SR.ZLibErrorUnexpected), "deflate", (int) errC, _zlibStream.GetErrorMessage());
|
||||
}
|
||||
}
|
||||
|
||||
#endregion // helpers & native call wrappers
|
||||
|
||||
} // internal class DeflaterZLib
|
||||
} // namespace System.IO.Compression
|
||||
|
||||
// file DeflaterZLib.cs
|
||||
@@ -0,0 +1,182 @@
|
||||
namespace System.IO.Compression {
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
internal class FastEncoder {
|
||||
|
||||
private FastEncoderWindow inputWindow; // input history window
|
||||
private Match currentMatch; // current match in history window
|
||||
private double lastCompressionRatio;
|
||||
|
||||
public FastEncoder() {
|
||||
inputWindow = new FastEncoderWindow();
|
||||
currentMatch = new Match();
|
||||
}
|
||||
|
||||
internal int BytesInHistory {
|
||||
get {
|
||||
return inputWindow.BytesAvailable;
|
||||
}
|
||||
}
|
||||
|
||||
internal DeflateInput UnprocessedInput {
|
||||
get {
|
||||
return inputWindow.UnprocessedInput;
|
||||
}
|
||||
}
|
||||
|
||||
internal void FlushInput() {
|
||||
inputWindow.FlushWindow();
|
||||
}
|
||||
|
||||
internal Double LastCompressionRatio {
|
||||
get { return lastCompressionRatio; }
|
||||
}
|
||||
|
||||
// Copy the compressed bytes to output buffer as a block. maxBytesToCopy limits the number of
|
||||
// bytes we can copy from input. Set to any value < 1 if no limit
|
||||
internal void GetBlock(DeflateInput input, OutputBuffer output, int maxBytesToCopy) {
|
||||
Debug.Assert(InputAvailable(input), "call SetInput before trying to compress!");
|
||||
|
||||
WriteDeflatePreamble(output);
|
||||
GetCompressedOutput(input, output, maxBytesToCopy);
|
||||
WriteEndOfBlock(output);
|
||||
}
|
||||
|
||||
// Compress data but don't format as block (doesn't have header and footer)
|
||||
internal void GetCompressedData(DeflateInput input, OutputBuffer output) {
|
||||
GetCompressedOutput(input, output, -1);
|
||||
}
|
||||
|
||||
internal void GetBlockHeader(OutputBuffer output) {
|
||||
WriteDeflatePreamble(output);
|
||||
}
|
||||
|
||||
internal void GetBlockFooter(OutputBuffer output) {
|
||||
WriteEndOfBlock(output);
|
||||
}
|
||||
|
||||
// maxBytesToCopy limits the number of bytes we can copy from input. Set to any value < 1 if no limit
|
||||
private void GetCompressedOutput(DeflateInput input, OutputBuffer output, int maxBytesToCopy) {
|
||||
// snapshot for compression ratio stats
|
||||
int bytesWrittenPre = output.BytesWritten;
|
||||
int bytesConsumedFromInput = 0;
|
||||
int inputBytesPre = BytesInHistory + input.Count;
|
||||
|
||||
do {
|
||||
// read more input data into the window if there is space available
|
||||
int bytesToCopy = (input.Count < inputWindow.FreeWindowSpace) ?
|
||||
input.Count : inputWindow.FreeWindowSpace;
|
||||
if (maxBytesToCopy >= 1) {
|
||||
bytesToCopy = Math.Min(bytesToCopy, maxBytesToCopy - bytesConsumedFromInput);
|
||||
}
|
||||
if (bytesToCopy > 0) {
|
||||
// copy data into history window
|
||||
inputWindow.CopyBytes(input.Buffer, input.StartIndex, bytesToCopy);
|
||||
input.ConsumeBytes(bytesToCopy);
|
||||
bytesConsumedFromInput += bytesToCopy;
|
||||
}
|
||||
|
||||
GetCompressedOutput(output);
|
||||
|
||||
} while (SafeToWriteTo(output) && InputAvailable(input) && (maxBytesToCopy < 1 || bytesConsumedFromInput < maxBytesToCopy));
|
||||
|
||||
// determine compression ratio, save
|
||||
int bytesWrittenPost = output.BytesWritten;
|
||||
int bytesWritten = bytesWrittenPost - bytesWrittenPre;
|
||||
int inputBytesPost = BytesInHistory + input.Count;
|
||||
int totalBytesConsumed = inputBytesPre - inputBytesPost;
|
||||
if (bytesWritten != 0) {
|
||||
lastCompressionRatio = (double)bytesWritten / (double)totalBytesConsumed;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// compress the bytes in input history window
|
||||
private void GetCompressedOutput(OutputBuffer output) {
|
||||
|
||||
while (inputWindow.BytesAvailable > 0 && SafeToWriteTo(output)) {
|
||||
|
||||
// Find next match. A match can be a symbol,
|
||||
// a distance/length pair, a symbol followed by a distance/Length pair
|
||||
inputWindow.GetNextSymbolOrMatch(currentMatch);
|
||||
|
||||
if (currentMatch.State == MatchState.HasSymbol) {
|
||||
WriteChar(currentMatch.Symbol, output);
|
||||
}
|
||||
else if (currentMatch.State == MatchState.HasMatch) {
|
||||
WriteMatch(currentMatch.Length, currentMatch.Position, output);
|
||||
}
|
||||
else {
|
||||
WriteChar(currentMatch.Symbol, output);
|
||||
WriteMatch(currentMatch.Length, currentMatch.Position, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool InputAvailable(DeflateInput input) {
|
||||
return input.Count > 0 || BytesInHistory > 0;
|
||||
}
|
||||
|
||||
private bool SafeToWriteTo(OutputBuffer output) { // can we safely continue writing to output buffer
|
||||
return output.FreeBytes > FastEncoderStatics.MaxCodeLen;
|
||||
}
|
||||
|
||||
private void WriteEndOfBlock(OutputBuffer output) {
|
||||
// The fast encoder outputs one long block, so it just needs to terminate this block
|
||||
const int EndOfBlockCode = 256;
|
||||
uint code_info = FastEncoderStatics.FastEncoderLiteralCodeInfo[EndOfBlockCode];
|
||||
int code_len = (int)(code_info & 31);
|
||||
output.WriteBits(code_len, code_info >> 5);
|
||||
}
|
||||
|
||||
static internal void WriteMatch(int matchLen, int matchPos, OutputBuffer output) {
|
||||
Debug.Assert(matchLen >= FastEncoderWindow.MinMatch && matchLen <= FastEncoderWindow.MaxMatch, "Illegal currentMatch length!");
|
||||
Debug.WriteLineIf(CompressionTracingSwitch.Verbose, String.Format(CultureInfo.InvariantCulture, "Match: {0}:{1}", matchLen, matchPos), "Compression");
|
||||
|
||||
// Get the code information for a match code
|
||||
uint codeInfo = FastEncoderStatics.FastEncoderLiteralCodeInfo[(FastEncoderStatics.NumChars + 1 - FastEncoderWindow.MinMatch) + matchLen];
|
||||
int codeLen = (int)codeInfo & 31;
|
||||
Debug.Assert(codeLen != 0, "Invalid Match Length!");
|
||||
if (codeLen <= 16) {
|
||||
output.WriteBits(codeLen, codeInfo >> 5);
|
||||
}
|
||||
else {
|
||||
output.WriteBits(16, (codeInfo >> 5) & 65535);
|
||||
output.WriteBits(codeLen - 16, codeInfo >> (5 + 16));
|
||||
}
|
||||
|
||||
// Get the code information for a distance code
|
||||
codeInfo = FastEncoderStatics.FastEncoderDistanceCodeInfo[FastEncoderStatics.GetSlot(matchPos)];
|
||||
output.WriteBits((int)(codeInfo & 15), codeInfo >> 8);
|
||||
int extraBits = (int)(codeInfo >> 4) & 15;
|
||||
if (extraBits != 0) {
|
||||
output.WriteBits(extraBits, (uint)matchPos & FastEncoderStatics.BitMask[extraBits]);
|
||||
}
|
||||
}
|
||||
|
||||
static internal void WriteChar(byte b, OutputBuffer output) {
|
||||
Debug.WriteLineIf(CompressionTracingSwitch.Verbose, String.Format(CultureInfo.InvariantCulture, "Literal: {0}", b ), "Compression");
|
||||
|
||||
uint code = FastEncoderStatics.FastEncoderLiteralCodeInfo[b];
|
||||
output.WriteBits((int)code & 31, code >> 5);
|
||||
}
|
||||
|
||||
// Output the block type and tree structure for our hard-coded trees.
|
||||
// Contains following data:
|
||||
// "final" block flag 1 bit
|
||||
// BLOCKTYPE_DYNAMIC 2 bits
|
||||
// FastEncoderLiteralTreeLength
|
||||
// FastEncoderDistanceTreeLength
|
||||
//
|
||||
static internal void WriteDeflatePreamble(OutputBuffer output) {
|
||||
//Debug.Assert( bitCount == 0, "bitCount must be zero before writing tree bit!");
|
||||
|
||||
output.WriteBytes(FastEncoderStatics.FastEncoderTreeStructureData, 0, FastEncoderStatics.FastEncoderTreeStructureData.Length);
|
||||
output.WriteBits(FastEncoderStatics.FastEncoderPostTreeBitCount, FastEncoderStatics.FastEncoderPostTreeBitBuf);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,232 @@
|
||||
namespace System.IO.Compression {
|
||||
using System.Diagnostics;
|
||||
using System.Globalization;
|
||||
|
||||
internal static class FastEncoderStatics {
|
||||
// static information for encoding, DO NOT MODIFY
|
||||
|
||||
internal static readonly byte[] FastEncoderTreeStructureData = {
|
||||
0xec,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca,
|
||||
0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60,
|
||||
0x13,0x24,0xd8,0x90,0x40,0x10,0xec,0xc1,0x88,0xcd,0xe6,0x92,
|
||||
0xec,0x1d,0x69,0x47,0x23,0x29,0xab,0x2a,0x81,0xca,0x65,0x56,
|
||||
0x65,0x5d,0x66,0x16,0x40,0xcc,0xed,0x9d,0xbc,0xf7,0xde,0x7b,
|
||||
0xef,0xbd,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xba,0x3b,0x9d,0x4e,
|
||||
0x27,0xf7,0xdf,0xff,0x3f,0x5c,0x66,0x64,0x01,0x6c,0xf6,0xce,
|
||||
0x4a,0xda,0xc9,0x9e,0x21,0x80,0xaa,0xc8,0x1f,0x3f,0x7e,0x7c,
|
||||
0x1f,0x3f,
|
||||
};
|
||||
|
||||
internal static readonly byte[] BFinalFastEncoderTreeStructureData = {
|
||||
0xed,0xbd,0x07,0x60,0x1c,0x49,0x96,0x25,0x26,0x2f,0x6d,0xca,
|
||||
0x7b,0x7f,0x4a,0xf5,0x4a,0xd7,0xe0,0x74,0xa1,0x08,0x80,0x60,
|
||||
0x13,0x24,0xd8,0x90,0x40,0x10,0xec,0xc1,0x88,0xcd,0xe6,0x92,
|
||||
0xec,0x1d,0x69,0x47,0x23,0x29,0xab,0x2a,0x81,0xca,0x65,0x56,
|
||||
0x65,0x5d,0x66,0x16,0x40,0xcc,0xed,0x9d,0xbc,0xf7,0xde,0x7b,
|
||||
0xef,0xbd,0xf7,0xde,0x7b,0xef,0xbd,0xf7,0xba,0x3b,0x9d,0x4e,
|
||||
0x27,0xf7,0xdf,0xff,0x3f,0x5c,0x66,0x64,0x01,0x6c,0xf6,0xce,
|
||||
0x4a,0xda,0xc9,0x9e,0x21,0x80,0xaa,0xc8,0x1f,0x3f,0x7e,0x7c,
|
||||
0x1f,0x3f,
|
||||
};
|
||||
|
||||
// Output a currentMatch with length matchLen (>= MIN_MATCH) and displacement matchPos
|
||||
//
|
||||
// Optimisation: unlike the other encoders, here we have an array of codes for each currentMatch
|
||||
// length (not just each currentMatch length slot), complete with all the extra bits filled in, in
|
||||
// a single array element.
|
||||
//
|
||||
// There are many advantages to doing this:
|
||||
//
|
||||
// 1. A single array lookup on g_FastEncoderLiteralCodeInfo, instead of separate array lookups
|
||||
// on g_LengthLookup (to get the length slot), g_FastEncoderLiteralTreeLength,
|
||||
// g_FastEncoderLiteralTreeCode, g_ExtraLengthBits, and g_BitMask
|
||||
//
|
||||
// 2. The array is an array of ULONGs, so no access penalty, unlike for accessing those USHORT
|
||||
// code arrays in the other encoders (although they could be made into ULONGs with some
|
||||
// modifications to the source).
|
||||
//
|
||||
// Note, if we could guarantee that codeLen <= 16 always, then we could skip an if statement here.
|
||||
//
|
||||
// A completely different optimisation is used for the distance codes since, obviously, a table for
|
||||
// all 8192 distances combining their extra bits is not feasible. The distance codeinfo table is
|
||||
// made up of code[], len[] and # extraBits for this code.
|
||||
//
|
||||
// The advantages are similar to the above; a ULONG array instead of a USHORT and BYTE array, better
|
||||
// cache locality, fewer memory operations.
|
||||
//
|
||||
|
||||
|
||||
// Encoding information for literal and Length.
|
||||
// The least 5 significant bits are the length
|
||||
// and the rest is the code bits.
|
||||
|
||||
internal static readonly uint[] FastEncoderLiteralCodeInfo = {
|
||||
0x0000d7ee,0x0004d7ee,0x0002d7ee,0x0006d7ee,0x0001d7ee,0x0005d7ee,0x0003d7ee,
|
||||
0x0007d7ee,0x000037ee,0x0000c7ec,0x00000126,0x000437ee,0x000237ee,0x000637ee,
|
||||
0x000137ee,0x000537ee,0x000337ee,0x000737ee,0x0000b7ee,0x0004b7ee,0x0002b7ee,
|
||||
0x0006b7ee,0x0001b7ee,0x0005b7ee,0x0003b7ee,0x0007b7ee,0x000077ee,0x000477ee,
|
||||
0x000277ee,0x000677ee,0x000017ed,0x000177ee,0x00000526,0x000577ee,0x000023ea,
|
||||
0x0001c7ec,0x000377ee,0x000777ee,0x000217ed,0x000063ea,0x00000b68,0x00000ee9,
|
||||
0x00005beb,0x000013ea,0x00000467,0x00001b68,0x00000c67,0x00002ee9,0x00000768,
|
||||
0x00001768,0x00000f68,0x00001ee9,0x00001f68,0x00003ee9,0x000053ea,0x000001e9,
|
||||
0x000000e8,0x000021e9,0x000011e9,0x000010e8,0x000031e9,0x000033ea,0x000008e8,
|
||||
0x0000f7ee,0x0004f7ee,0x000018e8,0x000009e9,0x000004e8,0x000029e9,0x000014e8,
|
||||
0x000019e9,0x000073ea,0x0000dbeb,0x00000ce8,0x00003beb,0x0002f7ee,0x000039e9,
|
||||
0x00000bea,0x000005e9,0x00004bea,0x000025e9,0x000027ec,0x000015e9,0x000035e9,
|
||||
0x00000de9,0x00002bea,0x000127ec,0x0000bbeb,0x0006f7ee,0x0001f7ee,0x0000a7ec,
|
||||
0x00007beb,0x0005f7ee,0x0000fbeb,0x0003f7ee,0x0007f7ee,0x00000fee,0x00000326,
|
||||
0x00000267,0x00000a67,0x00000667,0x00000726,0x00001ce8,0x000002e8,0x00000e67,
|
||||
0x000000a6,0x0001a7ec,0x00002de9,0x000004a6,0x00000167,0x00000967,0x000002a6,
|
||||
0x00000567,0x000117ed,0x000006a6,0x000001a6,0x000005a6,0x00000d67,0x000012e8,
|
||||
0x00000ae8,0x00001de9,0x00001ae8,0x000007eb,0x000317ed,0x000067ec,0x000097ed,
|
||||
0x000297ed,0x00040fee,0x00020fee,0x00060fee,0x00010fee,0x00050fee,0x00030fee,
|
||||
0x00070fee,0x00008fee,0x00048fee,0x00028fee,0x00068fee,0x00018fee,0x00058fee,
|
||||
0x00038fee,0x00078fee,0x00004fee,0x00044fee,0x00024fee,0x00064fee,0x00014fee,
|
||||
0x00054fee,0x00034fee,0x00074fee,0x0000cfee,0x0004cfee,0x0002cfee,0x0006cfee,
|
||||
0x0001cfee,0x0005cfee,0x0003cfee,0x0007cfee,0x00002fee,0x00042fee,0x00022fee,
|
||||
0x00062fee,0x00012fee,0x00052fee,0x00032fee,0x00072fee,0x0000afee,0x0004afee,
|
||||
0x0002afee,0x0006afee,0x0001afee,0x0005afee,0x0003afee,0x0007afee,0x00006fee,
|
||||
0x00046fee,0x00026fee,0x00066fee,0x00016fee,0x00056fee,0x00036fee,0x00076fee,
|
||||
0x0000efee,0x0004efee,0x0002efee,0x0006efee,0x0001efee,0x0005efee,0x0003efee,
|
||||
0x0007efee,0x00001fee,0x00041fee,0x00021fee,0x00061fee,0x00011fee,0x00051fee,
|
||||
0x00031fee,0x00071fee,0x00009fee,0x00049fee,0x00029fee,0x00069fee,0x00019fee,
|
||||
0x00059fee,0x00039fee,0x00079fee,0x00005fee,0x00045fee,0x00025fee,0x00065fee,
|
||||
0x00015fee,0x00055fee,0x00035fee,0x00075fee,0x0000dfee,0x0004dfee,0x0002dfee,
|
||||
0x0006dfee,0x0001dfee,0x0005dfee,0x0003dfee,0x0007dfee,0x00003fee,0x00043fee,
|
||||
0x00023fee,0x00063fee,0x00013fee,0x00053fee,0x00033fee,0x00073fee,0x0000bfee,
|
||||
0x0004bfee,0x0002bfee,0x0006bfee,0x0001bfee,0x0005bfee,0x0003bfee,0x0007bfee,
|
||||
0x00007fee,0x00047fee,0x00027fee,0x00067fee,0x00017fee,0x000197ed,0x000397ed,
|
||||
0x000057ed,0x00057fee,0x000257ed,0x00037fee,0x000157ed,0x00077fee,0x000357ed,
|
||||
0x0000ffee,0x0004ffee,0x0002ffee,0x0006ffee,0x0001ffee,0x00000084,0x00000003,
|
||||
0x00000184,0x00000044,0x00000144,0x000000c5,0x000002c5,0x000001c5,0x000003c6,
|
||||
0x000007c6,0x00000026,0x00000426,0x000003a7,0x00000ba7,0x000007a7,0x00000fa7,
|
||||
0x00000227,0x00000627,0x00000a27,0x00000e27,0x00000068,0x00000868,0x00001068,
|
||||
0x00001868,0x00000369,0x00001369,0x00002369,0x00003369,0x000006ea,0x000026ea,
|
||||
0x000046ea,0x000066ea,0x000016eb,0x000036eb,0x000056eb,0x000076eb,0x000096eb,
|
||||
0x0000b6eb,0x0000d6eb,0x0000f6eb,0x00003dec,0x00007dec,0x0000bdec,0x0000fdec,
|
||||
0x00013dec,0x00017dec,0x0001bdec,0x0001fdec,0x00006bed,0x0000ebed,0x00016bed,
|
||||
0x0001ebed,0x00026bed,0x0002ebed,0x00036bed,0x0003ebed,0x000003ec,0x000043ec,
|
||||
0x000083ec,0x0000c3ec,0x000103ec,0x000143ec,0x000183ec,0x0001c3ec,0x00001bee,
|
||||
0x00009bee,0x00011bee,0x00019bee,0x00021bee,0x00029bee,0x00031bee,0x00039bee,
|
||||
0x00041bee,0x00049bee,0x00051bee,0x00059bee,0x00061bee,0x00069bee,0x00071bee,
|
||||
0x00079bee,0x000167f0,0x000367f0,0x000567f0,0x000767f0,0x000967f0,0x000b67f0,
|
||||
0x000d67f0,0x000f67f0,0x001167f0,0x001367f0,0x001567f0,0x001767f0,0x001967f0,
|
||||
0x001b67f0,0x001d67f0,0x001f67f0,0x000087ef,0x000187ef,0x000287ef,0x000387ef,
|
||||
0x000487ef,0x000587ef,0x000687ef,0x000787ef,0x000887ef,0x000987ef,0x000a87ef,
|
||||
0x000b87ef,0x000c87ef,0x000d87ef,0x000e87ef,0x000f87ef,0x0000e7f0,0x0002e7f0,
|
||||
0x0004e7f0,0x0006e7f0,0x0008e7f0,0x000ae7f0,0x000ce7f0,0x000ee7f0,0x0010e7f0,
|
||||
0x0012e7f0,0x0014e7f0,0x0016e7f0,0x0018e7f0,0x001ae7f0,0x001ce7f0,0x001ee7f0,
|
||||
0x0005fff3,0x000dfff3,0x0015fff3,0x001dfff3,0x0025fff3,0x002dfff3,0x0035fff3,
|
||||
0x003dfff3,0x0045fff3,0x004dfff3,0x0055fff3,0x005dfff3,0x0065fff3,0x006dfff3,
|
||||
0x0075fff3,0x007dfff3,0x0085fff3,0x008dfff3,0x0095fff3,0x009dfff3,0x00a5fff3,
|
||||
0x00adfff3,0x00b5fff3,0x00bdfff3,0x00c5fff3,0x00cdfff3,0x00d5fff3,0x00ddfff3,
|
||||
0x00e5fff3,0x00edfff3,0x00f5fff3,0x00fdfff3,0x0003fff3,0x000bfff3,0x0013fff3,
|
||||
0x001bfff3,0x0023fff3,0x002bfff3,0x0033fff3,0x003bfff3,0x0043fff3,0x004bfff3,
|
||||
0x0053fff3,0x005bfff3,0x0063fff3,0x006bfff3,0x0073fff3,0x007bfff3,0x0083fff3,
|
||||
0x008bfff3,0x0093fff3,0x009bfff3,0x00a3fff3,0x00abfff3,0x00b3fff3,0x00bbfff3,
|
||||
0x00c3fff3,0x00cbfff3,0x00d3fff3,0x00dbfff3,0x00e3fff3,0x00ebfff3,0x00f3fff3,
|
||||
0x00fbfff3,0x0007fff3,0x000ffff3,0x0017fff3,0x001ffff3,0x0027fff3,0x002ffff3,
|
||||
0x0037fff3,0x003ffff3,0x0047fff3,0x004ffff3,0x0057fff3,0x005ffff3,0x0067fff3,
|
||||
0x006ffff3,0x0077fff3,0x007ffff3,0x0087fff3,0x008ffff3,0x0097fff3,0x009ffff3,
|
||||
0x00a7fff3,0x00affff3,0x00b7fff3,0x00bffff3,0x00c7fff3,0x00cffff3,0x00d7fff3,
|
||||
0x00dffff3,0x00e7fff3,0x00effff3,0x00f7fff3,0x00fffff3,0x0001e7f1,0x0003e7f1,
|
||||
0x0005e7f1,0x0007e7f1,0x0009e7f1,0x000be7f1,0x000de7f1,0x000fe7f1,0x0011e7f1,
|
||||
0x0013e7f1,0x0015e7f1,0x0017e7f1,0x0019e7f1,0x001be7f1,0x001de7f1,0x001fe7f1,
|
||||
0x0021e7f1,0x0023e7f1,0x0025e7f1,0x0027e7f1,0x0029e7f1,0x002be7f1,0x002de7f1,
|
||||
0x002fe7f1,0x0031e7f1,0x0033e7f1,0x0035e7f1,0x0037e7f1,0x0039e7f1,0x003be7f1,
|
||||
0x003de7f1,0x000047eb,
|
||||
};
|
||||
|
||||
internal static readonly uint[] FastEncoderDistanceCodeInfo = {
|
||||
0x00000f06,0x0001ff0a,0x0003ff0b,0x0007ff0b,0x0000ff19,0x00003f18,0x0000bf28,
|
||||
0x00007f28,0x00001f37,0x00005f37,0x00000d45,0x00002f46,0x00000054,0x00001d55,
|
||||
0x00000864,0x00000365,0x00000474,0x00001375,0x00000c84,0x00000284,0x00000a94,
|
||||
0x00000694,0x00000ea4,0x000001a4,0x000009b4,0x00000bb5,0x000005c4,0x00001bc5,
|
||||
0x000007d5,0x000017d5,0x00000000,0x00000100,
|
||||
};
|
||||
|
||||
internal static readonly uint[] BitMask = { 0, 1, 3, 7, 15, 31, 63, 127, 255, 511, 1023, 2047, 4095, 8191, 16383, 32767 };
|
||||
internal static readonly byte[] 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, 0 };
|
||||
internal static readonly byte[] ExtraDistanceBits = { 0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 12, 12, 13, 13, 0, 0 };
|
||||
internal const int NumChars = 256;
|
||||
internal const int NumLengthBaseCodes = 29;
|
||||
internal const int NumDistBaseCodes = 30;
|
||||
|
||||
internal const uint FastEncoderPostTreeBitBuf = 0x0022;
|
||||
internal const int FastEncoderPostTreeBitCount = 9;
|
||||
|
||||
internal const uint NoCompressionHeader = 0x0;
|
||||
internal const int NoCompressionHeaderBitCount = 3;
|
||||
internal const uint BFinalNoCompressionHeader = 0x1;
|
||||
internal const int BFinalNoCompressionHeaderBitCount = 3;
|
||||
internal const int MaxCodeLen = 16;
|
||||
|
||||
static private byte[] distLookup;
|
||||
|
||||
static FastEncoderStatics() {
|
||||
distLookup = new byte[512];
|
||||
|
||||
// Generate the global slot tables which allow us to convert a distance
|
||||
// (0..32K) to a distance slot (0..29)
|
||||
//
|
||||
// Distance table
|
||||
// Extra Extra Extra
|
||||
// Code Bits Dist Code Bits Dist Code Bits Distance
|
||||
// ---- ---- ---- ---- ---- ------ ---- ---- --------
|
||||
// 0 0 1 10 4 33-48 20 9 1025-1536
|
||||
// 1 0 2 11 4 49-64 21 9 1537-2048
|
||||
// 2 0 3 12 5 65-96 22 10 2049-3072
|
||||
// 3 0 4 13 5 97-128 23 10 3073-4096
|
||||
// 4 1 5,6 14 6 129-192 24 11 4097-6144
|
||||
// 5 1 7,8 15 6 193-256 25 11 6145-8192
|
||||
// 6 2 9-12 16 7 257-384 26 12 8193-12288
|
||||
// 7 2 13-16 17 7 385-512 27 12 12289-16384
|
||||
// 8 3 17-24 18 8 513-768 28 13 16385-24576
|
||||
// 9 3 25-32 19 8 769-1024 29 13 24577-32768
|
||||
|
||||
// Initialize the mapping length (0..255) -> length code (0..28)
|
||||
//int length = 0;
|
||||
//for (code = 0; code < FastEncoderStatics.NumLengthBaseCodes-1; code++) {
|
||||
// for (int n = 0; n < (1 << FastEncoderStatics.ExtraLengthBits[code]); n++)
|
||||
// lengthLookup[length++] = (byte) code;
|
||||
//}
|
||||
//lengthLookup[length-1] = (byte) code;
|
||||
|
||||
// Initialize the mapping dist (0..32K) -> dist code (0..29)
|
||||
int dist = 0;
|
||||
int code;
|
||||
for (code = 0; code < 16; code++) {
|
||||
for (int n = 0; n < (1 << FastEncoderStatics.ExtraDistanceBits[code]); n++)
|
||||
distLookup[dist++] = (byte)code;
|
||||
}
|
||||
|
||||
dist >>= 7; // from now on, all distances are divided by 128
|
||||
|
||||
for (; code < FastEncoderStatics.NumDistBaseCodes; code++) {
|
||||
for (int n = 0; n < (1 << (FastEncoderStatics.ExtraDistanceBits[code] - 7)); n++)
|
||||
distLookup[256 + dist++] = (byte)code;
|
||||
}
|
||||
}
|
||||
|
||||
// Return the position slot (0...29) of a match offset (0...32767)
|
||||
static internal int GetSlot(int pos) {
|
||||
return distLookup[((pos) < 256) ? (pos) : (256 + ((pos) >> 7))];
|
||||
}
|
||||
|
||||
// Reverse 'length' of the bits in code
|
||||
public static uint BitReverse(uint code, int length) {
|
||||
uint new_code = 0;
|
||||
|
||||
Debug.Assert(length > 0 && length <= 16, "Invalid len");
|
||||
do {
|
||||
new_code |= (code & 1);
|
||||
new_code <<= 1;
|
||||
code >>= 1;
|
||||
} while (--length > 0);
|
||||
|
||||
return new_code >> 1;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user