├── AdvSim.Compression.UnitTest ├── AdvSim.Compression.UnitTest.csproj ├── Properties │ └── AssemblyInfo.cs ├── Tests.cs └── packages.config ├── AdvSim.Compression.sln ├── AdvSim.Compression ├── AdvSim.Compression.csproj ├── Cabinet.cs ├── Direct3D.cs ├── GZip.cs ├── LZMA.cs ├── LZMASDK │ ├── Common │ │ ├── CRC.cs │ │ ├── InBuffer.cs │ │ └── OutBuffer.cs │ ├── Compress │ │ ├── LZ │ │ │ ├── IMatchFinder.cs │ │ │ ├── LzBinTree.cs │ │ │ ├── LzInWindow.cs │ │ │ └── LzOutWindow.cs │ │ ├── LZMA │ │ │ ├── LzmaBase.cs │ │ │ ├── LzmaDecoder.cs │ │ │ └── LzmaEncoder.cs │ │ └── RangeCoder │ │ │ ├── RangeCoder.cs │ │ │ ├── RangeCoderBit.cs │ │ │ └── RangeCoderBitTree.cs │ └── ICoder.cs └── LZNT.cs └── README.md /AdvSim.Compression.UnitTest/AdvSim.Compression.UnitTest.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {AE3D80AF-83E6-48CA-BF01-54CA5E5CFDB2} 8 | {FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 9 | Library 10 | Properties 11 | AdvSim.Compression.UnitTest 12 | AdvSim.Compression.UnitTest 13 | v4.5.2 14 | 512 15 | 16 | 17 | AnyCPU 18 | true 19 | full 20 | false 21 | bin\Debug\ 22 | DEBUG;TRACE 23 | prompt 24 | 4 25 | 26 | 27 | AnyCPU 28 | pdbonly 29 | true 30 | bin\Release\ 31 | TRACE 32 | prompt 33 | 4 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | ..\packages\NUnit.3.5.0\lib\net45\nunit.framework.dll 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | {4a89fc7c-9fa2-4610-a601-28ecc4beecff} 51 | AdvSim.Compression 52 | 53 | 54 | 55 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /AdvSim.Compression.UnitTest/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.InteropServices; 3 | 4 | // General Information about an assembly is controlled through the following 5 | // set of attributes. Change these attribute values to modify the information 6 | // associated with an assembly. 7 | [assembly: AssemblyTitle("AdvSim.Compression.UnitTest")] 8 | [assembly: AssemblyDescription("")] 9 | [assembly: AssemblyConfiguration("")] 10 | [assembly: AssemblyCompany("")] 11 | [assembly: AssemblyProduct("AdvSim.Compression.UnitTest")] 12 | [assembly: AssemblyCopyright("Copyright © 2022")] 13 | [assembly: AssemblyTrademark("")] 14 | [assembly: AssemblyCulture("")] 15 | 16 | // Setting ComVisible to false makes the types in this assembly not visible 17 | // to COM components. If you need to access a type in this assembly from 18 | // COM, set the ComVisible attribute to true on that type. 19 | [assembly: ComVisible(false)] 20 | 21 | // The following GUID is for the ID of the typelib if this project is exposed to COM 22 | [assembly: Guid("AE3D80AF-83E6-48CA-BF01-54CA5E5CFDB2")] 23 | 24 | // Version information for an assembly consists of the following four values: 25 | // 26 | // Major Version 27 | // Minor Version 28 | // Build Number 29 | // Revision 30 | // 31 | // You can specify all the values or you can default the Build and Revision Numbers 32 | // by using the '*' as shown below: 33 | // [assembly: AssemblyVersion("1.0.*")] 34 | [assembly: AssemblyVersion("1.0.0.0")] 35 | [assembly: AssemblyFileVersion("1.0.0.0")] -------------------------------------------------------------------------------- /AdvSim.Compression.UnitTest/Tests.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.Security.Cryptography; 3 | using NUnit.Framework; 4 | using AdvSim.Compression; 5 | 6 | namespace AdvSim.Compression.UnitTest 7 | { 8 | [TestFixture] 9 | public class Tests 10 | { 11 | // Unit test globals 12 | //=================================== 13 | 14 | private static Byte[] bTest = GenerateRandomByteArray(0x1000); 15 | private static String sTestHash = GenerateByteHash(bTest); 16 | 17 | // Helper functions 18 | //=================================== 19 | 20 | // Generate random byte array of given size 21 | private static Byte[] GenerateRandomByteArray(Int32 size) 22 | { 23 | Byte[] data = new Byte[size]; 24 | Random random = new Random(); 25 | random.NextBytes(data); 26 | return data; 27 | } 28 | 29 | // Hash byte array 30 | public static String GenerateByteHash(Byte[] bArray) 31 | { 32 | SHA1CryptoServiceProvider sha1 = new SHA1CryptoServiceProvider(); 33 | Byte[] bHash = sha1.ComputeHash(bArray); 34 | return BitConverter.ToString(bHash).Replace("-", ""); 35 | } 36 | 37 | // Tests 38 | //=================================== 39 | 40 | [Test] 41 | public void Test_Gzip() 42 | { 43 | // Compress 44 | Byte[] bCompressed = GZip.GzipCompress(bTest); 45 | // Decompress 46 | Byte[] bDecompressed = GZip.GzipDecompress(bCompressed); 47 | 48 | // Check that the decompressed data is the same as the original 49 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 50 | } 51 | 52 | [Test] 53 | public void Test_LZMA() 54 | { 55 | // Compress 56 | Byte[] bCompressed = LZMA.LZMACompress(bTest); 57 | // Decompress 58 | Byte[] bDecompressed = LZMA.LZMADecompress(bCompressed); 59 | 60 | // Check that the decompressed data is the same as the original 61 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 62 | } 63 | 64 | [Test] 65 | public void Test_LZNT() 66 | { 67 | // Compress 68 | Byte[] bCompressed = LZNT.RtlCompressBuffer(bTest); 69 | // Decompress 70 | Byte[] bDecompressed = LZNT.RtlDecompressBuffer(bCompressed); 71 | 72 | // Check that the decompressed data is the same as the original 73 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 74 | } 75 | 76 | [Test] 77 | public void Test_Direct3D() 78 | { 79 | // Compress 80 | Byte[] bCompressed = Direct3D.D3DCompressShaders(bTest); 81 | // Decompress 82 | Byte[] bDecompressed = Direct3D.D3DDecompressShaders(bCompressed); 83 | 84 | // Check that the decompressed data is the same as the original 85 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 86 | } 87 | 88 | [Test] 89 | public void Test_LZMS() 90 | { 91 | // Compress 92 | Byte[] bCompressed = Cabinet.CompressStorage(bTest, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_LZMS); 93 | // Decompress 94 | Byte[] bDecompressed = Cabinet.DecompressStorage(bCompressed, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_LZMS); 95 | 96 | // Check that the decompressed data is the same as the original 97 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 98 | } 99 | 100 | [Test] 101 | public void Test_MSZIP() 102 | { 103 | // Compress 104 | Byte[] bCompressed = Cabinet.CompressStorage(bTest, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_MSZIP); 105 | // Decompress 106 | Byte[] bDecompressed = Cabinet.DecompressStorage(bCompressed, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_MSZIP); 107 | 108 | // Check that the decompressed data is the same as the original 109 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 110 | } 111 | 112 | [Test] 113 | public void Test_XPRESS() 114 | { 115 | // Compress 116 | Byte[] bCompressed = Cabinet.CompressStorage(bTest, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_XPRESS); 117 | // Decompress 118 | Byte[] bDecompressed = Cabinet.DecompressStorage(bCompressed, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_XPRESS); 119 | 120 | // Check that the decompressed data is the same as the original 121 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 122 | } 123 | 124 | [Test] 125 | public void Test_HUFF() 126 | { 127 | // Compress 128 | Byte[] bCompressed = Cabinet.CompressStorage(bTest, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_XPRESS_HUFF); 129 | // Decompress 130 | Byte[] bDecompressed = Cabinet.DecompressStorage(bCompressed, Cabinet.CompressionAlgorithm.COMPRESS_ALGORITHM_XPRESS_HUFF); 131 | 132 | // Check that the decompressed data is the same as the original 133 | Assert.AreEqual(sTestHash, GenerateByteHash(bDecompressed)); 134 | } 135 | } 136 | } -------------------------------------------------------------------------------- /AdvSim.Compression.UnitTest/packages.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | -------------------------------------------------------------------------------- /AdvSim.Compression.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvSim.Compression", "AdvSim.Compression\AdvSim.Compression.csproj", "{4A89FC7C-9FA2-4610-A601-28ECC4BEECFF}" 4 | EndProject 5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AdvSim.Compression.UnitTest", "AdvSim.Compression.UnitTest\AdvSim.Compression.UnitTest.csproj", "{AE3D80AF-83E6-48CA-BF01-54CA5E5CFDB2}" 6 | EndProject 7 | Global 8 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 9 | Release|Any CPU = Release|Any CPU 10 | EndGlobalSection 11 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 12 | {4A89FC7C-9FA2-4610-A601-28ECC4BEECFF}.Release|Any CPU.ActiveCfg = Release|Any CPU 13 | {4A89FC7C-9FA2-4610-A601-28ECC4BEECFF}.Release|Any CPU.Build.0 = Release|Any CPU 14 | {AE3D80AF-83E6-48CA-BF01-54CA5E5CFDB2}.Release|Any CPU.ActiveCfg = Release|Any CPU 15 | {AE3D80AF-83E6-48CA-BF01-54CA5E5CFDB2}.Release|Any CPU.Build.0 = Release|Any CPU 16 | EndGlobalSection 17 | EndGlobal 18 | -------------------------------------------------------------------------------- /AdvSim.Compression/AdvSim.Compression.csproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | net35;net40;net452;netstandard2.0 5 | disable 6 | disable 7 | false 8 | Release 9 | AnyCPU 10 | true 11 | Compression Wrapper Library 12 | IBM AdvSim, Ruben Boonen (@FuzzySec) 13 | Copyright © 2022 14 | https://github.com/FuzzySecurity/AdvSim.Compression 15 | https://github.com/FuzzySecurity/AdvSim.Compression 16 | Compression;Direct3D;GZip;LZMA;LZNT1;HUFF;LZMS;MSZIP;XPRESS 17 | Initial package release. 18 | A simple and sane wrapper for a number of compression functions in C#. Compression operations include: Direct3D shader compression, GZip, LZMA, LZNT1, HUFF, LZMS, MSZIP and XPRESS. 19 | 20 | git 21 | MIT 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /AdvSim.Compression/Cabinet.cs: -------------------------------------------------------------------------------- 1 | #if NETFRAMEWORK 2 | 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace AdvSim.Compression 7 | { 8 | public class Cabinet 9 | { 10 | // Cabinet.dll API's 11 | //=================================== 12 | 13 | [DllImport("Cabinet.dll")] 14 | internal static extern Boolean CreateCompressor( 15 | CompressionAlgorithm iAlgorithm, 16 | IntPtr pAllocationRoutines, 17 | ref IntPtr hCompressorHandle); 18 | 19 | [DllImport("Cabinet.dll")] 20 | internal static extern Boolean CreateDecompressor( 21 | CompressionAlgorithm iAlgorithm, 22 | IntPtr pAllocationRoutines, 23 | ref IntPtr hDecompressorHandle); 24 | 25 | [DllImport("Cabinet.dll", SetLastError = true)] 26 | internal static extern Boolean Compress( 27 | IntPtr hCompressorHandle, 28 | Byte[] bUncompressedData, 29 | UInt32 iUncompressedDataSize, 30 | Byte[] bCompressedBuffer, 31 | UInt32 iCompressedBufferSize, 32 | ref UInt32 iCompressedDataSize); 33 | 34 | [DllImport("Cabinet.dll")] 35 | internal static extern Boolean Decompress( 36 | IntPtr hDecompressorHandle, 37 | Byte[] bCompressedData, 38 | UInt32 iCompressedDataSize, 39 | Byte[] bUncompressedBuffer, 40 | UInt32 iUncompressedBufferSize, 41 | ref UInt32 iUncompressedDataSize); 42 | 43 | [DllImport("Cabinet.dll")] 44 | internal static extern Boolean CloseCompressor( 45 | IntPtr hCompressHandle); 46 | 47 | [DllImport("Cabinet.dll")] 48 | internal static extern Boolean CloseDecompressor( 49 | IntPtr hCompressHandle); 50 | 51 | // Cabinet Enums 52 | //=================================== 53 | 54 | /// 55 | /// Enum defining supported Windows Storage compression types 56 | /// 57 | public enum CompressionAlgorithm : UInt32 58 | { 59 | COMPRESS_ALGORITHM_MSZIP = 2, 60 | COMPRESS_ALGORITHM_XPRESS = 3, 61 | COMPRESS_ALGORITHM_XPRESS_HUFF = 4, 62 | COMPRESS_ALGORITHM_LZMS = 5 63 | } 64 | 65 | // Methods 66 | //=================================== 67 | 68 | /// 69 | /// Use native Windows.Storage.Compression (Cabinet.dll) to compress a byte array to a byte array 70 | /// 71 | /// Byte array containing the uncompressed buffer 72 | /// Type of compressor to create (CompressionAlgorithm) 73 | /// Compressed Byte array 74 | public static Byte[] CompressStorage(Byte[] bUncompressedBuffer, CompressionAlgorithm eAlgorithm) 75 | { 76 | // Create a new compressor 77 | IntPtr hCompressorHandle = IntPtr.Zero; 78 | CreateCompressor( 79 | eAlgorithm, 80 | IntPtr.Zero, 81 | ref hCompressorHandle); 82 | 83 | // Find the correct compression buffer size 84 | UInt32 iCompressedDataSize = 0; 85 | Compress( 86 | hCompressorHandle, 87 | bUncompressedBuffer, 88 | (UInt32)bUncompressedBuffer.Length, 89 | null, 90 | 0, 91 | ref iCompressedDataSize); 92 | 93 | // Create the compressed buffer 94 | Byte[] bCompressedBuffer = new Byte[iCompressedDataSize]; 95 | 96 | // Compress the data 97 | Compress( 98 | hCompressorHandle, 99 | bUncompressedBuffer, 100 | (UInt32)bUncompressedBuffer.Length, 101 | bCompressedBuffer, 102 | (UInt32)bCompressedBuffer.Length, 103 | ref iCompressedDataSize); 104 | 105 | // Close the compressor 106 | CloseCompressor(hCompressorHandle); 107 | 108 | // Return the compressed data 109 | return bCompressedBuffer; 110 | } 111 | 112 | /// 113 | /// Use native Windows.Storage.Compression (Cabinet.dll) to compress a file to a byte array 114 | /// 115 | /// Full path to the file on disk which will be compressed 116 | /// Type of compressor to create (CompressionAlgorithm) 117 | /// Compressed Byte array 118 | public static Byte[] CompressStorage(String sFilePath, CompressionAlgorithm eAlgorithm) 119 | { 120 | // Read the file into a byte array 121 | Byte[] bUncompressedBuffer = System.IO.File.ReadAllBytes(sFilePath); 122 | 123 | // Compress the byte array 124 | return CompressStorage(bUncompressedBuffer, eAlgorithm); 125 | } 126 | 127 | /// 128 | /// Use native Windows.Storage.Compression (Cabinet.dll) to compress a byte array to a file 129 | /// 130 | /// Byte array containing the uncompressed buffer 131 | /// Full path to the file on disk where the compressed data will be written 132 | /// Type of compressor to create (CompressionAlgorithm) 133 | public static void CompressStorage(Byte[] bUncompressedBuffer, String sFilePath, CompressionAlgorithm eAlgorithm) 134 | { 135 | // Compress the byte array 136 | Byte[] bCompressedBuffer = CompressStorage(bUncompressedBuffer, eAlgorithm); 137 | 138 | // Write the compressed data to disk 139 | System.IO.File.WriteAllBytes(sFilePath, bCompressedBuffer); 140 | } 141 | 142 | /// 143 | /// Use native Windows.Storage.Compression (Cabinet.dll) to compress a file to a file 144 | /// 145 | /// Full path to the file on disk which will be compressed 146 | /// Full path to the file on disk where the compressed data will be written 147 | /// Type of compressor to create (CompressionAlgorithm) 148 | public static void CompressStorage(String sFilePath, String sOutputFilePath, CompressionAlgorithm eAlgorithm) 149 | { 150 | // Read the file into a byte array 151 | Byte[] bUncompressedBuffer = System.IO.File.ReadAllBytes(sFilePath); 152 | 153 | // Compress the byte array 154 | CompressStorage(bUncompressedBuffer, sOutputFilePath, eAlgorithm); 155 | } 156 | 157 | /// 158 | /// Use native Windows.Storage.Compression (Cabinet.dll) to decompress a byte array to a byte array 159 | /// 160 | /// Byte array containing the compressed buffer 161 | /// Type of decompressor to create (CompressionAlgorithm) 162 | /// Decompressed Byte array 163 | public static Byte[] DecompressStorage(Byte[] bCompressedBuffer, CompressionAlgorithm eAlgorithm) 164 | { 165 | // Create a new decompressor 166 | IntPtr hDecompressorHandle = IntPtr.Zero; 167 | CreateDecompressor( 168 | eAlgorithm, 169 | IntPtr.Zero, 170 | ref hDecompressorHandle); 171 | 172 | // Find the correct uncompressed size 173 | UInt32 iUncompressedDataSize = 0; 174 | Decompress( 175 | hDecompressorHandle, 176 | bCompressedBuffer, 177 | (UInt32)bCompressedBuffer.Length, 178 | null, 179 | 0, 180 | ref iUncompressedDataSize); 181 | 182 | // Create the uncompressed buffer 183 | Byte[] bUncompressedBuffer = new Byte[iUncompressedDataSize]; 184 | 185 | // Decompress the data 186 | Decompress( 187 | hDecompressorHandle, 188 | bCompressedBuffer, 189 | (UInt32)bCompressedBuffer.Length, 190 | bUncompressedBuffer, 191 | (UInt32)bUncompressedBuffer.Length, 192 | ref iUncompressedDataSize); 193 | 194 | // Close the decompressor 195 | CloseDecompressor(hDecompressorHandle); 196 | 197 | // Return the uncompressed data 198 | return bUncompressedBuffer; 199 | } 200 | 201 | /// 202 | /// Use native Windows.Storage.Compression (Cabinet.dll) to decompress a file to a byte array 203 | /// 204 | /// Full path to the file on disk which will be decompressed 205 | /// Type of decompressor to create (CompressionAlgorithm) 206 | /// Decompressed Byte array 207 | public static Byte[] DecompressStorage(String sFilePath, CompressionAlgorithm eAlgorithm) 208 | { 209 | // Read the file into a byte array 210 | Byte[] bCompressedBuffer = System.IO.File.ReadAllBytes(sFilePath); 211 | 212 | // Decompress the byte array 213 | return DecompressStorage(bCompressedBuffer, eAlgorithm); 214 | } 215 | 216 | /// 217 | /// Use native Windows.Storage.Compression (Cabinet.dll) to decompress a byte array to a file 218 | /// 219 | /// Byte array containing the compressed buffer 220 | /// Full path to the file on disk where the decompressed data will be written 221 | /// Type of decompressor to create (CompressionAlgorithm) 222 | public static void DecompressStorage(Byte[] bCompressedBuffer, String sFilePath, CompressionAlgorithm eAlgorithm) 223 | { 224 | // Decompress the byte array 225 | Byte[] bUncompressedBuffer = DecompressStorage(bCompressedBuffer, eAlgorithm); 226 | 227 | // Write the uncompressed data to disk 228 | System.IO.File.WriteAllBytes(sFilePath, bUncompressedBuffer); 229 | } 230 | 231 | /// 232 | /// Use native Windows.Storage.Compression (Cabinet.dll) to decompress a file to a file 233 | /// 234 | /// Full path to the file on disk which will be decompressed 235 | /// Full path to the file on disk where the decompressed data will be written 236 | /// Type of decompressor to create (CompressionAlgorithm) 237 | public static void DecompressStorage(String sFilePath, String sOutputFilePath, CompressionAlgorithm eAlgorithm) 238 | { 239 | // Read the file into a byte array 240 | Byte[] bCompressedBuffer = System.IO.File.ReadAllBytes(sFilePath); 241 | 242 | // Decompress the byte array 243 | DecompressStorage(bCompressedBuffer, sOutputFilePath, eAlgorithm); 244 | } 245 | } 246 | } 247 | 248 | #endif -------------------------------------------------------------------------------- /AdvSim.Compression/Direct3D.cs: -------------------------------------------------------------------------------- 1 | #if NETFRAMEWORK 2 | 3 | using System; 4 | using System.IO; 5 | using System.Runtime.InteropServices; 6 | 7 | namespace AdvSim.Compression 8 | { 9 | public class Direct3D 10 | { 11 | // Direct3D API's 12 | // |_ https://modexp.wordpress.com/2019/12/08/shellcode-compression/#d3d 13 | //=================================== 14 | 15 | [DllImport("D3DCompiler_47.dll")] 16 | internal static extern UInt32 D3DCompressShaders( 17 | UInt32 uuNumShaders, 18 | ref D3D_SHADER_DATA pShaderData, 19 | UInt32 uFlags, 20 | ref ID3DBlob ppCompressedData); 21 | 22 | [DllImport("D3DCompiler_47.dll")] 23 | internal static extern UInt32 D3DDecompressShaders( 24 | IntPtr pSrcData, 25 | UIntPtr iSrcDataSize, 26 | UInt32 uNumShaders, 27 | UInt32 uStartIndex, 28 | ref UInt32 pIndices, 29 | UInt32 uFlags, 30 | ref ID3DBlob ppShaders, 31 | ref UInt32 pTotalShaders); 32 | 33 | // Structs 34 | //=================================== 35 | 36 | [StructLayout(LayoutKind.Sequential)] 37 | internal struct D3D_SHADER_DATA 38 | { 39 | public IntPtr pBytecode; 40 | public UInt32 BytecodeLength; 41 | } 42 | 43 | // Interfaces 44 | //=================================== 45 | 46 | [Guid("8BA5FB08-5195-40e2-AC58-0D989C3A0102")] 47 | [InterfaceType(ComInterfaceType.InterfaceIsIUnknown)] 48 | internal interface ID3DBlob 49 | { 50 | [PreserveSig] 51 | IntPtr GetBufferPointer(); 52 | 53 | [PreserveSig] 54 | UInt32 GetBufferSize(); 55 | } 56 | 57 | // Constants 58 | //=================================== 59 | 60 | internal const UInt32 D3DCOMPRESS_SHADER_KEEP_ALL_PARTS = 0x00000001; 61 | 62 | // Methods 63 | //=================================== 64 | 65 | /// 66 | /// Use Direct3d shaders to compress a byte array to a byte array 67 | /// 68 | /// Byte array containing the uncompressed buffer 69 | /// Compressed Byte array 70 | public static Byte[] D3DCompressShaders(Byte[] bUncompressedBuffer) 71 | { 72 | // We must marshall an unmanaged pointer to the byte array 73 | IntPtr pUncompressedBuffer = Marshal.AllocHGlobal(bUncompressedBuffer.Length); 74 | Marshal.Copy(bUncompressedBuffer, 0, pUncompressedBuffer, bUncompressedBuffer.Length); 75 | 76 | // Create D3D_SHADER_DATA struct 77 | D3D_SHADER_DATA d3dShaderData = new D3D_SHADER_DATA(); 78 | d3dShaderData.pBytecode = pUncompressedBuffer; 79 | d3dShaderData.BytecodeLength = (UInt32)bUncompressedBuffer.Length; 80 | 81 | // Compress 82 | ID3DBlob oID3DBlob = null; 83 | UInt32 iCallRes = D3DCompressShaders( 84 | 1, 85 | ref d3dShaderData, 86 | D3DCOMPRESS_SHADER_KEEP_ALL_PARTS, 87 | ref oID3DBlob); 88 | 89 | // Call shader interface 90 | UInt32 iSize = oID3DBlob.GetBufferSize(); 91 | IntPtr pBlob = oID3DBlob.GetBufferPointer(); 92 | 93 | // Copy to byte[] 94 | Byte[] bCompressedBuffer = new Byte[iSize]; 95 | Marshal.Copy(pBlob, bCompressedBuffer, 0, (Int32)iSize); 96 | 97 | // Free blob 98 | Marshal.ReleaseComObject(oID3DBlob); 99 | Marshal.FreeHGlobal(pUncompressedBuffer); 100 | 101 | // Return compressed buffer 102 | return bCompressedBuffer; 103 | } 104 | 105 | /// 106 | /// Use Direct3d shaders to compress a file to a byte array 107 | /// 108 | /// Full path to the file on disk which will be compressed 109 | /// Compressed Byte array 110 | public static Byte[] D3DCompressShaders(String sFilePath) 111 | { 112 | // Read file 113 | Byte[] bUncompressedBuffer = File.ReadAllBytes(sFilePath); 114 | 115 | // Compress 116 | return D3DCompressShaders(bUncompressedBuffer); 117 | } 118 | 119 | /// 120 | /// Use Direct3d shaders to compress a byte array to a file 121 | /// 122 | /// Byte array containing the uncompressed buffer 123 | /// Full path to the file on disk where the compressed data will be written 124 | public static void D3DCompressShaders(Byte[] bUncompressedBuffer, String sFilePath) 125 | { 126 | // Compress 127 | Byte[] bCompressedBuffer = D3DCompressShaders(bUncompressedBuffer); 128 | 129 | // Write file 130 | File.WriteAllBytes(sFilePath, bCompressedBuffer); 131 | } 132 | 133 | /// 134 | /// Use Direct3d shaders to compress a file to a file 135 | /// 136 | /// Full path to the file on disk which will be compressed 137 | /// Full path to the file on disk where the compressed data will be written 138 | public static void D3DCompressShaders(String sFilePath, String sOutputFilePath) 139 | { 140 | // Read file 141 | Byte[] bUncompressedBuffer = File.ReadAllBytes(sFilePath); 142 | 143 | // Compress 144 | D3DCompressShaders(bUncompressedBuffer, sOutputFilePath); 145 | } 146 | 147 | /// 148 | /// Use Direct3d shaders to decompress a byte array to a byte array 149 | /// 150 | /// Byte array containing the compressed buffer 151 | /// Decompressed Byte array 152 | public static Byte[] D3DDecompressShaders(Byte[] bCompressedBuffer) 153 | { 154 | // We must marshall an unmanaged pointer to the byte array 155 | IntPtr pCompressedBuffer = Marshal.AllocHGlobal(bCompressedBuffer.Length); 156 | Marshal.Copy(bCompressedBuffer, 0, pCompressedBuffer, bCompressedBuffer.Length); 157 | 158 | UInt32 iTotalShaders = 0; 159 | UInt32 iIndices = 0; 160 | ID3DBlob oID3DBlob = null; 161 | 162 | UInt32 iCallRes = D3DDecompressShaders( 163 | pCompressedBuffer, 164 | new UIntPtr((UInt32)bCompressedBuffer.Length), 165 | 1, 166 | 0, 167 | ref iIndices, 168 | 0, 169 | ref oID3DBlob, 170 | ref iTotalShaders); 171 | 172 | // Call shader interface 173 | UInt32 iSize = oID3DBlob.GetBufferSize(); 174 | IntPtr pBlob = oID3DBlob.GetBufferPointer(); 175 | 176 | // Copy to byte[] 177 | Byte[] bUnCompressedBuffer = new Byte[iSize]; 178 | Marshal.Copy(pBlob, bUnCompressedBuffer, 0, (Int32)iSize); 179 | 180 | // Free blob 181 | Marshal.ReleaseComObject(oID3DBlob); 182 | Marshal.FreeHGlobal(pCompressedBuffer); 183 | 184 | // Return decompressed buffer 185 | return bUnCompressedBuffer; 186 | } 187 | 188 | /// 189 | /// Use Direct3d shaders to decompress a file to a byte array 190 | /// 191 | /// Full path to the file on disk which will be decompressed 192 | /// Decompressed Byte array 193 | public static Byte[] D3DDecompressShaders(String sFilePath) 194 | { 195 | // Read file 196 | Byte[] bCompressedBuffer = File.ReadAllBytes(sFilePath); 197 | 198 | // Decompress 199 | return D3DDecompressShaders(bCompressedBuffer); 200 | } 201 | 202 | /// 203 | /// Use Direct3d shaders to decompress a byte array to a file 204 | /// 205 | /// Byte array containing the compressed buffer 206 | /// Full path to the file on disk where the decompressed data will be written 207 | public static void D3DDecompressShaders(Byte[] bCompressedBuffer, String sFilePath) 208 | { 209 | // Decompress 210 | Byte[] bUnCompressedBuffer = D3DDecompressShaders(bCompressedBuffer); 211 | 212 | // Write file 213 | File.WriteAllBytes(sFilePath, bUnCompressedBuffer); 214 | } 215 | 216 | /// 217 | /// Use Direct3d shaders to decompress a file to a file 218 | /// 219 | /// Full path to the file on disk which will be decompressed 220 | /// Full path to the file on disk where the decompressed data will be written 221 | public static void D3DDecompressShaders(String sFilePath, String sOutputFilePath) 222 | { 223 | // Read file 224 | Byte[] bCompressedBuffer = File.ReadAllBytes(sFilePath); 225 | 226 | // Decompress 227 | D3DDecompressShaders(bCompressedBuffer, sOutputFilePath); 228 | } 229 | } 230 | } 231 | 232 | #endif -------------------------------------------------------------------------------- /AdvSim.Compression/GZip.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | using System.IO.Compression; 4 | 5 | namespace AdvSim.Compression 6 | { 7 | public class GZip 8 | { 9 | /// 10 | /// Use Gzip to compress a byte array to a byte array 11 | /// 12 | /// Byte array containing the uncompressed buffer 13 | /// Compressed Byte array 14 | public static Byte[] GzipCompress(Byte[] bUncompressedBuffer) 15 | { 16 | using (MemoryStream ms = new MemoryStream()) 17 | { 18 | using (GZipStream gzip = new GZipStream(ms, CompressionMode.Compress, true)) 19 | { 20 | gzip.Write(bUncompressedBuffer, 0, bUncompressedBuffer.Length); 21 | } 22 | return ms.ToArray(); 23 | } 24 | } 25 | 26 | /// 27 | /// Use Gzip to compress a file to a byte array 28 | /// 29 | /// Full path to the file on disk which will be compressed 30 | /// Compressed Byte array 31 | public static Byte[] GzipCompress(String sFilePath) 32 | { 33 | // Read file to byte array 34 | Byte[] bUncompressedBuffer = File.ReadAllBytes(sFilePath); 35 | 36 | // Compress byte array 37 | return GzipCompress(bUncompressedBuffer); 38 | } 39 | 40 | /// 41 | /// Use Gzip to compress a byte array to a file 42 | /// 43 | /// Byte array containing the uncompressed buffer 44 | /// Full path to the file on disk where the compressed data will be written 45 | public static void GzipCompress(Byte[] bUncompressedBuffer, String sFilePath) 46 | { 47 | // Compress byte array 48 | Byte[] bCompressedBuffer = GzipCompress(bUncompressedBuffer); 49 | 50 | // Write compressed byte array to file 51 | File.WriteAllBytes(sFilePath, bCompressedBuffer); 52 | } 53 | 54 | /// 55 | /// Use Gzip to compress a file to a file 56 | /// 57 | /// Full path to the file on disk which will be compressed 58 | /// Full path to the file on disk where the compressed data will be written 59 | public static void GzipCompress(String sFilePath, String sOutputFilePath) 60 | { 61 | // Compress byte array 62 | Byte[] bCompressedBuffer = GzipCompress(sFilePath); 63 | 64 | // Write compressed byte array to file 65 | File.WriteAllBytes(sOutputFilePath, bCompressedBuffer); 66 | } 67 | 68 | /// 69 | /// Use GZip to decompress a byte array to a byte array 70 | /// 71 | /// Byte array containing the compressed buffer 72 | /// Decompressed Byte array 73 | public static Byte[] GzipDecompress(Byte[] bCompressedBuffer) 74 | { 75 | using (MemoryStream src = new MemoryStream(bCompressedBuffer)) 76 | { 77 | using (MemoryStream dst = new MemoryStream()) 78 | { 79 | using (GZipStream gZipStream = new GZipStream(src, CompressionMode.Decompress)) 80 | { 81 | Byte[] buffer = new Byte[4096]; 82 | Int32 n; 83 | while ((n = gZipStream.Read(buffer, 0, buffer.Length)) != 0) 84 | { 85 | dst.Write(buffer, 0, n); 86 | } 87 | } 88 | return dst.ToArray(); 89 | } 90 | } 91 | } 92 | 93 | /// 94 | /// Use GZip to decompress a file to a byte array 95 | /// 96 | /// Full path to the file on disk which will be decompressed 97 | /// Decompressed Byte array 98 | public static Byte[] GzipDecompress(String sFilePath) 99 | { 100 | // Read file to byte array 101 | Byte[] bCompressedBuffer = File.ReadAllBytes(sFilePath); 102 | 103 | // Decompress byte array 104 | return GzipDecompress(bCompressedBuffer); 105 | } 106 | 107 | /// 108 | /// Use GZip to decompress a byte array to a file 109 | /// 110 | /// Byte array containing the compressed buffer 111 | /// Full path to the file on disk where the decompressed data will be written 112 | public static void GzipDecompress(Byte[] bCompressedBuffer, String sFilePath) 113 | { 114 | // Decompress byte array 115 | Byte[] bUncompressedBuffer = GzipDecompress(bCompressedBuffer); 116 | 117 | // Write uncompressed byte array to file 118 | File.WriteAllBytes(sFilePath, bUncompressedBuffer); 119 | } 120 | 121 | /// 122 | /// Use GZip to decompress a file to a file 123 | /// 124 | /// Full path to the file on disk which will be decompressed 125 | /// Full path to the file on disk where the decompressed data will be written 126 | public static void GzipDecompress(String sFilePath, String sOutputFilePath) 127 | { 128 | // Decompress byte array 129 | Byte[] bUncompressedBuffer = GzipDecompress(sFilePath); 130 | 131 | // Write uncompressed byte array to file 132 | File.WriteAllBytes(sOutputFilePath, bUncompressedBuffer); 133 | } 134 | } 135 | } -------------------------------------------------------------------------------- /AdvSim.Compression/LZMA.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | using System.IO; 3 | 4 | namespace AdvSim.Compression 5 | { 6 | public class LZMA 7 | { 8 | /// 9 | /// Use LZMA to compress a byte array to a byte array 10 | /// 11 | /// Byte array containing the uncompressed buffer 12 | /// Compressed Byte array 13 | public static Byte[] LZMACompress(Byte[] bUncompressedBuffer) 14 | { 15 | using (MemoryStream ms = new MemoryStream(bUncompressedBuffer)) 16 | { 17 | using (MemoryStream msLZMA = new MemoryStream()) 18 | { 19 | SevenZip.Compression.LZMA.Encoder encoder = new SevenZip.Compression.LZMA.Encoder(); 20 | encoder.WriteCoderProperties(msLZMA); 21 | msLZMA.Write(BitConverter.GetBytes(ms.Length), 0, 8); 22 | encoder.Code(ms, msLZMA, ms.Length, -1, null); 23 | 24 | return msLZMA.ToArray(); 25 | } 26 | } 27 | } 28 | 29 | /// 30 | /// Use LZMA to compress a file to a byte array 31 | /// 32 | /// Full path to the file on disk which will be compressed 33 | /// Compressed Byte array 34 | public static Byte[] LZMACompress(String sFilePath) 35 | { 36 | // Read file to byte array 37 | Byte[] bUncompressedBuffer = File.ReadAllBytes(sFilePath); 38 | 39 | // Compress byte array 40 | return LZMACompress(bUncompressedBuffer); 41 | } 42 | 43 | /// 44 | /// Use LZMA to compress a byte array to a file 45 | /// 46 | /// Byte array containing the uncompressed buffer 47 | /// Full path to the file on disk where the compressed data will be written 48 | public static void LZMACompress(Byte[] bUncompressedBuffer, String sFilePath) 49 | { 50 | // Compress byte array 51 | Byte[] bCompressedBuffer = LZMACompress(bUncompressedBuffer); 52 | 53 | // Write byte array to file 54 | File.WriteAllBytes(sFilePath, bCompressedBuffer); 55 | } 56 | 57 | /// 58 | /// Use LZMA to compress a file to a file 59 | /// 60 | /// Full path to the file on disk which will be compressed 61 | /// Full path to the file on disk where the compressed data will be written 62 | public static void LZMACompress(String sFilePath, String sOutputFilePath) 63 | { 64 | // Compress byte array 65 | Byte[] bCompressedBuffer = LZMACompress(sFilePath); 66 | 67 | // Write byte array to file 68 | File.WriteAllBytes(sOutputFilePath, bCompressedBuffer); 69 | } 70 | 71 | /// 72 | /// Use LZMA to decompress a byte array to a byte array 73 | /// 74 | /// Byte array containing the compressed buffer 75 | /// Decompressed Byte array 76 | public static Byte[] LZMADecompress(Byte[] bCompressedBuffer) 77 | { 78 | using (MemoryStream ms = new MemoryStream()) 79 | { 80 | using (MemoryStream msLZMA = new MemoryStream(bCompressedBuffer)) 81 | { 82 | SevenZip.Compression.LZMA.Decoder decoder = new SevenZip.Compression.LZMA.Decoder(); 83 | Byte[] properties = new Byte[5]; 84 | msLZMA.Read(properties, 0, 5); 85 | decoder.SetDecoderProperties(properties); 86 | 87 | Byte[] fileLengthBytes = new Byte[8]; 88 | msLZMA.Read(fileLengthBytes, 0, 8); 89 | Int64 fileLength = BitConverter.ToInt64(fileLengthBytes, 0); 90 | 91 | decoder.Code(msLZMA, ms, msLZMA.Length, fileLength, null); 92 | return ms.ToArray(); 93 | } 94 | } 95 | } 96 | 97 | /// 98 | /// Use LZMA to decompress a file to a byte array 99 | /// 100 | /// Full path to the file on disk which will be decompressed 101 | /// Decompressed Byte array 102 | public static Byte[] LZMADecompress(String sFilePath) 103 | { 104 | // Read file to byte array 105 | Byte[] bCompressedBuffer = File.ReadAllBytes(sFilePath); 106 | 107 | // Decompress byte array 108 | return LZMADecompress(bCompressedBuffer); 109 | } 110 | 111 | /// 112 | /// Use LZMA to decompress a byte array to a file 113 | /// 114 | /// Byte array containing the compressed buffer 115 | /// Full path to the file on disk where the decompressed data will be written 116 | public static void LZMADecompress(Byte[] bCompressedBuffer, String sFilePath) 117 | { 118 | // Decompress byte array 119 | Byte[] bUncompressedBuffer = LZMADecompress(bCompressedBuffer); 120 | 121 | // Write byte array to file 122 | File.WriteAllBytes(sFilePath, bUncompressedBuffer); 123 | } 124 | 125 | /// 126 | /// Use LZMA to decompress a file to a file 127 | /// 128 | /// Full path to the file on disk which will be decompressed 129 | /// Full path to the file on disk where the decompressed data will be written 130 | public static void LZMADecompress(String sFilePath, String sOutputFilePath) 131 | { 132 | // Decompress byte array 133 | Byte[] bUncompressedBuffer = LZMADecompress(sFilePath); 134 | 135 | // Write byte array to file 136 | File.WriteAllBytes(sOutputFilePath, bUncompressedBuffer); 137 | } 138 | } 139 | } -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Common/CRC.cs: -------------------------------------------------------------------------------- 1 | // Common/CRC.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip 6 | { 7 | class CRC 8 | { 9 | public static readonly UInt32[] Table; 10 | 11 | static CRC() 12 | { 13 | Table = new UInt32[256]; 14 | const UInt32 kPoly = 0xEDB88320; 15 | for (UInt32 i = 0; i < 256; i++) 16 | { 17 | UInt32 r = i; 18 | for (Int32 j = 0; j < 8; j++) 19 | if ((r & 1) != 0) 20 | r = (r >> 1) ^ kPoly; 21 | else 22 | r >>= 1; 23 | Table[i] = r; 24 | } 25 | } 26 | 27 | UInt32 _value = 0xFFFFFFFF; 28 | 29 | public void Init() { _value = 0xFFFFFFFF; } 30 | 31 | public void UpdateByte(Byte b) 32 | { 33 | _value = Table[(((Byte)(_value)) ^ b)] ^ (_value >> 8); 34 | } 35 | 36 | public void Update(Byte[] data, UInt32 offset, UInt32 size) 37 | { 38 | for (UInt32 i = 0; i < size; i++) 39 | _value = Table[(((Byte)(_value)) ^ data[offset + i])] ^ (_value >> 8); 40 | } 41 | 42 | public UInt32 GetDigest() { return _value ^ 0xFFFFFFFF; } 43 | 44 | static UInt32 CalculateDigest(Byte[] data, UInt32 offset, UInt32 size) 45 | { 46 | CRC crc = new CRC(); 47 | // crc.Init(); 48 | crc.Update(data, offset, size); 49 | return crc.GetDigest(); 50 | } 51 | 52 | static Boolean VerifyDigest(UInt32 digest, Byte[] data, UInt32 offset, UInt32 size) 53 | { 54 | return (CalculateDigest(data, offset, size) == digest); 55 | } 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Common/InBuffer.cs: -------------------------------------------------------------------------------- 1 | // InBuffer.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Buffer 6 | { 7 | public class InBuffer 8 | { 9 | Byte[] m_Buffer; 10 | UInt32 m_Pos; 11 | UInt32 m_Limit; 12 | UInt32 m_BufferSize; 13 | System.IO.Stream m_Stream; 14 | Boolean m_StreamWasExhausted; 15 | UInt64 m_ProcessedSize; 16 | 17 | public InBuffer(UInt32 bufferSize) 18 | { 19 | m_Buffer = new Byte[bufferSize]; 20 | m_BufferSize = bufferSize; 21 | } 22 | 23 | public void Init(System.IO.Stream stream) 24 | { 25 | m_Stream = stream; 26 | m_ProcessedSize = 0; 27 | m_Limit = 0; 28 | m_Pos = 0; 29 | m_StreamWasExhausted = false; 30 | } 31 | 32 | public Boolean ReadBlock() 33 | { 34 | if (m_StreamWasExhausted) 35 | return false; 36 | m_ProcessedSize += m_Pos; 37 | Int32 aNumProcessedBytes = m_Stream.Read(m_Buffer, 0, (Int32)m_BufferSize); 38 | m_Pos = 0; 39 | m_Limit = (UInt32)aNumProcessedBytes; 40 | m_StreamWasExhausted = (aNumProcessedBytes == 0); 41 | return (!m_StreamWasExhausted); 42 | } 43 | 44 | 45 | public void ReleaseStream() 46 | { 47 | // m_Stream.Close(); 48 | m_Stream = null; 49 | } 50 | 51 | public Boolean ReadByte(Byte b) // check it 52 | { 53 | if (m_Pos >= m_Limit) 54 | if (!ReadBlock()) 55 | return false; 56 | b = m_Buffer[m_Pos++]; 57 | return true; 58 | } 59 | 60 | public Byte ReadByte() 61 | { 62 | // return (byte)m_Stream.ReadByte(); 63 | if (m_Pos >= m_Limit) 64 | if (!ReadBlock()) 65 | return 0xFF; 66 | return m_Buffer[m_Pos++]; 67 | } 68 | 69 | public UInt64 GetProcessedSize() 70 | { 71 | return m_ProcessedSize + m_Pos; 72 | } 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Common/OutBuffer.cs: -------------------------------------------------------------------------------- 1 | // OutBuffer.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Buffer 6 | { 7 | public class OutBuffer 8 | { 9 | Byte[] m_Buffer; 10 | UInt32 m_Pos; 11 | UInt32 m_BufferSize; 12 | System.IO.Stream m_Stream; 13 | UInt64 m_ProcessedSize; 14 | 15 | public OutBuffer(UInt32 bufferSize) 16 | { 17 | m_Buffer = new Byte[bufferSize]; 18 | m_BufferSize = bufferSize; 19 | } 20 | 21 | public void SetStream(System.IO.Stream stream) { m_Stream = stream; } 22 | public void FlushStream() { m_Stream.Flush(); } 23 | public void CloseStream() { m_Stream.Close(); } 24 | public void ReleaseStream() { m_Stream = null; } 25 | 26 | public void Init() 27 | { 28 | m_ProcessedSize = 0; 29 | m_Pos = 0; 30 | } 31 | 32 | public void WriteByte(Byte b) 33 | { 34 | m_Buffer[m_Pos++] = b; 35 | if (m_Pos >= m_BufferSize) 36 | FlushData(); 37 | } 38 | 39 | public void FlushData() 40 | { 41 | if (m_Pos == 0) 42 | return; 43 | m_Stream.Write(m_Buffer, 0, (Int32)m_Pos); 44 | m_Pos = 0; 45 | } 46 | 47 | public UInt64 GetProcessedSize() { return m_ProcessedSize + m_Pos; } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZ/IMatchFinder.cs: -------------------------------------------------------------------------------- 1 | // IMatchFinder.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | interface IInWindowStream 8 | { 9 | void SetStream(System.IO.Stream inStream); 10 | void Init(); 11 | void ReleaseStream(); 12 | Byte GetIndexByte(Int32 index); 13 | UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit); 14 | UInt32 GetNumAvailableBytes(); 15 | } 16 | 17 | interface IMatchFinder : IInWindowStream 18 | { 19 | void Create(UInt32 historySize, UInt32 keepAddBufferBefore, 20 | UInt32 matchMaxLen, UInt32 keepAddBufferAfter); 21 | UInt32 GetMatches(UInt32[] distances); 22 | void Skip(UInt32 num); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZ/LzBinTree.cs: -------------------------------------------------------------------------------- 1 | // LzBinTree.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | public class BinTree : InWindow, IMatchFinder 8 | { 9 | UInt32 _cyclicBufferPos; 10 | UInt32 _cyclicBufferSize = 0; 11 | UInt32 _matchMaxLen; 12 | 13 | UInt32[] _son; 14 | UInt32[] _hash; 15 | 16 | UInt32 _cutValue = 0xFF; 17 | UInt32 _hashMask; 18 | UInt32 _hashSizeSum = 0; 19 | 20 | Boolean HASH_ARRAY = true; 21 | 22 | const UInt32 kHash2Size = 1 << 10; 23 | const UInt32 kHash3Size = 1 << 16; 24 | const UInt32 kBT2HashSize = 1 << 16; 25 | const UInt32 kStartMaxLen = 1; 26 | const UInt32 kHash3Offset = kHash2Size; 27 | const UInt32 kEmptyHashValue = 0; 28 | const UInt32 kMaxValForNormalize = ((UInt32)1 << 31) - 1; 29 | 30 | UInt32 kNumHashDirectBytes = 0; 31 | UInt32 kMinMatchCheck = 4; 32 | UInt32 kFixHashSize = kHash2Size + kHash3Size; 33 | 34 | public void SetType(Int32 numHashBytes) 35 | { 36 | HASH_ARRAY = (numHashBytes > 2); 37 | if (HASH_ARRAY) 38 | { 39 | kNumHashDirectBytes = 0; 40 | kMinMatchCheck = 4; 41 | kFixHashSize = kHash2Size + kHash3Size; 42 | } 43 | else 44 | { 45 | kNumHashDirectBytes = 2; 46 | kMinMatchCheck = 2 + 1; 47 | kFixHashSize = 0; 48 | } 49 | } 50 | 51 | public new void SetStream(System.IO.Stream stream) { base.SetStream(stream); } 52 | public new void ReleaseStream() { base.ReleaseStream(); } 53 | 54 | public new void Init() 55 | { 56 | base.Init(); 57 | for (UInt32 i = 0; i < _hashSizeSum; i++) 58 | _hash[i] = kEmptyHashValue; 59 | _cyclicBufferPos = 0; 60 | ReduceOffsets(-1); 61 | } 62 | 63 | public new void MovePos() 64 | { 65 | if (++_cyclicBufferPos >= _cyclicBufferSize) 66 | _cyclicBufferPos = 0; 67 | base.MovePos(); 68 | if (_pos == kMaxValForNormalize) 69 | Normalize(); 70 | } 71 | 72 | public new Byte GetIndexByte(Int32 index) { return base.GetIndexByte(index); } 73 | 74 | public new UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) 75 | { return base.GetMatchLen(index, distance, limit); } 76 | 77 | public new UInt32 GetNumAvailableBytes() { return base.GetNumAvailableBytes(); } 78 | 79 | public void Create(UInt32 historySize, UInt32 keepAddBufferBefore, 80 | UInt32 matchMaxLen, UInt32 keepAddBufferAfter) 81 | { 82 | if (historySize > kMaxValForNormalize - 256) 83 | throw new Exception(); 84 | _cutValue = 16 + (matchMaxLen >> 1); 85 | 86 | UInt32 windowReservSize = (historySize + keepAddBufferBefore + 87 | matchMaxLen + keepAddBufferAfter) / 2 + 256; 88 | 89 | base.Create(historySize + keepAddBufferBefore, matchMaxLen + keepAddBufferAfter, windowReservSize); 90 | 91 | _matchMaxLen = matchMaxLen; 92 | 93 | UInt32 cyclicBufferSize = historySize + 1; 94 | if (_cyclicBufferSize != cyclicBufferSize) 95 | _son = new UInt32[(_cyclicBufferSize = cyclicBufferSize) * 2]; 96 | 97 | UInt32 hs = kBT2HashSize; 98 | 99 | if (HASH_ARRAY) 100 | { 101 | hs = historySize - 1; 102 | hs |= (hs >> 1); 103 | hs |= (hs >> 2); 104 | hs |= (hs >> 4); 105 | hs |= (hs >> 8); 106 | hs >>= 1; 107 | hs |= 0xFFFF; 108 | if (hs > (1 << 24)) 109 | hs >>= 1; 110 | _hashMask = hs; 111 | hs++; 112 | hs += kFixHashSize; 113 | } 114 | if (hs != _hashSizeSum) 115 | _hash = new UInt32[_hashSizeSum = hs]; 116 | } 117 | 118 | public UInt32 GetMatches(UInt32[] distances) 119 | { 120 | UInt32 lenLimit; 121 | if (_pos + _matchMaxLen <= _streamPos) 122 | lenLimit = _matchMaxLen; 123 | else 124 | { 125 | lenLimit = _streamPos - _pos; 126 | if (lenLimit < kMinMatchCheck) 127 | { 128 | MovePos(); 129 | return 0; 130 | } 131 | } 132 | 133 | UInt32 offset = 0; 134 | UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; 135 | UInt32 cur = _bufferOffset + _pos; 136 | UInt32 maxLen = kStartMaxLen; // to avoid items for len < hashSize; 137 | UInt32 hashValue, hash2Value = 0, hash3Value = 0; 138 | 139 | if (HASH_ARRAY) 140 | { 141 | UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; 142 | hash2Value = temp & (kHash2Size - 1); 143 | temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); 144 | hash3Value = temp & (kHash3Size - 1); 145 | hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; 146 | } 147 | else 148 | hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); 149 | 150 | UInt32 curMatch = _hash[kFixHashSize + hashValue]; 151 | if (HASH_ARRAY) 152 | { 153 | UInt32 curMatch2 = _hash[hash2Value]; 154 | UInt32 curMatch3 = _hash[kHash3Offset + hash3Value]; 155 | _hash[hash2Value] = _pos; 156 | _hash[kHash3Offset + hash3Value] = _pos; 157 | if (curMatch2 > matchMinPos) 158 | if (_bufferBase[_bufferOffset + curMatch2] == _bufferBase[cur]) 159 | { 160 | distances[offset++] = maxLen = 2; 161 | distances[offset++] = _pos - curMatch2 - 1; 162 | } 163 | if (curMatch3 > matchMinPos) 164 | if (_bufferBase[_bufferOffset + curMatch3] == _bufferBase[cur]) 165 | { 166 | if (curMatch3 == curMatch2) 167 | offset -= 2; 168 | distances[offset++] = maxLen = 3; 169 | distances[offset++] = _pos - curMatch3 - 1; 170 | curMatch2 = curMatch3; 171 | } 172 | if (offset != 0 && curMatch2 == curMatch) 173 | { 174 | offset -= 2; 175 | maxLen = kStartMaxLen; 176 | } 177 | } 178 | 179 | _hash[kFixHashSize + hashValue] = _pos; 180 | 181 | UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; 182 | UInt32 ptr1 = (_cyclicBufferPos << 1); 183 | 184 | UInt32 len0, len1; 185 | len0 = len1 = kNumHashDirectBytes; 186 | 187 | if (kNumHashDirectBytes != 0) 188 | { 189 | if (curMatch > matchMinPos) 190 | { 191 | if (_bufferBase[_bufferOffset + curMatch + kNumHashDirectBytes] != 192 | _bufferBase[cur + kNumHashDirectBytes]) 193 | { 194 | distances[offset++] = maxLen = kNumHashDirectBytes; 195 | distances[offset++] = _pos - curMatch - 1; 196 | } 197 | } 198 | } 199 | 200 | UInt32 count = _cutValue; 201 | 202 | while(true) 203 | { 204 | if(curMatch <= matchMinPos || count-- == 0) 205 | { 206 | _son[ptr0] = _son[ptr1] = kEmptyHashValue; 207 | break; 208 | } 209 | UInt32 delta = _pos - curMatch; 210 | UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? 211 | (_cyclicBufferPos - delta) : 212 | (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; 213 | 214 | UInt32 pby1 = _bufferOffset + curMatch; 215 | UInt32 len = Math.Min(len0, len1); 216 | if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) 217 | { 218 | while(++len != lenLimit) 219 | if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) 220 | break; 221 | if (maxLen < len) 222 | { 223 | distances[offset++] = maxLen = len; 224 | distances[offset++] = delta - 1; 225 | if (len == lenLimit) 226 | { 227 | _son[ptr1] = _son[cyclicPos]; 228 | _son[ptr0] = _son[cyclicPos + 1]; 229 | break; 230 | } 231 | } 232 | } 233 | if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) 234 | { 235 | _son[ptr1] = curMatch; 236 | ptr1 = cyclicPos + 1; 237 | curMatch = _son[ptr1]; 238 | len1 = len; 239 | } 240 | else 241 | { 242 | _son[ptr0] = curMatch; 243 | ptr0 = cyclicPos; 244 | curMatch = _son[ptr0]; 245 | len0 = len; 246 | } 247 | } 248 | MovePos(); 249 | return offset; 250 | } 251 | 252 | public void Skip(UInt32 num) 253 | { 254 | do 255 | { 256 | UInt32 lenLimit; 257 | if (_pos + _matchMaxLen <= _streamPos) 258 | lenLimit = _matchMaxLen; 259 | else 260 | { 261 | lenLimit = _streamPos - _pos; 262 | if (lenLimit < kMinMatchCheck) 263 | { 264 | MovePos(); 265 | continue; 266 | } 267 | } 268 | 269 | UInt32 matchMinPos = (_pos > _cyclicBufferSize) ? (_pos - _cyclicBufferSize) : 0; 270 | UInt32 cur = _bufferOffset + _pos; 271 | 272 | UInt32 hashValue; 273 | 274 | if (HASH_ARRAY) 275 | { 276 | UInt32 temp = CRC.Table[_bufferBase[cur]] ^ _bufferBase[cur + 1]; 277 | UInt32 hash2Value = temp & (kHash2Size - 1); 278 | _hash[hash2Value] = _pos; 279 | temp ^= ((UInt32)(_bufferBase[cur + 2]) << 8); 280 | UInt32 hash3Value = temp & (kHash3Size - 1); 281 | _hash[kHash3Offset + hash3Value] = _pos; 282 | hashValue = (temp ^ (CRC.Table[_bufferBase[cur + 3]] << 5)) & _hashMask; 283 | } 284 | else 285 | hashValue = _bufferBase[cur] ^ ((UInt32)(_bufferBase[cur + 1]) << 8); 286 | 287 | UInt32 curMatch = _hash[kFixHashSize + hashValue]; 288 | _hash[kFixHashSize + hashValue] = _pos; 289 | 290 | UInt32 ptr0 = (_cyclicBufferPos << 1) + 1; 291 | UInt32 ptr1 = (_cyclicBufferPos << 1); 292 | 293 | UInt32 len0, len1; 294 | len0 = len1 = kNumHashDirectBytes; 295 | 296 | UInt32 count = _cutValue; 297 | while (true) 298 | { 299 | if (curMatch <= matchMinPos || count-- == 0) 300 | { 301 | _son[ptr0] = _son[ptr1] = kEmptyHashValue; 302 | break; 303 | } 304 | 305 | UInt32 delta = _pos - curMatch; 306 | UInt32 cyclicPos = ((delta <= _cyclicBufferPos) ? 307 | (_cyclicBufferPos - delta) : 308 | (_cyclicBufferPos - delta + _cyclicBufferSize)) << 1; 309 | 310 | UInt32 pby1 = _bufferOffset + curMatch; 311 | UInt32 len = Math.Min(len0, len1); 312 | if (_bufferBase[pby1 + len] == _bufferBase[cur + len]) 313 | { 314 | while (++len != lenLimit) 315 | if (_bufferBase[pby1 + len] != _bufferBase[cur + len]) 316 | break; 317 | if (len == lenLimit) 318 | { 319 | _son[ptr1] = _son[cyclicPos]; 320 | _son[ptr0] = _son[cyclicPos + 1]; 321 | break; 322 | } 323 | } 324 | if (_bufferBase[pby1 + len] < _bufferBase[cur + len]) 325 | { 326 | _son[ptr1] = curMatch; 327 | ptr1 = cyclicPos + 1; 328 | curMatch = _son[ptr1]; 329 | len1 = len; 330 | } 331 | else 332 | { 333 | _son[ptr0] = curMatch; 334 | ptr0 = cyclicPos; 335 | curMatch = _son[ptr0]; 336 | len0 = len; 337 | } 338 | } 339 | MovePos(); 340 | } 341 | while (--num != 0); 342 | } 343 | 344 | void NormalizeLinks(UInt32[] items, UInt32 numItems, UInt32 subValue) 345 | { 346 | for (UInt32 i = 0; i < numItems; i++) 347 | { 348 | UInt32 value = items[i]; 349 | if (value <= subValue) 350 | value = kEmptyHashValue; 351 | else 352 | value -= subValue; 353 | items[i] = value; 354 | } 355 | } 356 | 357 | void Normalize() 358 | { 359 | UInt32 subValue = _pos - _cyclicBufferSize; 360 | NormalizeLinks(_son, _cyclicBufferSize * 2, subValue); 361 | NormalizeLinks(_hash, _hashSizeSum, subValue); 362 | ReduceOffsets((Int32)subValue); 363 | } 364 | 365 | public void SetCutValue(UInt32 cutValue) { _cutValue = cutValue; } 366 | } 367 | } 368 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZ/LzInWindow.cs: -------------------------------------------------------------------------------- 1 | // LzInWindow.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | public class InWindow 8 | { 9 | public Byte[] _bufferBase = null; // pointer to buffer with data 10 | System.IO.Stream _stream; 11 | UInt32 _posLimit; // offset (from _buffer) of first byte when new block reading must be done 12 | Boolean _streamEndWasReached; // if (true) then _streamPos shows real end of stream 13 | 14 | UInt32 _pointerToLastSafePosition; 15 | 16 | public UInt32 _bufferOffset; 17 | 18 | public UInt32 _blockSize; // Size of Allocated memory block 19 | public UInt32 _pos; // offset (from _buffer) of curent byte 20 | UInt32 _keepSizeBefore; // how many BYTEs must be kept in buffer before _pos 21 | UInt32 _keepSizeAfter; // how many BYTEs must be kept buffer after _pos 22 | public UInt32 _streamPos; // offset (from _buffer) of first not read byte from Stream 23 | 24 | public void MoveBlock() 25 | { 26 | UInt32 offset = (UInt32)(_bufferOffset) + _pos - _keepSizeBefore; 27 | // we need one additional byte, since MovePos moves on 1 byte. 28 | if (offset > 0) 29 | offset--; 30 | 31 | UInt32 numBytes = (UInt32)(_bufferOffset) + _streamPos - offset; 32 | 33 | // check negative offset ???? 34 | for (UInt32 i = 0; i < numBytes; i++) 35 | _bufferBase[i] = _bufferBase[offset + i]; 36 | _bufferOffset -= offset; 37 | } 38 | 39 | public virtual void ReadBlock() 40 | { 41 | if (_streamEndWasReached) 42 | return; 43 | while (true) 44 | { 45 | Int32 size = (Int32)((0 - _bufferOffset) + _blockSize - _streamPos); 46 | if (size == 0) 47 | return; 48 | Int32 numReadBytes = _stream.Read(_bufferBase, (Int32)(_bufferOffset + _streamPos), size); 49 | if (numReadBytes == 0) 50 | { 51 | _posLimit = _streamPos; 52 | UInt32 pointerToPostion = _bufferOffset + _posLimit; 53 | if (pointerToPostion > _pointerToLastSafePosition) 54 | _posLimit = (UInt32)(_pointerToLastSafePosition - _bufferOffset); 55 | 56 | _streamEndWasReached = true; 57 | return; 58 | } 59 | _streamPos += (UInt32)numReadBytes; 60 | if (_streamPos >= _pos + _keepSizeAfter) 61 | _posLimit = _streamPos - _keepSizeAfter; 62 | } 63 | } 64 | 65 | void Free() { _bufferBase = null; } 66 | 67 | public void Create(UInt32 keepSizeBefore, UInt32 keepSizeAfter, UInt32 keepSizeReserv) 68 | { 69 | _keepSizeBefore = keepSizeBefore; 70 | _keepSizeAfter = keepSizeAfter; 71 | UInt32 blockSize = keepSizeBefore + keepSizeAfter + keepSizeReserv; 72 | if (_bufferBase == null || _blockSize != blockSize) 73 | { 74 | Free(); 75 | _blockSize = blockSize; 76 | _bufferBase = new Byte[_blockSize]; 77 | } 78 | _pointerToLastSafePosition = _blockSize - keepSizeAfter; 79 | } 80 | 81 | public void SetStream(System.IO.Stream stream) { _stream = stream; } 82 | public void ReleaseStream() { _stream = null; } 83 | 84 | public void Init() 85 | { 86 | _bufferOffset = 0; 87 | _pos = 0; 88 | _streamPos = 0; 89 | _streamEndWasReached = false; 90 | ReadBlock(); 91 | } 92 | 93 | public void MovePos() 94 | { 95 | _pos++; 96 | if (_pos > _posLimit) 97 | { 98 | UInt32 pointerToPostion = _bufferOffset + _pos; 99 | if (pointerToPostion > _pointerToLastSafePosition) 100 | MoveBlock(); 101 | ReadBlock(); 102 | } 103 | } 104 | 105 | public Byte GetIndexByte(Int32 index) { return _bufferBase[_bufferOffset + _pos + index]; } 106 | 107 | // index + limit have not to exceed _keepSizeAfter; 108 | public UInt32 GetMatchLen(Int32 index, UInt32 distance, UInt32 limit) 109 | { 110 | if (_streamEndWasReached) 111 | if ((_pos + index) + limit > _streamPos) 112 | limit = _streamPos - (UInt32)(_pos + index); 113 | distance++; 114 | // Byte *pby = _buffer + (size_t)_pos + index; 115 | UInt32 pby = _bufferOffset + _pos + (UInt32)index; 116 | 117 | UInt32 i; 118 | for (i = 0; i < limit && _bufferBase[pby + i] == _bufferBase[pby + i - distance]; i++); 119 | return i; 120 | } 121 | 122 | public UInt32 GetNumAvailableBytes() { return _streamPos - _pos; } 123 | 124 | public void ReduceOffsets(Int32 subValue) 125 | { 126 | _bufferOffset += (UInt32)subValue; 127 | _posLimit -= (UInt32)subValue; 128 | _pos -= (UInt32)subValue; 129 | _streamPos -= (UInt32)subValue; 130 | } 131 | } 132 | } 133 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZ/LzOutWindow.cs: -------------------------------------------------------------------------------- 1 | // LzOutWindow.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZ 6 | { 7 | public class OutWindow 8 | { 9 | Byte[] _buffer = null; 10 | UInt32 _pos; 11 | UInt32 _windowSize = 0; 12 | UInt32 _streamPos; 13 | System.IO.Stream _stream; 14 | 15 | public UInt32 TrainSize = 0; 16 | 17 | public void Create(UInt32 windowSize) 18 | { 19 | if (_windowSize != windowSize) 20 | { 21 | // System.GC.Collect(); 22 | _buffer = new Byte[windowSize]; 23 | } 24 | _windowSize = windowSize; 25 | _pos = 0; 26 | _streamPos = 0; 27 | } 28 | 29 | public void Init(System.IO.Stream stream, Boolean solid) 30 | { 31 | ReleaseStream(); 32 | _stream = stream; 33 | if (!solid) 34 | { 35 | _streamPos = 0; 36 | _pos = 0; 37 | TrainSize = 0; 38 | } 39 | } 40 | 41 | public Boolean Train(System.IO.Stream stream) 42 | { 43 | Int64 len = stream.Length; 44 | UInt32 size = (len < _windowSize) ? (UInt32)len : _windowSize; 45 | TrainSize = size; 46 | stream.Position = len - size; 47 | _streamPos = _pos = 0; 48 | while (size > 0) 49 | { 50 | UInt32 curSize = _windowSize - _pos; 51 | if (size < curSize) 52 | curSize = size; 53 | Int32 numReadBytes = stream.Read(_buffer, (Int32)_pos, (Int32)curSize); 54 | if (numReadBytes == 0) 55 | return false; 56 | size -= (UInt32)numReadBytes; 57 | _pos += (UInt32)numReadBytes; 58 | _streamPos += (UInt32)numReadBytes; 59 | if (_pos == _windowSize) 60 | _streamPos = _pos = 0; 61 | } 62 | return true; 63 | } 64 | 65 | public void ReleaseStream() 66 | { 67 | Flush(); 68 | _stream = null; 69 | } 70 | 71 | public void Flush() 72 | { 73 | UInt32 size = _pos - _streamPos; 74 | if (size == 0) 75 | return; 76 | _stream.Write(_buffer, (Int32)_streamPos, (Int32)size); 77 | if (_pos >= _windowSize) 78 | _pos = 0; 79 | _streamPos = _pos; 80 | } 81 | 82 | public void CopyBlock(UInt32 distance, UInt32 len) 83 | { 84 | UInt32 pos = _pos - distance - 1; 85 | if (pos >= _windowSize) 86 | pos += _windowSize; 87 | for (; len > 0; len--) 88 | { 89 | if (pos >= _windowSize) 90 | pos = 0; 91 | _buffer[_pos++] = _buffer[pos++]; 92 | if (_pos >= _windowSize) 93 | Flush(); 94 | } 95 | } 96 | 97 | public void PutByte(Byte b) 98 | { 99 | _buffer[_pos++] = b; 100 | if (_pos >= _windowSize) 101 | Flush(); 102 | } 103 | 104 | public Byte GetByte(UInt32 distance) 105 | { 106 | UInt32 pos = _pos - distance - 1; 107 | if (pos >= _windowSize) 108 | pos += _windowSize; 109 | return _buffer[pos]; 110 | } 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZMA/LzmaBase.cs: -------------------------------------------------------------------------------- 1 | // LzmaBase.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZMA 6 | { 7 | internal abstract class Base 8 | { 9 | public const UInt32 kNumRepDistances = 4; 10 | public const UInt32 kNumStates = 12; 11 | 12 | // static byte []kLiteralNextStates = {0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5}; 13 | // static byte []kMatchNextStates = {7, 7, 7, 7, 7, 7, 7, 10, 10, 10, 10, 10}; 14 | // static byte []kRepNextStates = {8, 8, 8, 8, 8, 8, 8, 11, 11, 11, 11, 11}; 15 | // static byte []kShortRepNextStates = {9, 9, 9, 9, 9, 9, 9, 11, 11, 11, 11, 11}; 16 | 17 | public struct State 18 | { 19 | public UInt32 Index; 20 | public void Init() { Index = 0; } 21 | public void UpdateChar() 22 | { 23 | if (Index < 4) Index = 0; 24 | else if (Index < 10) Index -= 3; 25 | else Index -= 6; 26 | } 27 | public void UpdateMatch() { Index = (UInt32)(Index < 7 ? 7 : 10); } 28 | public void UpdateRep() { Index = (UInt32)(Index < 7 ? 8 : 11); } 29 | public void UpdateShortRep() { Index = (UInt32)(Index < 7 ? 9 : 11); } 30 | public Boolean IsCharState() { return Index < 7; } 31 | } 32 | 33 | public const Int32 kNumPosSlotBits = 6; 34 | public const Int32 kDicLogSizeMin = 0; 35 | // public const int kDicLogSizeMax = 30; 36 | // public const uint kDistTableSizeMax = kDicLogSizeMax * 2; 37 | 38 | public const Int32 kNumLenToPosStatesBits = 2; // it's for speed optimization 39 | public const UInt32 kNumLenToPosStates = 1 << kNumLenToPosStatesBits; 40 | 41 | public const UInt32 kMatchMinLen = 2; 42 | 43 | public static UInt32 GetLenToPosState(UInt32 len) 44 | { 45 | len -= kMatchMinLen; 46 | if (len < kNumLenToPosStates) 47 | return len; 48 | return (UInt32)(kNumLenToPosStates - 1); 49 | } 50 | 51 | public const Int32 kNumAlignBits = 4; 52 | public const UInt32 kAlignTableSize = 1 << kNumAlignBits; 53 | public const UInt32 kAlignMask = (kAlignTableSize - 1); 54 | 55 | public const UInt32 kStartPosModelIndex = 4; 56 | public const UInt32 kEndPosModelIndex = 14; 57 | public const UInt32 kNumPosModels = kEndPosModelIndex - kStartPosModelIndex; 58 | 59 | public const UInt32 kNumFullDistances = 1 << ((Int32)kEndPosModelIndex / 2); 60 | 61 | public const UInt32 kNumLitPosStatesBitsEncodingMax = 4; 62 | public const UInt32 kNumLitContextBitsMax = 8; 63 | 64 | public const Int32 kNumPosStatesBitsMax = 4; 65 | public const UInt32 kNumPosStatesMax = (1 << kNumPosStatesBitsMax); 66 | public const Int32 kNumPosStatesBitsEncodingMax = 4; 67 | public const UInt32 kNumPosStatesEncodingMax = (1 << kNumPosStatesBitsEncodingMax); 68 | 69 | public const Int32 kNumLowLenBits = 3; 70 | public const Int32 kNumMidLenBits = 3; 71 | public const Int32 kNumHighLenBits = 8; 72 | public const UInt32 kNumLowLenSymbols = 1 << kNumLowLenBits; 73 | public const UInt32 kNumMidLenSymbols = 1 << kNumMidLenBits; 74 | public const UInt32 kNumLenSymbols = kNumLowLenSymbols + kNumMidLenSymbols + 75 | (1 << kNumHighLenBits); 76 | public const UInt32 kMatchMaxLen = kMatchMinLen + kNumLenSymbols - 1; 77 | } 78 | } 79 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZMA/LzmaDecoder.cs: -------------------------------------------------------------------------------- 1 | // LzmaDecoder.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZMA 6 | { 7 | using RangeCoder; 8 | 9 | public class Decoder : ICoder, ISetDecoderProperties // ,System.IO.Stream 10 | { 11 | class LenDecoder 12 | { 13 | BitDecoder m_Choice = new BitDecoder(); 14 | BitDecoder m_Choice2 = new BitDecoder(); 15 | BitTreeDecoder[] m_LowCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; 16 | BitTreeDecoder[] m_MidCoder = new BitTreeDecoder[Base.kNumPosStatesMax]; 17 | BitTreeDecoder m_HighCoder = new BitTreeDecoder(Base.kNumHighLenBits); 18 | UInt32 m_NumPosStates = 0; 19 | 20 | public void Create(UInt32 numPosStates) 21 | { 22 | for (UInt32 posState = m_NumPosStates; posState < numPosStates; posState++) 23 | { 24 | m_LowCoder[posState] = new BitTreeDecoder(Base.kNumLowLenBits); 25 | m_MidCoder[posState] = new BitTreeDecoder(Base.kNumMidLenBits); 26 | } 27 | m_NumPosStates = numPosStates; 28 | } 29 | 30 | public void Init() 31 | { 32 | m_Choice.Init(); 33 | for (UInt32 posState = 0; posState < m_NumPosStates; posState++) 34 | { 35 | m_LowCoder[posState].Init(); 36 | m_MidCoder[posState].Init(); 37 | } 38 | m_Choice2.Init(); 39 | m_HighCoder.Init(); 40 | } 41 | 42 | public UInt32 Decode(RangeCoder.Decoder rangeDecoder, UInt32 posState) 43 | { 44 | if (m_Choice.Decode(rangeDecoder) == 0) 45 | return m_LowCoder[posState].Decode(rangeDecoder); 46 | else 47 | { 48 | UInt32 symbol = Base.kNumLowLenSymbols; 49 | if (m_Choice2.Decode(rangeDecoder) == 0) 50 | symbol += m_MidCoder[posState].Decode(rangeDecoder); 51 | else 52 | { 53 | symbol += Base.kNumMidLenSymbols; 54 | symbol += m_HighCoder.Decode(rangeDecoder); 55 | } 56 | return symbol; 57 | } 58 | } 59 | } 60 | 61 | class LiteralDecoder 62 | { 63 | struct Decoder2 64 | { 65 | BitDecoder[] m_Decoders; 66 | public void Create() { m_Decoders = new BitDecoder[0x300]; } 67 | public void Init() { for (Int32 i = 0; i < 0x300; i++) m_Decoders[i].Init(); } 68 | 69 | public Byte DecodeNormal(RangeCoder.Decoder rangeDecoder) 70 | { 71 | UInt32 symbol = 1; 72 | do 73 | symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); 74 | while (symbol < 0x100); 75 | return (Byte)symbol; 76 | } 77 | 78 | public Byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, Byte matchByte) 79 | { 80 | UInt32 symbol = 1; 81 | do 82 | { 83 | UInt32 matchBit = (UInt32)(matchByte >> 7) & 1; 84 | matchByte <<= 1; 85 | UInt32 bit = m_Decoders[((1 + matchBit) << 8) + symbol].Decode(rangeDecoder); 86 | symbol = (symbol << 1) | bit; 87 | if (matchBit != bit) 88 | { 89 | while (symbol < 0x100) 90 | symbol = (symbol << 1) | m_Decoders[symbol].Decode(rangeDecoder); 91 | break; 92 | } 93 | } 94 | while (symbol < 0x100); 95 | return (Byte)symbol; 96 | } 97 | } 98 | 99 | Decoder2[] m_Coders; 100 | Int32 m_NumPrevBits; 101 | Int32 m_NumPosBits; 102 | UInt32 m_PosMask; 103 | 104 | public void Create(Int32 numPosBits, Int32 numPrevBits) 105 | { 106 | if (m_Coders != null && m_NumPrevBits == numPrevBits && 107 | m_NumPosBits == numPosBits) 108 | return; 109 | m_NumPosBits = numPosBits; 110 | m_PosMask = ((UInt32)1 << numPosBits) - 1; 111 | m_NumPrevBits = numPrevBits; 112 | UInt32 numStates = (UInt32)1 << (m_NumPrevBits + m_NumPosBits); 113 | m_Coders = new Decoder2[numStates]; 114 | for (UInt32 i = 0; i < numStates; i++) 115 | m_Coders[i].Create(); 116 | } 117 | 118 | public void Init() 119 | { 120 | UInt32 numStates = (UInt32)1 << (m_NumPrevBits + m_NumPosBits); 121 | for (UInt32 i = 0; i < numStates; i++) 122 | m_Coders[i].Init(); 123 | } 124 | 125 | UInt32 GetState(UInt32 pos, Byte prevByte) 126 | { return ((pos & m_PosMask) << m_NumPrevBits) + (UInt32)(prevByte >> (8 - m_NumPrevBits)); } 127 | 128 | public Byte DecodeNormal(RangeCoder.Decoder rangeDecoder, UInt32 pos, Byte prevByte) 129 | { return m_Coders[GetState(pos, prevByte)].DecodeNormal(rangeDecoder); } 130 | 131 | public Byte DecodeWithMatchByte(RangeCoder.Decoder rangeDecoder, UInt32 pos, Byte prevByte, Byte matchByte) 132 | { return m_Coders[GetState(pos, prevByte)].DecodeWithMatchByte(rangeDecoder, matchByte); } 133 | }; 134 | 135 | LZ.OutWindow m_OutWindow = new LZ.OutWindow(); 136 | RangeCoder.Decoder m_RangeDecoder = new RangeCoder.Decoder(); 137 | 138 | BitDecoder[] m_IsMatchDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; 139 | BitDecoder[] m_IsRepDecoders = new BitDecoder[Base.kNumStates]; 140 | BitDecoder[] m_IsRepG0Decoders = new BitDecoder[Base.kNumStates]; 141 | BitDecoder[] m_IsRepG1Decoders = new BitDecoder[Base.kNumStates]; 142 | BitDecoder[] m_IsRepG2Decoders = new BitDecoder[Base.kNumStates]; 143 | BitDecoder[] m_IsRep0LongDecoders = new BitDecoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; 144 | 145 | BitTreeDecoder[] m_PosSlotDecoder = new BitTreeDecoder[Base.kNumLenToPosStates]; 146 | BitDecoder[] m_PosDecoders = new BitDecoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; 147 | 148 | BitTreeDecoder m_PosAlignDecoder = new BitTreeDecoder(Base.kNumAlignBits); 149 | 150 | LenDecoder m_LenDecoder = new LenDecoder(); 151 | LenDecoder m_RepLenDecoder = new LenDecoder(); 152 | 153 | LiteralDecoder m_LiteralDecoder = new LiteralDecoder(); 154 | 155 | UInt32 m_DictionarySize; 156 | UInt32 m_DictionarySizeCheck; 157 | 158 | UInt32 m_PosStateMask; 159 | 160 | public Decoder() 161 | { 162 | m_DictionarySize = 0xFFFFFFFF; 163 | for (Int32 i = 0; i < Base.kNumLenToPosStates; i++) 164 | m_PosSlotDecoder[i] = new BitTreeDecoder(Base.kNumPosSlotBits); 165 | } 166 | 167 | void SetDictionarySize(UInt32 dictionarySize) 168 | { 169 | if (m_DictionarySize != dictionarySize) 170 | { 171 | m_DictionarySize = dictionarySize; 172 | m_DictionarySizeCheck = Math.Max(m_DictionarySize, 1); 173 | UInt32 blockSize = Math.Max(m_DictionarySizeCheck, (1 << 12)); 174 | m_OutWindow.Create(blockSize); 175 | } 176 | } 177 | 178 | void SetLiteralProperties(Int32 lp, Int32 lc) 179 | { 180 | if (lp > 8) 181 | throw new InvalidParamException(); 182 | if (lc > 8) 183 | throw new InvalidParamException(); 184 | m_LiteralDecoder.Create(lp, lc); 185 | } 186 | 187 | void SetPosBitsProperties(Int32 pb) 188 | { 189 | if (pb > Base.kNumPosStatesBitsMax) 190 | throw new InvalidParamException(); 191 | UInt32 numPosStates = (UInt32)1 << pb; 192 | m_LenDecoder.Create(numPosStates); 193 | m_RepLenDecoder.Create(numPosStates); 194 | m_PosStateMask = numPosStates - 1; 195 | } 196 | 197 | Boolean _solid = false; 198 | void Init(System.IO.Stream inStream, System.IO.Stream outStream) 199 | { 200 | m_RangeDecoder.Init(inStream); 201 | m_OutWindow.Init(outStream, _solid); 202 | 203 | UInt32 i; 204 | for (i = 0; i < Base.kNumStates; i++) 205 | { 206 | for (UInt32 j = 0; j <= m_PosStateMask; j++) 207 | { 208 | UInt32 index = (i << Base.kNumPosStatesBitsMax) + j; 209 | m_IsMatchDecoders[index].Init(); 210 | m_IsRep0LongDecoders[index].Init(); 211 | } 212 | m_IsRepDecoders[i].Init(); 213 | m_IsRepG0Decoders[i].Init(); 214 | m_IsRepG1Decoders[i].Init(); 215 | m_IsRepG2Decoders[i].Init(); 216 | } 217 | 218 | m_LiteralDecoder.Init(); 219 | for (i = 0; i < Base.kNumLenToPosStates; i++) 220 | m_PosSlotDecoder[i].Init(); 221 | // m_PosSpecDecoder.Init(); 222 | for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) 223 | m_PosDecoders[i].Init(); 224 | 225 | m_LenDecoder.Init(); 226 | m_RepLenDecoder.Init(); 227 | m_PosAlignDecoder.Init(); 228 | } 229 | 230 | public void Code(System.IO.Stream inStream, System.IO.Stream outStream, 231 | Int64 inSize, Int64 outSize, ICodeProgress progress) 232 | { 233 | Init(inStream, outStream); 234 | 235 | Base.State state = new Base.State(); 236 | state.Init(); 237 | UInt32 rep0 = 0, rep1 = 0, rep2 = 0, rep3 = 0; 238 | 239 | UInt64 nowPos64 = 0; 240 | UInt64 outSize64 = (UInt64)outSize; 241 | if (nowPos64 < outSize64) 242 | { 243 | if (m_IsMatchDecoders[state.Index << Base.kNumPosStatesBitsMax].Decode(m_RangeDecoder) != 0) 244 | throw new DataErrorException(); 245 | state.UpdateChar(); 246 | Byte b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, 0, 0); 247 | m_OutWindow.PutByte(b); 248 | nowPos64++; 249 | } 250 | while (nowPos64 < outSize64) 251 | { 252 | // UInt64 next = Math.Min(nowPos64 + (1 << 18), outSize64); 253 | // while(nowPos64 < next) 254 | { 255 | UInt32 posState = (UInt32)nowPos64 & m_PosStateMask; 256 | if (m_IsMatchDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) 257 | { 258 | Byte b; 259 | Byte prevByte = m_OutWindow.GetByte(0); 260 | if (!state.IsCharState()) 261 | b = m_LiteralDecoder.DecodeWithMatchByte(m_RangeDecoder, 262 | (UInt32)nowPos64, prevByte, m_OutWindow.GetByte(rep0)); 263 | else 264 | b = m_LiteralDecoder.DecodeNormal(m_RangeDecoder, (UInt32)nowPos64, prevByte); 265 | m_OutWindow.PutByte(b); 266 | state.UpdateChar(); 267 | nowPos64++; 268 | } 269 | else 270 | { 271 | UInt32 len; 272 | if (m_IsRepDecoders[state.Index].Decode(m_RangeDecoder) == 1) 273 | { 274 | if (m_IsRepG0Decoders[state.Index].Decode(m_RangeDecoder) == 0) 275 | { 276 | if (m_IsRep0LongDecoders[(state.Index << Base.kNumPosStatesBitsMax) + posState].Decode(m_RangeDecoder) == 0) 277 | { 278 | state.UpdateShortRep(); 279 | m_OutWindow.PutByte(m_OutWindow.GetByte(rep0)); 280 | nowPos64++; 281 | continue; 282 | } 283 | } 284 | else 285 | { 286 | UInt32 distance; 287 | if (m_IsRepG1Decoders[state.Index].Decode(m_RangeDecoder) == 0) 288 | { 289 | distance = rep1; 290 | } 291 | else 292 | { 293 | if (m_IsRepG2Decoders[state.Index].Decode(m_RangeDecoder) == 0) 294 | distance = rep2; 295 | else 296 | { 297 | distance = rep3; 298 | rep3 = rep2; 299 | } 300 | rep2 = rep1; 301 | } 302 | rep1 = rep0; 303 | rep0 = distance; 304 | } 305 | len = m_RepLenDecoder.Decode(m_RangeDecoder, posState) + Base.kMatchMinLen; 306 | state.UpdateRep(); 307 | } 308 | else 309 | { 310 | rep3 = rep2; 311 | rep2 = rep1; 312 | rep1 = rep0; 313 | len = Base.kMatchMinLen + m_LenDecoder.Decode(m_RangeDecoder, posState); 314 | state.UpdateMatch(); 315 | UInt32 posSlot = m_PosSlotDecoder[Base.GetLenToPosState(len)].Decode(m_RangeDecoder); 316 | if (posSlot >= Base.kStartPosModelIndex) 317 | { 318 | Int32 numDirectBits = (Int32)((posSlot >> 1) - 1); 319 | rep0 = ((2 | (posSlot & 1)) << numDirectBits); 320 | if (posSlot < Base.kEndPosModelIndex) 321 | rep0 += BitTreeDecoder.ReverseDecode(m_PosDecoders, 322 | rep0 - posSlot - 1, m_RangeDecoder, numDirectBits); 323 | else 324 | { 325 | rep0 += (m_RangeDecoder.DecodeDirectBits( 326 | numDirectBits - Base.kNumAlignBits) << Base.kNumAlignBits); 327 | rep0 += m_PosAlignDecoder.ReverseDecode(m_RangeDecoder); 328 | } 329 | } 330 | else 331 | rep0 = posSlot; 332 | } 333 | if (rep0 >= m_OutWindow.TrainSize + nowPos64 || rep0 >= m_DictionarySizeCheck) 334 | { 335 | if (rep0 == 0xFFFFFFFF) 336 | break; 337 | throw new DataErrorException(); 338 | } 339 | m_OutWindow.CopyBlock(rep0, len); 340 | nowPos64 += len; 341 | } 342 | } 343 | } 344 | m_OutWindow.Flush(); 345 | m_OutWindow.ReleaseStream(); 346 | m_RangeDecoder.ReleaseStream(); 347 | } 348 | 349 | public void SetDecoderProperties(Byte[] properties) 350 | { 351 | if (properties.Length < 5) 352 | throw new InvalidParamException(); 353 | Int32 lc = properties[0] % 9; 354 | Int32 remainder = properties[0] / 9; 355 | Int32 lp = remainder % 5; 356 | Int32 pb = remainder / 5; 357 | if (pb > Base.kNumPosStatesBitsMax) 358 | throw new InvalidParamException(); 359 | UInt32 dictionarySize = 0; 360 | for (Int32 i = 0; i < 4; i++) 361 | dictionarySize += ((UInt32)(properties[1 + i])) << (i * 8); 362 | SetDictionarySize(dictionarySize); 363 | SetLiteralProperties(lp, lc); 364 | SetPosBitsProperties(pb); 365 | } 366 | 367 | public Boolean Train(System.IO.Stream stream) 368 | { 369 | _solid = true; 370 | return m_OutWindow.Train(stream); 371 | } 372 | 373 | /* 374 | public override bool CanRead { get { return true; }} 375 | public override bool CanWrite { get { return true; }} 376 | public override bool CanSeek { get { return true; }} 377 | public override long Length { get { return 0; }} 378 | public override long Position 379 | { 380 | get { return 0; } 381 | set { } 382 | } 383 | public override void Flush() { } 384 | public override int Read(byte[] buffer, int offset, int count) 385 | { 386 | return 0; 387 | } 388 | public override void Write(byte[] buffer, int offset, int count) 389 | { 390 | } 391 | public override long Seek(long offset, System.IO.SeekOrigin origin) 392 | { 393 | return 0; 394 | } 395 | public override void SetLength(long value) {} 396 | */ 397 | } 398 | } 399 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/LZMA/LzmaEncoder.cs: -------------------------------------------------------------------------------- 1 | // LzmaEncoder.cs 2 | 3 | using System; 4 | 5 | namespace SevenZip.Compression.LZMA 6 | { 7 | using RangeCoder; 8 | 9 | public class Encoder : ICoder, ISetCoderProperties, IWriteCoderProperties 10 | { 11 | enum EMatchFinderType 12 | { 13 | BT2, 14 | BT4, 15 | }; 16 | 17 | const UInt32 kIfinityPrice = 0xFFFFFFF; 18 | 19 | static Byte[] g_FastPos = new Byte[1 << 11]; 20 | 21 | static Encoder() 22 | { 23 | const Byte kFastSlots = 22; 24 | Int32 c = 2; 25 | g_FastPos[0] = 0; 26 | g_FastPos[1] = 1; 27 | for (Byte slotFast = 2; slotFast < kFastSlots; slotFast++) 28 | { 29 | UInt32 k = ((UInt32)1 << ((slotFast >> 1) - 1)); 30 | for (UInt32 j = 0; j < k; j++, c++) 31 | g_FastPos[c] = slotFast; 32 | } 33 | } 34 | 35 | static UInt32 GetPosSlot(UInt32 pos) 36 | { 37 | if (pos < (1 << 11)) 38 | return g_FastPos[pos]; 39 | if (pos < (1 << 21)) 40 | return (UInt32)(g_FastPos[pos >> 10] + 20); 41 | return (UInt32)(g_FastPos[pos >> 20] + 40); 42 | } 43 | 44 | static UInt32 GetPosSlot2(UInt32 pos) 45 | { 46 | if (pos < (1 << 17)) 47 | return (UInt32)(g_FastPos[pos >> 6] + 12); 48 | if (pos < (1 << 27)) 49 | return (UInt32)(g_FastPos[pos >> 16] + 32); 50 | return (UInt32)(g_FastPos[pos >> 26] + 52); 51 | } 52 | 53 | Base.State _state = new Base.State(); 54 | Byte _previousByte; 55 | UInt32[] _repDistances = new UInt32[Base.kNumRepDistances]; 56 | 57 | void BaseInit() 58 | { 59 | _state.Init(); 60 | _previousByte = 0; 61 | for (UInt32 i = 0; i < Base.kNumRepDistances; i++) 62 | _repDistances[i] = 0; 63 | } 64 | 65 | const Int32 kDefaultDictionaryLogSize = 22; 66 | const UInt32 kNumFastBytesDefault = 0x20; 67 | 68 | class LiteralEncoder 69 | { 70 | public struct Encoder2 71 | { 72 | BitEncoder[] m_Encoders; 73 | 74 | public void Create() { m_Encoders = new BitEncoder[0x300]; } 75 | 76 | public void Init() { for (Int32 i = 0; i < 0x300; i++) m_Encoders[i].Init(); } 77 | 78 | public void Encode(RangeCoder.Encoder rangeEncoder, Byte symbol) 79 | { 80 | UInt32 context = 1; 81 | for (Int32 i = 7; i >= 0; i--) 82 | { 83 | UInt32 bit = (UInt32)((symbol >> i) & 1); 84 | m_Encoders[context].Encode(rangeEncoder, bit); 85 | context = (context << 1) | bit; 86 | } 87 | } 88 | 89 | public void EncodeMatched(RangeCoder.Encoder rangeEncoder, Byte matchByte, Byte symbol) 90 | { 91 | UInt32 context = 1; 92 | Boolean same = true; 93 | for (Int32 i = 7; i >= 0; i--) 94 | { 95 | UInt32 bit = (UInt32)((symbol >> i) & 1); 96 | UInt32 state = context; 97 | if (same) 98 | { 99 | UInt32 matchBit = (UInt32)((matchByte >> i) & 1); 100 | state += ((1 + matchBit) << 8); 101 | same = (matchBit == bit); 102 | } 103 | m_Encoders[state].Encode(rangeEncoder, bit); 104 | context = (context << 1) | bit; 105 | } 106 | } 107 | 108 | public UInt32 GetPrice(Boolean matchMode, Byte matchByte, Byte symbol) 109 | { 110 | UInt32 price = 0; 111 | UInt32 context = 1; 112 | Int32 i = 7; 113 | if (matchMode) 114 | { 115 | for (; i >= 0; i--) 116 | { 117 | UInt32 matchBit = (UInt32)(matchByte >> i) & 1; 118 | UInt32 bit = (UInt32)(symbol >> i) & 1; 119 | price += m_Encoders[((1 + matchBit) << 8) + context].GetPrice(bit); 120 | context = (context << 1) | bit; 121 | if (matchBit != bit) 122 | { 123 | i--; 124 | break; 125 | } 126 | } 127 | } 128 | for (; i >= 0; i--) 129 | { 130 | UInt32 bit = (UInt32)(symbol >> i) & 1; 131 | price += m_Encoders[context].GetPrice(bit); 132 | context = (context << 1) | bit; 133 | } 134 | return price; 135 | } 136 | } 137 | 138 | Encoder2[] m_Coders; 139 | Int32 m_NumPrevBits; 140 | Int32 m_NumPosBits; 141 | UInt32 m_PosMask; 142 | 143 | public void Create(Int32 numPosBits, Int32 numPrevBits) 144 | { 145 | if (m_Coders != null && m_NumPrevBits == numPrevBits && m_NumPosBits == numPosBits) 146 | return; 147 | m_NumPosBits = numPosBits; 148 | m_PosMask = ((UInt32)1 << numPosBits) - 1; 149 | m_NumPrevBits = numPrevBits; 150 | UInt32 numStates = (UInt32)1 << (m_NumPrevBits + m_NumPosBits); 151 | m_Coders = new Encoder2[numStates]; 152 | for (UInt32 i = 0; i < numStates; i++) 153 | m_Coders[i].Create(); 154 | } 155 | 156 | public void Init() 157 | { 158 | UInt32 numStates = (UInt32)1 << (m_NumPrevBits + m_NumPosBits); 159 | for (UInt32 i = 0; i < numStates; i++) 160 | m_Coders[i].Init(); 161 | } 162 | 163 | public Encoder2 GetSubCoder(UInt32 pos, Byte prevByte) 164 | { return m_Coders[((pos & m_PosMask) << m_NumPrevBits) + (UInt32)(prevByte >> (8 - m_NumPrevBits))]; } 165 | } 166 | 167 | class LenEncoder 168 | { 169 | RangeCoder.BitEncoder _choice = new RangeCoder.BitEncoder(); 170 | RangeCoder.BitEncoder _choice2 = new RangeCoder.BitEncoder(); 171 | RangeCoder.BitTreeEncoder[] _lowCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; 172 | RangeCoder.BitTreeEncoder[] _midCoder = new RangeCoder.BitTreeEncoder[Base.kNumPosStatesEncodingMax]; 173 | RangeCoder.BitTreeEncoder _highCoder = new RangeCoder.BitTreeEncoder(Base.kNumHighLenBits); 174 | 175 | public LenEncoder() 176 | { 177 | for (UInt32 posState = 0; posState < Base.kNumPosStatesEncodingMax; posState++) 178 | { 179 | _lowCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumLowLenBits); 180 | _midCoder[posState] = new RangeCoder.BitTreeEncoder(Base.kNumMidLenBits); 181 | } 182 | } 183 | 184 | public void Init(UInt32 numPosStates) 185 | { 186 | _choice.Init(); 187 | _choice2.Init(); 188 | for (UInt32 posState = 0; posState < numPosStates; posState++) 189 | { 190 | _lowCoder[posState].Init(); 191 | _midCoder[posState].Init(); 192 | } 193 | _highCoder.Init(); 194 | } 195 | 196 | public void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) 197 | { 198 | if (symbol < Base.kNumLowLenSymbols) 199 | { 200 | _choice.Encode(rangeEncoder, 0); 201 | _lowCoder[posState].Encode(rangeEncoder, symbol); 202 | } 203 | else 204 | { 205 | symbol -= Base.kNumLowLenSymbols; 206 | _choice.Encode(rangeEncoder, 1); 207 | if (symbol < Base.kNumMidLenSymbols) 208 | { 209 | _choice2.Encode(rangeEncoder, 0); 210 | _midCoder[posState].Encode(rangeEncoder, symbol); 211 | } 212 | else 213 | { 214 | _choice2.Encode(rangeEncoder, 1); 215 | _highCoder.Encode(rangeEncoder, symbol - Base.kNumMidLenSymbols); 216 | } 217 | } 218 | } 219 | 220 | public void SetPrices(UInt32 posState, UInt32 numSymbols, UInt32[] prices, UInt32 st) 221 | { 222 | UInt32 a0 = _choice.GetPrice0(); 223 | UInt32 a1 = _choice.GetPrice1(); 224 | UInt32 b0 = a1 + _choice2.GetPrice0(); 225 | UInt32 b1 = a1 + _choice2.GetPrice1(); 226 | UInt32 i = 0; 227 | for (i = 0; i < Base.kNumLowLenSymbols; i++) 228 | { 229 | if (i >= numSymbols) 230 | return; 231 | prices[st + i] = a0 + _lowCoder[posState].GetPrice(i); 232 | } 233 | for (; i < Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; i++) 234 | { 235 | if (i >= numSymbols) 236 | return; 237 | prices[st + i] = b0 + _midCoder[posState].GetPrice(i - Base.kNumLowLenSymbols); 238 | } 239 | for (; i < numSymbols; i++) 240 | prices[st + i] = b1 + _highCoder.GetPrice(i - Base.kNumLowLenSymbols - Base.kNumMidLenSymbols); 241 | } 242 | }; 243 | 244 | const UInt32 kNumLenSpecSymbols = Base.kNumLowLenSymbols + Base.kNumMidLenSymbols; 245 | 246 | class LenPriceTableEncoder : LenEncoder 247 | { 248 | UInt32[] _prices = new UInt32[Base.kNumLenSymbols << Base.kNumPosStatesBitsEncodingMax]; 249 | UInt32 _tableSize; 250 | UInt32[] _counters = new UInt32[Base.kNumPosStatesEncodingMax]; 251 | 252 | public void SetTableSize(UInt32 tableSize) { _tableSize = tableSize; } 253 | 254 | public UInt32 GetPrice(UInt32 symbol, UInt32 posState) 255 | { 256 | return _prices[posState * Base.kNumLenSymbols + symbol]; 257 | } 258 | 259 | void UpdateTable(UInt32 posState) 260 | { 261 | SetPrices(posState, _tableSize, _prices, posState * Base.kNumLenSymbols); 262 | _counters[posState] = _tableSize; 263 | } 264 | 265 | public void UpdateTables(UInt32 numPosStates) 266 | { 267 | for (UInt32 posState = 0; posState < numPosStates; posState++) 268 | UpdateTable(posState); 269 | } 270 | 271 | public new void Encode(RangeCoder.Encoder rangeEncoder, UInt32 symbol, UInt32 posState) 272 | { 273 | base.Encode(rangeEncoder, symbol, posState); 274 | if (--_counters[posState] == 0) 275 | UpdateTable(posState); 276 | } 277 | } 278 | 279 | const UInt32 kNumOpts = 1 << 12; 280 | class Optimal 281 | { 282 | public Base.State State; 283 | 284 | public Boolean Prev1IsChar; 285 | public Boolean Prev2; 286 | 287 | public UInt32 PosPrev2; 288 | public UInt32 BackPrev2; 289 | 290 | public UInt32 Price; 291 | public UInt32 PosPrev; 292 | public UInt32 BackPrev; 293 | 294 | public UInt32 Backs0; 295 | public UInt32 Backs1; 296 | public UInt32 Backs2; 297 | public UInt32 Backs3; 298 | 299 | public void MakeAsChar() { BackPrev = 0xFFFFFFFF; Prev1IsChar = false; } 300 | public void MakeAsShortRep() { BackPrev = 0; ; Prev1IsChar = false; } 301 | public Boolean IsShortRep() { return (BackPrev == 0); } 302 | }; 303 | Optimal[] _optimum = new Optimal[kNumOpts]; 304 | LZ.IMatchFinder _matchFinder = null; 305 | RangeCoder.Encoder _rangeEncoder = new RangeCoder.Encoder(); 306 | 307 | RangeCoder.BitEncoder[] _isMatch = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; 308 | RangeCoder.BitEncoder[] _isRep = new RangeCoder.BitEncoder[Base.kNumStates]; 309 | RangeCoder.BitEncoder[] _isRepG0 = new RangeCoder.BitEncoder[Base.kNumStates]; 310 | RangeCoder.BitEncoder[] _isRepG1 = new RangeCoder.BitEncoder[Base.kNumStates]; 311 | RangeCoder.BitEncoder[] _isRepG2 = new RangeCoder.BitEncoder[Base.kNumStates]; 312 | RangeCoder.BitEncoder[] _isRep0Long = new RangeCoder.BitEncoder[Base.kNumStates << Base.kNumPosStatesBitsMax]; 313 | 314 | RangeCoder.BitTreeEncoder[] _posSlotEncoder = new RangeCoder.BitTreeEncoder[Base.kNumLenToPosStates]; 315 | 316 | RangeCoder.BitEncoder[] _posEncoders = new RangeCoder.BitEncoder[Base.kNumFullDistances - Base.kEndPosModelIndex]; 317 | RangeCoder.BitTreeEncoder _posAlignEncoder = new RangeCoder.BitTreeEncoder(Base.kNumAlignBits); 318 | 319 | LenPriceTableEncoder _lenEncoder = new LenPriceTableEncoder(); 320 | LenPriceTableEncoder _repMatchLenEncoder = new LenPriceTableEncoder(); 321 | 322 | LiteralEncoder _literalEncoder = new LiteralEncoder(); 323 | 324 | UInt32[] _matchDistances = new UInt32[Base.kMatchMaxLen * 2 + 2]; 325 | 326 | UInt32 _numFastBytes = kNumFastBytesDefault; 327 | UInt32 _longestMatchLength; 328 | UInt32 _numDistancePairs; 329 | 330 | UInt32 _additionalOffset; 331 | 332 | UInt32 _optimumEndIndex; 333 | UInt32 _optimumCurrentIndex; 334 | 335 | Boolean _longestMatchWasFound; 336 | 337 | UInt32[] _posSlotPrices = new UInt32[1 << (Base.kNumPosSlotBits + Base.kNumLenToPosStatesBits)]; 338 | UInt32[] _distancesPrices = new UInt32[Base.kNumFullDistances << Base.kNumLenToPosStatesBits]; 339 | UInt32[] _alignPrices = new UInt32[Base.kAlignTableSize]; 340 | UInt32 _alignPriceCount; 341 | 342 | UInt32 _distTableSize = (kDefaultDictionaryLogSize * 2); 343 | 344 | Int32 _posStateBits = 2; 345 | UInt32 _posStateMask = (4 - 1); 346 | Int32 _numLiteralPosStateBits = 0; 347 | Int32 _numLiteralContextBits = 3; 348 | 349 | UInt32 _dictionarySize = (1 << kDefaultDictionaryLogSize); 350 | UInt32 _dictionarySizePrev = 0xFFFFFFFF; 351 | UInt32 _numFastBytesPrev = 0xFFFFFFFF; 352 | 353 | Int64 nowPos64; 354 | Boolean _finished; 355 | System.IO.Stream _inStream; 356 | 357 | EMatchFinderType _matchFinderType = EMatchFinderType.BT4; 358 | Boolean _writeEndMark = false; 359 | 360 | Boolean _needReleaseMFStream; 361 | 362 | void Create() 363 | { 364 | if (_matchFinder == null) 365 | { 366 | LZ.BinTree bt = new LZ.BinTree(); 367 | Int32 numHashBytes = 4; 368 | if (_matchFinderType == EMatchFinderType.BT2) 369 | numHashBytes = 2; 370 | bt.SetType(numHashBytes); 371 | _matchFinder = bt; 372 | } 373 | _literalEncoder.Create(_numLiteralPosStateBits, _numLiteralContextBits); 374 | 375 | if (_dictionarySize == _dictionarySizePrev && _numFastBytesPrev == _numFastBytes) 376 | return; 377 | _matchFinder.Create(_dictionarySize, kNumOpts, _numFastBytes, Base.kMatchMaxLen + 1); 378 | _dictionarySizePrev = _dictionarySize; 379 | _numFastBytesPrev = _numFastBytes; 380 | } 381 | 382 | public Encoder() 383 | { 384 | for (Int32 i = 0; i < kNumOpts; i++) 385 | _optimum[i] = new Optimal(); 386 | for (Int32 i = 0; i < Base.kNumLenToPosStates; i++) 387 | _posSlotEncoder[i] = new RangeCoder.BitTreeEncoder(Base.kNumPosSlotBits); 388 | } 389 | 390 | void SetWriteEndMarkerMode(Boolean writeEndMarker) 391 | { 392 | _writeEndMark = writeEndMarker; 393 | } 394 | 395 | void Init() 396 | { 397 | BaseInit(); 398 | _rangeEncoder.Init(); 399 | 400 | UInt32 i; 401 | for (i = 0; i < Base.kNumStates; i++) 402 | { 403 | for (UInt32 j = 0; j <= _posStateMask; j++) 404 | { 405 | UInt32 complexState = (i << Base.kNumPosStatesBitsMax) + j; 406 | _isMatch[complexState].Init(); 407 | _isRep0Long[complexState].Init(); 408 | } 409 | _isRep[i].Init(); 410 | _isRepG0[i].Init(); 411 | _isRepG1[i].Init(); 412 | _isRepG2[i].Init(); 413 | } 414 | _literalEncoder.Init(); 415 | for (i = 0; i < Base.kNumLenToPosStates; i++) 416 | _posSlotEncoder[i].Init(); 417 | for (i = 0; i < Base.kNumFullDistances - Base.kEndPosModelIndex; i++) 418 | _posEncoders[i].Init(); 419 | 420 | _lenEncoder.Init((UInt32)1 << _posStateBits); 421 | _repMatchLenEncoder.Init((UInt32)1 << _posStateBits); 422 | 423 | _posAlignEncoder.Init(); 424 | 425 | _longestMatchWasFound = false; 426 | _optimumEndIndex = 0; 427 | _optimumCurrentIndex = 0; 428 | _additionalOffset = 0; 429 | } 430 | 431 | void ReadMatchDistances(out UInt32 lenRes, out UInt32 numDistancePairs) 432 | { 433 | lenRes = 0; 434 | numDistancePairs = _matchFinder.GetMatches(_matchDistances); 435 | if (numDistancePairs > 0) 436 | { 437 | lenRes = _matchDistances[numDistancePairs - 2]; 438 | if (lenRes == _numFastBytes) 439 | lenRes += _matchFinder.GetMatchLen((Int32)lenRes - 1, _matchDistances[numDistancePairs - 1], 440 | Base.kMatchMaxLen - lenRes); 441 | } 442 | _additionalOffset++; 443 | } 444 | 445 | 446 | void MovePos(UInt32 num) 447 | { 448 | if (num > 0) 449 | { 450 | _matchFinder.Skip(num); 451 | _additionalOffset += num; 452 | } 453 | } 454 | 455 | UInt32 GetRepLen1Price(Base.State state, UInt32 posState) 456 | { 457 | return _isRepG0[state.Index].GetPrice0() + 458 | _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0(); 459 | } 460 | 461 | UInt32 GetPureRepPrice(UInt32 repIndex, Base.State state, UInt32 posState) 462 | { 463 | UInt32 price; 464 | if (repIndex == 0) 465 | { 466 | price = _isRepG0[state.Index].GetPrice0(); 467 | price += _isRep0Long[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); 468 | } 469 | else 470 | { 471 | price = _isRepG0[state.Index].GetPrice1(); 472 | if (repIndex == 1) 473 | price += _isRepG1[state.Index].GetPrice0(); 474 | else 475 | { 476 | price += _isRepG1[state.Index].GetPrice1(); 477 | price += _isRepG2[state.Index].GetPrice(repIndex - 2); 478 | } 479 | } 480 | return price; 481 | } 482 | 483 | UInt32 GetRepPrice(UInt32 repIndex, UInt32 len, Base.State state, UInt32 posState) 484 | { 485 | UInt32 price = _repMatchLenEncoder.GetPrice(len - Base.kMatchMinLen, posState); 486 | return price + GetPureRepPrice(repIndex, state, posState); 487 | } 488 | 489 | UInt32 GetPosLenPrice(UInt32 pos, UInt32 len, UInt32 posState) 490 | { 491 | UInt32 price; 492 | UInt32 lenToPosState = Base.GetLenToPosState(len); 493 | if (pos < Base.kNumFullDistances) 494 | price = _distancesPrices[(lenToPosState * Base.kNumFullDistances) + pos]; 495 | else 496 | price = _posSlotPrices[(lenToPosState << Base.kNumPosSlotBits) + GetPosSlot2(pos)] + 497 | _alignPrices[pos & Base.kAlignMask]; 498 | return price + _lenEncoder.GetPrice(len - Base.kMatchMinLen, posState); 499 | } 500 | 501 | UInt32 Backward(out UInt32 backRes, UInt32 cur) 502 | { 503 | _optimumEndIndex = cur; 504 | UInt32 posMem = _optimum[cur].PosPrev; 505 | UInt32 backMem = _optimum[cur].BackPrev; 506 | do 507 | { 508 | if (_optimum[cur].Prev1IsChar) 509 | { 510 | _optimum[posMem].MakeAsChar(); 511 | _optimum[posMem].PosPrev = posMem - 1; 512 | if (_optimum[cur].Prev2) 513 | { 514 | _optimum[posMem - 1].Prev1IsChar = false; 515 | _optimum[posMem - 1].PosPrev = _optimum[cur].PosPrev2; 516 | _optimum[posMem - 1].BackPrev = _optimum[cur].BackPrev2; 517 | } 518 | } 519 | UInt32 posPrev = posMem; 520 | UInt32 backCur = backMem; 521 | 522 | backMem = _optimum[posPrev].BackPrev; 523 | posMem = _optimum[posPrev].PosPrev; 524 | 525 | _optimum[posPrev].BackPrev = backCur; 526 | _optimum[posPrev].PosPrev = cur; 527 | cur = posPrev; 528 | } 529 | while (cur > 0); 530 | backRes = _optimum[0].BackPrev; 531 | _optimumCurrentIndex = _optimum[0].PosPrev; 532 | return _optimumCurrentIndex; 533 | } 534 | 535 | UInt32[] reps = new UInt32[Base.kNumRepDistances]; 536 | UInt32[] repLens = new UInt32[Base.kNumRepDistances]; 537 | 538 | 539 | UInt32 GetOptimum(UInt32 position, out UInt32 backRes) 540 | { 541 | if (_optimumEndIndex != _optimumCurrentIndex) 542 | { 543 | UInt32 lenRes = _optimum[_optimumCurrentIndex].PosPrev - _optimumCurrentIndex; 544 | backRes = _optimum[_optimumCurrentIndex].BackPrev; 545 | _optimumCurrentIndex = _optimum[_optimumCurrentIndex].PosPrev; 546 | return lenRes; 547 | } 548 | _optimumCurrentIndex = _optimumEndIndex = 0; 549 | 550 | UInt32 lenMain, numDistancePairs; 551 | if (!_longestMatchWasFound) 552 | { 553 | ReadMatchDistances(out lenMain, out numDistancePairs); 554 | } 555 | else 556 | { 557 | lenMain = _longestMatchLength; 558 | numDistancePairs = _numDistancePairs; 559 | _longestMatchWasFound = false; 560 | } 561 | 562 | UInt32 numAvailableBytes = _matchFinder.GetNumAvailableBytes() + 1; 563 | if (numAvailableBytes < 2) 564 | { 565 | backRes = 0xFFFFFFFF; 566 | return 1; 567 | } 568 | if (numAvailableBytes > Base.kMatchMaxLen) 569 | numAvailableBytes = Base.kMatchMaxLen; 570 | 571 | UInt32 repMaxIndex = 0; 572 | UInt32 i; 573 | for (i = 0; i < Base.kNumRepDistances; i++) 574 | { 575 | reps[i] = _repDistances[i]; 576 | repLens[i] = _matchFinder.GetMatchLen(0 - 1, reps[i], Base.kMatchMaxLen); 577 | if (repLens[i] > repLens[repMaxIndex]) 578 | repMaxIndex = i; 579 | } 580 | if (repLens[repMaxIndex] >= _numFastBytes) 581 | { 582 | backRes = repMaxIndex; 583 | UInt32 lenRes = repLens[repMaxIndex]; 584 | MovePos(lenRes - 1); 585 | return lenRes; 586 | } 587 | 588 | if (lenMain >= _numFastBytes) 589 | { 590 | backRes = _matchDistances[numDistancePairs - 1] + Base.kNumRepDistances; 591 | MovePos(lenMain - 1); 592 | return lenMain; 593 | } 594 | 595 | Byte currentByte = _matchFinder.GetIndexByte(0 - 1); 596 | Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - 1)); 597 | 598 | if (lenMain < 2 && currentByte != matchByte && repLens[repMaxIndex] < 2) 599 | { 600 | backRes = (UInt32)0xFFFFFFFF; 601 | return 1; 602 | } 603 | 604 | _optimum[0].State = _state; 605 | 606 | UInt32 posState = (position & _posStateMask); 607 | 608 | _optimum[1].Price = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + 609 | _literalEncoder.GetSubCoder(position, _previousByte).GetPrice(!_state.IsCharState(), matchByte, currentByte); 610 | _optimum[1].MakeAsChar(); 611 | 612 | UInt32 matchPrice = _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); 613 | UInt32 repMatchPrice = matchPrice + _isRep[_state.Index].GetPrice1(); 614 | 615 | if (matchByte == currentByte) 616 | { 617 | UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(_state, posState); 618 | if (shortRepPrice < _optimum[1].Price) 619 | { 620 | _optimum[1].Price = shortRepPrice; 621 | _optimum[1].MakeAsShortRep(); 622 | } 623 | } 624 | 625 | UInt32 lenEnd = ((lenMain >= repLens[repMaxIndex]) ? lenMain : repLens[repMaxIndex]); 626 | 627 | if(lenEnd < 2) 628 | { 629 | backRes = _optimum[1].BackPrev; 630 | return 1; 631 | } 632 | 633 | _optimum[1].PosPrev = 0; 634 | 635 | _optimum[0].Backs0 = reps[0]; 636 | _optimum[0].Backs1 = reps[1]; 637 | _optimum[0].Backs2 = reps[2]; 638 | _optimum[0].Backs3 = reps[3]; 639 | 640 | UInt32 len = lenEnd; 641 | do 642 | _optimum[len--].Price = kIfinityPrice; 643 | while (len >= 2); 644 | 645 | for (i = 0; i < Base.kNumRepDistances; i++) 646 | { 647 | UInt32 repLen = repLens[i]; 648 | if (repLen < 2) 649 | continue; 650 | UInt32 price = repMatchPrice + GetPureRepPrice(i, _state, posState); 651 | do 652 | { 653 | UInt32 curAndLenPrice = price + _repMatchLenEncoder.GetPrice(repLen - 2, posState); 654 | Optimal optimum = _optimum[repLen]; 655 | if (curAndLenPrice < optimum.Price) 656 | { 657 | optimum.Price = curAndLenPrice; 658 | optimum.PosPrev = 0; 659 | optimum.BackPrev = i; 660 | optimum.Prev1IsChar = false; 661 | } 662 | } 663 | while (--repLen >= 2); 664 | } 665 | 666 | UInt32 normalMatchPrice = matchPrice + _isRep[_state.Index].GetPrice0(); 667 | 668 | len = ((repLens[0] >= 2) ? repLens[0] + 1 : 2); 669 | if (len <= lenMain) 670 | { 671 | UInt32 offs = 0; 672 | while (len > _matchDistances[offs]) 673 | offs += 2; 674 | for (; ; len++) 675 | { 676 | UInt32 distance = _matchDistances[offs + 1]; 677 | UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(distance, len, posState); 678 | Optimal optimum = _optimum[len]; 679 | if (curAndLenPrice < optimum.Price) 680 | { 681 | optimum.Price = curAndLenPrice; 682 | optimum.PosPrev = 0; 683 | optimum.BackPrev = distance + Base.kNumRepDistances; 684 | optimum.Prev1IsChar = false; 685 | } 686 | if (len == _matchDistances[offs]) 687 | { 688 | offs += 2; 689 | if (offs == numDistancePairs) 690 | break; 691 | } 692 | } 693 | } 694 | 695 | UInt32 cur = 0; 696 | 697 | while (true) 698 | { 699 | cur++; 700 | if (cur == lenEnd) 701 | return Backward(out backRes, cur); 702 | UInt32 newLen; 703 | ReadMatchDistances(out newLen, out numDistancePairs); 704 | if (newLen >= _numFastBytes) 705 | { 706 | _numDistancePairs = numDistancePairs; 707 | _longestMatchLength = newLen; 708 | _longestMatchWasFound = true; 709 | return Backward(out backRes, cur); 710 | } 711 | position++; 712 | UInt32 posPrev = _optimum[cur].PosPrev; 713 | Base.State state; 714 | if (_optimum[cur].Prev1IsChar) 715 | { 716 | posPrev--; 717 | if (_optimum[cur].Prev2) 718 | { 719 | state = _optimum[_optimum[cur].PosPrev2].State; 720 | if (_optimum[cur].BackPrev2 < Base.kNumRepDistances) 721 | state.UpdateRep(); 722 | else 723 | state.UpdateMatch(); 724 | } 725 | else 726 | state = _optimum[posPrev].State; 727 | state.UpdateChar(); 728 | } 729 | else 730 | state = _optimum[posPrev].State; 731 | if (posPrev == cur - 1) 732 | { 733 | if (_optimum[cur].IsShortRep()) 734 | state.UpdateShortRep(); 735 | else 736 | state.UpdateChar(); 737 | } 738 | else 739 | { 740 | UInt32 pos; 741 | if (_optimum[cur].Prev1IsChar && _optimum[cur].Prev2) 742 | { 743 | posPrev = _optimum[cur].PosPrev2; 744 | pos = _optimum[cur].BackPrev2; 745 | state.UpdateRep(); 746 | } 747 | else 748 | { 749 | pos = _optimum[cur].BackPrev; 750 | if (pos < Base.kNumRepDistances) 751 | state.UpdateRep(); 752 | else 753 | state.UpdateMatch(); 754 | } 755 | Optimal opt = _optimum[posPrev]; 756 | if (pos < Base.kNumRepDistances) 757 | { 758 | if (pos == 0) 759 | { 760 | reps[0] = opt.Backs0; 761 | reps[1] = opt.Backs1; 762 | reps[2] = opt.Backs2; 763 | reps[3] = opt.Backs3; 764 | } 765 | else if (pos == 1) 766 | { 767 | reps[0] = opt.Backs1; 768 | reps[1] = opt.Backs0; 769 | reps[2] = opt.Backs2; 770 | reps[3] = opt.Backs3; 771 | } 772 | else if (pos == 2) 773 | { 774 | reps[0] = opt.Backs2; 775 | reps[1] = opt.Backs0; 776 | reps[2] = opt.Backs1; 777 | reps[3] = opt.Backs3; 778 | } 779 | else 780 | { 781 | reps[0] = opt.Backs3; 782 | reps[1] = opt.Backs0; 783 | reps[2] = opt.Backs1; 784 | reps[3] = opt.Backs2; 785 | } 786 | } 787 | else 788 | { 789 | reps[0] = (pos - Base.kNumRepDistances); 790 | reps[1] = opt.Backs0; 791 | reps[2] = opt.Backs1; 792 | reps[3] = opt.Backs2; 793 | } 794 | } 795 | _optimum[cur].State = state; 796 | _optimum[cur].Backs0 = reps[0]; 797 | _optimum[cur].Backs1 = reps[1]; 798 | _optimum[cur].Backs2 = reps[2]; 799 | _optimum[cur].Backs3 = reps[3]; 800 | UInt32 curPrice = _optimum[cur].Price; 801 | 802 | currentByte = _matchFinder.GetIndexByte(0 - 1); 803 | matchByte = _matchFinder.GetIndexByte((Int32)(0 - reps[0] - 1 - 1)); 804 | 805 | posState = (position & _posStateMask); 806 | 807 | UInt32 curAnd1Price = curPrice + 808 | _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice0() + 809 | _literalEncoder.GetSubCoder(position, _matchFinder.GetIndexByte(0 - 2)). 810 | GetPrice(!state.IsCharState(), matchByte, currentByte); 811 | 812 | Optimal nextOptimum = _optimum[cur + 1]; 813 | 814 | Boolean nextIsChar = false; 815 | if (curAnd1Price < nextOptimum.Price) 816 | { 817 | nextOptimum.Price = curAnd1Price; 818 | nextOptimum.PosPrev = cur; 819 | nextOptimum.MakeAsChar(); 820 | nextIsChar = true; 821 | } 822 | 823 | matchPrice = curPrice + _isMatch[(state.Index << Base.kNumPosStatesBitsMax) + posState].GetPrice1(); 824 | repMatchPrice = matchPrice + _isRep[state.Index].GetPrice1(); 825 | 826 | if (matchByte == currentByte && 827 | !(nextOptimum.PosPrev < cur && nextOptimum.BackPrev == 0)) 828 | { 829 | UInt32 shortRepPrice = repMatchPrice + GetRepLen1Price(state, posState); 830 | if (shortRepPrice <= nextOptimum.Price) 831 | { 832 | nextOptimum.Price = shortRepPrice; 833 | nextOptimum.PosPrev = cur; 834 | nextOptimum.MakeAsShortRep(); 835 | nextIsChar = true; 836 | } 837 | } 838 | 839 | UInt32 numAvailableBytesFull = _matchFinder.GetNumAvailableBytes() + 1; 840 | numAvailableBytesFull = Math.Min(kNumOpts - 1 - cur, numAvailableBytesFull); 841 | numAvailableBytes = numAvailableBytesFull; 842 | 843 | if (numAvailableBytes < 2) 844 | continue; 845 | if (numAvailableBytes > _numFastBytes) 846 | numAvailableBytes = _numFastBytes; 847 | if (!nextIsChar && matchByte != currentByte) 848 | { 849 | // try Literal + rep0 850 | UInt32 t = Math.Min(numAvailableBytesFull - 1, _numFastBytes); 851 | UInt32 lenTest2 = _matchFinder.GetMatchLen(0, reps[0], t); 852 | if (lenTest2 >= 2) 853 | { 854 | Base.State state2 = state; 855 | state2.UpdateChar(); 856 | UInt32 posStateNext = (position + 1) & _posStateMask; 857 | UInt32 nextRepMatchPrice = curAnd1Price + 858 | _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1() + 859 | _isRep[state2.Index].GetPrice1(); 860 | { 861 | UInt32 offset = cur + 1 + lenTest2; 862 | while (lenEnd < offset) 863 | _optimum[++lenEnd].Price = kIfinityPrice; 864 | UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice( 865 | 0, lenTest2, state2, posStateNext); 866 | Optimal optimum = _optimum[offset]; 867 | if (curAndLenPrice < optimum.Price) 868 | { 869 | optimum.Price = curAndLenPrice; 870 | optimum.PosPrev = cur + 1; 871 | optimum.BackPrev = 0; 872 | optimum.Prev1IsChar = true; 873 | optimum.Prev2 = false; 874 | } 875 | } 876 | } 877 | } 878 | 879 | UInt32 startLen = 2; // speed optimization 880 | 881 | for (UInt32 repIndex = 0; repIndex < Base.kNumRepDistances; repIndex++) 882 | { 883 | UInt32 lenTest = _matchFinder.GetMatchLen(0 - 1, reps[repIndex], numAvailableBytes); 884 | if (lenTest < 2) 885 | continue; 886 | UInt32 lenTestTemp = lenTest; 887 | do 888 | { 889 | while (lenEnd < cur + lenTest) 890 | _optimum[++lenEnd].Price = kIfinityPrice; 891 | UInt32 curAndLenPrice = repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState); 892 | Optimal optimum = _optimum[cur + lenTest]; 893 | if (curAndLenPrice < optimum.Price) 894 | { 895 | optimum.Price = curAndLenPrice; 896 | optimum.PosPrev = cur; 897 | optimum.BackPrev = repIndex; 898 | optimum.Prev1IsChar = false; 899 | } 900 | } 901 | while(--lenTest >= 2); 902 | lenTest = lenTestTemp; 903 | 904 | if (repIndex == 0) 905 | startLen = lenTest + 1; 906 | 907 | // if (_maxMode) 908 | if (lenTest < numAvailableBytesFull) 909 | { 910 | UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); 911 | UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, reps[repIndex], t); 912 | if (lenTest2 >= 2) 913 | { 914 | Base.State state2 = state; 915 | state2.UpdateRep(); 916 | UInt32 posStateNext = (position + lenTest) & _posStateMask; 917 | UInt32 curAndLenCharPrice = 918 | repMatchPrice + GetRepPrice(repIndex, lenTest, state, posState) + 919 | _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + 920 | _literalEncoder.GetSubCoder(position + lenTest, 921 | _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)).GetPrice(true, 922 | _matchFinder.GetIndexByte((Int32)((Int32)lenTest - 1 - (Int32)(reps[repIndex] + 1))), 923 | _matchFinder.GetIndexByte((Int32)lenTest - 1)); 924 | state2.UpdateChar(); 925 | posStateNext = (position + lenTest + 1) & _posStateMask; 926 | UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); 927 | UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); 928 | 929 | // for(; lenTest2 >= 2; lenTest2--) 930 | { 931 | UInt32 offset = lenTest + 1 + lenTest2; 932 | while(lenEnd < cur + offset) 933 | _optimum[++lenEnd].Price = kIfinityPrice; 934 | UInt32 curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); 935 | Optimal optimum = _optimum[cur + offset]; 936 | if (curAndLenPrice < optimum.Price) 937 | { 938 | optimum.Price = curAndLenPrice; 939 | optimum.PosPrev = cur + lenTest + 1; 940 | optimum.BackPrev = 0; 941 | optimum.Prev1IsChar = true; 942 | optimum.Prev2 = true; 943 | optimum.PosPrev2 = cur; 944 | optimum.BackPrev2 = repIndex; 945 | } 946 | } 947 | } 948 | } 949 | } 950 | 951 | if (newLen > numAvailableBytes) 952 | { 953 | newLen = numAvailableBytes; 954 | for (numDistancePairs = 0; newLen > _matchDistances[numDistancePairs]; numDistancePairs += 2) ; 955 | _matchDistances[numDistancePairs] = newLen; 956 | numDistancePairs += 2; 957 | } 958 | if (newLen >= startLen) 959 | { 960 | normalMatchPrice = matchPrice + _isRep[state.Index].GetPrice0(); 961 | while (lenEnd < cur + newLen) 962 | _optimum[++lenEnd].Price = kIfinityPrice; 963 | 964 | UInt32 offs = 0; 965 | while (startLen > _matchDistances[offs]) 966 | offs += 2; 967 | 968 | for (UInt32 lenTest = startLen; ; lenTest++) 969 | { 970 | UInt32 curBack = _matchDistances[offs + 1]; 971 | UInt32 curAndLenPrice = normalMatchPrice + GetPosLenPrice(curBack, lenTest, posState); 972 | Optimal optimum = _optimum[cur + lenTest]; 973 | if (curAndLenPrice < optimum.Price) 974 | { 975 | optimum.Price = curAndLenPrice; 976 | optimum.PosPrev = cur; 977 | optimum.BackPrev = curBack + Base.kNumRepDistances; 978 | optimum.Prev1IsChar = false; 979 | } 980 | 981 | if (lenTest == _matchDistances[offs]) 982 | { 983 | if (lenTest < numAvailableBytesFull) 984 | { 985 | UInt32 t = Math.Min(numAvailableBytesFull - 1 - lenTest, _numFastBytes); 986 | UInt32 lenTest2 = _matchFinder.GetMatchLen((Int32)lenTest, curBack, t); 987 | if (lenTest2 >= 2) 988 | { 989 | Base.State state2 = state; 990 | state2.UpdateMatch(); 991 | UInt32 posStateNext = (position + lenTest) & _posStateMask; 992 | UInt32 curAndLenCharPrice = curAndLenPrice + 993 | _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice0() + 994 | _literalEncoder.GetSubCoder(position + lenTest, 995 | _matchFinder.GetIndexByte((Int32)lenTest - 1 - 1)). 996 | GetPrice(true, 997 | _matchFinder.GetIndexByte((Int32)lenTest - (Int32)(curBack + 1) - 1), 998 | _matchFinder.GetIndexByte((Int32)lenTest - 1)); 999 | state2.UpdateChar(); 1000 | posStateNext = (position + lenTest + 1) & _posStateMask; 1001 | UInt32 nextMatchPrice = curAndLenCharPrice + _isMatch[(state2.Index << Base.kNumPosStatesBitsMax) + posStateNext].GetPrice1(); 1002 | UInt32 nextRepMatchPrice = nextMatchPrice + _isRep[state2.Index].GetPrice1(); 1003 | 1004 | UInt32 offset = lenTest + 1 + lenTest2; 1005 | while (lenEnd < cur + offset) 1006 | _optimum[++lenEnd].Price = kIfinityPrice; 1007 | curAndLenPrice = nextRepMatchPrice + GetRepPrice(0, lenTest2, state2, posStateNext); 1008 | optimum = _optimum[cur + offset]; 1009 | if (curAndLenPrice < optimum.Price) 1010 | { 1011 | optimum.Price = curAndLenPrice; 1012 | optimum.PosPrev = cur + lenTest + 1; 1013 | optimum.BackPrev = 0; 1014 | optimum.Prev1IsChar = true; 1015 | optimum.Prev2 = true; 1016 | optimum.PosPrev2 = cur; 1017 | optimum.BackPrev2 = curBack + Base.kNumRepDistances; 1018 | } 1019 | } 1020 | } 1021 | offs += 2; 1022 | if (offs == numDistancePairs) 1023 | break; 1024 | } 1025 | } 1026 | } 1027 | } 1028 | } 1029 | 1030 | Boolean ChangePair(UInt32 smallDist, UInt32 bigDist) 1031 | { 1032 | const Int32 kDif = 7; 1033 | return (smallDist < ((UInt32)(1) << (32 - kDif)) && bigDist >= (smallDist << kDif)); 1034 | } 1035 | 1036 | void WriteEndMarker(UInt32 posState) 1037 | { 1038 | if (!_writeEndMark) 1039 | return; 1040 | 1041 | _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 1); 1042 | _isRep[_state.Index].Encode(_rangeEncoder, 0); 1043 | _state.UpdateMatch(); 1044 | UInt32 len = Base.kMatchMinLen; 1045 | _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); 1046 | UInt32 posSlot = (1 << Base.kNumPosSlotBits) - 1; 1047 | UInt32 lenToPosState = Base.GetLenToPosState(len); 1048 | _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); 1049 | Int32 footerBits = 30; 1050 | UInt32 posReduced = (((UInt32)1) << footerBits) - 1; 1051 | _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); 1052 | _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); 1053 | } 1054 | 1055 | void Flush(UInt32 nowPos) 1056 | { 1057 | ReleaseMFStream(); 1058 | WriteEndMarker(nowPos & _posStateMask); 1059 | _rangeEncoder.FlushData(); 1060 | _rangeEncoder.FlushStream(); 1061 | } 1062 | 1063 | public void CodeOneBlock(out Int64 inSize, out Int64 outSize, out Boolean finished) 1064 | { 1065 | inSize = 0; 1066 | outSize = 0; 1067 | finished = true; 1068 | 1069 | if (_inStream != null) 1070 | { 1071 | _matchFinder.SetStream(_inStream); 1072 | _matchFinder.Init(); 1073 | _needReleaseMFStream = true; 1074 | _inStream = null; 1075 | if (_trainSize > 0) 1076 | _matchFinder.Skip(_trainSize); 1077 | } 1078 | 1079 | if (_finished) 1080 | return; 1081 | _finished = true; 1082 | 1083 | 1084 | Int64 progressPosValuePrev = nowPos64; 1085 | if (nowPos64 == 0) 1086 | { 1087 | if (_matchFinder.GetNumAvailableBytes() == 0) 1088 | { 1089 | Flush((UInt32)nowPos64); 1090 | return; 1091 | } 1092 | UInt32 len, numDistancePairs; // it's not used 1093 | ReadMatchDistances(out len, out numDistancePairs); 1094 | UInt32 posState = (UInt32)(nowPos64) & _posStateMask; 1095 | _isMatch[(_state.Index << Base.kNumPosStatesBitsMax) + posState].Encode(_rangeEncoder, 0); 1096 | _state.UpdateChar(); 1097 | Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); 1098 | _literalEncoder.GetSubCoder((UInt32)(nowPos64), _previousByte).Encode(_rangeEncoder, curByte); 1099 | _previousByte = curByte; 1100 | _additionalOffset--; 1101 | nowPos64++; 1102 | } 1103 | if (_matchFinder.GetNumAvailableBytes() == 0) 1104 | { 1105 | Flush((UInt32)nowPos64); 1106 | return; 1107 | } 1108 | while (true) 1109 | { 1110 | UInt32 pos; 1111 | UInt32 len = GetOptimum((UInt32)nowPos64, out pos); 1112 | 1113 | UInt32 posState = ((UInt32)nowPos64) & _posStateMask; 1114 | UInt32 complexState = (_state.Index << Base.kNumPosStatesBitsMax) + posState; 1115 | if (len == 1 && pos == 0xFFFFFFFF) 1116 | { 1117 | _isMatch[complexState].Encode(_rangeEncoder, 0); 1118 | Byte curByte = _matchFinder.GetIndexByte((Int32)(0 - _additionalOffset)); 1119 | LiteralEncoder.Encoder2 subCoder = _literalEncoder.GetSubCoder((UInt32)nowPos64, _previousByte); 1120 | if (!_state.IsCharState()) 1121 | { 1122 | Byte matchByte = _matchFinder.GetIndexByte((Int32)(0 - _repDistances[0] - 1 - _additionalOffset)); 1123 | subCoder.EncodeMatched(_rangeEncoder, matchByte, curByte); 1124 | } 1125 | else 1126 | subCoder.Encode(_rangeEncoder, curByte); 1127 | _previousByte = curByte; 1128 | _state.UpdateChar(); 1129 | } 1130 | else 1131 | { 1132 | _isMatch[complexState].Encode(_rangeEncoder, 1); 1133 | if (pos < Base.kNumRepDistances) 1134 | { 1135 | _isRep[_state.Index].Encode(_rangeEncoder, 1); 1136 | if (pos == 0) 1137 | { 1138 | _isRepG0[_state.Index].Encode(_rangeEncoder, 0); 1139 | if (len == 1) 1140 | _isRep0Long[complexState].Encode(_rangeEncoder, 0); 1141 | else 1142 | _isRep0Long[complexState].Encode(_rangeEncoder, 1); 1143 | } 1144 | else 1145 | { 1146 | _isRepG0[_state.Index].Encode(_rangeEncoder, 1); 1147 | if (pos == 1) 1148 | _isRepG1[_state.Index].Encode(_rangeEncoder, 0); 1149 | else 1150 | { 1151 | _isRepG1[_state.Index].Encode(_rangeEncoder, 1); 1152 | _isRepG2[_state.Index].Encode(_rangeEncoder, pos - 2); 1153 | } 1154 | } 1155 | if (len == 1) 1156 | _state.UpdateShortRep(); 1157 | else 1158 | { 1159 | _repMatchLenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); 1160 | _state.UpdateRep(); 1161 | } 1162 | UInt32 distance = _repDistances[pos]; 1163 | if (pos != 0) 1164 | { 1165 | for (UInt32 i = pos; i >= 1; i--) 1166 | _repDistances[i] = _repDistances[i - 1]; 1167 | _repDistances[0] = distance; 1168 | } 1169 | } 1170 | else 1171 | { 1172 | _isRep[_state.Index].Encode(_rangeEncoder, 0); 1173 | _state.UpdateMatch(); 1174 | _lenEncoder.Encode(_rangeEncoder, len - Base.kMatchMinLen, posState); 1175 | pos -= Base.kNumRepDistances; 1176 | UInt32 posSlot = GetPosSlot(pos); 1177 | UInt32 lenToPosState = Base.GetLenToPosState(len); 1178 | _posSlotEncoder[lenToPosState].Encode(_rangeEncoder, posSlot); 1179 | 1180 | if (posSlot >= Base.kStartPosModelIndex) 1181 | { 1182 | Int32 footerBits = (Int32)((posSlot >> 1) - 1); 1183 | UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); 1184 | UInt32 posReduced = pos - baseVal; 1185 | 1186 | if (posSlot < Base.kEndPosModelIndex) 1187 | RangeCoder.BitTreeEncoder.ReverseEncode(_posEncoders, 1188 | baseVal - posSlot - 1, _rangeEncoder, footerBits, posReduced); 1189 | else 1190 | { 1191 | _rangeEncoder.EncodeDirectBits(posReduced >> Base.kNumAlignBits, footerBits - Base.kNumAlignBits); 1192 | _posAlignEncoder.ReverseEncode(_rangeEncoder, posReduced & Base.kAlignMask); 1193 | _alignPriceCount++; 1194 | } 1195 | } 1196 | UInt32 distance = pos; 1197 | for (UInt32 i = Base.kNumRepDistances - 1; i >= 1; i--) 1198 | _repDistances[i] = _repDistances[i - 1]; 1199 | _repDistances[0] = distance; 1200 | _matchPriceCount++; 1201 | } 1202 | _previousByte = _matchFinder.GetIndexByte((Int32)(len - 1 - _additionalOffset)); 1203 | } 1204 | _additionalOffset -= len; 1205 | nowPos64 += len; 1206 | if (_additionalOffset == 0) 1207 | { 1208 | // if (!_fastMode) 1209 | if (_matchPriceCount >= (1 << 7)) 1210 | FillDistancesPrices(); 1211 | if (_alignPriceCount >= Base.kAlignTableSize) 1212 | FillAlignPrices(); 1213 | inSize = nowPos64; 1214 | outSize = _rangeEncoder.GetProcessedSizeAdd(); 1215 | if (_matchFinder.GetNumAvailableBytes() == 0) 1216 | { 1217 | Flush((UInt32)nowPos64); 1218 | return; 1219 | } 1220 | 1221 | if (nowPos64 - progressPosValuePrev >= (1 << 12)) 1222 | { 1223 | _finished = false; 1224 | finished = false; 1225 | return; 1226 | } 1227 | } 1228 | } 1229 | } 1230 | 1231 | void ReleaseMFStream() 1232 | { 1233 | if (_matchFinder != null && _needReleaseMFStream) 1234 | { 1235 | _matchFinder.ReleaseStream(); 1236 | _needReleaseMFStream = false; 1237 | } 1238 | } 1239 | 1240 | void SetOutStream(System.IO.Stream outStream) { _rangeEncoder.SetStream(outStream); } 1241 | void ReleaseOutStream() { _rangeEncoder.ReleaseStream(); } 1242 | 1243 | void ReleaseStreams() 1244 | { 1245 | ReleaseMFStream(); 1246 | ReleaseOutStream(); 1247 | } 1248 | 1249 | void SetStreams(System.IO.Stream inStream, System.IO.Stream outStream, 1250 | Int64 inSize, Int64 outSize) 1251 | { 1252 | _inStream = inStream; 1253 | _finished = false; 1254 | Create(); 1255 | SetOutStream(outStream); 1256 | Init(); 1257 | 1258 | // if (!_fastMode) 1259 | { 1260 | FillDistancesPrices(); 1261 | FillAlignPrices(); 1262 | } 1263 | 1264 | _lenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); 1265 | _lenEncoder.UpdateTables((UInt32)1 << _posStateBits); 1266 | _repMatchLenEncoder.SetTableSize(_numFastBytes + 1 - Base.kMatchMinLen); 1267 | _repMatchLenEncoder.UpdateTables((UInt32)1 << _posStateBits); 1268 | 1269 | nowPos64 = 0; 1270 | } 1271 | 1272 | 1273 | public void Code(System.IO.Stream inStream, System.IO.Stream outStream, 1274 | Int64 inSize, Int64 outSize, ICodeProgress progress) 1275 | { 1276 | _needReleaseMFStream = false; 1277 | try 1278 | { 1279 | SetStreams(inStream, outStream, inSize, outSize); 1280 | while (true) 1281 | { 1282 | Int64 processedInSize; 1283 | Int64 processedOutSize; 1284 | Boolean finished; 1285 | CodeOneBlock(out processedInSize, out processedOutSize, out finished); 1286 | if (finished) 1287 | return; 1288 | if (progress != null) 1289 | { 1290 | progress.SetProgress(processedInSize, processedOutSize); 1291 | } 1292 | } 1293 | } 1294 | finally 1295 | { 1296 | ReleaseStreams(); 1297 | } 1298 | } 1299 | 1300 | const Int32 kPropSize = 5; 1301 | Byte[] properties = new Byte[kPropSize]; 1302 | 1303 | public void WriteCoderProperties(System.IO.Stream outStream) 1304 | { 1305 | properties[0] = (Byte)((_posStateBits * 5 + _numLiteralPosStateBits) * 9 + _numLiteralContextBits); 1306 | for (Int32 i = 0; i < 4; i++) 1307 | properties[1 + i] = (Byte)((_dictionarySize >> (8 * i)) & 0xFF); 1308 | outStream.Write(properties, 0, kPropSize); 1309 | } 1310 | 1311 | UInt32[] tempPrices = new UInt32[Base.kNumFullDistances]; 1312 | UInt32 _matchPriceCount; 1313 | 1314 | void FillDistancesPrices() 1315 | { 1316 | for (UInt32 i = Base.kStartPosModelIndex; i < Base.kNumFullDistances; i++) 1317 | { 1318 | UInt32 posSlot = GetPosSlot(i); 1319 | Int32 footerBits = (Int32)((posSlot >> 1) - 1); 1320 | UInt32 baseVal = ((2 | (posSlot & 1)) << footerBits); 1321 | tempPrices[i] = BitTreeEncoder.ReverseGetPrice(_posEncoders, 1322 | baseVal - posSlot - 1, footerBits, i - baseVal); 1323 | } 1324 | 1325 | for (UInt32 lenToPosState = 0; lenToPosState < Base.kNumLenToPosStates; lenToPosState++) 1326 | { 1327 | UInt32 posSlot; 1328 | RangeCoder.BitTreeEncoder encoder = _posSlotEncoder[lenToPosState]; 1329 | 1330 | UInt32 st = (lenToPosState << Base.kNumPosSlotBits); 1331 | for (posSlot = 0; posSlot < _distTableSize; posSlot++) 1332 | _posSlotPrices[st + posSlot] = encoder.GetPrice(posSlot); 1333 | for (posSlot = Base.kEndPosModelIndex; posSlot < _distTableSize; posSlot++) 1334 | _posSlotPrices[st + posSlot] += ((((posSlot >> 1) - 1) - Base.kNumAlignBits) << RangeCoder.BitEncoder.kNumBitPriceShiftBits); 1335 | 1336 | UInt32 st2 = lenToPosState * Base.kNumFullDistances; 1337 | UInt32 i; 1338 | for (i = 0; i < Base.kStartPosModelIndex; i++) 1339 | _distancesPrices[st2 + i] = _posSlotPrices[st + i]; 1340 | for (; i < Base.kNumFullDistances; i++) 1341 | _distancesPrices[st2 + i] = _posSlotPrices[st + GetPosSlot(i)] + tempPrices[i]; 1342 | } 1343 | _matchPriceCount = 0; 1344 | } 1345 | 1346 | void FillAlignPrices() 1347 | { 1348 | for (UInt32 i = 0; i < Base.kAlignTableSize; i++) 1349 | _alignPrices[i] = _posAlignEncoder.ReverseGetPrice(i); 1350 | _alignPriceCount = 0; 1351 | } 1352 | 1353 | 1354 | static String[] kMatchFinderIDs = 1355 | { 1356 | "BT2", 1357 | "BT4", 1358 | }; 1359 | 1360 | static Int32 FindMatchFinder(String s) 1361 | { 1362 | for (Int32 m = 0; m < kMatchFinderIDs.Length; m++) 1363 | if (s == kMatchFinderIDs[m]) 1364 | return m; 1365 | return -1; 1366 | } 1367 | 1368 | public void SetCoderProperties(CoderPropID[] propIDs, Object[] properties) 1369 | { 1370 | for (UInt32 i = 0; i < properties.Length; i++) 1371 | { 1372 | Object prop = properties[i]; 1373 | switch (propIDs[i]) 1374 | { 1375 | case CoderPropID.NumFastBytes: 1376 | { 1377 | if (!(prop is Int32)) 1378 | throw new InvalidParamException(); 1379 | Int32 numFastBytes = (Int32)prop; 1380 | if (numFastBytes < 5 || numFastBytes > Base.kMatchMaxLen) 1381 | throw new InvalidParamException(); 1382 | _numFastBytes = (UInt32)numFastBytes; 1383 | break; 1384 | } 1385 | case CoderPropID.Algorithm: 1386 | { 1387 | /* 1388 | if (!(prop is Int32)) 1389 | throw new InvalidParamException(); 1390 | Int32 maximize = (Int32)prop; 1391 | _fastMode = (maximize == 0); 1392 | _maxMode = (maximize >= 2); 1393 | */ 1394 | break; 1395 | } 1396 | case CoderPropID.MatchFinder: 1397 | { 1398 | if (!(prop is String)) 1399 | throw new InvalidParamException(); 1400 | EMatchFinderType matchFinderIndexPrev = _matchFinderType; 1401 | Int32 m = FindMatchFinder(((String)prop).ToUpper()); 1402 | if (m < 0) 1403 | throw new InvalidParamException(); 1404 | _matchFinderType = (EMatchFinderType)m; 1405 | if (_matchFinder != null && matchFinderIndexPrev != _matchFinderType) 1406 | { 1407 | _dictionarySizePrev = 0xFFFFFFFF; 1408 | _matchFinder = null; 1409 | } 1410 | break; 1411 | } 1412 | case CoderPropID.DictionarySize: 1413 | { 1414 | const Int32 kDicLogSizeMaxCompress = 30; 1415 | if (!(prop is Int32)) 1416 | throw new InvalidParamException(); ; 1417 | Int32 dictionarySize = (Int32)prop; 1418 | if (dictionarySize < (UInt32)(1 << Base.kDicLogSizeMin) || 1419 | dictionarySize > (UInt32)(1 << kDicLogSizeMaxCompress)) 1420 | throw new InvalidParamException(); 1421 | _dictionarySize = (UInt32)dictionarySize; 1422 | Int32 dicLogSize; 1423 | for (dicLogSize = 0; dicLogSize < (UInt32)kDicLogSizeMaxCompress; dicLogSize++) 1424 | if (dictionarySize <= ((UInt32)(1) << dicLogSize)) 1425 | break; 1426 | _distTableSize = (UInt32)dicLogSize * 2; 1427 | break; 1428 | } 1429 | case CoderPropID.PosStateBits: 1430 | { 1431 | if (!(prop is Int32)) 1432 | throw new InvalidParamException(); 1433 | Int32 v = (Int32)prop; 1434 | if (v < 0 || v > (UInt32)Base.kNumPosStatesBitsEncodingMax) 1435 | throw new InvalidParamException(); 1436 | _posStateBits = (Int32)v; 1437 | _posStateMask = (((UInt32)1) << (Int32)_posStateBits) - 1; 1438 | break; 1439 | } 1440 | case CoderPropID.LitPosBits: 1441 | { 1442 | if (!(prop is Int32)) 1443 | throw new InvalidParamException(); 1444 | Int32 v = (Int32)prop; 1445 | if (v < 0 || v > (UInt32)Base.kNumLitPosStatesBitsEncodingMax) 1446 | throw new InvalidParamException(); 1447 | _numLiteralPosStateBits = (Int32)v; 1448 | break; 1449 | } 1450 | case CoderPropID.LitContextBits: 1451 | { 1452 | if (!(prop is Int32)) 1453 | throw new InvalidParamException(); 1454 | Int32 v = (Int32)prop; 1455 | if (v < 0 || v > (UInt32)Base.kNumLitContextBitsMax) 1456 | throw new InvalidParamException(); ; 1457 | _numLiteralContextBits = (Int32)v; 1458 | break; 1459 | } 1460 | case CoderPropID.EndMarker: 1461 | { 1462 | if (!(prop is Boolean)) 1463 | throw new InvalidParamException(); 1464 | SetWriteEndMarkerMode((Boolean)prop); 1465 | break; 1466 | } 1467 | default: 1468 | throw new InvalidParamException(); 1469 | } 1470 | } 1471 | } 1472 | 1473 | UInt32 _trainSize = 0; 1474 | public void SetTrainSize(UInt32 trainSize) 1475 | { 1476 | _trainSize = trainSize; 1477 | } 1478 | 1479 | } 1480 | } 1481 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/RangeCoder/RangeCoder.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | class Encoder 6 | { 7 | public const UInt32 kTopValue = (1 << 24); 8 | 9 | System.IO.Stream Stream; 10 | 11 | public UInt64 Low; 12 | public UInt32 Range; 13 | UInt32 _cacheSize; 14 | Byte _cache; 15 | 16 | Int64 StartPosition; 17 | 18 | public void SetStream(System.IO.Stream stream) 19 | { 20 | Stream = stream; 21 | } 22 | 23 | public void ReleaseStream() 24 | { 25 | Stream = null; 26 | } 27 | 28 | public void Init() 29 | { 30 | StartPosition = Stream.Position; 31 | 32 | Low = 0; 33 | Range = 0xFFFFFFFF; 34 | _cacheSize = 1; 35 | _cache = 0; 36 | } 37 | 38 | public void FlushData() 39 | { 40 | for (Int32 i = 0; i < 5; i++) 41 | ShiftLow(); 42 | } 43 | 44 | public void FlushStream() 45 | { 46 | Stream.Flush(); 47 | } 48 | 49 | public void CloseStream() 50 | { 51 | Stream.Close(); 52 | } 53 | 54 | public void Encode(UInt32 start, UInt32 size, UInt32 total) 55 | { 56 | Low += start * (Range /= total); 57 | Range *= size; 58 | while (Range < kTopValue) 59 | { 60 | Range <<= 8; 61 | ShiftLow(); 62 | } 63 | } 64 | 65 | public void ShiftLow() 66 | { 67 | if ((UInt32)Low < (UInt32)0xFF000000 || (UInt32)(Low >> 32) == 1) 68 | { 69 | Byte temp = _cache; 70 | do 71 | { 72 | Stream.WriteByte((Byte)(temp + (Low >> 32))); 73 | temp = 0xFF; 74 | } 75 | while (--_cacheSize != 0); 76 | _cache = (Byte)(((UInt32)Low) >> 24); 77 | } 78 | _cacheSize++; 79 | Low = ((UInt32)Low) << 8; 80 | } 81 | 82 | public void EncodeDirectBits(UInt32 v, Int32 numTotalBits) 83 | { 84 | for (Int32 i = numTotalBits - 1; i >= 0; i--) 85 | { 86 | Range >>= 1; 87 | if (((v >> i) & 1) == 1) 88 | Low += Range; 89 | if (Range < kTopValue) 90 | { 91 | Range <<= 8; 92 | ShiftLow(); 93 | } 94 | } 95 | } 96 | 97 | public void EncodeBit(UInt32 size0, Int32 numTotalBits, UInt32 symbol) 98 | { 99 | UInt32 newBound = (Range >> numTotalBits) * size0; 100 | if (symbol == 0) 101 | Range = newBound; 102 | else 103 | { 104 | Low += newBound; 105 | Range -= newBound; 106 | } 107 | while (Range < kTopValue) 108 | { 109 | Range <<= 8; 110 | ShiftLow(); 111 | } 112 | } 113 | 114 | public Int64 GetProcessedSizeAdd() 115 | { 116 | return _cacheSize + 117 | Stream.Position - StartPosition + 4; 118 | // (long)Stream.GetProcessedSize(); 119 | } 120 | } 121 | 122 | class Decoder 123 | { 124 | public const UInt32 kTopValue = (1 << 24); 125 | public UInt32 Range; 126 | public UInt32 Code; 127 | // public Buffer.InBuffer Stream = new Buffer.InBuffer(1 << 16); 128 | public System.IO.Stream Stream; 129 | 130 | public void Init(System.IO.Stream stream) 131 | { 132 | // Stream.Init(stream); 133 | Stream = stream; 134 | 135 | Code = 0; 136 | Range = 0xFFFFFFFF; 137 | for (Int32 i = 0; i < 5; i++) 138 | Code = (Code << 8) | (Byte)Stream.ReadByte(); 139 | } 140 | 141 | public void ReleaseStream() 142 | { 143 | // Stream.ReleaseStream(); 144 | Stream = null; 145 | } 146 | 147 | public void CloseStream() 148 | { 149 | Stream.Close(); 150 | } 151 | 152 | public void Normalize() 153 | { 154 | while (Range < kTopValue) 155 | { 156 | Code = (Code << 8) | (Byte)Stream.ReadByte(); 157 | Range <<= 8; 158 | } 159 | } 160 | 161 | public void Normalize2() 162 | { 163 | if (Range < kTopValue) 164 | { 165 | Code = (Code << 8) | (Byte)Stream.ReadByte(); 166 | Range <<= 8; 167 | } 168 | } 169 | 170 | public UInt32 GetThreshold(UInt32 total) 171 | { 172 | return Code / (Range /= total); 173 | } 174 | 175 | public void Decode(UInt32 start, UInt32 size, UInt32 total) 176 | { 177 | Code -= start * Range; 178 | Range *= size; 179 | Normalize(); 180 | } 181 | 182 | public UInt32 DecodeDirectBits(Int32 numTotalBits) 183 | { 184 | UInt32 range = Range; 185 | UInt32 code = Code; 186 | UInt32 result = 0; 187 | for (Int32 i = numTotalBits; i > 0; i--) 188 | { 189 | range >>= 1; 190 | /* 191 | result <<= 1; 192 | if (code >= range) 193 | { 194 | code -= range; 195 | result |= 1; 196 | } 197 | */ 198 | UInt32 t = (code - range) >> 31; 199 | code -= range & (t - 1); 200 | result = (result << 1) | (1 - t); 201 | 202 | if (range < kTopValue) 203 | { 204 | code = (code << 8) | (Byte)Stream.ReadByte(); 205 | range <<= 8; 206 | } 207 | } 208 | Range = range; 209 | Code = code; 210 | return result; 211 | } 212 | 213 | public UInt32 DecodeBit(UInt32 size0, Int32 numTotalBits) 214 | { 215 | UInt32 newBound = (Range >> numTotalBits) * size0; 216 | UInt32 symbol; 217 | if (Code < newBound) 218 | { 219 | symbol = 0; 220 | Range = newBound; 221 | } 222 | else 223 | { 224 | symbol = 1; 225 | Code -= newBound; 226 | Range -= newBound; 227 | } 228 | Normalize(); 229 | return symbol; 230 | } 231 | 232 | // ulong GetProcessedSize() {return Stream.GetProcessedSize(); } 233 | } 234 | } 235 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/RangeCoder/RangeCoderBit.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | struct BitEncoder 6 | { 7 | public const Int32 kNumBitModelTotalBits = 11; 8 | public const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); 9 | const Int32 kNumMoveBits = 5; 10 | const Int32 kNumMoveReducingBits = 2; 11 | public const Int32 kNumBitPriceShiftBits = 6; 12 | 13 | UInt32 Prob; 14 | 15 | public void Init() { Prob = kBitModelTotal >> 1; } 16 | 17 | public void UpdateModel(UInt32 symbol) 18 | { 19 | if (symbol == 0) 20 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 21 | else 22 | Prob -= (Prob) >> kNumMoveBits; 23 | } 24 | 25 | public void Encode(Encoder encoder, UInt32 symbol) 26 | { 27 | // encoder.EncodeBit(Prob, kNumBitModelTotalBits, symbol); 28 | // UpdateModel(symbol); 29 | UInt32 newBound = (encoder.Range >> kNumBitModelTotalBits) * Prob; 30 | if (symbol == 0) 31 | { 32 | encoder.Range = newBound; 33 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 34 | } 35 | else 36 | { 37 | encoder.Low += newBound; 38 | encoder.Range -= newBound; 39 | Prob -= (Prob) >> kNumMoveBits; 40 | } 41 | if (encoder.Range < Encoder.kTopValue) 42 | { 43 | encoder.Range <<= 8; 44 | encoder.ShiftLow(); 45 | } 46 | } 47 | 48 | private static UInt32[] ProbPrices = new UInt32[kBitModelTotal >> kNumMoveReducingBits]; 49 | 50 | static BitEncoder() 51 | { 52 | const Int32 kNumBits = (kNumBitModelTotalBits - kNumMoveReducingBits); 53 | for (Int32 i = kNumBits - 1; i >= 0; i--) 54 | { 55 | UInt32 start = (UInt32)1 << (kNumBits - i - 1); 56 | UInt32 end = (UInt32)1 << (kNumBits - i); 57 | for (UInt32 j = start; j < end; j++) 58 | ProbPrices[j] = ((UInt32)i << kNumBitPriceShiftBits) + 59 | (((end - j) << kNumBitPriceShiftBits) >> (kNumBits - i - 1)); 60 | } 61 | } 62 | 63 | public UInt32 GetPrice(UInt32 symbol) 64 | { 65 | return ProbPrices[(((Prob - symbol) ^ ((-(Int32)symbol))) & (kBitModelTotal - 1)) >> kNumMoveReducingBits]; 66 | } 67 | public UInt32 GetPrice0() { return ProbPrices[Prob >> kNumMoveReducingBits]; } 68 | public UInt32 GetPrice1() { return ProbPrices[(kBitModelTotal - Prob) >> kNumMoveReducingBits]; } 69 | } 70 | 71 | struct BitDecoder 72 | { 73 | public const Int32 kNumBitModelTotalBits = 11; 74 | public const UInt32 kBitModelTotal = (1 << kNumBitModelTotalBits); 75 | const Int32 kNumMoveBits = 5; 76 | 77 | UInt32 Prob; 78 | 79 | public void UpdateModel(Int32 numMoveBits, UInt32 symbol) 80 | { 81 | if (symbol == 0) 82 | Prob += (kBitModelTotal - Prob) >> numMoveBits; 83 | else 84 | Prob -= (Prob) >> numMoveBits; 85 | } 86 | 87 | public void Init() { Prob = kBitModelTotal >> 1; } 88 | 89 | public UInt32 Decode(RangeCoder.Decoder rangeDecoder) 90 | { 91 | UInt32 newBound = (UInt32)(rangeDecoder.Range >> kNumBitModelTotalBits) * (UInt32)Prob; 92 | if (rangeDecoder.Code < newBound) 93 | { 94 | rangeDecoder.Range = newBound; 95 | Prob += (kBitModelTotal - Prob) >> kNumMoveBits; 96 | if (rangeDecoder.Range < Decoder.kTopValue) 97 | { 98 | rangeDecoder.Code = (rangeDecoder.Code << 8) | (Byte)rangeDecoder.Stream.ReadByte(); 99 | rangeDecoder.Range <<= 8; 100 | } 101 | return 0; 102 | } 103 | else 104 | { 105 | rangeDecoder.Range -= newBound; 106 | rangeDecoder.Code -= newBound; 107 | Prob -= (Prob) >> kNumMoveBits; 108 | if (rangeDecoder.Range < Decoder.kTopValue) 109 | { 110 | rangeDecoder.Code = (rangeDecoder.Code << 8) | (Byte)rangeDecoder.Stream.ReadByte(); 111 | rangeDecoder.Range <<= 8; 112 | } 113 | return 1; 114 | } 115 | } 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/Compress/RangeCoder/RangeCoderBitTree.cs: -------------------------------------------------------------------------------- 1 | using System; 2 | 3 | namespace SevenZip.Compression.RangeCoder 4 | { 5 | struct BitTreeEncoder 6 | { 7 | BitEncoder[] Models; 8 | Int32 NumBitLevels; 9 | 10 | public BitTreeEncoder(Int32 numBitLevels) 11 | { 12 | NumBitLevels = numBitLevels; 13 | Models = new BitEncoder[1 << numBitLevels]; 14 | } 15 | 16 | public void Init() 17 | { 18 | for (UInt32 i = 1; i < (1 << NumBitLevels); i++) 19 | Models[i].Init(); 20 | } 21 | 22 | public void Encode(Encoder rangeEncoder, UInt32 symbol) 23 | { 24 | UInt32 m = 1; 25 | for (Int32 bitIndex = NumBitLevels; bitIndex > 0; ) 26 | { 27 | bitIndex--; 28 | UInt32 bit = (symbol >> bitIndex) & 1; 29 | Models[m].Encode(rangeEncoder, bit); 30 | m = (m << 1) | bit; 31 | } 32 | } 33 | 34 | public void ReverseEncode(Encoder rangeEncoder, UInt32 symbol) 35 | { 36 | UInt32 m = 1; 37 | for (UInt32 i = 0; i < NumBitLevels; i++) 38 | { 39 | UInt32 bit = symbol & 1; 40 | Models[m].Encode(rangeEncoder, bit); 41 | m = (m << 1) | bit; 42 | symbol >>= 1; 43 | } 44 | } 45 | 46 | public UInt32 GetPrice(UInt32 symbol) 47 | { 48 | UInt32 price = 0; 49 | UInt32 m = 1; 50 | for (Int32 bitIndex = NumBitLevels; bitIndex > 0; ) 51 | { 52 | bitIndex--; 53 | UInt32 bit = (symbol >> bitIndex) & 1; 54 | price += Models[m].GetPrice(bit); 55 | m = (m << 1) + bit; 56 | } 57 | return price; 58 | } 59 | 60 | public UInt32 ReverseGetPrice(UInt32 symbol) 61 | { 62 | UInt32 price = 0; 63 | UInt32 m = 1; 64 | for (Int32 i = NumBitLevels; i > 0; i--) 65 | { 66 | UInt32 bit = symbol & 1; 67 | symbol >>= 1; 68 | price += Models[m].GetPrice(bit); 69 | m = (m << 1) | bit; 70 | } 71 | return price; 72 | } 73 | 74 | public static UInt32 ReverseGetPrice(BitEncoder[] Models, UInt32 startIndex, 75 | Int32 NumBitLevels, UInt32 symbol) 76 | { 77 | UInt32 price = 0; 78 | UInt32 m = 1; 79 | for (Int32 i = NumBitLevels; i > 0; i--) 80 | { 81 | UInt32 bit = symbol & 1; 82 | symbol >>= 1; 83 | price += Models[startIndex + m].GetPrice(bit); 84 | m = (m << 1) | bit; 85 | } 86 | return price; 87 | } 88 | 89 | public static void ReverseEncode(BitEncoder[] Models, UInt32 startIndex, 90 | Encoder rangeEncoder, Int32 NumBitLevels, UInt32 symbol) 91 | { 92 | UInt32 m = 1; 93 | for (Int32 i = 0; i < NumBitLevels; i++) 94 | { 95 | UInt32 bit = symbol & 1; 96 | Models[startIndex + m].Encode(rangeEncoder, bit); 97 | m = (m << 1) | bit; 98 | symbol >>= 1; 99 | } 100 | } 101 | } 102 | 103 | struct BitTreeDecoder 104 | { 105 | BitDecoder[] Models; 106 | Int32 NumBitLevels; 107 | 108 | public BitTreeDecoder(Int32 numBitLevels) 109 | { 110 | NumBitLevels = numBitLevels; 111 | Models = new BitDecoder[1 << numBitLevels]; 112 | } 113 | 114 | public void Init() 115 | { 116 | for (UInt32 i = 1; i < (1 << NumBitLevels); i++) 117 | Models[i].Init(); 118 | } 119 | 120 | public UInt32 Decode(RangeCoder.Decoder rangeDecoder) 121 | { 122 | UInt32 m = 1; 123 | for (Int32 bitIndex = NumBitLevels; bitIndex > 0; bitIndex--) 124 | m = (m << 1) + Models[m].Decode(rangeDecoder); 125 | return m - ((UInt32)1 << NumBitLevels); 126 | } 127 | 128 | public UInt32 ReverseDecode(RangeCoder.Decoder rangeDecoder) 129 | { 130 | UInt32 m = 1; 131 | UInt32 symbol = 0; 132 | for (Int32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) 133 | { 134 | UInt32 bit = Models[m].Decode(rangeDecoder); 135 | m <<= 1; 136 | m += bit; 137 | symbol |= (bit << bitIndex); 138 | } 139 | return symbol; 140 | } 141 | 142 | public static UInt32 ReverseDecode(BitDecoder[] Models, UInt32 startIndex, 143 | RangeCoder.Decoder rangeDecoder, Int32 NumBitLevels) 144 | { 145 | UInt32 m = 1; 146 | UInt32 symbol = 0; 147 | for (Int32 bitIndex = 0; bitIndex < NumBitLevels; bitIndex++) 148 | { 149 | UInt32 bit = Models[startIndex + m].Decode(rangeDecoder); 150 | m <<= 1; 151 | m += bit; 152 | symbol |= (bit << bitIndex); 153 | } 154 | return symbol; 155 | } 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZMASDK/ICoder.cs: -------------------------------------------------------------------------------- 1 | // ICoder.h 2 | 3 | using System; 4 | 5 | namespace SevenZip 6 | { 7 | /// 8 | /// The exception that is thrown when an error in input stream occurs during decoding. 9 | /// 10 | class DataErrorException : ApplicationException 11 | { 12 | public DataErrorException(): base("Data Error") { } 13 | } 14 | 15 | /// 16 | /// The exception that is thrown when the value of an argument is outside the allowable range. 17 | /// 18 | class InvalidParamException : ApplicationException 19 | { 20 | public InvalidParamException(): base("Invalid Parameter") { } 21 | } 22 | 23 | public interface ICodeProgress 24 | { 25 | /// 26 | /// Callback progress. 27 | /// 28 | /// 29 | /// input size. -1 if unknown. 30 | /// 31 | /// 32 | /// output size. -1 if unknown. 33 | /// 34 | void SetProgress(Int64 inSize, Int64 outSize); 35 | }; 36 | 37 | public interface ICoder 38 | { 39 | /// 40 | /// Codes streams. 41 | /// 42 | /// 43 | /// input Stream. 44 | /// 45 | /// 46 | /// output Stream. 47 | /// 48 | /// 49 | /// input Size. -1 if unknown. 50 | /// 51 | /// 52 | /// output Size. -1 if unknown. 53 | /// 54 | /// 55 | /// callback progress reference. 56 | /// 57 | /// 58 | /// if input stream is not valid 59 | /// 60 | void Code(System.IO.Stream inStream, System.IO.Stream outStream, 61 | Int64 inSize, Int64 outSize, ICodeProgress progress); 62 | }; 63 | 64 | /* 65 | public interface ICoder2 66 | { 67 | void Code(ISequentialInStream []inStreams, 68 | const UInt64 []inSizes, 69 | ISequentialOutStream []outStreams, 70 | UInt64 []outSizes, 71 | ICodeProgress progress); 72 | }; 73 | */ 74 | 75 | /// 76 | /// Provides the fields that represent properties idenitifiers for compressing. 77 | /// 78 | public enum CoderPropID 79 | { 80 | /// 81 | /// Specifies default property. 82 | /// 83 | DefaultProp = 0, 84 | /// 85 | /// Specifies size of dictionary. 86 | /// 87 | DictionarySize, 88 | /// 89 | /// Specifies size of memory for PPM*. 90 | /// 91 | UsedMemorySize, 92 | /// 93 | /// Specifies order for PPM methods. 94 | /// 95 | Order, 96 | /// 97 | /// Specifies Block Size. 98 | /// 99 | BlockSize, 100 | /// 101 | /// Specifies number of postion state bits for LZMA (0 <= x <= 4). 102 | /// 103 | PosStateBits, 104 | /// 105 | /// Specifies number of literal context bits for LZMA (0 <= x <= 8). 106 | /// 107 | LitContextBits, 108 | /// 109 | /// Specifies number of literal position bits for LZMA (0 <= x <= 4). 110 | /// 111 | LitPosBits, 112 | /// 113 | /// Specifies number of fast bytes for LZ*. 114 | /// 115 | NumFastBytes, 116 | /// 117 | /// Specifies match finder. LZMA: "BT2", "BT4" or "BT4B". 118 | /// 119 | MatchFinder, 120 | /// 121 | /// Specifies the number of match finder cyckes. 122 | /// 123 | MatchFinderCycles, 124 | /// 125 | /// Specifies number of passes. 126 | /// 127 | NumPasses, 128 | /// 129 | /// Specifies number of algorithm. 130 | /// 131 | Algorithm, 132 | /// 133 | /// Specifies the number of threads. 134 | /// 135 | NumThreads, 136 | /// 137 | /// Specifies mode with end marker. 138 | /// 139 | EndMarker 140 | }; 141 | 142 | 143 | public interface ISetCoderProperties 144 | { 145 | void SetCoderProperties(CoderPropID[] propIDs, Object[] properties); 146 | }; 147 | 148 | public interface IWriteCoderProperties 149 | { 150 | void WriteCoderProperties(System.IO.Stream outStream); 151 | } 152 | 153 | public interface ISetDecoderProperties 154 | { 155 | void SetDecoderProperties(Byte[] properties); 156 | } 157 | } 158 | -------------------------------------------------------------------------------- /AdvSim.Compression/LZNT.cs: -------------------------------------------------------------------------------- 1 | #if NETFRAMEWORK 2 | 3 | using System; 4 | using System.Runtime.InteropServices; 5 | 6 | namespace AdvSim.Compression 7 | { 8 | public class LZNT 9 | { 10 | // NT Native API's 11 | //=================================== 12 | 13 | [DllImport("ntdll.dll")] 14 | internal static extern UInt32 RtlCompressBuffer( 15 | COMPRESSION_FLAGS iCompressionFormatAndEngine, 16 | Byte[] bUncompressedBuffer, 17 | UInt32 iUncompressedBufferSize, 18 | Byte[] bCompressedBuffer, 19 | UInt32 iCompressedBufferSize, 20 | UInt32 iUncompressedChunkSize, 21 | ref UInt32 iFinalCompressedSize, 22 | IntPtr pWorkSpace); 23 | 24 | [DllImport("ntdll.dll")] 25 | internal static extern UInt32 RtlGetCompressionWorkSpaceSize( 26 | COMPRESSION_FLAGS iCompressionFormatAndEngine, 27 | ref UInt32 iCompressBufferWorkSpaceSize, 28 | ref UInt32 iCompressFragmentWorkSpaceSize); 29 | 30 | [DllImport("ntdll.dll")] 31 | internal static extern UInt32 RtlDecompressBuffer( 32 | COMPRESSION_FLAGS iCompressionFormatAndEngine, 33 | Byte[] bUncompressedBuffer, 34 | UInt32 iUncompressedBufferSize, 35 | Byte[] bCompressedBuffer, 36 | UInt32 iCompressedBufferSize, 37 | ref UInt32 iFinalUncompressedSize); 38 | 39 | // Enums 40 | //=================================== 41 | 42 | internal enum COMPRESSION_FORMAT : UInt16 43 | { 44 | COMPRESSION_FORMAT_NONE = 0x0000, 45 | COMPRESSION_FORMAT_DEFAULT = 0x0001, 46 | COMPRESSION_FORMAT_LZNT1 = 0x0002 47 | } 48 | 49 | internal enum COMPRESSION_ENGINE : UInt16 50 | { 51 | COMPRESSION_ENGINE_STANDARD = 0x0000, 52 | COMPRESSION_ENGINE_MAXIMUM = 0x0100, 53 | COMPRESSION_ENGINE_HIBER = 0x0200 54 | } 55 | 56 | internal enum COMPRESSION_FLAGS : UInt16 57 | { 58 | COMPRESSION_FORMAT_LZNT1_STD = COMPRESSION_FORMAT.COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE.COMPRESSION_ENGINE_STANDARD, 59 | COMPRESSION_FORMAT_LZNT1_MAX = COMPRESSION_FORMAT.COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE.COMPRESSION_ENGINE_MAXIMUM, 60 | // Not supported, can be made to work on Ex version 61 | COMPRESSION_FORMAT_LZNT1_XPRESS_HUFF_HIBER = COMPRESSION_FORMAT.COMPRESSION_FORMAT_LZNT1 | COMPRESSION_ENGINE.COMPRESSION_ENGINE_HIBER 62 | } 63 | 64 | // Methods 65 | //=================================== 66 | 67 | /// 68 | /// Use LZNT1 to compress a byte array to a byte array 69 | /// 70 | /// Byte array containing the uncompressed buffer 71 | /// Compressed Byte array 72 | public static Byte[] RtlCompressBuffer(Byte[] bUncompressedBuffer) 73 | { 74 | // Set standard compression format and engine 75 | COMPRESSION_FLAGS iCompressionFormatAndEngine = COMPRESSION_FLAGS.COMPRESSION_FORMAT_LZNT1_STD; 76 | 77 | // Get the size of the compression workspace. 78 | UInt32 iCompressBufferWorkSpaceSize = 0; 79 | UInt32 iCompressFragmentWorkSpaceSize = 0; 80 | RtlGetCompressionWorkSpaceSize( 81 | iCompressionFormatAndEngine, 82 | ref iCompressBufferWorkSpaceSize, 83 | ref iCompressFragmentWorkSpaceSize); 84 | 85 | // "Allocate" the compression workspace. 86 | Byte[] bCompressBufferWorkSpace = new Byte[iCompressBufferWorkSpaceSize]; 87 | 88 | // "Allocate" the compressed buffer. We just add a page to the uncompressed buffer size. 89 | // |_ We will resize the array later. 90 | Byte[] bCompressedBuffer = new Byte[bUncompressedBuffer.Length + 0x1000]; 91 | 92 | // Compress the buffer. 93 | UInt32 iFinalCompressedSize = 0; 94 | RtlCompressBuffer( 95 | iCompressionFormatAndEngine, 96 | bUncompressedBuffer, 97 | (UInt32)bUncompressedBuffer.Length, 98 | bCompressedBuffer, 99 | (UInt32)bCompressedBuffer.Length, 100 | 0, 101 | ref iFinalCompressedSize, 102 | Marshal.UnsafeAddrOfPinnedArrayElement(bCompressBufferWorkSpace, 0)); 103 | 104 | // Resize the compressed buffer to the actual size. 105 | Array.Resize(ref bCompressedBuffer, (Int32)iFinalCompressedSize); 106 | 107 | // Create return buffer -> (UInt32) original size + compressed buffer. 108 | Byte[] bReturnBuffer = new Byte[bCompressedBuffer.Length + 4]; 109 | 110 | // Copy the original size to the return buffer. 111 | Array.Copy(BitConverter.GetBytes(bUncompressedBuffer.Length), 0, bReturnBuffer, 0, 4); 112 | 113 | // Copy the compressed buffer to the return buffer. 114 | Array.Copy(bCompressedBuffer, 0, bReturnBuffer, 4, bCompressedBuffer.Length); 115 | 116 | // Return the compressed buffer. 117 | return bReturnBuffer; 118 | } 119 | 120 | /// 121 | /// Use LZNT1 to compress a file to a byte array 122 | /// 123 | /// Full path to the file on disk which will be compressed 124 | /// Compressed Byte array 125 | public static Byte[] RtlCompressBuffer(String sFilePath) 126 | { 127 | // Read the file to a byte array. 128 | Byte[] bUncompressedBuffer = System.IO.File.ReadAllBytes(sFilePath); 129 | 130 | // Compress the byte array. 131 | return RtlCompressBuffer(bUncompressedBuffer); 132 | } 133 | 134 | /// 135 | /// Use LZNT1 to compress a byte array to a file 136 | /// 137 | /// Byte array containing the uncompressed buffer 138 | /// Full path to the file on disk where the compressed data will be written 139 | public static void RtlCompressBuffer(Byte[] bUncompressedBuffer, String sFilePath) 140 | { 141 | // Compress the byte array. 142 | Byte[] bCompressedBuffer = RtlCompressBuffer(bUncompressedBuffer); 143 | 144 | // Write the compressed byte array to a file. 145 | System.IO.File.WriteAllBytes(sFilePath, bCompressedBuffer); 146 | } 147 | 148 | /// 149 | /// Use LZNT1 to compress a file to a file 150 | /// 151 | /// Full path to the file on disk which will be compressed 152 | /// Full path to the file on disk where the compressed data will be written 153 | public static void RtlCompressBuffer(String sFilePath, String sOutputFilePath) 154 | { 155 | // Compress the file to a byte array. 156 | Byte[] bCompressedBuffer = RtlCompressBuffer(sFilePath); 157 | 158 | // Write the byte array to a file. 159 | System.IO.File.WriteAllBytes(sOutputFilePath, bCompressedBuffer); 160 | } 161 | 162 | /// 163 | /// Use LZNT1 to decompress a byte array to a byte array 164 | /// 165 | /// Byte array containing the compressed buffer 166 | /// Decompressed Byte array 167 | public static Byte[] RtlDecompressBuffer(Byte[] bCompressedBuffer) 168 | { 169 | // Set standard compression format and engine 170 | COMPRESSION_FLAGS iCompressionFormatAndEngine = COMPRESSION_FLAGS.COMPRESSION_FORMAT_LZNT1_STD; 171 | 172 | // Get the original size of the uncompressed buffer. 173 | Byte[] bOriginalSize = new Byte[4]; 174 | Array.Copy(bCompressedBuffer, bOriginalSize, 4); 175 | 176 | // Allocate the uncompressed buffer. 177 | Byte[] bUncompressedBuffer = new Byte[BitConverter.ToUInt32(bOriginalSize, 0)]; 178 | 179 | // Remove the original size from the compressed buffer. 180 | Byte[] bCompressedBufferWithoutOriginalSize = new Byte[bCompressedBuffer.Length - 4]; 181 | Array.Copy(bCompressedBuffer, 4, bCompressedBufferWithoutOriginalSize, 0, bCompressedBufferWithoutOriginalSize.Length); 182 | 183 | // Decompress the buffer. 184 | UInt32 iFinalUncompressedSize = 0; 185 | RtlDecompressBuffer( 186 | iCompressionFormatAndEngine, 187 | bUncompressedBuffer, 188 | (UInt32)bUncompressedBuffer.Length, 189 | bCompressedBufferWithoutOriginalSize, 190 | (UInt32)bCompressedBufferWithoutOriginalSize.Length, 191 | ref iFinalUncompressedSize); 192 | 193 | // Return the uncompressed buffer. 194 | return bUncompressedBuffer; 195 | } 196 | 197 | /// 198 | /// Use LZNT1 to decompress a file to a byte array 199 | /// 200 | /// Full path to the file on disk which will be decompressed 201 | /// Decompressed Byte array 202 | public static Byte[] RtlDecompressBuffer(String sFilePath) 203 | { 204 | // Read the file to a byte array. 205 | Byte[] bCompressedBuffer = System.IO.File.ReadAllBytes(sFilePath); 206 | 207 | // Decompress the byte array. 208 | return RtlDecompressBuffer(bCompressedBuffer); 209 | } 210 | 211 | /// 212 | /// Use LZNT1 to decompress a byte array to a file 213 | /// 214 | /// Byte array containing the compressed buffer 215 | /// Full path to the file on disk where the decompressed data will be written 216 | public static void RtlDecompressBuffer(Byte[] bCompressedBuffer, String sFilePath) 217 | { 218 | // Decompress the byte array. 219 | Byte[] bUncompressedBuffer = RtlDecompressBuffer(bCompressedBuffer); 220 | 221 | // Write the uncompressed byte array to a file. 222 | System.IO.File.WriteAllBytes(sFilePath, bUncompressedBuffer); 223 | } 224 | 225 | /// 226 | /// Use LZNT1 to decompress a file to a file 227 | /// 228 | /// Full path to the file on disk which will be decompressed 229 | /// Full path to the file on disk where the decompressed data will be written 230 | public static void RtlDecompressBuffer(String sFilePath, String sOutputFilePath) 231 | { 232 | // Decompress the file to a byte array. 233 | Byte[] bUncompressedBuffer = RtlDecompressBuffer(sFilePath); 234 | 235 | // Write the byte array to a file. 236 | System.IO.File.WriteAllBytes(sOutputFilePath, bUncompressedBuffer); 237 | } 238 | } 239 | } 240 | 241 | #endif -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | ![Release](https://badgen.net/badge/AdvSim.Compression/v1.0.0/cyan?icon=github) 3 | # AdvSim.Compression 4 | 5 | The `AdvSim.Compression` NuGet contains a set of compression wrapper functions which are reusable, configured with sane defaults and are easy to use. Further details are available under the different subheadings below. 6 | 7 | - [GZip](#gzip) 8 | - [LZMA](#lzma) 9 | - [LZNT1](#lznt1) 10 | - [Direct3D](#direct3d) 11 | - [Cabinet](#cabinet) 12 | 13 | #### NuGet Compatibility 14 | 15 | The `AdvSim.Compression` NuGet supports a wide variety of .Net versions. Due to native API usage, a number of the modules are available only on `NETFRAMEWORK`, these have been highlighted in the usage documentation below. 16 | 17 | **NuGet URL**: https://www.nuget.org/packages/AdvSim.Compression 18 | 19 | # Usage 20 | 21 | ### GZip 22 | 23 | ![Availability](https://badgen.net/badge/Availability/All/green) 24 | 25 | `GZip` is a standard wrapper around `System.IO.Compression`. 26 | 27 | ```c# 28 | // Compression 29 | //==================== 30 | 31 | // Compress Byte[] to Byte[] 32 | Byte[] bCompressed = GZip.GzipCompress(bUncompressedBuffer); 33 | // Compress File to Byte[] 34 | Byte[] bCompressed = GZip.GzipCompress(sFilePath); 35 | // Compress Byte[] to File 36 | GZip.GzipCompress(bUncompressedBuffer, sFilePath); 37 | // Compress File to File 38 | GZip.GzipCompress(sFilePath, sOutputFilePath); 39 | 40 | // Decompression 41 | //==================== 42 | 43 | // Decompress Byte[] to Byte[] 44 | Byte[] bDecompressed = GZip.GzipDecompress(bCompressedBuffer); 45 | // Decompress File to Byte[] 46 | Byte[] bDecompressed = GZip.GzipDecompress(sFilePath); 47 | // Decompress Byte[] to File 48 | GZip.GzipDecompress(bUncompressedBuffer, sFilePath); 49 | // Decompress File to File 50 | GZip.GzipDecompress(sFilePath, sOutputFilePath); 51 | ``` 52 | 53 | ### LZMA 54 | 55 | ![Availability](https://badgen.net/badge/Availability/All/green) 56 | 57 | `LZMA` is a wrapper built on the `7z` sdk provided [here](https://7-zip.org/sdk.html) under public domain licencing. 58 | 59 | ```c# 60 | // Compression 61 | //==================== 62 | 63 | // Compress Byte[] to Byte[] 64 | Byte[] bCompressed = LZMA.LZMACompress(bUncompressedBuffer); 65 | // Compress File to Byte[] 66 | Byte[] bCompressed = LZMA.LZMACompress(sFilePath); 67 | // Compress Byte[] to File 68 | LZMA.LZMACompress(bUncompressedBuffer, sFilePath); 69 | // Compress File to File 70 | LZMA.LZMACompress(sFilePath, sOutputFilePath); 71 | 72 | // Decompression 73 | //==================== 74 | 75 | // Decompress Byte[] to Byte[] 76 | Byte[] bDecompressed = LZMA.LZMACompress(bCompressedBuffer); 77 | // Decompress File to Byte[] 78 | Byte[] bDecompressed = LZMA.LZMACompress(sFilePath); 79 | // Decompress Byte[] to File 80 | LZMA.LZMACompress(bUncompressedBuffer, sFilePath); 81 | // Decompress File to File 82 | LZMA.LZMACompress(sFilePath, sOutputFilePath); 83 | ``` 84 | 85 | ### LZNT1 86 | 87 | ![Availability](https://badgen.net/badge/Availability/NETFRAMEWORK/green) 88 | 89 | `LZNT` is a wrapper around `ntdll!RtlCompressBuffer` and `ntdll!RtlDecompressBuffer`. More details about `LZNT1` are available [here](https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-xca/5655f4a3-6ba4-489b-959f-e1f407c52f15). The compression workspace here is using the `Standard Engine`. 90 | 91 | ```c# 92 | // Compression 93 | //==================== 94 | 95 | // Compress Byte[] to Byte[] 96 | Byte[] bCompressed = LZNT.RtlCompressBuffer(bUncompressedBuffer); 97 | // Compress File to Byte[] 98 | Byte[] bCompressed = LZNT.RtlCompressBuffer(sFilePath); 99 | // Compress Byte[] to File 100 | LZNT.RtlCompressBuffer(bUncompressedBuffer, sFilePath); 101 | // Compress File to File 102 | LZNT.RtlCompressBuffer(sFilePath, sOutputFilePath); 103 | 104 | // Decompression 105 | //==================== 106 | 107 | // Decompress Byte[] to Byte[] 108 | Byte[] bDecompressed = LZNT.RtlDecompressBuffer(bCompressedBuffer); 109 | // Decompress File to Byte[] 110 | Byte[] bDecompressed = LZNT.RtlDecompressBuffer(sFilePath); 111 | // Decompress Byte[] to File 112 | LZNT.RtlDecompressBuffer(bUncompressedBuffer, sFilePath); 113 | // Decompress File to File 114 | LZNT.RtlDecompressBuffer(sFilePath, sOutputFilePath); 115 | ``` 116 | 117 | ### Direct3D 118 | 119 | ![Availability](https://badgen.net/badge/Availability/NETFRAMEWORK/green) 120 | 121 | `Direct3D` is using shader compression from `D3DCompiler_47!D3DCompressShaders` and `D3DCompiler_47!D3DDecompressShaders`. Compression here is really good and I want to give a shout-out to [@modexpblog](https://twitter.com/modexpblog) for documenting this [here](https://modexp.wordpress.com/2019/12/08/shellcode-compression/) and helping me do some debugging <3! 122 | 123 | ```c# 124 | // Compression 125 | //==================== 126 | 127 | // Compress Byte[] to Byte[] 128 | Byte[] bCompressed = Direct3D.D3DCompressShaders(bUncompressedBuffer); 129 | // Compress File to Byte[] 130 | Byte[] bCompressed = Direct3D.D3DCompressShaders(sFilePath); 131 | // Compress Byte[] to File 132 | Direct3D.D3DCompressShaders(bUncompressedBuffer, sFilePath); 133 | // Compress File to File 134 | Direct3D.D3DCompressShaders(sFilePath, sOutputFilePath); 135 | 136 | // Decompression 137 | //==================== 138 | 139 | // Decompress Byte[] to Byte[] 140 | Byte[] bDecompressed = Direct3D.D3DDecompressShaders(bCompressedBuffer); 141 | // Decompress File to Byte[] 142 | Byte[] bDecompressed = Direct3D.D3DDecompressShaders(sFilePath); 143 | // Decompress Byte[] to File 144 | Direct3D.D3DDecompressShaders(bUncompressedBuffer, sFilePath); 145 | // Decompress File to File 146 | Direct3D.D3DDecompressShaders(sFilePath, sOutputFilePath); 147 | ``` 148 | 149 | ### Cabinet 150 | 151 | ![Availability](https://badgen.net/badge/Availability/NETFRAMEWORK/green) 152 | 153 | `Cabinet` is built mainly around `cabinet!Compress` and `cabinet!Decompress`. These functions are actually exposed through managed code as well, within [Windows.Storage.Compression](https://learn.microsoft.com/en-us/uwp/api/windows.storage.compression?view=winrt-22621), however this namespace is tied to the Universal Windows Platform (UWP) making it not practicable. 154 | 155 | The `cabinet` wrapper functions are able to use various types of compression. The `Enum` below lists the supported compression types. 156 | 157 | ```c# 158 | public enum CompressionAlgorithm : UInt32 159 | { 160 | COMPRESS_ALGORITHM_MSZIP = 2, 161 | COMPRESS_ALGORITHM_XPRESS = 3, 162 | COMPRESS_ALGORITHM_XPRESS_HUFF = 4, 163 | COMPRESS_ALGORITHM_LZMS = 5 164 | } 165 | ``` 166 | 167 | Usage is very similar to the other wrappers in this library. 168 | 169 | ```c# 170 | // Compression 171 | //==================== 172 | 173 | // Compress Byte[] to Byte[] 174 | Byte[] bCompressed = Cabinet.CompressStorage(bUncompressedBuffer, eAlgorithm); 175 | // Compress File to Byte[] 176 | Byte[] bCompressed = Cabinet.CompressStorage(sFilePath, eAlgorithm); 177 | // Compress Byte[] to File 178 | Cabinet.CompressStorage(bUncompressedBuffer, sFilePath, eAlgorithm); 179 | // Compress File to File 180 | Cabinet.CompressStorage(sFilePath, sOutputFilePath, eAlgorithm); 181 | 182 | // Decompression 183 | //==================== 184 | 185 | // Decompress Byte[] to Byte[] 186 | Byte[] bDecompressed = Cabinet.DecompressStorage(bCompressedBuffer, eAlgorithm); 187 | // Decompress File to Byte[] 188 | Byte[] bDecompressed = Cabinet.DecompressStorage(sFilePath, eAlgorithm); 189 | // Decompress Byte[] to File 190 | Cabinet.DecompressStorage(bUncompressedBuffer, sFilePath, eAlgorithm); 191 | // Decompress File to File 192 | Cabinet.DecompressStorage(sFilePath, sOutputFilePath, eAlgorithm); 193 | ``` 194 | --------------------------------------------------------------------------------