├── 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 | 
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 | 
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 | 
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 | 
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 | 
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 | 
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 |
--------------------------------------------------------------------------------